update TextLayout
This commit is contained in:
parent
2f70131ca4
commit
8cb2df9a35
2
CMCore
2
CMCore
@ -1 +1 @@
|
||||
Subproject commit 360a743491e3310c8eedfc594a5c49b97180f177
|
||||
Subproject commit 0e9bb594d737717493ab0c943d34d2851f616f59
|
@ -20,82 +20,66 @@ namespace hgl
|
||||
Color4f CharColor; ///<字符颜色
|
||||
Color4f BackgroundColor; ///<背影颜色
|
||||
};//struct CharAttributes
|
||||
|
||||
/**
|
||||
* 文本排列方向
|
||||
*/
|
||||
union TextDirection
|
||||
{
|
||||
uint8 text_direction;
|
||||
|
||||
struct
|
||||
{
|
||||
uint vertical:1; ///<是否竖排
|
||||
uint right_to_left:1; ///<是否从右往左
|
||||
uint bottom_to_top:1; ///<是否从下到上
|
||||
};
|
||||
};//union TextDirection
|
||||
|
||||
/**
|
||||
* 段落对齐
|
||||
* 文本对齐
|
||||
*/
|
||||
enum class ParagraphAlign
|
||||
enum class TextAlign
|
||||
{
|
||||
Left=0, ///<左对齐
|
||||
Right, ///<右对齐
|
||||
Center, ///<居中
|
||||
Fill, ///<排满整行/列
|
||||
|
||||
Top =Left, ///<上对齐
|
||||
Bottom =Right ///<下对齐
|
||||
};//enum class ParagraphAlign
|
||||
};//enum class TextAlign
|
||||
|
||||
/**
|
||||
* 段落属性
|
||||
*/
|
||||
struct ParagraphAttributes
|
||||
{
|
||||
ParagraphAlign align =ParagraphAlign::Left; ///<段落对齐
|
||||
float char_gap =0.0f; ///<字间距
|
||||
float line_gap =0.1f; ///<行间距(相对于字符高度)
|
||||
|
||||
uint32 char_attributes =0; ///<缺省字符属性
|
||||
|
||||
bool border_symbols_disable =true; ///<边界符号禁用(如行首禁用逗号)
|
||||
bool auto_symbols_convert =true; ///<自动符号转换(如tm/(r)/(c)等)
|
||||
|
||||
float space_size =0.5f; ///<空格符尺寸(对应字符高度的系数)
|
||||
float tab_size =2.0f; ///<Tab符号尺寸(对应字符高度的系数)
|
||||
|
||||
bool auto_spaces_size =false; ///<自动空白字符尺寸(用于将每行/列文本长度拉至一样)
|
||||
};//struct ParagraphAttributes
|
||||
|
||||
/**
|
||||
* 文本排列方向
|
||||
*/
|
||||
enum class TextDirection
|
||||
{
|
||||
HorizontalLeftToRight=0, ///<横排从左到右
|
||||
HorizontalRightToLeft, ///<横排从右到左
|
||||
VerticalRightToLeft, ///<坚排从上到下从右到左(一般用于中文)
|
||||
VerticalRightToLeftRotate90,///<坚排从上到下从右到左字符旋转90度(一般用于英文)
|
||||
};//enum class Direction
|
||||
|
||||
struct TextAttributes
|
||||
{
|
||||
TextDirection direction =TextDirection::HorizontalLeftToRight; ///<文本排列方向
|
||||
uint32_t paragraph_attribute =0; ///<缺省段落属性
|
||||
float paragraph_gap =1.0f; ///<段间距
|
||||
};//struct TextAttributes
|
||||
|
||||
using CharAttributesList=Map<UTF16String,CharAttributes>;
|
||||
using ParagraphAttributesList=Map<UTF16String,ParagraphAttributes>;
|
||||
|
||||
/**
|
||||
* 文本排版处理配置
|
||||
* 文本排版属性
|
||||
*/
|
||||
struct TextLayoutAttributes
|
||||
{
|
||||
FontSource * source =nullptr; ///字符源
|
||||
FontSource * font_source =nullptr; ///<字符源
|
||||
CharAttributes *char_attributes =nullptr; ///<缺省字符属性
|
||||
|
||||
CharAttributesList char_attributes; ///<文本属性
|
||||
ParagraphAttributesList paragraph_attributes; ///<段落属性
|
||||
|
||||
float max_width =0.0f; ///<最大宽度(<=0代表无限制)
|
||||
float max_height =0.0f; ///<最大高度(<=0代表无限制)
|
||||
uint8 text_direction =0; ///<文本排列方向
|
||||
TextAlign align =TextAlign::Left; ///<段落对齐
|
||||
float char_gap =0.0f; ///<字间距
|
||||
float line_gap =0.1f; ///<行间距(相对于字符高度)
|
||||
float paragraph_gap =1.0f; ///<段间距(相对于字符高度)
|
||||
|
||||
TextAttributes attributes; ///<文本属性
|
||||
float max_width =0.0f; ///<最大宽度(<=0代表无限制)
|
||||
float max_height =0.0f; ///<最大高度(<=0代表无限制)
|
||||
|
||||
bool border_symbols_disable =true; ///<边界符号禁用(如行首禁用逗号)
|
||||
// bool auto_symbols_convert =true; ///<自动符号转换(如tm/(r)/(c)等)
|
||||
|
||||
float space_size =0.5f; ///<半角空格尺寸(对应字符高度的系数)
|
||||
float full_space_size =1.0f; ///<全角空格尺寸(对应字符高度的系数)
|
||||
float tab_size =4.0f; ///<Tab符号尺寸(对应字符高度的系数)
|
||||
|
||||
bool compress_punctuation =false; ///<压缩标点符号
|
||||
};//struct TextLayoutAttributes
|
||||
|
||||
uint TextLayout(vulkan::Renderable *,const TextLayoutAttributes *,const uint max_chars,const UTF16String &);
|
||||
// uint TextLayout(vulkan::Renderable *,const TextLayoutAttributes *,const uint max_chars,const UTF16StringList &);
|
||||
int TextLayout(RenderableCreater *,const TextLayoutAttributes *,const int max_chars,const UTF16String &);
|
||||
|
||||
uint TextLayout(vulkan::Renderable *,const TextLayoutAttributes *,const uint max_chars,const UTF32String &);
|
||||
// uint TextLayout(vulkan::Renderable *,const TextLayoutAttributes *,const uint max_chars,const UTF32StringList &);
|
||||
int PlaneTextLayout(RenderableCreater *,FontSource *font_source,const int max_chars,const UTF16String &);
|
||||
}//namespace graph
|
||||
}//namespace hgl
|
||||
#endif//HGL_GRAPH_TEXT_LAYOUT_INCLUDE
|
||||
|
@ -48,24 +48,33 @@ SET(RENDERABLE_FILES ${ROOT_INCLUDE_PATH}/hgl/graph/RenderableCreater.h
|
||||
|
||||
SOURCE_GROUP("Renderable" FILES ${RENDERABLE_FILES})
|
||||
|
||||
file(GLOB FONT_HEADER ${ROOT_INCLUDE_PATH}/hgl/graph/font/*.*)
|
||||
SET(FONT_MANAGE_SOURCE ${ROOT_INCLUDE_PATH}/hgl/graph/font/Font.h
|
||||
${ROOT_INCLUDE_PATH}/hgl/graph/font/FontManage.h
|
||||
font/Font.cpp)
|
||||
|
||||
SET(FONT_SOURCE font/Font.cpp
|
||||
SET(FONT_SOURCE ${ROOT_INCLUDE_PATH}/hgl/graph/font/FontSource.h
|
||||
font/FontSource.cpp
|
||||
font/FontSourceSingle.cpp
|
||||
font/FontSourceMulti.cpp
|
||||
font/FontSourceManage.cpp
|
||||
font/TileFont.cpp)
|
||||
font/FontSourceManage.cpp)
|
||||
|
||||
SOURCE_GROUP("Font" FILES ${FONT_HEADER} ${FONT_SOURCE})
|
||||
SET(TILE_FONT_SOURCE ${ROOT_INCLUDE_PATH}/hgl/graph/font/TileFont.h
|
||||
font/TileFont.cpp)
|
||||
|
||||
SET(FONT_LAYOUT_SOURCE ${ROOT_INCLUDE_PATH}/hgl/graph/font/TextLayout.h
|
||||
font/TextLayout.cpp
|
||||
font/TextLayoutPlane.cpp)
|
||||
|
||||
SOURCE_GROUP("Font" FILES ${FONT_MANAGE_SOURCE})
|
||||
SOURCE_GROUP("Font\\Source" FILES ${FONT_SOURCE})
|
||||
SOURCE_GROUP("Font\\TileFont" FILES ${TILE_FONT_SOURCE})
|
||||
SOURCE_GROUP("Font\\Layout" FILES ${FONT_LAYOUT_SOURCE})
|
||||
|
||||
IF(WIN32)
|
||||
SET(FONT_SOURCE_OS font/FontSourceWin.cpp
|
||||
font/FontSourceWin.h)
|
||||
|
||||
SOURCE_GROUP("Font\\Windows" FILES ${FONT_SOURCE_OS})
|
||||
|
||||
SET(FONT_SOURCE ${FONT_SOURCE} ${FONT_SOURCE_OS})
|
||||
SOURCE_GROUP("Font\\Source\\Windows" FILES ${FONT_SOURCE_OS})
|
||||
ENDIF(WIN32)
|
||||
|
||||
SOURCE_GROUP("Header Files" FILES ${SCENE_GRAPH_HEADER})
|
||||
@ -83,5 +92,8 @@ add_cm_library(ULRE.SceneGraph "ULRE" ${SCENE_GRAPH_HEADER}
|
||||
|
||||
${RENDERABLE_FILES}
|
||||
|
||||
${FONT_HEADER}
|
||||
${FONT_SOURCE})
|
||||
${FONT_MANAGE_SOURCE}
|
||||
${FONT_SOURCE}
|
||||
${FONT_SOURCE_OS}
|
||||
${TILE_FONT_SOURCE}
|
||||
${FONT_LAYOUT_SOURCE})
|
||||
|
@ -39,7 +39,7 @@ namespace hgl
|
||||
|
||||
const int count=source_map.GetCount();
|
||||
|
||||
const auto **fsp=source_map.GetDataList();
|
||||
auto **fsp=source_map.GetDataList();
|
||||
|
||||
for(int i=0;i<count;i++)
|
||||
{
|
||||
|
@ -61,8 +61,6 @@ namespace hgl
|
||||
{
|
||||
hdc=CreateCompatibleDC(0);
|
||||
|
||||
CharHeight=fnt.height;
|
||||
|
||||
hfont=CreateFont( -fnt.height,
|
||||
fnt.width,
|
||||
0,
|
||||
@ -126,7 +124,7 @@ namespace hgl
|
||||
bmp->h=gm.gmBlackBoxY;
|
||||
|
||||
bmp->x=gm.gmptGlyphOrigin.x;
|
||||
bmp->y=fnt.height-gm.gmptGlyphOrigin.y-LineDistance;
|
||||
bmp->y=gm.gmptGlyphOrigin.y;
|
||||
|
||||
bmp->adv_x=gm.gmCellIncX;
|
||||
bmp->adv_y=gm.gmCellIncY;
|
||||
|
243
src/SceneGraph/font/TextLayout.cpp
Normal file
243
src/SceneGraph/font/TextLayout.cpp
Normal file
@ -0,0 +1,243 @@
|
||||
#include<hgl/graph/font/TextLayout.h>
|
||||
#include<hgl/type/Extent.h>
|
||||
#include<hgl/type/UnicodeBlocks.h>
|
||||
|
||||
namespace hgl
|
||||
{
|
||||
namespace graph
|
||||
{
|
||||
namespace
|
||||
{
|
||||
constexpr u16char BeginSymbols []=U16_TEXT("!),❟.:;?]}¨·ˇˉ―‖’❜”„❞…∶、。〃々❯〉》」』】〕〗!"'),.:;?]`|}~»›"); //行首禁用符号
|
||||
constexpr u16char EndSymbols []=U16_TEXT("([{·❛‘“‟❝❮〈《「『【〔〖(.[{«‹"); //行尾禁用符号
|
||||
constexpr u16char CurrencySymbols []=U16_TEXT("₳฿₿¢₡¢₢₵₫€££₤₣ƒ₲₭Ł₥₦₽₱$$₮ℳ₶₩₩¥¥₴₸¤₰៛₪₯₠₧﷼㍐원৳₹₨৲௹"); //货币符号
|
||||
constexpr u16char VRotateSymbols []=U16_TEXT("()[]{}〈〉《》「」『』【】〔〕〖〗()[]{}―‖…∶|~"); //竖排必须旋转的符号
|
||||
|
||||
constexpr int BeginSymbolsCount =sizeof(BeginSymbols) /sizeof(u16char);
|
||||
constexpr int EndSymbolsCount =sizeof(EndSymbols) /sizeof(u16char);
|
||||
constexpr int CurrencySymbolsCount=sizeof(CurrencySymbols)/sizeof(u16char);
|
||||
constexpr int VRotateSymbolsCount =sizeof(VRotateSymbols) /sizeof(u16char);
|
||||
|
||||
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; ///<竖排时是否需要旋转
|
||||
};//struct CharLayoutAttributes
|
||||
|
||||
/**
|
||||
* 4舍5入处理
|
||||
*/
|
||||
inline TEXT_COORD_TYPE out4in5(const double value)
|
||||
{
|
||||
return TEXT_COORD_TYPE(floor(value+0.5));
|
||||
}
|
||||
|
||||
template<typename T> class TextLayoutEngine
|
||||
{
|
||||
protected:
|
||||
|
||||
RenderableCreater *rc;
|
||||
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;
|
||||
|
||||
public:
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
const float origin_char_height=tla->font_source->GetCharHeight();
|
||||
|
||||
x=y=0;
|
||||
char_height =out4in5(origin_char_height);
|
||||
space_size =out4in5(origin_char_height*tla->space_size);
|
||||
full_space_size =out4in5(origin_char_height*tla->full_space_size);
|
||||
tab_size =out4in5(origin_char_height*tla->tab_size);
|
||||
char_gap =out4in5(origin_char_height*tla->char_gap);
|
||||
line_gap =out4in5(origin_char_height*tla->line_gap);
|
||||
line_height =out4in5(origin_char_height+line_gap);
|
||||
paragraph_gap =out4in5(origin_char_height*tla->paragraph_gap);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* 预处理所有的字符,获取所有字符的宽高,以及是否标点符号等信息
|
||||
*/
|
||||
int preprocess()
|
||||
{
|
||||
const int count=hgl_min(max_chars,origin_string.Length());
|
||||
|
||||
if(count<=0)
|
||||
return 0;
|
||||
|
||||
chars_attributes.SetCount(count);
|
||||
|
||||
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->begin_disable =hgl::strchr(BeginSymbols, *cp,BeginSymbolsCount );
|
||||
cla->end_disable =hgl::strchr(EndSymbols, *cp,EndSymbolsCount );
|
||||
|
||||
if(!cla->end_disable) //货币符号同样行尾禁用
|
||||
cla->end_disable =hgl::strchr(CurrencySymbols,*cp,CurrencySymbolsCount );
|
||||
|
||||
cla->vrotate =hgl::strchr(VRotateSymbols,*cp,VRotateSymbolsCount );
|
||||
|
||||
cla->is_cjk =isCJK(*cp);
|
||||
cla->is_emoji =isEmoji(*cp);
|
||||
|
||||
cla->is_punctuation =isPunctuation(*cp);
|
||||
}
|
||||
|
||||
++cp;
|
||||
++cla;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串断成多行,处理标点禁用,以及英文单词禁拆分
|
||||
*/
|
||||
bool h_splite_to_lines(float view_limit)
|
||||
{
|
||||
const int count=chars_attributes.GetCount();
|
||||
const CLA *cla=chars_attributes.GetData();
|
||||
|
||||
int cur_size=0;
|
||||
|
||||
for(int i=0;i<count;i++)
|
||||
{
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool v_splite_to_lines(float view_limit)
|
||||
{
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
int layout(const int mc,const BaseString<T> &str)
|
||||
{
|
||||
if(mc<=0
|
||||
||!str
|
||||
||!(*str))
|
||||
return(-1);
|
||||
|
||||
max_chars=mc;
|
||||
origin_string=str;
|
||||
|
||||
if(preprocess()<=0)
|
||||
return(-3);
|
||||
|
||||
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;
|
||||
}
|
||||
};//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 hgl
|
21
src/SceneGraph/font/TextLayoutPlane.cpp
Normal file
21
src/SceneGraph/font/TextLayoutPlane.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include<hgl/graph/font/TextLayout.h>
|
||||
|
||||
namespace hgl
|
||||
{
|
||||
namespace graph
|
||||
{
|
||||
/**
|
||||
* 平面文本排版
|
||||
*/
|
||||
int PlaneTextLayout(RenderableCreater *rc,FontSource *font_source,const int max_chars,const UTF16String &str)
|
||||
{
|
||||
if(!rc
|
||||
||!font_source
|
||||
||max_chars<=0
|
||||
||str.IsEmpty())
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
}//namespace graph
|
||||
}//namespace hgl
|
Loading…
x
Reference in New Issue
Block a user