diff --git a/sources/ewol/font/Font.h b/sources/ewol/font/Font.h index c17d5f80..3428a117 100644 --- a/sources/ewol/font/Font.h +++ b/sources/ewol/font/Font.h @@ -14,77 +14,34 @@ #include #include #include +#include namespace ewol { - /* - | | | | - | | | | - | | | | - Y | | | | - ^ |------------| |------------| - | - m_advance.y:/-> | - | | - | | - m_sizeTex.x/-> | | |------------| |------------| - | | | | | | | - | | | | | | | - | | | | | | | - | | | | | | | - | | | | A | | G | - | | | | | | | - | | | | | | | - | | | | | | | - | | | | | | | - \-> | | |------------| |------------| - /--> | | - \--> \-> | - m_bearing.y | - |____*________________________*____________>> X - - - <------------------------> : m_advance.x - - <------------> : m_sizeTexture.x - - <---> : m_bearing.x - - */ - typedef struct { - uniChar_t m_UVal; // Unicode value - int32_t m_glyphIndex; // Glyph index in the system - etk::Vector2D m_sizeTexture; // size of the element to display - etk::Vector2D m_bearing; // offset to display the data (can be negatif id the texture sise is bigger than the théoric places in the string) - etk::Vector2D m_advance; // space use in the display for this specific char - } GlyphProperty; - class Font : public ewol::Resource { public: Font(etk::UString fontName) : ewol::Resource(fontName) {}; + virtual ~Font(void) {}; + const char* GetType(void) { return "ewol::Font"; }; - virtual int32_t Draw(draw::Image& imageOut, - int32_t fontSize, - etk::Vector2D textPos, - const etk::UString& unicodeString, - draw::Color& textColor) = 0; - virtual int32_t Draw(draw::Image& imageOut, - int32_t fontSize, - etk::Vector2D textPos, - const uniChar_t unicodeChar, - draw::Color& textColor) = 0; + virtual bool GetGlyphProperty(int32_t fontSize, ewol::GlyphProperty& property) = 0; + virtual bool DrawGlyph(draw::Image& imageOut, int32_t fontSize, etk::Vector2D glyphPosition, ewol::GlyphProperty& property, int8_t posInImage) = 0; + virtual etk::Vector2D GetSize(int32_t fontSize, const etk::UString & unicodeString) = 0; + virtual int32_t GetHeight(int32_t fontSize) = 0; + + virtual void GenerateKerning(int32_t fontSize, etk::Vector& listGlyph) { }; }; }; diff --git a/sources/ewol/font/FontFreeType.cpp b/sources/ewol/font/FontFreeType.cpp index b7bcd38f..c91e7f78 100644 --- a/sources/ewol/font/FontFreeType.cpp +++ b/sources/ewol/font/FontFreeType.cpp @@ -103,31 +103,6 @@ ewol::FontFreeType::~FontFreeType(void) // must be deleted fftFace } -int32_t ewol::FontFreeType::Draw(draw::Image& imageOut, - int32_t fontSize, - etk::Vector2D textPos, - const etk::UString& unicodeString, - draw::Color& textColor) -{ - if(false==m_init) { - return 0; - } - // TODO : ... - return 0; -} - -int32_t ewol::FontFreeType::Draw(draw::Image& imageOut, - int32_t fontSize, - etk::Vector2D textPos, - const uniChar_t unicodeChar, - draw::Color& textColor) -{ - if(false==m_init) { - return 0; - } - // TODO : ... - return 0; -} etk::Vector2D ewol::FontFreeType::GetSize(int32_t fontSize, const etk::UString & unicodeString) { @@ -189,11 +164,11 @@ bool ewol::FontFreeType::GetGlyphProperty(int32_t fontSize, return true; } -bool ewol::FontFreeType::DrawGlyph(draw::Image& imageOut, - int32_t fontSize, - etk::Vector2D glyphPosition, - ewol::GlyphProperty& property, - int8_t posInImage) +bool ewol::FontFreeType::DrawGlyph(draw::Image& imageOut, + int32_t fontSize, + etk::Vector2D glyphPosition, + ewol::GlyphProperty& property, + int8_t posInImage) { if(false==m_init) { @@ -254,6 +229,38 @@ bool ewol::FontFreeType::DrawGlyph(draw::Image& imageOut, return true; } + +void ewol::FontFreeType::GenerateKerning(int32_t fontSize, etk::Vector& listGlyph) +{ + if(false==m_init) { + return; + } + // 300dpi (hight quality) 96 dpi (normal quality) + int32_t fontQuality = 96; + // Select Size ... + // note tha <<6==*64 corespond with the 1/64th of points calculation of freetype + int32_t error = FT_Set_Char_Size(m_fftFace, fontSize<<6, fontSize<<6, fontQuality, fontQuality); + if (0!=error ) { + EWOL_ERROR("FT_Set_Char_Size ==> error in settings ..."); + return; + } + // For all the kerning element we get the kerning value : + for(int32_t iii=0; iii " << (kerning.x/64.0f)); + } + } + } +} + + void ewol::FontFreeType::Display(void) { if(false==m_init) { diff --git a/sources/ewol/font/FontFreeType.h b/sources/ewol/font/FontFreeType.h index a24e399b..39f811f5 100644 --- a/sources/ewol/font/FontFreeType.h +++ b/sources/ewol/font/FontFreeType.h @@ -30,25 +30,21 @@ namespace ewol public: FontFreeType(etk::UString fontName); ~FontFreeType(void); - int32_t Draw(draw::Image& imageOut, - int32_t fontSize, - etk::Vector2D textPos, - const etk::UString& unicodeString, - draw::Color& textColor); - int32_t Draw(draw::Image& imageOut, - int32_t fontSize, - etk::Vector2D textPos, - const uniChar_t unicodeChar, - draw::Color& textColor); + bool GetGlyphProperty(int32_t fontSize, ewol::GlyphProperty& property); - bool DrawGlyph(draw::Image& imageOut, - int32_t fontSize, - etk::Vector2D glyphPosition, - ewol::GlyphProperty& property, + + bool DrawGlyph(draw::Image& imageOut, + int32_t fontSize, + etk::Vector2D glyphPosition, + ewol::GlyphProperty& property, int8_t posInImage); + etk::Vector2D GetSize(int32_t fontSize, const etk::UString & unicodeString); + int32_t GetHeight(int32_t fontSize); + + void GenerateKerning(int32_t fontSize, etk::Vector& listGlyph); }; void FreeTypeInit(void); void FreeTypeUnInit(void); diff --git a/sources/ewol/font/GlyphProperty.h b/sources/ewol/font/GlyphProperty.h new file mode 100644 index 00000000..72dc6792 --- /dev/null +++ b/sources/ewol/font/GlyphProperty.h @@ -0,0 +1,86 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2011, Edouard DUPIN, all right reserved + * + * @license BSD v3 (see license file) + */ + +#ifndef __EWOL_FONT_GLYPH_PROPERTY_H__ +#define __EWOL_FONT_GLYPH_PROPERTY_H__ + +#include + + +namespace ewol +{ + /* + | | | | + | | | | + | | | | + Y | | | | + ^ |------------| |------------| + | + m_advance.y:/-> | + | | + | | + m_sizeTex.x/-> | | |------------| |------------| + | | | | | | | + | | | | | | | + | | | | | | | + | | | | | | | + | | | | A | | G | + | | | | | | | + | | | | | | | + | | | | | | | + | | | | | | | + \-> | | |------------| |------------| + /--> | | + \--> \-> | + m_bearing.y | + |____*________________________*____________>> X + + + <------------------------> : m_advance.x + + <------------> : m_sizeTexture.x + + <---> : m_bearing.x + + */ + + class GlyphProperty + { + public: + uniChar_t m_UVal; //!< Unicode value + int32_t m_glyphIndex; //!< Glyph index in the system + etk::Vector2D m_sizeTexture; //!< size of the element to display + etk::Vector2D m_bearing; //!< offset to display the data (can be negatif id the texture sise is bigger than the theoric places in the string) + etk::Vector2D m_advance; //!< space use in the display for this specific char + texCoord_ts m_texturePosStart; //!< Texture normalised position (START) + texCoord_ts m_texturePosStop; //!< Texture normalised position (STOP) + private: + etk::Vector m_kerning; //!< kerning values of link of all elements + public: + float KerningGet(const uniChar_t charcode) + { + for(int32_t iii=0; iii glyphPosition(1,1); for (int32_t iii=0; iiiGetGlyphProperty(m_size, (m_listElement[iiiFontId])[iii].property)) { + if (true == m_font[iiiFontId]->GetGlyphProperty(m_size, (m_listElement[iiiFontId])[iii])) { // change line if needed ... - if (glyphPosition.x+(m_listElement[iiiFontId])[iii].property.m_sizeTexture.x > textureWidth) { + if (glyphPosition.x+(m_listElement[iiiFontId])[iii].m_sizeTexture.x > textureWidth) { glyphPosition.x = 0; glyphPosition.y += CurrentLineHigh; CurrentLineHigh = 0; } // draw the glyph - m_font[iiiFontId]->DrawGlyph(m_data, m_size, glyphPosition, (m_listElement[iiiFontId])[iii].property, iiiFontId); + m_font[iiiFontId]->DrawGlyph(m_data, m_size, glyphPosition, (m_listElement[iiiFontId])[iii], iiiFontId); // set video position - (m_listElement[iiiFontId])[iii].posStart.u = (float)(glyphPosition.x) / (float)textureWidth; - (m_listElement[iiiFontId])[iii].posStart.v = (float)(glyphPosition.y) / (float)textureHeight; - (m_listElement[iiiFontId])[iii].posStop.u = (float)(glyphPosition.x + (m_listElement[iiiFontId])[iii].property.m_sizeTexture.x) / (float)textureWidth; - (m_listElement[iiiFontId])[iii].posStop.v = (float)(glyphPosition.y + (m_listElement[iiiFontId])[iii].property.m_sizeTexture.y) / (float)textureHeight; + (m_listElement[iiiFontId])[iii].m_texturePosStart.u = (float)(glyphPosition.x) / (float)textureWidth; + (m_listElement[iiiFontId])[iii].m_texturePosStart.v = (float)(glyphPosition.y) / (float)textureHeight; + (m_listElement[iiiFontId])[iii].m_texturePosStop.u = (float)(glyphPosition.x + (m_listElement[iiiFontId])[iii].m_sizeTexture.x) / (float)textureWidth; + (m_listElement[iiiFontId])[iii].m_texturePosStop.v = (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].property.m_sizeTexture.y) { + 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].property.m_sizeTexture.y+1; + 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.x += (m_listElement[iiiFontId])[iii].property.m_sizeTexture.x+1; + glyphPosition.x += (m_listElement[iiiFontId])[iii].m_sizeTexture.x+1; } } + // generate the kerning for all the characters : + m_font[iiiFontId]->GenerateKerning(m_size, m_listElement[iiiFontId]); } // For testing cheree the box are set) #if 0 @@ -261,8 +265,11 @@ int32_t ewol::TexturedFont::Draw(etk::Vector2D textPos, { float totalSize = 0; etk::Vector2D tmpPos = textPos; + uniChar_t unicodeCharPrevious = 0; for(int32_t iii=0; iii textPos, etk::Vector & vectDisplayMode, bool hasClipping, clipping_ts& clipping, - ewol::font::mode_te displayMode) + ewol::font::mode_te displayMode, + const uniChar_t unicodeCharPrevious) { float posDrawX = textPos.x; - int32_t charIndex; if (unicodeChar < 0x20) { charIndex = 0; @@ -288,12 +295,18 @@ int32_t ewol::TexturedFont::Draw(etk::Vector2D textPos, } else { charIndex = 0; for (int32_t iii=0x80-0x20; iii < m_listElement[0].Size(); iii++) { - if ((m_listElement[displayMode])[iii].property.m_UVal == unicodeChar) { + if ((m_listElement[displayMode])[iii].m_UVal == unicodeChar) { charIndex = iii; break; } } } + float kerningOffset = (m_listElement[displayMode])[charIndex].KerningGet(unicodeCharPrevious); + /* + if (kerningOffset != 0) { + EWOL_DEBUG("Kerning between : '" << (char)unicodeCharPrevious << "'&'" << (char)(m_listElement[displayMode])[charIndex].m_UVal << "' value : " << kerningOffset); + } + */ // 0x01 == 0x20 == ' '; if (unicodeChar != 0x01) { /* Bitmap position @@ -303,15 +316,15 @@ int32_t ewol::TexturedFont::Draw(etk::Vector2D textPos, * | | * yD *------* */ - float dxA = posDrawX + (m_listElement[displayMode])[charIndex].property.m_bearing.x; - float dxB = posDrawX + (m_listElement[displayMode])[charIndex].property.m_bearing.x + (m_listElement[displayMode])[charIndex].property.m_sizeTexture.x; - float dyC = textPos.y + (m_listElement[displayMode])[charIndex].property.m_bearing.y + m_height[displayMode] - m_size; - float dyD = dyC - (m_listElement[displayMode])[charIndex].property.m_sizeTexture.y; + float dxA = posDrawX + (m_listElement[displayMode])[charIndex].m_bearing.x + kerningOffset; + float dxB = dxA + (m_listElement[displayMode])[charIndex].m_sizeTexture.x; + float dyC = textPos.y + (m_listElement[displayMode])[charIndex].m_bearing.y + m_height[displayMode] - m_size; + float dyD = dyC - (m_listElement[displayMode])[charIndex].m_sizeTexture.y; - float tuA = (m_listElement[displayMode])[charIndex].posStart.u; - float tuB = (m_listElement[displayMode])[charIndex].posStop.u; - float tvC = (m_listElement[displayMode])[charIndex].posStart.v; - float tvD = (m_listElement[displayMode])[charIndex].posStop.v; + float tuA = (m_listElement[displayMode])[charIndex].m_texturePosStart.u; + float tuB = (m_listElement[displayMode])[charIndex].m_texturePosStop.u; + float tvC = (m_listElement[displayMode])[charIndex].m_texturePosStart.v; + float tvD = (m_listElement[displayMode])[charIndex].m_texturePosStop.v; // Clipping and drawing area @@ -328,7 +341,7 @@ int32_t ewol::TexturedFont::Draw(etk::Vector2D textPos, float drawSize = clipping.x - dxA; // Update element start display dxA = clipping.x; - float addElement = TexSizeX * drawSize / (float)(m_listElement[displayMode])[charIndex].property.m_sizeTexture.x; + float addElement = TexSizeX * drawSize / (float)(m_listElement[displayMode])[charIndex].m_sizeTexture.x; // update texture start X Pos tuA += addElement; } @@ -337,7 +350,7 @@ int32_t ewol::TexturedFont::Draw(etk::Vector2D textPos, float drawSize = dxB - (clipping.x + clipping.w); // Update element start display dxB = clipping.x + clipping.w; - float addElement = TexSizeX * drawSize / (float)(m_listElement[displayMode])[charIndex].property.m_sizeTexture.x; + float addElement = TexSizeX * drawSize / (float)(m_listElement[displayMode])[charIndex].m_sizeTexture.x; // update texture start X Pos tuB -= addElement; } @@ -347,7 +360,7 @@ int32_t ewol::TexturedFont::Draw(etk::Vector2D textPos, float drawSize = clipping.y - dyC; // Update element start display dyC = clipping.y; - float addElement = TexSizeY * drawSize / (float)(m_listElement[displayMode])[charIndex].property.m_sizeTexture.x; + float addElement = TexSizeY * drawSize / (float)(m_listElement[displayMode])[charIndex].m_sizeTexture.x; // update texture start X Pos tvC += addElement; } @@ -356,7 +369,7 @@ int32_t ewol::TexturedFont::Draw(etk::Vector2D textPos, float drawSize = dyD - (clipping.y + clipping.h); // Update element start display dyD = clipping.y + clipping.h; - float addElement = TexSizeX * drawSize / (float)(m_listElement[displayMode])[charIndex].property.m_sizeTexture.x; + float addElement = TexSizeX * drawSize / (float)(m_listElement[displayMode])[charIndex].m_sizeTexture.x; // update texture start X Pos tvD -= addElement; } @@ -433,24 +446,28 @@ int32_t ewol::TexturedFont::Draw(etk::Vector2D textPos, } } } - posDrawX += (m_listElement[displayMode])[charIndex].property.m_advance.x; + posDrawX += (m_listElement[displayMode])[charIndex].m_advance.x + kerningOffset; int32_t sizeOut = posDrawX - textPos.x; textPos.x = posDrawX; return sizeOut; } -etk::Vector2D ewol::TexturedFont::GetSize(const etk::UString & unicodeString) +etk::Vector2D ewol::TexturedFont::GetSize(const etk::UString & unicodeString, const ewol::font::mode_te displayMode) { etk::Vector2D outputSize(0,m_height[0]); + uniChar_t unicodeCharPrevious = 0; for(int32_t iii=0; iii tmpp = GetSize(unicodeString[iii]); + etk::Vector2D tmpp = GetSize(unicodeString[iii], unicodeCharPrevious, displayMode); + unicodeCharPrevious = unicodeString[iii]; outputSize.x += tmpp.x; } return outputSize; } -etk::Vector2D ewol::TexturedFont::GetSize(const uniChar_t unicodeChar) +etk::Vector2D ewol::TexturedFont::GetSize(const uniChar_t unicodeChar, + const uniChar_t unicodeCharPrevious, + const ewol::font::mode_te displayMode) { etk::Vector2D outputSize(0,m_height[0]); int32_t charIndex; @@ -462,7 +479,7 @@ etk::Vector2D ewol::TexturedFont::GetSize(const uniChar_t unicodeChar) charIndex = unicodeChar - 0x1F; } else { for (int32_t iii=0x80-0x20; iii < m_listElement[0].Size(); iii++) { - if ((m_listElement[0])[iii].property.m_UVal == unicodeChar) { + if ((m_listElement[0])[iii].m_UVal == unicodeChar) { charIndex = iii; break; } @@ -470,7 +487,8 @@ etk::Vector2D ewol::TexturedFont::GetSize(const uniChar_t unicodeChar) // TODO : Update if possible the mapping charIndex = 0; } - outputSize.x = (m_listElement[0])[charIndex].property.m_advance.x; + float kerningOffset = (m_listElement[displayMode])[charIndex].KerningGet(unicodeCharPrevious); + outputSize.x = (m_listElement[0])[charIndex].m_advance.x + kerningOffset; return outputSize; } diff --git a/sources/ewol/font/TexturedFont.h b/sources/ewol/font/TexturedFont.h index ef4af6a8..fa7c4779 100644 --- a/sources/ewol/font/TexturedFont.h +++ b/sources/ewol/font/TexturedFont.h @@ -26,11 +26,6 @@ namespace ewol }; class TexturedFont : public ewol::Texture { - typedef struct { - GlyphProperty property; - texCoord_ts posStart; - texCoord_ts posStop; - }freeTypeFontElement_ts; private: etk::UString m_fileName[4]; int32_t m_size; @@ -39,7 +34,7 @@ namespace ewol // ==> otherwise I can just generate italic ... // ==> Bold is a little more complicated (maybe with the bordersize) ewol::Font* m_font[4]; - etk::Vector m_listElement[4]; + etk::Vector m_listElement[4]; // for the texture generation : etk::Vector2D m_lastGlyphPos[4]; int32_t m_lastRawHeigh[4]; @@ -65,12 +60,38 @@ namespace ewol etk::Vector & vectDisplayMode, bool hasClipping, clipping_ts& clipping, - ewol::font::mode_te displayMode); + ewol::font::mode_te displayMode, + const uniChar_t unicodeCharPrevious = 0); - etk::Vector2D GetSize(const etk::UString & unicodeString); - etk::Vector2D GetSize(const uniChar_t unicodeChar); - // TODO : Remove this element, it is stupid ... - int32_t GetHeight(void) { return m_height[0]; }; + /** + * @brief Get the size of the specified String + * @param[in] unicodeString The string that we might calculate the display size + * @param[in] displayMode Mode to display the currrent font + * @return Dimention of the string use + */ + etk::Vector2D GetSize(const etk::UString & unicodeString, + const ewol::font::mode_te displayMode = ewol::font::Regular); + + /** + * @brief Get the size of the specified unicode value + * @param[in] unicodeChar the char that might be displayed + * @param[in] unicodeCharPrevious Previous char of this One ==> 0 no previous char + * @param[in] displayMode Mode to display the currrent font + * @return Dimention of the font use + */ + etk::Vector2D GetSize(const uniChar_t unicodeChar, + const uniChar_t unicodeCharPrevious = 0, + const ewol::font::mode_te displayMode = ewol::font::Regular); + /** + * @brief Get the display height of this font + * @param[in] displayMode Mode to display the currrent font + * @return Dimention of the font need between 2 lines + */ + int32_t GetHeight(const ewol::font::mode_te displayMode = ewol::font::Regular) { return m_height[displayMode]; }; + /** + * @brief Get the font height (user friendly) + * @return Dimention of the font the user requested + */ int32_t GetFontSize(void) { return m_size; }; };