From 7a8cabb6256f8ba45a3282dbbf4ce21189e0644c Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Mon, 30 Sep 2013 00:06:39 +0200 Subject: [PATCH] [DEV] dynamic font add elements and support multyple language --- external/egami | 2 +- external/etk | 2 +- sources/ewol/compositing/Text.cpp | 8 +- sources/ewol/resources/TexturedFont.cpp | 240 +++++++++----------- sources/ewol/resources/TexturedFont.h | 9 +- sources/ewol/resources/font/GlyphProperty.h | 23 +- 6 files changed, 144 insertions(+), 140 deletions(-) diff --git a/external/egami b/external/egami index a2ec749e..9ab5eea1 160000 --- a/external/egami +++ b/external/egami @@ -1 +1 @@ -Subproject commit a2ec749e8e34a40de57c714117dbaa4d0272de11 +Subproject commit 9ab5eea1f349fdae52932508d108d2e954813bad diff --git a/external/etk b/external/etk index e443c8a4..78d09864 160000 --- a/external/etk +++ b/external/etk @@ -1 +1 @@ -Subproject commit e443c8a405d4b10febcd0d22d7ab4b7ce34fbd6d +Subproject commit 78d0986454e70b2292984f15e66ffe4c5c146d31 diff --git a/sources/ewol/compositing/Text.cpp b/sources/ewol/compositing/Text.cpp index b09cf3d8..a719c08f 100644 --- a/sources/ewol/compositing/Text.cpp +++ b/sources/ewol/compositing/Text.cpp @@ -739,7 +739,7 @@ void ewol::Text::Print(const etk::UniChar& _charcode) return; } // get a pointer on the glyph property : - ewol::GlyphProperty * myGlyph = m_font->GetGlyphPointer(_charcode, m_mode); + ewol::GlyphProperty* myGlyph = m_font->GetGlyphPointer(_charcode, m_mode); if (NULL==myGlyph) { EWOL_ERROR(" font does not really existed ..."); return; @@ -756,7 +756,7 @@ void ewol::Text::Print(const etk::UniChar& _charcode) } } // 0x01 == 0x20 == ' '; - if (_charcode != 0x01) { + if (_charcode.Get() != 0x01) { /* Bitmap position * xA xB * yC *------* @@ -770,9 +770,9 @@ void ewol::Text::Print(const etk::UniChar& _charcode) float dyD = dyC - myGlyph->m_sizeTexture.y(); float tuA = myGlyph->m_texturePosStart.x(); - float tuB = myGlyph->m_texturePosStop.x(); + float tuB = tuA + myGlyph->m_texturePosSize.x(); float tvC = myGlyph->m_texturePosStart.y(); - float tvD = myGlyph->m_texturePosStop.y(); + float tvD = tvC + myGlyph->m_texturePosSize.y(); // Clipping and drawing area diff --git a/sources/ewol/resources/TexturedFont.cpp b/sources/ewol/resources/TexturedFont.cpp index 6b566ce8..91b0665f 100644 --- a/sources/ewol/resources/TexturedFont.cpp +++ b/sources/ewol/resources/TexturedFont.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -42,33 +43,6 @@ etk::CCout& ewol::operator <<(etk::CCout& _os, const ewol::font::mode_te& _obj) #undef __class__ #define __class__ "TexturedFont" -static int32_t nextP2(int32_t value) -{ - int32_t val=1; - for (int32_t iii=1; iii<31; iii++) { - if (value <= val) { - return val; - } - val *=2; - } - EWOL_CRITICAL("impossible CASE.... request power 2 of "<< value); - return val; -} - -static int32_t simpleSQRT(int32_t value) -{ - int32_t val=1; - for (int32_t iii=1; iii<1000; iii++) { - val =iii*iii; - if (value <= val) { - return iii; - } - } - EWOL_CRITICAL("impossible CASE...."); - return val; -} - - ewol::TexturedFont::TexturedFont(etk::UString fontName) : ewol::Texture(fontName) { @@ -82,10 +56,10 @@ ewol::TexturedFont::TexturedFont(etk::UString fontName) : m_modeWraping[2] = ewol::font::Regular; m_modeWraping[3] = ewol::font::Regular; - m_lastGlyphPos[0].setValue(0,0); - m_lastGlyphPos[1].setValue(0,0); - m_lastGlyphPos[2].setValue(0,0); - m_lastGlyphPos[3].setValue(0,0); + m_lastGlyphPos[0].setValue(1,1); + m_lastGlyphPos[1].setValue(1,1); + m_lastGlyphPos[2].setValue(1,1); + m_lastGlyphPos[3].setValue(1,1); m_lastRawHeigh[0] = 0; m_lastRawHeigh[1] = 0; @@ -215,104 +189,34 @@ ewol::TexturedFont::TexturedFont(etk::UString fontName) : } EWOL_INFO("Load FONT [" << iiiFontId << "] name : \"" << m_fileName[iiiFontId] << "\" ==> size=" << m_size); m_font[iiiFontId] = ewol::FontFreeType::Keep(m_fileName[iiiFontId]); - if (NULL == m_font[iiiFontId]) { - return; + if (m_font[iiiFontId] == NULL) { + EWOL_DEBUG("error in loading FONT [" << iiiFontId << "] name : \"" << m_fileName[iiiFontId] << "\" ==> size=" << m_size ); } - + } + for (int32_t iiiFontId=0; iiiFontId<4 ; iiiFontId++) { // set the bassic charset: m_listElement[iiiFontId].Clear(); - GlyphProperty tmpchar1; - tmpchar1.m_UVal = 0; - m_listElement[iiiFontId].PushBack(tmpchar1); - for (int32_t iii=0x20; iii<0xFF; iii++) { - GlyphProperty tmpchar; - tmpchar.m_UVal = iii; - m_listElement[iiiFontId].PushBack(tmpchar); - if (0x7F == iii) { - iii = 0x9F; - } - } - - /* this is a bad code for now ... */ - // ==> determine the texture Size - GlyphProperty tmpproperty; - tmpproperty.m_UVal = 'A'; - m_font[iiiFontId]->GetGlyphProperty(m_size, tmpproperty); - - int32_t nbElement = 0xFF - 0x20 + 1; - int32_t coter = simpleSQRT(nbElement); - // note : +1 is for the overlapping of the glyph (Part 1) - int32_t glyphMaxWidth = tmpproperty.m_advance.x() +1; - int32_t glyphMaxHeight = tmpproperty.m_advance.y() +1; - int32_t textureWidth = nextP2(coter*glyphMaxWidth); - int32_t nbRaws = textureWidth / glyphMaxWidth; - if (nbRaws <= 0) { - EWOL_ERROR("devide by 0"); - nbRaws = 1; - } - int32_t nbLine = (nbElement / nbRaws) + 1; - int32_t textureHeight = nextP2(nbLine*glyphMaxHeight); - // for android : - textureHeight = etk_max(textureHeight, textureWidth); - textureWidth = textureHeight; - - if (iiiFontId == 0) { - EWOL_DEBUG("Generate a text texture for char(" << nbRaws << "," << nbLine << ") with size=(" << textureWidth << "," << textureHeight << ")"); - // resize must be done on the texture ... - SetImageSize(ivec2(textureWidth,textureHeight)); - // now we can acces directly on the image - m_data.Clear(etk::Color<>(0x00000000)); + if (m_font[iiiFontId] == NULL) { + continue; } m_height[iiiFontId] = m_font[iiiFontId]->GetHeight(m_size); - - int32_t CurrentLineHigh = 0; - ivec2 glyphPosition(1,1); - for (int32_t iii=0; iiiGetGlyphProperty(m_size, (m_listElement[iiiFontId])[iii])) { - // change line if needed ... - if (glyphPosition.x()+(m_listElement[iiiFontId])[iii].m_sizeTexture.x() > textureWidth) { - glyphPosition.setX(0); - glyphPosition.setY(glyphPosition.y()+CurrentLineHigh); - CurrentLineHigh = 0; - } - // draw the glyph - m_font[iiiFontId]->DrawGlyph(m_data, m_size, glyphPosition, (m_listElement[iiiFontId])[iii], iiiFontId); - // set video position - (m_listElement[iiiFontId])[iii].m_texturePosStart.setValue( (float)(glyphPosition.x()) / (float)textureWidth, - (float)(glyphPosition.y()) / (float)textureHeight ); - (m_listElement[iiiFontId])[iii].m_texturePosStop.setValue( (float)(glyphPosition.x() + (m_listElement[iiiFontId])[iii].m_sizeTexture.x()) / (float)textureWidth, - (float)(glyphPosition.y() + (m_listElement[iiiFontId])[iii].m_sizeTexture.y()) / (float)textureHeight ); - - // update the maximum of the line hight : - if (CurrentLineHigh<(m_listElement[iiiFontId])[iii].m_sizeTexture.y()) { - // note : +1 is for the overlapping of the glyph (Part 2) - CurrentLineHigh = (m_listElement[iiiFontId])[iii].m_sizeTexture.y()+1; - } - // note : +1 is for the overlapping of the glyph (Part 3) - // update the Bitmap position drawing : - glyphPosition.setX(glyphPosition.x() + (m_listElement[iiiFontId])[iii].m_sizeTexture.x()+1); - } - - } - //m_font[iiiFontId]->Display(); - // generate the kerning for all the characters : - m_font[iiiFontId]->GenerateKerning(m_size, m_listElement[iiiFontId]); + // TODO : basic font use 512 is better ... ==> maybe estimate it with the dpi ??? + SetImageSize(ivec2(256,32)); + // now we can acces directly on the image + m_data.Clear(etk::Color<>(0x00000000)); } - // For testing cheree the box are set) - #if 0 - draw::Color tlpppp(0xFF,0xFF,0xFF,0x00); - for(int32_t jjj=0; jjj < textureHeight;jjj++) { - for(int32_t iii=0; iii < textureWidth; iii++){ - tlpppp = m_data.Get(ivec2(iii, jjj) ); - // set only alpha : - tlpppp.a = etk_min( tlpppp.a+0x60, 0xFF); - // real set of color - m_data.Set(ivec2(iii, jjj), tlpppp ); - } + // Add error glyph + { + etk::UniChar tmpchar; + tmpchar.Set(0); + AddGlyph(tmpchar); + } + // by default we set only the first AINSI char availlable + for (int32_t iii=0x20; iii<0x7F; iii++) { + etk::UniChar tmpchar; + tmpchar.Set(iii); + AddGlyph(tmpchar); } - #endif - EWOL_DEBUG("End generation of the Fond bitmap, start adding texture"); - //m_data.DistanceField(); Flush(); EWOL_DEBUG("Wrapping properties : "); EWOL_DEBUG(" " << ewol::font::Regular << "==>" << GetWrappingMode(ewol::font::Regular)); @@ -328,6 +232,75 @@ ewol::TexturedFont::~TexturedFont(void) } } +bool ewol::TexturedFont::AddGlyph(const etk::UniChar& _val) +{ + bool hasChange = false; + // for each font : + for (int32_t iii=0; iii<4 ; iii++) { + if (m_font[iii] == NULL) { + continue; + } + // add the curent "char" + GlyphProperty tmpchar; + tmpchar.m_UVal = _val; + + if (true == m_font[iii]->GetGlyphProperty(m_size, tmpchar)) { + //EWOL_DEBUG("load char : '" << _val << "'=" << _val.Get()); + hasChange = true; + // change line if needed ... + if (m_lastGlyphPos[iii].x()+tmpchar.m_sizeTexture.x() > m_data.GetSize().x()) { + m_lastGlyphPos[iii].setX(1); + m_lastGlyphPos[iii] += ivec2(0, m_lastRawHeigh[iii]); + m_lastRawHeigh[iii] = 0; + } + while(m_lastGlyphPos[iii].y()+tmpchar.m_sizeTexture.y() > m_data.GetSize().y()) { + ivec2 size = m_data.GetSize(); + size.setY(size.y()*2); + m_data.Resize(size, etk::Color<>(0)); + // note : need to rework all the lyer due to the fact that the texture is used by the faur type... + for (int32_t kkk=0; kkk<4 ; kkk++) { + // change the coordonate on the element in the texture + for (int32_t jjj=0 ; jjjDrawGlyph(m_data, m_size, m_lastGlyphPos[iii], tmpchar, iii); + // set video position + tmpchar.m_texturePosStart.setValue( (float)m_lastGlyphPos[iii].x() / (float)m_data.GetSize().x(), + (float)m_lastGlyphPos[iii].y() / (float)m_data.GetSize().y() ); + tmpchar.m_texturePosSize.setValue( (float)tmpchar.m_sizeTexture.x() / (float)m_data.GetSize().x(), + (float)tmpchar.m_sizeTexture.y() / (float)m_data.GetSize().y() ); + + // update the maximum of the line hight : + if (m_lastRawHeigh[iii] wrapping index : " << m_modeWraping[_displayMode]); int32_t index = GetIndex(_charcode, _displayMode); - if( index <0 - || index >=m_listElement[_displayMode].Size() ) { + if( index < 0 + || index >= m_listElement[_displayMode].Size() ) { EWOL_ERROR(" Try to get glyph index inexistant ... ==> return the index 0 ... id=" << index); if (m_listElement[_displayMode].Size()>=0) { return &((m_listElement[_displayMode])[0]); diff --git a/sources/ewol/resources/TexturedFont.h b/sources/ewol/resources/TexturedFont.h index 6712381a..94fb7aae 100644 --- a/sources/ewol/resources/TexturedFont.h +++ b/sources/ewol/resources/TexturedFont.h @@ -67,7 +67,7 @@ namespace ewol * @param[in] displayMode Mode to display the currrent font * @return The ID in the table (if it does not exist : return 0) */ - int32_t GetIndex(const uniChar_t& charcode, const ewol::font::mode_te displayMode) const; + int32_t GetIndex(const uniChar_t& charcode, const ewol::font::mode_te displayMode); /** * @brief Get the pointer on the coresponding glyph * @param[in] charcode The unicodeValue @@ -95,6 +95,13 @@ namespace ewol * @param[in,out] reference on the object pointer */ static void Release(ewol::TexturedFont*& _object); + private: + /** + * @brief Add a glyph in a texture font. + * @param[in] _val Char value to add. + * @return true if the image size have change, false otherwise + */ + bool AddGlyph(const etk::UniChar& _val); }; diff --git a/sources/ewol/resources/font/GlyphProperty.h b/sources/ewol/resources/font/GlyphProperty.h index 739b4fc4..29924861 100644 --- a/sources/ewol/resources/font/GlyphProperty.h +++ b/sources/ewol/resources/font/GlyphProperty.h @@ -53,23 +53,27 @@ namespace ewol { public: uniChar_t m_UVal; //!< Unicode value + private: + bool m_exist; + public: int32_t m_glyphIndex; //!< Glyph index in the system ivec2 m_sizeTexture; //!< size of the element to display ivec2 m_bearing; //!< offset to display the data (can be negatif id the texture sise is bigger than the theoric places in the string) ivec2 m_advance; //!< space use in the display for this specific char vec2 m_texturePosStart; //!< Texture normalised position (START) - vec2 m_texturePosStop; //!< Texture normalised position (STOP) + vec2 m_texturePosSize; //!< Texture normalised position (SIZE) private: etk::Vector m_kerning; //!< kerning values of link of all elements public: GlyphProperty(void) : m_UVal(0), + m_exist(true), m_glyphIndex(0), m_sizeTexture(0,0), m_bearing(0,0), m_advance(0,0), m_texturePosStart(0,0), - m_texturePosStop(0,0) + m_texturePosSize(0,0) { }; float KerningGet(const uniChar_t charcode) { @@ -79,15 +83,24 @@ namespace ewol } } return 0; - } + }; void KerningAdd(const uniChar_t charcode, float value) { m_kerning.PushBack(ewol::Kerning(charcode, value)); - } + }; void KerningClear(void) { m_kerning.Clear(); - } + }; + /** + * @brief Get the status of the char, if it exist or not in the FONT + * @return true if the char is availlable, false otherwise + */ + bool Exist(void) const { return m_exist; }; + /** + * @brief Set the element doen not exist !!! + */ + void SetNotExist(void) { m_exist = false; }; }; };