cocos2dx RichText关于字符串截取的bug

cocos2dx RichText关于字符串截取的bug,第1张

概述cocos2dx 3.3rc版本中 RichText类 当自定义了RichText的宽度, 对于字符串截取有问题,如果中文和英文数字混合的时候,会导致  要么 一行还有位置 就换行了,要么 显示不全。 看了下RichText实现, 重点是handlerTextRenderer方法 void RichText::handleTextRenderer(const std::string& text,

cocos2dx 3.3rc版本中 RichText类 当自定义了RichText的宽度, 对于字符串的截取有问题,如果中文和英文数字混合的时候,会导致 要么 一行还有位置 就换行了,要么 显示不全。 看了下RichText实现,

重点是handlerTextRenderer方法

voID RichText::handleTextRenderer(const std::string& text,const std::string& Fontname,float FontSize,const color3B &color,glubyte opacity){    auto fileExist = fileUtils::getInstance()->isfileExist(Fontname);    Label* textRenderer = nullptr;    if (fileExist)    {        textRenderer = Label::createWithTTF(text,Fontname,FontSize);    }else if(fileUtils::getInstance()->isfileExist(Label::getCustomFont())){		textRenderer = Label::createWithTTF(text,Label::getCustomFont(),FontSize);	}     else    {        textRenderer = Label::createWithSystemFont(text,FontSize);    }    float textRendererWIDth = textRenderer->getContentSize().wIDth;    _leftSpaceWIDth -= textRendererWIDth;    if (_leftSpaceWIDth < 0.0f)    {        <span >float overstepPercent = (-_leftSpaceWIDth) / textRendererWIDth;        std::string curText = text;        size_t stringLength = StringUtils::getCharacterCountInUTF8String(text);        int leftLength = stringLength * (1.0f - overstepPercent);</span>        std::string leftWords = Helper::getSubStringOfUTF8String(curText,leftLength);        std::string cutWords = Helper::getSubStringOfUTF8String(curText,leftLength,stringLength - leftLength);        if (leftLength > 0)        {            Label* leftRenderer = nullptr;            if (fileExist)            {                leftRenderer = Label::createWithTTF(Helper::getSubStringOfUTF8String(leftWords,leftLength),FontSize);            }	    else if (fileUtils::getInstance()->isfileExist(Label::getCustomFont()))	    {		leftRenderer = Label::createWithTTF(Helper::getSubStringOfUTF8String(leftWords,FontSize);	    }            else             {                leftRenderer = Label::createWithSystemFont(Helper::getSubStringOfUTF8String(leftWords,FontSize);            }            if (leftRenderer)            {                leftRenderer->setcolor(color);                leftRenderer->setopacity(opacity);                pushToContainer(leftRenderer);            }        }        addNewline();        handleTextRenderer(cutWords.c_str(),FontSize,color,opacity);    }    else    {        textRenderer->setcolor(color);        textRenderer->setopacity(opacity);        pushToContainer(textRenderer);    }}
关键是标红的那几句代码: 他是用 当前行空余宽度 除以 文字纹理的长度得出的百分比 再乘以字符串长度得出字符个数,除出来的float值 用int 接收,直接丢弃掉小数部分,看似没有问题。实际上, 用百分比乘出来的宽度默认 认为 所有字符的宽度都是一样的, 所以当英文 数字混合的时候 就会导致 还有空余放的下 英文, 它却直接换行了。

还有个问题,就是 int 去接收 float类型的数据 可能导致浮点误差 比如 我 空余宽度除以文字纹理长度得出的百分比是 0.215054,文字字符个数是93, 我摁计算器算出来的都是20.000022, 用int 接收应该是20, 但是这里的出来的结果竟然是19??? 让人莫名其妙。 实际上 我知道 这是 类型运算的转换 可能导致的浮点误差 导致的。但是也没有理解到底问题在哪里。

起初想到的是 Label 指定了Label的宽度的时候,Label纹理宽度超过了指定宽度的时候 它也有自动换行的 *** 作,但是看了Label的实现,觉得Label 写的可读性太差了,很难看懂呀。我看到 Label对 字符位置的更新是在 alignText这个方法里, 有个Labeltextformatter:createStringSprite 的静态方法。

  Labeltextformatter::createStringSprites(this);        if(_maxlinewidth > 0 && _contentSize.wIDth > _maxlinewidth && Labeltextformatter::multilineText(this) )              Labeltextformatter::createStringSprites(this);    if(_labelWIDth > 0 || (_currNumlines > 1 && _hAlignment != TextHAlignment::left))        Labeltextformatter::alignText(this);
看着就让人好费解, 先调用一次createStringSprites 判断条件 再调用一次。不知道它想干啥?
在createStringSprites中, 将字符串 创建出字符纹理,设置好坐标等, 但是 Labeltextformatter::multilineText 这个方法看了几遍 愣是不知道它想干啥?


好, 回到 RichText。

其实 关键是要得到 leftLength这个 精确数值, 通过这个数值确定最终截取位置。

为了解决这个问题 看了下Label的实现, 无论是UIText 还是LabelTTF 最终渲染的 都是Label, Label 有 getLetter 这个接口,就可以 通过文字纹理拿到 当前的字符 ,从而拿到 当前字符的位置,然后再做精细调整。

最终结果就是:

 if (_leftSpaceWIDth < 0.0f) {        float overstepPercent = (-_leftSpaceWIDth) / textRendererWIDth;        std::string curText = text;        size_t stringLength = StringUtils::getCharacterCountInUTF8String(text);        int leftLength = stringLength * (1.0f - overstepPercent);	Sprite *letter =textRenderer->getLetter( leftLength );	float pos_left_x_  = letter->getpositionX() -  letter->getContentSize().wIDth/2;	float pos_right_x_ = letter->getpositionX() + letter->getContentSize().wIDth/2;	while( pos_left_x_ < _leftSpaceWIDth+textRendererWIDth ) {		leftLength = leftLength + 1;		letter =textRenderer->getLetter( leftLength );		if ( letter == NulL ){			break;		}	        pos_left_x_  = letter->getpositionX() +  letter->getContentSize().wIDth/2;	}			while( pos_right_x_ > _leftSpaceWIDth+textRendererWIDth ){		leftLength = leftLength - 1;		letter =textRenderer->getLetter( leftLength );		if ( letter == NulL ){		    break;		}		pos_right_x_ = letter->getpositionX() + letter->getContentSize().wIDth/2;	}        std::string leftWords = Helper::getSubStringOfUTF8String(curText,FontSize);            }            if (leftRenderer)            {                leftRenderer->setcolor(color);                leftRenderer->setopacity(opacity);                pushToContainer(leftRenderer);            }        }
问题解决。 如果谁有更好的方案,求分享。 总结

以上是内存溢出为你收集整理的cocos2dx RichText关于字符串截取的bug全部内容,希望文章能够帮你解决cocos2dx RichText关于字符串截取的bug所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1045416.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存