为了配合工作,所以定点突破文本控件的格式管理问题。
Day1:
了解了文本控件根据格式绘制的具体流程。如下:
1在TextDemo的formatChangedHandler(const CEGUI::EventArgs& e)里面调用PropertySet::setProperty(const String& name,const String& value)函数来传入属性字符串以及属性值字符串来设置对应的属性。
2利用泛型机制调用到FalagardStaticText类的setVerticalFormatting函数。
3在setVerticalFormattinghan里面调用configureScrollbars来设置我们需要绘制的文本区域的大小。以及是否存在滚动条等等。
4在configureScrollbars里面调用getDocumentSize来计算文本区域的大小。其中,使用getFormattedLineCount来计算行数,再乘以每行的高度,即为全部区域的高度。而使用getFormattedTextExtent得到绘制区域的最大宽度。
5特别提一下getFormattedLineCount计算字符串的行数的问题。这个接口实现考虑到了多行文本的问题,可以借鉴下。
6之后是getFormattedTextExtent得到最宽的那一行的宽度。使用getWrappedTextExtent来得到最宽的那行字符串的宽度。
上面是设置文本的一些属性,以下为绘制:
1.在FalagardStaticText::render()里面调用renderScrolledText();
2.这里要说的是绘制字符串是在RenderCache::render这个函数里面完成的。该函数将d_cachedImages里面所有的图片均draw出来,将d_cachedTexts里面所有的字符串也绘制出来。
3.在这里搞不明白的就是size_t Font::drawText(const String& text, const Rect& draw_area, float z, const Rect& clip_rect, TextFormatting fmt, const ColourRect& colours, float x_scale, float y_scale)这个函数为什么在绘制的时候又将文本的分行规律计算了一遍,个人觉得类似这样的计算完全只需要计算一遍就可以了哩。
4.在size_t Font::drawWrappedText(const String& text, const Rect& draw_area, float z, const Rect& clip_rect, TextFormatting fmt, const ColourRect& colours, float x_scale, float y_scale)里面计算了分行的规律。然后按照该规律来依次画字。
明天要将计算换行的机制搞清楚,为什么在设置文本的时候需要计算一次,而在绘制的时候又计算了一次。
Day2:
今天MS感冒了,上个班累死。还好上班的时候研究了下。发现其不但所有的Image对象、所有的字符串对象,都是被RenderCache类里面的d_cachedImages以及d_cachedTexts容器管理起来的。甚至连所有的绘制区域都是使用一个d_quadlist的容器来管理的。这样的管理对象的思想是不是值得借鉴下哩,又该如何借鉴哩,考虑下。不过上屏的时候仍然是d_quadlist里面所有的成员都要上屏的,也就是说局部刷新MS没有在CEGUI里面实现。也不能说绝对,比方说鼠标在界面上移动的时候,MS仅仅只绘制了鼠标图片。在DirectX9Renderer类的addQuad函数里有renderQuadDirect直接绘制,而不是insert到d_quadlist里面。明天继续研究。
Day3:
今天主要分析下Font类里面的drawWrappedText函数。MS在帮助文档里面暂时还找不到该函数的解释。字面上来理解应该是绘制换行文本的意思。我拿了一个右对齐的单行文本做例子传进去。
/*************************************************************************
draws wrapped text
*************************************************************************/
size_t Font::drawWrappedText(const String& text, const Rect& draw_area, float z, const Rect& clip_rect, TextFormatting fmt, const ColourRect& colours, float x_scale, float y_scale)
{
size_t line_count = 0;
Rect dest_area(draw_area);//绘制文字的区域
float wrap_width = draw_area.getWidth();//区域的宽度,用来比较是否需要新开一行
String whitespace = TextUtils::DefaultWhitespace;
String thisLine, thisWord;
size_t currpos = 0;
// get first word.
currpos += getNextWord(text, currpos, thisLine);//得到第一个单词的字母个数(到第一个分隔符默认为空格处为止)
// while there are words left in the string...
while (String::npos != text.find_first_not_of(whitespace, currpos))//只要存在字符
{
// get next word of the string...
currpos += getNextWord(text, currpos, thisWord);//再得到下一个单词的长度
// if the new word would make the string too long
if ((getTextExtent(thisLine, x_scale) + getTextExtent(thisWord, x_scale)) > wrap_width)//如果当前行的单词加上下一个单词的宽度要大于绘制区域宽度的话
{
// output what we had until this new word
line_count += drawText(thisLine, dest_area, z, clip_rect, fmt, colours, x_scale, y_scale);//仅仅绘制当前行已经存在的单词
// remove whitespace from next word - it will form start of next line
thisWord = thisWord.substr(thisWord.find_first_not_of(whitespace));//之后的字符串之前的空格符
// reset for a new line.
thisLine.clear();//当前行清空
// update y co-ordinate for next line
dest_area.d_top += getLineSpacing(y_scale);//绘制区域下移一行字的高度
}
// add the next word to the line
thisLine += thisWord;//如果没有达到换行的要求的话则继续往后加
}
// Last line is left aligned
TextFormatting last_fmt = (fmt == Justified ? LeftAligned : fmt);
// output last bit of string
line_count += drawText(thisLine, dest_area, z, clip_rect, last_fmt, colours, x_scale, y_scale);//绘制最后一行
return line_count;
}