update TextLayout.h/.cpp

This commit is contained in:
hyzboy 2020-07-23 18:24:45 +08:00
parent 3119c1367d
commit 4f9553305c
2 changed files with 363 additions and 302 deletions

View File

@ -76,9 +76,113 @@ namespace hgl
bool compress_punctuation =false; ///<压缩标点符号 bool compress_punctuation =false; ///<压缩标点符号
};//struct TextLayoutAttributes };//struct TextLayoutAttributes
int TextLayout(RenderableCreater *,const TextLayoutAttributes *,const int max_chars,const UTF16String &); using TEXT_COORD_TYPE=int; //字符必须坐标对齐显示才能不模糊,所以这里坐标系全部使用整型坐标
int PlaneTextLayout(RenderableCreater *,FontSource *font_source,const int max_chars,const UTF16String &,const uint8 text_direction=0); class TextLayout
{
protected:
struct CharLayoutAttributes
{
u32char ch; ///<字符
int size; ///<字符排版尺寸(一般为宽)
bool visible; ///<是否可显示字符
bool is_cjk; ///<是否是中日韩文字
bool is_emoji; ///<是否是表情符号
bool is_punctuation; ///<是否是标点符号
bool begin_disable; ///<是否行首禁用符号
bool end_disable; ///<是否行尾禁用符号
bool vrotate; ///<竖排时是否需要旋转
FontAdvInfo adv_info; ///<字符绘制信息
};//struct CharLayoutAttributes
using CLA=CharLayoutAttributes;
protected:
RenderableCreater *rc;
TextLayoutAttributes tla;
protected:
TextDirection direction;
bool endless;
float splite_line_max_limit;
int max_chars; ///<总字符数量
int draw_chars_count; ///<可绘制字符数量
List<CLA> chars_attributes;
protected:
template<typename T> int preprocess(const BaseString<T> &origin_string);
template<typename T> int plane_preprocess(const BaseString<T> &origin_string);
bool h_splite_to_lines(float view_limit);
bool v_splite_to_lines(float view_limit);
int pl_h_l2r();
int pl_h_r2l();
int pl_v_r2l();
int pl_v_l2r();
protected:
TEXT_COORD_TYPE x,y;
TEXT_COORD_TYPE char_height;
TEXT_COORD_TYPE space_size;
TEXT_COORD_TYPE full_space_size;
TEXT_COORD_TYPE tab_size;
TEXT_COORD_TYPE char_gap;
TEXT_COORD_TYPE line_gap;
TEXT_COORD_TYPE line_height;
TEXT_COORD_TYPE paragraph_gap;
protected:
AutoDelete<VB4f> vertex,
tex_coord;
public:
TextLayout()
{
rc=nullptr;
direction.text_direction=0;
max_chars =0;
draw_chars_count =0;
vertex =nullptr;
tex_coord =nullptr;
}
virtual ~TextLayout()=default;
bool Set(RenderableCreater *_rc) {if(_rc)rc=_rc;}
bool Set(const TextLayoutAttributes *_tla) {if(_tla)memcpy(&tla,_tla,sizeof(TextLayoutAttributes));}
bool Set(FontSource *fs) {if(fs)tla.font_source=fs;}
bool SetTextDirection(const uint8 &td) {tla.text_direction=td;}
bool Set(const TextAlign &ta) {tla.align=ta;}
bool SetMaxWidth(const float mw) {tla.max_width=mw;}
bool SetMaxHeight(const float mh) {tla.max_height=mh;}
virtual bool Init (); ///<初始化排版
// virtual int Layout (const int max_chars,const BaseString<T> &)=0; ///<排版
template<typename T>
int PlaneLayout (const int max_chars,const BaseString<T> &)=0; ///<简易排版
};//class TextLayout
}//namespace graph }//namespace graph
}//namespace hgl }//namespace hgl
#endif//HGL_GRAPH_TEXT_LAYOUT_INCLUDE #endif//HGL_GRAPH_TEXT_LAYOUT_INCLUDE

