Replace all core::unicode::ustring with std::u32string (#13775)

This commit is contained in:
Caleb Butler 2023-10-02 07:43:38 -04:00 committed by GitHub
parent 56965bc814
commit 3a4bf14c20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 87 additions and 59 deletions

@ -2,6 +2,7 @@
CGUITTFont FreeType class for Irrlicht
Copyright (c) 2009-2010 John Norman
Copyright (c) 2016 Nathanaëlle Courant
Copyright (c) 2023 Caleb Butler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@ -31,6 +32,8 @@
#include <irrlicht.h>
#include <iostream>
#include <codecvt>
#include <locale>
#include "CGUITTFont.h"
namespace irr
@ -313,7 +316,7 @@ bool CGUITTFont::load(const io::path& filename, const u32 size, const bool antia
// Log.
if (logger)
logger->log(L"CGUITTFont", core::stringw(core::stringw(L"Creating new font: ") + core::ustring(filename).toWCHAR_s() + L" " + core::stringc(size) + L"pt " + (antialias ? L"+antialias " : L"-antialias ") + (transparency ? L"+transparency" : L"-transparency")).c_str(), irr::ELL_INFORMATION);
logger->log(L"CGUITTFont", core::stringw(core::stringw(L"Creating new font: ") + core::stringw(filename) + L" " + core::stringc(size) + L"pt " + (antialias ? L"+antialias " : L"-antialias ") + (transparency ? L"+transparency" : L"-transparency")).c_str(), irr::ELL_INFORMATION);
// Grab the face.
SGUITTFace* face = 0;
@ -354,8 +357,7 @@ bool CGUITTFont::load(const io::path& filename, const u32 size, const bool antia
}
else
{
core::ustring converter(filename);
if (FT_New_Face(c_library, reinterpret_cast<const char*>(converter.toUTF8_s().c_str()), 0, &face->face))
if (FT_New_Face(c_library, reinterpret_cast<const char*>(filename.c_str()), 0, &face->face))
{
if (logger) logger->log(L"CGUITTFont", L"FT_New_Face failed.", irr::ELL_INFORMATION);
@ -398,7 +400,7 @@ bool CGUITTFont::load(const io::path& filename, const u32 size, const bool antia
// Cache the first 127 ascii characters.
u32 old_size = batch_load_size;
batch_load_size = 127;
getGlyphIndexByChar((uchar32_t)0);
getGlyphIndexByChar((char32_t)0);
batch_load_size = old_size;
return true;
@ -578,28 +580,28 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& positio
}
// Convert to a unicode string.
core::ustring utext = text.getString();
std::u32string utext = convertWCharToU32String(text.c_str());
// Set up our render map.
std::map<u32, CGUITTGlyphPage*> Render_Map;
// Start parsing characters.
u32 n;
uchar32_t previousChar = 0;
core::ustring::const_iterator iter(utext);
while (!iter.atEnd())
char32_t previousChar = 0;
std::u32string::const_iterator iter = utext.begin();
while (iter != utext.end())
{
uchar32_t currentChar = *iter;
char32_t currentChar = *iter;
n = getGlyphIndexByChar(currentChar);
bool visible = (Invisible.findFirst(currentChar) == -1);
bool visible = (Invisible.find_first_of(currentChar) == std::u32string::npos);
bool lineBreak=false;
if (currentChar == L'\r') // Mac or Windows breaks
{
lineBreak = true;
if (*(iter + 1) == (uchar32_t)'\n') // Windows line breaks.
if (*(iter + 1) == (char32_t)'\n') // Windows line breaks.
currentChar = *(++iter);
}
else if (currentChar == (uchar32_t)'\n') // Unix breaks
else if (currentChar == (char32_t)'\n') // Unix breaks
{
lineBreak = true;
}
@ -632,8 +634,9 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& positio
CGUITTGlyphPage* const page = Glyph_Pages[glyph.glyph_page];
page->render_positions.push_back(core::position2di(offset.X + offx, offset.Y + offy));
page->render_source_rects.push_back(glyph.source_rect);
if (iter.getPos() < colors.size())
page->render_colors.push_back(colors[iter.getPos()]);
const size_t iterPos = iter - utext.begin();
if (iterPos < colors.size())
page->render_colors.push_back(colors[iterPos]);
else
page->render_colors.push_back(video::SColor(255,255,255,255));
Render_Map[glyph.glyph_page] = page;
@ -653,7 +656,7 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& positio
offset.X += fallback->getKerningWidth(l1, &l2);
offset.Y += fallback->getKerningHeight();
u32 current_color = iter.getPos();
const u32 current_color = iter - utext.begin();
fallback->draw(core::stringw(l1),
core::rect<s32>({offset.X-1, offset.Y-1}, position.LowerRightCorner), // ???
current_color < colors.size() ? colors[current_color] : video::SColor(255, 255, 255, 255),
@ -718,10 +721,10 @@ core::dimension2d<u32> CGUITTFont::getCharDimension(const wchar_t ch) const
core::dimension2d<u32> CGUITTFont::getDimension(const wchar_t* text) const
{
return getDimension(core::ustring(text));
return getDimension(convertWCharToU32String(text));
}
core::dimension2d<u32> CGUITTFont::getDimension(const core::ustring& text) const
core::dimension2d<u32> CGUITTFont::getDimension(const std::u32string& text) const
{
// Get the maximum font height. Unfortunately, we have to do this hack as
// Irrlicht will draw things wrong. In FreeType, the font size is the
@ -730,19 +733,19 @@ core::dimension2d<u32> CGUITTFont::getDimension(const core::ustring& text) const
// Irrlicht does not understand this concept when drawing fonts. Also, I
// add +1 to give it a 1 pixel blank border. This makes things like
// tooltips look nicer.
s32 test1 = getHeightFromCharacter((uchar32_t)'g') + 1;
s32 test2 = getHeightFromCharacter((uchar32_t)'j') + 1;
s32 test3 = getHeightFromCharacter((uchar32_t)'_') + 1;
s32 test1 = getHeightFromCharacter((char32_t)'g') + 1;
s32 test2 = getHeightFromCharacter((char32_t)'j') + 1;
s32 test3 = getHeightFromCharacter((char32_t)'_') + 1;
s32 max_font_height = core::max_(test1, core::max_(test2, test3));
core::dimension2d<u32> text_dimension(0, max_font_height);
core::dimension2d<u32> line(0, max_font_height);
uchar32_t previousChar = 0;
core::ustring::const_iterator iter = text.begin();
for (; !iter.atEnd(); ++iter)
char32_t previousChar = 0;
std::u32string::const_iterator iter = text.begin();
for (; iter != text.end(); ++iter)
{
uchar32_t p = *iter;
char32_t p = *iter;
bool lineBreak = false;
if (p == '\r') // Mac or Windows line breaks.
{
@ -784,10 +787,10 @@ core::dimension2d<u32> CGUITTFont::getDimension(const core::ustring& text) const
inline u32 CGUITTFont::getWidthFromCharacter(wchar_t c) const
{
return getWidthFromCharacter((uchar32_t)c);
return getWidthFromCharacter((char32_t)c);
}
inline u32 CGUITTFont::getWidthFromCharacter(uchar32_t c) const
inline u32 CGUITTFont::getWidthFromCharacter(char32_t c) const
{
// Set the size of the face.
// This is because we cache faces and the face may have been set to a different size.
@ -812,10 +815,10 @@ inline u32 CGUITTFont::getWidthFromCharacter(uchar32_t c) const
inline u32 CGUITTFont::getHeightFromCharacter(wchar_t c) const
{
return getHeightFromCharacter((uchar32_t)c);
return getHeightFromCharacter((char32_t)c);
}
inline u32 CGUITTFont::getHeightFromCharacter(uchar32_t c) const
inline u32 CGUITTFont::getHeightFromCharacter(char32_t c) const
{
// Set the size of the face.
// This is because we cache faces and the face may have been set to a different size.
@ -841,10 +844,10 @@ inline u32 CGUITTFont::getHeightFromCharacter(uchar32_t c) const
u32 CGUITTFont::getGlyphIndexByChar(wchar_t c) const
{
return getGlyphIndexByChar((uchar32_t)c);
return getGlyphIndexByChar((char32_t)c);
}
u32 CGUITTFont::getGlyphIndexByChar(uchar32_t c) const
u32 CGUITTFont::getGlyphIndexByChar(char32_t c) const
{
// Get the glyph.
u32 glyph = FT_Get_Char_Index(tt_face, c);
@ -888,20 +891,20 @@ u32 CGUITTFont::getGlyphIndexByChar(uchar32_t c) const
s32 CGUITTFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
{
return getCharacterFromPos(core::ustring(text), pixel_x);
return getCharacterFromPos(convertWCharToU32String(text), pixel_x);
}
s32 CGUITTFont::getCharacterFromPos(const core::ustring& text, s32 pixel_x) const
s32 CGUITTFont::getCharacterFromPos(const std::u32string& text, s32 pixel_x) const
{
s32 x = 0;
//s32 idx = 0;
u32 character = 0;
uchar32_t previousChar = 0;
core::ustring::const_iterator iter = text.begin();
while (!iter.atEnd())
char32_t previousChar = 0;
std::u32string::const_iterator iter = text.begin();
while (iter != text.end())
{
uchar32_t c = *iter;
char32_t c = *iter;
x += getWidthFromCharacter(c);
// Kerning.
@ -936,10 +939,10 @@ s32 CGUITTFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previo
if (thisLetter == 0 || previousLetter == 0)
return 0;
return getKerningWidth((uchar32_t)*thisLetter, (uchar32_t)*previousLetter);
return getKerningWidth((char32_t)*thisLetter, (char32_t)*previousLetter);
}
s32 CGUITTFont::getKerningWidth(const uchar32_t thisLetter, const uchar32_t previousLetter) const
s32 CGUITTFont::getKerningWidth(const char32_t thisLetter, const char32_t previousLetter) const
{
// Return only the kerning width.
return getKerning(thisLetter, previousLetter).X;
@ -953,10 +956,10 @@ s32 CGUITTFont::getKerningHeight() const
core::vector2di CGUITTFont::getKerning(const wchar_t thisLetter, const wchar_t previousLetter) const
{
return getKerning((uchar32_t)thisLetter, (uchar32_t)previousLetter);
return getKerning((char32_t)thisLetter, (char32_t)previousLetter);
}
core::vector2di CGUITTFont::getKerning(const uchar32_t thisLetter, const uchar32_t previousLetter) const
core::vector2di CGUITTFont::getKerning(const char32_t thisLetter, const char32_t previousLetter) const
{
if (tt_face == 0 || thisLetter == 0 || previousLetter == 0)
return core::vector2di();
@ -1006,20 +1009,18 @@ core::vector2di CGUITTFont::getKerning(const uchar32_t thisLetter, const uchar32
void CGUITTFont::setInvisibleCharacters(const wchar_t *s)
{
core::ustring us(s);
Invisible = us;
Invisible = convertWCharToU32String(s);
}
void CGUITTFont::setInvisibleCharacters(const core::ustring& s)
video::IImage* CGUITTFont::createTextureFromChar(const char32_t& ch)
{
Invisible = s;
}
// This character allows us to print something to the screen for unknown, unrecognizable, or
// unrepresentable characters. See Unicode spec.
const char32_t UTF_REPLACEMENT_CHARACTER = 0xFFFD;
video::IImage* CGUITTFont::createTextureFromChar(const uchar32_t& ch)
{
u32 n = getGlyphIndexByChar(ch);
if (n == 0)
n = getGlyphIndexByChar((uchar32_t) core::unicode::UTF_REPLACEMENT_CHARACTER);
n = getGlyphIndexByChar(UTF_REPLACEMENT_CHARACTER);
const SGUITTGlyph& glyph = Glyphs[n-1];
CGUITTGlyphPage* page = Glyph_Pages[glyph.glyph_page];
@ -1246,5 +1247,27 @@ core::array<scene::ISceneNode*> CGUITTFont::addTextSceneNode(const wchar_t* text
return container;
}
std::u32string CGUITTFont::convertWCharToU32String(const wchar_t* const charArray) const
{
static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "unexpected wchar size");
if (sizeof(wchar_t) == 4) // Systems where wchar_t is UTF-32
return std::u32string(reinterpret_cast<const char32_t*>(charArray));
// Systems where wchar_t is UTF-16:
// First, convert to UTF-8
std::u16string utf16String(reinterpret_cast<const char16_t*>(charArray));
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter1;
std::string utf8String = converter1.to_bytes(utf16String);
// Next, convert to UTF-32
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter2;
return converter2.from_bytes(utf8String);
// This is inefficient, but importantly it is _correct_, rather than a hand-rolled UTF-16 to
// UTF-32 converter which may or may not be correct.
}
} // end namespace gui
} // end namespace irr

@ -2,6 +2,7 @@
CGUITTFont FreeType class for Irrlicht
Copyright (c) 2009-2010 John Norman
Copyright (c) 2016 Nathanaëlle Courant
Copyright (c) 2023 Caleb Butler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
@ -35,7 +36,6 @@
#include <ft2build.h>
#include <vector>
#include <map>
#include <irrUString.h>
#include "util/enriched_string.h"
#include "util/basic_macros.h"
#include FT_FREETYPE_H
@ -289,11 +289,9 @@ namespace gui
//! Returns the dimension of a text string.
virtual core::dimension2d<u32> getDimension(const wchar_t* text) const;
virtual core::dimension2d<u32> getDimension(const core::ustring& text) const;
//! Calculates the index of the character in the text which is on a specific position.
virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const;
virtual s32 getCharacterFromPos(const core::ustring& text, s32 pixel_x) const;
//! Sets global kerning width for the font.
virtual void setKerningWidth(s32 kerning);
@ -303,14 +301,13 @@ namespace gui
//! Gets kerning values (distance between letters) for the font. If no parameters are provided,
virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const;
virtual s32 getKerningWidth(const uchar32_t thisLetter=0, const uchar32_t previousLetter=0) const;
virtual s32 getKerningWidth(const char32_t thisLetter=0, const char32_t previousLetter=0) const;
//! Returns the distance between letters
virtual s32 getKerningHeight() const;
//! Define which characters should not be drawn by the font.
virtual void setInvisibleCharacters(const wchar_t *s);
virtual void setInvisibleCharacters(const core::ustring& s);
//! Get the last glyph page if there's still available slots.
//! If not, it will return zero.
@ -330,7 +327,7 @@ namespace gui
//! Create corresponding character's software image copy from the font,
//! so you can use this data just like any ordinary video::IImage.
//! \param ch The character you need
virtual video::IImage* createTextureFromChar(const uchar32_t& ch);
virtual video::IImage* createTextureFromChar(const char32_t& ch);
//! This function is for debugging mostly. If the page doesn't exist it returns zero.
//! \param page_index Simply return the texture handle of a given page index.
@ -360,6 +357,14 @@ namespace gui
static scene::IMesh* shared_plane_ptr_;
static scene::SMesh shared_plane_;
// Helper functions for the same-named public member functions above
// (Since std::u32string is nicer to work with than wchar_t *)
core::dimension2d<u32> getDimension(const std::u32string& text) const;
s32 getCharacterFromPos(const std::u32string& text, s32 pixel_x) const;
// Helper function for the above helper functions :P
std::u32string convertWCharToU32String(const wchar_t* const) const;
CGUITTFont(IGUIEnvironment *env);
bool load(const io::path& filename, const u32 size, const bool antialias, const bool transparency);
void reset_images();
@ -374,13 +379,13 @@ namespace gui
else load_flags |= FT_LOAD_TARGET_NORMAL;
}
u32 getWidthFromCharacter(wchar_t c) const;
u32 getWidthFromCharacter(uchar32_t c) const;
u32 getWidthFromCharacter(char32_t c) const;
u32 getHeightFromCharacter(wchar_t c) const;
u32 getHeightFromCharacter(uchar32_t c) const;
u32 getHeightFromCharacter(char32_t c) const;
u32 getGlyphIndexByChar(wchar_t c) const;
u32 getGlyphIndexByChar(uchar32_t c) const;
u32 getGlyphIndexByChar(char32_t c) const;
core::vector2di getKerning(const wchar_t thisLetter, const wchar_t previousLetter) const;
core::vector2di getKerning(const uchar32_t thisLetter, const uchar32_t previousLetter) const;
core::vector2di getKerning(const char32_t thisLetter, const char32_t previousLetter) const;
core::dimension2d<u32> getDimensionUntilEndOfLine(const wchar_t* p) const;
void createSharedPlane();
@ -398,7 +403,7 @@ namespace gui
s32 GlobalKerningWidth;
s32 GlobalKerningHeight;
core::ustring Invisible;
std::u32string Invisible;
u32 shadow_offset;
u32 shadow_alpha;