From 43f9c600fc07e0fca8947296173cded6298bdd2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=C2=ADn=20Lucas=20Golini?= Date: Sun, 12 Mar 2017 23:42:26 -0300 Subject: [PATCH] New Font class integrated to the old Font class. --HG-- branch : dev-font --- include/eepp/graphics.hpp | 6 +- include/eepp/graphics/console.hpp | 3 +- include/eepp/graphics/font.hpp | 80 +- include/eepp/graphics/fonttruetype.hpp | 62 +- include/eepp/graphics/fonttruetypeloader.hpp | 106 +++ include/eepp/graphics/text.hpp | 126 --- include/eepp/graphics/textcache.hpp | 144 ++-- include/eepp/graphics/texturefont.hpp | 82 -- include/eepp/graphics/texturefontloader.hpp | 111 --- include/eepp/graphics/ttffont.hpp | 121 --- include/eepp/graphics/ttffontloader.hpp | 113 --- include/eepp/ui/uithemeconfig.hpp | 24 +- include/eepp/ui/uithememanager.hpp | 2 +- projects/linux/ee.files | 6 +- src/eepp/graphics/console.cpp | 7 +- src/eepp/graphics/font.cpp | 323 ++++---- src/eepp/graphics/fonttruetype.cpp | 366 ++------- src/eepp/graphics/fonttruetypeloader.cpp | 120 +++ src/eepp/graphics/text.cpp | 618 -------------- src/eepp/graphics/textcache.cpp | 811 ++++++++++++------- src/eepp/graphics/texturefont.cpp | 217 ----- src/eepp/graphics/texturefontloader.cpp | 147 ---- src/eepp/graphics/ttffont.cpp | 455 ----------- src/eepp/graphics/ttffontloader.cpp | 129 --- src/eepp/ui/uilistbox.cpp | 15 +- src/eepp/ui/uitextedit.cpp | 4 +- src/eepp/ui/uitextinput.cpp | 8 +- src/eepp/ui/uitextinputpassword.cpp | 5 +- src/eepp/ui/uitextview.cpp | 15 +- src/eepp/ui/uithememanager.cpp | 4 +- src/eepp/ui/uitooltip.cpp | 1 + src/examples/fonts/fonts.cpp | 93 +-- src/test/eetest.cpp | 22 +- 33 files changed, 1166 insertions(+), 3180 deletions(-) create mode 100644 include/eepp/graphics/fonttruetypeloader.hpp delete mode 100644 include/eepp/graphics/text.hpp delete mode 100755 include/eepp/graphics/texturefont.hpp delete mode 100644 include/eepp/graphics/texturefontloader.hpp delete mode 100755 include/eepp/graphics/ttffont.hpp delete mode 100644 include/eepp/graphics/ttffontloader.hpp create mode 100644 src/eepp/graphics/fonttruetypeloader.cpp delete mode 100644 src/eepp/graphics/text.cpp delete mode 100755 src/eepp/graphics/texturefont.cpp delete mode 100644 src/eepp/graphics/texturefontloader.cpp delete mode 100755 src/eepp/graphics/ttffont.cpp delete mode 100644 src/eepp/graphics/ttffontloader.cpp diff --git a/include/eepp/graphics.hpp b/include/eepp/graphics.hpp index a6cfc5d77..b148126bb 100644 --- a/include/eepp/graphics.hpp +++ b/include/eepp/graphics.hpp @@ -20,10 +20,8 @@ #include #include #include -#include -#include -#include -#include +#include +#include #include #include #include diff --git a/include/eepp/graphics/console.hpp b/include/eepp/graphics/console.hpp index 237420c0a..8adf657da 100755 --- a/include/eepp/graphics/console.hpp +++ b/include/eepp/graphics/console.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include namespace EE { namespace Window { class Window; class InputTextBuffer; class InputEvent; } } @@ -245,7 +246,7 @@ class EE_API Console : protected LogReaderInterface { void privVideoResize( EE::Window::Window * win ); - void writeLog( const std::string& Text ); + void writeLog( const std::string& TextCache ); void getFilesFrom( std::string txt, const Uint32& curPos ); diff --git a/include/eepp/graphics/font.hpp b/include/eepp/graphics/font.hpp index 319ca802b..a60c677d1 100755 --- a/include/eepp/graphics/font.hpp +++ b/include/eepp/graphics/font.hpp @@ -4,41 +4,30 @@ #include #include #include -#include namespace EE { namespace Graphics { +class EE_API Glyph { + public: + Glyph() : advance(0) {} + + Float advance; ///< Offset to move horizontally to the next character + Rectf bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline + Recti textureRect; ///< Texture coordinates of the glyph inside the font's texture +}; + /** @brief Font interface class. */ class EE_API Font { public: + struct Info + { + std::string family; ///< The font family + }; + virtual ~Font(); - /** @return The current font size */ - Uint32 getFontSize() const; - /** @return The current font height */ - Uint32 getFontHeight() const; - - /** @return The recommended line spacing */ - Int32 getLineSkip() const; - - /** Shrink the String to a max width - * @param Str The string to shrink - * @param MaxWidth The Max Width posible - */ - void shrinkText( String& Str, const Uint32& MaxWidth ); - - /** Shrink the string to a max width - * @param Str The string to shrink - * @param MaxWidth The Max Width posible - */ - void shrinkText( std::string& Str, const Uint32& MaxWidth ); - - /** Cache the with of the current text */ - void cacheWidth( const String& Text, std::vector& LinesWidth, Float& CachedWidth, int& NumLines, int& LargestLineCharCount ); - - /** @return The font texture id */ - const Uint32& getTexId() const; + virtual Uint32 getFontHeight( const Uint32& characterSize ) = 0; /** @return The type of the instance of the font, can be FONT_TYPE_TTF ( true type font ) or FONT_TYPE_TEX ( texture font ) */ const Uint32& getType() const; @@ -52,20 +41,43 @@ class EE_API Font { /** @return The font id */ const Uint32& getId(); + /** Shrink the String to a max width + * @param Str The string to shrink + * @param MaxWidth The Max Width posible + */ + void shrinkText( String& Str, const Uint32& characterSize, bool bold, Float outlineThickness, const Uint32& MaxWidth ); + + /** Shrink the string to a max width + * @param Str The string to shrink + * @param MaxWidth The Max Width posible + */ + void shrinkText( std::string& Str, const Uint32& characterSize, bool bold, Float outlineThickness, const Uint32& MaxWidth ); + + /** Cache the with of the current text */ + void cacheWidth( const String& TextCache, const Uint32& characterSize, bool bold, Float outlineThickness, std::vector& LinesWidth, Float& CachedWidth, int& NumLines, int& LargestLineCharCount ); + /** Finds the closest cursor position to the point position */ - Int32 findClosestCursorPosFromPoint( const String& Text, const Vector2i& pos ); + Int32 findClosestCursorPosFromPoint( const String& TextCache, const Uint32& characterSize, bool bold, Float outlineThickness, const Vector2i& pos ); /** Simulates a selection request and return the initial and end cursor position when the selection worked. Otherwise both parameters will be -1. */ - void selectSubStringFromCursor( const String& Text, const Int32& CurPos, Int32& InitCur, Int32& EndCur ); + void selectSubStringFromCursor(const String& TextCache, const Int32& CurPos, Int32& InitCur, Int32& EndCur ); /** @return The cursor position inside the string */ - Vector2i getCursorPos( const String& Text, const Uint32& Pos ); + Vector2i getCursorPos( const String& TextCache, const Uint32& characterSize, bool bold, Float outlineThickness, const Uint32& Pos ); - const GlyphData& getGlyph( const Uint32& index ); + virtual const Info& getInfo() const = 0; - const TextureCoords& getTextureCoords( const Uint32& index ); + virtual const Glyph& getGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, Float outlineThickness = 0) const = 0; - Uint32 getGlyphCount() const; + virtual Float getKerning(Uint32 first, Uint32 second, unsigned int characterSize) const = 0; + + virtual Float getLineSpacing(unsigned int characterSize) const = 0; + + virtual Float getUnderlinePosition(unsigned int characterSize) const = 0; + + virtual Float getUnderlineThickness(unsigned int characterSize) const = 0; + + virtual Texture * getTexture(unsigned int characterSize) const = 0; protected: Uint32 mType; std::string mFontName; @@ -74,14 +86,10 @@ class EE_API Font { Uint32 mHeight; Uint32 mSize; Int32 mLineSkip; - Int32 mAscent; - Int32 mDescent; std::vector mGlyphs; std::vector mTexCoords; - TextCache mTextCache; - Font( const Uint32& Type, const std::string& setName ); }; diff --git a/include/eepp/graphics/fonttruetype.hpp b/include/eepp/graphics/fonttruetype.hpp index 2cf92ea54..5e6060405 100644 --- a/include/eepp/graphics/fonttruetype.hpp +++ b/include/eepp/graphics/fonttruetype.hpp @@ -3,62 +3,21 @@ #include #include +#include #include #include #include namespace EE { namespace System { +class Pack; class IOStream; }} namespace EE { namespace Graphics { -class EE_API Glyph -{ +class EE_API FontTrueType : public Font { public: - Glyph() : advance(0) {} - - Float advance; ///< Offset to move horizontally to the next character - Rectf bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline - Recti textureRect; ///< Texture coordinates of the glyph inside the font's texture -}; - -class EE_API FontTrueType -{ - public: - /** Shrink the String to a max width - * @param Str The string to shrink - * @param MaxWidth The Max Width posible - */ - void shrinkText( String& Str, const Uint32& characterSize, bool bold, Float outlineThickness, const Uint32& MaxWidth ); - - /** Shrink the string to a max width - * @param Str The string to shrink - * @param MaxWidth The Max Width posible - */ - void shrinkText( std::string& Str, const Uint32& characterSize, bool bold, Float outlineThickness, const Uint32& MaxWidth ); - - /** Cache the with of the current text */ - void cacheWidth( const String& Text, const Uint32& characterSize, bool bold, Float outlineThickness, std::vector& LinesWidth, Float& CachedWidth, int& NumLines, int& LargestLineCharCount ); - - /** Finds the closest cursor position to the point position */ - Int32 findClosestCursorPosFromPoint( const String& Text, const Uint32& characterSize, bool bold, Float outlineThickness, const Vector2i& pos ); - - /** Simulates a selection request and return the initial and end cursor position when the selection worked. Otherwise both parameters will be -1. */ - void selectSubStringFromCursor( const String& Text, const Uint32& characterSize, bool bold, Float outlineThickness, const Int32& CurPos, Int32& InitCur, Int32& EndCur ); - - /** @return The cursor position inside the string */ - Vector2i getCursorPos( const String& Text, const Uint32& characterSize, bool bold, Float outlineThickness, const Uint32& Pos ); - - public: - struct Info - { - std::string family; ///< The font family - }; - - FontTrueType(); - - FontTrueType(const FontTrueType& copy); + static FontTrueType * New( const std::string FontName ) ; ~FontTrueType(); @@ -66,9 +25,11 @@ class EE_API FontTrueType bool loadFromMemory(const void* data, std::size_t sizeInBytes); - bool loadFromStream(IOStream& stream); + bool loadFromStream( IOStream& stream ); - const Info& getInfo() const; + bool loadFromPack( Pack * pack, std::string filePackPath ); + + const Font::Info& getInfo() const; const Glyph& getGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, Float outlineThickness = 0) const; @@ -76,6 +37,8 @@ class EE_API FontTrueType Float getLineSpacing(unsigned int characterSize) const; + Uint32 getFontHeight( const Uint32& characterSize ); + Float getUnderlinePosition(unsigned int characterSize) const; Float getUnderlineThickness(unsigned int characterSize) const; @@ -83,8 +46,9 @@ class EE_API FontTrueType Texture * getTexture(unsigned int characterSize) const; FontTrueType& operator =(const FontTrueType& right); + protected: + FontTrueType(const std::string FontName); - private: struct Row { Row(unsigned int rowTop, unsigned int rowHeight) : width(0), top(rowTop), height(rowHeight) {} @@ -123,7 +87,7 @@ class EE_API FontTrueType void* mStreamRec; ///< Pointer to the stream rec instance (it is typeless to avoid exposing implementation details) void* mStroker; ///< Pointer to the stroker (it is typeless to avoid exposing implementation details) int* mRefCount; ///< Reference counter used by implicit sharing - Info mInfo; ///< Information about the font + Font::Info mInfo; ///< Information about the font mutable PageTable mPages; ///< Table containing the glyphs pages by character size mutable std::vector mPixelBuffer; ///< Pixel buffer holding a glyph's pixels before being written to the texture }; diff --git a/include/eepp/graphics/fonttruetypeloader.hpp b/include/eepp/graphics/fonttruetypeloader.hpp new file mode 100644 index 000000000..73c280fbd --- /dev/null +++ b/include/eepp/graphics/fonttruetypeloader.hpp @@ -0,0 +1,106 @@ +#ifndef EE_GRAPHICSCTTFFONTLOADER +#define EE_GRAPHICSCTTFFONTLOADER + +#include +#include +#include +#include + +namespace EE { namespace System { +class IOStream; +class Pack; +}} + +namespace EE { namespace Graphics { + +/** @brief The TTF Font loader loads a true type font to memory in synchronous or asynchronous mode. +@see ObjectLoader +*/ +class EE_API FontTrueTypeLoader : public ObjectLoader { + public: + /** Load a True Type Font from path + * @param FontName The font name + * @param Filepath The TTF file path + */ + FontTrueTypeLoader( const std::string& FontName, const std::string& Filepath ); + + /** Load a True Type Font from a Pack + * @param FontName The font name + * @param Pack Pointer to the pack instance + * @param FilePackPath The path of the file inside the pack + */ + FontTrueTypeLoader( const std::string& FontName, Pack * Pack, const std::string& FilePackPath ); + + /** Loads a True Type Font from memory + * @param FontName The font name + * @param TTFData The pointer to the data + * @param TTFDataSize The size of the data + */ + FontTrueTypeLoader( const std::string& FontName, Uint8* TTFData, const unsigned int& TTFDataSize ); + + /** Loads a True Type Font from a IO Steam + * @param FontName The font name + * @oaram stream The IO Stream + */ + FontTrueTypeLoader( const std::string& FontName, IOStream& stream ); + + virtual ~FontTrueTypeLoader(); + + /** This must be called for the asynchronous mode to update the texture data to the GPU, the call must be done from the same thread that the GL Context was created ( the main thread ). + ** The TTF Font creates texture from the data obtained from the true type file. + ** @see ObjectLoader::Update */ + void update(); + + /** Releases the Font instance and the texture loaded ( if was already loaded ), it will destroy the font texture from memory */ + void unload(); + + /** @return The font name. */ + const std::string& getId() const; + + /** @return The font instance if already exists, otherwise returns NULL. */ + Graphics::Font * getFont() const; + protected: + enum TTF_LOAD_TYPE + { + TTF_LT_PATH = 1, + TTF_LT_MEM = 2, + TTF_LT_PACK = 3, + TTF_LT_STREAM = 4 + }; + + Uint32 mLoadType; // From memory, from path, from pack + + FontTrueType * mFont; + + std::string mFontName; + std::string mFilepath; + unsigned int mSize; + EE_TTF_FONT_STYLE mStyle; + Uint16 mNumCharsToGen; + RGB mFontColor; + Uint8 mOutlineSize; + RGB mOutlineColor; + bool mAddPixelSeparator; + Pack * mPack; + Uint8 * mData; + unsigned int mDataSize; + IOStream * mIOStream; + + void start(); + + void reset(); + private: + bool mFontLoaded; + + void loadFromFile(); + void loadFromMemory(); + void loadFromPack(); + void loadFromStream(); + void create(); +}; + +}} + +#endif + + diff --git a/include/eepp/graphics/text.hpp b/include/eepp/graphics/text.hpp deleted file mode 100644 index 8ea9b0300..000000000 --- a/include/eepp/graphics/text.hpp +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef EE_GRAPHICS_TEXT_HPP -#define EE_GRAPHICS_TEXT_HPP - -#include -#include -#include -#include - -namespace EE { namespace Graphics { - -class EE_API Text { - public: - enum Style - { - Regular = 0, ///< Regular characters, no style - Bold = 1 << 0, ///< Bold characters - Italic = 1 << 1, ///< Italic characters - Underlined = 1 << 2, ///< Underlined characters - StrikeThrough = 1 << 3 ///< Strike through characters - }; - - Text(); - - Text(const String& string, FontTrueType * font, unsigned int characterSize = 30); - - void setText(const String& string); - - void setFontTrueType(FontTrueType * font); - - void setCharacterSize(unsigned int size); - - void setStyle(Uint32 style); - - void setColor(const ColorA& color); - - void setFillColor(const ColorA& color); - - void setOutlineColor(const ColorA& color); - - void setOutlineThickness(Float thickness); - - const String& getText() const; - - const FontTrueType* getFontTrueType() const; - - unsigned int getCharacterSize() const; - - Uint32 getStyle() const; - - /** @see Set the alpha of each individual character. - ** This doesn't break any custom color per-character setted. */ - void setAlpha( const Uint8& alpha ); - - const ColorA& getFillColor() const; - - const ColorA& getOutlineColor() const; - - Float getOutlineThickness() const; - - Vector2f findCharacterPos(std::size_t index) const; - - Rectf getLocalBounds(); - - /** @return The cached text width */ - Float getTextWidth(); - - /** @return The cached text height */ - Float getTextHeight(); - - /** Draw the cached text on screen */ - void draw( const Float& X, const Float& Y, const Vector2f& Scale = Vector2f::One, const Float& Angle = 0, EE_BLEND_MODE Effect = ALPHA_NORMAL ); - - /** @return The Shadow Font Color */ - const ColorA& getShadowColor() const; - - /** Set the shadow color of the string rendered */ - void setShadowColor(const ColorA& color); - - /** @return Every cached text line width */ - const std::vector& getLinesWidth(); - - /** Set the font draw flags */ - void setFlags( const Uint32& flags ); - - /** @return The font draw flags */ - const Uint32& getFlags() const; - - /** @return The number of lines that the cached text contains */ - const int& getNumLines() const; - - private: - void ensureGeometryUpdate(); - - String mString; ///< String to display - FontTrueType * mFont; ///< FontTrueType used to display the string - unsigned int mCharacterSize; ///< Base size of characters, in pixels - Uint32 mStyle; ///< Text style (see Style enum) - ColorA mFillColor; ///< Text fill color - ColorA mOutlineColor; ///< Text outline color - Float mOutlineThickness; ///< Thickness of the text's outline - Sizei mTextureSize; - - mutable Rectf mBounds; ///< Bounding rectangle of the text (in local coordinates) - mutable bool mGeometryNeedUpdate; ///< Does the geometry need to be recomputed? - - Float mCachedWidth; - int mNumLines; - int mLargestLineCharCount; - ColorA mFontShadowColor; - Uint32 mFlags; - - std::vector mVertices; - std::vector mColors; - - std::vector mOutlineVertices; - std::vector mOutlineColors; - std::vector mLinesWidth; - - /** Force to cache the width of the current text */ - void cacheWidth(); -}; - -}} - - -#endif diff --git a/include/eepp/graphics/textcache.hpp b/include/eepp/graphics/textcache.hpp index c8a4ad975..25d889084 100644 --- a/include/eepp/graphics/textcache.hpp +++ b/include/eepp/graphics/textcache.hpp @@ -1,78 +1,92 @@ -#ifndef EE_GRAPHICSCTEXTCACHE_H -#define EE_GRAPHICSCTEXTCACHE_H +#ifndef EE_GRAPHICS_TEXT_HPP +#define EE_GRAPHICS_TEXT_HPP -#include +#include #include namespace EE { namespace Graphics { -class Font; - -/** @brief Caches text for a fast font rendering. */ class EE_API TextCache { public: - /** Create a text from a font */ - TextCache( Graphics::Font * font, const String& text = "", ColorA FontColor = ColorA(255,255,255,255), ColorA FontShadowColor = ColorA(0,0,0,255) ); + enum Style + { + Regular = 0, ///< Regular characters, no style + Bold = 1 << 0, ///< Bold characters + Italic = 1 << 1, ///< Italic characters + Underlined = 1 << 2, ///< Underlined characters + StrikeThrough = 1 << 3 ///< Strike through characters + }; TextCache(); - ~TextCache(); + TextCache(const String& string, Font * font, unsigned int characterSize = 30); + + TextCache(Font * font, unsigned int characterSize = 30); /** Create a text from a font */ - void create( Graphics::Font * font, const String& text = "", ColorA FontColor = ColorA(255,255,255,255), ColorA FontShadowColor = ColorA(0,0,0,255) ); + void create(Graphics::Font * font, const String& text = "", ColorA FontColor = ColorA(255,255,255,255), ColorA FontShadowColor = ColorA(0,0,0,255) , Uint32 characterSize = 12); - /** @return The font used for the text cache */ - Graphics::Font * getFont() const; + void setText(const String& string); - /** Change the font used for the text cache */ - void setFont( Graphics::Font * font ); + void setFont(Font * font); + + void setCharacterSize(unsigned int size); + + void setStyle(Uint32 style); + + void setColor(const ColorA& color); + + void setFillColor(const ColorA& color); + + void setOutlineColor(const ColorA& color); + + void setOutlineThickness(Float thickness); - /** @return The text cached */ String& getText(); - /** Set the text to be cached */ - void setText( const String& text ); + Font * getFont() const; + unsigned int getCharacterSize() const; + + unsigned int getCharacterSizePx() const; + + const Uint32& getFontHeight() const; + + Uint32 getStyle() const; + + /** @see Set the alpha of each individual character. + ** This doesn't break any custom color per-character setted. */ + void setAlpha( const Uint8& alpha ); + + const ColorA& getFillColor() const; + + const ColorA& getColor() const; + + const ColorA& getOutlineColor() const; + + Float getOutlineThickness() const; + + Vector2f findCharacterPos(std::size_t index) const; + + Rectf getLocalBounds(); + /** @return The cached text width */ Float getTextWidth(); /** @return The cached text height */ Float getTextHeight(); - /** @return Every cached text line width */ - const std::vector& getLinesWidth(); - - /** @return The text colors cached */ - std::vector& getColors(); - /** Draw the cached text on screen */ void draw( const Float& X, const Float& Y, const Vector2f& Scale = Vector2f::One, const Float& Angle = 0, EE_BLEND_MODE Effect = ALPHA_NORMAL ); - /** @return The Font Color */ - const ColorA& getColor() const; - - /** Set the color of the string rendered */ - void setColor(const ColorA& color); - - /** @see Set the alpha of each individual character. - ** This doesn't break any custom color per-character setted. */ - void setAlpha( const Uint8& alpha ); - - /** Set the color of the substring - * @param color The color - * @param from The first char to change the color - * @param to The last char to change the color - */ - void setColor(const ColorA& color, Uint32 from, Uint32 to ); - /** @return The Shadow Font Color */ const ColorA& getShadowColor() const; /** Set the shadow color of the string rendered */ void setShadowColor(const ColorA& color); - /** @return The number of lines that the cached text contains */ - const int& getNumLines() const; + /** @return Every cached text line width */ + const std::vector& getLinesWidth(); /** Set the font draw flags */ void setFlags( const Uint32& flags ); @@ -80,35 +94,43 @@ class EE_API TextCache { /** @return The font draw flags */ const Uint32& getFlags() const; + /** @return The number of lines that the cached text contains */ + const int& getNumLines() const; + /** Force to cache the width of the current text */ void cacheWidth(); - protected: - friend class Font; + private: + void ensureGeometryUpdate(); - String mText; - Graphics::Font * mFont; + String mString; ///< String to display + Font * mFont; ///< FontTrueType used to display the string + unsigned int mCharacterSize; ///< Base size of characters, in pixels + unsigned int mRealCharacterSize; + Uint32 mStyle; ///< Text style (see Style enum) + ColorA mFillColor; ///< Text fill color + ColorA mOutlineColor; ///< Text outline color + Float mOutlineThickness; ///< Thickness of the text's outline + Sizei mTextureSize; - Float mCachedWidth; - int mNumLines; - int mLargestLineCharCount; + mutable Rectf mBounds; ///< Bounding rectangle of the text (in local coordinates) + mutable bool mGeometryNeedUpdate; ///< Does the geometry need to be recomputed? - ColorA mFontColor; - ColorA mFontShadowColor; + Float mCachedWidth; + int mNumLines; + int mLargestLineCharCount; + ColorA mFontShadowColor; + Uint32 mFlags; + Uint32 mFontHeight; - Uint32 mFlags; - Uint32 mVertexNumCached; - - bool mCachedCoords; - - std::vector mLinesWidth; - std::vector mRenderCoords; + std::vector mVertices; std::vector mColors; - void cacheVerts(); - - void updateCoords(); + std::vector mOutlineVertices; + std::vector mOutlineColors; + std::vector mLinesWidth; }; }} + #endif diff --git a/include/eepp/graphics/texturefont.hpp b/include/eepp/graphics/texturefont.hpp deleted file mode 100755 index 092d86cb3..000000000 --- a/include/eepp/graphics/texturefont.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef EECTEXTUREFONT_H -#define EECTEXTUREFONT_H - -#include -#include -#include - -namespace EE { namespace Graphics { - -/** @brief This class loads texture fonts and draw strings to the screen. */ -class EE_API TextureFont : public Font { - public: - /** Creates an instance of a texture font */ - static TextureFont * New( const std::string FontName ); - - /** The destructor will not unload the texture from memory. If you want that you'll have to remove it manually ( TextureFactory::instance()->remove( MyFontInstance->GetTexId() ) ). */ - virtual ~TextureFont(); - - /** Load's a texture font - * @param TexId The texture id returned by TextureFactory - * @param StartChar The fist char represented on the texture - * @param Spacing The space between every char ( default 0 means TextureWidth / TexColumns ) - * @param TexColumns The number of chars per column - * @param TexRows The number of chars per row - * @param NumChars The number of characters to read from the texture - * @return True if success - */ - bool load( const Uint32& TexId, const unsigned int& StartChar = 0, const unsigned int& Spacing = 0, const unsigned int& TexColumns = 16, const unsigned int& TexRows = 16, const Uint16& NumChars = 256 ); - - /** Load's a texture font and then load's the character coordinates file ( generated by the TTFFont class ) - * @param TexId The texture id returned by TextureFactory - * @param CoordinatesDatPath The character coordinates file - * @return True if success - */ - bool load( const Uint32& TexId, const std::string& CoordinatesDatPath ); - - /** - * @param TexId The texture id returned by TextureFactory - * @param Pack Pointer to the pack instance - * @param FilePackPath The path of the file inside the pack - * @return True success - */ - bool loadFromPack( const Uint32& TexId, Pack * Pack, const std::string& FilePackPath ); - - /** Load's a texture font and then load's the character coordinates file previously loaded on memory ( generated by the TTFFont class ) - * @param TexId The texture id returned by TextureFactory - * @param CoordData The character coordinates buffer pointer - * @param CoordDataSize The size of CoordData - * @return True if success - */ - bool loadFromMemory( const Uint32& TexId, const char* CoordData, const Uint32& CoordDataSize ); - - /** Load's a texture font and then load's the character coordinates from a IO stream file ( generated by the TTFFont class ) - * @param TexId The texture id returned by TextureFactory - * @param IOS IO stream file for the coordinates - * @return True if success - */ - bool loadFromStream( const Uint32& TexId, IOStream& IOS ); - private: - unsigned int mStartChar; - unsigned int mTexColumns; - unsigned int mTexRows; - unsigned int mSpacing; - unsigned int mNumChars; - - Float mtX; - Float mtY; - Float mFWidth; - Float mFHeight; - - bool mLoadedCoords; - - TextureFont( const std::string FontName ); - - void buildFont(); - - void buildFromGlyphs(); -}; - -}} - -#endif diff --git a/include/eepp/graphics/texturefontloader.hpp b/include/eepp/graphics/texturefontloader.hpp deleted file mode 100644 index b6b7c5d3d..000000000 --- a/include/eepp/graphics/texturefontloader.hpp +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef EE_GRAPHICSCTEXTUREFONTLOADER -#define EE_GRAPHICSCTEXTUREFONTLOADER - -#include -#include -#include -#include -#include - -namespace EE { namespace Graphics { - -/** @brief The Texture Font loads a texture font in synchronous or asynchronous mode. -@see ObjectLoader */ -class EE_API TextureFontLoader : public ObjectLoader { - public: - /** Loads a texture font from a texture ( only for monospaced fonts ) - * @param FontName The font name - * @param TexLoader An instance of a texture loader that will be used to load the texture. The instance will be released by the Texture Font Loader when is destroyed. - * @param StartChar The fist char represented on the texture - * @param Spacing The space between every char ( default 0 means TextureWidth / TexColumns ) - * @param TexColumns The number of chars per column - * @param TexRows The number of chars per row - * @param NumChars The number of characters to read from the texture - */ - TextureFontLoader( const std::string FontName, TextureLoader * TexLoader, const unsigned int& StartChar = 0, const unsigned int& Spacing = 0, const unsigned int& TexColumns = 16, const unsigned int& TexRows = 16, const Uint16& NumChars = 256 ); - - /** Load's a texture font and then load's the character coordinates file ( generated by the TTFFont class ) - * @param FontName The font name - * @param TexLoader An instance of a texture loader that will be used to load the texture. The instance will be released by the Texture Font Loader when is destroyed. - * @param CoordinatesDatPath The character coordinates file ( this is the file created when the TTF font was converted to a texture font. @see TTFFont::Save ). - */ - TextureFontLoader( const std::string FontName, TextureLoader * TexLoader, const std::string& CoordinatesDatPath ); - - /** Load's a texture font and then load's the character coordinates file ( generated by the TTFFont class ) stored in a pack file. - * @param FontName The font name - * @param TexLoader An instance of a texture loader that will be used to load the texture. The instance will be released by the Texture Font Loader when is destroyed. - * @param Pack The pack used to load the characters coordinates - * @param FilePackPath The character coordinates file path inside the pack ( this is the file created when the TTF font was converted to a texture font. @see TTFFont::Save ). - */ - TextureFontLoader( const std::string FontName, TextureLoader * TexLoader, Pack * Pack, const std::string& FilePackPath ); - - /** Load's a texture font and then load's the character coordinates file ( generated by the TTFFont class ) from memory. - * @param FontName The font name - * @param TexLoader An instance of a texture loader that will be used to load the texture. The instance will be released by the Texture Font Loader when is destroyed. - * @param CoordData The character coordinates buffer pointer ( this is the file created when the TTF font was converted to a texture font. @see TTFFont::Save ). - * @param CoordDataSize The buffer pointer size - */ - TextureFontLoader( const std::string FontName, TextureLoader * TexLoader, const char* CoordData, const Uint32& CoordDataSize ); - - virtual ~TextureFontLoader(); - - /** Updates the current state of the loading in progress ( must be called from the instancer thread, usually the main thread ). - * @see ObjectLoader::Update */ - void update(); - - /** @brief Releases the font loaded ( if was already loaded ) */ - void unload(); - - /** @return The font name */ - const std::string& getId() const; - - /** @return The instance of the font created after loading it. ( NULL if was not created yet ) */ - Graphics::Font * getFont() const; - protected: - enum TEXTURE_FONT_LOAD_TYPE - { - TEF_LT_PATH = 1, - TEF_LT_MEM = 2, - TEF_LT_PACK = 3, - TEF_LT_TEX = 4 - }; - - Uint32 mLoadType; // From memory, from path, from pack - - TextureFont * mFont; - - std::string mFontName; - TextureLoader * mTexLoader; - - std::string mFilepath; - - unsigned int mStartChar; - unsigned int mSpacing; - unsigned int mTexColumns; - unsigned int mTexRows; - unsigned int mNumChars; - - Pack * mPack; - - const char * mData; - Uint32 mDataSize; - - void start(); - - void reset(); - private: - bool mTexLoaded; - bool mFontLoaded; - - void loadFont(); - void loadFromPath(); - void loadFromMemory(); - void loadFromPack(); - void loadFromTex(); -}; - -}} - -#endif - - diff --git a/include/eepp/graphics/ttffont.hpp b/include/eepp/graphics/ttffont.hpp deleted file mode 100755 index a2eb3990b..000000000 --- a/include/eepp/graphics/ttffont.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef EE_GRAPHICSCTTFFONT_H -#define EE_GRAPHICSCTTFFONT_H - -#include -#include -#include - -namespace HaikuTTF { - class hkFont; -} - -namespace EE { namespace Graphics { - -/** @brief This class loads True Type Font and then draw strings to the screen. */ -class EE_API TTFFont : public Font { - public: - enum OutlineMethods - { - OutlineEntropia, //! Slow, but better for small fonts - OutlineFreetype //! Faster, usually better for big fonts - }; - - //! Let the user select the default method to use for outlining the glyphs - static OutlineMethods OutlineMethod; - - /** Creates an instance of a true type font */ - static TTFFont * New( const std::string FontName ); - - /** The destructor will not unload the texture from memory. If you want that you'll have to remove it manually ( TextureFactory::instance()->remove( MyFontInstance->GetTexId() ) ). */ - virtual ~TTFFont(); - - /** Loads a True Type Font from path - * @param Filepath The TTF file path - * @param Size The Size Width and Height for the font. - * @param Style The Font Style - * @param NumCharsToGen Determine the number of characters to generate ( from char 0 to ... x ) - * @param FontColor The Font color (this is the texture font color, if you plan to use a custom color and use outline, set it ) - * @param OutlineSize The Ouline Size - * @param OutlineColor The Outline Color - * @param AddPixelSeparator Indicates if separates the glyphs by a pixel to avoid problems with font scaling - * @return If success - */ - bool load( const std::string& Filepath, const unsigned int& Size, EE_TTF_FONT_STYLE Style = TTF_STYLE_NORMAL, const Uint16& NumCharsToGen = 512, const RGB& FontColor = RGB(), const Uint8& OutlineSize = 0, const RGB& OutlineColor = RGB(0,0,0), const bool& AddPixelSeparator = true ); - - /** Loads a True Type Font from pack - * @param Pack Pointer to the pack instance - * @param FilePackPath The path of the file inside the pack - * @param Size The Size of the Font - * @param Style The Font Style - * @param NumCharsToGen Determine the number of characters to generate ( from char 0 to ... x ) - * @param FontColor The Font color (this is the texture font color, if you plan to use a custom color and use outline, set it ) - * @param OutlineSize The Ouline Size - * @param OutlineColor The Outline Color - * @param AddPixelSeparator Indicates if separates the glyphs by a pixel to avoid problems with font scaling - * @return If success - */ - bool loadFromPack( Pack* Pack, const std::string& FilePackPath, const unsigned int& Size, EE_TTF_FONT_STYLE Style = TTF_STYLE_NORMAL, const Uint16& NumCharsToGen = 512, const RGB& FontColor = RGB(), const Uint8& OutlineSize = 0, const RGB& OutlineColor = RGB(0,0,0), const bool& AddPixelSeparator = true ); - - /** Loads a True Type Font from memory - * @param TTFData The pointer to the data - * @param TTFDataSize The size of the data - * @param Size The Size of the Font - * @param Style The Font Style - * @param NumCharsToGen Determine the number of characters to generate ( from char 0 to ... x ) - * @param FontColor The Font color (this is the texture font color, if you plan to use a custom color and use outline, set it ) - * @param OutlineSize The Ouline Size - * @param OutlineColor The Outline Color - * @param AddPixelSeparator Indicates if separates the glyphs by a pixel to avoid problems with font scaling - * @return If success - */ - bool loadFromMemory( Uint8* TTFData, const unsigned int& TTFDataSize, const unsigned int& Size, EE_TTF_FONT_STYLE Style = TTF_STYLE_NORMAL, const Uint16& NumCharsToGen = 512, const RGB& FontColor = RGB(), const Uint8& OutlineSize = 0, const RGB& OutlineColor = RGB(0,0,0), const bool& AddPixelSeparator = true ); - - /** Save the texture generated from the TTF file to disk */ - bool saveTexture( const std::string& Filepath, const EE_SAVE_TYPE& Format = SAVE_TYPE_PNG ); - - /** Save the characters coordinates to use it later to load the Texture Font */ - bool saveCoordinates( const std::string& Filepath ); - - /** Save the texture generated from the TTF file and the character coordinates. */ - bool save( const std::string& TexturePath, const std::string& CoordinatesDatPath, const EE_SAVE_TYPE& Format = SAVE_TYPE_PNG ); - protected: - friend class TTFFontLoader; - - HaikuTTF::hkFont * mFont; - HaikuTTF::hkFont * mFontOutline; - ColorA * mPixels; - - std::string mFilepath; - Uint32 mNumChars; - Uint8 mOutlineSize; - - RGB mFontColor; - RGB mOutlineColor; - - EE_TTF_FONT_STYLE mStyle; - - Float mTexWidth; - Float mTexHeight; - - bool mLoadedFromMemory; - bool mThreadedLoading; - bool mTexReady; - - TTFFont( const std::string FontName ); - - bool threadedLoading() const; - - void threadedLoading( const bool& isThreaded ); - - void updateLoading(); - - bool iLoad( const unsigned int& Size, EE_TTF_FONT_STYLE Style, const Uint16& NumCharsToGen, const RGB& FontColor, Uint8 OutlineSize, const RGB& OutlineColor, const bool& AddPixelSeparator ); - - void makeOutline( Uint8 *in, Uint8 *out, Int16 w, Int16 h, Int16 OutlineSize ); - - void rebuildFromGlyphs(); -}; - -}} - -#endif diff --git a/include/eepp/graphics/ttffontloader.hpp b/include/eepp/graphics/ttffontloader.hpp deleted file mode 100644 index ba2db6888..000000000 --- a/include/eepp/graphics/ttffontloader.hpp +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef EE_GRAPHICSCTTFFONTLOADER -#define EE_GRAPHICSCTTFFONTLOADER - -#include -#include -#include -#include - -namespace EE { namespace Graphics { - -/** @brief The TTF Font loader loads a true type font to memory in synchronous or asynchronous mode. -@see ObjectLoader -*/ -class EE_API TTFFontLoader : public ObjectLoader { - public: - /** Load a True Type Font from path - * @param FontName The font name - * @param Filepath The TTF file path - * @param Size The Size Width and Height for the font. - * @param Style The Font Style - * @param NumCharsToGen Determine the number of characters to generate ( from char 0 to ... x ) - * @param FontColor The Font color (this is the texture font color, if you plan to use a custom color and use outline, set it ) - * @param OutlineSize The Ouline Size - * @param OutlineColor The Outline Color - * @param AddPixelSeparator Indicates if separates the glyphs by a pixel to avoid problems with font scaling - */ - TTFFontLoader( const std::string& FontName, const std::string& Filepath, const unsigned int& Size, EE_TTF_FONT_STYLE Style = TTF_STYLE_NORMAL, const Uint16& NumCharsToGen = 512, const RGB& FontColor = RGB(), const Uint8& OutlineSize = 0, const RGB& OutlineColor = RGB(0,0,0), const bool& AddPixelSeparator = true ); - - /** Load a True Type Font from a Pack - * @param FontName The font name - * @param Pack Pointer to the pack instance - * @param FilePackPath The path of the file inside the pack - * @param Size The Size of the Font - * @param Style The Font Style - * @param NumCharsToGen Determine the number of characters to generate ( from char 0 to ... x ) - * @param FontColor The Font color (this is the texture font color, if you plan to use a custom color and use outline, set it ) - * @param OutlineSize The Ouline Size - * @param OutlineColor The Outline Color - * @param AddPixelSeparator Indicates if separates the glyphs by a pixel to avoid problems with font scaling - */ - TTFFontLoader( const std::string& FontName, Pack * Pack, const std::string& FilePackPath, const unsigned int& Size, EE_TTF_FONT_STYLE Style = TTF_STYLE_NORMAL, const Uint16& NumCharsToGen = 512, const RGB& FontColor = RGB(), const Uint8& OutlineSize = 0, const RGB& OutlineColor = RGB(0,0,0), const bool& AddPixelSeparator = true ); - - /** Loads a True Type Font from memory - * @param FontName The font name - * @param TTFData The pointer to the data - * @param TTFDataSize The size of the data - * @param Size The Size of the Font - * @param Style The Font Style - * @param NumCharsToGen Determine the number of characters to generate ( from char 0 to ... x ) - * @param FontColor The Font color (this is the texture font color, if you plan to use a custom color and use outline, set it ) - * @param OutlineSize The Ouline Size - * @param OutlineColor The Outline Color - * @param AddPixelSeparator Indicates if separates the glyphs by a pixel to avoid problems with font scaling - */ - TTFFontLoader( const std::string& FontName, Uint8* TTFData, const unsigned int& TTFDataSize, const unsigned int& Size, EE_TTF_FONT_STYLE Style = TTF_STYLE_NORMAL, const Uint16& NumCharsToGen = 512, const RGB& FontColor = RGB(), const Uint8& OutlineSize = 0, const RGB& OutlineColor = RGB(0,0,0), const bool& AddPixelSeparator = true ); - - virtual ~TTFFontLoader(); - - /** This must be called for the asynchronous mode to update the texture data to the GPU, the call must be done from the same thread that the GL Context was created ( the main thread ). - ** The TTF Font creates texture from the data obtained from the true type file. - ** @see ObjectLoader::Update */ - void update(); - - /** Releases the Font instance and the texture loaded ( if was already loaded ), it will destroy the font texture from memory */ - void unload(); - - /** @return The font name. */ - const std::string& getId() const; - - /** @return The font instance if already exists, otherwise returns NULL. */ - Graphics::Font * getFont() const; - protected: - enum TTF_LOAD_TYPE - { - TTF_LT_PATH = 1, - TTF_LT_MEM = 2, - TTF_LT_PACK = 3 - }; - - Uint32 mLoadType; // From memory, from path, from pack - - TTFFont * mFont; - - std::string mFontName; - std::string mFilepath; - unsigned int mSize; - EE_TTF_FONT_STYLE mStyle; - Uint16 mNumCharsToGen; - RGB mFontColor; - Uint8 mOutlineSize; - RGB mOutlineColor; - bool mAddPixelSeparator; - Pack * mPack; - Uint8 * mData; - unsigned int mDataSize; - - void start(); - - void reset(); - private: - bool mFontLoaded; - - void loadFromPath(); - void loadFromMemory(); - void loadFromPack(); - void create(); -}; - -}} - -#endif - - diff --git a/include/eepp/ui/uithemeconfig.hpp b/include/eepp/ui/uithemeconfig.hpp index 12a0064e2..ed895856c 100644 --- a/include/eepp/ui/uithemeconfig.hpp +++ b/include/eepp/ui/uithemeconfig.hpp @@ -60,10 +60,19 @@ class FontStyleConfig { FontSelectionBackColor = color; } + Uint32 getFontCharacterSize() const { + return FontCharacterSize; + } + + void setFontCharacterSize(const Uint32 & value) { + FontCharacterSize = value; + } + FontStyleConfig() {} FontStyleConfig( const FontStyleConfig& fontStyleConfig ) : Font( fontStyleConfig.Font ), + FontCharacterSize( fontStyleConfig.FontCharacterSize ), FontColor( fontStyleConfig.FontColor ), FontShadowColor( fontStyleConfig.FontShadowColor ), FontOverColor( fontStyleConfig.FontOverColor ), @@ -73,6 +82,7 @@ class FontStyleConfig { void updateFontStyleConfig( const FontStyleConfig& fontStyleConfig ) { Font = fontStyleConfig.Font ; + FontCharacterSize = fontStyleConfig.FontCharacterSize; FontColor = fontStyleConfig.FontColor ; FontShadowColor = fontStyleConfig.FontShadowColor ; FontOverColor = fontStyleConfig.FontOverColor ; @@ -80,13 +90,13 @@ class FontStyleConfig { FontSelectionBackColor = fontStyleConfig.FontSelectionBackColor ; } - Graphics::Font * Font; - Uint32 FontCharacterSize; - ColorA FontColor; - ColorA FontShadowColor; - ColorA FontOverColor; - ColorA FontSelectedColor; - ColorA FontSelectionBackColor; + Graphics::Font * Font = NULL; + Uint32 FontCharacterSize = 12; + ColorA FontColor = ColorA(255,255,255,255); + ColorA FontShadowColor = ColorA(50,50,50,230); + ColorA FontOverColor = ColorA(255,255,255,255); + ColorA FontSelectedColor = ColorA(255,255,255,255); + ColorA FontSelectionBackColor = ColorA(255,255,255,255); }; class TabWidgetStyleConfig : public FontStyleConfig { diff --git a/include/eepp/ui/uithememanager.hpp b/include/eepp/ui/uithememanager.hpp index 4593c3792..673c029e2 100644 --- a/include/eepp/ui/uithememanager.hpp +++ b/include/eepp/ui/uithememanager.hpp @@ -58,7 +58,7 @@ class EE_API UIThemeManager : public ResourceManager { const Sizei& getCursorSize() const; - TooltipStyleConfig getDefaultFontStyleConfig(); + FontStyleConfig getDefaultFontStyleConfig(); protected: Font * mFont; UITheme * mThemeDefault; diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 069851b88..ec5d5e946 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -1,6 +1,7 @@ ../../include/eepp/graphics/font.hpp ../../include/eepp/graphics/fonttruetype.hpp -../../include/eepp/graphics/text.hpp +../../include/eepp/graphics/fonttruetypeloader.hpp +../../include/eepp/graphics/textcache.hpp ../../include/eepp/math/interpolation1d.hpp ../../include/eepp/math/interpolation2d.hpp ../../include/eepp/ui/uidragablecontrol.hpp @@ -16,10 +17,11 @@ ../../include/eepp/ui/uiwidget.hpp ../../src/eepp/gaming/mapobjectlayer.cpp ../../src/eepp/graphics/fonttruetype.cpp +../../src/eepp/graphics/fonttruetypeloader.cpp ../../src/eepp/graphics/globalbatchrenderer.cpp ../../src/eepp/graphics/pixeldensity.cpp ../../src/eepp/graphics/pixelperfect.cpp -../../src/eepp/graphics/text.cpp +../../src/eepp/graphics/textcache.cpp ../../src/eepp/math/interpolation1d.cpp ../../src/eepp/math/interpolation2d.cpp ../../src/eepp/ui/uidragablecontrol.cpp diff --git a/src/eepp/graphics/console.cpp b/src/eepp/graphics/console.cpp index 2743bbcf9..daee0ce24 100755 --- a/src/eepp/graphics/console.cpp +++ b/src/eepp/graphics/console.cpp @@ -108,10 +108,7 @@ void Console::create( Font* Font, const bool& MakeDefaultCommands, const bool& A mTextCache.setFont( mFont ); - mFontSize = (Float)( mFont->getFontSize() * 1.25 ); - - if ( mFont->getFontHeight() < mFontSize && ( mFont->getFontHeight() != mFont->getFontSize() || mFont->getLineSkip() != (Int32)mFont->getFontHeight() ) ) - mFontSize = mFont->getFontHeight(); + mFontSize = (Float)( mTextCache.getFont()->getLineSpacing( mTextCache.getCharacterSizePx() ) ); if ( TextureId > 0 ) mTexId = TextureId; @@ -579,7 +576,7 @@ void Console::getFilesFrom( std::string txt, const Uint32& curPos ) { } Int32 Console::linesInScreen() { - return static_cast ( (mCurHeight / mFontSize) - 1 ); + return static_cast ( ( mCurHeight / mFontSize ) - 1 ); } void Console::privInputCallback( InputEvent * Event ) { diff --git a/src/eepp/graphics/font.cpp b/src/eepp/graphics/font.cpp index ee8b295ba..00083ace8 100644 --- a/src/eepp/graphics/font.cpp +++ b/src/eepp/graphics/font.cpp @@ -6,13 +6,7 @@ namespace EE { namespace Graphics { Font::Font( const Uint32& Type, const std::string& Name ) : - mType( Type ), - mTexId(0), - mHeight(0), - mSize(0), - mLineSkip(0), - mAscent(0), - mDescent(0) + mType( Type ) { this->setName( Name ); FontManager::instance()->add( this ); @@ -26,59 +20,60 @@ Font::~Font() { } } -Uint32 Font::getFontSize() const { - return mSize; +const Uint32& Font::getType() const { + return mType; } -Uint32 Font::getFontHeight() const { - return mHeight; +const std::string& Font::getName() const { + return mFontName; } -Int32 Font::getLineSkip() const { - return mLineSkip; +void Font::setName( const std::string& name ) { + mFontName = name; + mFontHash = String::hash( mFontName ); } -void Font::cacheWidth( const String& Text, std::vector& LinesWidth, Float& CachedWidth, int& NumLines , int& LargestLineCharCount ) { +const Uint32& Font::getId() { + return mFontHash; +} + +void Font::cacheWidth( const String& Text, const Uint32& characterSize, bool bold, Float outlineThickness, std::vector& LinesWidth, Float& CachedWidth, int& NumLines , int& LargestLineCharCount ) { LinesWidth.clear(); Float Width = 0, MaxWidth = 0; Int32 CharID; Int32 Lines = 1; Int32 CharCount = 0; - - Int32 tGlyphSize = (Int32)mGlyphs.size(); - LargestLineCharCount = 0; for (std::size_t i = 0; i < Text.size(); ++i) { CharID = static_cast( Text.at(i) ); + Glyph glyph = getGlyph( CharID, characterSize, bold, outlineThickness ); - if ( CharID >= 0 && CharID < tGlyphSize ) { - Width += mGlyphs[CharID].Advance; + Width += glyph.advance; - CharCount++; + CharCount++; - if ( CharID == '\t' ) - Width += mGlyphs[CharID].Advance * 3; + if ( CharID == '\t' ) + Width += glyph.advance * 3; - if ( CharID == '\n' ) { - Lines++; + if ( CharID == '\n' ) { + Lines++; - Float lWidth = ( CharID == '\t' ) ? mGlyphs[CharID].Advance * 4.f : mGlyphs[CharID].Advance; + Float lWidth = ( CharID == '\t' ) ? glyph.advance * 4.f : glyph.advance; - LinesWidth.push_back( Width - lWidth ); + LinesWidth.push_back( Width - lWidth ); - Width = 0; + Width = 0; - CharCount = 0; - } else { - if ( CharCount > LargestLineCharCount ) - LargestLineCharCount = CharCount; - } - - if ( Width > MaxWidth ) - MaxWidth = Width; + CharCount = 0; + } else { + if ( CharCount > LargestLineCharCount ) + LargestLineCharCount = CharCount; } + + if ( Width > MaxWidth ) + MaxWidth = Width; } if ( Text.size() && Text.at( Text.size() - 1 ) != '\n' ) { @@ -89,50 +84,48 @@ void Font::cacheWidth( const String& Text, std::vector& LinesWidth, Float NumLines = Lines; } -Int32 Font::findClosestCursorPosFromPoint( const String& Text, const Vector2i& pos ) { - Float Width = 0, lWidth = 0, Height = getFontHeight(), lHeight = 0; +Int32 Font::findClosestCursorPosFromPoint( const String& Text, const Uint32& characterSize, bool bold, Float outlineThickness, const Vector2i& pos ) { + Float Width = 0, lWidth = 0, Height = getLineSpacing(characterSize), lHeight = 0; Int32 CharID; - Int32 tGlyphSize = (Int32)mGlyphs.size(); std::size_t tSize = Text.size(); for (std::size_t i = 0; i < tSize; ++i) { CharID = static_cast( Text.at(i) ); + Glyph glyph = getGlyph( CharID, characterSize, bold, outlineThickness ); - if ( CharID >= 0 && CharID < tGlyphSize ) { - lWidth = Width; + lWidth = Width; - Width += mGlyphs[CharID].Advance; + Width += glyph.advance; - if ( CharID == '\t' ) { - Width += mGlyphs[CharID].Advance * 3; - } + if ( CharID == '\t' ) { + Width += glyph.advance * 3; + } - if ( CharID == '\n' ) { - lWidth = 0; - Width = 0; - } + if ( CharID == '\n' ) { + lWidth = 0; + Width = 0; + } - if ( pos.x <= Width && pos.x >= lWidth && pos.y <= Height && pos.y >= lHeight ) { - if ( i + 1 < tSize ) { - Int32 curDist = eeabs( pos.x - lWidth ); - Int32 nextDist = eeabs( pos.x - ( lWidth + mGlyphs[CharID].Advance ) ); + if ( pos.x <= Width && pos.x >= lWidth && pos.y <= Height && pos.y >= lHeight ) { + if ( i + 1 < tSize ) { + Int32 curDist = eeabs( pos.x - lWidth ); + Int32 nextDist = eeabs( pos.x - ( lWidth + glyph.advance ) ); - if ( nextDist < curDist ) { - return i + 1; - } + if ( nextDist < curDist ) { + return i + 1; } + } + return i; + } + + if ( CharID == '\n' ) { + lHeight = Height; + Height += getLineSpacing(characterSize); + + if ( pos.x > Width && pos.y <= lHeight ) { return i; } - - if ( CharID == '\n' ) { - lHeight = Height; - Height += getFontHeight(); - - if ( pos.x > Width && pos.y <= lHeight ) { - return i; - } - } } } @@ -143,46 +136,30 @@ Int32 Font::findClosestCursorPosFromPoint( const String& Text, const Vector2i& p return -1; } -Vector2i Font::getCursorPos( const String& Text, const Uint32& Pos ) { - Float Width = 0, Height = getFontHeight(); +Vector2i Font::getCursorPos( const String& Text, const Uint32& characterSize, bool bold, Float outlineThickness, const Uint32& Pos ) { + Float Width = 0, Height = getLineSpacing(characterSize); Int32 CharID; - Int32 tGlyphSize = mGlyphs.size(); std::size_t tSize = ( Pos < Text.size() ) ? Pos : Text.size(); for (std::size_t i = 0; i < tSize; ++i) { CharID = static_cast( Text.at(i) ); + Glyph glyph = getGlyph( CharID, characterSize, bold, outlineThickness ); - if ( CharID >= 0 && CharID < tGlyphSize ) { - Width += mGlyphs[CharID].Advance; + Width += glyph.advance; - if ( CharID == '\t' ) { - Width += mGlyphs[CharID].Advance * 3; - } + if ( CharID == '\t' ) { + Width += glyph.advance * 3; + } - if ( CharID == '\n' ) { - Width = 0; - Height += getFontHeight(); - } + if ( CharID == '\n' ) { + Width = 0; + Height += getLineSpacing(characterSize); } } return Vector2i( Width, Height ); } -const GlyphData& Font::getGlyph(const Uint32 & index) { - eeASSERT( index < mGlyphs.size() ); - return mGlyphs[ index ]; -} - -const TextureCoords& Font::getTextureCoords(const Uint32 & index) { - eeASSERT( index < mTexCoords.size() ); - return mTexCoords[ index ]; -} - -Uint32 Font::getGlyphCount() const { - return mGlyphs.size(); -} - static bool isStopSelChar( Uint32 c ) { return ( !String::isCharacter( c ) && !String::isNumber( c ) ) || ' ' == c || @@ -222,7 +199,7 @@ void Font::selectSubStringFromCursor( const String& Text, const Int32& CurPos, I } } -void Font::shrinkText( std::string& Str, const Uint32& MaxWidth ) { +void Font::shrinkText( std::string& Str, const Uint32& characterSize, bool bold, Float outlineThickness, const Uint32& MaxWidth ) { if ( !Str.size() ) return; @@ -231,55 +208,50 @@ void Font::shrinkText( std::string& Str, const Uint32& MaxWidth ) { Float tMaxWidth = (Float) MaxWidth; char * tChar = &Str[0]; char * tLastSpace = NULL; - Uint32 tGlyphSize = (Uint32)mGlyphs.size(); while ( *tChar ) { - if ( (Uint32)( *tChar ) < tGlyphSize ) { - GlyphData * pChar = &mGlyphs[ ( *tChar ) ]; - Float fCharWidth = (Float)pChar->Advance; + Glyph pChar = getGlyph( *tChar, characterSize, bold, outlineThickness ); + Float fCharWidth = (Float)pChar.advance; - if ( ( *tChar ) == '\t' ) - fCharWidth += pChar->Advance * 3; + if ( ( *tChar ) == '\t' ) + fCharWidth += pChar.advance * 3; - tWordWidth += fCharWidth; + tWordWidth += fCharWidth; - if ( ' ' == *tChar || '\0' == *( tChar + 1 ) ) { - if ( tCurWidth + tWordWidth < tMaxWidth ) { - tCurWidth += tWordWidth; - tLastSpace = tChar; + if ( ' ' == *tChar || '\0' == *( tChar + 1 ) ) { + if ( tCurWidth + tWordWidth < tMaxWidth ) { + tCurWidth += tWordWidth; + tLastSpace = tChar; - tChar++; - } else { - if ( NULL != tLastSpace ) { - *tLastSpace = '\n'; - tChar = tLastSpace + 1; - } else { - *tChar = '\n'; - } - - if ( '\0' == *( tChar + 1 ) ) - tChar++; - - tLastSpace = NULL; - tCurWidth = 0.f; - } - - tWordWidth = 0.f; - } else if ( '\n' == *tChar ) { - tWordWidth = 0.f; - tCurWidth = 0.f; - tLastSpace = NULL; tChar++; } else { - tChar++; + if ( NULL != tLastSpace ) { + *tLastSpace = '\n'; + tChar = tLastSpace + 1; + } else { + *tChar = '\n'; + } + + if ( '\0' == *( tChar + 1 ) ) + tChar++; + + tLastSpace = NULL; + tCurWidth = 0.f; } + + tWordWidth = 0.f; + } else if ( '\n' == *tChar ) { + tWordWidth = 0.f; + tCurWidth = 0.f; + tLastSpace = NULL; + tChar++; } else { - *tChar = ' '; + tChar++; } } } -void Font::shrinkText( String& Str, const Uint32& MaxWidth ) { +void Font::shrinkText( String& Str, const Uint32& characterSize, bool bold, Float outlineThickness, const Uint32& MaxWidth ) { if ( !Str.size() ) return; @@ -290,79 +262,56 @@ void Font::shrinkText( String& Str, const Uint32& MaxWidth ) { String::StringBaseType * tLastSpace = NULL; while ( *tChar ) { - if ( (String::StringBaseType)( *tChar ) < mGlyphs.size() ) { - GlyphData * pChar = &mGlyphs[ ( *tChar ) ]; - Float fCharWidth = (Float)pChar->Advance; + Glyph pChar = getGlyph( *tChar, characterSize, bold, outlineThickness ); - if ( ( *tChar ) == '\t' ) - fCharWidth += pChar->Advance * 3; + Float fCharWidth = (Float)pChar.advance; - // Add the new char width to the current word width - tWordWidth += fCharWidth; + if ( ( *tChar ) == '\t' ) + fCharWidth += pChar.advance * 3; - if ( ' ' == *tChar || '\0' == *( tChar + 1 ) ) { + // Add the new char width to the current word width + tWordWidth += fCharWidth; - // If current width plus word width is minor to the max width, continue adding - if ( tCurWidth + tWordWidth < tMaxWidth ) { - tCurWidth += tWordWidth; - tLastSpace = tChar; + if ( ' ' == *tChar || '\0' == *( tChar + 1 ) ) { - tChar++; - } else { - // If it was an space before, replace that space for an new line - // Start counting from the new line first character - if ( NULL != tLastSpace ) { - *tLastSpace = '\n'; - tChar = tLastSpace + 1; - } else { // The word is larger than the current possible width - *tChar = '\n'; - } + // If current width plus word width is minor to the max width, continue adding + if ( tCurWidth + tWordWidth < tMaxWidth ) { + tCurWidth += tWordWidth; + tLastSpace = tChar; - if ( '\0' == *( tChar + 1 ) ) - tChar++; - - // Set the last spaces as null, because is a new line - tLastSpace = NULL; - - // New line, new current width - tCurWidth = 0.f; - } - - // New word, so we reset the current word width - tWordWidth = 0.f; - } else if ( '\n' == *tChar ) { - tWordWidth = 0.f; - tCurWidth = 0.f; - tLastSpace = NULL; tChar++; } else { - tChar++; + // If it was an space before, replace that space for an new line + // Start counting from the new line first character + if ( NULL != tLastSpace ) { + *tLastSpace = '\n'; + tChar = tLastSpace + 1; + } else { // The word is larger than the current possible width + *tChar = '\n'; + } + + if ( '\0' == *( tChar + 1 ) ) + tChar++; + + // Set the last spaces as null, because is a new line + tLastSpace = NULL; + + // New line, new current width + tCurWidth = 0.f; } - } else { // Replace any unknown char as spaces. - *tChar = ' '; + + // New word, so we reset the current word width + tWordWidth = 0.f; + } else if ( '\n' == *tChar ) { + tWordWidth = 0.f; + tCurWidth = 0.f; + tLastSpace = NULL; + tChar++; + } else { + tChar++; } } } -const Uint32& Font::getTexId() const { - return mTexId; -} - -const Uint32& Font::getType() const { - return mType; -} - -const std::string& Font::getName() const { - return mFontName; -} - -void Font::setName( const std::string& name ) { - mFontName = name; - mFontHash = String::hash( mFontName ); -} - -const Uint32& Font::getId() { - return mFontHash; -} }} diff --git a/src/eepp/graphics/fonttruetype.cpp b/src/eepp/graphics/fonttruetype.cpp index 1c1c39983..4dd2ff6be 100644 --- a/src/eepp/graphics/fonttruetype.cpp +++ b/src/eepp/graphics/fonttruetype.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include @@ -31,7 +33,12 @@ namespace { namespace EE { namespace Graphics { -FontTrueType::FontTrueType() : +FontTrueType * FontTrueType::New( const std::string FontName ) { + return eeNew( FontTrueType, ( FontName ) ); +} + +FontTrueType::FontTrueType( const std::string FontName ) : + Font( FONT_TYPE_TTF, FontName ), mLibrary (NULL), mFace (NULL), mStreamRec(NULL), @@ -41,25 +48,15 @@ FontTrueType::FontTrueType() : { } -FontTrueType::FontTrueType(const FontTrueType& copy) : - mLibrary (copy.mLibrary), - mFace (copy.mFace), - mStreamRec (copy.mStreamRec), - mStroker (copy.mStroker), - mRefCount (copy.mRefCount), - mInfo (copy.mInfo), - mPages (copy.mPages), - mPixelBuffer(copy.mPixelBuffer) -{ - if (mRefCount) - (*mRefCount)++; -} - FontTrueType::~FontTrueType() { cleanup(); } bool FontTrueType::loadFromFile(const std::string& filename) { + if ( !FileSystem::fileExists( filename ) && PackManager::instance()->isFallbackToPacksActive() ) { + loadFromPack( PackManager::instance()->getPackByPath( filename ), filename ); + } + // Cleanup the previous resources cleanup(); mRefCount = new int(1); @@ -67,7 +64,7 @@ bool FontTrueType::loadFromFile(const std::string& filename) { // Initialize FreeType FT_Library library; if (FT_Init_FreeType(&library) != 0) { - std::cout << "Failed to load font \"" << filename << "\" (failed to initialize FreeType)" << std::endl; + eePRINTL( "Failed to load font \"%s\" (failed to initialize FreeType)", filename.c_str() ); return false; } mLibrary = library; @@ -75,21 +72,21 @@ bool FontTrueType::loadFromFile(const std::string& filename) { // Load the new font face from the specified file FT_Face face; if (FT_New_Face(static_cast(mLibrary), filename.c_str(), 0, &face) != 0) { - std::cout << "Failed to load font \"" << filename << "\" (failed to create the font face)" << std::endl; + eePRINTL( "Failed to load font \"%s\" (failed to create the font face)", filename.c_str() ); return false; } // Load the stroker that will be used to outline the font FT_Stroker stroker; if (FT_Stroker_New(static_cast(mLibrary), &stroker) != 0) { - std::cout << "Failed to load font \"" << filename << "\" (failed to create the stroker)" << std::endl; + eePRINTL( "Failed to load font \"%s\" (failed to create the stroker)", filename.c_str() ); return false; } mStroker = stroker; // Select the unicode character map if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) { - std::cout << "Failed to load font \"" << filename << "\" (failed to set the Unicode character set)" << std::endl; + eePRINTL( "Failed to load font \"%s\" (failed to set the Unicode character set)", filename.c_str() ); FT_Done_Face(face); return false; } @@ -111,7 +108,7 @@ bool FontTrueType::loadFromMemory(const void* data, std::size_t sizeInBytes) { // Initialize FreeType FT_Library library; if (FT_Init_FreeType(&library) != 0) { - std::cout << "Failed to load font from memory (failed to initialize FreeType)" << std::endl; + eePRINTL( "Failed to load font from memory (failed to initialize FreeType)" ); return false; } mLibrary = library; @@ -119,21 +116,21 @@ bool FontTrueType::loadFromMemory(const void* data, std::size_t sizeInBytes) { // Load the new font face from the specified file FT_Face face; if (FT_New_Memory_Face(static_cast(mLibrary), reinterpret_cast(data), static_cast(sizeInBytes), 0, &face) != 0) { - std::cout << "Failed to load font from memory (failed to create the font face)" << std::endl; + eePRINTL( "Failed to load font from memory (failed to create the font face)" ); return false; } // Load the stroker that will be used to outline the font FT_Stroker stroker; if (FT_Stroker_New(static_cast(mLibrary), &stroker) != 0) { - std::cout << "Failed to load font from memory (failed to create the stroker)" << std::endl; + eePRINTL( "Failed to load font from memory (failed to create the stroker)" ); return false; } mStroker = stroker; // Select the Unicode character map if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) { - std::cout << "Failed to load font from memory (failed to set the Unicode character set)" << std::endl; + eePRINTL( "Failed to load font from memory (failed to set the Unicode character set)" ); FT_Done_Face(face); return false; } @@ -155,7 +152,7 @@ bool FontTrueType::loadFromStream(IOStream& stream) { // Initialize FreeType FT_Library library; if (FT_Init_FreeType(&library) != 0) { - std::cout << "Failed to load font from stream (failed to initialize FreeType)" << std::endl; + eePRINTL( "Failed to load font from stream (failed to initialize FreeType)" ); return false; } mLibrary = library; @@ -182,7 +179,7 @@ bool FontTrueType::loadFromStream(IOStream& stream) { // Load the new font face from the specified stream FT_Face face; if (FT_Open_Face(static_cast(mLibrary), &args, 0, &face) != 0) { - std::cout << "Failed to load font from stream (failed to create the font face)" << std::endl; + eePRINTL( "Failed to load font from stream (failed to create the font face)" ); delete rec; return false; } @@ -190,14 +187,14 @@ bool FontTrueType::loadFromStream(IOStream& stream) { // Load the stroker that will be used to outline the font FT_Stroker stroker; if (FT_Stroker_New(static_cast(mLibrary), &stroker) != 0) { - std::cout << "Failed to load font from stream (failed to create the stroker)" << std::endl; + eePRINTL( "Failed to load font from stream (failed to create the stroker)" ); return false; } mStroker = stroker; // Select the Unicode character map if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) { - std::cout << "Failed to load font from stream (failed to set the Unicode character set)" << std::endl; + eePRINTL( "Failed to load font from stream (failed to set the Unicode character set)" ); FT_Done_Face(face); delete rec; return false; @@ -213,6 +210,20 @@ bool FontTrueType::loadFromStream(IOStream& stream) { return true; } +bool FontTrueType::loadFromPack( Pack * pack, std::string filePackPath ) { + if ( NULL == pack ) + return false; + + bool Ret = false; + SafeDataPointer PData; + + if ( pack->isOpen() && pack->extractFileToMemory( filePackPath, PData ) ) { + Ret = loadFromMemory( PData.Data, PData.DataSize ); + } + + return Ret; +} + const FontTrueType::Info& FontTrueType::getInfo() const { return mInfo; } @@ -276,6 +287,16 @@ Float FontTrueType::getLineSpacing(unsigned int characterSize) const { } } +Uint32 FontTrueType::getFontHeight(const Uint32 & characterSize) { + FT_Face face = static_cast(mFace); + + if (face && setCurrentSize(characterSize)) { + return static_cast(face->height) / static_cast(1 << 6); + } else { + return 0.f; + } +} + Float FontTrueType::getUnderlinePosition(unsigned int characterSize) const { FT_Face face = static_cast(mFace); @@ -417,7 +438,7 @@ Glyph FontTrueType::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool FT_Bitmap_Embolden(static_cast(mLibrary), &bitmap, weight, weight); if (outlineThickness != 0) - std::cout << "Failed to outline glyph (no fallback available)" << std::endl; + eePRINTL( "Failed to outline glyph (no fallback available)" ); } // Compute the glyph's advance offset @@ -540,9 +561,10 @@ Recti FontTrueType::findGlyphRect(Page& page, unsigned int width, unsigned int h newImage.copyImage(page.texture, 0, 0); //page.texture->unlock(); - page.texture->replace(&newImage); } else { + page.texture->replace(&newImage); + } else { // Oops, we've reached the maximum texture size... - std::cout << "Failed to add a new character to the font: the maximum texture size has been reached" << std::endl; + eePRINTL( "Failed to add a new character to the font: the maximum texture size has been reached" ); return Recti(0, 0, 2, 2); } } @@ -578,11 +600,11 @@ bool FontTrueType::setCurrentSize(unsigned int characterSize) const { // fail if the requested size is not available if (!FT_IS_SCALABLE(face)) { - std::cout << "Failed to set bitmap font size to " << characterSize << std::endl; - std::cout << "Available sizes are: "; + eePRINTL( "Failed to set bitmap font size to %d", characterSize ); + eePRINTL( "Available sizes are: " ); for (int i = 0; i < face->num_fixed_sizes; ++i) - std::cout << face->available_sizes[i].height << " "; - std::cout << std::endl; + eePRINT( "%d ", face->available_sizes[i].height ); + eePRINTL(""); } } @@ -615,280 +637,4 @@ FontTrueType::Page::~Page() { TextureFactory::instance()->remove( texture->getId() ); } -void FontTrueType::cacheWidth( const String& Text, const Uint32& characterSize, bool bold, Float outlineThickness, std::vector& LinesWidth, Float& CachedWidth, int& NumLines , int& LargestLineCharCount ) { - LinesWidth.clear(); - - Float Width = 0, MaxWidth = 0; - Int32 CharID; - Int32 Lines = 1; - Int32 CharCount = 0; - LargestLineCharCount = 0; - - for (std::size_t i = 0; i < Text.size(); ++i) { - CharID = static_cast( Text.at(i) ); - Glyph glyph = getGlyph( CharID, characterSize, bold, outlineThickness ); - - Width += glyph.advance; - - CharCount++; - - if ( CharID == '\t' ) - Width += glyph.advance * 3; - - if ( CharID == '\n' ) { - Lines++; - - Float lWidth = ( CharID == '\t' ) ? glyph.advance * 4.f : glyph.advance; - - LinesWidth.push_back( Width - lWidth ); - - Width = 0; - - CharCount = 0; - } else { - if ( CharCount > LargestLineCharCount ) - LargestLineCharCount = CharCount; - } - - if ( Width > MaxWidth ) - MaxWidth = Width; - } - - if ( Text.size() && Text.at( Text.size() - 1 ) != '\n' ) { - LinesWidth.push_back( Width ); - } - - CachedWidth = MaxWidth; - NumLines = Lines; -} - -Int32 FontTrueType::findClosestCursorPosFromPoint( const String& Text, const Uint32& characterSize, bool bold, Float outlineThickness, const Vector2i& pos ) { - Float Width = 0, lWidth = 0, Height = getLineSpacing(characterSize), lHeight = 0; - Int32 CharID; - std::size_t tSize = Text.size(); - - for (std::size_t i = 0; i < tSize; ++i) { - CharID = static_cast( Text.at(i) ); - Glyph glyph = getGlyph( CharID, characterSize, bold, outlineThickness ); - - lWidth = Width; - - Width += glyph.advance; - - if ( CharID == '\t' ) { - Width += glyph.advance * 3; - } - - if ( CharID == '\n' ) { - lWidth = 0; - Width = 0; - } - - if ( pos.x <= Width && pos.x >= lWidth && pos.y <= Height && pos.y >= lHeight ) { - if ( i + 1 < tSize ) { - Int32 curDist = eeabs( pos.x - lWidth ); - Int32 nextDist = eeabs( pos.x - ( lWidth + glyph.advance ) ); - - if ( nextDist < curDist ) { - return i + 1; - } - } - - return i; - } - - if ( CharID == '\n' ) { - lHeight = Height; - Height += getLineSpacing(characterSize); - - if ( pos.x > Width && pos.y <= lHeight ) { - return i; - } - } - } - - if ( pos.x >= Width ) { - return tSize; - } - - return -1; -} - -Vector2i FontTrueType::getCursorPos( const String& Text, const Uint32& characterSize, bool bold, Float outlineThickness, const Uint32& Pos ) { - Float Width = 0, Height = getLineSpacing(characterSize); - Int32 CharID; - std::size_t tSize = ( Pos < Text.size() ) ? Pos : Text.size(); - - for (std::size_t i = 0; i < tSize; ++i) { - CharID = static_cast( Text.at(i) ); - Glyph glyph = getGlyph( CharID, characterSize, bold, outlineThickness ); - - Width += glyph.advance; - - if ( CharID == '\t' ) { - Width += glyph.advance * 3; - } - - if ( CharID == '\n' ) { - Width = 0; - Height += getLineSpacing(characterSize); - } - } - - return Vector2i( Width, Height ); -} - -static bool isStopSelChar( Uint32 c ) { - return ( !String::isCharacter( c ) && !String::isNumber( c ) ) || - ' ' == c || - '.' == c || - ',' == c || - ';' == c || - ':' == c || - '\n' == c || - '"' == c || - '\'' == c; -} - -void FontTrueType::selectSubStringFromCursor( const String& Text, const Uint32& characterSize, bool bold, Float outlineThickness, const Int32& CurPos, Int32& InitCur, Int32& EndCur ) { - InitCur = 0; - EndCur = Text.size(); - - for ( std::size_t i = CurPos; i < Text.size(); i++ ) { - if ( isStopSelChar( Text[i] ) ) { - EndCur = i; - break; - } - } - - if ( 0 == CurPos ) { - InitCur = 0; - } - - for ( Int32 i = CurPos; i >= 0; i-- ) { - if ( isStopSelChar( Text[i] ) ) { - InitCur = i + 1; - break; - } - } - - if ( InitCur == EndCur ) { - InitCur = EndCur = -1; - } -} - -void FontTrueType::shrinkText( std::string& Str, const Uint32& characterSize, bool bold, Float outlineThickness, const Uint32& MaxWidth ) { - if ( !Str.size() ) - return; - - Float tCurWidth = 0.f; - Float tWordWidth = 0.f; - Float tMaxWidth = (Float) MaxWidth; - char * tChar = &Str[0]; - char * tLastSpace = NULL; - - while ( *tChar ) { - Glyph pChar = getGlyph( *tChar, characterSize, bold, outlineThickness ); - Float fCharWidth = (Float)pChar.advance; - - if ( ( *tChar ) == '\t' ) - fCharWidth += pChar.advance * 3; - - tWordWidth += fCharWidth; - - if ( ' ' == *tChar || '\0' == *( tChar + 1 ) ) { - if ( tCurWidth + tWordWidth < tMaxWidth ) { - tCurWidth += tWordWidth; - tLastSpace = tChar; - - tChar++; - } else { - if ( NULL != tLastSpace ) { - *tLastSpace = '\n'; - tChar = tLastSpace + 1; - } else { - *tChar = '\n'; - } - - if ( '\0' == *( tChar + 1 ) ) - tChar++; - - tLastSpace = NULL; - tCurWidth = 0.f; - } - - tWordWidth = 0.f; - } else if ( '\n' == *tChar ) { - tWordWidth = 0.f; - tCurWidth = 0.f; - tLastSpace = NULL; - tChar++; - } else { - tChar++; - } - } -} - -void FontTrueType::shrinkText( String& Str, const Uint32& characterSize, bool bold, Float outlineThickness, const Uint32& MaxWidth ) { - if ( !Str.size() ) - return; - - Float tCurWidth = 0.f; - Float tWordWidth = 0.f; - Float tMaxWidth = (Float) MaxWidth; - String::StringBaseType * tChar = &Str[0]; - String::StringBaseType * tLastSpace = NULL; - - while ( *tChar ) { - Glyph pChar = getGlyph( *tChar, characterSize, bold, outlineThickness ); - - Float fCharWidth = (Float)pChar.advance; - - if ( ( *tChar ) == '\t' ) - fCharWidth += pChar.advance * 3; - - // Add the new char width to the current word width - tWordWidth += fCharWidth; - - if ( ' ' == *tChar || '\0' == *( tChar + 1 ) ) { - - // If current width plus word width is minor to the max width, continue adding - if ( tCurWidth + tWordWidth < tMaxWidth ) { - tCurWidth += tWordWidth; - tLastSpace = tChar; - - tChar++; - } else { - // If it was an space before, replace that space for an new line - // Start counting from the new line first character - if ( NULL != tLastSpace ) { - *tLastSpace = '\n'; - tChar = tLastSpace + 1; - } else { // The word is larger than the current possible width - *tChar = '\n'; - } - - if ( '\0' == *( tChar + 1 ) ) - tChar++; - - // Set the last spaces as null, because is a new line - tLastSpace = NULL; - - // New line, new current width - tCurWidth = 0.f; - } - - // New word, so we reset the current word width - tWordWidth = 0.f; - } else if ( '\n' == *tChar ) { - tWordWidth = 0.f; - tCurWidth = 0.f; - tLastSpace = NULL; - tChar++; - } else { - tChar++; - } - } -} - }} diff --git a/src/eepp/graphics/fonttruetypeloader.cpp b/src/eepp/graphics/fonttruetypeloader.cpp new file mode 100644 index 000000000..319a039bc --- /dev/null +++ b/src/eepp/graphics/fonttruetypeloader.cpp @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include + +namespace EE { namespace Graphics { + +FontTrueTypeLoader::FontTrueTypeLoader( const std::string& FontName, const std::string& Filepath ) : + ObjectLoader( FontTTFLoaderType ), + mLoadType( TTF_LT_PATH ), + mFontName( FontName ), + mFilepath( Filepath ), + mFontLoaded( false ) +{ + create(); +} + +FontTrueTypeLoader::FontTrueTypeLoader( const std::string& FontName, System::Pack * Pack, const std::string& FilePackPath ) : + ObjectLoader( FontTTFLoaderType ), + mLoadType( TTF_LT_PACK ), + mFontName( FontName ), + mFilepath( FilePackPath ), + mPack( Pack ), + mFontLoaded( false ) +{ + create(); +} + +FontTrueTypeLoader::FontTrueTypeLoader( const std::string& FontName, Uint8* TTFData, const unsigned int& TTFDataSize ) : + ObjectLoader( FontTTFLoaderType ), + mLoadType( TTF_LT_MEM ), + mFontName( FontName ), + mData( TTFData ), + mDataSize( TTFDataSize ), + mFontLoaded( false ) +{ + create(); +} + +FontTrueTypeLoader::FontTrueTypeLoader( const std::string& FontName, IOStream& stream ) : + ObjectLoader( FontTTFLoaderType ), + mLoadType( TTF_LT_MEM ), + mFontName( FontName ), + mIOStream( &stream ), + mFontLoaded( false ) +{ + create(); +} + +FontTrueTypeLoader::~FontTrueTypeLoader() { +} + +void FontTrueTypeLoader::create() { + mFont = FontTrueType::New( mFontName ); +} + +void FontTrueTypeLoader::start() { + ObjectLoader::start(); + + if ( TTF_LT_PATH == mLoadType ) + loadFromFile(); + else if ( TTF_LT_MEM == mLoadType ) + loadFromMemory(); + else if ( TTF_LT_PACK == mLoadType ) + loadFromPack(); + else if ( TTF_LT_STREAM == mLoadType ) + loadFromStream(); + + mFontLoaded = true; + + if ( !mThreaded ) + update(); +} + +void FontTrueTypeLoader::update() { + if ( !mLoaded && mFontLoaded ) { + setLoaded(); + } +} + +const std::string& FontTrueTypeLoader::getId() const { + return mFontName; +} + +void FontTrueTypeLoader::loadFromFile() { + mFont->loadFromFile( mFilepath ); +} + +void FontTrueTypeLoader::loadFromMemory() { + mFont->loadFromMemory( mData, mDataSize ); +} + +void FontTrueTypeLoader::loadFromPack() { + mFont->loadFromPack( mPack, mFilepath ); +} + +void FontTrueTypeLoader::loadFromStream() { + mFont->loadFromStream( *mIOStream ); +} + +Graphics::Font * FontTrueTypeLoader::getFont() const { + return mFont; +} + +void FontTrueTypeLoader::unload() { + if ( mLoaded ) { + FontManager::instance()->remove( mFont ); + + reset(); + } +} + +void FontTrueTypeLoader::reset() { + ObjectLoader::reset(); + + mFontLoaded = false; +} + +}} diff --git a/src/eepp/graphics/text.cpp b/src/eepp/graphics/text.cpp deleted file mode 100644 index 13bf067b7..000000000 --- a/src/eepp/graphics/text.cpp +++ /dev/null @@ -1,618 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -namespace EE { namespace Graphics { - // Add an underline or strikethrough line to the vertex array - static void addLine(std::vector& vertices, std::vector& colors, Float lineLength, Float lineTop, const EE::System::ColorA& color, Float offset, Float thickness, Float outlineThickness, Sizei textureSize, Int32 centerDiffX) { - Float top = std::floor(lineTop + offset - (thickness / 2) + 0.5f); - Float bottom = top + std::floor(thickness + 0.5f); - Float u1 = 0; - Float v1 = 0; - Float u2 = 1 / (Float)textureSize.getWidth(); - Float v2 = 1 / (Float)textureSize.getHeight(); - - if ( GLi->quadsSupported() ) { - VertexCoords vc; - - vc.TexCoords[0] = u1; - vc.TexCoords[1] = v1; - vc.Vertex[0] = centerDiffX + -outlineThickness; - vc.Vertex[1] = top - outlineThickness; - colors.push_back( color ); - vertices.push_back( vc ); - - vc.TexCoords[0] = u1; - vc.TexCoords[1] = v2; - vc.Vertex[0] = centerDiffX + -outlineThickness; - vc.Vertex[1] = bottom + outlineThickness; - colors.push_back( color ); - vertices.push_back( vc ); - - vc.TexCoords[0] = u2; - vc.TexCoords[1] = v2; - vc.Vertex[0] = centerDiffX + lineLength + outlineThickness; - vc.Vertex[1] = bottom + outlineThickness; - colors.push_back( color ); - vertices.push_back( vc ); - - vc.TexCoords[0] = u2; - vc.TexCoords[1] = v1; - vc.Vertex[0] = centerDiffX + lineLength + outlineThickness; - vc.Vertex[1] = top - outlineThickness; - colors.push_back( color ); - vertices.push_back( vc ); - } else { - - } - } - - // Add a glyph quad to the vertex array - static void addGlyphQuad(std::vector& vertices, std::vector& colors, Vector2f position, const EE::System::ColorA& color, const EE::Graphics::Glyph& glyph, Float italic, Float outlineThickness, Sizei textureSize, Int32 centerDiffX) { - Float left = glyph.bounds.Left; - Float top = glyph.bounds.Top; - Float right = glyph.bounds.Left + glyph.bounds.Right; - Float bottom = glyph.bounds.Top + glyph.bounds.Bottom; - - Float u1 = static_cast(glyph.textureRect.Left) / (Float)textureSize.getWidth(); - Float v1 = static_cast(glyph.textureRect.Top) / (Float)textureSize.getHeight(); - Float u2 = static_cast(glyph.textureRect.Left + glyph.textureRect.Right) / (Float)textureSize.getWidth(); - Float v2 = static_cast(glyph.textureRect.Top + glyph.textureRect.Bottom) / (Float)textureSize.getHeight(); - - if ( GLi->quadsSupported() ) { - VertexCoords vc; - - vc.TexCoords[0] = u1; - vc.TexCoords[1] = v1; - vc.Vertex[0] = centerDiffX + position.x + left - italic * top - outlineThickness; - vc.Vertex[1] = position.y + top - outlineThickness; - colors.push_back( color ); - vertices.push_back( vc ); - - vc.TexCoords[0] = u1; - vc.TexCoords[1] = v2; - vc.Vertex[0] = centerDiffX + position.x + left - italic * bottom - outlineThickness; - vc.Vertex[1] = position.y + bottom - outlineThickness; - colors.push_back( color ); - vertices.push_back( vc ); - - vc.TexCoords[0] = u2; - vc.TexCoords[1] = v2; - vc.Vertex[0] = centerDiffX + position.x + right - italic * bottom - outlineThickness; - vc.Vertex[1] = position.y + bottom - outlineThickness; - colors.push_back( color ); - vertices.push_back( vc ); - - vc.TexCoords[0] = u2; - vc.TexCoords[1] = v1; - vc.Vertex[0] = centerDiffX + position.x + right - italic * top - outlineThickness; - vc.Vertex[1] = position.y + top - outlineThickness; - colors.push_back( color ); - vertices.push_back( vc ); - } else { - - } - } -}} - -namespace EE { namespace Graphics { - -Text::Text() : - mString(), - mFont(NULL), - mCharacterSize(30), - mStyle(Regular), - mFillColor(255, 255, 255, 255), - mOutlineColor(0, 0, 0, 255), - mOutlineThickness (0), - mGeometryNeedUpdate(false), - mCachedWidth(0), - mNumLines(0), - mLargestLineCharCount(0), - mFontShadowColor( ColorA( 0, 0, 0, 255 ) ), - mFlags(0) -{ -} - -Text::Text(const String& string, FontTrueType * font, unsigned int characterSize) : - mString(string), - mFont(font), - mCharacterSize(characterSize), - mStyle(Regular), - mFillColor(255, 255, 255, 255), - mOutlineColor(0, 0, 0, 255), - mOutlineThickness(0), - mGeometryNeedUpdate(true), - mCachedWidth(0), - mNumLines(0), - mLargestLineCharCount(0), - mFontShadowColor( ColorA( 0, 0, 0, 255 ) ), - mFlags(0) -{ -} - -void Text::setText(const String& string) { - if (mString != string) { - mString = string; - mGeometryNeedUpdate = true; - cacheWidth(); - } -} - -void Text::setFontTrueType(FontTrueType * font) { - if (mFont != font) { - mFont = font; - mGeometryNeedUpdate = true; - cacheWidth(); - } -} - -void Text::setCharacterSize(unsigned int size) { - if (mCharacterSize != size) { - mCharacterSize = size; - mGeometryNeedUpdate = true; - cacheWidth(); - } -} - -void Text::setStyle(Uint32 style) { - if (mStyle != style) { - mStyle = style; - mGeometryNeedUpdate = true; - cacheWidth(); - } -} - -void Text::setColor(const ColorA & color) { - setFillColor(color); -} - -void Text::setFillColor(const ColorA& color) { - if (color != mFillColor) { - mFillColor = color; - - // Change vertex colors directly, no need to update whole geometry - // (if geometry is updated anyway, we can skip this step) - if (!mGeometryNeedUpdate) { - mColors.assign( mVertices.size(), mFillColor ); - } - } -} - -void Text::setOutlineColor(const ColorA& color) { - if (color != mOutlineColor) { - mOutlineColor = color; - - // Change vertex colors directly, no need to update whole geometry - // (if geometry is updated anyway, we can skip this step) - if (!mGeometryNeedUpdate) { - mOutlineColors.assign( mOutlineVertices.size(), mOutlineColor ); - } - } -} - -void Text::setOutlineThickness(Float thickness) { - if (thickness != mOutlineThickness) { - mOutlineThickness = thickness; - mGeometryNeedUpdate = true; - } -} - -const String& Text::getText() const { - return mString; -} - -const FontTrueType* Text::getFontTrueType() const { - return mFont; -} - -unsigned int Text::getCharacterSize() const { - return mCharacterSize; -} - -Uint32 Text::getStyle() const { - return mStyle; -} - -void Text::setAlpha( const Uint8& alpha ) { - std::size_t s = mColors.size(); - for ( Uint32 i = 0; i < s; i++ ) { - mColors[ i ].Alpha = alpha; - } -} - -const ColorA& Text::getFillColor() const { - return mFillColor; -} - -const ColorA& Text::getOutlineColor() const { - return mOutlineColor; -} - -Float Text::getOutlineThickness() const { - return mOutlineThickness; -} - -Vector2f Text::findCharacterPos(std::size_t index) const { - // Make sure that we have a valid font - if (!mFont) - return Vector2f(); - - // Adjust the index if it's out of range - if (index > mString.size()) - index = mString.size(); - - // Precompute the variables needed by the algorithm - bool bold = (mStyle & Bold) != 0; - Float hspace = static_cast(mFont->getGlyph(L' ', mCharacterSize, bold).advance); - Float vspace = static_cast(mFont->getLineSpacing(mCharacterSize)); - - // Compute the position - Vector2f position; - Uint32 prevChar = 0; - for (std::size_t i = 0; i < index; ++i) { - Uint32 curChar = mString[i]; - - // Apply the kerning offset - position.x += static_cast(mFont->getKerning(prevChar, curChar, mCharacterSize)); - prevChar = curChar; - - // Handle special characters - switch (curChar) - { - case ' ': position.x += hspace; continue; - case '\t': position.x += hspace * 4; continue; - case '\n': position.y += vspace; position.x = 0; continue; - } - - // For regular characters, add the advance offset of the glyph - position.x += static_cast(mFont->getGlyph(curChar, mCharacterSize, bold).advance); - } - - return position; -} - -Rectf Text::getLocalBounds() { - ensureGeometryUpdate(); - - return mBounds; -} - -Float Text::getTextWidth() { - return mCachedWidth; -} - -Float Text::getTextHeight() { - return mFont->getLineSpacing(mCharacterSize) * mNumLines; -} - -void Text::draw(const Float & X, const Float & Y, const Vector2f & Scale, const Float & Angle, EE_BLEND_MODE Effect) { - if ( NULL != mFont ) { - GlobalBatchRenderer::instance()->draw(); - TextureFactory::instance()->bind( mFont->getTexture(mCharacterSize) ); - BlendMode::setMode( Effect ); - - if ( mFlags & FONT_DRAW_SHADOW ) { - Uint32 f = mFlags; - - mFlags &= ~FONT_DRAW_SHADOW; - - ColorA Col = getFillColor(); - - if ( Col.a() != 255 ) { - ColorA ShadowColor = getShadowColor(); - - ShadowColor.Alpha = (Uint8)( (Float)ShadowColor.Alpha * ( (Float)Col.a() / (Float)255 ) ); - - setFillColor( ShadowColor ); - } else { - setFillColor( getShadowColor() ); - } - - Float pd = PixelDensity::dpToPx(1); - - draw( X + pd, Y + pd, Scale, Angle, Effect ); - - mFlags = f; - - setFillColor( Col ); - } - - unsigned int numvert = 0; - - if ( Angle != 0.0f || Scale != 1.0f ) { - Float cX = (Float) ( (Int32)X ); - Float cY = (Float) ( (Int32)Y ); - - GLi->pushMatrix(); - - Vector2f Center( cX + mCachedWidth * 0.5f, cY + getTextHeight() * 0.5f ); - GLi->translatef( Center.x , Center.y, 0.f ); - GLi->rotatef( Angle, 0.0f, 0.0f, 1.0f ); - GLi->scalef( Scale.x, Scale.y, 1.0f ); - GLi->translatef( -Center.x + X, -Center.y + Y, 0.f ); - } else { - GLi->translatef( X, Y, 0 ); - } - - ensureGeometryUpdate(); - - numvert = mVertices.size(); - - Uint32 alloc = numvert * sizeof(VertexCoords); - Uint32 allocC = numvert * GLi->quadVertexs(); - - if ( 0 != mOutlineThickness ) { - GLi->colorPointer ( 4, GL_UNSIGNED_BYTE , 0 , reinterpret_cast( &mOutlineColors[0] ) , allocC ); - GLi->texCoordPointer( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast( &mOutlineVertices[0] ) , alloc ); - GLi->vertexPointer ( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast( &mOutlineVertices[0] ) + sizeof(Float) * 2 , alloc ); - - if ( GLi->quadsSupported() ) { - GLi->drawArrays( GL_QUADS, 0, numvert ); - } else { - GLi->drawArrays( GL_TRIANGLES, 0, numvert ); - } - } - - GLi->colorPointer ( 4, GL_UNSIGNED_BYTE , 0 , reinterpret_cast( &mColors[0] ) , allocC ); - GLi->texCoordPointer( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast( &mVertices[0] ) , alloc ); - GLi->vertexPointer ( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast( &mVertices[0] ) + sizeof(Float) * 2 , alloc ); - - if ( GLi->quadsSupported() ) { - GLi->drawArrays( GL_QUADS, 0, numvert ); - } else { - GLi->drawArrays( GL_TRIANGLES, 0, numvert ); - } - - if ( Angle != 0.0f || Scale != 1.0f ) { - GLi->popMatrix(); - } else { - GLi->translatef( -X, -Y, 0 ); - } - } -} - -void Text::ensureGeometryUpdate() { - Sizei textureSize = mFont->getTexture(mCharacterSize)->getSize(); - - if ( textureSize != mTextureSize ) - mGeometryNeedUpdate = true; - - // Do nothing, if geometry has not changed - if (!mGeometryNeedUpdate) - return; - - cacheWidth(); - - // Mark geometry as updated - mGeometryNeedUpdate = false; - - // Clear the previous geometry - mVertices.clear(); - mColors.clear();; - mOutlineVertices.clear(); - mOutlineColors.clear(); - mBounds = Rectf(); - - // No font or text: nothing to draw - if (!mFont || mString.empty()) - return; - - // Compute values related to the text style - bool bold = (mStyle & Bold) != 0; - bool underlined = (mStyle & Underlined) != 0; - bool strikeThrough = (mStyle & StrikeThrough) != 0; - Float italic = (mStyle & Italic) ? 0.208f : 0.f; // 12 degrees - Float underlineOffset = mFont->getUnderlinePosition(mCharacterSize); - Float underlineThickness = mFont->getUnderlineThickness(mCharacterSize); - - // Compute the location of the strike through dynamically - // We use the center point of the lowercase 'x' glyph as the reference - // We reuse the underline thickness as the thickness of the strike through as well - Rectf xBounds = mFont->getGlyph(L'x', mCharacterSize, bold).bounds; - Float strikeThroughOffset = xBounds.Top + xBounds.Bottom / 2.f; - - // Precompute the variables needed by the algorithm - Float hspace = static_cast(mFont->getGlyph(L' ', mCharacterSize, bold).advance); - Float vspace = static_cast(mFont->getLineSpacing(mCharacterSize)); - Float x = 0.f; - Float y = static_cast(mCharacterSize); - - // Create one quad for each character - Float minX = static_cast(mCharacterSize); - Float minY = static_cast(mCharacterSize); - Float maxX = 0.f; - Float maxY = 0.f; - Uint32 prevChar = 0; - - for (std::size_t i = 0; i < mString.size(); ++i) { - Uint32 curChar = mString[i]; - - // Apply the outline - if (mOutlineThickness != 0) { - mFont->getGlyph(curChar, mCharacterSize, bold, mOutlineThickness); - } - - // Extract the current glyph's description - mFont->getGlyph(curChar, mCharacterSize, bold); - } - - Float centerDiffX = 0; - unsigned int Line = 0; - - if ( !( mFlags & FONT_DRAW_VERTICAL ) ) { - switch ( fontHAlignGet( mFlags ) ) { - case FONT_DRAW_CENTER: - centerDiffX = (Float)( (Int32)( ( mCachedWidth - mLinesWidth[ Line ] ) * 0.5f ) ); - Line++; - break; - case FONT_DRAW_RIGHT: - centerDiffX = mCachedWidth - getLinesWidth()[ Line ]; - Line++; - break; - } - } - - for (std::size_t i = 0; i < mString.size(); ++i) { - Uint32 curChar = mString[i]; - - // Apply the kerning offset - x += mFont->getKerning(prevChar, curChar, mCharacterSize); - prevChar = curChar; - - // If we're using the underlined style and there's a new line, draw a line - if (underlined && (curChar == L'\n')) { - addLine(mVertices, mColors, x, y, mFillColor, underlineOffset, underlineThickness, 0, textureSize, centerDiffX); - - if (mOutlineThickness != 0) - addLine(mOutlineVertices, mOutlineColors, x, y, mOutlineColor, underlineOffset, underlineThickness, mOutlineThickness, textureSize, centerDiffX); - } - - // If we're using the strike through style and there's a new line, draw a line across all characters - if (strikeThrough && (curChar == L'\n')) { - addLine(mVertices, mColors, x, y, mFillColor, strikeThroughOffset, underlineThickness, 0, textureSize, centerDiffX); - - if (mOutlineThickness != 0) - addLine(mOutlineVertices, mOutlineColors, x, y, mOutlineColor, strikeThroughOffset, underlineThickness, mOutlineThickness, textureSize, centerDiffX); - } - - if ( curChar == L'\n' ) { - switch ( fontHAlignGet( mFlags ) ) { - case FONT_DRAW_CENTER: - centerDiffX = (Float)( (Int32)( ( mCachedWidth - mLinesWidth[ Line ] ) * 0.5f ) ); - break; - case FONT_DRAW_RIGHT: - centerDiffX = mCachedWidth - mLinesWidth[ Line ]; - break; - } - - Line++; - } - - // Handle special characters - if ((curChar == ' ') || (curChar == '\t') || (curChar == '\n')) { - // Update the current bounds (min coordinates) - minX = std::min(minX, x); - minY = std::min(minY, y); - - switch (curChar) { - case ' ': x += hspace; break; - case '\t': x += hspace * 4; break; - case '\n': y += vspace; x = 0; break; - } - - // Update the current bounds (max coordinates) - maxX = std::max(maxX, x); - maxY = std::max(maxY, y); - - // Next glyph, no need to create a quad for whitespace - continue; - } - - - // Apply the outline - if (mOutlineThickness != 0) { - const Glyph& glyph = mFont->getGlyph(curChar, mCharacterSize, bold, mOutlineThickness); - - Float left = glyph.bounds.Left; - Float top = glyph.bounds.Top; - Float right = glyph.bounds.Left + glyph.bounds.Right; - Float bottom = glyph.bounds.Top + glyph.bounds.Bottom; - - // Add the outline glyph to the vertices - addGlyphQuad(mOutlineVertices, mOutlineColors, Vector2f(x, y), mOutlineColor, glyph, italic, mOutlineThickness, textureSize, centerDiffX); - - // Update the current bounds with the outlined glyph bounds - minX = std::min(minX, x + left - italic * bottom - mOutlineThickness); - maxX = std::max(maxX, x + right - italic * top - mOutlineThickness); - minY = std::min(minY, y + top - mOutlineThickness); - maxY = std::max(maxY, y + bottom - mOutlineThickness); - } - - // Extract the current glyph's description - const Glyph& glyph = mFont->getGlyph(curChar, mCharacterSize, bold); - - // Add the glyph to the vertices - addGlyphQuad(mVertices, mColors, Vector2f(x, y), mFillColor, glyph, italic, 0, textureSize, centerDiffX); - - // Update the current bounds with the non outlined glyph bounds - if (mOutlineThickness == 0) { - Float left = glyph.bounds.Left; - Float top = glyph.bounds.Top; - Float right = glyph.bounds.Left + glyph.bounds.Right; - Float bottom = glyph.bounds.Top + glyph.bounds.Bottom; - - minX = std::min(minX, x + left - italic * bottom); - maxX = std::max(maxX, x + right - italic * top); - minY = std::min(minY, y + top); - maxY = std::max(maxY, y + bottom); - } - - // Advance to the next character - x += glyph.advance; - } - - // If we're using the underlined style, add the last line - if (underlined && (x > 0)) { - addLine(mVertices, mColors, x, y, mFillColor, underlineOffset, underlineThickness, 0, textureSize, centerDiffX); - - if (mOutlineThickness != 0) - addLine(mOutlineVertices, mOutlineColors, x, y, mOutlineColor, underlineOffset, underlineThickness, mOutlineThickness, textureSize, centerDiffX); - } - - // If we're using the strike through style, add the last line across all characters - if (strikeThrough && (x > 0)) { - addLine(mVertices, mColors, x, y, mFillColor, strikeThroughOffset, underlineThickness, 0, textureSize, centerDiffX); - - if (mOutlineThickness != 0) - addLine(mOutlineVertices, mOutlineColors, x, y, mOutlineColor, strikeThroughOffset, underlineThickness, mOutlineThickness, textureSize, centerDiffX); - } - - // Update the bounding rectangle - mBounds.Left = minX; - mBounds.Top = minY; - mBounds.Right = maxX - minX; - mBounds.Bottom = maxY - minY; -} - -const ColorA& Text::getShadowColor() const { - return mFontShadowColor; -} - -void Text::setShadowColor(const ColorA& color) { - mFontShadowColor = color; -} - -const int& Text::getNumLines() const { - return mNumLines; -} - -const std::vector& Text::getLinesWidth() { - return mLinesWidth; -} - -void Text::setFlags( const Uint32& flags ) { - if ( mFlags != flags ) { - mFlags = flags; - mGeometryNeedUpdate = true; - } -} - -const Uint32& Text::getFlags() const { - return mFlags; -} - -void Text::cacheWidth() { - if ( NULL != mFont && mString.size() ) { - mFont->cacheWidth( mString, mCharacterSize, (mStyle & Bold), mOutlineThickness, mLinesWidth, mCachedWidth, mNumLines, mLargestLineCharCount ); - } else { - mCachedWidth = 0; - } -} - - -}} diff --git a/src/eepp/graphics/textcache.cpp b/src/eepp/graphics/textcache.cpp index 4c6a50acd..4250a12df 100644 --- a/src/eepp/graphics/textcache.cpp +++ b/src/eepp/graphics/textcache.cpp @@ -1,88 +1,271 @@ #include -#include -#include +#include #include #include +#include +#include +#include + +namespace EE { namespace Graphics { + // Add an underline or strikethrough line to the vertex array + static void addLine(std::vector& vertices, std::vector& colors, Float lineLength, Float lineTop, const EE::System::ColorA& color, Float offset, Float thickness, Float outlineThickness, Sizei textureSize, Int32 centerDiffX) { + Float top = std::floor(lineTop + offset - (thickness / 2) + 0.5f); + Float bottom = top + std::floor(thickness + 0.5f); + Float u1 = 0; + Float v1 = 0; + Float u2 = 1 / (Float)textureSize.getWidth(); + Float v2 = 1 / (Float)textureSize.getHeight(); + + if ( GLi->quadsSupported() ) { + VertexCoords vc; + + vc.TexCoords[0] = u1; + vc.TexCoords[1] = v1; + vc.Vertex[0] = centerDiffX + -outlineThickness; + vc.Vertex[1] = top - outlineThickness; + colors.push_back( color ); + vertices.push_back( vc ); + + vc.TexCoords[0] = u1; + vc.TexCoords[1] = v2; + vc.Vertex[0] = centerDiffX + -outlineThickness; + vc.Vertex[1] = bottom + outlineThickness; + colors.push_back( color ); + vertices.push_back( vc ); + + vc.TexCoords[0] = u2; + vc.TexCoords[1] = v2; + vc.Vertex[0] = centerDiffX + lineLength + outlineThickness; + vc.Vertex[1] = bottom + outlineThickness; + colors.push_back( color ); + vertices.push_back( vc ); + + vc.TexCoords[0] = u2; + vc.TexCoords[1] = v1; + vc.Vertex[0] = centerDiffX + lineLength + outlineThickness; + vc.Vertex[1] = top - outlineThickness; + colors.push_back( color ); + vertices.push_back( vc ); + } else { + + } + } + + // Add a glyph quad to the vertex array + static void addGlyphQuad(std::vector& vertices, std::vector& colors, Vector2f position, const EE::System::ColorA& color, const EE::Graphics::Glyph& glyph, Float italic, Float outlineThickness, Sizei textureSize, Int32 centerDiffX) { + Float left = glyph.bounds.Left; + Float top = glyph.bounds.Top; + Float right = glyph.bounds.Left + glyph.bounds.Right; + Float bottom = glyph.bounds.Top + glyph.bounds.Bottom; + + Float u1 = static_cast(glyph.textureRect.Left) / (Float)textureSize.getWidth(); + Float v1 = static_cast(glyph.textureRect.Top) / (Float)textureSize.getHeight(); + Float u2 = static_cast(glyph.textureRect.Left + glyph.textureRect.Right) / (Float)textureSize.getWidth(); + Float v2 = static_cast(glyph.textureRect.Top + glyph.textureRect.Bottom) / (Float)textureSize.getHeight(); + + if ( GLi->quadsSupported() ) { + VertexCoords vc; + + vc.TexCoords[0] = u1; + vc.TexCoords[1] = v1; + vc.Vertex[0] = centerDiffX + position.x + left - italic * top - outlineThickness; + vc.Vertex[1] = position.y + top - outlineThickness; + colors.push_back( color ); + vertices.push_back( vc ); + + vc.TexCoords[0] = u1; + vc.TexCoords[1] = v2; + vc.Vertex[0] = centerDiffX + position.x + left - italic * bottom - outlineThickness; + vc.Vertex[1] = position.y + bottom - outlineThickness; + colors.push_back( color ); + vertices.push_back( vc ); + + vc.TexCoords[0] = u2; + vc.TexCoords[1] = v2; + vc.Vertex[0] = centerDiffX + position.x + right - italic * bottom - outlineThickness; + vc.Vertex[1] = position.y + bottom - outlineThickness; + colors.push_back( color ); + vertices.push_back( vc ); + + vc.TexCoords[0] = u2; + vc.TexCoords[1] = v1; + vc.Vertex[0] = centerDiffX + position.x + right - italic * top - outlineThickness; + vc.Vertex[1] = position.y + top - outlineThickness; + colors.push_back( color ); + vertices.push_back( vc ); + } else { + + } + } +}} namespace EE { namespace Graphics { TextCache::TextCache() : + mString(), mFont(NULL), - mCachedWidth(0.f), - mNumLines(1), + mCharacterSize(12), + mRealCharacterSize(PixelDensity::dpToPxI(mCharacterSize)), + mStyle(Regular), + mFillColor(255, 255, 255, 255), + mOutlineColor(0, 0, 0, 255), + mOutlineThickness (0), + mGeometryNeedUpdate(false), + mCachedWidth(0), + mNumLines(0), mLargestLineCharCount(0), - mFontColor(255,255,255,255), - mFontShadowColor(0,0,0,255), + mFontShadowColor( ColorA( 0, 0, 0, 255 ) ), mFlags(0), - mVertexNumCached(0), - mCachedCoords(false) + mFontHeight(0) { } -TextCache::TextCache( Graphics::Font * font, const String& text, ColorA FontColor, ColorA FontShadowColor ) : - mText( text ), - mFont( font ), - mCachedWidth(0.f), - mNumLines(1), +TextCache::TextCache(const String& string, Font * font, unsigned int characterSize) : + mString(string), + mFont(font), + mCharacterSize(characterSize), + mRealCharacterSize(PixelDensity::dpToPxI(mCharacterSize)), + mStyle(Regular), + mFillColor(255, 255, 255, 255), + mOutlineColor(0, 0, 0, 255), + mOutlineThickness(0), + mGeometryNeedUpdate(true), + mCachedWidth(0), + mNumLines(0), mLargestLineCharCount(0), + mFontShadowColor( ColorA( 0, 0, 0, 255 ) ), mFlags(0), - mVertexNumCached(0), - mCachedCoords(false) + mFontHeight( mFont->getFontHeight( mRealCharacterSize ) ) { - cacheWidth(); - updateCoords(); - setColor( FontColor ); - setShadowColor( FontShadowColor ); } -TextCache::~TextCache() { +TextCache::TextCache(Font * font, unsigned int characterSize) : + mFont(font), + mCharacterSize(characterSize), + mRealCharacterSize(PixelDensity::dpToPxI(mCharacterSize)), + mStyle(Regular), + mFillColor(255, 255, 255, 255), + mOutlineColor(0, 0, 0, 255), + mOutlineThickness(0), + mGeometryNeedUpdate(true), + mCachedWidth(0), + mNumLines(0), + mLargestLineCharCount(0), + mFontShadowColor( ColorA( 0, 0, 0, 255 ) ), + mFlags(0), + mFontHeight( mFont->getFontHeight( mRealCharacterSize ) ) +{ } -void TextCache::create( Graphics::Font * font, const String& text, ColorA FontColor, ColorA FontShadowColor ) { +void TextCache::create(Font * font, const String & text, ColorA FontColor, ColorA FontShadowColor, Uint32 characterSize ) { mFont = font; - mText = text; - updateCoords(); + mString = text; + mCharacterSize = characterSize; + mRealCharacterSize = PixelDensity::dpToPxI(mCharacterSize); setColor( FontColor ); setShadowColor( FontShadowColor ); cacheWidth(); + mGeometryNeedUpdate = true; + ensureGeometryUpdate(); } -Graphics::Font * TextCache::getFont() const { - return mFont; +void TextCache::setText(const String& string) { + if (mString != string) { + mString = string; + mGeometryNeedUpdate = true; + cacheWidth(); + } } -void TextCache::setFont( Graphics::Font * font ) { - mFont = font; - cacheWidth(); +void TextCache::setFont(Font * font) { + if (mFont != font) { + mFont = font; + + mRealCharacterSize = PixelDensity::dpToPxI( mCharacterSize ); + mFontHeight = mFont->getFontHeight( mRealCharacterSize ); + + mGeometryNeedUpdate = true; + cacheWidth(); + } +} + +void TextCache::setCharacterSize(unsigned int size) { + if (mCharacterSize != size) { + mCharacterSize = size; + + mRealCharacterSize = PixelDensity::dpToPxI( mCharacterSize ); + mFontHeight = mFont->getFontHeight( mRealCharacterSize ); + + mGeometryNeedUpdate = true; + cacheWidth(); + } +} + +void TextCache::setStyle(Uint32 style) { + if (mStyle != style) { + mStyle = style; + mGeometryNeedUpdate = true; + cacheWidth(); + } +} + +void TextCache::setColor(const ColorA & color) { + setFillColor(color); +} + +void TextCache::setFillColor(const ColorA& color) { + if (color != mFillColor) { + mFillColor = color; + + // Change vertex colors directly, no need to update whole geometry + // (if geometry is updated anyway, we can skip this step) + if (!mGeometryNeedUpdate) { + mColors.assign( mVertices.size(), mFillColor ); + } + } +} + +void TextCache::setOutlineColor(const ColorA& color) { + if (color != mOutlineColor) { + mOutlineColor = color; + + // Change vertex colors directly, no need to update whole geometry + // (if geometry is updated anyway, we can skip this step) + if (!mGeometryNeedUpdate) { + mOutlineColors.assign( mOutlineVertices.size(), mOutlineColor ); + } + } +} + +void TextCache::setOutlineThickness(Float thickness) { + if (thickness != mOutlineThickness) { + mOutlineThickness = thickness; + mGeometryNeedUpdate = true; + } } String& TextCache::getText() { - return mText; + return mString; } -void TextCache::updateCoords() { - Uint32 size = (Uint32)mText.size() * GLi->quadVertexs(); - - mRenderCoords.resize( size ); - mColors.resize( size, mFontColor ); +Font* TextCache::getFont() const { + return mFont; } -void TextCache::setText( const String& text ) { - bool needUpdate = false; - - if ( mText.size() != text.size() ) - needUpdate = true; - - mText = text; - - if ( needUpdate ) - updateCoords(); - - cacheWidth(); +unsigned int TextCache::getCharacterSize() const { + return mCharacterSize; } -const ColorA& TextCache::getColor() const { - return mFontColor; +unsigned int TextCache::getCharacterSizePx() const { + return mRealCharacterSize; +} + +const Uint32 &TextCache::getFontHeight() const { + return mFontHeight; +} + +Uint32 TextCache::getStyle() const { + return mStyle; } void TextCache::setAlpha( const Uint8& alpha ) { @@ -92,239 +275,79 @@ void TextCache::setAlpha( const Uint8& alpha ) { } } -void TextCache::setColor( const ColorA& color ) { - if ( mFontColor != color ) { - mFontColor = color; - - mColors.assign( mText.size() * GLi->quadVertexs(), mFontColor ); - } +const ColorA& TextCache::getFillColor() const { + return mFillColor; } -void TextCache::setColor( const ColorA& color, Uint32 from, Uint32 to ) { - std::vector colors( GLi->quadVertexs(), color ); - std::size_t s = mText.size(); +const ColorA &TextCache::getColor() const { + return getFillColor(); +} - if ( to >= s ) { - to = s - 1; - } +const ColorA& TextCache::getOutlineColor() const { + return mOutlineColor; +} - if ( from <= to && from < s && to <= s ) { - size_t rto = to + 1; - Int32 rpos = from; - Int32 lpos = 0; - Uint32 i; - Uint32 qsize = sizeof(ColorA) * GLi->quadVertexs(); - String::StringBaseType curChar; +Float TextCache::getOutlineThickness() const { + return mOutlineThickness; +} - // New lines and tabs are not rendered, and not counted as a color - // We need to skip those characters as nonexistent chars - for ( i = 0; i < from; i++ ) { - curChar = mText.at(i); - if ( '\n' == curChar || '\t' == curChar || '\v' == curChar ) { - if ( rpos > 0 ) { - rpos--; - } - } +Vector2f TextCache::findCharacterPos(std::size_t index) const { + // Make sure that we have a valid font + if (!mFont) + return Vector2f(); + + // Adjust the index if it's out of range + if (index > mString.size()) + index = mString.size(); + + // Precompute the variables needed by the algorithm + bool bold = (mStyle & Bold) != 0; + Float hspace = static_cast(mFont->getGlyph(L' ', mRealCharacterSize, bold).advance); + Float vspace = static_cast(mFont->getLineSpacing(mRealCharacterSize)); + + // Compute the position + Vector2f position; + Uint32 prevChar = 0; + for (std::size_t i = 0; i < index; ++i) { + Uint32 curChar = mString[i]; + + // Apply the kerning offset + position.x += static_cast(mFont->getKerning(prevChar, curChar, mRealCharacterSize)); + prevChar = curChar; + + // Handle special characters + switch (curChar) + { + case ' ': position.x += hspace; continue; + case '\t': position.x += hspace * 4; continue; + case '\n': position.y += vspace; position.x = 0; continue; } - for ( Uint32 i = from; i < rto; i++ ) { - curChar = mText.at(i); - - lpos = rpos; - rpos++; - - // Same here - if ( '\n' == curChar || '\t' == curChar || '\v' == curChar ) { - if ( rpos > 0 ) { - rpos--; - } - } - - memcpy( &(mColors[ lpos * GLi->quadVertexs() ]), &colors[0], qsize ); - } - } -} - -const ColorA& TextCache::getShadowColor() const { - return mFontShadowColor; -} - -void TextCache::setShadowColor(const ColorA& color) { - mFontShadowColor = color; -} - -std::vector& TextCache::getColors() { - return mColors; -} - -void TextCache::cacheWidth() { - if ( NULL != mFont && mText.size() ) { - mFont->cacheWidth( mText, mLinesWidth, mCachedWidth, mNumLines, mLargestLineCharCount ); - }else { - mCachedWidth = 0; + // For regular characters, add the advance offset of the glyph + position.x += static_cast(mFont->getGlyph(curChar, mRealCharacterSize, bold).advance); } - mCachedCoords = false; + return position; } -void TextCache::cacheVerts() { - if ( mCachedCoords ) - return; +Rectf TextCache::getLocalBounds() { + ensureGeometryUpdate(); - Float nX = 0; - Float nY = 0; - Uint32 Char = 0; - unsigned int Line = 0; - - if ( !( mFlags & FONT_DRAW_VERTICAL ) ) { - switch ( fontHAlignGet( mFlags ) ) { - case FONT_DRAW_CENTER: - nX = (Float)( (Int32)( ( getTextWidth() - getLinesWidth()[ Line ] ) * 0.5f ) ); - Line++; - break; - case FONT_DRAW_RIGHT: - nX = getTextWidth() - getLinesWidth()[ Line ]; - Line++; - break; - } - } - - Uint32 tGlyphSize = mFont->getGlyphCount(); - unsigned int numvert = 0; - - for ( unsigned int i = 0; i < getText().size(); i++ ) { - Char = getText().at(i); - - if ( Char < 0 && Char > -128 ) - Char = 256 + Char; - - if ( Char >= 0 && Char < tGlyphSize ) { - TextureCoords C = mFont->getTextureCoords( Char ); - GlyphData Glyph = mFont->getGlyph( Char ); - - switch( Char ) { - case '\v': - { - if ( mFlags & FONT_DRAW_VERTICAL ) - nY += mFont->getFontHeight(); - else - nX += Glyph.Advance; - break; - } - case '\t': - { - if ( mFlags & FONT_DRAW_VERTICAL ) - nY += mFont->getFontHeight() * 4; - else - nX += Glyph.Advance * 4; - break; - } - case '\n': - { - if ( mFlags & FONT_DRAW_VERTICAL ) { - nX += mFont->getFontHeight(); - nY = 0; - } else { - if ( i + 1 < getText().size() ) { - switch ( fontHAlignGet( mFlags ) ) { - case FONT_DRAW_CENTER: - nX = (Float)( (Int32)( ( getTextWidth() - getLinesWidth()[ Line ] ) * 0.5f ) ); - break; - case FONT_DRAW_RIGHT: - nX = getTextWidth() - getLinesWidth()[ Line ]; - break; - default: - nX = 0; - } - } - - nY += mFont->getLineSkip(); - Line++; - } - - break; - } - default: - { - if ( GLi->quadsSupported() ) { - for ( Uint8 z = 0; z < 8; z+=2 ) { - mRenderCoords[ numvert ].TexCoords[0] = C.TexCoords[z]; - mRenderCoords[ numvert ].TexCoords[1] = C.TexCoords[ z + 1 ]; - mRenderCoords[ numvert ].Vertex[0] = C.Vertex[z] + nX; - mRenderCoords[ numvert ].Vertex[1] = C.Vertex[ z + 1 ] + nY; - numvert++; - } - } else { - mRenderCoords[ numvert ].TexCoords[0] = C.TexCoords[2]; - mRenderCoords[ numvert ].TexCoords[1] = C.TexCoords[ 2 + 1 ]; - mRenderCoords[ numvert ].Vertex[0] = C.Vertex[2] + nX; - mRenderCoords[ numvert ].Vertex[1] = C.Vertex[ 2 + 1 ] + nY; - numvert++; - - mRenderCoords[ numvert ].TexCoords[0] = C.TexCoords[0]; - mRenderCoords[ numvert ].TexCoords[1] = C.TexCoords[ 0 + 1 ]; - mRenderCoords[ numvert ].Vertex[0] = C.Vertex[0] + nX; - mRenderCoords[ numvert ].Vertex[1] = C.Vertex[ 0 + 1 ] + nY; - numvert++; - - mRenderCoords[ numvert ].TexCoords[0] = C.TexCoords[6]; - mRenderCoords[ numvert ].TexCoords[1] = C.TexCoords[ 6 + 1 ]; - mRenderCoords[ numvert ].Vertex[0] = C.Vertex[6] + nX; - mRenderCoords[ numvert ].Vertex[1] = C.Vertex[ 6 + 1 ] + nY; - numvert++; - - mRenderCoords[ numvert ].TexCoords[0] = C.TexCoords[2]; - mRenderCoords[ numvert ].TexCoords[1] = C.TexCoords[ 2 + 1 ]; - mRenderCoords[ numvert ].Vertex[0] = C.Vertex[2] + nX; - mRenderCoords[ numvert ].Vertex[1] = C.Vertex[ 2 + 1 ] + nY; - numvert++; - - mRenderCoords[ numvert ].TexCoords[0] = C.TexCoords[4]; - mRenderCoords[ numvert ].TexCoords[1] = C.TexCoords[ 4 + 1 ]; - mRenderCoords[ numvert ].Vertex[0] = C.Vertex[4] + nX; - mRenderCoords[ numvert ].Vertex[1] = C.Vertex[ 4 + 1 ] + nY; - numvert++; - - mRenderCoords[ numvert ].TexCoords[0] = C.TexCoords[6]; - mRenderCoords[ numvert ].TexCoords[1] = C.TexCoords[ 6 + 1 ]; - mRenderCoords[ numvert ].Vertex[0] = C.Vertex[6] + nX; - mRenderCoords[ numvert ].Vertex[1] = C.Vertex[ 6 + 1 ] + nY; - numvert++; - } - - if ( mFlags & FONT_DRAW_VERTICAL ) - nY += mFont->getFontHeight(); - else - nX += Glyph.Advance; - } - } - } - } - - mCachedCoords = true; - mVertexNumCached = numvert; + return mBounds; } Float TextCache::getTextWidth() { - return ( mFlags & FONT_DRAW_VERTICAL ) ? (Float)mFont->getFontHeight() * (Float)mNumLines : mCachedWidth; + return mCachedWidth; } Float TextCache::getTextHeight() { - return ( mFlags & FONT_DRAW_VERTICAL ) ? mLargestLineCharCount * (Float)mFont->getFontHeight() : (Float)mFont->getFontHeight() * (Float)mNumLines; + return mFont->getLineSpacing(mRealCharacterSize) * mNumLines; } -const int& TextCache::getNumLines() const { - return mNumLines; -} - -const std::vector& TextCache::getLinesWidth() { - return mLinesWidth; -} - -void TextCache::draw( const Float& X, const Float& Y, const Vector2f& Scale, const Float& Angle, EE_BLEND_MODE Effect ) { +void TextCache::draw(const Float & X, const Float & Y, const Vector2f & Scale, const Float & Angle, EE_BLEND_MODE Effect) { if ( NULL != mFont ) { GlobalBatchRenderer::instance()->draw(); - TextureFactory::instance()->bind( mFont->getTexId() ); + TextureFactory::instance()->bind( mFont->getTexture(mRealCharacterSize) ); BlendMode::setMode( Effect ); if ( mFlags & FONT_DRAW_SHADOW ) { @@ -332,16 +355,16 @@ void TextCache::draw( const Float& X, const Float& Y, const Vector2f& Scale, con mFlags &= ~FONT_DRAW_SHADOW; - ColorA Col = getColor(); + ColorA Col = getFillColor(); if ( Col.a() != 255 ) { ColorA ShadowColor = getShadowColor(); ShadowColor.Alpha = (Uint8)( (Float)ShadowColor.Alpha * ( (Float)Col.a() / (Float)255 ) ); - setColor( ShadowColor ); + setFillColor( ShadowColor ); } else { - setColor( getShadowColor() ); + setFillColor( getShadowColor() ); } Float pd = PixelDensity::dpToPx(1); @@ -350,7 +373,7 @@ void TextCache::draw( const Float& X, const Float& Y, const Vector2f& Scale, con mFlags = f; - setColor( Col ); + setFillColor( Col ); } unsigned int numvert = 0; @@ -361,7 +384,7 @@ void TextCache::draw( const Float& X, const Float& Y, const Vector2f& Scale, con GLi->pushMatrix(); - Vector2f Center( cX + getTextWidth() * 0.5f, cY + getTextHeight() * 0.5f ); + Vector2f Center( cX + mCachedWidth * 0.5f, cY + getTextHeight() * 0.5f ); GLi->translatef( Center.x , Center.y, 0.f ); GLi->rotatef( Angle, 0.0f, 0.0f, 1.0f ); GLi->scalef( Scale.x, Scale.y, 1.0f ); @@ -370,18 +393,28 @@ void TextCache::draw( const Float& X, const Float& Y, const Vector2f& Scale, con GLi->translatef( X, Y, 0 ); } - if ( !mCachedCoords ) { - cacheVerts(); - } + ensureGeometryUpdate(); - numvert = mVertexNumCached; + numvert = mVertices.size(); Uint32 alloc = numvert * sizeof(VertexCoords); Uint32 allocC = numvert * GLi->quadVertexs(); - GLi->colorPointer ( 4, GL_UNSIGNED_BYTE , 0 , reinterpret_cast( &mColors[0] ) , allocC ); - GLi->texCoordPointer( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast( &mRenderCoords[0] ) , alloc ); - GLi->vertexPointer ( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast( &mRenderCoords[0] ) + sizeof(Float) * 2 , alloc ); + if ( 0 != mOutlineThickness ) { + GLi->colorPointer ( 4, GL_UNSIGNED_BYTE , 0 , reinterpret_cast( &mOutlineColors[0] ) , allocC ); + GLi->texCoordPointer( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast( &mOutlineVertices[0] ) , alloc ); + GLi->vertexPointer ( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast( &mOutlineVertices[0] ) + sizeof(Float) * 2 , alloc ); + + if ( GLi->quadsSupported() ) { + GLi->drawArrays( GL_QUADS, 0, numvert ); + } else { + GLi->drawArrays( GL_TRIANGLES, 0, numvert ); + } + } + + GLi->colorPointer ( 4, GL_UNSIGNED_BYTE , 0 , reinterpret_cast( &mColors[0] ) , allocC ); + GLi->texCoordPointer( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast( &mVertices[0] ) , alloc ); + GLi->vertexPointer ( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast( &mVertices[0] ) + sizeof(Float) * 2 , alloc ); if ( GLi->quadsSupported() ) { GLi->drawArrays( GL_QUADS, 0, numvert ); @@ -397,14 +430,231 @@ void TextCache::draw( const Float& X, const Float& Y, const Vector2f& Scale, con } } +void TextCache::ensureGeometryUpdate() { + Sizei textureSize = mFont->getTexture(mRealCharacterSize)->getSize(); + + if ( textureSize != mTextureSize ) + mGeometryNeedUpdate = true; + + // Do nothing, if geometry has not changed + if (!mGeometryNeedUpdate) + return; + + mTextureSize = textureSize; + + cacheWidth(); + + // Mark geometry as updated + mGeometryNeedUpdate = false; + + // Clear the previous geometry + mVertices.clear(); + mColors.clear();; + mOutlineVertices.clear(); + mOutlineColors.clear(); + mBounds = Rectf(); + + // No font or text: nothing to draw + if (!mFont || mString.empty()) + return; + + // Compute values related to the text style + bool bold = (mStyle & Bold) != 0; + bool underlined = (mStyle & Underlined) != 0; + bool strikeThrough = (mStyle & StrikeThrough) != 0; + Float italic = (mStyle & Italic) ? 0.208f : 0.f; // 12 degrees + Float underlineOffset = mFont->getUnderlinePosition(mRealCharacterSize); + Float underlineThickness = mFont->getUnderlineThickness(mRealCharacterSize); + + // Compute the location of the strike through dynamically + // We use the center point of the lowercase 'x' glyph as the reference + // We reuse the underline thickness as the thickness of the strike through as well + Rectf xBounds = mFont->getGlyph(L'x', mRealCharacterSize, bold).bounds; + Float strikeThroughOffset = xBounds.Top + xBounds.Bottom / 2.f; + + // Precompute the variables needed by the algorithm + Float hspace = static_cast(mFont->getGlyph(L' ', mRealCharacterSize, bold).advance); + Float vspace = static_cast(mFont->getLineSpacing(mRealCharacterSize)); + Float x = 0.f; + Float y = static_cast(mRealCharacterSize); + + // Create one quad for each character + Float minX = static_cast(mRealCharacterSize); + Float minY = static_cast(mRealCharacterSize); + Float maxX = 0.f; + Float maxY = 0.f; + Uint32 prevChar = 0; + + for (std::size_t i = 0; i < mString.size(); ++i) { + Uint32 curChar = mString[i]; + + // Apply the outline + if (mOutlineThickness != 0) { + mFont->getGlyph(curChar, mRealCharacterSize, bold, mOutlineThickness); + } + + // Extract the current glyph's description + mFont->getGlyph(curChar, mRealCharacterSize, bold); + } + + Float centerDiffX = 0; + unsigned int Line = 0; + + if ( !( mFlags & FONT_DRAW_VERTICAL ) ) { + switch ( fontHAlignGet( mFlags ) ) { + case FONT_DRAW_CENTER: + centerDiffX = (Float)( (Int32)( ( mCachedWidth - mLinesWidth[ Line ] ) * 0.5f ) ); + Line++; + break; + case FONT_DRAW_RIGHT: + centerDiffX = mCachedWidth - getLinesWidth()[ Line ]; + Line++; + break; + } + } + + for (std::size_t i = 0; i < mString.size(); ++i) { + Uint32 curChar = mString[i]; + + // Apply the kerning offset + x += mFont->getKerning(prevChar, curChar, mRealCharacterSize); + prevChar = curChar; + + // If we're using the underlined style and there's a new line, draw a line + if (underlined && (curChar == L'\n')) { + addLine(mVertices, mColors, x, y, mFillColor, underlineOffset, underlineThickness, 0, textureSize, centerDiffX); + + if (mOutlineThickness != 0) + addLine(mOutlineVertices, mOutlineColors, x, y, mOutlineColor, underlineOffset, underlineThickness, mOutlineThickness, textureSize, centerDiffX); + } + + // If we're using the strike through style and there's a new line, draw a line across all characters + if (strikeThrough && (curChar == L'\n')) { + addLine(mVertices, mColors, x, y, mFillColor, strikeThroughOffset, underlineThickness, 0, textureSize, centerDiffX); + + if (mOutlineThickness != 0) + addLine(mOutlineVertices, mOutlineColors, x, y, mOutlineColor, strikeThroughOffset, underlineThickness, mOutlineThickness, textureSize, centerDiffX); + } + + if ( curChar == L'\n' ) { + switch ( fontHAlignGet( mFlags ) ) { + case FONT_DRAW_CENTER: + centerDiffX = (Float)( (Int32)( ( mCachedWidth - mLinesWidth[ Line ] ) * 0.5f ) ); + break; + case FONT_DRAW_RIGHT: + centerDiffX = mCachedWidth - mLinesWidth[ Line ]; + break; + } + + Line++; + } + + // Handle special characters + if ((curChar == ' ') || (curChar == '\t') || (curChar == '\n')) { + // Update the current bounds (min coordinates) + minX = std::min(minX, x); + minY = std::min(minY, y); + + switch (curChar) { + case ' ': x += hspace; break; + case '\t': x += hspace * 4; break; + case '\n': y += vspace; x = 0; break; + } + + // Update the current bounds (max coordinates) + maxX = std::max(maxX, x); + maxY = std::max(maxY, y); + + // Next glyph, no need to create a quad for whitespace + continue; + } + + + // Apply the outline + if (mOutlineThickness != 0) { + const Glyph& glyph = mFont->getGlyph(curChar, mRealCharacterSize, bold, mOutlineThickness); + + Float left = glyph.bounds.Left; + Float top = glyph.bounds.Top; + Float right = glyph.bounds.Left + glyph.bounds.Right; + Float bottom = glyph.bounds.Top + glyph.bounds.Bottom; + + // Add the outline glyph to the vertices + addGlyphQuad(mOutlineVertices, mOutlineColors, Vector2f(x, y), mOutlineColor, glyph, italic, mOutlineThickness, textureSize, centerDiffX); + + // Update the current bounds with the outlined glyph bounds + minX = std::min(minX, x + left - italic * bottom - mOutlineThickness); + maxX = std::max(maxX, x + right - italic * top - mOutlineThickness); + minY = std::min(minY, y + top - mOutlineThickness); + maxY = std::max(maxY, y + bottom - mOutlineThickness); + } + + // Extract the current glyph's description + const Glyph& glyph = mFont->getGlyph(curChar, mRealCharacterSize, bold); + + // Add the glyph to the vertices + addGlyphQuad(mVertices, mColors, Vector2f(x, y), mFillColor, glyph, italic, 0, textureSize, centerDiffX); + + // Update the current bounds with the non outlined glyph bounds + if (mOutlineThickness == 0) { + Float left = glyph.bounds.Left; + Float top = glyph.bounds.Top; + Float right = glyph.bounds.Left + glyph.bounds.Right; + Float bottom = glyph.bounds.Top + glyph.bounds.Bottom; + + minX = std::min(minX, x + left - italic * bottom); + maxX = std::max(maxX, x + right - italic * top); + minY = std::min(minY, y + top); + maxY = std::max(maxY, y + bottom); + } + + // Advance to the next character + x += glyph.advance; + } + + // If we're using the underlined style, add the last line + if (underlined && (x > 0)) { + addLine(mVertices, mColors, x, y, mFillColor, underlineOffset, underlineThickness, 0, textureSize, centerDiffX); + + if (mOutlineThickness != 0) + addLine(mOutlineVertices, mOutlineColors, x, y, mOutlineColor, underlineOffset, underlineThickness, mOutlineThickness, textureSize, centerDiffX); + } + + // If we're using the strike through style, add the last line across all characters + if (strikeThrough && (x > 0)) { + addLine(mVertices, mColors, x, y, mFillColor, strikeThroughOffset, underlineThickness, 0, textureSize, centerDiffX); + + if (mOutlineThickness != 0) + addLine(mOutlineVertices, mOutlineColors, x, y, mOutlineColor, strikeThroughOffset, underlineThickness, mOutlineThickness, textureSize, centerDiffX); + } + + // Update the bounding rectangle + mBounds.Left = minX; + mBounds.Top = minY; + mBounds.Right = maxX - minX; + mBounds.Bottom = maxY - minY; +} + +const ColorA& TextCache::getShadowColor() const { + return mFontShadowColor; +} + +void TextCache::setShadowColor(const ColorA& color) { + mFontShadowColor = color; +} + +const int& TextCache::getNumLines() const { + return mNumLines; +} + +const std::vector& TextCache::getLinesWidth() { + return mLinesWidth; +} + void TextCache::setFlags( const Uint32& flags ) { if ( mFlags != flags ) { mFlags = flags; - mCachedCoords = false; - - if ( ( mFlags & FONT_DRAW_VERTICAL ) != ( flags & FONT_DRAW_VERTICAL ) ) { - cacheWidth(); - } + mGeometryNeedUpdate = true; } } @@ -412,4 +662,13 @@ const Uint32& TextCache::getFlags() const { return mFlags; } +void TextCache::cacheWidth() { + if ( NULL != mFont && mString.size() ) { + mFont->cacheWidth( mString, mRealCharacterSize, (mStyle & Bold), mOutlineThickness, mLinesWidth, mCachedWidth, mNumLines, mLargestLineCharCount ); + } else { + mCachedWidth = 0; + } +} + + }} diff --git a/src/eepp/graphics/texturefont.cpp b/src/eepp/graphics/texturefont.cpp deleted file mode 100755 index e01c3a901..000000000 --- a/src/eepp/graphics/texturefont.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#include -#include -#include -#include - -namespace EE { namespace Graphics { - -TextureFont * TextureFont::New( const std::string FontName ) { - return eeNew( TextureFont, ( FontName ) ); -} - -TextureFont::TextureFont( const std::string FontName ) : - Font( FONT_TYPE_TEX, FontName ), - mStartChar(0), - mNumChars(256), - mLoadedCoords(false) -{ -} - -TextureFont::~TextureFont() { -} - -bool TextureFont::load( const Uint32& TexId, const unsigned int& StartChar, const unsigned int& Spacing, const unsigned int& TexColumns, const unsigned int& TexRows, const Uint16& NumChars ) { - Texture * Tex = TextureFactory::instance()->getTexture( TexId ); - - mTexId = TexId; - - if ( NULL != Tex ) { - mTexColumns = TexColumns; - mTexRows = TexRows; - mStartChar = StartChar; - mNumChars = NumChars; - - mtX = ( 1 / static_cast( mTexColumns ) ); - mtY = ( 1 / static_cast( mTexRows ) ); - - mFWidth = (Float)( Tex->getWidth() / mTexColumns ); - mFHeight = (Float)( Tex->getHeight() / mTexRows ); - mHeight = mSize = mLineSkip = (unsigned int)mFHeight; - - if ( Spacing == 0 ) - mSpacing = static_cast( mFWidth ); - else - mSpacing = Spacing; - - buildFont(); - - eePRINTL( "Texture Font %s loaded.", Tex->getFilepath().c_str() ); - - return true; - } - - eePRINTL( "Failed to Load Texture Font: Unknown Texture." ); - - return false; -} - -void TextureFont::buildFont() { - Float cX = 0, cY = 0; - - mTexCoords.resize( mNumChars ); - mGlyphs.resize( mNumChars ); - - TextureFactory::instance()->bind( mTexId ); - - int c = 0; - - for (unsigned int i = 0; i < mNumChars; i++) { - if ( i >= mStartChar || ( mStartChar <= 32 && i == 9 ) ) { - c = i; - - // Little hack to always provide a tab - if ( 9 == i ) { - c = 32; - } - - cX = (Float)( (c-mStartChar) % mTexColumns ) / (Float)mTexColumns; - cY = (Float)( (c-mStartChar) / mTexColumns ) / (Float)mTexRows; - - mGlyphs[i].Advance = mSpacing; - - mTexCoords[i].TexCoords[0] = cX; - mTexCoords[i].TexCoords[1] = cY; - mTexCoords[i].TexCoords[2] = cX; - mTexCoords[i].TexCoords[3] = cY + mtY; - mTexCoords[i].TexCoords[4] = cX + mtX; - mTexCoords[i].TexCoords[5] = cY + mtY; - mTexCoords[i].TexCoords[6] = cX + mtX; - mTexCoords[i].TexCoords[7] = cY; - mTexCoords[i].Vertex[0] = 0; - mTexCoords[i].Vertex[1] = 0; - mTexCoords[i].Vertex[2] = 0; - mTexCoords[i].Vertex[3] = mFHeight; - mTexCoords[i].Vertex[4] = mFWidth; - mTexCoords[i].Vertex[5] = mFHeight; - mTexCoords[i].Vertex[6] = mFWidth; - mTexCoords[i].Vertex[7] = 0; - } - } -} - -void TextureFont::buildFromGlyphs() { - Float Top, Bottom; - Rectf tR; - - mTexCoords.resize( mNumChars ); - - Texture * Tex = TextureFactory::instance()->getTexture( mTexId ); - - TextureFactory::instance()->bind( Tex ); - - GlyphData tGlyph; - - for (unsigned int i = 0; i < mNumChars; i++) { - tGlyph = mGlyphs[i]; - - tR.Left = (Float)tGlyph.CurX / Tex->getWidth(); - tR.Top = (Float)tGlyph.CurY / Tex->getHeight(); - - tR.Right = (Float)(tGlyph.CurX + tGlyph.CurW) / Tex->getWidth(); - tR.Bottom = (Float)(tGlyph.CurY + tGlyph.CurH) / Tex->getHeight(); - - Top = mHeight + mDescent - tGlyph.GlyphH - tGlyph.MinY; - Bottom = mHeight + mDescent + tGlyph.GlyphH - tGlyph.MaxY; - - mTexCoords[i].TexCoords[0] = tR.Left; - mTexCoords[i].TexCoords[1] = tR.Top; - mTexCoords[i].TexCoords[2] = tR.Left; - mTexCoords[i].TexCoords[3] = tR.Bottom; - mTexCoords[i].TexCoords[4] = tR.Right; - mTexCoords[i].TexCoords[5] = tR.Bottom; - mTexCoords[i].TexCoords[6] = tR.Right; - mTexCoords[i].TexCoords[7] = tR.Top; - mTexCoords[i].Vertex[0] = (Float) tGlyph.MinX; - mTexCoords[i].Vertex[1] = Top; - mTexCoords[i].Vertex[2] = (Float) tGlyph.MinX; - mTexCoords[i].Vertex[3] = Bottom; - mTexCoords[i].Vertex[4] = (Float) tGlyph.MaxX; - mTexCoords[i].Vertex[5] = Bottom; - mTexCoords[i].Vertex[6] = (Float) tGlyph.MaxX; - mTexCoords[i].Vertex[7] = Top; - } -} - -bool TextureFont::load( const Uint32& TexId, const std::string& CoordinatesDatPath ) { - if ( FileSystem::fileExists( CoordinatesDatPath ) ) { - IOStreamFile IOS( CoordinatesDatPath, std::ios::in | std::ios::binary ); - - return loadFromStream( TexId, IOS ); - } else if ( PackManager::instance()->isFallbackToPacksActive() ) { - std::string tPath( CoordinatesDatPath ); - - Pack * tPack = PackManager::instance()->exists( tPath ); - - if ( NULL != tPack ) { - return loadFromPack( TexId, tPack, tPath ); - } - } - - return false; -} - -bool TextureFont::loadFromPack( const Uint32& TexId, Pack* Pack, const std::string& FilePackPath ) { - if ( NULL != Pack && Pack->isOpen() && -1 != Pack->exists( FilePackPath ) ) { - SafeDataPointer PData; - - Pack->extractFileToMemory( FilePackPath, PData ); - - return loadFromMemory( TexId, reinterpret_cast ( PData.Data ), PData.DataSize ); - } - - return false; -} - -bool TextureFont::loadFromMemory( const Uint32& TexId, const char* CoordData, const Uint32& CoordDataSize ) { - IOStreamMemory IOS( CoordData, CoordDataSize ); - - return loadFromStream( TexId, IOS ); -} - -bool TextureFont::loadFromStream( const Uint32& TexId, IOStream& IOS ) { - mTexId = TexId; - - if ( mTexId > 0 ) { - if ( IOS.isOpen() ) { - sFntHdr FntHdr; - - IOS.read( (char*)&FntHdr, sizeof(sFntHdr) ); - - if ( EE_TTF_FONT_MAGIC != FntHdr.Magic ) - return false; - - mStartChar = FntHdr.FirstChar; - mNumChars = FntHdr.NumChars; - mSize = FntHdr.Size; - mHeight = FntHdr.Height; - mLineSkip = FntHdr.LineSkip; - mAscent = FntHdr.Ascent; - mDescent = FntHdr.Descent; - - mGlyphs.resize( mNumChars ); - - // Read the glyphs - IOS.read( (char*)&mGlyphs[0], sizeof(GlyphData) * mNumChars ); - - buildFromGlyphs(); - - mLoadedCoords = true; - - return true; - } - } - - return false; -} - -}} diff --git a/src/eepp/graphics/texturefontloader.cpp b/src/eepp/graphics/texturefontloader.cpp deleted file mode 100644 index e36181fd0..000000000 --- a/src/eepp/graphics/texturefontloader.cpp +++ /dev/null @@ -1,147 +0,0 @@ -#include -#include - -namespace EE { namespace Graphics { - -TextureFontLoader::TextureFontLoader( const std::string FontName, TextureLoader * TexLoader, const unsigned int& StartChar, const unsigned int& Spacing, const unsigned int& TexColumns, const unsigned int& TexRows, const Uint16& NumChars ) : - ObjectLoader( FontTexLoaderType ), - mLoadType( TEF_LT_TEX ), - mFontName( FontName ), - mStartChar( StartChar ), - mSpacing( Spacing ), - mTexColumns( TexColumns ), - mTexRows( TexRows ), - mNumChars( NumChars ), - mTexLoaded( false ), - mFontLoaded( false ) -{ - mTexLoader = TexLoader; -} - -TextureFontLoader::TextureFontLoader( const std::string FontName, TextureLoader * TexLoader, const std::string& CoordinatesDatPath ) : - ObjectLoader( FontTexLoaderType ), - mLoadType( TEF_LT_PATH ), - mFontName( FontName ), - mFilepath( CoordinatesDatPath ), - mTexLoaded( false ), - mFontLoaded( false ) -{ - mTexLoader = TexLoader; -} - -TextureFontLoader::TextureFontLoader( const std::string FontName, TextureLoader * TexLoader, Pack * Pack, const std::string& FilePackPath ) : - ObjectLoader( FontTexLoaderType ), - mLoadType( TEF_LT_PACK ), - mFontName( FontName ), - mFilepath( FilePackPath ), - mPack( Pack ), - mTexLoaded( false ), - mFontLoaded( false ) -{ - mTexLoader = TexLoader; -} - -TextureFontLoader::TextureFontLoader( const std::string FontName, TextureLoader * TexLoader, const char* CoordData, const Uint32& CoordDataSize ) : - ObjectLoader( FontTexLoaderType ), - mLoadType( TEF_LT_MEM ), - mFontName( FontName ), - mData( CoordData ), - mDataSize( CoordDataSize ), - mTexLoaded( false ), - mFontLoaded( false ) -{ - mTexLoader = TexLoader; -} - -TextureFontLoader::~TextureFontLoader() { - eeSAFE_DELETE( mTexLoader ); -} - -void TextureFontLoader::start() { - ObjectLoader::start(); - - mTexLoader->setThreaded( false ); - - if ( !mThreaded ) { - update(); - } -} - -void TextureFontLoader::update() { - if ( !mLoaded ) { - if ( !mTexLoaded ) { - mTexLoader->load(); - - mTexLoader->update(); - - mTexLoaded = mTexLoader->isLoaded(); - } - - if ( mTexLoaded && !mFontLoaded ) { - loadFont(); - } - - if ( mFontLoaded ) { - setLoaded(); - } - } -} - -const std::string& TextureFontLoader::getId() const { - return mFontName; -} - -void TextureFontLoader::loadFromPath() { - mFont->load( mTexLoader->getId(), mFilepath ); -} - -void TextureFontLoader::loadFromMemory() { - mFont->loadFromMemory( mTexLoader->getId(), mData, mDataSize ); -} - -void TextureFontLoader::loadFromPack() { - mFont->loadFromPack( mTexLoader->getId(), mPack, mFilepath ); -} - -void TextureFontLoader::loadFromTex() { - mFont->load( mTexLoader->getId(), mStartChar, mSpacing, mTexColumns, mTexRows, mNumChars ); -} - -void TextureFontLoader::loadFont() { - mFont = TextureFont::New( mFontName ); - - if ( TEF_LT_PATH == mLoadType ) - loadFromPath(); - else if ( TEF_LT_MEM == mLoadType ) - loadFromMemory(); - else if ( TEF_LT_PACK == mLoadType ) - loadFromPack(); - else if ( TEF_LT_TEX == mLoadType ) - loadFromTex(); - - mFontLoaded = true; -} - -Graphics::Font * TextureFontLoader::getFont() const { - return mFont; -} - -void TextureFontLoader::unload() { - if ( mLoaded ) { - mTexLoader->unload(); - - FontManager::instance()->remove( mFont ); - - reset(); - } -} - -void TextureFontLoader::reset() { - ObjectLoader::reset(); - - mFont = NULL; - mTexLoaded = false; - mFontLoaded = false; -} - -}} diff --git a/src/eepp/graphics/ttffont.cpp b/src/eepp/graphics/ttffont.cpp deleted file mode 100755 index 66b116f0a..000000000 --- a/src/eepp/graphics/ttffont.cpp +++ /dev/null @@ -1,455 +0,0 @@ -#include -#include -#include -#include -#include -using namespace HaikuTTF; - -namespace EE { namespace Graphics { - -TTFFont::OutlineMethods TTFFont::OutlineMethod = TTFFont::OutlineEntropia; - -TTFFont * TTFFont::New( const std::string FontName ) { - return eeNew( TTFFont, ( FontName ) ); -} - -TTFFont::TTFFont( const std::string FontName ) : - Font( FONT_TYPE_TTF, FontName ), - mFont(NULL), - mFontOutline(NULL), - mPixels(NULL), - mThreadedLoading(false), - mTexReady(false) -{ -} - -TTFFont::~TTFFont() { - hkFontManager::instance()->destroy(); -} - -bool TTFFont::loadFromPack( Pack* Pack, const std::string& FilePackPath, const unsigned int& Size, EE_TTF_FONT_STYLE Style, const Uint16& NumCharsToGen, const RGB& FontColor, const Uint8& OutlineSize, const RGB& OutlineColor, const bool& AddPixelSeparator ) { - bool Ret = false; - SafeDataPointer PData; - - if ( Pack->isOpen() && Pack->extractFileToMemory( FilePackPath, PData ) ) { - mFilepath = FilePackPath; - - Ret = loadFromMemory( PData.Data, PData.DataSize, Size, Style, NumCharsToGen, FontColor, OutlineSize, OutlineColor, AddPixelSeparator ); - } - - return Ret; -} - -bool TTFFont::loadFromMemory( Uint8* TTFData, const unsigned int& TTFDataSize, const unsigned int& Size, EE_TTF_FONT_STYLE Style, const Uint16& NumCharsToGen, const RGB& FontColor, const Uint8& OutlineSize, const RGB& OutlineColor, const bool& AddPixelSeparator ) { - if ( !mFilepath.size() ) - mFilepath = "from memory"; - - mLoadedFromMemory = true; - - Int32 rSize = (Int32)((Float)Size * PixelDensity::getPixelDensity()); - - mFont = hkFontManager::instance()->openFromMemory( reinterpret_cast(&TTFData[0]), TTFDataSize, rSize, 0, NumCharsToGen ); - - if ( OutlineSize && OutlineFreetype == OutlineMethod ) { - mFontOutline = hkFontManager::instance()->openFromMemory( reinterpret_cast(&TTFData[0]), TTFDataSize, rSize, 0, NumCharsToGen ); - mFontOutline->outline( OutlineSize * PixelDensity::getPixelDensity() ); - } - - return iLoad( rSize, Style, NumCharsToGen, FontColor, OutlineSize * PixelDensity::getPixelDensity(), OutlineColor, AddPixelSeparator ); -} - -bool TTFFont::load( const std::string& Filepath, const unsigned int& Size, EE_TTF_FONT_STYLE Style, const Uint16& NumCharsToGen, const RGB& FontColor, const Uint8& OutlineSize, const RGB& OutlineColor, const bool& AddPixelSeparator ) { - mFilepath = Filepath; - - if ( FileSystem::fileExists( Filepath ) ) { - mLoadedFromMemory = false; - - Int32 rSize = (Int32)((Float)Size * PixelDensity::getPixelDensity()); - - mFont = hkFontManager::instance()->openFromFile( Filepath.c_str(), rSize, 0, NumCharsToGen ); - - if ( OutlineSize && OutlineFreetype == OutlineMethod ) { - mFontOutline = hkFontManager::instance()->openFromFile( Filepath.c_str(), rSize, 0, NumCharsToGen ); - mFontOutline->outline( OutlineSize * PixelDensity::getPixelDensity() ); - } - - return iLoad( rSize, Style, NumCharsToGen, FontColor, OutlineSize * PixelDensity::getPixelDensity(), OutlineColor, AddPixelSeparator ); - } else if ( PackManager::instance()->isFallbackToPacksActive() ) { - Pack * tPack = PackManager::instance()->exists( mFilepath ); - - if ( NULL != tPack ) { - return loadFromPack( tPack, mFilepath, Size, Style, NumCharsToGen, FontColor, OutlineSize, OutlineColor, AddPixelSeparator ); - } - } - - return false; -} - -bool TTFFont::iLoad( const unsigned int& Size, EE_TTF_FONT_STYLE Style, const Uint16& NumCharsToGen, const RGB& FontColor, Uint8 OutlineSize, const RGB& OutlineColor, const bool& AddPixelSeparator ) { - Rect CurrentPos; - Sizei GlyphRect; - - unsigned char * TempGlyphSurface = NULL; - unsigned char * TempOutGlyphSurface = NULL; - - // Change the outline size to add a pixel separating the character from the around characters to prevent ugly zooming of characters - Uint32 PixelSep = 0; - - if ( AddPixelSeparator ) - PixelSep = 1; - - Uint32 TexSize; - Uint32 OutSize = ( OutlineFreetype == OutlineMethod ) ? 0 : OutlineSize; - Uint32 OutTotal = ( OutlineFreetype == OutlineMethod ) ? 0 : OutlineSize * 2; - - if ( mFont == NULL ) { - eePRINTL( "Failed to load TTF Font %s.", mFilepath.c_str() ); - - return false; - } - - mSize = Size; - - mFont->style( Style ); - - mHeight = mFont->height() + OutTotal; - mLineSkip = mFont->lineSkip(); - mAscent = mFont->ascent(); - mDescent = mFont->descent(); - - if ( NULL != mFontOutline ) - mHeight = mFontOutline->height(); - - mNumChars = NumCharsToGen; - mFontColor = FontColor; - mOutlineColor = OutlineColor; - mStyle = Style; - mTexWidth = 128; - mTexHeight = 128; - - mGlyphs.clear(); - mGlyphs.resize( mNumChars ); - - bool lastWasWidth = false; - Uint32 ReqSize; - - // Find the best size for the texture ( aprox ) - // Totally wild guessing, but it's working - Int32 tWildGuessW = ( mAscent + PixelSep + OutlineSize ); - Int32 tWildGuessH = tWildGuessW; - - ReqSize = mNumChars * tWildGuessW * tWildGuessH; - - do { - TexSize = (Uint32)mTexWidth * (Uint32)mTexHeight; - - if ( TexSize < ReqSize ) { - if ( !lastWasWidth ) - mTexWidth *= 2; - else - mTexHeight *= 2; - - lastWasWidth = !lastWasWidth; - } - } while ( TexSize < ReqSize ); - - mPixels = eeNewArray( ColorA, TexSize ); - memset( mPixels, 0x00000000, TexSize * 4 ); - - CurrentPos.Left = OutSize; - CurrentPos.Top = OutSize; - - Uint32 * TexGlyph; - Uint32 w = (Uint32)mTexWidth; - //Uint32 h = (Uint32)mTexHeight; - ColorA fFontColor( FontColor ); - - //Loop through all chars - for ( unsigned int i = 0; i < mNumChars; i++ ) { - TempGlyphSurface = mFont->renderGlyph( i, fFontColor.getValue() ); - - //New temp glyph - GlyphData TempGlyph; - - //Get the glyph attributes - mFont->getGlyphMetrics( i, &TempGlyph.MinX, &TempGlyph.MaxX, &TempGlyph.MinY, &TempGlyph.MaxY, &TempGlyph.Advance ); - - //Set size of glyph rect - GlyphRect.x = mFont->current()->pixmap()->width; - GlyphRect.y = mFont->current()->pixmap()->rows; - - // Create the outline for the glyph and copy the outline to the texture - if ( OutlineSize && OutlineFreetype == OutlineMethod ) { - TempOutGlyphSurface = mFontOutline->renderGlyph( i, ColorA( OutlineColor ).getValue() ); - - mFontOutline->getGlyphMetrics( i, &TempGlyph.MinX, &TempGlyph.MaxX, &TempGlyph.MinY, &TempGlyph.MaxY, &TempGlyph.Advance ); - - // Set size of glyph rect - GlyphRect.x = mFontOutline->current()->pixmap()->width; - GlyphRect.y = mFontOutline->current()->pixmap()->rows; - - // Fix to ensure that the glyph is rendered with the real size - if ( eeabs( TempGlyph.MaxX - TempGlyph.MinX ) != GlyphRect.x ) { - TempGlyph.MaxX = TempGlyph.MinX + GlyphRect.x; - } - - Image out( TempOutGlyphSurface, GlyphRect.x, GlyphRect.y, 4 ); out.avoidFreeImage( true ); - Image in( TempGlyphSurface, mFont->current()->pixmap()->width, mFont->current()->pixmap()->rows, 4 ); in.avoidFreeImage( true ); - - Uint32 px = ( ( (Float)out.getWidth() - (Float)in.getWidth() ) * 0.5f ); - Uint32 py = ( ( (Float)out.getHeight() - (Float)in.getHeight() ) * 0.5f ); - - out.blit( &in, px, py ); - - TexGlyph = reinterpret_cast ( TempOutGlyphSurface ); - } else { - TexGlyph = reinterpret_cast ( TempGlyphSurface ); - } - - //Set size of current position rect - CurrentPos.Right = CurrentPos.Left + TempGlyph.MaxX; - CurrentPos.Bottom = CurrentPos.Top + TempGlyph.MaxY; - - if ( CurrentPos.Right >= mTexWidth ) { - CurrentPos.Left = OutSize; - CurrentPos.Top += mHeight; - } - - // Copy the glyph to the texture - for (int y = 0; y < GlyphRect.y; ++y ) { - // Copy per row - memcpy( &mPixels[ CurrentPos.Left + (CurrentPos.Top + y) * w ], &TexGlyph[ y * GlyphRect.x ], GlyphRect.x * sizeof(ColorA) ); - } - - // Fixes the width and height of the current pos - CurrentPos.Right = GlyphRect.x; - CurrentPos.Bottom = GlyphRect.y; - - GlyphRect.y += OutSize; - TempGlyph.Advance += OutSize; - - // Translate the Glyph coordinates to the new texture coordinates - TempGlyph.MinX -= OutSize; - TempGlyph.MinY -= OutSize; - TempGlyph.MaxX += OutSize; - TempGlyph.MaxY += OutSize; - TempGlyph.CurX = CurrentPos.Left - OutSize; - TempGlyph.CurW = CurrentPos.Right + OutTotal; - TempGlyph.CurY = CurrentPos.Top - OutSize; - TempGlyph.CurH = CurrentPos.Bottom + OutTotal; - TempGlyph.GlyphH = GlyphRect.y + OutSize; - - //Position xpos ready for next glyph - CurrentPos.Left += GlyphRect.x + OutTotal + PixelSep; - - //If the next character will run off the edge of the glyph sheet, advance to next row - if ( CurrentPos.Left + CurrentPos.Right > mTexWidth ) { - CurrentPos.Left = OutSize; - CurrentPos.Top += mHeight; - } - - // Create the outline for the glyph and copy the outline to the texture - if ( OutlineSize && OutlineEntropia == OutlineMethod ) { - Recti nGlyphR( - TempGlyph.CurX, - TempGlyph.CurY, - TempGlyph.CurX + TempGlyph.CurW, - TempGlyph.CurY + TempGlyph.CurH - ); - Sizei nGlyphS( nGlyphR.getSize() ); - - if ( nGlyphS.x > 0 && nGlyphS.y > 0 ) { - Uint32 Pos = 0; - Uint32 RPos = 0; - Uint32 alphaSize = nGlyphS.x * nGlyphS.y; - Uint8 * alpha_init = (Uint8*)malloc( alphaSize ); - Uint8 * alpha_final = (Uint8*)malloc( alphaSize ); - - // Fill the alpha_init ( the default font alpha channels ) and the alpha_final ( the new outline ) - for ( Int32 y = 0; y < nGlyphS.y; y++ ) { - for( Int32 x = 0; x < nGlyphS.x; x++) { - RPos = ( nGlyphR.Left + x ) + ( nGlyphR.Top + y ) * w; - Pos = x + y * nGlyphS.x; - - alpha_init[ Pos ] = mPixels[ RPos ].a(); - alpha_final[ Pos ] = 0; - } - } - - // Create the outline - makeOutline( alpha_init, alpha_final, nGlyphS.x, nGlyphS.y, OutlineSize ); - - for ( Int32 y = 0; y < nGlyphS.y; y++ ) { - for( Int32 x = 0; x < nGlyphS.x; x++) { - RPos = ( nGlyphR.Left + x ) + ( nGlyphR.Top + y ) * w; - Pos = x + y * nGlyphS.x; - - // Blending the normal glyph color to the outline color - mPixels[ RPos ] = Color::blend( ColorA( FontColor, alpha_init[ Pos ] ), ColorA( OutlineColor, alpha_final[ Pos ] ) ); - } - } - - free( alpha_init ); - free( alpha_final ); - } - } - - //Push back to glyphs vector - mGlyphs[i] = TempGlyph; - - //Free surface - hkSAFE_DELETE_ARRAY( TempGlyphSurface ); - - hkSAFE_DELETE_ARRAY( TempOutGlyphSurface ); - } - - hkFontManager::instance()->closeFont( mFont ); - - if ( NULL != mFontOutline ) - hkFontManager::instance()->closeFont( mFontOutline ); - - mTexReady = true; - - if ( !mThreadedLoading ) - updateLoading(); - - return true; -} - -void TTFFont::updateLoading() { - if ( mTexReady && NULL != mPixels ) { - std::string name( FileSystem::fileRemoveExtension( FileSystem::fileNameFromPath( mFilepath ) ) ); - - mTexId = TextureFactory::instance()->loadFromPixels( reinterpret_cast ( &mPixels[0] ), (Uint32)mTexWidth, (Uint32)mTexHeight, 4, false, CLAMP_TO_EDGE, false, false, name ); - - eeSAFE_DELETE_ARRAY( mPixels ); - - rebuildFromGlyphs(); - - eePRINTL( "TTF Font %s loaded.", mFilepath.c_str() ); - } -} - -void TTFFont::rebuildFromGlyphs() { - Float Top, Bottom; - Rectf tR; - - mTexCoords.resize( mNumChars ); - - Texture * Tex = TextureFactory::instance()->getTexture( mTexId ); - - GlyphData tGlyph; - - for (unsigned int i = 0; i < mNumChars; i++) { - tGlyph = mGlyphs[i]; - - tR.Left = (Float)tGlyph.CurX / Tex->getWidth(); - tR.Top = (Float)tGlyph.CurY / Tex->getHeight(); - - tR.Right = (Float)(tGlyph.CurX + tGlyph.CurW) / Tex->getWidth(); - tR.Bottom = (Float)(tGlyph.CurY + tGlyph.CurH) / Tex->getHeight(); - - Top = (Float)mHeight + mDescent - tGlyph.GlyphH - tGlyph.MinY; - Bottom = (Float)mHeight + mDescent + tGlyph.GlyphH - tGlyph.MaxY; - - mTexCoords[i].TexCoords[0] = tR.Left; - mTexCoords[i].TexCoords[1] = tR.Top; - mTexCoords[i].TexCoords[2] = tR.Left; - mTexCoords[i].TexCoords[3] = tR.Bottom; - mTexCoords[i].TexCoords[4] = tR.Right; - mTexCoords[i].TexCoords[5] = tR.Bottom; - mTexCoords[i].TexCoords[6] = tR.Right; - mTexCoords[i].TexCoords[7] = tR.Top; - mTexCoords[i].Vertex[0] = (Float) tGlyph.MinX; - mTexCoords[i].Vertex[1] = Top; - mTexCoords[i].Vertex[2] = (Float) tGlyph.MinX; - mTexCoords[i].Vertex[3] = Bottom; - mTexCoords[i].Vertex[4] = (Float) tGlyph.MaxX; - mTexCoords[i].Vertex[5] = Bottom; - mTexCoords[i].Vertex[6] = (Float) tGlyph.MaxX; - mTexCoords[i].Vertex[7] = Top; - } -} - -bool TTFFont::saveTexture( const std::string& Filepath, const EE_SAVE_TYPE& Format ) { - Texture* Tex = TextureFactory::instance()->getTexture(mTexId); - - if ( Tex != NULL ) - return Tex->saveToFile( Filepath, Format ); - - return false; -} - -bool TTFFont::saveCoordinates( const std::string& Filepath ) { - IOStreamFile fs( Filepath, std::ios::out | std::ios::binary ); - - if ( fs.isOpen() ) { - sFntHdr FntHdr; - - FntHdr.Magic = EE_TTF_FONT_MAGIC; - FntHdr.FirstChar = 0; - FntHdr.NumChars = mGlyphs.size(); - FntHdr.Size = mSize; - FntHdr.Height = mHeight; - FntHdr.LineSkip = mLineSkip; - FntHdr.Ascent = mAscent; - FntHdr.Descent = mDescent; - - // Write the header - fs.write( reinterpret_cast( &FntHdr ), sizeof(sFntHdr) ); - - // Write the glyphs - fs.write( reinterpret_cast (&mGlyphs[0]), sizeof(GlyphData) * mGlyphs.size() ); - - rebuildFromGlyphs(); - - return true; - } else { - eePRINTL("TTFFont::SaveCoordinates(): Unable to write file: %s.", Filepath.c_str() ); - } - - return false; -} - -bool TTFFont::save( const std::string& TexturePath, const std::string& CoordinatesDatPath, const EE_SAVE_TYPE& Format ) { - return saveTexture(TexturePath, Format) && saveCoordinates( CoordinatesDatPath ); -} - -void TTFFont::makeOutline( Uint8 *in, Uint8 *out, Int16 w, Int16 h , Int16 OutlineSize ) { - int y, x, s_y, s_x, get_y, get_x, index, pos; - Uint8 c; - - for ( y = 0; y < h; y++ ) { - for( x = 0; x < w; x++ ) { - pos = y * w + x; - - c = in[ pos ]; - - for ( s_y = -OutlineSize; s_y <= OutlineSize; s_y++ ) { - for ( s_x = -OutlineSize; s_x <= OutlineSize; s_x++ ) { - get_x = x + s_x; - get_y = y + s_y; - - if ( get_x >= 0 && get_y >= 0 && get_x < w && get_y < h ) { - index = get_y * w + get_x; - - if ( in[index] > c ) - c = in[index]; - } - } - } - - out[ pos ] = c; - } - } -} - -bool TTFFont::threadedLoading() const { - return mThreadedLoading; -} - -void TTFFont::threadedLoading( const bool& isThreaded ) { - mThreadedLoading = isThreaded; -} - -}} diff --git a/src/eepp/graphics/ttffontloader.cpp b/src/eepp/graphics/ttffontloader.cpp deleted file mode 100644 index 12d809b37..000000000 --- a/src/eepp/graphics/ttffontloader.cpp +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include -#include - -namespace EE { namespace Graphics { - -TTFFontLoader::TTFFontLoader( const std::string& FontName, const std::string& Filepath, const unsigned int& Size, EE_TTF_FONT_STYLE Style, const Uint16& NumCharsToGen, const RGB& FontColor, const Uint8& OutlineSize, const RGB& OutlineColor, const bool& AddPixelSeparator ) : - ObjectLoader( FontTTFLoaderType ), - mLoadType( TTF_LT_PATH ), - mFontName( FontName ), - mFilepath( Filepath ), - mSize( Size ), - mStyle( Style ), - mNumCharsToGen( NumCharsToGen ), - mFontColor( FontColor ), - mOutlineSize( OutlineSize ), - mOutlineColor( OutlineColor ), - mAddPixelSeparator( AddPixelSeparator ), - mFontLoaded( false ) -{ - create(); -} - -TTFFontLoader::TTFFontLoader( const std::string& FontName, Pack * Pack, const std::string& FilePackPath, const unsigned int& Size, EE_TTF_FONT_STYLE Style, const Uint16& NumCharsToGen, const RGB& FontColor, const Uint8& OutlineSize, const RGB& OutlineColor, const bool& AddPixelSeparator ) : - ObjectLoader( FontTTFLoaderType ), - mLoadType( TTF_LT_PACK ), - mFontName( FontName ), - mFilepath( FilePackPath ), - mSize( Size ), - mStyle( Style ), - mNumCharsToGen( NumCharsToGen ), - mFontColor( FontColor ), - mOutlineSize( OutlineSize ), - mOutlineColor( OutlineColor ), - mAddPixelSeparator( AddPixelSeparator ), - mPack( Pack ), - mFontLoaded( false ) -{ - create(); -} - -TTFFontLoader::TTFFontLoader( const std::string& FontName, Uint8* TTFData, const unsigned int& TTFDataSize, const unsigned int& Size, EE_TTF_FONT_STYLE Style, const Uint16& NumCharsToGen, const RGB& FontColor, const Uint8& OutlineSize, const RGB& OutlineColor, const bool& AddPixelSeparator ) : - ObjectLoader( FontTTFLoaderType ), - mLoadType( TTF_LT_MEM ), - mFontName( FontName ), - mSize( Size ), - mStyle( Style ), - mNumCharsToGen( NumCharsToGen ), - mFontColor( FontColor ), - mOutlineSize( OutlineSize ), - mOutlineColor( OutlineColor ), - mAddPixelSeparator( AddPixelSeparator ), - mData( TTFData ), - mDataSize( TTFDataSize ), - mFontLoaded( false ) -{ - create(); -} - -TTFFontLoader::~TTFFontLoader() { -} - -void TTFFontLoader::create() { - mFont = TTFFont::New( mFontName ); -} - -void TTFFontLoader::start() { - ObjectLoader::start(); - - mFont->threadedLoading( mThreaded ); - - if ( TTF_LT_PATH == mLoadType ) - loadFromPath(); - else if ( TTF_LT_MEM == mLoadType ) - loadFromMemory(); - else if ( TTF_LT_PACK == mLoadType ) - loadFromPack(); - - mFontLoaded = true; - - if ( !mThreaded ) - update(); -} - -void TTFFontLoader::update() { - if ( !mLoaded && mFontLoaded ) { - mFont->updateLoading(); - - setLoaded(); - } -} - -const std::string& TTFFontLoader::getId() const { - return mFontName; -} - -void TTFFontLoader::loadFromPath() { - mFont->load( mFilepath, mSize, mStyle, mNumCharsToGen, mFontColor, mOutlineSize, mOutlineColor, mAddPixelSeparator ); -} - -void TTFFontLoader::loadFromMemory() { - mFont->loadFromMemory( mData, mDataSize, mSize, mStyle, mNumCharsToGen, mFontColor, mOutlineSize, mOutlineColor, mAddPixelSeparator ); -} - -void TTFFontLoader::loadFromPack() { - mFont->loadFromPack( mPack, mFilepath, mSize, mStyle, mNumCharsToGen, mFontColor, mOutlineSize, mOutlineColor, mAddPixelSeparator ); -} - -Graphics::Font * TTFFontLoader::getFont() const { - return mFont; -} - -void TTFFontLoader::unload() { - if ( mLoaded ) { - TextureFactory::instance()->remove( mFont->getTexId() ); - - FontManager::instance()->remove( mFont ); - - reset(); - } -} - -void TTFFontLoader::reset() { - ObjectLoader::reset(); - - mFontLoaded = false; -} - -}} diff --git a/src/eepp/ui/uilistbox.cpp b/src/eepp/ui/uilistbox.cpp index 5f2d9edc7..a9dd23dfb 100644 --- a/src/eepp/ui/uilistbox.cpp +++ b/src/eepp/ui/uilistbox.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace EE { namespace UI { @@ -143,7 +144,7 @@ Uint32 UIListBox::addListBoxItem( const String& Text ) { mItems.push_back( NULL ); if ( NULL != mFontStyleConfig.Font ) { - TextCache textCache( mFontStyleConfig.Font ); + TextCache textCache( mFontStyleConfig.Font, mFontStyleConfig.FontCharacterSize ); textCache.setText( Text ); Uint32 twidth = textCache.getTextWidth(); @@ -295,18 +296,18 @@ void UIListBox::setRowHeight() { Uint32 tOldRowHeight = mRowHeight; if ( 0 == mRowHeight ) { - Uint32 FontSize = 12; + Uint32 FontSize = PixelDensity::dpToPxI( 12 ); if ( NULL != UIThemeManager::instance()->getDefaultFont() ) - FontSize = UIThemeManager::instance()->getDefaultFont()->getFontHeight(); + FontSize = UIThemeManager::instance()->getDefaultFont()->getFontHeight( PixelDensity::dpToPxI( UIThemeManager::instance()->getDefaultFontStyleConfig().FontCharacterSize ) ); if ( NULL != mSkinState && NULL != mSkinState->getSkin() && NULL != mSkinState->getSkin()->getTheme() && NULL != mSkinState->getSkin()->getTheme()->getFontStyleConfig().getFont() ) - FontSize = mSkinState->getSkin()->getTheme()->getFontStyleConfig().getFont()->getFontHeight(); + FontSize = mSkinState->getSkin()->getTheme()->getFontStyleConfig().getFont()->getFontHeight( PixelDensity::dpToPxI( mSkinState->getSkin()->getTheme()->getFontStyleConfig().FontCharacterSize ) ); if ( NULL != mFontStyleConfig.getFont() ) - FontSize = mFontStyleConfig.getFont()->getFontHeight(); + FontSize = mFontStyleConfig.getFont()->getFontHeight( PixelDensity::dpToPxI( mFontStyleConfig.FontCharacterSize ) ); - mRowHeight = (Uint32)PixelDensity::pxToDpI( FontSize + 4 ); + mRowHeight = (Uint32)PixelDensity::pxToDpI( FontSize ); } if ( tOldRowHeight != mRowHeight ) { @@ -331,7 +332,7 @@ void UIListBox::setHScrollStep() { void UIListBox::findMaxWidth() { Uint32 size = (Uint32)mItems.size(); Int32 width; - TextCache textCache( mFontStyleConfig.Font ); + TextCache textCache( mFontStyleConfig.Font, mFontStyleConfig.FontCharacterSize ); mMaxTextWidth = 0; diff --git a/src/eepp/ui/uitextedit.cpp b/src/eepp/ui/uitextedit.cpp index 1d522f9f5..595af395e 100644 --- a/src/eepp/ui/uitextedit.cpp +++ b/src/eepp/ui/uitextedit.cpp @@ -345,7 +345,7 @@ void UITextEdit::fixScrollToCursor() { Uint32 NLPos = 0; Uint32 LineNum = mTextInput->getInputTextBuffer()->getCurPosLinePos( NLPos ); - TextCache textCache( mTextInput->getTextCache()->getFont() ); + TextCache textCache( mTextInput->getTextCache()->getFont(), mTextInput->getFontStyleConfig().FontCharacterSize ); textCache.setText( mTextInput->getInputTextBuffer()->getBuffer().substr( NLPos, mTextInput->getInputTextBuffer()->getCursorPos() - NLPos @@ -355,7 +355,7 @@ void UITextEdit::fixScrollToCursor() { mSkipValueChange = true; Float tW = textCache.getTextWidth(); - Float tH = (Float)(LineNum + 1) * (Float)textCache.getFont()->getFontHeight(); + Float tH = (Float)(LineNum + 1) * (Float)textCache.getFont()->getLineSpacing( textCache.getCharacterSizePx() ); if ( tW > Width ) { mTextInput->setPixelsPosition( mContainerPadding.Left + Width - tW, mTextInput->getRealPosition().y ); diff --git a/src/eepp/ui/uitextinput.cpp b/src/eepp/ui/uitextinput.cpp index 75ffff540..ca385f2d7 100644 --- a/src/eepp/ui/uitextinput.cpp +++ b/src/eepp/ui/uitextinput.cpp @@ -100,7 +100,7 @@ void UITextInput::drawWaitingCursor() { if ( CurPosX > (Float)mScreenPos.x + (Float)mRealSize.x ) CurPosX = (Float)mScreenPos.x + (Float)mRealSize.x; - P.drawLine( Line2f( Vector2f( CurPosX, CurPosY ), Vector2f( CurPosX, CurPosY + mTextCache->getFont()->getFontHeight() ) ) ); + P.drawLine( Line2f( Vector2f( CurPosX, CurPosY ), Vector2f( CurPosX, CurPosY + mTextCache->getFont()->getLineSpacing( mTextCache->getCharacterSizePx() ) ) ) ); if ( disableSmooth ) GLi->lineSmooth( true ); @@ -159,7 +159,7 @@ void UITextInput::alignFix() { Uint32 NLPos = 0; Uint32 LineNum = mTextBuffer.getCurPosLinePos( NLPos ); - TextCache textCache( mTextCache->getFont() ); + TextCache textCache( mTextCache->getFont(), mTextCache->getCharacterSize() ); textCache.setText( mTextBuffer.getBuffer().substr( NLPos, mTextBuffer.getCursorPos() - NLPos ) ); @@ -167,7 +167,7 @@ void UITextInput::alignFix() { Float tX = mRealAlignOffset.x + tW; mCurPos.x = tW; - mCurPos.y = (Float)LineNum * (Float)mTextCache->getFont()->getFontHeight(); + mCurPos.y = (Float)LineNum * (Float)mTextCache->getFont()->getLineSpacing( mTextCache->getCharacterSizePx() ); if ( !mTextBuffer.setSupportNewLine() ) { if ( tX < 0.f ) @@ -257,7 +257,7 @@ Uint32 UITextInput::onMouseClick( const Vector2i& Pos, const Uint32 Flags ) { worldToControl( controlPos ); controlPos = PixelDensity::dpToPxI( controlPos ) - Vector2i( (Int32)mRealAlignOffset.x, (Int32)mRealAlignOffset.y ); - Int32 curPos = mTextCache->getFont()->findClosestCursorPosFromPoint( mTextCache->getText(), controlPos ); + Int32 curPos = mTextCache->getFont()->findClosestCursorPosFromPoint( mTextCache->getText(), mTextCache->getCharacterSizePx(), mTextCache->getStyle() & TextCache::Bold, mTextCache->getOutlineThickness(), controlPos ); if ( -1 != curPos ) { mTextBuffer.setCursorPos( curPos ); diff --git a/src/eepp/ui/uitextinputpassword.cpp b/src/eepp/ui/uitextinputpassword.cpp index b039d4f00..dd5742b08 100644 --- a/src/eepp/ui/uitextinputpassword.cpp +++ b/src/eepp/ui/uitextinputpassword.cpp @@ -69,7 +69,7 @@ void UITextInputPassword::alignFix() { Float tX = mRealAlignOffset.x + tW; mCurPos.x = tW; - mCurPos.y = (Float)LineNum * (Float)mPassCache->getFont()->getFontHeight(); + mCurPos.y = (Float)LineNum * (Float)mPassCache->getFont()->getLineSpacing( mPassCache->getCharacterSizePx() ); if ( !mTextBuffer.setSupportNewLine() ) { if ( tX < 0.f ) @@ -111,8 +111,6 @@ void UITextInputPassword::updateText() { } void UITextInputPassword::updatePass( const String& pass ) { - mPassCache->getText().clear(); - String newTxt; for ( size_t i = 0; i < pass.size(); i++ ) { @@ -137,6 +135,7 @@ TextCache *UITextInputPassword::getPassCache() const { void UITextInputPassword::setFontStyleConfig(const TooltipStyleConfig & fontStyleConfig) { UITextInput::setFontStyleConfig( fontStyleConfig ); + mPassCache->setCharacterSize( mFontStyleConfig.FontCharacterSize ); mPassCache->setFont( mFontStyleConfig.getFont() ); mPassCache->setColor( mFontStyleConfig.getFontColor() ); mPassCache->setShadowColor( mFontStyleConfig.getFontShadowColor() ); diff --git a/src/eepp/ui/uitextview.cpp b/src/eepp/ui/uitextview.cpp index 275e9c4f5..ec57a5bc5 100644 --- a/src/eepp/ui/uitextview.cpp +++ b/src/eepp/ui/uitextview.cpp @@ -23,6 +23,7 @@ UITextView::UITextView() : mFontStyleConfig = UIThemeManager::instance()->getDefaultFontStyleConfig(); mTextCache = eeNew( TextCache, () ); + mTextCache->setCharacterSize( mFontStyleConfig.FontCharacterSize ); mTextCache->setFont( mFontStyleConfig.Font ); mTextCache->setColor( mFontStyleConfig.FontColor ); mTextCache->setShadowColor( mFontStyleConfig.FontShadowColor ); @@ -153,7 +154,7 @@ void UITextView::shrinkText( const Uint32& MaxWidth ) { mTextCache->setText( mString ); } - mTextCache->getFont()->shrinkText( mTextCache->getText(), MaxWidth ); + mTextCache->getFont()->shrinkText( mTextCache->getText(), mTextCache->getCharacterSizePx(), mTextCache->getStyle() & TextCache::Bold, mTextCache->getOutlineThickness(), MaxWidth ); mTextCache->cacheWidth(); } @@ -252,7 +253,7 @@ Uint32 UITextView::onMouseDoubleClick( const Vector2i& Pos, const Uint32 Flags ) worldToControl( controlPos ); controlPos = PixelDensity::dpToPxI( controlPos ); - Int32 curPos = mTextCache->getFont()->findClosestCursorPosFromPoint( mTextCache->getText(), controlPos ); + Int32 curPos = mTextCache->getFont()->findClosestCursorPosFromPoint( mTextCache->getText(), mTextCache->getCharacterSizePx(), mTextCache->getStyle() & TextCache::Bold, mTextCache->getOutlineThickness(), controlPos ); if ( -1 != curPos ) { Int32 tSelCurInit, tSelCurEnd; @@ -288,7 +289,7 @@ Uint32 UITextView::onMouseDown( const Vector2i& Pos, const Uint32 Flags ) { worldToControl( controlPos ); controlPos = PixelDensity::dpToPxI( controlPos ) - Vector2i( (Int32)mRealAlignOffset.x, (Int32)mRealAlignOffset.y ); - Int32 curPos = mTextCache->getFont()->findClosestCursorPosFromPoint( mTextCache->getText(), controlPos ); + Int32 curPos = mTextCache->getFont()->findClosestCursorPosFromPoint( mTextCache->getText(), mTextCache->getCharacterSizePx(), mTextCache->getStyle() & TextCache::Bold, mTextCache->getOutlineThickness(), controlPos ); if ( -1 != curPos ) { if ( -1 == selCurInit() || !( mControlFlags & UI_CTRL_FLAG_SELECTING ) ) { @@ -321,19 +322,19 @@ void UITextView::drawSelection( TextCache * textCache ) { P.setColor( mFontStyleConfig.FontSelectionBackColor ); do { - initPos = textCache->getFont()->getCursorPos( textCache->getText(), init ); + initPos = textCache->getFont()->getCursorPos( textCache->getText(), textCache->getCharacterSizePx(), textCache->getStyle() & TextCache::Bold, textCache->getOutlineThickness(), init ); lastEnd = textCache->getText().find_first_of( '\n', init ); if ( lastEnd < end && -1 != lastEnd ) { - endPos = textCache->getFont()->getCursorPos( textCache->getText(), lastEnd ); + endPos = textCache->getFont()->getCursorPos( textCache->getText(), textCache->getCharacterSizePx(), textCache->getStyle() & TextCache::Bold, textCache->getOutlineThickness(), lastEnd ); init = lastEnd + 1; } else { - endPos = textCache->getFont()->getCursorPos( textCache->getText(), end ); + endPos = textCache->getFont()->getCursorPos( textCache->getText(), textCache->getCharacterSizePx(), textCache->getStyle() & TextCache::Bold, textCache->getOutlineThickness(), end ); lastEnd = end; } P.drawRectangle( Rectf( mScreenPos.x + initPos.x + mRealAlignOffset.x + mRealPadding.Left, - mScreenPos.y + initPos.y - textCache->getFont()->getFontHeight() + mRealAlignOffset.y + mRealPadding.Top, + mScreenPos.y + initPos.y - textCache->getFont()->getLineSpacing( textCache->getCharacterSizePx() ) + mRealAlignOffset.y + mRealPadding.Top, mScreenPos.x + endPos.x + mRealAlignOffset.x + mRealPadding.Left, mScreenPos.y + endPos.y + mRealAlignOffset.y + mRealPadding.Top ) ); diff --git a/src/eepp/ui/uithememanager.cpp b/src/eepp/ui/uithememanager.cpp index 06edd91b2..afa9af8a5 100644 --- a/src/eepp/ui/uithememanager.cpp +++ b/src/eepp/ui/uithememanager.cpp @@ -133,12 +133,12 @@ const Sizei& UIThemeManager::getCursorSize() const { return mCursorSize; } -TooltipStyleConfig UIThemeManager::getDefaultFontStyleConfig() { +FontStyleConfig UIThemeManager::getDefaultFontStyleConfig() { if ( NULL != getDefaultTheme() ) { return getDefaultTheme()->getFontStyleConfig(); } - return TooltipStyleConfig(); + return FontStyleConfig(); } }} diff --git a/src/eepp/ui/uitooltip.cpp b/src/eepp/ui/uitooltip.cpp index 6624e8bca..e7adc8602 100644 --- a/src/eepp/ui/uitooltip.cpp +++ b/src/eepp/ui/uitooltip.cpp @@ -272,6 +272,7 @@ void UITooltip::setStyleConfig(const TooltipStyleConfig & styleConfig) { setFont( mStyleConfig.Font ); setFontColor( mStyleConfig.FontColor ); setFontShadowColor( mStyleConfig.FontShadowColor ); + mTextCache->setCharacterSize( mStyleConfig.FontCharacterSize ); } }} diff --git a/src/examples/fonts/fonts.cpp b/src/examples/fonts/fonts.cpp index a3460db80..b43cb39d1 100644 --- a/src/examples/fonts/fonts.cpp +++ b/src/examples/fonts/fonts.cpp @@ -1,23 +1,12 @@ #include #include -#include +#include EE::Window::Window * win = NULL; -TTFFont * TTF = NULL; -TTFFont * TTFO = NULL; -TTFFont * TTF2 = NULL; -TextureFont * TexF = NULL; -TextureFont * TexF2 = NULL; -TextCache TTFCache; -TextCache TTF2Cache; -TextCache TTFOCache; -TextCache TexFCache; -TextCache TexF2Cache; -TextCache TxtCache; -FontTrueType fontTest; +FontTrueType * fontTest; Uint32 nextGliph = 0; Clock timer; -Text text; +TextCache text; void mainLoop() { @@ -78,84 +67,16 @@ EE_MAIN_FUNC int main (int argc, char * argv []) // Get the application path std::string AppPath = Sys::getProcessPath(); - // Create a new True Type Font - TTF = TTFFont::New( "DejaVuSansMonoOutline" ); - TTFO = TTFFont::New( "DejaVuSansMonoOutlineFreetype" ); - TTF2 = TTFFont::New( "DejaVuSansMono" ); - TexF = TextureFont::New( "ProggySquareSZ" ); - TexF2 = TextureFont::New( "conchars" ); - - // Load the TTF font - TTF->load( AppPath + "assets/fonts/DejaVuSansMono.ttf", 18, TTF_STYLE_NORMAL, 128, RGB(255,255,255), 3, RGB(0,0,0), true ); - - // Change the default method to use for outlining the font glyphs - TTFFont::OutlineMethod = TTFFont::OutlineFreetype; - - // Create the exact same font than before but using the new outlining method - TTFO->load( AppPath + "assets/fonts/DejaVuSansMono.ttf", 18, TTF_STYLE_NORMAL, 128, RGB(255,255,255), 3, RGB(0,0,0), true ); - - TTF2->load( AppPath + "assets/fonts/DejaVuSansMono.ttf", 48, TTF_STYLE_NORMAL, 128, RGB(255,255,255), 0, RGB(0,0,0), true ); - // Save the TTF font so then it can be loaded as a TextureFont //TTF->save( AppPath + "assets/temp/DejaVuSansMono.png", AppPath + "assets/temp/DejaVuSansMono.fnt" ); - // Load the texture font, previusly generated from a True Type Font - // First load the texture - Uint32 TexFid = TextureFactory::instance()->load( AppPath + "assets/fonts/ProggySquareSZ.png" ); - TexF->load( TexFid, AppPath + "assets/fonts/ProggySquareSZ.dat" ); - - // Load a monospaced texture font from image ( using the texture loader to set the color key ) - TextureLoader TexLoader( AppPath + "assets/fonts/conchars.png" ); - TexLoader.setColorKey( RGB(0,0,0) ); - TexLoader.load();; - TexF2->load( TexLoader.getId(), 32 ); - - // Set the font to the text cache - TTFCache.setFont( TTF ); - // Set a text to render - TTFCache.setText( "Lorem ipsum dolor sit amet, consectetur adipisicing elit." ); - - TTFOCache.setFont( TTFO ); - TTFOCache.setText( TTFCache.getText() ); - - TTF2Cache.setFont( TTF2 ); - TTF2Cache.setText( TTFCache.getText() ); - - // Set the font color - TTF2Cache.setColor( RGB(0,0,0) ); - - TexFCache.setFont( TexF ); - TexFCache.setText( TTFCache.getText() ); - TexFCache.setColor( RGB(0,0,0) ); - - TexF2Cache.setFont( TexF2 ); - TexF2Cache.setText( TTFCache.getText() ); - // Create a new text string String Txt( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." ); - // Make the text fit the screen width ( wrap the text ) - //TTF2->shrinkText( Txt, win->getWidth() - 96 ); - - // Create a new text cache to draw on screen - // The cached text will - TxtCache.create( TTF2, Txt, ColorA(0,0,0,255) ); - - // Set the text cache to be centered - TxtCache.setFlags( FONT_DRAW_CENTER ); - - // Set the font color to a substring of the text - // To be able to set the color of the font, create the font as white - // Create a gradient - size_t size = TxtCache.getText().size(); - - for ( size_t i = 0; i < size; i++ ) { - TxtCache.setColor( ColorA(255*i/size,0,0,255), i, i+1 ); - } - - fontTest.loadFromFile( AppPath + "assets/fonts/DejaVuSansMono.ttf" ); - fontTest.shrinkText( Txt, 24, false, 2, win->getWidth() - 96 ); - text.setFontTrueType( &fontTest ); + fontTest = FontTrueType::New( "DejaVuSansMono" ); + fontTest->loadFromFile( AppPath + "assets/fonts/DejaVuSansMono.ttf" ); + fontTest->shrinkText( Txt, 24, false, 2, win->getWidth() - 96 ); + text.setFont( fontTest ); text.setCharacterSize( 24 ); text.setFillColor( 0xFFFFFFFF ); text.setOutlineThickness( 2 ); diff --git a/src/test/eetest.cpp b/src/test/eetest.cpp index f5e5b77b5..94aaa45a3 100644 --- a/src/test/eetest.cpp +++ b/src/test/eetest.cpp @@ -172,20 +172,20 @@ void EETest::loadFonts() { TextureLoader * tl = eeNew( TextureLoader, ( MyPath + "fonts/conchars.png" ) ); tl->setColorKey( RGB(0,0,0) ); - mFontLoader.add( eeNew( TextureFontLoader, ( "conchars", tl, (unsigned int)32 ) ) ); - mFontLoader.add( eeNew( TextureFontLoader, ( "ProggySquareSZ", eeNew( TextureLoader, ( MyPath + "fonts/ProggySquareSZ.png" ) ), MyPath + "fonts/ProggySquareSZ.dat" ) ) ); - mFontLoader.add( eeNew( TTFFontLoader, ( "arial", MyPath + "fonts/arial.ttf", 12, TTF_STYLE_NORMAL, 256, RGB(255,255,255) ) ) ); - mFontLoader.add( eeNew( TTFFontLoader, ( "arialb", MyPath + "fonts/arial.ttf", 12, TTF_STYLE_NORMAL, 256, RGB(255,255,255), 1, RGB(0,0,0), true ) ) ); - mFontLoader.add( eeNew( TTFFontLoader, ( "DejaVuSansMono", MyPath + "fonts/DejaVuSansMono.ttf", 12, TTF_STYLE_NORMAL, 256, RGB(255,255,255), 1 ) ) ); + //mFontLoader.add( eeNew( TextureFontLoader, ( "conchars", tl, (unsigned int)32 ) ) ); + //mFontLoader.add( eeNew( TextureFontLoader, ( "ProggySquareSZ", eeNew( TextureLoader, ( MyPath + "fonts/ProggySquareSZ.png" ) ), MyPath + "fonts/ProggySquareSZ.dat" ) ) ); + mFontLoader.add( eeNew( FontTrueTypeLoader, ( "arial", MyPath + "fonts/arial.ttf" ) ) ); + mFontLoader.add( eeNew( FontTrueTypeLoader, ( "arialb", MyPath + "fonts/arial.ttf" ) ) ); + mFontLoader.add( eeNew( FontTrueTypeLoader, ( "DejaVuSansMono", MyPath + "fonts/DejaVuSansMono.ttf" ) ) ); mFontLoader.load( cb::Make1( this, &EETest::onFontLoaded ) ); } void EETest::onFontLoaded( ResourceLoader * ObjLoaded ) { - FF = FontManager::instance()->getByName( "conchars" ); - FF2 = FontManager::instance()->getByName( "ProggySquareSZ" ); - TTF = FontManager::instance()->getByName( "arial" ); - TTFB = FontManager::instance()->getByName( "arialb" ); + //FF = FontManager::instance()->getByName( "conchars" ); + //FF2 = FontManager::instance()->getByName( "ProggySquareSZ" ); + FF = TTF = FontManager::instance()->getByName( "arial" ); + FF2 = TTFB = FontManager::instance()->getByName( "arialb" ); DBSM = FontManager::instance()->getByName( "DejaVuSansMono" ); eePRINTL( "Fonts loading time: %4.3f ms.", mFTE.getElapsed().asMilliseconds() ); @@ -202,8 +202,8 @@ void EETest::onFontLoaded( ResourceLoader * ObjLoaded ) { mEEText.create( TTFB, "Entropia Engine++\nCTRL + Number to change Demo Screen\nRight click to see the PopUp Menu" ); mFBOText.create( TTFB, "This is a VBO\nInside of a FBO" ); - mFBOText.setColor( ColorA(255,255,0,255), mFBOText.getText().find( "VBO" ), mFBOText.getText().find( "VBO" ) + 2 ); - mFBOText.setColor( ColorA(255,255,0,255), mFBOText.getText().find( "FBO" ), mFBOText.getText().find( "FBO" ) + 2 ); + //mFBOText.setColor( ColorA(255,255,0,255), mFBOText.getText().find( "VBO" ), mFBOText.getText().find( "VBO" ) + 2 ); + //mFBOText.setColor( ColorA(255,255,0,255), mFBOText.getText().find( "FBO" ), mFBOText.getText().find( "FBO" ) + 2 ); mInfoText.create( FF, "", ColorA(255,255,255,150) ); }