View File

@ -18,29 +18,6 @@ namespace hgl
constexpr int CurrencySymbolsCount=(sizeof(CurrencySymbols)/sizeof(u16char))-1; constexpr int CurrencySymbolsCount=(sizeof(CurrencySymbols)/sizeof(u16char))-1;
constexpr int VRotateSymbolsCount =(sizeof(VRotateSymbols) /sizeof(u16char))-1; constexpr int VRotateSymbolsCount =(sizeof(VRotateSymbols) /sizeof(u16char))-1;
using TEXT_COORD_TYPE=int; //字符必须坐标对齐显示才能不模糊,所以这里坐标系全部使用整型坐标
template<typename T>
struct CharLayoutAttributes
{
T ch; ///<字符
int size; ///<字符排版尺寸(一般为宽)
bool visible; ///<是否可显示字符
bool is_cjk; ///<是否是中日韩文字
bool is_emoji; ///<是否是表情符号
bool is_punctuation; ///<是否是标点符号
bool begin_disable; ///<是否行首禁用符号
bool end_disable; ///<是否行尾禁用符号
bool vrotate; ///<竖排时是否需要旋转
FontAdvInfo adv_info; ///<字符绘制信息
};//struct CharLayoutAttributes
/** /**
* 45 * 45
*/ */
@ -48,101 +25,48 @@ namespace hgl
{ {
return TEXT_COORD_TYPE(floor(value+0.5)); return TEXT_COORD_TYPE(floor(value+0.5));
} }
}//namespace
template<typename T> class TextLayoutEngine bool TextLayout::Init()
{ {
protected: if(!rc
||!tla.font_source
||!tla.char_attributes)
return(false);
RenderableCreater *rc; direction.text_direction=tla.text_direction;
const TextLayoutAttributes *tla;
TextDirection direction;
bool endless;
float splite_line_max_limit;
int max_chars;
BaseString<T> origin_string;
using CLA=CharLayoutAttributes<T>;
List<CLA> chars_attributes;
protected:
TEXT_COORD_TYPE x,y;
TEXT_COORD_TYPE char_height;
TEXT_COORD_TYPE space_size;
TEXT_COORD_TYPE full_space_size;
TEXT_COORD_TYPE tab_size;
TEXT_COORD_TYPE char_gap;
TEXT_COORD_TYPE line_gap;
TEXT_COORD_TYPE line_height;
TEXT_COORD_TYPE paragraph_gap;
protected:
AutoDelete<VB4f> vertex;
public:
TextLayoutEngine()
{
rc=nullptr;
tla=nullptr;
direction.text_direction=0;
max_chars=0;
vertex=nullptr;
}
virtual ~TextLayoutEngine()=default;
bool Init(RenderableCreater *_rc,const TextLayoutAttributes *_tla)
{
if(!_rc
||!_tla
||!tla->font_source
||!tla->char_attributes)
return false;
rc=_rc;
tla=_tla;
direction.text_direction=tla->text_direction;
if(direction.vertical) if(direction.vertical)
{ {
endless =(tla->max_width<=0.0f); endless =(tla.max_width<=0.0f);
splite_line_max_limit =tla->max_width; splite_line_max_limit = tla.max_width;
} }
else else
{ {
endless =(tla->max_height<=0.0f); endless =(tla.max_height<=0.0f);
splite_line_max_limit =tla->max_height; splite_line_max_limit = tla.max_height;
} }
const float origin_char_height=tla->font_source->GetCharHeight(); const float origin_char_height=tla.font_source->GetCharHeight();
x=y=0; x=y=0;
char_height =out4in5(origin_char_height); char_height =out4in5(origin_char_height);
space_size =out4in5(origin_char_height*tla->space_size); space_size =out4in5(origin_char_height*tla.space_size);
full_space_size =out4in5(origin_char_height*tla->full_space_size); full_space_size =out4in5(origin_char_height*tla.full_space_size);
tab_size =out4in5(origin_char_height*tla->tab_size); tab_size =out4in5(origin_char_height*tla.tab_size);
char_gap =out4in5(origin_char_height*tla->char_gap); char_gap =out4in5(origin_char_height*tla.char_gap);
line_gap =out4in5(origin_char_height*tla->line_gap); line_gap =out4in5(origin_char_height*tla.line_gap);
line_height =out4in5(origin_char_height+line_gap); line_height =out4in5(origin_char_height+line_gap);
paragraph_gap =out4in5(origin_char_height*tla->paragraph_gap); paragraph_gap =out4in5(origin_char_height*tla.paragraph_gap);
return(true); return(true);
} }
protected:
/** /**
* *
*/ */
int preprocess() template<typename T>
int TextLayout::preprocess(const BaseString<T> &origin_string)
{ {
const int count=hgl_min(max_chars,origin_string.Length()); const int count=hgl_min(max_chars,origin_string.Length());
@ -150,6 +74,7 @@ namespace hgl
return 0; return 0;
chars_attributes.SetCount(count); chars_attributes.SetCount(count);
draw_chars_count=0;
CLA *cla=chars_attributes.GetData(); CLA *cla=chars_attributes.GetData();
const T *cp=origin_string.c_str(); const T *cp=origin_string.c_str();
@ -168,7 +93,7 @@ namespace hgl
} }
else else
{ {
cla->visible=true; cla->size=out4in5(tla->font_source->GetCharAdvWidth(*cp)); cla->visible=true; cla->size=out4in5(tla.font_source->GetCharAdvWidth(*cp));
cla->begin_disable =hgl::strchr(BeginSymbols, *cp,BeginSymbolsCount ); cla->begin_disable =hgl::strchr(BeginSymbols, *cp,BeginSymbolsCount );
cla->end_disable =hgl::strchr(EndSymbols, *cp,EndSymbolsCount ); cla->end_disable =hgl::strchr(EndSymbols, *cp,EndSymbolsCount );
@ -185,6 +110,58 @@ namespace hgl
if(!tla->font_source->GetCharAdvInfo(cla->adv_info,*cp)) if(!tla->font_source->GetCharAdvInfo(cla->adv_info,*cp))
hgl_zero(cla->adv_info); hgl_zero(cla->adv_info);
else
if(cla->adv_info.w>0&&cla->adv_info.h>0)
++draw_chars_count;
}
++cp;
++cla;
}
return count;
}
/**
*
*/
template<typename T>
int TextLayout::plane_preprocess(const BaseString<T> &origin_string)
{
const int count=hgl_min(max_chars,origin_string.Length());
if(count<=0)
return 0;
chars_attributes.SetCount(count);
draw_chars_count=0;
CLA *cla=chars_attributes.GetData();
const T *cp=origin_string.c_str();
for(int i=0;i<count;i++)
{
cla->ch=*cp;
if(hgl::isspace(*cp))
{
cla->visible=false;
if(*cp=='\t') cla->size=tab_size; else
if(*cp==HGL_FULL_SPACE) cla->size=full_space_size; else
cla->size=space_size;
}
else
{
cla->visible=true; cla->size=out4in5(tla.font_source->GetCharAdvWidth(*cp));
cla->vrotate =hgl::strchr(VRotateSymbols,*cp,VRotateSymbolsCount );
if(!tla->font_source->GetCharAdvInfo(cla->adv_info,*cp))
hgl_zero(cla->adv_info);
else
if(cla->adv_info.w>0&&cla->adv_info.h>0)
++draw_chars_count;
} }
++cp; ++cp;
@ -197,7 +174,7 @@ namespace hgl
/** /**
* *
*/ */
bool h_splite_to_lines(float view_limit) bool TextLayout::h_splite_to_lines(float view_limit)
{ {
const int count=chars_attributes.GetCount(); const int count=chars_attributes.GetCount();
const CLA *cla=chars_attributes.GetData(); const CLA *cla=chars_attributes.GetData();
@ -211,96 +188,88 @@ namespace hgl
return(true); return(true);
} }
bool v_splite_to_lines(float view_limit) bool TextLayout::v_splite_to_lines(float view_limit)
{ {
return(true); return(true);
} }
public: //int TextLayout::Layout(const int mc,const BaseString<T> &str)
//{
// if(mc<=0
// ||!str
// ||!(*str))
// return(-1);
int layout(const int mc,const BaseString<T> &str) // max_chars=mc;
{ // origin_string=str;
if(mc<=0
||!str
||!(*str))
return(-1);
max_chars=mc; // if(preprocess()<=0)
origin_string=str; // return(-3);
//
// if(!rc->Init(draw_chars_count))
// return(-4);
if(preprocess()<=0) // vertex =rc->CreateVADA<VB4f>(VAN::Vertex);
return(-3); // tex_coord =rc->CreateVADA<VB4f>(VAN::TexCoord);
if(direction.vertical) // if(!vertex||!tex_coord)
{ // return(-5);
if(!v_splite_to_lines(tla->max_height))
return(-4);
}
else
{
if(!h_splite_to_lines(tla->max_width))
return(-4);
}
return 0; // if(direction.vertical)
} // {
// if(!v_splite_to_lines(tla->max_height))
// return(-4);
// }
// else
// {
// if(!h_splite_to_lines(tla->max_width))
// return(-4);
// }
protected: // return 0;
//}
int pl_h_l2r() int TextLayout::pl_h_l2r()
{ {
const int count=chars_attributes.GetCount(); const int count=chars_attributes.GetCount();
const CLA *cla=chars_attributes.GetData(); const CLA *cla=chars_attributes.GetData();
int cur_size=0; int cur_size=0;
int left=0,top=0;
for(int i=0;i<count;i++) for(int i=0;i<count;i++)
{ {
vertex->Write(x,y vertex->Write(
} }
} }
int pl_h_r2l() int TextLayout::pl_h_r2l(){return 0;}
{ int TextLayout::pl_v_r2l(){return 0;}
return 0; int TextLayout::pl_v_l2r(){return 0;}
}
int pl_v_r2l()
{
return 0;
}
int pl_v_l2r()
{
return 0;
}
public:
/** /**
* <br> * <br>
* \r\n换行 * \r\n换行
*/ */
int plane_layout(const int mc,const BaseString<T> &str) template<typename T>
int TextLayout::PlaneLayout(const int mc,const BaseString<T> &str)
{ {
if(mc<=0 if(mc<=0||str.IsEmpty()
||!str
||!(*str))
return(-1); return(-1);
max_chars=hgl_min(mc,str.Length()); max_chars=hgl_min(mc,str.Length());
origin_string=str;
if(preprocess()<=0) if(plane_preprocess<T>(str)<=0)
return(-3); return(-3);
if(!rc->Init(ch_count)) if(!rc->Init(draw_chars_count))
return(-4); return(-4);
vertex=rc->CreateVADA<VB4f>(VAN::Vertex); vertex =rc->CreateVADA<VB4f>(VAN::Vertex);
tex_coord =rc->CreateVADA<VB4f>(VAN::TexCoord);
if(!vertex) if(!vertex||!tex_coord)
return(-5); return(-5);
if(direction.vertical) if(direction.vertical)
@ -320,17 +289,5 @@ namespace hgl
return 0; return 0;
} }
};//template<typename T> class TextLayoutEngine
}//namespace
int TextLayout(RenderableCreater *rc,const TextLayoutAttributes *tla,const int max_chars,const UTF16String &str)
{
TextLayoutEngine<u16char> engine;
if(!engine.Init(rc,tla))
return(-1);
return engine.layout(max_chars,str);
}
}//namespace graph }//namespace graph
}//namespace hgl }//namespace hgl