ULRE/src/SceneGraph/font/TextLayout.cpp

307 lines
9.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include<hgl/graph/font/TextLayout.h>
#include<hgl/graph/font/TileFont.h>
#include<hgl/graph/font/TextPrimitive.h>
#include<hgl/type/Extent.h>
namespace hgl
{
namespace graph
{
bool TextLayout::Init()
{
if((!tla.font_source&&!font_source)
||!tla.char_layout_attr)
return(false);
direction.text_direction=tla.text_direction;
if(direction.vertical)
{
endless =(tla.max_width<=0.0f);
splite_line_max_limit = tla.max_width;
}
else
{
endless =(tla.max_height<=0.0f);
splite_line_max_limit = tla.max_height;
}
if(!font_source)
font_source=tla.font_source;
const float origin_char_height=font_source->GetCharHeight();
x=y=0;
char_height =ceil(origin_char_height);
space_size =ceil(origin_char_height*tla.space_size);
full_space_size =ceil(origin_char_height*tla.full_space_size);
tab_size =ceil(origin_char_height*tla.tab_size);
char_gap =ceil(origin_char_height*tla.char_gap);
line_gap =ceil(origin_char_height*tla.line_gap);
line_height =ceil(origin_char_height+line_gap);
paragraph_gap =ceil(origin_char_height*tla.paragraph_gap);
return(true);
}
/**
* 预处理所有的字符,获取所有字符的宽高,以及是否标点符号等信息
*/
template<typename T>
bool TextLayout::preprocess(TextPrimitive *tr,TileFont *tile_font,const T *str,const int str_length)
{
if(!tr
||!tile_font
||!str||!*str||str_length<=0
||!font_source)
return(false);
//遍历所有字符,取得每一个字符的基本绘制信息
{
draw_chars_count=0;
chars_sets.ClearData();
draw_chars_list.ClearData();
const T *cp=str;
CharDrawAttr *cda;
for(int i=0;i<str_length;i++)
{
cda=new CharDrawAttr;
cda->cla=font_source->GetCLA(*cp);
if(cda->cla->visible)
{
chars_sets.Add(*cp); //统计所有不重复字符
++draw_chars_count;
}
draw_chars_list.Add(cda);
++cp;
}
}
//释放不再使用的字符
{
clear_chars_sets=tr->GetCharsSets(); //获取不再使用的字符合集
clear_chars_sets.Clear(chars_sets); //清除下一步要用的字符合集
if(clear_chars_sets.GetCount()>0) //可以彻底清除的字符
{
tile_font->Unregistry(clear_chars_sets.GetList());
clear_chars_sets.ClearData();
}
}
//注册不重复字符给tile font系统获取所有字符的UV
if(!tile_font->Registry(chars_uv,chars_sets))
{
draw_chars_list.ClearData();
chars_sets.ClearData();
return(false);
}
tr->SetCharsSets(chars_sets); //注册需要使用的字符合集
//为可绘制字符列表中的字符获取UV
{
CharDrawAttr **cda=draw_chars_list.GetData();
for(int i=0;i<str_length;i++)
{
chars_uv.Get((*cda)->cla->attr->ch,(*cda)->uv);
++cda;
}
}
return(true);
}
/**
* 将字符串断成多行,处理标点禁用,以及英文单词禁拆分
*/
bool TextLayout::h_splite_to_lines(float view_limit)
{
//const int count=cla_list.GetCount();
//const CLA **cla=cla_list.GetData();
//int cur_size=0;
//for(int i=0;i<count;i++)
//{
//}
return(true);
}
bool TextLayout::v_splite_to_lines(float view_limit)
{
return(true);
}
//int TextLayout::Layout(const int mc,const String<T> &str)
//{
// if(mc<=0
// ||!str
// ||!(*str))
// return(-1);
// max_chars=mc;
// origin_string=str;
// if(preprocess()<=0)
// return(-3);
//
// if(!rc->Init(draw_chars_count))
// return(-4);
// vertex =rc->CreateVADA<VB4f>(VAN::Position);
// tex_coord =rc->CreateVADA<VB4f>(VAN::TexCoord);
// if(!vertex||!tex_coord)
// return(-5);
// if(direction.vertical)
// {
// if(!v_splite_to_lines(tla->max_height))
// return(-4);
// }
// else
// {
// if(!h_splite_to_lines(tla->max_width))
// return(-4);
// }
// return 0;
//}
int TextLayout::sl_h_l2r()
{
const int count=draw_chars_list.GetCount();
CharDrawAttr **cda=draw_chars_list.GetData();
int cur_size=0;
int left=0,top=0;
int16 *tp=vertex;
float *tcp=tex_coord;
for(int i=0;i<count;i++)
{
if((*cda)->cla->visible)
{
tp=WriteRect( tp,
left+(*cda)->cla->metrics.x,
top -(*cda)->cla->metrics.y+font_source->GetCharHeight(),
(*cda)->cla->metrics.w,
(*cda)->cla->metrics.h);
tcp=WriteRect(tcp,(*cda)->uv);
left+=(*cda)->cla->metrics.adv_x;
}
else
{
if((*cda)->cla->attr->ch==' ')
left+=space_size;
else
if((*cda)->cla->attr->ch==U32_FULL_WIDTH_SPACE)
left+=full_space_size;
else
if((*cda)->cla->attr->ch=='\t')
left+=tab_size;
else
if((*cda)->cla->attr->ch=='\n')
{
left=0;
top+=font_source->GetCharHeight()+line_gap;
}
else
{
left+=(*cda)->cla->metrics.adv_x;
}
}
++cda;
}
return count;
}
int TextLayout::sl_h_r2l(){return 0;}
int TextLayout::sl_v_r2l(){return 0;}
int TextLayout::sl_v_l2r(){return 0;}
/**
* 简易文本排版。无任何特殊处理,不支持任何转义符,不支持\r\n
*/
template<typename T>
int TextLayout::SimpleLayout(TextPrimitive *tr,TileFont *tf,const String<T> &str)
{
if(!tr)
return(-1);
if(!tf||str.IsEmpty())
return(-1);
int max_chars=str.Length();
if(!preprocess<T>(tr,tf,str.c_str(),max_chars))
return(-2);
if(draw_chars_count<=0) //可绘制字符为0这是全空格
return(-3);
vertex .SetLength(max_chars*4);
tex_coord .SetLength(max_chars*4);
if(!vertex||!tex_coord)
return(-5);
int result;
if(direction.vertical)
{
if(direction.right_to_left)
result=sl_v_r2l();
else
result=sl_v_l2r();
}
else
{
if(direction.right_to_left)
result=sl_h_r2l();
else
result=sl_h_l2r();
}
if(result>0)
{
tr->SetCharCount(result);
tr->WriteVertex(vertex);
tr->WriteTexCoord(tex_coord);
}
return result;
}
int TextLayout::SimpleLayout(TextPrimitive *tr,TileFont *tf,const UTF16String &str){return this->SimpleLayout<u16char>(tr,tf,str);}
int TextLayout::SimpleLayout(TextPrimitive *tr,TileFont *tf,const UTF32String &str){return this->SimpleLayout<u32char>(tr,tf,str);}
//template<typename T>
//int TextLayout::SimpleLayout(TileFont *tf,const StringList<String<T>> &sl)
//{
//}
//int TextLayout::SimpleLayout(TileFont *tf,const UTF16StringList &sl){return this->SimpleLayout<u16char>(tf,sl);}
//int TextLayout::SimpleLayout(TileFont *tf,const UTF32StringList &sl){return this->SimpleLayout<u32char>(tf,sl);}
}//namespace graph
}//namespace hgl