標籤:blog 使用 os io for 2014 問題 ar
先吐個槽,剛準備發這條部落格的時候居然發現帳號被盜了,真是有人閑得蛋疼,順便贊一個csdn的客服,處理的很快。
好了,言歸正轉。看了一下,自動換行的實現在CCFreeType這個類裡,這個類的實現只是針對英文的,它採用空格斷句的方式來進行操作,一個word一個word的加,如果發現超過規定的範圍就會換行,但是對於中文來說,這個實現簡直弱爆了,所以就會出現不能自動換行的情況。參考它的實現,做一點小的修改,基本原理如下
1、讀一行文本出來,參考它的實現,算出這個文本的寬度
2、如果這個寬度沒有超過,則直接顯示
3、如果這個寬度走過了,則按等寬字型處理,根據寬度算出來總共應該是幾行,然後按長度進行分隔換行。
注意這個實現有幾個問題:
1、效能問題,其實是在計算出了所有的字之後才發現超過了,這個本來可以發現的更早,但是為了儘可能利用原有的代碼結構,只用先這樣了。
2、是以等寬字型的實現的,這個不一定正確,所以可能會出現某一些還是超過了的情況。
最後附上修改的diff,我使用的是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<TGlyph> 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<std::string> lines;- vector<std::string> 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<TGlyph>& glyphs, const std:: return error; } +FT_Error CCFreeTypeFont::initWordGlyphs(std::vector<TGlyph>& 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<TGlyph>& 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<TGlyph>& glyphs, const std::string& text, FT_Vector& pen);+ FT_Error CCFreeTypeFont::initWordGlyphs(std::vector<TGlyph>& glyphs, wchar_t* word, int size, FT_Vector& pen); void compute_bbox(std::vector<TGlyph>& 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();