diff --git a/src/framework/graphics/bitmapfont.cpp b/src/framework/graphics/bitmapfont.cpp index 21bd582e..6a6bea09 100644 --- a/src/framework/graphics/bitmapfont.cpp +++ b/src/framework/graphics/bitmapfont.cpp @@ -27,6 +27,14 @@ #include +namespace +{ + // for performance reasons we use statics vectors that are allocated on demand + CoordsBuffer s_coordsBuffer; + std::vector s_glyphsPositions(1); + std::vector s_lineWidths(1); +} + void BitmapFont::load(const OTMLNodePtr& fontNode) { OTMLNodePtr textureNode = fontNode->at("texture"); @@ -35,11 +43,12 @@ void BitmapFont::load(const OTMLNodePtr& fontNode) m_glyphHeight = fontNode->valueAt("height"); m_yOffset = fontNode->valueAt("y-offset", 0); m_firstGlyph = fontNode->valueAt("first-glyph", 32); - m_glyphSpacing = fontNode->valueAt("spacing", Size(0,0)); + m_glyphSpacing = fontNode->valueAt("spacing", Size(0, 0)); int spaceWidth = fontNode->valueAt("space-width", glyphSize.width()); // load font texture m_texture = g_textures.getTexture(textureFile); + Size textureSize = m_texture->getSize(); if(OTMLNodePtr node = fontNode->get("fixed-glyph-width")) { for(int glyph = m_firstGlyph; glyph < 256; ++glyph) @@ -68,7 +77,7 @@ void BitmapFont::load(const OTMLNodePtr& fontNode) // calculate glyphs texture coords - int numHorizontalGlyphs = m_texture->getSize().width() / glyphSize.width(); + int numHorizontalGlyphs = textureSize.width() / glyphSize.width(); for(int glyph = m_firstGlyph; glyph < 256; ++glyph) { m_glyphsTextureCoords[glyph].setRect(((glyph - m_firstGlyph) % numHorizontalGlyphs) * glyphSize.width(), ((glyph - m_firstGlyph) / numHorizontalGlyphs) * glyphSize.height(), @@ -86,11 +95,9 @@ void BitmapFont::drawText(const std::string& text, const Point& startPos) void BitmapFont::drawText(const std::string& text, const Rect& screenCoords, Fw::AlignmentFlag align) { - static CoordsBuffer coordsBuffer; - coordsBuffer.clear(); - - calculateDrawTextCoords(coordsBuffer, text, screenCoords, align); - g_painter->drawTextureCoords(coordsBuffer, m_texture); + s_coordsBuffer.clear(); + calculateDrawTextCoords(s_coordsBuffer, text, screenCoords, align); + g_painter->drawTextureCoords(s_coordsBuffer, m_texture); } void BitmapFont::calculateDrawTextCoords(CoordsBuffer& coordsBuffer, const std::string& text, const Rect& screenCoords, Fw::AlignmentFlag align) @@ -103,7 +110,7 @@ void BitmapFont::calculateDrawTextCoords(CoordsBuffer& coordsBuffer, const std:: // map glyphs positions Size textBoxSize; - const std::vector& glyphsPositions = calculateGlyphsPositions(text, align, &textBoxSize); + const auto& glyphsPositions = calculateGlyphsPositions(text, align, &textBoxSize); for(int i = 0; i < textLenght; ++i) { int glyph = (uchar)text[i]; @@ -171,52 +178,49 @@ void BitmapFont::calculateDrawTextCoords(CoordsBuffer& coordsBuffer, const std:: const std::vector& BitmapFont::calculateGlyphsPositions(const std::string& text, Fw::AlignmentFlag align, - Size *textBoxSize) + Size* textBoxSize) { - // for performance reasons we use statics vectors that are allocated on demand - static std::vector glyphsPositions(1); - static std::vector lineWidths(1); - int textLength = text.length(); int maxLineWidth = 0; int lines = 0; int glyph; - int i; // return if there is no text if(textLength == 0) { if(textBoxSize) - textBoxSize->resize(0,m_glyphHeight); - return glyphsPositions; + textBoxSize->resize(0, m_glyphHeight); + return s_glyphsPositions; } - // resize glyphsPositions vector when needed - if(textLength > (int)glyphsPositions.size()) - glyphsPositions.resize(textLength); + // resize s_glyphsPositions vector when needed + if(textLength > (int)s_glyphsPositions.size()) + s_glyphsPositions.resize(textLength); // calculate lines width if((align & Fw::AlignRight || align & Fw::AlignHorizontalCenter) || textBoxSize) { - lineWidths[0] = 0; - for(i = 0; i< textLength; ++i) { + s_lineWidths[0] = 0; + for(int i = 0; i < textLength; ++i) { glyph = (uchar)text[i]; if(glyph == (uchar)'\n') { lines++; - if(lines+1 > (int)lineWidths.size()) - lineWidths.resize(lines+1); - lineWidths[lines] = 0; + // resize s_lineWidths vector when needed + if(lines+1 > (int)s_lineWidths.size()) + s_lineWidths.resize(lines+1); + s_lineWidths[lines] = 0; } else if(glyph >= 32) { - lineWidths[lines] += m_glyphsSize[glyph].width() ; - if((i+1 != textLength && text[i+1] != '\n')) // only add space if letter is not the last or before a \n. - lineWidths[lines] += m_glyphSpacing.width(); - maxLineWidth = std::max(maxLineWidth, lineWidths[lines]); + s_lineWidths[lines] += m_glyphsSize[glyph].width(); + // only add space if letter is not the last or before a \n + if((i+1 != textLength && text[i+1] != '\n')) + s_lineWidths[lines] += m_glyphSpacing.width(); + maxLineWidth = std::max(maxLineWidth, s_lineWidths[lines]); } } } Point virtualPos(0, m_yOffset); lines = 0; - for(i = 0; i < textLength; ++i) { + for(int i = 0; i < textLength; ++i) { glyph = (uchar)text[i]; // new line or first glyph @@ -228,16 +232,16 @@ const std::vector& BitmapFont::calculateGlyphsPositions(const std::string // calculate start x pos if(align & Fw::AlignRight) { - virtualPos.x = (maxLineWidth - lineWidths[lines]); + virtualPos.x = (maxLineWidth - s_lineWidths[lines]); } else if(align & Fw::AlignHorizontalCenter) { - virtualPos.x = (maxLineWidth - lineWidths[lines]) / 2; + virtualPos.x = (maxLineWidth - s_lineWidths[lines]) / 2; } else { // AlignLeft virtualPos.x = 0; } } // store current glyph topLeft - glyphsPositions[i] = virtualPos; + s_glyphsPositions[i] = virtualPos; // render only if the glyph is valid if(glyph >= 32 && glyph != (uchar)'\n') { @@ -250,7 +254,7 @@ const std::vector& BitmapFont::calculateGlyphsPositions(const std::string textBoxSize->setHeight(virtualPos.y + m_glyphHeight); } - return glyphsPositions; + return s_glyphsPositions; } Size BitmapFont::calculateTextRectSize(const std::string& text) @@ -265,11 +269,12 @@ void BitmapFont::calculateGlyphsWidthsAutomatically(const ImagePtr& image, const if(!image) return; - int numHorizontalGlyphs = image->getSize().width() / glyphSize.width(); - auto texturePixels = image->getPixels(); + Size imageSize = image->getSize(); + int numHorizontalGlyphs = imageSize.width() / glyphSize.width(); + const auto& texturePixels = image->getPixels(); // small AI to auto calculate pixels widths - for(int glyph = m_firstGlyph; glyph< 256; ++glyph) { + for(int glyph = m_firstGlyph; glyph < 256; ++glyph) { Rect glyphCoords(((glyph - m_firstGlyph) % numHorizontalGlyphs) * glyphSize.width(), ((glyph - m_firstGlyph) / numHorizontalGlyphs) * glyphSize.height(), glyphSize.width(), @@ -279,7 +284,7 @@ void BitmapFont::calculateGlyphsWidthsAutomatically(const ImagePtr& image, const int filledPixels = 0; // check if all vertical pixels are alpha for(int y = glyphCoords.top(); y <= glyphCoords.bottom(); ++y) { - if(texturePixels[(y * image->getSize().width() * 4) + (x*4) + 3] != 0) + if(texturePixels[(y * imageSize.width() * 4) + (x*4) + 3] != 0) filledPixels++; } if(filledPixels > 0) @@ -293,51 +298,54 @@ void BitmapFont::calculateGlyphsWidthsAutomatically(const ImagePtr& image, const std::string BitmapFont::wrapText(const std::string& text, int maxWidth) { std::string outText; - std::string line; std::vector words; std::vector wordsSplit = stdext::split(text); // break huge words into small ones - for(const auto &word: wordsSplit) { + for(const auto& word: wordsSplit) { int wordWidth = calculateTextRectSize(word).width(); if(wordWidth > maxWidth) { std::string newWord; - for(uint j=0;j maxWidth) { - newWord += "-"; + newWord += '-'; words.push_back(newWord); - newWord = ""; + newWord.clear(); } newWord += word[j]; } words.push_back(newWord); - } else + } else { words.push_back(word); + } } // compose lines - for(const auto &word: words) { - std::string candidate = line + word; - int candidateWidth = calculateTextRectSize(candidate).width(); + std::string line(words[0]); + for(ulong i = 1; i < words.size(); ++i) + { + const auto& word = words[i]; - if(candidateWidth > maxWidth) { - if(!line.empty()) - outText += line.substr(0, line.length()-1) + "\n"; - line = ""; + line.push_back(' '); + ulong lineSize = line.size(); + line.append(word); + + if(calculateTextRectSize(line).width() > maxWidth) + { + line.resize(lineSize); + line.back() = '\n'; + outText.append(line); + line.assign(word); } - - line += word + " "; } - - outText += line; - outText = outText.substr(0, outText.length()-1); + outText.append(line); return outText; } diff --git a/src/framework/graphics/bitmapfont.h b/src/framework/graphics/bitmapfont.h index 1ac2c517..d4860b78 100644 --- a/src/framework/graphics/bitmapfont.h +++ b/src/framework/graphics/bitmapfont.h @@ -55,7 +55,7 @@ public: std::string wrapText(const std::string& text, int maxWidth); - std::string getName() { return m_name; } + const std::string& getName() { return m_name; } int getGlyphHeight() { return m_glyphHeight; } const Rect* getGlyphsTextureCoords() { return m_glyphsTextureCoords; } const Size* getGlyphsSize() { return m_glyphsSize; } @@ -79,4 +79,3 @@ private: #endif - diff --git a/src/framework/stdext/string.cpp b/src/framework/stdext/string.cpp index dd80d383..32b8c3b8 100644 --- a/src/framework/stdext/string.cpp +++ b/src/framework/stdext/string.cpp @@ -50,18 +50,16 @@ std::string date_time_string(const char* format/* = "%b %d %Y %H:%M:%S"*/) char date[100]; std::time_t tnow; std::time(&tnow); - std::tm *ts = std::localtime(&tnow); + std::tm* ts = std::localtime(&tnow); std::strftime(date, 100, format, ts); return std::string(date); } std::string dec_to_hex(uint64_t num) { - std::string str; std::ostringstream o; o << std::hex << num; - str = o.str(); - return str; + return o.str(); } uint64_t hex_to_dec(const std::string& str) @@ -74,7 +72,7 @@ uint64_t hex_to_dec(const std::string& str) bool is_valid_utf8(const std::string& src) { - const unsigned char *bytes = (const unsigned char *)src.c_str(); + const unsigned char* bytes = (const unsigned char*)src.c_str(); while(*bytes) { if( (// ASCII // use bytes[0] <= 0x7F to allow ASCII control characters @@ -146,7 +144,7 @@ bool is_valid_utf8(const std::string& src) std::string utf8_to_latin1(const std::string& src) { std::string out; - for(uint i=0;i= 32 && c < 128) || c == 0x0d || c == 0x0a || c == 0x09) out += c; @@ -273,7 +271,7 @@ void replace_all(std::string& str, const std::string& search, const std::string& std::vector split(const std::string& str, const std::string& separators) { std::vector splitted; - boost::split(splitted, str, boost::is_any_of(std::string(separators))); + boost::split(splitted, str, boost::is_any_of(separators)); return splitted; } diff --git a/src/framework/stdext/string.h b/src/framework/stdext/string.h index 8262de9f..88dc7f4d 100644 --- a/src/framework/stdext/string.h +++ b/src/framework/stdext/string.h @@ -63,11 +63,12 @@ std::string utf16_to_latin1(const std::wstring& src); std::wstring latin1_to_utf16(const std::string& src); #endif +// always returns at least one element in vector std::vector split(const std::string& str, const std::string& separators = " "); template std::vector split(const std::string& str, const std::string& separators = " ") { std::vector splitted = split(str, separators); std::vector results(splitted.size()); - for(uint i=0;i(splitted[i]); return results; } diff --git a/src/framework/ui/uitextedit.cpp b/src/framework/ui/uitextedit.cpp index 78969a7f..fa6501c2 100644 --- a/src/framework/ui/uitextedit.cpp +++ b/src/framework/ui/uitextedit.cpp @@ -142,9 +142,9 @@ void UITextEdit::update(bool focusCursor) // map glyphs positions Size textBoxSize; - const std::vector& glyphsPositions = m_font->calculateGlyphsPositions(text, m_textAlign, &textBoxSize); - const Rect *glyphsTextureCoords = m_font->getGlyphsTextureCoords(); - const Size *glyphsSize = m_font->getGlyphsSize(); + const auto& glyphsPositions = m_font->calculateGlyphsPositions(text, m_textAlign, &textBoxSize); + const Rect* glyphsTextureCoords = m_font->getGlyphsTextureCoords(); + const Size* glyphsSize = m_font->getGlyphsSize(); int glyph; // update rect size diff --git a/src/framework/ui/uitextedit.h b/src/framework/ui/uitextedit.h index d091731e..aafd8f9a 100644 --- a/src/framework/ui/uitextedit.h +++ b/src/framework/ui/uitextedit.h @@ -42,7 +42,7 @@ public: void setCursorVisible(bool enable) { m_cursorVisible = enable; } void setChangeCursorImage(bool enable) { m_changeCursorImage = enable; } void setTextHidden(bool hidden); - void setValidCharacters(const std::string validCharacters) { m_validCharacters = validCharacters; } + void setValidCharacters(const std::string& validCharacters) { m_validCharacters = validCharacters; } void setShiftNavigation(bool enable) { m_shiftNavigation = enable; } void setMultiline(bool enable) { m_multiline = enable; } void setMaxLength(uint maxLength) { m_maxLength = maxLength; }