给BGE加上了富文本显示功能
相关代码如下:
void GLTextRenderer::render(const Color& color,const String& string,const FloatRect& area,bool isMultiLine,
Horizontal hAlignment,Vertical vAlignment,bool rich)
{
if(typeFace_ != 0 && !rich)
{
typeFace_->setColor(color);
if(isMultiLine)
{
renderMultiline(color,string,area,hAlignment);
}
else
{
Vector2f position(typeFace_->penX(string,area,hAlignment),baseLineY(area,vAlignment));
typeFace_->render(string,position);
}
}
else if(typeFace_)
{
if(!isMultiLine)
{
auto cmdlist = parseString(string);
Vector2f position(typeFace_->penX(string,area,hAlignment),baseLineY(area,vAlignment));
typeFace_->render(String(),position,cmdlist);
}
else
{
auto cmdlist = parseString(string);
renderMultiline(color,cmdlist,area,hAlignment);
}
}
}
这里的parseString用于解析类似html的问题
函数实现如下:
std::list<textRenderCmdUnit> TextRenderer::parseString(const String& content)
{
String text(content);
std::list<textRenderCmdUnit> cmdList;
String current;
auto list = text.split('<');
for(int i=0;i<list.size();i++)
{
current = list[i];
if(current.startWith(L"/>"))
{
textRenderCmdUnit unit;
unit.undo = true;
cmdList.push_back(unit);
String remain = current.substr(2);
if(!remain.empty())
{
unit.text = remain;
unit.undo = false;
cmdList.push_back(unit);
}
}
else if(current.find('>') != String::InvalidPos)
{
textRenderCmdUnit unit;
unit.tag = current.substr(0,current.find('>'));
unit.undo = false;
cmdList.push_back(unit);
int32_t find = current.find('>');
if(find < current.size()-1)
{
unit.tag.clear();
unit.text = current.substr(find+1);
cmdList.push_back(unit);
}
}
else
{
textRenderCmdUnit unit;
unit.text = current;
unit.undo = false;
cmdList.push_back(unit);
}
}
return cmdList;
}
以下用于渲染富文本
void TypeFace::render(const FloatRect& area,const std::list<textRenderCmdUnit>& queue,Horizontal hAlignment,float vpos)
{
const float availableWidth = area.width_ - 2.0f;
textRenderCmdUnit unit;
String line,lineRemain;
String tag;
std::queue<String> cmdStack;
float y = vpos;
float x = penX(String(),area,hAlignment);
auto itr = queue.begin();
while(itr != queue.end())
{
unit = *itr;
if(unit.undo)
{
if(!cmdStack.empty())
{
tag = cmdStack.front();
cmdStack.pop();
if(tag == "bold")
bold_ = false;
else if(tag == "italic")
italic_ = false;
else if(tag == "underline")
underline_ = false;
else
applyColor(tag);
}
}
else if(!unit.tag.empty())
{
tag = unit.tag;
cmdStack.push(tag);
if(tag == "bold")
bold_ = true;
else if(tag == "italic")
italic_ = true;
else if(tag == "underline")
underline_ = true;
else
applyColor(tag);
}
else
{
line += unit.text;
while(true)
{
size_t pos = hitCharacterIndex(line,availableWidth-x);
if(pos == 0)
{
x = penX(String(),area,hAlignment);
y += lineHeight();
continue;
}
if(pos == String::InvalidPos)
pos = line.size();
String current = line.substr(0,pos);
lineRemain = line.substr(pos);
line = current;
auto linefeed = line.get().find_first_of('\n');
if(linefeed != std::basic_string<uint32_t>::npos)
{
line = line.substr(0,linefeed);
lineRemain = line.substr(linefeed+1) + lineRemain;
}
render(line,Vector2f(x,y),std::list<textRenderCmdUnit>());
x += width(line);
if(linefeed != String::InvalidPos)
{
x = penX(String(),area,hAlignment);
y += lineHeight();
}
line = lineRemain;
if(lineRemain.empty())
break;
}
}
itr ++;
}
}
以下渲染单色文本
void TypeFace::renderGlyphs(const std::list<textRenderCmdUnit>& cmd)
{
Vector2f position(0.0f,0.0f);
size_t leftChar = 0;
textRenderCmdUnit unit;
String tag;
std::queue<String> cmdStack;
std::list<textRenderCmdUnit>::const_iterator itr = cmd.begin();
while(itr != cmd.end())
{
unit = *itr;
if(unit.tag.empty() && !unit.undo)
{
position = renderGlyphs(unit.text,position);
}
else if(!unit.tag.empty())
{
tag = unit.tag;
cmdStack.push(tag);
if(tag == "bold")
bold_ = true;
else if(tag == "italic")
italic_ = true;
else if(tag == "underline")
underline_ = true;
else
applyColor(tag);
}
else if(unit.undo)
{
if(!cmdStack.empty())
{
tag = cmdStack.front();
cmdStack.pop();
if(tag == "bold")
bold_ = false;
else if(tag == "italic")
italic_ = false;
else if(tag == "underline")
underline_ = false;
else
applyColor(tag);
}
}
itr ++;
}
}
可以看出 支持的文本格式为<Tag>Text</>
一个例子是:
<Blue>这段代码主要测试BGE的富文本显示功能\n</Blue><Red>需要指出的是当前只要能支持多行显示和多颜色显示功能即可(不考虑下划线斜体以及加粗显示)。</Red><White>这句话将被显示为白色</><Blue>这句话应该被蓝色字体</Blue><Green>绿色字体</><Cyan>Cyan色</>";
最终显示如下: