New Font class integrated to the old Font class.

--HG--
branch : dev-font
This commit is contained in:
Martí­n Lucas Golini
2017-03-12 23:42:26 -03:00
parent 786b8d67b3
commit 43f9c600fc
33 changed files with 1166 additions and 3180 deletions

View File

@@ -20,10 +20,8 @@
#include <eepp/graphics/particle.hpp>
#include <eepp/graphics/particlesystem.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/texturefont.hpp>
#include <eepp/graphics/ttffont.hpp>
#include <eepp/graphics/texturefontloader.hpp>
#include <eepp/graphics/ttffontloader.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/fonttruetypeloader.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/primitives.hpp>
#include <eepp/graphics/scrollparallax.hpp>

View File

@@ -5,6 +5,7 @@
#include <eepp/window/inputtextbuffer.hpp>
#include <eepp/graphics/primitives.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/textcache.hpp>
#include <deque>
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 );

View File

@@ -4,41 +4,30 @@
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/fonthelper.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/graphics/textcache.hpp>
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<Float>& 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<Float>& 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<GlyphData> mGlyphs;
std::vector<TextureCoords> mTexCoords;
TextCache mTextCache;
Font( const Uint32& Type, const std::string& setName );
};

View File

@@ -3,62 +3,21 @@
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/texture.hpp>
#include <eepp/graphics/font.hpp>
#include <map>
#include <string>
#include <vector>
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<Float>& 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<Uint8> mPixelBuffer; ///< Pixel buffer holding a glyph's pixels before being written to the texture
};

View File

@@ -0,0 +1,106 @@
#ifndef EE_GRAPHICSCTTFFONTLOADER
#define EE_GRAPHICSCTTFFONTLOADER
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/system/objectloader.hpp>
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

View File

@@ -1,126 +0,0 @@
#ifndef EE_GRAPHICS_TEXT_HPP
#define EE_GRAPHICS_TEXT_HPP
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/fonthelper.hpp>
#include <string>
#include <vector>
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<Float>& 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<VertexCoords> mVertices;
std::vector<ColorA> mColors;
std::vector<VertexCoords> mOutlineVertices;
std::vector<ColorA> mOutlineColors;
std::vector<Float> mLinesWidth;
/** Force to cache the width of the current text */
void cacheWidth();
};
}}
#endif

View File

@@ -1,78 +1,92 @@
#ifndef EE_GRAPHICSCTEXTCACHE_H
#define EE_GRAPHICSCTEXTCACHE_H
#ifndef EE_GRAPHICS_TEXT_HPP
#define EE_GRAPHICS_TEXT_HPP
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/fonthelper.hpp>
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<Float>& getLinesWidth();
/** @return The text colors cached */
std::vector<ColorA>& 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<Float>& 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<Float> mLinesWidth;
std::vector<VertexCoords> mRenderCoords;
std::vector<VertexCoords> mVertices;
std::vector<ColorA> mColors;
void cacheVerts();
void updateCoords();
std::vector<VertexCoords> mOutlineVertices;
std::vector<ColorA> mOutlineColors;
std::vector<Float> mLinesWidth;
};
}}
#endif

View File

@@ -1,82 +0,0 @@
#ifndef EECTEXTUREFONT_H
#define EECTEXTUREFONT_H
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/graphics/font.hpp>
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

View File

@@ -1,111 +0,0 @@
#ifndef EE_GRAPHICSCTEXTUREFONTLOADER
#define EE_GRAPHICSCTEXTUREFONTLOADER
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/texturefont.hpp>
#include <eepp/system/objectloader.hpp>
#include <eepp/graphics/textureloader.hpp>
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

View File

@@ -1,121 +0,0 @@
#ifndef EE_GRAPHICSCTTFFONT_H
#define EE_GRAPHICSCTTFFONT_H
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/graphics/font.hpp>
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

View File

@@ -1,113 +0,0 @@
#ifndef EE_GRAPHICSCTTFFONTLOADER
#define EE_GRAPHICSCTTFFONTLOADER
#include <eepp/graphics/base.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/ttffont.hpp>
#include <eepp/system/objectloader.hpp>
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

View File

@@ -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 {

View File

@@ -58,7 +58,7 @@ class EE_API UIThemeManager : public ResourceManager<UITheme> {
const Sizei& getCursorSize() const;
TooltipStyleConfig getDefaultFontStyleConfig();
FontStyleConfig getDefaultFontStyleConfig();
protected:
Font * mFont;
UITheme * mThemeDefault;

View File

@@ -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

View File

@@ -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<Int32> ( (mCurHeight / mFontSize) - 1 );
return static_cast<Int32> ( ( mCurHeight / mFontSize ) - 1 );
}
void Console::privInputCallback( InputEvent * Event ) {

View File

@@ -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<Float>& 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<Float>& 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<Int32>( 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<Float>& 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<Int32>( 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<Int32>( 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;
}
}}

View File

@@ -1,5 +1,7 @@
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/system/iostream.hpp>
#include <eepp/system/pack.hpp>
#include <eepp/system/packmanager.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <ft2build.h>
@@ -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<FT_Library>(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<FT_Library>(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<FT_Library>(mLibrary), reinterpret_cast<const FT_Byte*>(data), static_cast<FT_Long>(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<FT_Library>(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<FT_Library>(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<FT_Library>(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<FT_Face>(mFace);
if (face && setCurrentSize(characterSize)) {
return static_cast<Float>(face->height) / static_cast<Float>(1 << 6);
} else {
return 0.f;
}
}
Float FontTrueType::getUnderlinePosition(unsigned int characterSize) const {
FT_Face face = static_cast<FT_Face>(mFace);
@@ -417,7 +438,7 @@ Glyph FontTrueType::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool
FT_Bitmap_Embolden(static_cast<FT_Library>(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<Float>& 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<Int32>( 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<Int32>( 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<Int32>( 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++;
}
}
}
}}

View File

@@ -0,0 +1,120 @@
#include <eepp/graphics/fonttruetypeloader.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/system/iostream.hpp>
#include <eepp/system/pack.hpp>
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;
}
}}

View File

@@ -1,618 +0,0 @@
#include <eepp/graphics/text.hpp>
#include <eepp/graphics/texture.hpp>
#include <eepp/graphics/renderer/gl.hpp>
#include <eepp/graphics/glextensions.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <cmath>
namespace EE { namespace Graphics {
// Add an underline or strikethrough line to the vertex array
static void addLine(std::vector<VertexCoords>& vertices, std::vector<ColorA>& 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<VertexCoords>& vertices, std::vector<ColorA>& 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<Float>(glyph.textureRect.Left) / (Float)textureSize.getWidth();
Float v1 = static_cast<Float>(glyph.textureRect.Top) / (Float)textureSize.getHeight();
Float u2 = static_cast<Float>(glyph.textureRect.Left + glyph.textureRect.Right) / (Float)textureSize.getWidth();
Float v2 = static_cast<Float>(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<Float>(mFont->getGlyph(L' ', mCharacterSize, bold).advance);
Float vspace = static_cast<Float>(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<Float>(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<Float>(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<char*>( &mOutlineColors[0] ) , allocC );
GLi->texCoordPointer( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast<char*>( &mOutlineVertices[0] ) , alloc );
GLi->vertexPointer ( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast<char*>( &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<char*>( &mColors[0] ) , allocC );
GLi->texCoordPointer( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast<char*>( &mVertices[0] ) , alloc );
GLi->vertexPointer ( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast<char*>( &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<Float>(mFont->getGlyph(L' ', mCharacterSize, bold).advance);
Float vspace = static_cast<Float>(mFont->getLineSpacing(mCharacterSize));
Float x = 0.f;
Float y = static_cast<Float>(mCharacterSize);
// Create one quad for each character
Float minX = static_cast<Float>(mCharacterSize);
Float minY = static_cast<Float>(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<Float>& 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;
}
}
}}

View File

@@ -1,88 +1,271 @@
#include <eepp/graphics/textcache.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/texture.hpp>
#include <eepp/graphics/renderer/gl.hpp>
#include <eepp/graphics/glextensions.hpp>
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <cmath>
namespace EE { namespace Graphics {
// Add an underline or strikethrough line to the vertex array
static void addLine(std::vector<VertexCoords>& vertices, std::vector<ColorA>& 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<VertexCoords>& vertices, std::vector<ColorA>& 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<Float>(glyph.textureRect.Left) / (Float)textureSize.getWidth();
Float v1 = static_cast<Float>(glyph.textureRect.Top) / (Float)textureSize.getHeight();
Float u2 = static_cast<Float>(glyph.textureRect.Left + glyph.textureRect.Right) / (Float)textureSize.getWidth();
Float v2 = static_cast<Float>(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<ColorA> 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<Float>(mFont->getGlyph(L' ', mRealCharacterSize, bold).advance);
Float vspace = static_cast<Float>(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<Float>(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<ColorA>& 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<Float>(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<Float>& 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<char*>( &mColors[0] ) , allocC );
GLi->texCoordPointer( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast<char*>( &mRenderCoords[0] ) , alloc );
GLi->vertexPointer ( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast<char*>( &mRenderCoords[0] ) + sizeof(Float) * 2 , alloc );
if ( 0 != mOutlineThickness ) {
GLi->colorPointer ( 4, GL_UNSIGNED_BYTE , 0 , reinterpret_cast<char*>( &mOutlineColors[0] ) , allocC );
GLi->texCoordPointer( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast<char*>( &mOutlineVertices[0] ) , alloc );
GLi->vertexPointer ( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast<char*>( &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<char*>( &mColors[0] ) , allocC );
GLi->texCoordPointer( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast<char*>( &mVertices[0] ) , alloc );
GLi->vertexPointer ( 2, GL_FP , sizeof(VertexCoords), reinterpret_cast<char*>( &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<Float>(mFont->getGlyph(L' ', mRealCharacterSize, bold).advance);
Float vspace = static_cast<Float>(mFont->getLineSpacing(mRealCharacterSize));
Float x = 0.f;
Float y = static_cast<Float>(mRealCharacterSize);
// Create one quad for each character
Float minX = static_cast<Float>(mRealCharacterSize);
Float minY = static_cast<Float>(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<Float>& 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;
}
}
}}

View File

@@ -1,217 +0,0 @@
#include <eepp/graphics/texturefont.hpp>
#include <eepp/graphics/texture.hpp>
#include <eepp/system/iostreamfile.hpp>
#include <eepp/system/iostreammemory.hpp>
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<Float>( mTexColumns ) );
mtY = ( 1 / static_cast<Float>( mTexRows ) );
mFWidth = (Float)( Tex->getWidth() / mTexColumns );
mFHeight = (Float)( Tex->getHeight() / mTexRows );
mHeight = mSize = mLineSkip = (unsigned int)mFHeight;
if ( Spacing == 0 )
mSpacing = static_cast<unsigned int>( 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<const char*> ( 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;
}
}}

View File

@@ -1,147 +0,0 @@
#include <eepp/graphics/texturefontloader.hpp>
#include <eepp/graphics/fontmanager.hpp>
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;
}
}}

View File

@@ -1,455 +0,0 @@
#include <eepp/graphics/ttffont.hpp>
#include <eepp/graphics/texture.hpp>
#include <eepp/system/iostreamfile.hpp>
#include <eepp/helper/haikuttf/haikuttf.hpp>
#include <eepp/window/engine.hpp>
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<Uint8*>(&TTFData[0]), TTFDataSize, rSize, 0, NumCharsToGen );
if ( OutlineSize && OutlineFreetype == OutlineMethod ) {
mFontOutline = hkFontManager::instance()->openFromMemory( reinterpret_cast<Uint8*>(&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<Uint32 *> ( TempOutGlyphSurface );
} else {
TexGlyph = reinterpret_cast<Uint32 *> ( 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<unsigned char *> ( &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<const char*>( &FntHdr ), sizeof(sFntHdr) );
// Write the glyphs
fs.write( reinterpret_cast<const char*> (&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;
}
}}

View File

@@ -1,129 +0,0 @@
#include <eepp/graphics/ttffontloader.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/texturefactory.hpp>
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;
}
}}

View File

@@ -5,6 +5,7 @@
#include <eepp/graphics/font.hpp>
#include <eepp/helper/pugixml/pugixml.hpp>
#include <eepp/graphics/fontmanager.hpp>
#include <eepp/graphics/textcache.hpp>
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;

View File

@@ -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 );

View File

@@ -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 );

View File

@@ -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() );

View File

@@ -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 )
);

View File

@@ -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();
}
}}

View File

@@ -272,6 +272,7 @@ void UITooltip::setStyleConfig(const TooltipStyleConfig & styleConfig) {
setFont( mStyleConfig.Font );
setFontColor( mStyleConfig.FontColor );
setFontShadowColor( mStyleConfig.FontShadowColor );
mTextCache->setCharacterSize( mStyleConfig.FontCharacterSize );
}
}}

View File

@@ -1,23 +1,12 @@
#include <eepp/ee.hpp>
#include <eepp/graphics/fonttruetype.hpp>
#include <eepp/graphics/text.hpp>
#include <eepp/graphics/textcache.hpp>
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 );

View File

@@ -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) );
}