Implementation of CCLabelTTF automatic line feed on cocos2dx windows phone platform
Let's talk about it first. When I was about to send this blog, I found that my account was stolen. It was really a waste of time. By the way, I liked a csdn customer service and handled it very quickly.
All right. After reading it, the implementation of automatic line feed is in the CCFreeType class. The implementation of this class is only for English. It uses space-separated sentences for operations, and adds a word to a word, if a line break is found to exceed the specified range, but for Chinese, this implementation is almost weak, so there will be a situation where the line break cannot be automatically entered. Refer to its implementation and make minor modifications. The basic principles are as follows:
1. Read a line of text and calculate the width of the text based on its implementation.
2. If the width is not exceeded
3. If the width has passed, the font size is equal to the width. The total number of rows is calculated based on the width, and the line feed is separated by length.
Note:
1. performance problems are discovered only after all words are computed. This can be found earlier, but in order to make full use of the original code structure, this is the only option.
2. It is implemented with an equal-width font. This is not necessarily correct, so some situations may still exceed.
The modified diff is attached. I use version 2.2.4.
diff --git a/cocos2d-x-2.2.4/cocos2dx/platform/winrt/CCFreeTypeFont.cpp b/cocos2d-x-2.2.4/cocos2dx/platform/winrt/CCFreeTypeFont.cppindex 9886d0a..46489af 100644--- a/cocos2d-x-2.2.4/cocos2dx/platform/winrt/CCFreeTypeFont.cpp+++ b/cocos2d-x-2.2.4/cocos2dx/platform/winrt/CCFreeTypeFont.cpp@@ -368,13 +368,67 @@ FT_Error CCFreeTypeFont::addWord(const std::string& word) return error; } +FT_Error CCFreeTypeFont::addLine(wchar_t* line, int size, bool wrap)+{+ std::vector
glyphs; // glyphs for the word+ FT_BBox bbox; // bounding box containing all of the glyphs in the word+ int maxWidth = m_inWidth ? m_inWidth : m_windowWidth;++ FT_Vector pen = m_currentLine->pen;+ FT_Error error = initWordGlyphs(glyphs, line, size, pen);+ if (!error)+ {+ compute_bbox(glyphs, &bbox);+ if (!wrap || bbox.xMax <= maxWidth)+ {+ m_currentLine->pen = pen;+ m_currentLine->glyphs.insert(m_currentLine->glyphs.end(), glyphs.begin(), glyphs.end());+ if (m_currentLine->width == 0)+ {+ m_currentLine->bbox = bbox;+ }+ else+ {+ m_currentLine->bbox.xMax = bbox.xMax;+ }+ m_currentLine->width = m_currentLine->bbox.xMax - m_currentLine->bbox.xMin;+ }+ else+ {+ int width = bbox.xMax;+ int lines = width / maxWidth + 1;+ float fline = float(width) / float(maxWidth);+ int lineWidth = int(size / fline);+ int offset = 0;+ for (int i = 0; i < lines; i++)+ {+ if (i)+ {+ newLine();+ }+ wchar_t* buffer = line + offset;+ int buffer_len = size - offset;+ if (buffer_len > lineWidth)+ {+ buffer_len = lineWidth;+ }+ offset += buffer_len;+ addLine(buffer, buffer_len, false);+ if (i < lines - 1)+ {+ endLine();+ }+ }+ }+ }+ return error;+}+ FT_Error CCFreeTypeFont::initGlyphs(const char* text) { FT_Error error = 0; std::stringstream stringStream(text); std::string line;- vector
lines;- vector
words; m_textWidth = 0; m_textHeight = 0;@@ -387,19 +441,21 @@ FT_Error CCFreeTypeFont::initGlyphs(const char* text) { newLine(); - std::size_t prev = 0, pos;- while ((pos = line.find_first_of(" ", prev)) != std::string::npos)- {- if (pos > prev)- {- addWord(line.substr(prev, pos-prev));- }- prev = pos + 1;- }- if (prev < line.length())- {- addWord(line.substr(prev, std::string::npos));- }+ wchar_t * pwszBuffer = nullptr;++ int num_chars = line.size();+ int nBufLen = num_chars + 1;+ pwszBuffer = new wchar_t[nBufLen];+ if (!pwszBuffer)+ {+ return -1;+ }++ memset(pwszBuffer, 0, nBufLen);+ num_chars = MultiByteToWideChar(CP_UTF8, 0, line.c_str(), num_chars, pwszBuffer, nBufLen);+ pwszBuffer[num_chars] = '\0';+ error = addLine(pwszBuffer, num_chars, true);+ CC_SAFE_DELETE_ARRAY(pwszBuffer); endLine(); } @@ -513,6 +569,64 @@ FT_Error CCFreeTypeFont::initWordGlyphs(std::vector
& glyphs, const std:: return error; } +FT_Error CCFreeTypeFont::initWordGlyphs(std::vector
& glyphs, wchar_t* word, int size, FT_Vector& pen)+{+ FT_GlyphSlot slot = m_face->glyph;+ FT_UInt glyph_index;+ FT_UInt previous = 0;+ FT_Error error = 0;+ PGlyph glyph;+ unsigned int numGlyphs = 0;++ glyphs.clear();+ glyphs.resize(size);+ FT_Bool useKerning = FT_HAS_KERNING(m_face);++ for (int n = 0; n < size; n++)+ {+ glyph = &glyphs[numGlyphs];++ /* convert character code to glyph index */+ FT_ULong c = word[n];+ glyph_index = FT_Get_Char_Index(m_face, c);++ if (useKerning && previous && glyph_index)+ {+ FT_Vector delta;+ FT_Get_Kerning(m_face, previous, glyph_index,+ FT_KERNING_DEFAULT, &delta);+ pen.x += delta.x >> 6;+ }++ /* store current pen position */+ glyph->pos = pen;+ glyph->index = glyph_index;++ /* load glyph image into the slot without rendering */+ error = FT_Load_Glyph(m_face, glyph_index, FT_LOAD_DEFAULT);+ if (error)+ continue; /* ignore errors, jump to next glyph */++ /* extract glyph image and store it in our table */+ error = FT_Get_Glyph(m_face->glyph, &glyph->image);+ if (error)+ continue; /* ignore errors, jump to next glyph */++ /* translate the glyph image now */+ FT_Glyph_Transform(glyph->image, 0, &glyph->pos);++ /* increment pen position */+ pen.x += slot->advance.x >> 6;++ /* record current glyph index */+ previous = glyph_index;++ numGlyphs++;+ }++ return error;+}+ void CCFreeTypeFont::compute_bbox(std::vector
& glyphs, FT_BBox *abbox) { FT_BBox bbox;diff --git a/cocos2d-x-2.2.4/cocos2dx/platform/winrt/CCFreeTypeFont.h b/cocos2d-x-2.2.4/cocos2dx/platform/winrt/CCFreeTypeFont.hindex 4c1cc3e..a325071 100644--- a/cocos2d-x-2.2.4/cocos2dx/platform/winrt/CCFreeTypeFont.h+++ b/cocos2d-x-2.2.4/cocos2dx/platform/winrt/CCFreeTypeFont.h@@ -100,6 +100,7 @@ private: FT_Error CCFreeTypeFont::initGlyphs(const char* text); FT_Error CCFreeTypeFont::initWordGlyphs(std::vector
& glyphs, const std::string& text, FT_Vector& pen);+ FT_Error CCFreeTypeFont::initWordGlyphs(std::vector
& glyphs, wchar_t* word, int size, FT_Vector& pen); void compute_bbox(std::vector
& glyphs, FT_BBox *abbox); @@ -114,6 +115,7 @@ private: FT_Vector getPenForAlignment(FTLineInfo* pInfo, CCImage::ETextAlign eAlignMask, int lineNumber, int totalLines); FT_Error addWord(const std::string& word);+ FT_Error addLine(wchar_t* line, int size, bool wrap); void newLine(); void endLine();