diff --git a/irr/include/IGUIFont.h b/irr/include/IGUIFont.h index c18354c79..5efce9796 100644 --- a/irr/include/IGUIFont.h +++ b/irr/include/IGUIFont.h @@ -53,7 +53,7 @@ public: //! Calculates the width and height of a given string of text. /** \return Returns width and height of the area covered by the text if it would be drawn. */ - virtual core::dimension2d getDimension(const wchar_t *text) const = 0; + virtual core::dimension2du getDimension(const wchar_t *text) const = 0; //! Calculates the index of the character in the text which is on a specific position. /** \param text: Text string. @@ -82,10 +82,7 @@ public: which supports kerning pairs a string such as 'Wo' may have the 'o' tucked neatly under the 'W'. */ - virtual s32 getKerningWidth(const wchar_t *thisLetter = 0, const wchar_t *previousLetter = 0) const = 0; - - //! Returns the distance between letters - virtual s32 getKerningHeight() const = 0; + virtual core::vector2di getKerning(const wchar_t thisLetter = 0, const wchar_t previousLetter = 0) const = 0; //! Define which characters should not be drawn by the font. /** For example " " would not draw any space which is usually blank in diff --git a/irr/include/IGUIFontBitmap.h b/irr/include/IGUIFontBitmap.h index b86dbe2bf..f7bd70dc3 100644 --- a/irr/include/IGUIFontBitmap.h +++ b/irr/include/IGUIFontBitmap.h @@ -24,17 +24,6 @@ public: //! returns the sprite number from a given character virtual u32 getSpriteNoFromChar(const wchar_t *c) const = 0; - - //! Gets kerning values (distance between letters) for the font. If no parameters are provided, - /** the global kerning distance is returned. - \param thisLetter: If this parameter is provided, the left side kerning for this letter is added - to the global kerning value. For example, a space might only be one pixel wide, but it may - be displayed as several pixels. - \param previousLetter: If provided, kerning is calculated for both letters and added to the global - kerning value. For example, EGFT_BITMAP will add the right kerning value of previousLetter to the - left side kerning value of thisLetter, then add the global value. - */ - s32 getKerningWidth(const wchar_t *thisLetter = 0, const wchar_t *previousLetter = 0) const override = 0; }; } // end namespace gui diff --git a/irr/src/CGUIEditBox.cpp b/irr/src/CGUIEditBox.cpp index 7d1571606..6c29e89a9 100644 --- a/irr/src/CGUIEditBox.cpp +++ b/irr/src/CGUIEditBox.cpp @@ -788,9 +788,9 @@ void CGUIEditBox::draw() mbegin = font->getDimension(s.c_str()).Width; // deal with kerning - mbegin += font->getKerningWidth( - &((*txtLine)[realmbgn - startPos]), - realmbgn - startPos > 0 ? &((*txtLine)[realmbgn - startPos - 1]) : 0); + mbegin += font->getKerning( + (*txtLine)[realmbgn - startPos], + realmbgn - startPos > 0 ? (*txtLine)[realmbgn - startPos - 1] : 0).X; lineStartPos = realmbgn - startPos; } @@ -832,7 +832,8 @@ void CGUIEditBox::draw() } s = txtLine->subString(0, CursorPos - startPos); charcursorpos = font->getDimension(s.c_str()).Width + - font->getKerningWidth(CursorChar.c_str(), CursorPos - startPos > 0 ? &((*txtLine)[CursorPos - startPos - 1]) : 0); + font->getKerning(CursorChar[0], + CursorPos - startPos > 0 ? (*txtLine)[CursorPos - startPos - 1] : 0).X; if (focus && (CursorBlinkTime == 0 || (os::Timer::getTime() - BlinkStartTime) % (2 * CursorBlinkTime) < CursorBlinkTime)) { setTextRect(cursorLine); @@ -1194,7 +1195,7 @@ void CGUIEditBox::setTextRect(s32 line) d = font->getDimension(Text.c_str()); d.Height = AbsoluteRect.getHeight(); } - d.Height += font->getKerningHeight(); + d.Height += font->getKerning(L'A').Y; // justification switch (HAlign) { @@ -1382,7 +1383,7 @@ void CGUIEditBox::calculateScrollPos() // calculate vertical scrolling if (hasBrokenText) { - irr::u32 lineHeight = font->getDimension(L"A").Height + font->getKerningHeight(); + irr::u32 lineHeight = font->getDimension(L"A").Height + font->getKerning(L'A').Y; // only up to 1 line fits? if (lineHeight >= (irr::u32)FrameRect.getHeight()) { VScrollPos = 0; diff --git a/irr/src/CGUIFont.cpp b/irr/src/CGUIFont.cpp index c00b40395..951304476 100644 --- a/irr/src/CGUIFont.cpp +++ b/irr/src/CGUIFont.cpp @@ -53,141 +53,6 @@ CGUIFont::~CGUIFont() } } -#if 0 -//! loads a font file from xml -bool CGUIFont::load(io::IXMLReader* xml, const io::path& directory) -{ - if (!SpriteBank) - return false; - - SpriteBank->clear(); - - while (xml->read()) - { - if (io::EXN_ELEMENT == xml->getNodeType()) - { - if (core::stringw(L"Texture") == xml->getNodeName()) - { - // add a texture - core::stringc fn = xml->getAttributeValue(L"filename"); - u32 i = (u32)xml->getAttributeValueAsInt(L"index"); - core::stringw alpha = xml->getAttributeValue(L"hasAlpha"); - - while (i+1 > SpriteBank->getTextureCount()) - SpriteBank->addTexture(0); - - bool flags[3]; - pushTextureCreationFlags(flags); - - // load texture - io::path textureFullName = core::mergeFilename(directory, fn); - SpriteBank->setTexture(i, Driver->getTexture(textureFullName)); - - popTextureCreationFlags(flags); - - // couldn't load texture, abort. - if (!SpriteBank->getTexture(i)) - { - os::Printer::log("Unable to load all textures in the font, aborting", ELL_ERROR); - return false; - } - else - { - // colorkey texture rather than alpha channel? - if (alpha == core::stringw("false")) - Driver->makeColorKeyTexture(SpriteBank->getTexture(i), core::position2di(0,0)); - } - } - else if (core::stringw(L"c") == xml->getNodeName()) - { - // adding a character to this font - SFontArea a; - SGUISpriteFrame f; - SGUISprite s; - core::rect rectangle; - - a.underhang = xml->getAttributeValueAsInt(L"u"); - a.overhang = xml->getAttributeValueAsInt(L"o"); - a.spriteno = SpriteBank->getSprites().size(); - s32 texno = xml->getAttributeValueAsInt(L"i"); - - // parse rectangle - core::stringc rectstr = xml->getAttributeValue(L"r"); - wchar_t ch = xml->getAttributeValue(L"c")[0]; - - const c8 *c = rectstr.c_str(); - s32 val; - val = 0; - while (*c >= '0' && *c <= '9') - { - val *= 10; - val += *c - '0'; - c++; - } - rectangle.UpperLeftCorner.X = val; - while (*c == L' ' || *c == L',') c++; - - val = 0; - while (*c >= '0' && *c <= '9') - { - val *= 10; - val += *c - '0'; - c++; - } - rectangle.UpperLeftCorner.Y = val; - while (*c == L' ' || *c == L',') c++; - - val = 0; - while (*c >= '0' && *c <= '9') - { - val *= 10; - val += *c - '0'; - c++; - } - rectangle.LowerRightCorner.X = val; - while (*c == L' ' || *c == L',') c++; - - val = 0; - while (*c >= '0' && *c <= '9') - { - val *= 10; - val += *c - '0'; - c++; - } - rectangle.LowerRightCorner.Y = val; - - CharacterMap.emplace(ch, Areas.size()); - - // make frame - f.rectNumber = SpriteBank->getPositions().size(); - f.textureNumber = texno; - - // add frame to sprite - s.Frames.push_back(f); - s.frameTime = 0; - - // add rectangle to sprite bank - SpriteBank->getPositions().push_back(rectangle); - a.width = rectangle.getWidth(); - - // add sprite to sprite bank - SpriteBank->getSprites().push_back(s); - - // add character to font - Areas.push_back(a); - } - } - } - - // set bad character - WrongCharacter = getAreaFromCharacter(L' '); - - setMaxHeight(); - - return true; -} -#endif - void CGUIFont::setMaxHeight() { if (!SpriteBank) @@ -365,17 +230,15 @@ void CGUIFont::setKerningWidth(s32 kerning) GlobalKerningWidth = kerning; } -//! set an Pixel Offset on Drawing ( scale position on width ) -s32 CGUIFont::getKerningWidth(const wchar_t *thisLetter, const wchar_t *previousLetter) const +core::vector2di CGUIFont::getKerning(const wchar_t thisLetter, const wchar_t previousLetter) const { - s32 ret = GlobalKerningWidth; + core::vector2di ret(GlobalKerningWidth, GlobalKerningHeight); if (thisLetter) { - ret += Areas[getAreaFromCharacter(*thisLetter)].overhang; + ret.X += Areas[getAreaFromCharacter(thisLetter)].overhang; - if (previousLetter) { - ret += Areas[getAreaFromCharacter(*previousLetter)].underhang; - } + if (previousLetter) + ret.X += Areas[getAreaFromCharacter(previousLetter)].underhang; } return ret; @@ -387,12 +250,6 @@ void CGUIFont::setKerningHeight(s32 kerning) GlobalKerningHeight = kerning; } -//! set an Pixel Offset on Drawing ( scale position on height ) -s32 CGUIFont::getKerningHeight() const -{ - return GlobalKerningHeight; -} - //! returns the sprite number from a given character u32 CGUIFont::getSpriteNoFromChar(const wchar_t *c) const { diff --git a/irr/src/CGUIFont.h b/irr/src/CGUIFont.h index 2f383a5f7..8a3b8100b 100644 --- a/irr/src/CGUIFont.h +++ b/irr/src/CGUIFont.h @@ -58,8 +58,7 @@ public: void setKerningHeight(s32 kerning) override; //! set an Pixel Offset on Drawing ( scale position on width ) - s32 getKerningWidth(const wchar_t *thisLetter = 0, const wchar_t *previousLetter = 0) const override; - s32 getKerningHeight() const override; + core::vector2di getKerning(const wchar_t thisLetter, const wchar_t previousLetter) const override; //! gets the sprite bank IGUISpriteBank *getSpriteBank() const override; diff --git a/irr/src/CGUIStaticText.cpp b/irr/src/CGUIStaticText.cpp index 871589447..4cd3f7905 100644 --- a/irr/src/CGUIStaticText.cpp +++ b/irr/src/CGUIStaticText.cpp @@ -74,10 +74,12 @@ void CGUIStaticText::draw() IGUIFont *font = getActiveFont(); if (font) { + s32 kerningHeight = font->getKerning(L'A').Y; + if (!WordWrap) { if (VAlign == EGUIA_LOWERRIGHT) { frameRect.UpperLeftCorner.Y = frameRect.LowerRightCorner.Y - - font->getDimension(L"A").Height - font->getKerningHeight(); + font->getDimension(L"A").Height - kerningHeight; } if (HAlign == EGUIA_LOWERRIGHT) { frameRect.UpperLeftCorner.X = frameRect.LowerRightCorner.X - @@ -92,7 +94,7 @@ void CGUIStaticText::draw() breakText(); core::rect r = frameRect; - s32 height = font->getDimension(L"A").Height + font->getKerningHeight(); + s32 height = font->getDimension(L"A").Height + kerningHeight; s32 totalHeight = height * BrokenText.size(); if (VAlign == EGUIA_CENTER) { r.UpperLeftCorner.Y = r.getCenter().Y - (totalHeight / 2); @@ -471,7 +473,7 @@ s32 CGUIStaticText::getTextHeight() const return 0; if (WordWrap) { - s32 height = font->getDimension(L"A").Height + font->getKerningHeight(); + s32 height = font->getDimension(L"A").Height + font->getKerning(L'A').Y; return height * BrokenText.size(); } else { // TODO: Text can have multiple lines which are not in BrokenText diff --git a/src/client/fontengine.cpp b/src/client/fontengine.cpp index aa3e0cd4c..89214ef7c 100644 --- a/src/client/fontengine.cpp +++ b/src/client/fontengine.cpp @@ -140,7 +140,7 @@ unsigned int FontEngine::getLineHeight(const FontSpec &spec) gui::IGUIFont *font = getFont(spec); return font->getDimension(L"Some unimportant example String").Height - + font->getKerningHeight(); + + font->getKerning(L'S').Y; } /******************************************************************************/ diff --git a/src/gui/guiEditBoxWithScrollbar.cpp b/src/gui/guiEditBoxWithScrollbar.cpp index bc594bba6..4206a2249 100644 --- a/src/gui/guiEditBoxWithScrollbar.cpp +++ b/src/gui/guiEditBoxWithScrollbar.cpp @@ -194,9 +194,9 @@ void GUIEditBoxWithScrollBar::draw() mbegin = font->getDimension(s.c_str()).Width; // deal with kerning - mbegin += font->getKerningWidth( - &((*txt_line)[realmbgn - start_pos]), - realmbgn - start_pos > 0 ? &((*txt_line)[realmbgn - start_pos - 1]) : 0); + mbegin += font->getKerning( + (*txt_line)[realmbgn - start_pos], + realmbgn - start_pos > 0 ? (*txt_line)[realmbgn - start_pos - 1] : 0).X; lineStartPos = realmbgn - start_pos; } @@ -242,7 +242,8 @@ void GUIEditBoxWithScrollBar::draw() } s = txt_line->subString(0, m_cursor_pos - start_pos); charcursorpos = font->getDimension(s.c_str()).Width + - font->getKerningWidth(L"_", m_cursor_pos - start_pos > 0 ? &((*txt_line)[m_cursor_pos - start_pos - 1]) : 0); + font->getKerning(L'_', + m_cursor_pos - start_pos > 0 ? (*txt_line)[m_cursor_pos - start_pos - 1] : 0).X; if (focus && (porting::getTimeMs() - m_blink_start_time) % 700 < 350) { setTextRect(cursor_line); @@ -431,7 +432,7 @@ void GUIEditBoxWithScrollBar::setTextRect(s32 line) d = font->getDimension(Text.c_str()); d.Height = AbsoluteRect.getHeight(); } - d.Height += font->getKerningHeight(); + d.Height += font->getKerning(L'A').Y; // justification switch (m_halign) { @@ -536,7 +537,7 @@ void GUIEditBoxWithScrollBar::calculateScrollPos() // calculate vertical scrolling if (has_broken_text) { - irr::u32 line_height = font->getDimension(L"A").Height + font->getKerningHeight(); + irr::u32 line_height = font->getDimension(L"A").Height + font->getKerning(L'A').Y; // only up to 1 line fits? if (line_height >= (irr::u32)m_frame_rect.getHeight()) { m_vscroll_pos = 0; diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 8a69f0429..7478c389d 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -79,7 +79,7 @@ */ static unsigned int font_line_height(gui::IGUIFont *font) { - return font->getDimension(L"Ay").Height + font->getKerningHeight(); + return font->getDimension(L"Ay").Height + font->getKerning(L'A').Y; } inline u32 clamp_u8(s32 value) diff --git a/src/irrlicht_changes/CGUITTFont.cpp b/src/irrlicht_changes/CGUITTFont.cpp index 73962605d..980752149 100644 --- a/src/irrlicht_changes/CGUITTFont.cpp +++ b/src/irrlicht_changes/CGUITTFont.cpp @@ -1,6 +1,7 @@ /* CGUITTFont FreeType class for Irrlicht Copyright (c) 2009-2010 John Norman + with changes from Luanti contributors: Copyright (c) 2016 Nathanaƫlle Courant Copyright (c) 2023 Caleb Butler @@ -31,14 +32,13 @@ */ #include +#include "log.h" +#include "filesys.h" +#include "debug.h" + #include "CGUITTFont.h" -#include "CMeshBuffer.h" #include "IFileSystem.h" #include "IGUIEnvironment.h" -#include "IMeshManipulator.h" -#include "IMeshSceneNode.h" -#include "ISceneManager.h" -#include "ISceneNode.h" namespace irr { @@ -46,9 +46,9 @@ namespace gui { // Manages the FT_Face cache. -struct SGUITTFace : public virtual irr::IReferenceCounted +struct SGUITTFace : public irr::IReferenceCounted { - SGUITTFace() : face_buffer(0), face_buffer_size(0) + SGUITTFace() { memset((void*)&face, 0, sizeof(FT_Face)); } @@ -56,46 +56,29 @@ struct SGUITTFace : public virtual irr::IReferenceCounted ~SGUITTFace() { FT_Done_Face(face); - delete[] face_buffer; } FT_Face face; - FT_Byte* face_buffer; - FT_Long face_buffer_size; + std::string face_buffer; }; // Static variables. FT_Library CGUITTFont::c_library; std::map CGUITTFont::c_faces; bool CGUITTFont::c_libraryLoaded = false; -scene::IMesh* CGUITTFont::shared_plane_ptr_ = 0; -scene::SMesh CGUITTFont::shared_plane_; // -/** Checks that no dimension of the FT_BitMap object is negative. If either is - * negative, abort execution. - */ -inline void checkFontBitmapSize(const FT_Bitmap &bits) -{ - if ((s32)bits.rows < 0 || (s32)bits.width < 0) { - std::cout << "Insane font glyph size. File: " - << __FILE__ << " Line " << __LINE__ - << std::endl; - abort(); - } -} - video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const { // Make sure our casts to s32 in the loops below will not cause problems - checkFontBitmapSize(bits); + if ((s32)bits.rows < 0 || (s32)bits.width < 0) + FATAL_ERROR("Insane font glyph size"); // Determine what our texture size should be. // Add 1 because textures are inclusive-exclusive. core::dimension2du d(bits.width + 1, bits.rows + 1); core::dimension2du texture_size; - //core::dimension2du texture_size(bits.width + 1, bits.rows + 1); // Create and load our image now. video::IImage* image = 0; @@ -147,36 +130,36 @@ video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVide for (s32 x = 0; x < (s32)bits.width; ++x) { image_data[y * image_pitch + x] |= static_cast(255.0f * (static_cast(*row++) / gray_count)) << 24; - //data[y * image_pitch + x] |= ((u32)(*bitsdata++) << 24); } glyph_data += bits.pitch; } break; } default: - // TODO: error message? + errorstream << "CGUITTFont: unknown pixel mode " << (int)bits.pixel_mode << std::endl; return 0; } return image; } -void SGUITTGlyph::preload(u32 char_index, FT_Face face, video::IVideoDriver* driver, u32 font_size, const FT_Int32 loadFlags) +void SGUITTGlyph::preload(u32 char_index, FT_Face face, CGUITTFont *parent, u32 font_size, const FT_Int32 loadFlags) { - if (isLoaded) return; - // Set the size of the glyph. FT_Set_Pixel_Sizes(face, 0, font_size); // Attempt to load the glyph. - if (FT_Load_Glyph(face, char_index, loadFlags) != FT_Err_Ok) - // TODO: error message? + auto err = FT_Load_Glyph(face, char_index, loadFlags); + if (err != FT_Err_Ok) { + warningstream << "SGUITTGlyph: failed to load glyph " << char_index + << " with error: " << (int)err << std::endl; return; + } FT_GlyphSlot glyph = face->glyph; - FT_Bitmap bits = glyph->bitmap; + const FT_Bitmap &bits = glyph->bitmap; // Setup the glyph information here: - advance = glyph->advance; + advance = core::vector2di(glyph->advance.x, glyph->advance.y); offset = core::vector2di(glyph->bitmap_left, glyph->bitmap_top); // Try to get the last page with available slots. @@ -187,7 +170,6 @@ void SGUITTGlyph::preload(u32 char_index, FT_Face face, video::IVideoDriver* dri { page = parent->createGlyphPage(bits.pixel_mode); if (!page) - // TODO: add error message? return; } @@ -205,10 +187,7 @@ void SGUITTGlyph::preload(u32 char_index, FT_Face face, video::IVideoDriver* dri --page->available_slots; // We grab the glyph bitmap here so the data won't be removed when the next glyph is loaded. - surface = createGlyphImage(bits, driver); - - // Set our glyph as loaded. - isLoaded = true; + surface = createGlyphImage(bits, parent->getDriver()); } void SGUITTGlyph::unload() @@ -218,7 +197,8 @@ void SGUITTGlyph::unload() surface->drop(); surface = 0; } - isLoaded = false; + // reset isLoaded to false + source_rect = core::recti(); } ////////////////////// @@ -251,14 +231,13 @@ CGUITTFont* CGUITTFont::createTTFont(IGUIEnvironment *env, const io::path& filen //! Constructor. CGUITTFont::CGUITTFont(IGUIEnvironment *env) : use_monochrome(false), use_transparency(true), use_hinting(true), use_auto_hinting(true), -batch_load_size(1), Device(0), Environment(env), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0), +batch_load_size(1), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0), shadow_offset(0), shadow_alpha(0), fallback(0) { - if (Environment) - { + if (env) { // don't grab environment, to avoid circular references - Driver = Environment->getVideoDriver(); + Driver = env->getVideoDriver(); } if (Driver) @@ -270,13 +249,10 @@ shadow_offset(0), shadow_alpha(0), fallback(0) bool CGUITTFont::load(const io::path& filename, const u32 size, const bool antialias, const bool transparency) { // Some sanity checks. - if (Environment == 0 || Driver == 0) return false; + if (!Driver) return false; if (size == 0) return false; - if (filename.size() == 0) return false; + if (filename.empty()) return false; - io::IFileSystem* filesystem = Environment->getFileSystem(); - irr::ILogger* logger = (Device != 0 ? Device->getLogger() : 0); - // FIXME: this is always null ^ this->size = size; this->filename = filename; @@ -285,62 +261,33 @@ bool CGUITTFont::load(const io::path& filename, const u32 size, const bool antia this->use_transparency = transparency; update_load_flags(); - // Log. - if (logger) - logger->log("CGUITTFont", (core::stringc(L"Creating new font: ") + filename + " " + core::stringc(size) + "pt " + (antialias ? "+antialias " : "-antialias ") + (transparency ? "+transparency" : "-transparency")).c_str(), irr::ELL_INFORMATION); + infostream << "CGUITTFont: Creating new font: " << filename.c_str() << " " + << size << "pt " << (antialias ? "+antialias " : "-antialias ") + << (transparency ? "+transparency" : "-transparency") << std::endl; // Grab the face. - SGUITTFace* face = 0; + SGUITTFace* face = nullptr; auto node = c_faces.find(filename); - if (node == c_faces.end()) - { + if (node == c_faces.end()) { face = new SGUITTFace(); + + if (!fs::ReadFile(filename.c_str(), face->face_buffer, true)) { + delete face; + return false; + } + + // Create the face. + if (FT_New_Memory_Face(c_library, + reinterpret_cast(face->face_buffer.data()), + face->face_buffer.size(), 0, &face->face)) + { + errorstream << "CGUITTFont: FT_New_Memory_Face failed." << std::endl; + delete face; + return false; + } + c_faces.emplace(filename, face); - - if (filesystem) - { - // Read in the file data. - io::IReadFile* file = filesystem->createAndOpenFile(filename); - if (file == 0) - { - if (logger) logger->log("CGUITTFont", "Failed to open the file.", irr::ELL_INFORMATION); - - c_faces.erase(filename); - delete face; - face = 0; - return false; - } - face->face_buffer = new FT_Byte[file->getSize()]; - file->read(face->face_buffer, file->getSize()); - face->face_buffer_size = file->getSize(); - file->drop(); - - // Create the face. - if (FT_New_Memory_Face(c_library, face->face_buffer, face->face_buffer_size, 0, &face->face)) - { - if (logger) logger->log("CGUITTFont", "FT_New_Memory_Face failed.", irr::ELL_INFORMATION); - - c_faces.erase(filename); - delete face; - face = 0; - return false; - } - } - else - { - if (FT_New_Face(c_library, reinterpret_cast(filename.c_str()), 0, &face->face)) - { - if (logger) logger->log("CGUITTFont", "FT_New_Face failed.", irr::ELL_INFORMATION); - - c_faces.erase(filename); - delete face; - face = 0; - return false; - } - } - } - else - { + } else { // Using another instance of this face. face = node->second; face->grab(); @@ -353,20 +300,12 @@ bool CGUITTFont::load(const io::path& filename, const u32 size, const bool antia FT_Set_Pixel_Sizes(tt_face, size, 0); font_metrics = tt_face->size->metrics; + verbosestream << tt_face->num_glyphs << " glyphs, ascender=" << font_metrics.ascender + << " height=" << font_metrics.height << std::endl; + // Allocate our glyphs. Glyphs.clear(); - Glyphs.reallocate(tt_face->num_glyphs); Glyphs.set_used(tt_face->num_glyphs); - for (FT_Long i = 0; i < tt_face->num_glyphs; ++i) - { - Glyphs[i].isLoaded = false; - Glyphs[i].glyph_page = 0; - Glyphs[i].source_rect = core::recti(); - Glyphs[i].offset = core::vector2di(); - Glyphs[i].advance = FT_Vector(); - Glyphs[i].surface = 0; - Glyphs[i].parent = this; - } // Cache the first 127 ascii characters. u32 old_size = batch_load_size; @@ -444,7 +383,7 @@ CGUITTGlyphPage* CGUITTFont::getLastGlyphPage() const return page; } -CGUITTGlyphPage* CGUITTFont::createGlyphPage(const u8& pixel_mode) +CGUITTGlyphPage* CGUITTFont::createGlyphPage(const u8 pixel_mode) { CGUITTGlyphPage* page = 0; @@ -481,7 +420,8 @@ CGUITTGlyphPage* CGUITTFont::createGlyphPage(const u8& pixel_mode) page_texture_size = max_texture_size; if (!page->createPageTexture(pixel_mode, page_texture_size)) { - // TODO: add error message? + errorstream << "CGUITTGlyphPage: failed to create texture (" + << page_texture_size.Width << "x" << page_texture_size.Height << ")" << std::endl; delete page; return 0; } @@ -622,13 +562,12 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect& positio else if (fallback != 0) { // Let the fallback font draw it, this isn't super efficient but hopefully that doesn't matter - wchar_t l1[] = { (wchar_t) currentChar, 0 }, l2 = (wchar_t) previousChar; + wchar_t l1[] = { (wchar_t) currentChar, 0 }; if (visible) { // Apply kerning. - offset.X += fallback->getKerningWidth(l1, &l2); - offset.Y += fallback->getKerningHeight(); + offset += fallback->getKerning(*l1, (wchar_t) previousChar); const u32 current_color = iter - utext.begin(); fallback->draw(core::stringw(l1), @@ -688,11 +627,6 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect& positio } } -core::dimension2d CGUITTFont::getCharDimension(const wchar_t ch) const -{ - return core::dimension2d(getWidthFromCharacter(ch), getHeightFromCharacter(ch)); -} - core::dimension2d CGUITTFont::getDimension(const wchar_t* text) const { return getDimension(convertWCharToU32String(text)); @@ -759,21 +693,12 @@ core::dimension2d CGUITTFont::getDimension(const std::u32string& text) cons return text_dimension; } -inline u32 CGUITTFont::getWidthFromCharacter(wchar_t c) const -{ - return getWidthFromCharacter((char32_t)c); -} - 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. - //FT_Set_Pixel_Sizes(tt_face, 0, size); - u32 n = getGlyphIndexByChar(c); if (n > 0) { - int w = Glyphs[n-1].advance.x / 64; + int w = Glyphs[n-1].advance.X / 64; return w; } if (fallback != 0) @@ -787,17 +712,8 @@ inline u32 CGUITTFont::getWidthFromCharacter(char32_t c) const else return (font_metrics.ascender / 64) / 2; } -inline u32 CGUITTFont::getHeightFromCharacter(wchar_t c) const -{ - return getHeightFromCharacter((char32_t)c); -} - 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. - //FT_Set_Pixel_Sizes(tt_face, 0, size); - u32 n = getGlyphIndexByChar(c); if (n > 0) { @@ -816,11 +732,6 @@ inline u32 CGUITTFont::getHeightFromCharacter(char32_t c) const else return (font_metrics.ascender / 64) / 2; } -u32 CGUITTFont::getGlyphIndexByChar(wchar_t c) const -{ - return getGlyphIndexByChar((char32_t)c); -} - u32 CGUITTFont::getGlyphIndexByChar(char32_t c) const { // Get the glyph. @@ -831,7 +742,7 @@ u32 CGUITTFont::getGlyphIndexByChar(char32_t c) const return 0; // If our glyph is already loaded, don't bother doing any batch loading code. - if (glyph != 0 && Glyphs[glyph - 1].isLoaded) + if (glyph != 0 && Glyphs[glyph - 1].isLoaded()) return glyph; // Determine our batch loading positions. @@ -850,9 +761,10 @@ u32 CGUITTFont::getGlyphIndexByChar(char32_t c) const if (char_index) { SGUITTGlyph& glyph = Glyphs[char_index - 1]; - if (!glyph.isLoaded) + if (!glyph.isLoaded()) { - glyph.preload(char_index, tt_face, Driver, size, load_flags); + auto *this2 = const_cast(this); // oh well + glyph.preload(char_index, tt_face, this2, size, load_flags); Glyph_Pages[glyph.glyph_page]->pushGlyphToBePaged(&glyph); } } @@ -871,11 +783,10 @@ s32 CGUITTFont::getCharacterFromPos(const wchar_t* 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; char32_t previousChar = 0; - std::u32string::const_iterator iter = text.begin(); + auto iter = text.begin(); while (iter != text.end()) { char32_t c = *iter; @@ -906,28 +817,6 @@ void CGUITTFont::setKerningHeight(s32 kerning) GlobalKerningHeight = kerning; } -s32 CGUITTFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const -{ - if (tt_face == 0) - return GlobalKerningWidth; - if (thisLetter == 0 || previousLetter == 0) - return 0; - - return getKerningWidth((char32_t)*thisLetter, (char32_t)*previousLetter); -} - -s32 CGUITTFont::getKerningWidth(const char32_t thisLetter, const char32_t previousLetter) const -{ - // Return only the kerning width. - return getKerning(thisLetter, previousLetter).X; -} - -s32 CGUITTFont::getKerningHeight() const -{ - // FreeType 2 currently doesn't return any height kerning information. - return GlobalKerningHeight; -} - core::vector2di CGUITTFont::getKerning(const wchar_t thisLetter, const wchar_t previousLetter) const { return getKerning((char32_t)thisLetter, (char32_t)previousLetter); @@ -949,11 +838,8 @@ core::vector2di CGUITTFont::getKerning(const char32_t thisLetter, const char32_t // If we don't have this glyph, ask fallback font if (n == 0) { - if (fallback != 0) { - wchar_t l1 = (wchar_t) thisLetter, l2 = (wchar_t) previousLetter; - ret.X = fallback->getKerningWidth(&l1, &l2); - ret.Y = fallback->getKerningHeight(); - } + if (fallback) + ret = fallback->getKerning((wchar_t) thisLetter, (wchar_t) previousLetter); return ret; } @@ -1029,196 +915,6 @@ video::ITexture* CGUITTFont::getPageTextureByIndex(const u32& page_index) const return 0; } -void CGUITTFont::createSharedPlane() -{ - /* - 2___3 - | /| - | / | <-- plane mesh is like this, point 2 is (0,0), point 0 is (0, -1) - |/ | <-- the texture coords of point 2 is (0,0, point 0 is (0, 1) - 0---1 - */ - - using namespace core; - using namespace video; - using namespace scene; - S3DVertex vertices[4]; - u16 indices[6] = {0,2,3,3,1,0}; - vertices[0] = S3DVertex(vector3df(0,-1,0), vector3df(0,0,-1), SColor(255,255,255,255), vector2df(0,1)); - vertices[1] = S3DVertex(vector3df(1,-1,0), vector3df(0,0,-1), SColor(255,255,255,255), vector2df(1,1)); - vertices[2] = S3DVertex(vector3df(0, 0,0), vector3df(0,0,-1), SColor(255,255,255,255), vector2df(0,0)); - vertices[3] = S3DVertex(vector3df(1, 0,0), vector3df(0,0,-1), SColor(255,255,255,255), vector2df(1,0)); - - SMeshBuffer* buf = new SMeshBuffer(); - buf->append(vertices, 4, indices, 6); - - shared_plane_.addMeshBuffer( buf ); - shared_plane_.setHardwareMappingHint(EHM_STATIC); - - shared_plane_ptr_ = &shared_plane_; - buf->drop(); //the addMeshBuffer method will grab it, so we can drop this ptr. -} - -core::dimension2d CGUITTFont::getDimensionUntilEndOfLine(const wchar_t* p) const -{ - core::stringw s; - for (const wchar_t* temp = p; temp && *temp != '\0' && *temp != L'\r' && *temp != L'\n'; ++temp ) - s.append(*temp); - - return getDimension(s.c_str()); -} - -core::array CGUITTFont::addTextSceneNode(const wchar_t* text, scene::ISceneManager* smgr, scene::ISceneNode* parent, const video::SColor& color, bool center) -{ - using namespace core; - using namespace video; - using namespace scene; - - array container; - - if (!Driver || !smgr) return container; - if (!parent) - parent = smgr->addEmptySceneNode(smgr->getRootSceneNode(), -1); - // if you don't specify parent, then we add an empty node attached to the root node - // this is generally undesirable. - - if (!shared_plane_ptr_) //this points to a static mesh that contains the plane - createSharedPlane(); //if it's not initialized, we create one. - - dimension2d text_size(getDimension(text)); //convert from unsigned to signed. - vector3df start_point(0, 0, 0), offset; - - /** NOTICE: - Because we are considering adding texts into 3D world, all Y axis vectors are inverted. - **/ - - // There's currently no "vertical center" concept when you apply text scene node to the 3D world. - if (center) - { - offset.X = start_point.X = -text_size.Width / 2.f; - offset.Y = start_point.Y = +text_size.Height/ 2.f; - offset.X += (text_size.Width - getDimensionUntilEndOfLine(text).Width) >> 1; - } - - // the default font material - SMaterial mat; - mat.ZWriteEnable = video::EZW_OFF; - mat.MaterialType = use_transparency ? video::EMT_TRANSPARENT_ALPHA_CHANNEL : video::EMT_SOLID; - mat.MaterialTypeParam = 0.01f; - - wchar_t current_char = 0, previous_char = 0; - u32 n = 0; - - array glyph_indices; - - while (*text) - { - current_char = *text; - bool line_break=false; - if (current_char == L'\r') // Mac or Windows breaks - { - line_break = true; - if (*(text + 1) == L'\n') // Windows line breaks. - current_char = *(++text); - } - else if (current_char == L'\n') // Unix breaks - { - line_break = true; - } - - if (line_break) - { - previous_char = 0; - offset.Y -= tt_face->size->metrics.ascender / 64; - offset.X = start_point.X; - if (center) - offset.X += (text_size.Width - getDimensionUntilEndOfLine(text+1).Width) >> 1; - ++text; - } - else - { - n = getGlyphIndexByChar(current_char); - if (n > 0) - { - glyph_indices.push_back( n ); - - // Store glyph size and offset informations. - SGUITTGlyph const& glyph = Glyphs[n-1]; - u32 texw = glyph.source_rect.getWidth(); - u32 texh = glyph.source_rect.getHeight(); - s32 offx = glyph.offset.X; - s32 offy = (font_metrics.ascender / 64) - glyph.offset.Y; - - // Apply kerning. - vector2di k = getKerning(current_char, previous_char); - offset.X += k.X; - offset.Y += k.Y; - - vector3df current_pos(offset.X + offx, offset.Y - offy, 0); - dimension2d letter_size = dimension2d(texw, texh); - - // Now we copy planes corresponding to the letter size. - IMeshManipulator* mani = smgr->getMeshManipulator(); - IMesh* meshcopy = mani->createMeshCopy(shared_plane_ptr_); - mani->scale(meshcopy, vector3df((f32)letter_size.Width, (f32)letter_size.Height, 1)); - - ISceneNode* current_node = smgr->addMeshSceneNode(meshcopy, parent, -1, current_pos); - meshcopy->drop(); - - current_node->getMaterial(0) = mat; - current_node->setAutomaticCulling(EAC_OFF); - current_node->setIsDebugObject(true); //so the picking won't have any effect on individual letter - //current_node->setDebugDataVisible(EDS_BBOX); //de-comment this when debugging - - container.push_back(current_node); - } - offset.X += getWidthFromCharacter(current_char); - // Note that fallback font handling is missing here (Minetest never uses this) - - previous_char = current_char; - ++text; - } - } - - update_glyph_pages(); - //only after we update the textures can we use the glyph page textures. - - for (u32 i = 0; i < glyph_indices.size(); ++i) - { - u32 n = glyph_indices[i]; - SGUITTGlyph const& glyph = Glyphs[n-1]; - ITexture* current_tex = Glyph_Pages[glyph.glyph_page]->texture; - f32 page_texture_size = (f32)current_tex->getSize().Width; - //Now we calculate the UV position according to the texture size and the source rect. - // - // 2___3 - // | /| - // | / | <-- plane mesh is like this, point 2 is (0,0), point 0 is (0, -1) - // |/ | <-- the texture coords of point 2 is (0,0, point 0 is (0, 1) - // 0---1 - // - f32 u1 = glyph.source_rect.UpperLeftCorner.X / page_texture_size; - f32 u2 = u1 + (glyph.source_rect.getWidth() / page_texture_size); - f32 v1 = glyph.source_rect.UpperLeftCorner.Y / page_texture_size; - f32 v2 = v1 + (glyph.source_rect.getHeight() / page_texture_size); - - //we can be quite sure that this is IMeshSceneNode, because we just added them in the above loop. - IMeshSceneNode* node = static_cast(container[i]); - - S3DVertex* pv = static_cast(node->getMesh()->getMeshBuffer(0)->getVertices()); - //pv[0].TCoords.Y = pv[1].TCoords.Y = (letter_size.Height - 1) / static_cast(letter_size.Height); - //pv[1].TCoords.X = pv[3].TCoords.X = (letter_size.Width - 1) / static_cast(letter_size.Width); - pv[0].TCoords = vector2df(u1, v2); - pv[1].TCoords = vector2df(u2, v2); - pv[2].TCoords = vector2df(u1, v1); - pv[3].TCoords = vector2df(u2, v1); - - container[i]->getMaterial(0).setTexture(0, current_tex); - } - - 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"); diff --git a/src/irrlicht_changes/CGUITTFont.h b/src/irrlicht_changes/CGUITTFont.h index f8e9d8896..c010cf181 100644 --- a/src/irrlicht_changes/CGUITTFont.h +++ b/src/irrlicht_changes/CGUITTFont.h @@ -32,17 +32,17 @@ #pragma once -#include #include +#include +#include FT_FREETYPE_H + #include "IGUIEnvironment.h" #include "IGUIFont.h" -#include "ISceneManager.h" #include "IVideoDriver.h" #include "IrrlichtDevice.h" #include "SMesh.h" #include "util/enriched_string.h" #include "util/basic_macros.h" -#include FT_FREETYPE_H namespace irr { @@ -56,26 +56,22 @@ namespace gui { //! Constructor. SGUITTGlyph() : - isLoaded(false), glyph_page(0), source_rect(), offset(), advance(), - surface(0), - parent(0) + surface(0) {} DISABLE_CLASS_COPY(SGUITTGlyph); //! This class would be trivially copyable except for the reference count on `surface`. SGUITTGlyph(SGUITTGlyph &&other) noexcept : - isLoaded(other.isLoaded), glyph_page(other.glyph_page), source_rect(other.source_rect), offset(other.offset), advance(other.advance), - surface(other.surface), - parent(other.parent) + surface(other.surface) { other.surface = 0; } @@ -83,12 +79,17 @@ namespace gui //! Destructor. ~SGUITTGlyph() { unload(); } + //! If true, the glyph has been loaded. + inline bool isLoaded() const { + return source_rect != core::recti(); + } + //! Preload the glyph. //! The preload process occurs when the program tries to cache the glyph from FT_Library. //! However, it simply defines the SGUITTGlyph's properties and will only create the page //! textures if necessary. The actual creation of the textures should only occur right //! before the batch draw call. - void preload(u32 char_index, FT_Face face, video::IVideoDriver* driver, u32 font_size, const FT_Int32 loadFlags); + void preload(u32 char_index, FT_Face face, CGUITTFont *parent, u32 font_size, const FT_Int32 loadFlags); //! Unloads the glyph. void unload(); @@ -96,9 +97,6 @@ namespace gui //! Creates the IImage object from the FT_Bitmap. video::IImage* createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const; - //! If true, the glyph has been loaded. - bool isLoaded; - //! The page the glyph is on. u32 glyph_page; @@ -109,14 +107,11 @@ namespace gui core::vector2di offset; //! Glyph advance information. - FT_Vector advance; + core::vector2di advance; //! This is just the temporary image holder. After this glyph is paged, //! it will be dropped. mutable video::IImage* surface; - - //! The pointer pointing to the parent (CGUITTFont) - CGUITTFont* parent; }; //! Holds a sheet of glyphs. @@ -130,7 +125,8 @@ namespace gui { if (driver) driver->removeTexture(texture); - else texture->drop(); + else + texture->drop(); } } @@ -184,19 +180,11 @@ namespace gui for (u32 i = 0; i < glyph_to_be_paged.size(); ++i) { const SGUITTGlyph* glyph = glyph_to_be_paged[i]; - if (glyph && glyph->isLoaded) + if (glyph && glyph->surface) { - if (glyph->surface) - { - glyph->surface->copyTo(pageholder, glyph->source_rect.UpperLeftCorner); - glyph->surface->drop(); - glyph->surface = 0; - } - else - { - ; // TODO: add error message? - //currently, if we failed to create the image, just ignore this operation. - } + glyph->surface->copyTo(pageholder, glyph->source_rect.UpperLeftCorner); + glyph->surface->drop(); + glyph->surface = 0; } } @@ -238,77 +226,70 @@ namespace gui virtual ~CGUITTFont(); //! Sets the amount of glyphs to batch load. - virtual void setBatchLoadSize(u32 batch_size) { batch_load_size = batch_size; } + void setBatchLoadSize(u32 batch_size) { batch_load_size = batch_size; } //! Sets the maximum texture size for a page of glyphs. - virtual void setMaxPageTextureSize(const core::dimension2du& texture_size) { max_page_texture_size = texture_size; } + void setMaxPageTextureSize(const core::dimension2du& texture_size) { max_page_texture_size = texture_size; } //! Get the font size. - virtual u32 getFontSize() const { return size; } + u32 getFontSize() const { return size; } //! Check the font's transparency. - virtual bool isTransparent() const { return use_transparency; } + bool isTransparent() const { return use_transparency; } //! Check if the font auto-hinting is enabled. //! Auto-hinting is FreeType's built-in font hinting engine. - virtual bool useAutoHinting() const { return use_auto_hinting; } + bool useAutoHinting() const { return use_auto_hinting; } //! Check if the font hinting is enabled. - virtual bool useHinting() const { return use_hinting; } + bool useHinting() const { return use_hinting; } //! Check if the font is being loaded as a monochrome font. //! The font can either be a 256 color grayscale font, or a 2 color monochrome font. - virtual bool useMonochrome() const { return use_monochrome; } + bool useMonochrome() const { return use_monochrome; } //! Tells the font to allow transparency when rendering. //! Default: true. //! \param flag If true, the font draws using transparency. - virtual void setTransparency(const bool flag); + void setTransparency(const bool flag); //! Tells the font to use monochrome rendering. //! Default: false. //! \param flag If true, the font draws using a monochrome image. If false, the font uses a grayscale image. - virtual void setMonochrome(const bool flag); + void setMonochrome(const bool flag); //! Enables or disables font hinting. //! Default: Hinting and auto-hinting true. //! \param enable If false, font hinting is turned off. If true, font hinting is turned on. //! \param enable_auto_hinting If true, FreeType uses its own auto-hinting algorithm. If false, it tries to use the algorithm specified by the font. - virtual void setFontHinting(const bool enable, const bool enable_auto_hinting = true); + void setFontHinting(const bool enable, const bool enable_auto_hinting = true); //! Draws some text and clips it to the specified rectangle if wanted. virtual void draw(const core::stringw& text, const core::rect& position, video::SColor color, bool hcenter=false, bool vcenter=false, - const core::rect* clip=0); + const core::rect* clip=0) override; void draw(const EnrichedString& text, const core::rect& position, bool hcenter=false, bool vcenter=false, const core::rect* clip=0); - //! Returns the dimension of a character produced by this font. - virtual core::dimension2d getCharDimension(const wchar_t ch) const; - //! Returns the dimension of a text string. - virtual core::dimension2d getDimension(const wchar_t* text) const; + virtual core::dimension2du getDimension(const wchar_t* text) const override; //! Calculates the index of the character in the text which is on a specific position. - virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const; + virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const override; //! Sets global kerning width for the font. - virtual void setKerningWidth(s32 kerning); + virtual void setKerningWidth(s32 kerning) override; //! Sets global kerning height for the font. - virtual void setKerningHeight(s32 kerning); - - //! 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 char32_t thisLetter=0, const char32_t previousLetter=0) const; + virtual void setKerningHeight(s32 kerning) override; //! Returns the distance between letters - virtual s32 getKerningHeight() const; + virtual core::vector2di getKerning(const wchar_t thisLetter, const wchar_t previousLetter) const override; //! Define which characters should not be drawn by the font. - virtual void setInvisibleCharacters(const wchar_t *s); + virtual void setInvisibleCharacters(const wchar_t *s) override; //! Get the last glyph page if there's still available slots. //! If not, it will return zero. @@ -317,7 +298,7 @@ namespace gui //! Create a new glyph page texture. //! \param pixel_mode the pixel mode defined by FT_Pixel_Mode //should be better typed. fix later. - CGUITTGlyphPage* createGlyphPage(const u8& pixel_mode); + CGUITTGlyphPage* createGlyphPage(const u8 pixel_mode); //! Get the last glyph page's index. u32 getLastGlyphPageIndex() const { return Glyph_Pages.size() - 1; } @@ -328,16 +309,13 @@ 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 char32_t& ch); + 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. - virtual video::ITexture* getPageTextureByIndex(const u32& page_index) const; + video::ITexture* getPageTextureByIndex(const u32& page_index) const; - //! Add a list of scene nodes generated by putting font textures on the 3D planes. - virtual core::array addTextSceneNode - (const wchar_t* text, scene::ISceneManager* smgr, scene::ISceneNode* parent = 0, - const video::SColor& color = video::SColor(255, 0, 0, 0), bool center = false ); + inline video::IVideoDriver *getDriver() const { return Driver; } inline s32 getAscender() const { return font_metrics.ascender; } @@ -355,8 +333,6 @@ namespace gui static FT_Library c_library; static std::map c_faces; static bool c_libraryLoaded; - 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 *) @@ -379,20 +355,11 @@ namespace gui if (useMonochrome()) load_flags |= FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO; else load_flags |= FT_LOAD_TARGET_NORMAL; } - u32 getWidthFromCharacter(wchar_t c) const; u32 getWidthFromCharacter(char32_t c) const; - u32 getHeightFromCharacter(wchar_t c) const; u32 getHeightFromCharacter(char32_t c) const; - u32 getGlyphIndexByChar(wchar_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 char32_t thisLetter, const char32_t previousLetter) const; - core::dimension2d getDimensionUntilEndOfLine(const wchar_t* p) const; - void createSharedPlane(); - - irr::IrrlichtDevice* Device; - gui::IGUIEnvironment* Environment; video::IVideoDriver* Driver; io::path filename; FT_Face tt_face; diff --git a/src/irrlicht_changes/static_text.cpp b/src/irrlicht_changes/static_text.cpp index d06419e1f..e9be122b5 100644 --- a/src/irrlicht_changes/static_text.cpp +++ b/src/irrlicht_changes/static_text.cpp @@ -74,7 +74,7 @@ void StaticText::draw() updateText(); core::rect r = frameRect; - s32 height_line = font->getDimension(L"A").Height + font->getKerningHeight(); + s32 height_line = font->getDimension(L"A").Height + font->getKerning(L'A').Y; s32 height_total = height_line * BrokenText.size(); if (VAlign == EGUIA_CENTER && WordWrap) { @@ -546,7 +546,7 @@ s32 StaticText::getTextHeight() const return 0; if (WordWrap) { - s32 height = font->getDimension(L"A").Height + font->getKerningHeight(); + s32 height = font->getDimension(L"A").Height + font->getKerning(L'A').Y; return height * BrokenText.size(); } // There may be intentional new lines without WordWrap