cocos2dx windows phone平台下CCLabelTTF自动换行的实现

先吐个槽,刚准备发这条博客的时候居然发现账号被盗了,真是有人闲得蛋疼,顺便赞一个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.cpp
index 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.h
index 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();

cocos2dx windows phone平台下CCLabelTTF自动换行的实现

时间: 2024-10-11 07:11:36

cocos2dx windows phone平台下CCLabelTTF自动换行的实现的相关文章

cocos2dx windows phone平台下CCLabelTTF自动换行的实现(2)

前几天发过一篇文章说如何实现wp8下的CCLabelTTF如何自动换行,后来发现果如预料的那般,效果很不好,主要是非等宽字体的情况下看着很糟心,因此再修改了一版,效果要好很多了. 具体实现其实就是参考initGlyphs,但是会不断的检查是否超过宽度,如果超过则自动换行. 具体的直接看代码就明白了 /**************************************************************************** Copyright (c) 2010 coc

cocos2dx windows phone平台下CCLabelTTF自己主动换行的实现(2)

前几天发过一篇文章说怎样实现wp8下的CCLabelTTF怎样自己主动换行,后来发现果如预料的那般.效果非常不好.主要是非等宽字体的情况下看着非常糟心.因此再改动了一版.效果要好非常多了. 详细实现事实上就是參考initGlyphs,可是会不断的检查是否超过宽度.假设超过则自己主动换行. 详细的直接看代码就明确了 /**************************************************************************** Copyright (c)

在Windows 10平台下的MySQL-5.7.15-winx64安装

白发渔樵江渚上,惯看秋月春风. 一壶浊酒喜相逢,古今多少事,都付笑谈中. --<临江仙> 一.下载 1.在官网上下载MySQL对应的版本:https://downloads.mysql.com/archives/community/ 2.下载完成解压到指定路径: 二.配置MySQL 在mysql-5.7.15-winx64目录下,复制my-default.ini命名为my.ini. 配置my.ini文件 [mysql] # 设置mysql客户端默认字符集 default-character-s

windows平台下的oracle ORA-01031的解决方法

今天下午遇到一个很怪异的问题,在windows平台下sqlplus  / as sysdba登陆数据库,提示权限不足, 当时就纳闷了,sys用户登陆数据库还能权限不足,问题出现了,就开始寻找解决方法呗 首先查看$ORACLE_HOME/network/admin/sqlnet.ora中SQLNET.AUTHENTICATION_SERVICES项的配置信息, 网上的大多数帖子一致结论为: 在windows平台上,SQLNET.AUTHENTICATION_SERVICES必须设置为NTS或者AL

Windows平台下Oracle监听服务启动过程中日志输出

Windows平台下Oracle监听服务启动过程中日志输出记录. 日志目录:D:\app\Administrator\diag\tnslsnr\WIN-RU03CB21QGA\listener\trace\listener.log 日志输出内容: Sat Aug 06 20:38:44 2016 系统参数文件为D:\app\Administrator\product\11.2.0\dbhome_1\network\admin\listener.ora 写入d:\app\administrator

Windows平台下Oracle实例启动过程中日志输出

Windows平台下Oracle实例启动过程中日志输出记录. 路径:D:\app\Administrator\diag\rdbms\orcl\orcl\trace\alert_orcl.log 输出内容: Sat Aug 06 20:39:55 2016 Starting ORACLE instance (normal) LICENSE_MAX_SESSION = 0 LICENSE_SESSIONS_WARNING = 0 Picked latch-free SCN scheme 3 Usin

wchar_t内置还是别名(wchar_t在windows下是16整数的别名,在linux等平台下是32位整数的别名。MSVC2008开始默认是/Zc:wchar_t)

接前一篇C++ ABI之名字改编(以Qt为例),继续看看C++名字改编相关的问题. 问题 MSVC 有一对选项/Zc:wchar_t- 与 /Zc:wchar_t控制wchar_t 于是 wchar_t 可以是 unsigned short 或 __wchar_t(称为原生类型?) 的别名 两个东西混用会怎么样? 首先考虑,会混用么?,是杞人忧天么? 由于 Qt 为 MSVC 提供的二进制包采用的前者/Zc:wchar_t-.考虑: 如果你编译自己的Qt程序时,启用了后者,会怎么样? 如果Qt程

Windows 平台下Git 服务器搭建

由于项目中一直在使用git作为版本管理,自己对git的理解.使用都还不是怎么的熟悉,所以准备深入了解一下git及一些常用命令的使用,于是干脆把服务端架上,通过自己的PC作为服务端同时作为客户端的角色进行折腾了...本文主要介绍在Windows平台下Git服务器的搭建,如下: 一:下载java,地址:http://www.java.com/zh_CN/ 二:安装Java.安装步骤不再详述. 三:配置Java环境变量. 右键 计算机->属性->高级系统设置->高级->环境变量->

Windows平台下Git服务器搭建

该文章转自:http://www.codeceo.com/article/windows-git-server.html 第一步:下载Java,下载地址:http://www.java.com/zh_CN/ 第二步:安装Java.安装步骤不再详述. 第三步:配置Java环境变量. 右键”计算机” => ”属性” => ”高级系统设置” => ”高级” => “环境变量” => “系统变量”. 新建: 变量名:JAVA_HOME 变量值:D:\Program Files (x8