[DEV] Parse decorated text like a html page

This commit is contained in:
Edouard DUPIN 2012-11-20 21:56:12 +01:00
parent f848ee4ce0
commit c3dde8d2ac
5 changed files with 247 additions and 43 deletions

2
build

@ -1 +1 @@
Subproject commit 606c90b3685e5be82c055e337f11f764f6be7d55
Subproject commit 1b6659890d1ce315d52398954f77966c72a7fc99

View File

@ -466,6 +466,11 @@ void ewol::Drawing::LineTo(etk::Vector3D<float> dest)
m_position = dest;
}
void ewol::Drawing::LineRel(etk::Vector3D<float> vect)
{
LineTo(m_position+vect);
}
void ewol::Drawing::Rectangle(etk::Vector3D<float> dest)
{

View File

@ -138,6 +138,11 @@ namespace ewol
* @param[in] dest Position of the end of the line.
*/
void LineTo(etk::Vector3D<float> dest);
/**
* @brief Relative drawing a line (spacial vector)
* @param[in] vect Vector of the curent line.
*/
void LineRel(etk::Vector3D<float> vect);
/**
* @brief Draw a 2D rectangle to the position requested.
* @param[in] dest Position the the end of the rectangle

View File

@ -10,6 +10,7 @@
#include <ewol/Debug.h>
#include <ewol/compositing/Text.h>
#include <ewol/font/FontManager.h>
#include <tinyXML/tinyxml.h>
/*
@ -178,6 +179,8 @@ void ewol::Text::Clear(void)
m_startTextpos = 0;
m_stopTextPos = 0;
m_alignement = ewol::Text::alignDisable;
m_htmlCurrrentLine = "";
m_htmlDecoration.Clear();
}
@ -304,6 +307,12 @@ void ewol::Text::SetFontMode(ewol::font::mode_te mode)
}
ewol::font::mode_te ewol::Text::GetFontMode(void)
{
return m_mode;
}
void ewol::Text::SetFontBold(bool status)
{
if (true == status) {
@ -363,10 +372,111 @@ void ewol::Text::Print(const etk::UString& text)
}
void ewol::Text::PrintDecorated(const etk::UString& text)
void ewol::Text::ParseHtmlNode(void* element2)
{
EWOL_TODO("The Decorated print is not supported now ...");
Print(text);
TiXmlNode* element = static_cast<TiXmlNode*>(element2);
if (NULL != element) {
/*const char *myData = element->ToElement()->GetText();
if (NULL != myData) {
etk::UString outputData(myData);
Print(myData);
} else {
*/
for (TiXmlNode * child = element->FirstChild(); NULL != child ; child = child->NextSibling() ) {
if (child->Type()==TiXmlNode::TINYXML_COMMENT) {
// nothing to do ...
} else if (child->Type()==TiXmlNode::TINYXML_TEXT) {
HtmlAddData(child->Value() );
} else if (!strcmp(child->Value(), "br")) {
HtmlFlush();
ForceLineReturn();
} else if (!strcmp(child->Value(), "font")) {
TextDecoration tmpDeco = m_htmlDecoTmp;
const char *colorValue = child->ToElement()->Attribute("color");
if (NULL != colorValue) {
draw::ParseColor(colorValue, m_htmlDecoTmp.m_colorFg);
}
colorValue = child->ToElement()->Attribute("colorBg");
if (NULL != colorValue) {
draw::ParseColor(colorValue, m_htmlDecoTmp.m_colorBg);
}
ParseHtmlNode(child);
m_htmlDecoTmp = tmpDeco;
} else if (!strcmp(child->Value(), "b")) {
TextDecoration tmpDeco = m_htmlDecoTmp;
if (m_htmlDecoTmp.m_mode == ewol::font::Regular) {
m_htmlDecoTmp.m_mode = ewol::font::Bold;
} else if (m_htmlDecoTmp.m_mode == ewol::font::Italic) {
m_htmlDecoTmp.m_mode = ewol::font::BoldItalic;
}
ParseHtmlNode(child);
m_htmlDecoTmp = tmpDeco;
} else if (!strcmp(child->Value(), "i")) {
TextDecoration tmpDeco = m_htmlDecoTmp;
if (m_htmlDecoTmp.m_mode == ewol::font::Regular) {
m_htmlDecoTmp.m_mode = ewol::font::Italic;
} else if (m_htmlDecoTmp.m_mode == ewol::font::Bold) {
m_htmlDecoTmp.m_mode = ewol::font::BoldItalic;
}
ParseHtmlNode(child);
m_htmlDecoTmp = tmpDeco;
} else if (!strcmp(child->Value(), "u")) {
ParseHtmlNode(child);
} else if (!strcmp(child->Value(), "p")) {
HtmlFlush();
m_alignement = ewol::Text::alignLeft;
ForceLineReturn();
ParseHtmlNode(child);
ForceLineReturn();
} else if (!strcmp(child->Value(), "center")) {
HtmlFlush();
m_alignement = ewol::Text::alignCenter;
ParseHtmlNode(child);
} else if (!strcmp(child->Value(), "left")) {
HtmlFlush();
m_alignement = ewol::Text::alignLeft;
ParseHtmlNode(child);
} else if (!strcmp(child->Value(), "right")) {
HtmlFlush();
m_alignement = ewol::Text::alignRight;
ParseHtmlNode(child);
} else if (!strcmp(child->Value(), "justify")) {
HtmlFlush();
m_alignement = ewol::Text::alignJustify;
ParseHtmlNode(child);
} else {
EWOL_ERROR("(l "<< child->Row() << ") node not suported type : " << child->Type() << " val=\""<< child->Value() << "\"" );
}
//}
}
}
}
void ewol::Text::PrintDecorated(etk::UString& text)
{
TiXmlDocument XmlDocument;
// reset parameter :
m_htmlDecoTmp.m_colorBg = draw::color::none;
m_htmlDecoTmp.m_colorFg = draw::color::black;
m_htmlDecoTmp.m_mode = ewol::font::Regular;
// load the XML from the memory
bool loadError = XmlDocument.Parse((const char*)text.c_str(), 0, TIXML_ENCODING_UTF8);
if (false == loadError) {
EWOL_ERROR( "can not load Hightlight XML: PARSING error: Decorated text ");
return;
}
TiXmlElement* root = XmlDocument.FirstChildElement( "html" );
if (NULL == root) {
EWOL_ERROR( "can not load Hightlight XML: main node not find: \"html\"");
return;
}
TiXmlElement* bodyNode = root->FirstChildElement( "body" );
ParseHtmlNode(bodyNode);
HtmlFlush();
}
@ -395,6 +505,10 @@ void ewol::Text::Print(const etk::UString& text, const etk::Vector<TextDecoratio
}
}
} else {
// special start case at the right of the endpoint :
if (m_stopTextPos <= m_position.x) {
ForceLineReturn();
}
float basicSpaceWidth = CalculateSize(' ').x;
int32_t currentId = 0;
int32_t stop;
@ -439,12 +553,16 @@ void ewol::Text::Print(const etk::UString& text, const etk::Vector<TextDecoratio
}
// special for the justify mode
if (text[iii] == (uniChar_t)' ') {
m_vectorialDraw.SetPos(m_position);
if (m_colorBg.a != 0) {
m_vectorialDraw.SetPos(m_position);
}
// Must generate a dynamic space :
SetPos(etk::Vector3D<float>(m_position.x + interpolation,
m_position.y,
m_position.z) );
m_vectorialDraw.RectangleWidth(etk::Vector3D<float>(interpolation,fontHeigh,0.0f) );
if (m_colorBg.a != 0) {
m_vectorialDraw.RectangleWidth(etk::Vector3D<float>(interpolation,fontHeigh,0.0f) );
}
} else {
if (m_colorBg.a != 0) {
etk::Vector3D<float> pos = m_position;
@ -460,6 +578,10 @@ void ewol::Text::Print(const etk::UString& text, const etk::Vector<TextDecoratio
currentId++;
} else if(text[stop] == (uniChar_t)' ') {
currentId = stop+1;
// Reset position :
SetPos(etk::Vector3D<float>(m_startTextpos,
(float)(m_position.y - m_font->GetHeight(m_mode)),
m_position.z) );
} else if(text[stop] == (uniChar_t)'\n') {
currentId = stop+1;
// Reset position :
@ -619,20 +741,6 @@ void ewol::Text::Print(const uniChar_t charcode)
m_coordColor.PushBack(m_color);
m_coordColor.PushBack(m_color);
m_coordColor.PushBack(m_color);
/*
if (m_colorBg.a != 0) {
m_vectorialDraw.SetPos();
// set display positions :
m_coordBg.PushBack(bitmapDrawPos[0]);
m_coordBg.PushBack(bitmapDrawPos[1]);
m_coordBg.PushBack(bitmapDrawPos[2]);
// set the color
m_coordColorBg.PushBack(m_colorBg);
m_coordColorBg.PushBack(m_colorBg);
m_coordColorBg.PushBack(m_colorBg);
}
*/
/* Step 2 :
*
* **
@ -652,18 +760,6 @@ void ewol::Text::Print(const uniChar_t charcode)
m_coordColor.PushBack(m_color);
m_coordColor.PushBack(m_color);
m_coordColor.PushBack(m_color);
/*
if (m_colorBg.a != 0) {
// set display positions :
m_coordBg.PushBack(bitmapDrawPos[0]);
m_coordBg.PushBack(bitmapDrawPos[2]);
m_coordBg.PushBack(bitmapDrawPos[3]);
// set the color
m_coordColorBg.PushBack(m_colorBg);
m_coordColorBg.PushBack(m_colorBg);
m_coordColorBg.PushBack(m_colorBg);
}
*/
}
}
}
@ -683,7 +779,7 @@ void ewol::Text::ForceLineReturn(void)
}
void ewol::Text::SetTextAlignement(float startTextpos, float stopTextPos, aligneMode_te alignement)
void ewol::Text::SetTextAlignement(float startTextpos, float stopTextPos, ewol::Text::aligneMode_te alignement)
{
m_startTextpos = startTextpos;
m_stopTextPos = stopTextPos;
@ -694,6 +790,12 @@ void ewol::Text::SetTextAlignement(float startTextpos, float stopTextPos, aligne
}
ewol::Text::aligneMode_te ewol::Text::GetAlignement(void)
{
return m_alignement;
}
void ewol::Text::DisableAlignement(void)
{
m_alignement = ewol::Text::alignDisable;
@ -741,6 +843,19 @@ etk::Vector3D<float> ewol::Text::CalculateSize(const uniChar_t charcode)
}
void ewol::Text::PrintCursor(bool isInsertMode)
{
int32_t fontHeigh = m_font->GetHeight(m_mode);
if (true == isInsertMode) {
m_vectorialDraw.RectangleWidth(etk::Vector3D<float>(20, fontHeigh, 0) );
} else {
m_vectorialDraw.SetThickness(2);
m_vectorialDraw.LineRel( etk::Vector3D<float>(0, fontHeigh, 0) );
m_vectorialDraw.SetThickness(0);
}
}
bool ewol::Text::ExtrapolateLastId(const etk::UString& text, const int32_t start, int32_t& stop, int32_t& space, int32_t& freeSpace)
{
// store previous :
@ -794,4 +909,30 @@ bool ewol::Text::ExtrapolateLastId(const etk::UString& text, const int32_t start
}
}
void ewol::Text::HtmlAddData(etk::UString data)
{
if( m_htmlCurrrentLine.Size()>0
&& m_htmlCurrrentLine[m_htmlCurrrentLine.Size()-1] != ' ') {
m_htmlCurrrentLine+=" ";
if(m_htmlDecoration.Size()>0) {
TextDecoration tmp = m_htmlDecoration[m_htmlDecoration.Size()-1];
m_htmlDecoration.PushBack(tmp);
} else {
m_htmlDecoration.PushBack(m_htmlDecoTmp);
}
}
m_htmlCurrrentLine += data;
for(int32_t iii=0; iii<data.Size() ; iii++) {
m_htmlDecoration.PushBack(m_htmlDecoTmp);
}
}
void ewol::Text::HtmlFlush(void)
{
if (m_htmlCurrrentLine.Size()>0) {
Print(m_htmlCurrrentLine, m_htmlDecoration);
}
m_htmlCurrrentLine = "";
m_htmlDecoration.Clear();
}

View File

@ -185,6 +185,11 @@ namespace ewol
* @param[in] mode The font mode requested
*/
void SetFontMode(ewol::font::mode_te mode);
/**
* @brief Get the current font mode
* @return The font mode applied
*/
ewol::font::mode_te GetFontMode(void);
/**
* @brief Enable or disable the bold mode
* @param[in] status The new status for this display property
@ -212,18 +217,37 @@ namespace ewol
*/
void Print(const etk::UString& text);
/**
* @brief Display a compleat string in the current element with the generic decoration specification.
* \<b\> ... \</b\> For bold text.
* \<i\> ... \</i\> For italic text.
* \<color="#54325165"\> ... \</color\> To specify a color.
* \<left\> ... \</left\> To align left.
* \<right\> ... \</right\> To align right.
* \<center\> ... \</center\> To align center.
* \<justify\> ... \</justify\> To align justify.
* @brief Display a compleat string in the current element with the generic decoration specification. (basic html data)
* <pre>
* <html>
* <body>
* <br/>
* <br/><br/><br/>
* <center>
* text exemple <b>in bold</b> other text <b>bold part <i>boldItalic part</i></b> an other thext
* <font color=\"#FF0000\">colored text <b>bold color text</b> <i>bold italic text</i> normal color text</font> the end of the string<br/>
* an an other thext
* </center>
* <br/><br/><br/>
* <left>
* plop 1
* </left>
* <br/><br/><br/>
* <right>
* plop 2
* </right>
* <br/><br/><br/>
* <justify>
* Un exemple de text
* </justify>
* </body>
* </html>
* </pre>
* @note This is parsed with tiny xml, then be carfull that the XML is correct, and all balises are closed ... otherwite the display can not be done
* @param[in] text The string to display.
* @TODO : implementation not done ....
*/
void PrintDecorated(const etk::UString& text);
void PrintDecorated(etk::UString& text);
/**
* @brief Display a compleat string in the current element whith specific decorations (advence mode).
* @param[in] text The string to display.
@ -239,6 +263,11 @@ namespace ewol
* @brief This Generate the line return ==> it return to the alignement position start and at the correct line position ==> it might be use to not know the line height
*/
void ForceLineReturn(void);
/**
* @brief This parse a tinyXML node (void pointer to permit to hide tiny XML in include)
* @param[in] element the tynyXML element : TiXmlNode*
*/
void ParseHtmlNode( void* element);
/**
* @brief This generate the possibility to generate the big text property
* @param[in] startTextpos The x text start position of the display.
@ -246,11 +275,16 @@ namespace ewol
* @param[in] alignement mode of alignement for the Text.
* @note The text align in center change of line every display done (even if it was just a char)
*/
void SetTextAlignement(float startTextpos, float stopTextPos, aligneMode_te alignement);
void SetTextAlignement(float startTextpos, float stopTextPos, ewol::Text::aligneMode_te alignement);
/**
* @brief Disable the alignement system
*/
void DisableAlignement(void);
/**
* @brief Get the current alignement property
* @return the curent alignement type
*/
ewol::Text::aligneMode_te GetAlignement(void);
/**
* @brief Calculate a theoric text size
* @param[in] text The string to calculate dimention.
@ -263,6 +297,11 @@ namespace ewol
* @return The theoric size used.
*/
etk::Vector3D<float> CalculateSize(const uniChar_t charcode);
/**
* @brief Draw a cursor at the specify position
* @param[in] isInsertMode True if the insert mode is activated
*/
void PrintCursor(bool isInsertMode);
private:
/**
* @brief Calculate the element number that is the first out the alignement range
@ -275,6 +314,20 @@ namespace ewol
* @return true if the rifht has free space that can be use for jystify (return false if we find \n
*/
bool ExtrapolateLastId(const etk::UString& text, const int32_t start, int32_t& stop, int32_t& space, int32_t& freeSpace);
private:
// this section is reserved for HTML parsing and display:
etk::UString m_htmlCurrrentLine; //!< current line for HTML display
etk::Vector<TextDecoration> m_htmlDecoration; //!< current decoration for the HTML display
TextDecoration m_htmlDecoTmp; //!< current decoration
/**
* @brief add a line with the current m_htmlDecoTmp decoration
* @param[in] the cuurent data to add.
*/
void HtmlAddData(etk::UString data);
/**
* @brief Draw the current line
*/
void HtmlFlush(void);
};
};