From 2ae2228546223414e0f9a0dfb38c6374886565be Mon Sep 17 00:00:00 2001 From: hyzboy Date: Mon, 3 Aug 2020 21:22:02 +0800 Subject: [PATCH] first finished TileFont and test program. --- example/Vulkan/DrawText.cpp | 87 +++++++++----------- inc/hgl/graph/font/TextLayout.h | 54 ++++++------ inc/hgl/graph/font/TileFont.h | 3 +- src/SceneGraph/font/TextLayout.cpp | 128 +++++++++++++++++------------ src/SceneGraph/font/TileFont.cpp | 43 ++++------ 5 files changed, 157 insertions(+), 158 deletions(-) diff --git a/example/Vulkan/DrawText.cpp b/example/Vulkan/DrawText.cpp index 0001e989..83d477c3 100644 --- a/example/Vulkan/DrawText.cpp +++ b/example/Vulkan/DrawText.cpp @@ -48,13 +48,11 @@ private: TextLayout tl_engine; ///<文本排版引擎 RenderableCreater * text_rc =nullptr; - Renderable * text_renderable =nullptr; ///<文本渲染对象列表 public: ~TestApp() { - SAFE_CLEAR(text_renderable); SAFE_CLEAR(text_rc); SAFE_CLEAR(tile_font); } @@ -69,33 +67,6 @@ private: return(true); } - bool InitTextRenderable() - { - CharAttributes ca; - TextLayoutAttributes tla; - - ca.CharColor=Color4f(COLOR::White); - ca.BackgroundColor=Color4f(COLOR::Black); - - tla.char_attributes=&ca; - - text_rc=new RenderableCreater(db,material); - - tl_engine.Set(text_rc); - tl_engine.Set(&tla); - tl_engine.SetTextDirection(0); - tl_engine.Set(TextAlign::Left); - tl_engine.SetMaxWidth(0); - tl_engine.SetMaxHeight(0); - - if(!tl_engine.Init()) - return(false); - - UTF16String str=U16_TEXT("道可道,非常道。名可名,非常名。无名天地之始。有名万物之母。故常无欲以观其妙。常有欲以观其徼。此两者同出而异名,同谓之玄。玄之又玄,众妙之门。"); - - tl_engine.PlaneLayout(tile_font,0,str); - } - bool InitMaterial() { material=shader_manage->CreateMaterial( OS_TEXT("res/shader/DrawRect2D.vert"), @@ -108,7 +79,7 @@ private: sampler=db->CreateSampler(); - material_instance->BindSampler("tex",tile_data->GetTexture(),sampler); + material_instance->BindSampler("tex",tile_font->GetTexture(),sampler); material_instance->BindUBO("world",ubo_world_matrix); material_instance->Update(); @@ -134,21 +105,6 @@ private: return(true); } - void InitVBO() - { - const int tile_count=tile_list.GetCount(); - - render_obj=material->CreateRenderable(tile_count); - - vertex_buffer =db->CreateVAB(VAF_VEC4,tile_count,vertex_data); - tex_coord_buffer=db->CreateVAB(VAF_VEC4,tile_count,tex_coord_data); - - render_obj->Set("Vertex",vertex_buffer); - render_obj->Set("TexCoord",tex_coord_buffer); - - db->Add(render_obj); - } - bool InitPipeline() { AutoDelete @@ -162,6 +118,39 @@ private: return pipeline; } + bool InitTextRenderable() + { + CharLayoutAttr cla; + TextLayoutAttributes tla; + + cla.CharColor=Color4f(COLOR::White); + cla.BackgroundColor=Color4f(COLOR::Black); + + tla.char_layout_attr=&cla; + + text_rc=new RenderableCreater(db,material); + + tl_engine.Set(text_rc); + tl_engine.Set(&tla); + tl_engine.SetTextDirection(0); + tl_engine.Set(TextAlign::Left); + tl_engine.SetMaxWidth(0); + tl_engine.SetMaxHeight(0); + + if(!tl_engine.Init()) + return(false); + + UTF16String str=U16_TEXT("道可道,非常道。名可名,非常名。无名天地之始。有名万物之母。故常无欲以观其妙。常有欲以观其徼。此两者同出而异名,同谓之玄。玄之又玄,众妙之门。"); + + if(tl_engine.SimpleLayout(tile_font,str)>0) + { + render_obj=text_rc->Finish(); + return(true); + } + + return(false); + } + public: bool Init() @@ -169,9 +158,6 @@ public: if(!VulkanApplicationFramework::Init(SCREEN_WIDTH,SCREEN_HEIGHT)) return(false); - if(!InitTileData()) - return(false); - if(!InitTileFont()) return(false); @@ -181,10 +167,11 @@ public: if(!InitMaterial()) return(false); - InitVBO(); - if(!InitPipeline()) return(false); + + if(!InitTextRenderable()) + return(false); BuildCommandBuffer(pipeline,material_instance,render_obj); diff --git a/inc/hgl/graph/font/TextLayout.h b/inc/hgl/graph/font/TextLayout.h index 3cc0ad44..2839e6c9 100644 --- a/inc/hgl/graph/font/TextLayout.h +++ b/inc/hgl/graph/font/TextLayout.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace hgl { namespace graph @@ -13,7 +14,7 @@ namespace hgl /** * 字符属性,可精确到字也可精确到段落或是全文 */ - struct CharAttributes + struct CharLayoutAttr { bool bold =false; ///<加粗 bool italic =false; ///<右斜 @@ -21,7 +22,7 @@ namespace hgl Color4f CharColor; ///<字符颜色 Color4f BackgroundColor; ///<背影颜色 - };//struct CharAttributes + };//struct CharLayoutAttr /** * 文本排列方向 @@ -57,7 +58,7 @@ namespace hgl struct TextLayoutAttributes { FontSource * font_source =nullptr; ///<字符源 - CharAttributes *char_attributes =nullptr; ///<缺省字符属性 + CharLayoutAttr *char_layout_attr =nullptr; ///<缺省字符排版属性 uint8 text_direction =0; ///<文本排列方向 TextAlign align =TextAlign::Left; ///<段落对齐 @@ -94,25 +95,30 @@ namespace hgl bool endless; float splite_line_max_limit; - int max_chars; ///<总字符数量 + int draw_chars_count; ///<要绘制字符列表 Set alone_chars; ///<不重复字符统计缓冲区 + TileUVFloatMap alone_chars_uv; ///<所有要绘制字符的uv - List cla_list; ///<所有字符属性列表 - - protected: - - template int stat_chars(const T *,const int); - template int preprocess(const T *,const int); + struct CharDrawAttr + { + CLA *cla; + TileUVFloat uv; + }; + ObjectList draw_chars_list; ///<所有字符属性列表 + + template int preprocess(const T *,const int); + + protected: + 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(); + int sl_h_l2r(); + int sl_h_r2l(); + int sl_v_r2l(); + int sl_v_l2r(); protected: @@ -138,7 +144,7 @@ namespace hgl rc=nullptr; direction.text_direction=0; - max_chars =0; + draw_chars_count=0; vertex =nullptr; tex_coord =nullptr; @@ -146,20 +152,20 @@ namespace hgl 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;} + void Set (RenderableCreater *_rc) {if(_rc)rc=_rc;} + void Set (const TextLayoutAttributes *_tla) {if(_tla)memcpy(&tla,_tla,sizeof(TextLayoutAttributes));} + void Set (FontSource *fs) {if(fs)tla.font_source=fs;} + void SetTextDirection (const uint8 &td) {tla.text_direction=td;} + void Set (const TextAlign &ta) {tla.align=ta;} + void SetMaxWidth (const float mw) {tla.max_width=mw;} + void SetMaxHeight (const float mh) {tla.max_height=mh;} virtual bool Init (); ///<初始化排版 // virtual int Layout (const int max_chars,const BaseString &)=0; ///<排版 template - int PlaneLayout (TileFont *,const int max_chars,const BaseString &); ///<简易排版 + int SimpleLayout (TileFont *,const BaseString &); ///<简易排版 };//class TextLayout }//namespace graph }//namespace hgl diff --git a/inc/hgl/graph/font/TileFont.h b/inc/hgl/graph/font/TileFont.h index 883f5d5b..70524ca7 100644 --- a/inc/hgl/graph/font/TileFont.h +++ b/inc/hgl/graph/font/TileFont.h @@ -26,13 +26,14 @@ namespace hgl FontSource *GetFontSource (){return source;} TileData * GetTileData (){return tile_data;} + Texture2D * GetTexture (){return tile_data->GetTexture();} public: TileFont(TileData *td,FontSource *fs); virtual ~TileFont(); - bool Registry(List &,const List &); ///<注册要使用的字符 + bool Registry(TileUVFloatMap &,const u32char *ch_list,const int ch_count); ///<注册要使用的字符 void Unregistry(const List &); ///<注销要使用的字符 };//class TileFont }//namespace graph diff --git a/src/SceneGraph/font/TextLayout.cpp b/src/SceneGraph/font/TextLayout.cpp index 085d5d43..4e6cb580 100644 --- a/src/SceneGraph/font/TextLayout.cpp +++ b/src/SceneGraph/font/TextLayout.cpp @@ -40,47 +40,55 @@ namespace hgl return(true); } - - template - int TextLayout::stat_chars(const T *str,const int str_length) - { - if(!str||!*str||str_length<=0) - return 0; - - alone_chars.ClearData(); - - for(int i=0;i + template int TextLayout::preprocess(const T *str,const int str_length) { - const int count=hgl_min(max_chars,str_length); - - if(count<=0) + if(!str||!*str||str_length<=0) return 0; + + draw_chars_count=0; + alone_chars.ClearData(); - cla_list.ClearData(); - cla_list.SetCount(count); + draw_chars_list.ClearData(); + draw_chars_list.SetCount(str_length); - CLA **cla=cla.GetData(); + CharDrawAttr **cda=draw_chars_list.GetData(); const T *cp=str; for(int i=0;ifont_source.GetCLA(*cp); + (*cda)->cla=tla->font_source.GetCLA(*cp); + + if((*cda)->cla->visible) + { + alone_chars.Add(*cp); //统计所有不重复字符 + ++draw_chars_count; + } ++cp; - ++cla; + ++cda; + } + + //注册不重复字符给tile font系统,获取所有字符的UV + if(!tf->Registry(alone_chars_uv,alone_chars.GetData(),alone_chars.GetCount())) + { + draw_chars_list.ClearData(); + alone_chars.ClearData(); + + return(false); + } + + //为可绘制字符列表中的字符获取UV + cda=draw_chars_list.GetData(); + for(int i=0;icla->ch,(*cda)->uv); + + ++cda; } return count; @@ -91,14 +99,14 @@ namespace hgl */ bool TextLayout::h_splite_to_lines(float view_limit) { - const int count=cla_list.GetCount(); - const CLA **cla=cla_list.GetData(); + //const int count=cla_list.GetCount(); + //const CLA **cla=cla_list.GetData(); - int cur_size=0; + //int cur_size=0; - for(int i=0;iBegin(); + float *tcp=tex_coord->Begin(); for(int i=0;iadv_info.w;++tp; - *tp=top +(*cla)->adv_info.h;++tp; + if((*cda)->cla->visible) + { + tp=WriteRect( tp, + left, + top, + (*cda)->cla->metrics.w, + (*cda)->cla->metrics.h); + + tcp=WriteRect(tcp,(*cda)->uv); + } + else + { + } + + left+=(*cda)->cla->metrics.adv_x; + + ++cda; } + tex_coord->End(); vertex->End(); - return 0; + return count; } - int TextLayout::pl_h_r2l(){return 0;} - int TextLayout::pl_v_r2l(){return 0;} - int TextLayout::pl_v_l2r(){return 0;} + int TextLayout::sl_h_r2l(){return 0;} + int TextLayout::sl_v_r2l(){return 0;} + int TextLayout::sl_v_l2r(){return 0;} /** - * 平面文本排版
- * 不处理自动换行,仅支持\r\n换行。无任何特殊处理 + * 简易文本排版。无任何特殊处理,不支持任何转义符,不支持\r\n */ template - int TextLayout::PlaneLayout(TileFont *tf,const int mc,const BaseString &str) + int TextLayout::SimpleLayout(TileFont *tf,const BaseString &str) { - if(mc<=0||str.IsEmpty()) + if(!tf||str.IsEmpty()) return(-1); - max_chars=hgl_min(mc,str.Length()); - - if(stat_chars(str.c_str(),str.Length())<=0) - return(-2); - if(preprocess(str.c_str(),str.Length())<=0) return(-3); - if(!rc->Init(draw_chars_count)) + if(draw_chars_count<=0) //可绘制字符为0???这是全空格? return(-4); + if(!rc->Init(draw_chars_count)) //创建 + return(-5); + vertex =rc->CreateVADA(VAN::Vertex); tex_coord =rc->CreateVADA(VAN::TexCoord); diff --git a/src/SceneGraph/font/TileFont.cpp b/src/SceneGraph/font/TileFont.cpp index 1b90790b..e484f689 100644 --- a/src/SceneGraph/font/TileFont.cpp +++ b/src/SceneGraph/font/TileFont.cpp @@ -30,45 +30,32 @@ namespace hgl * @param rs 每个字符在纹理中的UV坐标 * @param ch_list 要注册的字符列表 */ - bool TileFont::Registry(List &rs,const List &ch_list) + bool TileFont::Registry(TileUVFloatMap &uv_map,const u32char *ch_list,const int ch_count) { - const u32char *cp=ch_list.GetData(); + const u32char *cp=ch_list; TileObject *to; List new_chars; - int in_active_count; - int in_idle_count; - int out_count; - int idle_left_count; + int in_active_count; //在活跃列表中的数量 + int in_idle_count; //在闲置列表中的数量 + int out_count; //不存在的字符数量 + int idle_left_count; //闲置列表中可释放的数量 - int exist_count; + to_res.Stats(ch_list,ch_count,&in_active_count,&in_idle_count,&out_count,&idle_left_count); - to_res.Stats(ch_list.GetData(),ch_list.GetCount(),&in_active_count,&in_idle_count,&out_count,&idle_left_count); + if(out_count>idle_left_count+tile_data->GetFreeCount()) //不存在的字符数量总量>剩余可释放的闲置项+剩余可用的空余tile + return(false); - exist_count=in_active_count+in_idle_count; - - if(exist_count>tile_data->GetFreeCount()) //剩余空间不够了 - { - int need=new_chars.GetCount()-tile_data->GetFreeCount(); //计算需要的tile数量差值 - - to_res.Get - - if(need>to_res.GetIdleCount()) //闲置项都不够,那没戏了 - return(false); - } - - rs.ClearData(); - rs.SetCount(ch_list.GetCount()); + uv_map.ClearData(); FontBitmap *bmp; - TileUVFloat *tp=rs.GetData(); - cp=ch_list.GetData(); + cp=ch_list; if(new_chars.GetCount()) { tile_data->BeginCommit(); - for(uint i=0;iuv_float); ++cp; - - *tp=to->uv_float; - ++tp; } tile_data->EndCommit(); } else { - for(uint i=0;i