Complete rewrite of sf::Font to make it more flexible (no more fixed charset and size)
FS#125 - Fix tab character not working in sf::String git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1309 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
parent
839c80556d
commit
3a34f81561
@ -232,6 +232,10 @@
|
||||
RelativePath="..\..\src\SFML\Graphics\FontStruct.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\include\SFML\Graphics\Glyph.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\SFML\Graphics\Image.cpp"
|
||||
>
|
||||
|
@ -36,26 +36,22 @@
|
||||
/// Create a new font from a file
|
||||
///
|
||||
/// \param filename : Path of the font file to load
|
||||
/// \param charSize : Size of characters in bitmap - the bigger, the higher quality
|
||||
/// \param charset : Characters set to generate (just pass NULL to get the default charset)
|
||||
///
|
||||
/// \return A new sfFont object, or NULL if it failed
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_API sfFont* sfFont_CreateFromFile(const char* filename, unsigned int charSize, const sfUint32* charset);
|
||||
CSFML_API sfFont* sfFont_CreateFromFile(const char* filename);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Create a new image font a file in memory
|
||||
///
|
||||
/// \param data : Pointer to the file data in memory
|
||||
/// \param sizeInBytes : Size of the data to load, in bytes
|
||||
/// \param charSize : Size of characters in bitmap - the bigger, the higher quality
|
||||
/// \param charset : Characters set to generate (just pass NULL to get the default charset)
|
||||
///
|
||||
/// \return A new sfFont object, or NULL if it failed
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_API sfFont* sfFont_CreateFromMemory(const char* data, size_t sizeInBytes, unsigned int charSize, const sfUint32* charset);
|
||||
CSFML_API sfFont* sfFont_CreateFromMemory(const char* data, size_t sizeInBytes);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Destroy an existing font
|
||||
@ -66,15 +62,52 @@ CSFML_API sfFont* sfFont_CreateFromMemory(const char* data, size_t sizeInBytes,
|
||||
CSFML_API void sfFont_Destroy(sfFont* font);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the base size of characters in a font;
|
||||
/// All glyphs dimensions are based on this value
|
||||
/// Get a glyph in a font
|
||||
///
|
||||
/// \param font : Font object
|
||||
/// \param font : Source font
|
||||
/// \param codePoint : Unicode code point of the character to get
|
||||
/// \param characterSize : Character size, in pixels
|
||||
///
|
||||
/// \return Base size of characters
|
||||
/// \return The corresponding glyph
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_API unsigned int sfFont_GetCharacterSize(const sfFont* font);
|
||||
CSFML_API sfGlyph sfFont_GetGlyph(sfFont* font, sfUint32 codePoint, unsigned int characterSize);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the kerning value corresponding to a given pair of characters in a font
|
||||
///
|
||||
/// \param font : Source font
|
||||
/// \param first : Unicode code point of the first character
|
||||
/// \param second : Unicode code point of the second character
|
||||
/// \param characterSize : Character size, in pixels
|
||||
///
|
||||
/// \return Kerning offset, in pixels
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_API int sfFont_GetKerning(sfFont* font, sfUint32 first, sfUint32 second, unsigned int characterSize);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the line spacing value
|
||||
///
|
||||
/// \param font : Source font
|
||||
/// \param codePoint : Unicode code point of the character to get
|
||||
/// \param characterSize : Character size, in pixels
|
||||
///
|
||||
/// \return Line spacing, in pixels
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_API int sfFont_GetLineSpacing(sfFont* font, unsigned int characterSize);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the image containing the glyphs of a given size in a font
|
||||
///
|
||||
/// \param font : Source font
|
||||
/// \param characterSize : Character size, in pixels
|
||||
///
|
||||
/// \return Read-only pointer to the image
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_API const sfImage* sfFont_GetImage(sfFont* font, unsigned int characterSize);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the built-in default font (Arial)
|
||||
|
@ -336,7 +336,7 @@ CSFML_API void sfText_SetFont(sfText* text, const sfFont* font);
|
||||
/// \param size : New size, in pixels
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_API void sfText_SetSize(sfText* text, float size);
|
||||
CSFML_API void sfText_SetCharacterSize(sfText* text, unsigned int size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Set the style of a text
|
||||
@ -385,7 +385,7 @@ CSFML_API const sfFont* sfText_GetFont(const sfText* text);
|
||||
/// \return Size of the characters
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
CSFML_API float sfText_GetSize(const sfText* text);
|
||||
CSFML_API unsigned int sfText_GetCharacterSize(const sfText* text);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the style of a text
|
||||
|
@ -33,17 +33,10 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Create a new font from a file
|
||||
////////////////////////////////////////////////////////////
|
||||
sfFont* sfFont_CreateFromFile(const char* filename, unsigned int charSize, const sfUint32* charset)
|
||||
sfFont* sfFont_CreateFromFile(const char* filename)
|
||||
{
|
||||
sfFont* font = new sfFont;
|
||||
|
||||
bool success = false;
|
||||
if (charset)
|
||||
success = font->This.LoadFromFile(filename, charSize, charset);
|
||||
else
|
||||
success = font->This.LoadFromFile(filename, charSize);
|
||||
|
||||
if (!success)
|
||||
if (!font->This.LoadFromFile(filename))
|
||||
{
|
||||
delete font;
|
||||
font = NULL;
|
||||
@ -56,17 +49,10 @@ sfFont* sfFont_CreateFromFile(const char* filename, unsigned int charSize, const
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Create a new font from a file in memory
|
||||
////////////////////////////////////////////////////////////
|
||||
sfFont* sfFont_CreateFromMemory(const char* data, size_t sizeInBytes, unsigned int charSize, const sfUint32* charset)
|
||||
sfFont* sfFont_CreateFromMemory(const char* data, size_t sizeInBytes)
|
||||
{
|
||||
sfFont* font = new sfFont;
|
||||
|
||||
bool success = false;
|
||||
if (charset)
|
||||
success = font->This.LoadFromMemory(data, sizeInBytes, charSize, charset);
|
||||
else
|
||||
success = font->This.LoadFromMemory(data, sizeInBytes, charSize);
|
||||
|
||||
if (!success)
|
||||
if (!font->This.LoadFromMemory(data, sizeInBytes))
|
||||
{
|
||||
delete font;
|
||||
font = NULL;
|
||||
@ -86,12 +72,57 @@ void sfFont_Destroy(sfFont* font)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the base size of characters in a font;
|
||||
/// All glyphs dimensions are based on this value
|
||||
/// Get a glyph in a font
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int sfFont_GetCharacterSize(const sfFont* font)
|
||||
sfGlyph sfFont_GetGlyph(sfFont* font, sfUint32 codePoint, unsigned int characterSize)
|
||||
{
|
||||
CSFML_CALL_RETURN(font, GetCharacterSize(), 0);
|
||||
sfGlyph glyph = {0, {0, 0, 0, 0}, {0, 0, 0, 0}};
|
||||
CSFML_CHECK_RETURN(font, glyph);
|
||||
|
||||
sf::Glyph SFMLGlyph = font->This.GetGlyph(codePoint, characterSize);
|
||||
|
||||
glyph.Advance = SFMLGlyph.Advance;
|
||||
glyph.Rectangle.Left = SFMLGlyph.Rectangle.Left;
|
||||
glyph.Rectangle.Top = SFMLGlyph.Rectangle.Top;
|
||||
glyph.Rectangle.Right = SFMLGlyph.Rectangle.Right;
|
||||
glyph.Rectangle.Bottom = SFMLGlyph.Rectangle.Bottom;
|
||||
glyph.TexCoords.Left = SFMLGlyph.TexCoords.Left;
|
||||
glyph.TexCoords.Top = SFMLGlyph.TexCoords.Top;
|
||||
glyph.TexCoords.Right = SFMLGlyph.TexCoords.Right;
|
||||
glyph.TexCoords.Bottom = SFMLGlyph.TexCoords.Bottom;
|
||||
|
||||
return glyph;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the kerning value corresponding to a given pair of characters in a font
|
||||
////////////////////////////////////////////////////////////
|
||||
int sfFont_GetKerning(sfFont* font, sfUint32 first, sfUint32 second, unsigned int characterSize)
|
||||
{
|
||||
CSFML_CALL_RETURN(font, GetKerning(first, second, characterSize), 0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the line spacing value
|
||||
////////////////////////////////////////////////////////////
|
||||
int sfFont_GetLineSpacing(sfFont* font, unsigned int characterSize)
|
||||
{
|
||||
CSFML_CALL_RETURN(font, GetLineSpacing(characterSize), 0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the image containing the glyphs of a given size in a font
|
||||
////////////////////////////////////////////////////////////
|
||||
const sfImage* sfFont_GetImage(sfFont* font, unsigned int characterSize)
|
||||
{
|
||||
CSFML_CHECK_RETURN(font, NULL);
|
||||
|
||||
*font->Images[characterSize].This = font->This.GetImage(characterSize);
|
||||
|
||||
return &font->Images[characterSize];
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,6 +29,8 @@
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Font.hpp>
|
||||
#include <SFML/Graphics/ImageStruct.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -37,6 +39,7 @@
|
||||
struct sfFont
|
||||
{
|
||||
sf::Font This;
|
||||
std::map<unsigned int, sfImage> Images;
|
||||
};
|
||||
|
||||
|
||||
|
@ -42,9 +42,9 @@ struct sfImage
|
||||
OwnInstance = true;
|
||||
}
|
||||
|
||||
sfImage(sf::Image* Image)
|
||||
sfImage(sf::Image* image)
|
||||
{
|
||||
This = Image;
|
||||
This = image;
|
||||
OwnInstance = false;
|
||||
}
|
||||
|
||||
|
@ -320,9 +320,9 @@ void sfText_SetFont(sfText* text, const sfFont* font)
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Set the size of a string
|
||||
////////////////////////////////////////////////////////////
|
||||
void sfText_SetSize(sfText* text, float size)
|
||||
void sfText_SetCharacterSize(sfText* text, unsigned int size)
|
||||
{
|
||||
CSFML_CALL(text, SetSize(size))
|
||||
CSFML_CALL(text, SetCharacterSize(size))
|
||||
}
|
||||
|
||||
|
||||
@ -373,9 +373,9 @@ const sfFont* sfText_GetFont(const sfText* text)
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the size of the characters of a text
|
||||
////////////////////////////////////////////////////////////
|
||||
float sfText_GetSize(const sfText* text)
|
||||
unsigned int sfText_GetCharacterSize(const sfText* text)
|
||||
{
|
||||
CSFML_CALL_RETURN(text, GetSize(), 0.f)
|
||||
CSFML_CALL_RETURN(text, GetCharacterSize(), 0.f)
|
||||
}
|
||||
|
||||
|
||||
|
@ -127,7 +127,10 @@ EXPORTS
|
||||
sfFont_CreateFromFile
|
||||
sfFont_CreateFromMemory
|
||||
sfFont_Destroy
|
||||
sfFont_GetCharacterSize
|
||||
sfFont_GetGlyph
|
||||
sfFont_GetKerning
|
||||
sfFont_GetLineSpacing
|
||||
sfFont_GetImage
|
||||
sfFont_GetDefaultFont
|
||||
sfText_Create
|
||||
sfText_Destroy
|
||||
@ -158,12 +161,12 @@ EXPORTS
|
||||
sfText_SetString
|
||||
sfText_SetUnicodeString
|
||||
sfText_SetFont
|
||||
sfText_SetSize
|
||||
sfText_SetCharacterSize
|
||||
sfText_SetStyle
|
||||
sfText_GetUnicodeString
|
||||
sfText_GetString
|
||||
sfText_GetFont
|
||||
sfText_GetSize
|
||||
sfText_GetCharacterSize
|
||||
sfText_GetStyle
|
||||
sfText_GetCharacterPos
|
||||
sfText_GetRect
|
||||
|
@ -127,7 +127,10 @@ EXPORTS
|
||||
sfFont_CreateFromFile
|
||||
sfFont_CreateFromMemory
|
||||
sfFont_Destroy
|
||||
sfFont_GetCharacterSize
|
||||
sfFont_GetGlyph
|
||||
sfFont_GetKerning
|
||||
sfFont_GetLineSpacing
|
||||
sfFont_GetImage
|
||||
sfFont_GetDefaultFont
|
||||
sfText_Create
|
||||
sfText_Destroy
|
||||
@ -158,12 +161,12 @@ EXPORTS
|
||||
sfText_SetString
|
||||
sfText_SetUnicodeString
|
||||
sfText_SetFont
|
||||
sfText_SetSize
|
||||
sfText_SetCharacterSize
|
||||
sfText_SetStyle
|
||||
sfText_GetUnicodeString
|
||||
sfText_GetString
|
||||
sfText_GetFont
|
||||
sfText_GetSize
|
||||
sfText_GetCharacterSize
|
||||
sfText_GetStyle
|
||||
sfText_GetCharacterPos
|
||||
sfText_GetRect
|
||||
|
@ -140,8 +140,6 @@
|
||||
<Unit filename="..\..\src\SFML\Graphics\Color.cpp" />
|
||||
<Unit filename="..\..\src\SFML\Graphics\Drawable.cpp" />
|
||||
<Unit filename="..\..\src\SFML\Graphics\Font.cpp" />
|
||||
<Unit filename="..\..\src\SFML\Graphics\FontLoader.cpp" />
|
||||
<Unit filename="..\..\src\SFML\Graphics\FontLoader.hpp" />
|
||||
<Unit filename="..\..\src\SFML\Graphics\GLCheck.cpp" />
|
||||
<Unit filename="..\..\src\SFML\Graphics\GLCheck.hpp" />
|
||||
<Unit filename="..\..\src\SFML\Graphics\GLEW\glew.c">
|
||||
|
@ -3434,14 +3434,6 @@
|
||||
RelativePath="..\..\include\SFML\Graphics\Font.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\SFML\Graphics\FontLoader.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\SFML\Graphics\FontLoader.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\SFML\Graphics\GLCheck.cpp"
|
||||
>
|
||||
|
@ -14,6 +14,9 @@ EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sfml-main", "sfml-main.vcproj", "{2BD26A09-E1B6-42E2-A0D0-63987B76BB97}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sfml-network", "sfml-network.vcproj", "{823DDC98-42D5-4A38-88CF-9DC06C788AE4}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{C061A27D-7CA0-4179-9869-672FA04A86A8} = {C061A27D-7CA0-4179-9869-672FA04A86A8}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sfml-system", "sfml-system.vcproj", "{C061A27D-7CA0-4179-9869-672FA04A86A8}"
|
||||
EndProject
|
||||
|
@ -3433,14 +3433,6 @@
|
||||
RelativePath="..\..\include\SFML\Graphics\Font.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\SFML\Graphics\FontLoader.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\SFML\Graphics\FontLoader.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\SFML\Graphics\GLCheck.cpp"
|
||||
>
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -93,7 +93,7 @@ namespace sample_shader
|
||||
Sprite entity = new Sprite(new Image("datas/shader/sprite.png"));
|
||||
|
||||
// Load the text font
|
||||
Font font = new Font("datas/shader/arial.ttf", 20);
|
||||
Font font = new Font("datas/shader/arial.ttf");
|
||||
|
||||
// Load the image needed for the wave effect
|
||||
Image waveImage = new Image("datas/shader/wave.jpg");
|
||||
@ -135,7 +135,7 @@ namespace sample_shader
|
||||
Text infoText = new Text();
|
||||
infoText.Font = font;
|
||||
infoText.Size = 20;
|
||||
infoText.Position = new Vector2(5.0F, 510.0F);
|
||||
infoText.Position = new Vector2(5.0F, 500.0F);
|
||||
infoText.Color = new Color(250, 100, 30);
|
||||
infoText.DisplayedString = "Move your mouse to change the shaders' parameters\n" +
|
||||
"Press numpad 1 to change the background shader\n" +
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.IO;
|
||||
@ -7,6 +8,24 @@ namespace SFML
|
||||
{
|
||||
namespace Graphics
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// <summary>
|
||||
/// Structure describing a glyph (a visual character)
|
||||
/// </summary>
|
||||
////////////////////////////////////////////////////////////
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Glyph
|
||||
{
|
||||
/// <summary>Offset to move horizontically to the next character</summary>
|
||||
public int Advance;
|
||||
|
||||
/// <summary>Bounding rectangle of the glyph, in coordinates relative to the baseline</summary>
|
||||
public IntRect Rectangle;
|
||||
|
||||
/// <summary>Texture coordinates of the glyph inside the font's image</summary>
|
||||
public FloatRect TexCoords;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// <summary>
|
||||
/// Font is the low-level class for loading and
|
||||
@ -24,47 +43,8 @@ namespace SFML
|
||||
/// <exception cref="LoadingFailedException" />
|
||||
////////////////////////////////////////////////////////////
|
||||
public Font(string filename) :
|
||||
this(filename, 30)
|
||||
base(sfFont_CreateFromFile(filename))
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// <summary>
|
||||
/// Construct the font from a file, using custom size
|
||||
/// </summary>
|
||||
/// <param name="filename">Font file to load</param>
|
||||
/// <param name="charSize">Character size</param>
|
||||
/// <exception cref="LoadingFailedException" />
|
||||
////////////////////////////////////////////////////////////
|
||||
public Font(string filename, uint charSize) :
|
||||
this(filename, charSize, "")
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// <summary>
|
||||
/// Construct the font from a file, using custom size and characters set
|
||||
/// </summary>
|
||||
/// <param name="filename">Font file to load</param>
|
||||
/// <param name="charSize">Character size</param>
|
||||
/// <param name="charset">Set of characters to generate</param>
|
||||
/// <exception cref="LoadingFailedException" />
|
||||
////////////////////////////////////////////////////////////
|
||||
public Font(string filename, uint charSize, string charset) :
|
||||
base(IntPtr.Zero)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
IntPtr ptr;
|
||||
int size;
|
||||
if (Int32.TryParse(charset, out size))
|
||||
ptr = new IntPtr(&size);
|
||||
else
|
||||
ptr = IntPtr.Zero;
|
||||
|
||||
SetThis(sfFont_CreateFromFile(filename, charSize, ptr));
|
||||
}
|
||||
|
||||
if (This == IntPtr.Zero)
|
||||
throw new LoadingFailedException("font", filename);
|
||||
}
|
||||
@ -77,64 +57,73 @@ namespace SFML
|
||||
/// <exception cref="LoadingFailedException" />
|
||||
////////////////////////////////////////////////////////////
|
||||
public Font(Stream stream) :
|
||||
this(stream, 30)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// <summary>
|
||||
/// Construct the font from a file in a stream, using custom size
|
||||
/// </summary>
|
||||
/// <param name="stream">Stream containing the file contents</param>
|
||||
/// <param name="charSize">Character size</param>
|
||||
/// <exception cref="LoadingFailedException" />
|
||||
////////////////////////////////////////////////////////////
|
||||
public Font(Stream stream, uint charSize) :
|
||||
this(stream, charSize, "")
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// <summary>
|
||||
/// Construct the font from a file in a stream
|
||||
/// </summary>
|
||||
/// <param name="stream">Stream containing the file contents</param>
|
||||
/// <param name="charSize">Character size</param>
|
||||
/// <param name="charset">Set of characters to generate</param>
|
||||
/// <exception cref="LoadingFailedException" />
|
||||
////////////////////////////////////////////////////////////
|
||||
public Font(Stream stream, uint charSize, string charset) :
|
||||
base(IntPtr.Zero)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
IntPtr ptr;
|
||||
int size;
|
||||
if (Int32.TryParse(charset, out size))
|
||||
ptr = new IntPtr(&size);
|
||||
else
|
||||
ptr = IntPtr.Zero;
|
||||
|
||||
stream.Position = 0;
|
||||
byte[] StreamData = new byte[stream.Length];
|
||||
uint Read = (uint)stream.Read(StreamData, 0, StreamData.Length);
|
||||
fixed (byte* dataPtr = StreamData)
|
||||
{
|
||||
SetThis(sfFont_CreateFromMemory((char*)dataPtr, Read, charSize, ptr));
|
||||
SetThis(sfFont_CreateFromMemory((char*)dataPtr, Read));
|
||||
}
|
||||
}
|
||||
|
||||
if (This == IntPtr.Zero)
|
||||
throw new LoadingFailedException("font");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// <summary>
|
||||
/// Base character size
|
||||
/// Get a glyph in the font
|
||||
/// </summary>
|
||||
/// <param name="codePoint">Unicode code point of the character to get</param>
|
||||
/// <param name="characterSize">Character size</param>
|
||||
/// <returns>The glyph corresponding to the character</returns>
|
||||
////////////////////////////////////////////////////////////
|
||||
public uint CharacterSize
|
||||
public Glyph GetGlyph(uint codePoint, uint characterSize)
|
||||
{
|
||||
get { return sfFont_GetCharacterSize(This); }
|
||||
return sfFont_GetGlyph(This, codePoint, characterSize);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// <summary>
|
||||
/// Get the kerning offset between two glyphs
|
||||
/// </summary>
|
||||
/// <param name="first">Unicode code point of the first character</param>
|
||||
/// <param name="second">Unicode code point of the second character</param>
|
||||
/// <param name="characterSize">Character size</param>
|
||||
/// <returns>Kerning offset, in pixels</returns>
|
||||
////////////////////////////////////////////////////////////
|
||||
public int GetKerning(uint first, uint second, uint characterSize)
|
||||
{
|
||||
return sfFont_GetKerning(This, first, second, characterSize);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// <summary>
|
||||
/// Get spacing between two consecutive lines
|
||||
/// </summary>
|
||||
/// <param name="characterSize">Character size</param>
|
||||
/// <returns>Line spacing, in pixels</returns>
|
||||
////////////////////////////////////////////////////////////
|
||||
public int GetLineSpacing(uint characterSize)
|
||||
{
|
||||
return sfFont_GetLineSpacing(This, characterSize);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// <summary>
|
||||
/// Get the image containing the glyphs of a given size
|
||||
/// </summary>
|
||||
/// <param name="characterSize">Character size</param>
|
||||
/// <returns>Image storing the glyphs for the given size</returns>
|
||||
////////////////////////////////////////////////////////////
|
||||
public Image GetImage(uint characterSize)
|
||||
{
|
||||
myImages[characterSize] = new Image(sfFont_GetImage(This, characterSize));
|
||||
return myImages[characterSize];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -168,6 +157,12 @@ namespace SFML
|
||||
|
||||
sfFont_Destroy(This);
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
foreach (Image image in myImages.Values)
|
||||
image.Dispose();
|
||||
}
|
||||
|
||||
if (!disposing)
|
||||
Context.Global.SetActive(false);
|
||||
}
|
||||
@ -184,20 +179,30 @@ namespace SFML
|
||||
{
|
||||
}
|
||||
|
||||
private Dictionary<uint, Image> myImages = new Dictionary<uint, Image>();
|
||||
private static Font ourDefaultFont = null;
|
||||
|
||||
#region Imports
|
||||
[DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity]
|
||||
static extern IntPtr sfFont_CreateFromFile(string Filename, uint CharSize, IntPtr Charset);
|
||||
static extern IntPtr sfFont_CreateFromFile(string Filename);
|
||||
|
||||
[DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity]
|
||||
unsafe static extern IntPtr sfFont_CreateFromMemory(char* Data, uint SizeInBytes, uint CharSize, IntPtr Charset);
|
||||
unsafe static extern IntPtr sfFont_CreateFromMemory(char* Data, uint SizeInBytes);
|
||||
|
||||
[DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity]
|
||||
static extern void sfFont_Destroy(IntPtr This);
|
||||
|
||||
[DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity]
|
||||
static extern uint sfFont_GetCharacterSize(IntPtr This);
|
||||
static extern Glyph sfFont_GetGlyph(IntPtr This, uint codePoint, uint characterSize);
|
||||
|
||||
[DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity]
|
||||
static extern int sfFont_GetKerning(IntPtr This, uint first, uint second, uint characterSize);
|
||||
|
||||
[DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity]
|
||||
static extern int sfFont_GetLineSpacing(IntPtr This, uint characterSize);
|
||||
|
||||
[DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity]
|
||||
static extern IntPtr sfFont_GetImage(IntPtr This, uint characterSize);
|
||||
|
||||
[DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity]
|
||||
static extern IntPtr sfFont_GetDefaultFont();
|
||||
|
@ -211,10 +211,10 @@ namespace SFML
|
||||
/// Base size of characters
|
||||
/// </summary>
|
||||
////////////////////////////////////////////////////////////
|
||||
public float Size
|
||||
public uint Size
|
||||
{
|
||||
get {return sfText_GetSize(This);}
|
||||
set {sfText_SetSize(This, value);}
|
||||
get {return sfText_GetCharacterSize(This);}
|
||||
set {sfText_SetCharacterSize(This, value);}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -376,7 +376,7 @@ namespace SFML
|
||||
static extern void sfText_SetFont(IntPtr This, IntPtr Font);
|
||||
|
||||
[DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity]
|
||||
static extern void sfText_SetSize(IntPtr This, float Size);
|
||||
static extern void sfText_SetCharacterSize(IntPtr This, uint Size);
|
||||
|
||||
[DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity]
|
||||
static extern void sfText_SetStyle(IntPtr This, Styles Style);
|
||||
@ -385,7 +385,7 @@ namespace SFML
|
||||
static extern string sfText_GetString(IntPtr This);
|
||||
|
||||
[DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity]
|
||||
static extern float sfText_GetSize(IntPtr This);
|
||||
static extern uint sfText_GetCharacterSize(IntPtr This);
|
||||
|
||||
[DllImport("csfml-graphics"), SuppressUnmanagedCodeSecurity]
|
||||
static extern Styles sfText_GetStyle(IntPtr This);
|
||||
|
@ -36,109 +36,328 @@
|
||||
#include <SFML/Graphics/Rect.hpp>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
class FontLoader;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Font is the low-level class for loading and
|
||||
/// manipulating character fonts. This class is meant to
|
||||
/// be used by sf::Text
|
||||
/// \brief Class for loading and manipulating character fonts
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
class SFML_API Font : public Resource<Font>
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
/// \brief Default constructor
|
||||
///
|
||||
/// This constructor defines an empty font
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Font();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Load the font from a file
|
||||
/// \brief Copy constructor
|
||||
///
|
||||
/// \param filename : Font file to load
|
||||
/// \param charSize : Size of characters in bitmap - the bigger, the higher quality
|
||||
/// \param charset : Characters set to generate (by default, contains the ISO-8859-1 printable characters)
|
||||
///
|
||||
/// \return True if loading was successful
|
||||
/// \param copy Instance to copy
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool LoadFromFile(const std::string& filename, unsigned int charSize = 30, String charset = ourDefaultCharset);
|
||||
Font(const Font& copy);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Load the font from a file in memory
|
||||
/// \brief Destructor
|
||||
///
|
||||
/// \param data : Pointer to the data to load
|
||||
/// \param sizeInBytes : Size of the data, in bytes
|
||||
/// \param charSize : Size of characters in bitmap - the bigger, the higher quality
|
||||
/// \param charset : Characters set to generate (by default, contains the ISO-8859-1 printable characters)
|
||||
///
|
||||
/// \return True if loading was successful
|
||||
/// Cleans up all the internal resources used by the font
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool LoadFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize = 30, String charset = ourDefaultCharset);
|
||||
~Font();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the base size of characters in the font;
|
||||
/// All glyphs dimensions are based on this value
|
||||
/// \brief Load the font from a file
|
||||
///
|
||||
/// \return Base size of characters
|
||||
/// The supported font formats are: TrueType, Type 1, CFF,
|
||||
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
|
||||
/// Note that this function know nothing about the standard
|
||||
/// fonts installed on the user's system, thus you can't
|
||||
/// load them directly.
|
||||
///
|
||||
/// \param filename Path of the font file to load
|
||||
///
|
||||
/// \return True if loading succeeded, false if it failed
|
||||
///
|
||||
/// \see LoadFromMemory
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int GetCharacterSize() const;
|
||||
bool LoadFromFile(const std::string& filename);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the description of a glyph (character)
|
||||
/// given by its unicode value
|
||||
/// \brief Load the font from a file
|
||||
///
|
||||
/// \param codePoint : Unicode value of the character to get
|
||||
/// The supported font formats are: TrueType, Type 1, CFF,
|
||||
/// OpenType, SFNT, X11 PCF, Windows FNT, BDF, PFR and Type 42.
|
||||
/// Note that this function know nothing about the standard
|
||||
/// fonts installed on the user's system, thus you can't
|
||||
/// load them directly.
|
||||
///
|
||||
/// \return Glyph's visual settings, or an invalid glyph if character not found
|
||||
/// \param data Pointer to the file data in memory
|
||||
/// \param sizeInBytes Size of the data to load, in bytes
|
||||
///
|
||||
/// \return True if loading succeeded, false if it failed
|
||||
///
|
||||
/// \see LoadFromFile
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const Glyph& GetGlyph(Uint32 codePoint) const;
|
||||
bool LoadFromMemory(const char* data, std::size_t sizeInBytes);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the image containing the rendered characters (glyphs)
|
||||
/// \brief Retrieve a glyph of the font
|
||||
///
|
||||
/// \return Image containing glyphs
|
||||
/// \param codePoint Unicode code point of the character to get
|
||||
/// \param characterSize Reference character size
|
||||
///
|
||||
/// \return The glyph corresponding to \a codePoint and \a characterSize
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const Image& GetImage() const;
|
||||
const Glyph& GetGlyph(Uint32 codePoint, unsigned int characterSize) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the SFML default built-in font (Arial)
|
||||
/// \brief Get the kerning offset of two glyphs
|
||||
///
|
||||
/// \return Instance of the default font
|
||||
/// The kerning is an extra offset (negative) to apply between two
|
||||
/// glyphs when rendering them, to make the pair look more "natural".
|
||||
/// For example, the pair "AV" have a special kerning to make them
|
||||
/// closer than other characters. Most of the glyphs pairs have a
|
||||
/// kerning offset of zero, though.
|
||||
///
|
||||
/// \param first Unicode code point of the first character
|
||||
/// \param second Unicode code point of the second character
|
||||
/// \param characterSize Reference character size
|
||||
///
|
||||
/// \return Kerning value for \a first and \a second, in pixels
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
int GetKerning(Uint32 first, Uint32 second, unsigned int characterSize) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the line spacing
|
||||
///
|
||||
/// Line spacing is the vertical offset to apply between two
|
||||
/// consecutive lines of text.
|
||||
///
|
||||
/// \param characterSize Reference character size
|
||||
///
|
||||
/// \return Line spacing, in pixels
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
int GetLineSpacing(unsigned int characterSize) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Retrieve the image containing the loaded glyphs of a certain size
|
||||
///
|
||||
/// The contents of the returned image changes as more glyphs
|
||||
/// are requested, thus it is not very relevant. It is mainly
|
||||
/// used internally by sf::Text.
|
||||
///
|
||||
/// \param characterSize Reference character size
|
||||
///
|
||||
/// \return Image containing the glyphs of the requested size
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
const Image& GetImage(unsigned int characterSize) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Overload of assignment operator
|
||||
///
|
||||
/// \param right Instance to assign
|
||||
///
|
||||
/// \return Reference to self
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
Font& operator =(const Font& right);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Return the default built-in font
|
||||
///
|
||||
/// This font is provided for convenience, it is used by
|
||||
/// sf::Text instances by default. It is provided so that
|
||||
/// users don't have to provide and load a font file in order
|
||||
/// to display text on screen.
|
||||
/// The font used is Arial.
|
||||
///
|
||||
/// \return Reference to the built-in default font
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static const Font& GetDefaultFont();
|
||||
|
||||
private :
|
||||
|
||||
friend class priv::FontLoader;
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Structure storing a glyph together with its
|
||||
/// rectangle in the texture
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
struct GlyphInfo
|
||||
{
|
||||
Glyph GlyphDesc;
|
||||
IntRect TextureRect;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Static member data
|
||||
/// \brief Structure defining a row of glyphs
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static Uint32 ourDefaultCharset[]; ///< The default charset (all printable ISO-8859-1 characters)
|
||||
struct Row
|
||||
{
|
||||
Row(unsigned int top, unsigned int height) : Width(0), Top(top), Height(height) {}
|
||||
|
||||
unsigned int Width; ///< Current width of the row
|
||||
unsigned int Top; ///< Y position of the row into the texture
|
||||
unsigned int Height; ///< Height of the row
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef std::map<Uint32, GlyphInfo> GlyphTable; ///< Table mapping a codepoint to its glyph
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Structure defining a page if glyphs
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
struct Page
|
||||
{
|
||||
Page();
|
||||
|
||||
GlyphTable Glyphs; ///< Table mapping code points to their corresponding glyph
|
||||
Image Texture; ///< Image containing the pixels of the glyphs
|
||||
unsigned int NextRow; ///< Y position of the next new row in the image
|
||||
std::vector<Row> Rows; ///< List containing the position of all the existing rows
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Free all the internal resources
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void Cleanup();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Load a new glyph and store it in the cache
|
||||
///
|
||||
/// \param codePoint Unicode code point of the character to load
|
||||
/// \param characterSize Reference character size
|
||||
///
|
||||
/// \return The glyph corresponding to \a codePoint and \a characterSize
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
GlyphInfo LoadGlyph(Uint32 codePoint, unsigned int characterSize) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Find a suitable rectangle within the texture for a glyph
|
||||
///
|
||||
/// \param page Page of glyphs to search in
|
||||
/// \param width Width of the rectangle
|
||||
/// \param height Height of the rectangle
|
||||
///
|
||||
/// \return Found rectangle within the texture
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
IntRect FindGlyphRect(Page& page, unsigned int width, unsigned int height) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Make sure that the given size is the current one
|
||||
///
|
||||
/// \param characterSize Reference character size
|
||||
///
|
||||
/// \return True on success, false if any error happened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SetCurrentSize(unsigned int characterSize) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
////////////////////////////////////////////////////////////
|
||||
typedef std::map<unsigned int, Page> PageTable; ///< Table mapping a character size to its page (image)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
Image myTexture; ///< Texture holding the bitmap font
|
||||
unsigned int myCharSize; ///< Size of characters in the bitmap font
|
||||
std::map<Uint32, Glyph> myGlyphs; ///< Rendering settings of each character (glyph)
|
||||
void* myLibrary; ///< Pointer to the internal library interface (it is typeless to avoid exposing implementation details)
|
||||
void* myFace; ///< Pointer to the internal font face (it is typeless to avoid exposing implementation details)
|
||||
int* myRefCount; ///< Reference counter used by implicit sharing
|
||||
mutable PageTable myPages; ///< Table containing the glyphs pages by character size
|
||||
mutable std::vector<Uint8> myPixelBuffer; ///< Pixel buffer holding a glyph's pixels before being written to the texture
|
||||
mutable unsigned int myCurrentSize; ///< Current character size in use
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_FONT_HPP
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \class sf::Font
|
||||
///
|
||||
/// Fonts can be loaded from a file or from memory, from
|
||||
/// the most common types of fonts. See the LoadFromFile()
|
||||
/// function for the complete list of supported formats.
|
||||
///
|
||||
/// Once it is loaded, a sf::Font instance provides three
|
||||
/// types of informations about the font:
|
||||
/// \li Global metrics, such as the line spacing
|
||||
/// \li Per-glyph metrics, such as bounding box or kerning
|
||||
/// \li Pixel representation of glyphs
|
||||
///
|
||||
/// Fonts alone are not very useful: they hold the font data
|
||||
/// but cannot make anything useful of it. To do so you need to
|
||||
/// use the sf::Text class, which is able to properly output text
|
||||
/// with several options such as character size, style, color,
|
||||
/// position, rotation, etc.
|
||||
/// This separation allows more flexibility and better performances:
|
||||
/// indeed a sf::Font is a heavy resource, and any operation on it
|
||||
/// is slow (often too slow for real-time applications). On the other
|
||||
/// side, a sf::Text is a lightweight object which can combine the
|
||||
/// glyphs data and metrics of a sf::Font to display any text on a
|
||||
/// render target.
|
||||
/// Note that it is also possible to bind several sf::Text instances
|
||||
/// to the same sf::Font.
|
||||
///
|
||||
/// It is important to note that the sf::Text instance doesn't
|
||||
/// copy the font that it uses, it only keeps a reference to it.
|
||||
/// Thus, a sf::Font must not be destructed while it is
|
||||
/// used by a sf::Text (i.e. never write a function that
|
||||
/// uses a local sf::Font instance for creating a text).
|
||||
///
|
||||
/// Usage example:
|
||||
/// \code
|
||||
/// // Declare a new font
|
||||
/// sf::Font font;
|
||||
///
|
||||
/// // Load it from a file
|
||||
/// if (!font.LoadFromFile("arial.ttf"))
|
||||
/// {
|
||||
/// // error...
|
||||
/// }
|
||||
///
|
||||
/// // Create a text which uses our font
|
||||
/// sf::Text text1;
|
||||
/// text1.SetFont(font);
|
||||
/// text1.SetCharacterSize(30);
|
||||
/// text1.SetStyle(sf::Text::Regular);
|
||||
///
|
||||
/// // Create another text using the same font, but with different parameters
|
||||
/// sf::Text text2;
|
||||
/// text2.SetFont(font);
|
||||
/// text2.SetCharacterSize(50);
|
||||
/// text1.SetStyle(sf::Text::Italic);
|
||||
/// \endcode
|
||||
///
|
||||
/// Apart from loading font files, and passing them to instances
|
||||
/// of sf::Text, you should normally not have to deal directly
|
||||
/// with this class. However, it may be useful to access the
|
||||
/// font metrics or rasterized glyphs for advanced usage.
|
||||
///
|
||||
/// \see sf::Text
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -51,8 +51,8 @@ public :
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
int Advance; ///< Offset to move horizontically to the next character
|
||||
IntRect Rectangle; ///< Bounding rectangle of the glyph, in relative coordinates
|
||||
FloatRect TexCoords; ///< Texture coordinates of the glyph inside the bitmap font
|
||||
IntRect Rectangle; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline
|
||||
FloatRect TexCoords; ///< Texture coordinates of the glyph inside the font's image
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
@ -203,7 +203,7 @@ public :
|
||||
/// Warning: for performances reasons, this function doesn't
|
||||
/// perform any check; thus you're responsible of ensuring that
|
||||
/// \a rectangle does not exceed the image size, and that
|
||||
/// \a pixels contain enough elements.
|
||||
/// \a pixels contains enough elements.
|
||||
///
|
||||
/// \param rectangle : Sub-rectangle of the image to update
|
||||
/// \param pixels : Array of pixels to write to the image
|
||||
|
@ -67,10 +67,10 @@ public :
|
||||
///
|
||||
/// \param string : Text assigned to the string
|
||||
/// \param font : Font used to draw the string
|
||||
/// \param size : Characters size
|
||||
/// \param characterSize : Base size of characters, in pixels
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
explicit Text(const String& string, const Font& font = Font::GetDefaultFont(), float size = 30.f);
|
||||
explicit Text(const String& string, const Font& font = Font::GetDefaultFont(), unsigned int characterSize = 30);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Set the text (from any kind of string)
|
||||
@ -89,13 +89,13 @@ public :
|
||||
void SetFont(const Font& font);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Set the size of the string
|
||||
/// Set the base size for the characters.
|
||||
/// The default size is 30
|
||||
///
|
||||
/// \param size : New size, in pixels
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
void SetSize(float size);
|
||||
void SetCharacterSize(unsigned int size);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Set the style of the text
|
||||
@ -123,12 +123,12 @@ public :
|
||||
const Font& GetFont() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the size of the characters
|
||||
/// Get the base size of characters
|
||||
///
|
||||
/// \return Size of the characters
|
||||
/// \return Size of the characters, in pixels
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
float GetSize() const;
|
||||
unsigned int GetCharacterSize() const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the style of the text
|
||||
@ -148,7 +148,7 @@ public :
|
||||
/// \return Position of the index-th character (end of string if Index is out of range)
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
sf::Vector2f GetCharacterPos(std::size_t index) const;
|
||||
Vector2f GetCharacterPos(std::size_t index) const;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the string rectangle on screen
|
||||
@ -179,7 +179,7 @@ private :
|
||||
////////////////////////////////////////////////////////////
|
||||
String myString; ///< String to display
|
||||
ResourcePtr<Font> myFont; ///< Font used to display the string
|
||||
float mySize; ///< Size of the characters
|
||||
unsigned int myCharacterSize; ///< Base size of characters, in pixels
|
||||
unsigned long myStyle; ///< Text style (see Style enum)
|
||||
FloatRect myBaseRect; ///< Bounding rectangle of the text in object coordinates
|
||||
bool myNeedRectUpdate; ///< Does the bounding rect need an update ?
|
||||
|
@ -47,7 +47,7 @@ int main()
|
||||
// Initialize the end text
|
||||
sf::Text end;
|
||||
end.SetFont(font);
|
||||
end.SetSize(60.f);
|
||||
end.SetCharacterSize(60);
|
||||
end.Move(150.f, 200.f);
|
||||
end.SetColor(sf::Color(50, 50, 250));
|
||||
|
||||
|
@ -108,7 +108,7 @@ int main()
|
||||
|
||||
// Load the text font
|
||||
sf::Font font;
|
||||
if (!font.LoadFromFile("datas/shader/arial.ttf", 20))
|
||||
if (!font.LoadFromFile("datas/shader/arial.ttf"))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
// Load the image needed for the wave shader
|
||||
@ -144,7 +144,7 @@ int main()
|
||||
// Define a string for displaying the description of the current shader
|
||||
sf::Text shaderStr;
|
||||
shaderStr.SetFont(font);
|
||||
shaderStr.SetSize(20);
|
||||
shaderStr.SetCharacterSize(20);
|
||||
shaderStr.SetPosition(5.f, 0.f);
|
||||
shaderStr.SetColor(sf::Color(250, 100, 30));
|
||||
shaderStr.SetString("Background shader: \"" + backgroundShader.GetName() + "\"\n"
|
||||
@ -154,8 +154,8 @@ int main()
|
||||
// Define a string for displaying help
|
||||
sf::Text infoStr;
|
||||
infoStr.SetFont(font);
|
||||
infoStr.SetSize(20);
|
||||
infoStr.SetPosition(5.f, 510.f);
|
||||
infoStr.SetCharacterSize(20);
|
||||
infoStr.SetPosition(5.f, 500.f);
|
||||
infoStr.SetColor(sf::Color(250, 100, 30));
|
||||
infoStr.SetString("Move your mouse to change the shaders' parameters\n"
|
||||
"Press numpad 1/4 to change the background shader\n"
|
||||
|
@ -26,133 +26,213 @@
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/Font.hpp>
|
||||
#include <SFML/Graphics/FontLoader.hpp>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_GLYPH_H
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
// Static member data
|
||||
////////////////////////////////////////////////////////////
|
||||
Uint32 Font::ourDefaultCharset[] =
|
||||
{
|
||||
// Printable characters in ASCII range
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E,
|
||||
|
||||
// Printable characters in extended ASCII range
|
||||
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0x2A, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
|
||||
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
|
||||
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
|
||||
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE,
|
||||
|
||||
// To make it a valid string
|
||||
0x00
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
Font::Font() :
|
||||
myCharSize(0)
|
||||
myLibrary (NULL),
|
||||
myFace (NULL),
|
||||
myRefCount (NULL),
|
||||
myCurrentSize(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Load the font from a file
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Font::LoadFromFile(const std::string& filename, unsigned int charSize, String charset)
|
||||
Font::Font(const Font& copy) :
|
||||
myLibrary (copy.myLibrary),
|
||||
myFace (copy.myFace),
|
||||
myRefCount (copy.myRefCount),
|
||||
myPages (copy.myPages),
|
||||
myPixelBuffer(copy.myPixelBuffer),
|
||||
myCurrentSize(copy.myCurrentSize)
|
||||
{
|
||||
// Clear the previous character map
|
||||
myGlyphs.clear();
|
||||
// Note: as FreeType doesn't provide functions for copying/cloning,
|
||||
// we must share all the FreeType pointers
|
||||
|
||||
// Always add these special characters
|
||||
if (std::find(charset.Begin(), charset.End(), L' ') == charset.End()) charset += L' ';
|
||||
if (std::find(charset.Begin(), charset.End(), L'\n') == charset.End()) charset += L'\n';
|
||||
if (std::find(charset.Begin(), charset.End(), L'\v') == charset.End()) charset += L'\v';
|
||||
if (std::find(charset.Begin(), charset.End(), L'\t') == charset.End()) charset += L'\t';
|
||||
|
||||
return priv::FontLoader::GetInstance().LoadFontFromFile(filename, charSize, charset, *this);
|
||||
if (myRefCount)
|
||||
(*myRefCount)++;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Load the font from a file in memory
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Font::LoadFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize, String charset)
|
||||
Font::~Font()
|
||||
{
|
||||
// Clear the previous character map
|
||||
myGlyphs.clear();
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
// Check parameters
|
||||
if (!data || (sizeInBytes == 0))
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Font::LoadFromFile(const std::string& filename)
|
||||
{
|
||||
std::cerr << "Failed to load font from memory, no data provided" << std::endl;
|
||||
// Cleanup the previous resources
|
||||
Cleanup();
|
||||
|
||||
// Initialize FreeType
|
||||
// Note: we initialize FreeType for every font instance in order to avoid having a single
|
||||
// global manager that would create a lot of issues regarding creation and destruction order.
|
||||
FT_Library library;
|
||||
if (FT_Init_FreeType(&library) != 0)
|
||||
{
|
||||
std::cerr << "Failed to load font \"" << filename << "\" (failed to initialize FreeType)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
myLibrary = library;
|
||||
|
||||
// Load the new font face from the specified file
|
||||
FT_Face face;
|
||||
if (FT_New_Face(static_cast<FT_Library>(myLibrary), filename.c_str(), 0, &face) != 0)
|
||||
{
|
||||
std::cerr << "Failed to load font \"" << filename << "\" (failed to create the font face)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Always add these special characters
|
||||
if (std::find(charset.Begin(), charset.End(), L' ') == charset.End()) charset += L' ';
|
||||
if (std::find(charset.Begin(), charset.End(), L'\n') == charset.End()) charset += L'\n';
|
||||
if (std::find(charset.Begin(), charset.End(), L'\v') == charset.End()) charset += L'\v';
|
||||
if (std::find(charset.Begin(), charset.End(), L'\t') == charset.End()) charset += L'\t';
|
||||
// Select the unicode character map
|
||||
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
|
||||
{
|
||||
std::cerr << "Failed to load font \"" << filename << "\" (failed to set the Unicode character set)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return priv::FontLoader::GetInstance().LoadFontFromMemory(data, sizeInBytes, charSize, charset, *this);
|
||||
// Store the loaded font in our ugly void* :)
|
||||
myFace = face;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the base size of characters in the font;
|
||||
/// All glyphs dimensions are based on this value
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Font::GetCharacterSize() const
|
||||
bool Font::LoadFromMemory(const char* data, std::size_t sizeInBytes)
|
||||
{
|
||||
return myCharSize;
|
||||
// Cleanup the previous resources
|
||||
Cleanup();
|
||||
|
||||
// Initialize FreeType
|
||||
// Note: we initialize FreeType for every font instance in order to avoid having a single
|
||||
// global manager that would create a lot of issues regarding creation and destruction order.
|
||||
FT_Library library;
|
||||
if (FT_Init_FreeType(&library) != 0)
|
||||
{
|
||||
std::cerr << "Failed to load font from memory (failed to initialize FreeType)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
myLibrary = library;
|
||||
|
||||
// Load the new font face from the specified file
|
||||
FT_Face face;
|
||||
if (FT_New_Memory_Face(static_cast<FT_Library>(myLibrary), reinterpret_cast<const FT_Byte*>(data), static_cast<FT_Long>(sizeInBytes), 0, &face) != 0)
|
||||
{
|
||||
std::cerr << "Failed to load font from memory (failed to create the font face)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Select the unicode character map
|
||||
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
|
||||
{
|
||||
std::cerr << "Failed to load font from memory (failed to set the Unicode character set)" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store the loaded font in our ugly void* :)
|
||||
myFace = face;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the description of a glyph (character)
|
||||
/// given by its unicode value
|
||||
////////////////////////////////////////////////////////////
|
||||
const Glyph& Font::GetGlyph(Uint32 codePoint) const
|
||||
const Glyph& Font::GetGlyph(Uint32 codePoint, unsigned int characterSize) const
|
||||
{
|
||||
std::map<Uint32, Glyph>::const_iterator it = myGlyphs.find(codePoint);
|
||||
if (it != myGlyphs.end())
|
||||
// Get the page corresponding to the character size
|
||||
GlyphTable& glyphs = myPages[characterSize].Glyphs;
|
||||
|
||||
// Search the glyph into the cache
|
||||
GlyphTable::const_iterator it = glyphs.find(codePoint);
|
||||
if (it != glyphs.end())
|
||||
{
|
||||
// Valid glyph
|
||||
return it->second;
|
||||
// Found: just return it
|
||||
return it->second.GlyphDesc;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid glyph -- return an invalid glyph
|
||||
static const Glyph invalid;
|
||||
return invalid;
|
||||
// Not found: we have to load it
|
||||
GlyphInfo glyph = LoadGlyph(codePoint, characterSize);
|
||||
return glyphs.insert(std::make_pair(codePoint, glyph)).first->second.GlyphDesc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the image containing the rendered characters (glyphs)
|
||||
////////////////////////////////////////////////////////////
|
||||
const Image& Font::GetImage() const
|
||||
int Font::GetKerning(Uint32 first, Uint32 second, unsigned int characterSize) const
|
||||
{
|
||||
return myTexture;
|
||||
FT_Face face = static_cast<FT_Face>(myFace);
|
||||
|
||||
if (face && FT_HAS_KERNING(face) && SetCurrentSize(characterSize))
|
||||
{
|
||||
// Convert the characters to indices
|
||||
FT_UInt index1 = FT_Get_Char_Index(face, first);
|
||||
FT_UInt index2 = FT_Get_Char_Index(face, second);
|
||||
|
||||
// Get the kerning vector
|
||||
FT_Vector kerning;
|
||||
FT_Get_Kerning(face, index1, index2, FT_KERNING_DEFAULT, &kerning);
|
||||
|
||||
// Return the X advance
|
||||
return kerning.x >> 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid font, or no kerning
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the SFML default built-in font (Arial)
|
||||
int Font::GetLineSpacing(unsigned int characterSize) const
|
||||
{
|
||||
FT_Face face = static_cast<FT_Face>(myFace);
|
||||
|
||||
if (face && SetCurrentSize(characterSize))
|
||||
{
|
||||
return (face->size->metrics.height >> 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Image& Font::GetImage(unsigned int characterSize) const
|
||||
{
|
||||
return myPages[characterSize].Texture;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Font& Font::operator =(const Font& right)
|
||||
{
|
||||
Font temp(right);
|
||||
|
||||
std::swap(myLibrary, temp.myLibrary);
|
||||
std::swap(myFace, temp.myFace);
|
||||
std::swap(myPages, temp.myPages);
|
||||
std::swap(myPixelBuffer, temp.myPixelBuffer);
|
||||
std::swap(myCurrentSize, temp.myCurrentSize);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
const Font& Font::GetDefaultFont()
|
||||
{
|
||||
@ -167,11 +247,231 @@ const Font& Font::GetDefaultFont()
|
||||
#include <SFML/Graphics/Arial.hpp>
|
||||
};
|
||||
|
||||
font.LoadFromMemory(data, sizeof(data), 30);
|
||||
font.LoadFromMemory(data, sizeof(data));
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void Font::Cleanup()
|
||||
{
|
||||
// Check if we must destroy the FreeType pointers
|
||||
if (myRefCount)
|
||||
{
|
||||
// Decrease the reference counter
|
||||
(*myRefCount)--;
|
||||
|
||||
// Free the resources only if we are the last owner
|
||||
if (*myRefCount == 0)
|
||||
{
|
||||
// Delete the reference counter
|
||||
delete myRefCount;
|
||||
|
||||
// Destroy the font face
|
||||
if (myFace)
|
||||
FT_Done_Face(static_cast<FT_Face>(myFace));
|
||||
|
||||
// Close the library
|
||||
if (myLibrary)
|
||||
FT_Done_FreeType(static_cast<FT_Library>(myLibrary));
|
||||
}
|
||||
}
|
||||
|
||||
// Reset members
|
||||
myLibrary = NULL;
|
||||
myFace = NULL;
|
||||
myRefCount = NULL;
|
||||
myCurrentSize = 0;
|
||||
myPages.clear();
|
||||
myPixelBuffer.clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Font::GlyphInfo Font::LoadGlyph(Uint32 codePoint, unsigned int characterSize) const
|
||||
{
|
||||
// The glyph to return
|
||||
GlyphInfo glyphInfo;
|
||||
|
||||
// First, transform our ugly void* to a FT_Face
|
||||
FT_Face face = static_cast<FT_Face>(myFace);
|
||||
if (!face)
|
||||
return glyphInfo;
|
||||
|
||||
// Set the character size
|
||||
if (!SetCurrentSize(characterSize))
|
||||
return glyphInfo;
|
||||
|
||||
// Load the glyph corresponding to the code point
|
||||
if (FT_Load_Char(face, codePoint, FT_LOAD_TARGET_NORMAL) != 0)
|
||||
return glyphInfo;
|
||||
|
||||
// Convert the glyph to a bitmap (i.e. rasterize it)
|
||||
FT_Glyph glyphDesc;
|
||||
if (FT_Get_Glyph(face->glyph, &glyphDesc) != 0)
|
||||
return glyphInfo;
|
||||
FT_Glyph_To_Bitmap(&glyphDesc, FT_RENDER_MODE_NORMAL, 0, 1);
|
||||
FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyphDesc;
|
||||
FT_Bitmap& bitmap = bitmapGlyph->bitmap;
|
||||
|
||||
// Compute the glyph's advance offset
|
||||
glyphInfo.GlyphDesc.Advance = bitmapGlyph->root.advance.x >> 16;
|
||||
|
||||
if ((bitmap.width > 0) && (bitmap.rows > 0))
|
||||
{
|
||||
// Leave a small padding around characters, so that filtering doesn't
|
||||
// pollute them with pixels from neighbours
|
||||
const unsigned int padding = 1;
|
||||
|
||||
// Get the glyphs page corresponding to the character size
|
||||
Page& page = myPages[characterSize];
|
||||
|
||||
// Find a good position for the new glyph into the texture
|
||||
glyphInfo.TextureRect = FindGlyphRect(page, bitmap.width + 2 * padding, bitmap.rows + 2 * padding);
|
||||
|
||||
// Compute the glyph's texture coordinates and bounding box
|
||||
glyphInfo.GlyphDesc.TexCoords = page.Texture.GetTexCoords(glyphInfo.TextureRect);
|
||||
glyphInfo.GlyphDesc.Rectangle.Left = bitmapGlyph->left - padding;
|
||||
glyphInfo.GlyphDesc.Rectangle.Top = -bitmapGlyph->top - padding;
|
||||
glyphInfo.GlyphDesc.Rectangle.Right = bitmapGlyph->left + bitmap.width + padding;
|
||||
glyphInfo.GlyphDesc.Rectangle.Bottom = -bitmapGlyph->top + bitmap.rows + padding;
|
||||
|
||||
// Extract the glyph's pixels from the bitmap
|
||||
myPixelBuffer.resize(bitmap.width * bitmap.rows * 4, 255);
|
||||
const Uint8* pixels = bitmap.buffer;
|
||||
for (int y = 0; y < bitmap.rows; ++y)
|
||||
{
|
||||
for (int x = 0; x < bitmap.width; ++x)
|
||||
{
|
||||
// The color channels remain white, just fill the alpha channel
|
||||
std::size_t index = (x + y * bitmap.width) * 4 + 3;
|
||||
myPixelBuffer[index] = pixels[x];
|
||||
|
||||
// Formula for FT_RENDER_MODE_MONO
|
||||
// myPixelBuffer[index] = ((pixels[x / 8]) & (1 << (7 - (x % 8)))) ? 255 : 0;
|
||||
}
|
||||
pixels += bitmap.pitch;
|
||||
}
|
||||
|
||||
// Write the pixels to the texture
|
||||
IntRect subrect = glyphInfo.TextureRect;
|
||||
subrect.Left += padding;
|
||||
subrect.Top += padding;
|
||||
subrect.Right -= padding;
|
||||
subrect.Bottom -= padding;
|
||||
page.Texture.UpdatePixels(&myPixelBuffer[0], subrect);
|
||||
}
|
||||
|
||||
// Delete the FT glyph
|
||||
FT_Done_Glyph(glyphDesc);
|
||||
|
||||
// Done :)
|
||||
return glyphInfo;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
IntRect Font::FindGlyphRect(Page& page, unsigned int width, unsigned int height) const
|
||||
{
|
||||
// Find the line that fits well the glyph
|
||||
Row* row = NULL;
|
||||
float bestRatio = 0;
|
||||
for (std::vector<Row>::iterator it = page.Rows.begin(); it != page.Rows.end() && !row; ++it)
|
||||
{
|
||||
float ratio = static_cast<float>(height) / it->Height;
|
||||
|
||||
// Ignore rows that are either too small or too high
|
||||
if ((ratio < 0.7f) || (ratio > 1.f))
|
||||
continue;
|
||||
|
||||
// Check if there's enough horizontal space left in the row
|
||||
if (width > page.Texture.GetWidth() - it->Width)
|
||||
continue;
|
||||
|
||||
// Make sure that this new row is the best found so far
|
||||
if (ratio < bestRatio)
|
||||
continue;
|
||||
|
||||
// The current row passed all the tests: we can select it
|
||||
row = &*it;
|
||||
bestRatio = ratio;
|
||||
}
|
||||
|
||||
// If we didn't find a matching row, create a new one (10% taller than the glyph)
|
||||
if (!row)
|
||||
{
|
||||
int rowHeight = height + height / 10;
|
||||
if (page.NextRow + rowHeight >= page.Texture.GetHeight())
|
||||
{
|
||||
// Not enough space: resize the texture if possible
|
||||
unsigned int textureWidth = page.Texture.GetWidth();
|
||||
unsigned int textureHeight = page.Texture.GetHeight();
|
||||
if ((textureWidth * 2 <= Image::GetMaximumSize()) && (textureHeight * 2 <= Image::GetMaximumSize()))
|
||||
{
|
||||
// Make the texture 2 times bigger
|
||||
std::size_t size = textureWidth * textureHeight * 4;
|
||||
std::vector<Uint8> pixels(size);
|
||||
memcpy(&pixels[0], page.Texture.GetPixelsPtr(), size);
|
||||
page.Texture.Create(textureWidth * 2, textureHeight * 2, sf::Color(255, 255, 255, 0));
|
||||
page.Texture.UpdatePixels(&pixels[0], IntRect(0, 0, textureWidth, textureHeight));
|
||||
|
||||
// Adjust the texture coordinates of all the glyphs that are stored in this page
|
||||
for (GlyphTable::iterator it = page.Glyphs.begin(); it != page.Glyphs.end(); ++it)
|
||||
{
|
||||
it->second.GlyphDesc.TexCoords = page.Texture.GetTexCoords(it->second.TextureRect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Oops, we've reached the maximum texture size...
|
||||
std::cerr << "Failed to add a new character to the font: the maximum image size has been reached" << std::endl;
|
||||
return IntRect(0, 0, 2, 2);
|
||||
}
|
||||
}
|
||||
|
||||
// We can now create the new row
|
||||
page.Rows.push_back(Row(page.NextRow, rowHeight));
|
||||
page.NextRow += rowHeight;
|
||||
row = &page.Rows.back();
|
||||
}
|
||||
|
||||
// Find the glyph's rectangle on the selected row
|
||||
IntRect rect(row->Width, row->Top, row->Width + width, row->Top + height);
|
||||
|
||||
// Update the row informations
|
||||
row->Width += width;
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Font::SetCurrentSize(unsigned int characterSize) const
|
||||
{
|
||||
// FT_Set_Pixel_Sizes is an expensive function, so we must call it
|
||||
// only when necessary to avoid killing performances
|
||||
|
||||
if (myCurrentSize != characterSize)
|
||||
{
|
||||
myCurrentSize = characterSize;
|
||||
return FT_Set_Pixel_Sizes(static_cast<FT_Face>(myFace), characterSize, characterSize) == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
Font::Page::Page() :
|
||||
NextRow(0)
|
||||
{
|
||||
// Make sure that the texture is initialized by default
|
||||
Texture.Create(128, 128, Color(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
@ -1,671 +0,0 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented;
|
||||
// you must not claim that you wrote the original software.
|
||||
// If you use this software in a product, an acknowledgment
|
||||
// in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such,
|
||||
// and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
//#define SFML_USE_STBTT
|
||||
#ifndef SFML_USE_STBTT
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/FontLoader.hpp>
|
||||
#include <SFML/Graphics/Color.hpp>
|
||||
#include <SFML/Graphics/Font.hpp>
|
||||
#include <SFML/Graphics/Image.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
#include FT_GLYPH_H
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
// Functor to sort glyphs by size
|
||||
////////////////////////////////////////////////////////////
|
||||
struct SizeCompare
|
||||
{
|
||||
bool operator ()(FT_BitmapGlyph left, FT_BitmapGlyph right) const
|
||||
{
|
||||
return left->bitmap.rows < right->bitmap.rows;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the unique instance of the class
|
||||
////////////////////////////////////////////////////////////
|
||||
FontLoader& FontLoader::GetInstance()
|
||||
{
|
||||
static FontLoader instance;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
FontLoader::FontLoader()
|
||||
{
|
||||
// Initialize FreeType library
|
||||
FT_Error error = FT_Init_FreeType(&myLibrary);
|
||||
if (error)
|
||||
{
|
||||
std::cerr << "Failed to initialize FreeType library (error code : " << error << ")" << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Destructor
|
||||
////////////////////////////////////////////////////////////
|
||||
FontLoader::~FontLoader()
|
||||
{
|
||||
// Shutdown FreeType library
|
||||
if (myLibrary)
|
||||
FT_Done_FreeType(myLibrary);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Load a font from a file
|
||||
////////////////////////////////////////////////////////////
|
||||
bool FontLoader::LoadFontFromFile(const std::string& filename, unsigned int charSize, const String& charset, Font& font)
|
||||
{
|
||||
// Check if Freetype is correctly initialized
|
||||
if (!myLibrary)
|
||||
{
|
||||
std::cerr << "Failed to load font \"" << filename << "\", FreeType has not been initialized" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a new font face from the specified file
|
||||
FT_Face face;
|
||||
FT_Error error = FT_New_Face(myLibrary, filename.c_str(), 0, &face);
|
||||
if (error)
|
||||
{
|
||||
std::cerr << "Failed to load font \"" << filename << "\" (" << GetErrorDesc(error) << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the bitmap font
|
||||
error = CreateBitmapFont(face, charSize, charset, font);
|
||||
if (error)
|
||||
std::cerr << "Failed to load font \"" << filename << "\" (" << GetErrorDesc(error) << ")" << std::endl;
|
||||
|
||||
// Delete the font
|
||||
FT_Done_Face(face);
|
||||
|
||||
return error == 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Load the font from a file in memory
|
||||
////////////////////////////////////////////////////////////
|
||||
bool FontLoader::LoadFontFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize, const String& charset, Font& font)
|
||||
{
|
||||
// Check if Freetype is correctly initialized
|
||||
if (!myLibrary)
|
||||
{
|
||||
std::cerr << "Failed to load font from memory, FreeType has not been initialized" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a new font face from the specified memory data
|
||||
FT_Face face;
|
||||
FT_Error error = FT_New_Memory_Face(myLibrary, reinterpret_cast<const FT_Byte*>(data), static_cast<FT_Long>(sizeInBytes), 0, &face);
|
||||
if (error)
|
||||
{
|
||||
std::cerr << "Failed to load font from memory (" << GetErrorDesc(error) << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the bitmap font
|
||||
error = CreateBitmapFont(face, charSize, charset, font);
|
||||
if (error)
|
||||
std::cerr << "Failed to load font from memory (" << GetErrorDesc(error) << ")" << std::endl;
|
||||
|
||||
// Delete the font
|
||||
FT_Done_Face(face);
|
||||
|
||||
return error == 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Create a bitmap font from a font face and a characters set
|
||||
////////////////////////////////////////////////////////////
|
||||
FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const String& charset, Font& font)
|
||||
{
|
||||
// Let's find how many characters to put in each row to make them fit into a squared texture
|
||||
unsigned int maxSize = Image::GetMaximumSize();
|
||||
int nbChars = static_cast<int>(sqrt(static_cast<double>(charset.GetSize())) * 0.75);
|
||||
|
||||
// Clamp the character size to make sure we won't create a texture too big
|
||||
if (nbChars * charSize >= maxSize)
|
||||
charSize = maxSize / nbChars;
|
||||
|
||||
// Initialize the dimensions
|
||||
unsigned int left = 0;
|
||||
unsigned int top = 0;
|
||||
unsigned int texWidth = Image::GetValidSize(charSize * nbChars);
|
||||
unsigned int texHeight = charSize * nbChars;
|
||||
std::vector<unsigned int> tops(texWidth, 0);
|
||||
|
||||
// Create a pixel buffer for rendering every glyph
|
||||
std::vector<Uint8> glyphsBuffer(texWidth * texHeight * 4);
|
||||
|
||||
// Setup the font size
|
||||
FT_Error error = FT_Set_Pixel_Sizes(face, charSize, charSize);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
// Select the unicode character map
|
||||
error = FT_Select_Charmap(face, FT_ENCODING_UNICODE);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
// Render all glyphs and sort them by size to optimize texture space
|
||||
typedef std::multimap<FT_BitmapGlyph, Uint32, SizeCompare> GlyphTable;
|
||||
GlyphTable glyphs;
|
||||
for (std::size_t i = 0; i < charset.GetSize(); ++i)
|
||||
{
|
||||
// Load the glyph corresponding to the current character
|
||||
error = FT_Load_Char(face, charset[i], FT_LOAD_TARGET_NORMAL);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
// Convert the glyph to a bitmap (ie. rasterize it)
|
||||
FT_Glyph glyph;
|
||||
error = FT_Get_Glyph(face->glyph, &glyph);
|
||||
if (error)
|
||||
return error;
|
||||
FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
|
||||
FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
|
||||
|
||||
// Add it to the sorted table of glyphs
|
||||
glyphs.insert(std::make_pair(bitmapGlyph, charset[i]));
|
||||
}
|
||||
|
||||
// Leave a small margin around characters, so that filtering doesn't
|
||||
// pollute them with pixels from neighbours
|
||||
unsigned int padding = 1;
|
||||
unsigned int margin = 1;
|
||||
|
||||
// Copy the rendered glyphs into the texture
|
||||
unsigned int maxHeight = 0;
|
||||
std::map<Uint32, IntRect> coords;
|
||||
for (GlyphTable::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i)
|
||||
{
|
||||
// Get the bitmap of the current glyph
|
||||
Glyph& curGlyph = font.myGlyphs[i->second];
|
||||
FT_BitmapGlyph bitmapGlyph = i->first;
|
||||
FT_Bitmap& bitmap = bitmapGlyph->bitmap;
|
||||
|
||||
// Make sure we don't go over the texture width
|
||||
if (left + bitmap.width + 2 * padding + margin >= texWidth)
|
||||
left = 0;
|
||||
|
||||
// Compute the top coordinate
|
||||
top = tops[left];
|
||||
for (unsigned int x = 0; x < bitmap.width + 2 * padding + margin; ++x)
|
||||
top = std::max(top, tops[left + x]);
|
||||
|
||||
// Make sure we don't go over the texture height -- resize it if we need more space
|
||||
if (top + bitmap.rows + 2 * padding + margin >= texHeight)
|
||||
{
|
||||
texHeight *= 2;
|
||||
glyphsBuffer.resize(texWidth * texHeight * 4);
|
||||
}
|
||||
|
||||
// Store the character's position and size
|
||||
curGlyph.Rectangle.Left = bitmapGlyph->left - padding;
|
||||
curGlyph.Rectangle.Top = -bitmapGlyph->top - padding;
|
||||
curGlyph.Rectangle.Right = bitmapGlyph->left + bitmap.width + padding;
|
||||
curGlyph.Rectangle.Bottom = -bitmapGlyph->top + bitmap.rows + padding;
|
||||
curGlyph.Advance = bitmapGlyph->root.advance.x >> 16;
|
||||
|
||||
// Texture size may change, so let the texture coordinates be calculated later
|
||||
coords[i->second] = IntRect(left, top, left + bitmap.width + 2 * padding, top + bitmap.rows + 2 * padding);
|
||||
|
||||
// Draw the glyph into our bitmap font
|
||||
const Uint8* pixels = bitmap.buffer;
|
||||
for (int y = 0; y < bitmap.rows; ++y)
|
||||
{
|
||||
for (int x = 0; x < bitmap.width; ++x)
|
||||
{
|
||||
std::size_t index = x + left + padding + (y + top + padding) * texWidth;
|
||||
glyphsBuffer[index * 4 + 0] = 255;
|
||||
glyphsBuffer[index * 4 + 1] = 255;
|
||||
glyphsBuffer[index * 4 + 2] = 255;
|
||||
glyphsBuffer[index * 4 + 3] = pixels[x];
|
||||
|
||||
// Formula for FT_RENDER_MODE_MONO
|
||||
// glyphsBuffer[index * 4 + 3] = ((pixels[x / 8]) & (1 << (7 - (x % 8)))) ? 255 : 0;
|
||||
}
|
||||
pixels += bitmap.pitch;
|
||||
}
|
||||
|
||||
// Update the rendering coordinates
|
||||
for (unsigned int x = 0; x < bitmap.width + 2 * padding + margin; ++x)
|
||||
tops[left + x] = top + bitmap.rows + 2 * padding + margin;
|
||||
left += bitmap.width + 2 * padding + margin;
|
||||
if (top + bitmap.rows + 2 * padding > maxHeight)
|
||||
maxHeight = top + bitmap.rows + 2 * padding;
|
||||
|
||||
// Delete the glyph
|
||||
FT_Done_Glyph((FT_Glyph)bitmapGlyph);
|
||||
}
|
||||
|
||||
// Create the font's texture
|
||||
texHeight = maxHeight;
|
||||
glyphsBuffer.resize(texWidth * texHeight * 4);
|
||||
font.myTexture.LoadFromPixels(texWidth, texHeight, &glyphsBuffer[0]);
|
||||
|
||||
// Now that the texture is created, we can precompute texture coordinates
|
||||
for (std::size_t i = 0; i < charset.GetSize(); ++i)
|
||||
{
|
||||
Uint32 curChar = charset[i];
|
||||
font.myGlyphs[curChar].TexCoords = font.myTexture.GetTexCoords(coords[curChar]);
|
||||
}
|
||||
|
||||
// Update the character size (it may have been changed by the function)
|
||||
font.myCharSize = charSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get a description from a FT error code
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string FontLoader::GetErrorDesc(FT_Error error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
// Generic errors
|
||||
case FT_Err_Cannot_Open_Resource : return "cannot open resource";
|
||||
case FT_Err_Unknown_File_Format : return "unknown file format";
|
||||
case FT_Err_Invalid_File_Format : return "broken file";
|
||||
case FT_Err_Invalid_Version : return "invalid FreeType version";
|
||||
case FT_Err_Lower_Module_Version : return "module version is too low";
|
||||
case FT_Err_Invalid_Argument : return "invalid argument";
|
||||
case FT_Err_Unimplemented_Feature : return "unimplemented feature";
|
||||
case FT_Err_Invalid_Table : return "broken table";
|
||||
case FT_Err_Invalid_Offset : return "broken offset within table";
|
||||
|
||||
// Glyph / character errors
|
||||
case FT_Err_Invalid_Glyph_Index : return "invalid glyph index";
|
||||
case FT_Err_Invalid_Character_Code : return "invalid character code";
|
||||
case FT_Err_Invalid_Glyph_Format : return "unsupported glyph image format";
|
||||
case FT_Err_Cannot_Render_Glyph : return "cannot render this glyph format";
|
||||
case FT_Err_Invalid_Outline : return "invalid outline";
|
||||
case FT_Err_Invalid_Composite : return "invalid composite glyph";
|
||||
case FT_Err_Too_Many_Hints : return "too many hints";
|
||||
case FT_Err_Invalid_Pixel_Size : return "invalid pixel size";
|
||||
|
||||
// Handle errors
|
||||
case FT_Err_Invalid_Handle : return "invalid object handle";
|
||||
case FT_Err_Invalid_Library_Handle : return "invalid library handle";
|
||||
case FT_Err_Invalid_Driver_Handle : return "invalid module handle";
|
||||
case FT_Err_Invalid_Face_Handle : return "invalid face handle";
|
||||
case FT_Err_Invalid_Size_Handle : return "invalid size handle";
|
||||
case FT_Err_Invalid_Slot_Handle : return "invalid glyph slot handle";
|
||||
case FT_Err_Invalid_CharMap_Handle : return "invalid charmap handle";
|
||||
case FT_Err_Invalid_Cache_Handle : return "invalid cache manager handle";
|
||||
case FT_Err_Invalid_Stream_Handle : return "invalid stream handle";
|
||||
|
||||
// Driver errors
|
||||
case FT_Err_Too_Many_Drivers : return "too many modules";
|
||||
case FT_Err_Too_Many_Extensions : return "too many extensions";
|
||||
|
||||
// Memory errors
|
||||
case FT_Err_Out_Of_Memory : return "out of memory";
|
||||
case FT_Err_Unlisted_Object : return "unlisted object";
|
||||
|
||||
// Stream errors
|
||||
case FT_Err_Cannot_Open_Stream : return "cannot open stream";
|
||||
case FT_Err_Invalid_Stream_Seek : return "invalid stream seek";
|
||||
case FT_Err_Invalid_Stream_Skip : return "invalid stream skip";
|
||||
case FT_Err_Invalid_Stream_Read : return "invalid stream read";
|
||||
case FT_Err_Invalid_Stream_Operation : return "invalid stream operation";
|
||||
case FT_Err_Invalid_Frame_Operation : return "invalid frame operation";
|
||||
case FT_Err_Nested_Frame_Access : return "nested frame access";
|
||||
case FT_Err_Invalid_Frame_Read : return "invalid frame read";
|
||||
|
||||
// Raster errors
|
||||
case FT_Err_Raster_Uninitialized : return "raster uninitialized";
|
||||
case FT_Err_Raster_Corrupted : return "raster corrupted";
|
||||
case FT_Err_Raster_Overflow : return "raster overflow";
|
||||
case FT_Err_Raster_Negative_Height : return "negative height while rastering";
|
||||
|
||||
// Cache errors
|
||||
case FT_Err_Too_Many_Caches : return "too many registered caches";
|
||||
|
||||
// TrueType and SFNT errors
|
||||
case FT_Err_Invalid_Opcode : return "invalid opcode";
|
||||
case FT_Err_Too_Few_Arguments : return "too few arguments";
|
||||
case FT_Err_Stack_Overflow : return "stack overflow";
|
||||
case FT_Err_Code_Overflow : return "code overflow";
|
||||
case FT_Err_Bad_Argument : return "bad argument";
|
||||
case FT_Err_Divide_By_Zero : return "division by zero";
|
||||
case FT_Err_Invalid_Reference : return "invalid reference";
|
||||
case FT_Err_Debug_OpCode : return "found debug opcode";
|
||||
case FT_Err_ENDF_In_Exec_Stream : return "found ENDF opcode in execution stream";
|
||||
case FT_Err_Nested_DEFS : return "nested DEFS";
|
||||
case FT_Err_Invalid_CodeRange : return "invalid code range";
|
||||
case FT_Err_Execution_Too_Long : return "execution context too long";
|
||||
case FT_Err_Too_Many_Function_Defs : return "too many function definitions";
|
||||
case FT_Err_Too_Many_Instruction_Defs : return "too many instruction definitions";
|
||||
case FT_Err_Table_Missing : return "SFNT font table missing";
|
||||
case FT_Err_Horiz_Header_Missing : return "horizontal header (hhea) table missing";
|
||||
case FT_Err_Locations_Missing : return "locations (loca) table missing";
|
||||
case FT_Err_Name_Table_Missing : return "name table missing";
|
||||
case FT_Err_CMap_Table_Missing : return "character map (cmap) table missing";
|
||||
case FT_Err_Hmtx_Table_Missing : return "horizontal metrics (hmtx) table missing";
|
||||
case FT_Err_Post_Table_Missing : return "PostScript (post) table missing";
|
||||
case FT_Err_Invalid_Horiz_Metrics : return "invalid horizontal metrics";
|
||||
case FT_Err_Invalid_CharMap_Format : return "invalid character map (cmap) format";
|
||||
case FT_Err_Invalid_PPem : return "invalid ppem value";
|
||||
case FT_Err_Invalid_Vert_Metrics : return "invalid vertical metrics";
|
||||
case FT_Err_Could_Not_Find_Context : return "could not find context";
|
||||
case FT_Err_Invalid_Post_Table_Format : return "invalid PostScript (post) table format";
|
||||
case FT_Err_Invalid_Post_Table : return "invalid PostScript (post) table";
|
||||
|
||||
// CCF, CID and Type 1 errors
|
||||
case FT_Err_Syntax_Error : return "opcode syntax error";
|
||||
case FT_Err_Stack_Underflow : return "argument stack underflow";
|
||||
case FT_Err_Ignore : return "ignore";
|
||||
|
||||
// BDF errors
|
||||
case FT_Err_Missing_Startfont_Field : return "`STARTFONT' field missing";
|
||||
case FT_Err_Missing_Font_Field : return "`FONT' field missing";
|
||||
case FT_Err_Missing_Size_Field : return "`SIZE' field missing";
|
||||
case FT_Err_Missing_Chars_Field : return "`CHARS' field missing";
|
||||
case FT_Err_Missing_Startchar_Field : return "`STARTCHAR' field missing";
|
||||
case FT_Err_Missing_Encoding_Field : return "`ENCODING' field missing";
|
||||
case FT_Err_Missing_Bbx_Field : return "`BBX' field missing";
|
||||
}
|
||||
|
||||
return "unknown error";
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
#else
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Graphics/FontLoader.hpp>
|
||||
#include <SFML/Graphics/Color.hpp>
|
||||
#include <SFML/Graphics/Font.hpp>
|
||||
#include <SFML/Graphics/Image.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include <SFML/Graphics/stb_truetype/stb_truetype.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
// Functor to sort glyphs by size
|
||||
////////////////////////////////////////////////////////////
|
||||
struct SizeCompare
|
||||
{
|
||||
bool operator ()(const sf::Glyph& left, const sf::Glyph& right) const
|
||||
{
|
||||
return left.Rectangle.GetSize().y < right.Rectangle.GetSize().y;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace sf
|
||||
{
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the unique instance of the class
|
||||
////////////////////////////////////////////////////////////
|
||||
FontLoader& FontLoader::GetInstance()
|
||||
{
|
||||
static FontLoader instance;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
FontLoader::FontLoader()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Destructor
|
||||
////////////////////////////////////////////////////////////
|
||||
FontLoader::~FontLoader()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Load a font from a file
|
||||
////////////////////////////////////////////////////////////
|
||||
bool FontLoader::LoadFontFromFile(const std::string& filename, unsigned int charSize, const String& charset, Font& font)
|
||||
{
|
||||
// Get the contents of the font file
|
||||
std::ifstream file(filename.c_str(), std::ios_base::binary);
|
||||
if (!file)
|
||||
return false;
|
||||
file.seekg(0, std::ios::end);
|
||||
std::size_t length = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
std::vector<char> data(length);
|
||||
file.read(&data[0], static_cast<std::streamsize>(length));
|
||||
|
||||
// Load from memory
|
||||
return LoadFontFromMemory(&data[0], data.size(), charSize, charset, font);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Load the font from a file in memory
|
||||
////////////////////////////////////////////////////////////
|
||||
bool FontLoader::LoadFontFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize, const String& charset, Font& font)
|
||||
{
|
||||
// Let's find how many characters to put in each row to make them fit into a squared texture
|
||||
unsigned int maxSize = Image::GetMaximumSize();
|
||||
int nbChars = static_cast<int>(sqrt(static_cast<double>(charset.GetSize())) * 0.75);
|
||||
|
||||
// Clamp the character size to make sure we won't create a texture too big
|
||||
if (nbChars * charSize >= maxSize)
|
||||
charSize = maxSize / nbChars;
|
||||
|
||||
// Initialize the dimensions
|
||||
unsigned int left = 0;
|
||||
unsigned int top = 0;
|
||||
unsigned int texWidth = Image::GetValidSize(charSize * nbChars);
|
||||
unsigned int texHeight = charSize * nbChars;
|
||||
std::vector<unsigned int> tops(texWidth, 0);
|
||||
|
||||
// Create a pixel buffer for rendering every glyph
|
||||
std::vector<Uint8> glyphsBuffer(texWidth * texHeight * 4);
|
||||
|
||||
// Load the font
|
||||
stbtt_fontinfo info;
|
||||
int success = stbtt_InitFont(&info, reinterpret_cast<const unsigned char*>(data), 0);
|
||||
if (!success)
|
||||
return false;
|
||||
|
||||
// Compute the global scale to apply to match the character size
|
||||
float scale = stbtt_ScaleForPixelHeight(&info, static_cast<float>(charSize));
|
||||
|
||||
// Render all glyphs and sort them by size to optimize texture space
|
||||
typedef std::multimap<Glyph, Uint32, SizeCompare> GlyphTable;
|
||||
GlyphTable glyphs;
|
||||
for (std::size_t i = 0; i < charset.GetSize(); ++i)
|
||||
{
|
||||
// Load the glyph corresponding to the current character
|
||||
int index = stbtt_FindGlyphIndex(&info, static_cast<int>(charset[i]));
|
||||
|
||||
// Extract the glyph parameters (bounding box, horizontal advance)
|
||||
Glyph glyph;
|
||||
stbtt_GetGlyphHMetrics(&info, index, &glyph.Advance, NULL);
|
||||
stbtt_GetGlyphBitmapBox(&info, index, scale, scale, &glyph.Rectangle.Left, &glyph.Rectangle.Top, &glyph.Rectangle.Right, &glyph.Rectangle.Bottom);
|
||||
|
||||
// Apply the global scale to the horizontal advance
|
||||
glyph.Advance = static_cast<int>(glyph.Advance * scale);
|
||||
|
||||
// Add it to the sorted table of glyphs
|
||||
glyphs.insert(std::make_pair(glyph, charset[i]));
|
||||
}
|
||||
|
||||
// Leave a small margin around characters, so that filtering doesn't
|
||||
// pollute them with pixels from neighbours
|
||||
unsigned int padding = 1;
|
||||
unsigned int margin = 1;
|
||||
|
||||
// Copy the rendered glyphs into the texture
|
||||
unsigned int maxHeight = 0;
|
||||
std::map<Uint32, IntRect> coords;
|
||||
for (GlyphTable::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i)
|
||||
{
|
||||
// Get the bitmap of the current glyph
|
||||
Glyph& curGlyph = font.myGlyphs[i->second];
|
||||
const Glyph& bitmapGlyph = i->first;
|
||||
const Vector2i& glyphSize = bitmapGlyph.Rectangle.GetSize();
|
||||
|
||||
// Make sure we don't go over the texture width
|
||||
if (left + glyphSize.x + 2 * padding + margin >= texWidth)
|
||||
left = 0;
|
||||
|
||||
// Compute the top coordinate
|
||||
top = tops[left];
|
||||
for (unsigned int x = 0; x < glyphSize.x + 2 * padding + margin; ++x)
|
||||
top = std::max(top, tops[left + x]);
|
||||
|
||||
// Make sure we don't go over the texture height -- resize it if we need more space
|
||||
if (top + glyphSize.x + 2 * padding + margin >= texHeight)
|
||||
{
|
||||
texHeight *= 2;
|
||||
glyphsBuffer.resize(texWidth * texHeight * 4);
|
||||
}
|
||||
|
||||
// Store the character's position and size
|
||||
curGlyph.Rectangle.Left = bitmapGlyph.Rectangle.Left - padding;
|
||||
curGlyph.Rectangle.Top = bitmapGlyph.Rectangle.Top - padding;
|
||||
curGlyph.Rectangle.Right = bitmapGlyph.Rectangle.Right + padding;
|
||||
curGlyph.Rectangle.Bottom = bitmapGlyph.Rectangle.Bottom + padding;
|
||||
curGlyph.Advance = bitmapGlyph.Advance;
|
||||
|
||||
// Texture size may change, so let the texture coordinates be calculated later
|
||||
coords[i->second] = IntRect(left, top, left + glyphSize.x + 2 * padding, top + glyphSize.y + 2 * padding);
|
||||
|
||||
// Draw the glyph into our bitmap font
|
||||
int width, height;
|
||||
unsigned char* bitmap = stbtt_GetCodepointBitmap(&info, scale, scale, i->second, &width, &height, NULL, NULL);
|
||||
unsigned char* pixels = bitmap;
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
std::size_t index = x + left + padding + (y + top + padding) * texWidth;
|
||||
glyphsBuffer[index * 4 + 0] = 255;
|
||||
glyphsBuffer[index * 4 + 1] = 255;
|
||||
glyphsBuffer[index * 4 + 2] = 255;
|
||||
glyphsBuffer[index * 4 + 3] = pixels[x];
|
||||
}
|
||||
pixels += width;
|
||||
}
|
||||
|
||||
// Update the rendering coordinates
|
||||
for (unsigned int x = 0; x < width + 2 * padding + margin; ++x)
|
||||
tops[left + x] = top + height + 2 * padding + margin;
|
||||
left += width + 2 * padding + margin;
|
||||
if (top + height + 2 * padding > maxHeight)
|
||||
maxHeight = top + height + 2 * padding;
|
||||
|
||||
// Delete the bitmap
|
||||
stbtt_FreeBitmap(bitmap, NULL);
|
||||
}
|
||||
|
||||
// Create the font's texture
|
||||
texHeight = maxHeight;
|
||||
glyphsBuffer.resize(texWidth * texHeight * 4);
|
||||
font.myTexture.LoadFromPixels(texWidth, texHeight, &glyphsBuffer[0]);
|
||||
|
||||
// Now that the texture is created, we can precompute texture coordinates
|
||||
for (std::size_t i = 0; i < charset.GetSize(); ++i)
|
||||
{
|
||||
Uint32 curChar = charset[i];
|
||||
font.myGlyphs[curChar].TexCoords = font.myTexture.GetTexCoords(coords[curChar]);
|
||||
}
|
||||
|
||||
// Update the character size (it may have been changed by the function)
|
||||
font.myCharSize = charSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Create a bitmap font from a font face and a characters set
|
||||
////////////////////////////////////////////////////////////
|
||||
FT_Error FontLoader::CreateBitmapFont(FT_Face face, unsigned int charSize, const String& charset, Font& font)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get a description from a FT error code
|
||||
////////////////////////////////////////////////////////////
|
||||
std::string FontLoader::GetErrorDesc(FT_Error error)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
#endif
|
@ -1,132 +0,0 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SFML - Simple and Fast Multimedia Library
|
||||
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented;
|
||||
// you must not claim that you wrote the original software.
|
||||
// If you use this software in a product, an acknowledgment
|
||||
// in the product documentation would be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such,
|
||||
// and must not be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SFML_FONTLOADER_HPP
|
||||
#define SFML_FONTLOADER_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
#include <SFML/System/String.hpp>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
class Font;
|
||||
|
||||
namespace priv
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
/// FontLoader loads and saves character fonts
|
||||
////////////////////////////////////////////////////////////
|
||||
class FontLoader : NonCopyable
|
||||
{
|
||||
public :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the unique instance of the class
|
||||
///
|
||||
/// \return Reference to the FontLoader instance
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static FontLoader& GetInstance();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Load a font from a file
|
||||
///
|
||||
/// \param filename : Path of the font file to load
|
||||
/// \param charSize : Size of characters in bitmap - the bigger, the higher quality
|
||||
/// \param charset : Characters set to generate
|
||||
/// \param font : Font object to fill up
|
||||
///
|
||||
/// \return True if loading was successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool LoadFontFromFile(const std::string& filename, unsigned int charSize, const String& charset, Font& font);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Load the font from a file in memory
|
||||
///
|
||||
/// \param data : Pointer to the data to load
|
||||
/// \param sizeInBytes : Size of the data, in bytes
|
||||
/// \param charSize : Size of characters in bitmap - the bigger, the higher quality
|
||||
/// \param charset : Characters set to generate
|
||||
/// \param font : Font object to fill up
|
||||
///
|
||||
/// \return True if loading was successful
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
bool LoadFontFromMemory(const char* data, std::size_t sizeInBytes, unsigned int charSize, const String& charset, Font& font);
|
||||
|
||||
private :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
FontLoader();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~FontLoader();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Create a bitmap font from a font face and a characters set
|
||||
///
|
||||
/// \param face : Font face containing the loaded font
|
||||
/// \param charSize : Size of characters in bitmap
|
||||
/// \param charset : Characters set to generate
|
||||
/// \param font : Font object to fill up
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
FT_Error CreateBitmapFont(FT_Face face, unsigned int charSize, const String& charset, Font& font);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get a description from a FT error code
|
||||
///
|
||||
/// \param error : FreeType error code
|
||||
///
|
||||
/// \return Error description
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static std::string GetErrorDesc(FT_Error error);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Member data
|
||||
////////////////////////////////////////////////////////////
|
||||
FT_Library myLibrary; ///< Handle to the Freetype library
|
||||
};
|
||||
|
||||
} // namespace priv
|
||||
|
||||
} // namespace sf
|
||||
|
||||
|
||||
#endif // SFML_FONTLOADER_HPP
|
@ -28,7 +28,6 @@
|
||||
#include <SFML/Graphics/RenderWindow.hpp>
|
||||
#include <SFML/Graphics/Drawable.hpp>
|
||||
#include <SFML/Graphics/Image.hpp>
|
||||
#include <SFML/Graphics/GLCheck.hpp>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
Text::Text() :
|
||||
myFont (&Font::GetDefaultFont()),
|
||||
mySize (30.f),
|
||||
myCharacterSize (30),
|
||||
myStyle (Regular),
|
||||
myNeedRectUpdate(true)
|
||||
{
|
||||
@ -48,9 +48,9 @@ myNeedRectUpdate(true)
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Construct the string from any kind of text
|
||||
////////////////////////////////////////////////////////////
|
||||
Text::Text(const String& string, const Font& font, float size) :
|
||||
Text::Text(const String& string, const Font& font, unsigned int characterSize) :
|
||||
myFont (&font),
|
||||
mySize (size),
|
||||
myCharacterSize (characterSize),
|
||||
myStyle (Regular),
|
||||
myNeedRectUpdate(true)
|
||||
{
|
||||
@ -82,14 +82,14 @@ void Text::SetFont(const Font& font)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Set the size of the string
|
||||
/// Set the base size for the characters.
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::SetSize(float size)
|
||||
void Text::SetCharacterSize(unsigned int size)
|
||||
{
|
||||
if (mySize != size)
|
||||
if (myCharacterSize != size)
|
||||
{
|
||||
myNeedRectUpdate = true;
|
||||
mySize = size;
|
||||
myCharacterSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,11 +127,11 @@ const Font& Text::GetFont() const
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// Get the size of the characters
|
||||
/// Get the base size of characters
|
||||
////////////////////////////////////////////////////////////
|
||||
float Text::GetSize() const
|
||||
unsigned int Text::GetCharacterSize() const
|
||||
{
|
||||
return mySize;
|
||||
return myCharacterSize;
|
||||
}
|
||||
|
||||
|
||||
@ -149,36 +149,42 @@ unsigned long Text::GetStyle() const
|
||||
/// in coordinates relative to the string
|
||||
/// (note : translation, center, rotation and scale are not applied)
|
||||
////////////////////////////////////////////////////////////
|
||||
sf::Vector2f Text::GetCharacterPos(std::size_t index) const
|
||||
Vector2f Text::GetCharacterPos(std::size_t index) const
|
||||
{
|
||||
// Make sure that we have a valid font
|
||||
if (!myFont)
|
||||
return Vector2f(0, 0);
|
||||
|
||||
// Adjust the index if it's out of range
|
||||
if (index > myString.GetSize())
|
||||
index = myString.GetSize();
|
||||
|
||||
// The final size is based on the text size
|
||||
float factor = mySize / myFont->GetCharacterSize();
|
||||
float advanceY = mySize;
|
||||
// We'll need this a lot
|
||||
float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize).Advance);
|
||||
|
||||
// Compute the position
|
||||
sf::Vector2f position;
|
||||
Uint32 prevChar = 0;
|
||||
float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize));
|
||||
for (std::size_t i = 0; i < index; ++i)
|
||||
{
|
||||
// Get the current character and its corresponding glyph
|
||||
Uint32 curChar = myString[i];
|
||||
const Glyph& curGlyph = myFont->GetGlyph(curChar);
|
||||
float advanceX = curGlyph.Advance * factor;
|
||||
|
||||
// Apply the kerning offset
|
||||
position.x += static_cast<float>(myFont->GetKerning(prevChar, curChar, myCharacterSize));
|
||||
prevChar = curChar;
|
||||
|
||||
// Handle special characters
|
||||
switch (curChar)
|
||||
{
|
||||
// Handle special characters
|
||||
case L' ' : position.x += advanceX; break;
|
||||
case L'\t' : position.x += advanceX * 4; break;
|
||||
case L'\v' : position.y += advanceY * 4; break;
|
||||
case L'\n' : position.y += advanceY; position.x = 0; break;
|
||||
|
||||
// Regular character : just add its advance value
|
||||
default : position.x += advanceX; break;
|
||||
case L' ' : position.x += space; continue;
|
||||
case L'\t' : position.x += space * 4; continue;
|
||||
case L'\v' : position.y += lineSpacing * 4; continue;
|
||||
case L'\n' : position.y += lineSpacing; position.x = 0; continue;
|
||||
}
|
||||
|
||||
// For regular characters, add the advance offset of the glyph
|
||||
position.x += static_cast<float>(myFont->GetGlyph(curChar, myCharacterSize).Advance);
|
||||
}
|
||||
|
||||
return position;
|
||||
@ -204,24 +210,22 @@ FloatRect Text::GetRect() const
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// /see sfDrawable::Render
|
||||
/// /see Drawable::Render
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::Render(RenderTarget&, RenderQueue& queue) const
|
||||
{
|
||||
// No text, no rendering :)
|
||||
if (myString.IsEmpty())
|
||||
// No text or not font: nothing to render
|
||||
if (!myFont || myString.IsEmpty())
|
||||
return;
|
||||
|
||||
// Set the scaling factor to get the actual size
|
||||
float charSize = static_cast<float>(myFont->GetCharacterSize());
|
||||
float factor = mySize / charSize;
|
||||
|
||||
// Bind the font texture
|
||||
queue.SetTexture(&myFont->GetImage());
|
||||
queue.SetTexture(&myFont->GetImage(myCharacterSize));
|
||||
|
||||
// Initialize the rendering coordinates
|
||||
float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize).Advance);
|
||||
float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize));
|
||||
float x = 0.f;
|
||||
float y = charSize;
|
||||
float y = static_cast<float>(myCharacterSize);
|
||||
|
||||
// Holds the lines to draw later, for underlined style
|
||||
std::vector<float> underlineCoords;
|
||||
@ -232,15 +236,15 @@ void Text::Render(RenderTarget&, RenderQueue& queue) const
|
||||
|
||||
// Draw one quad for each character
|
||||
unsigned int index = 0;
|
||||
Uint32 prevChar = 0;
|
||||
queue.BeginBatch();
|
||||
for (std::size_t i = 0; i < myString.GetSize(); ++i)
|
||||
{
|
||||
// Get the current character and its corresponding glyph
|
||||
Uint32 curChar = myString[i];
|
||||
const Glyph& curGlyph = myFont->GetGlyph(curChar);
|
||||
int advance = curGlyph.Advance;
|
||||
const IntRect& rect = curGlyph.Rectangle;
|
||||
const FloatRect& coord = curGlyph.TexCoords;
|
||||
|
||||
// Apply the kerning offset
|
||||
x += static_cast<float>(myFont->GetKerning(prevChar, curChar, myCharacterSize));
|
||||
prevChar = curChar;
|
||||
|
||||
// If we're using the underlined style and there's a new line,
|
||||
// we keep track of the previous line to draw it later
|
||||
@ -253,17 +257,23 @@ void Text::Render(RenderTarget&, RenderQueue& queue) const
|
||||
// Handle special characters
|
||||
switch (curChar)
|
||||
{
|
||||
case L' ' : x += advance; continue;
|
||||
case L'\n' : y += charSize; x = 0; continue;
|
||||
case L'\t' : x += advance * 4; continue;
|
||||
case L'\v' : y += charSize * 4; continue;
|
||||
case L' ' : x += space; continue;
|
||||
case L'\t' : x += space * 4; continue;
|
||||
case L'\n' : y += lineSpacing; x = 0; continue;
|
||||
case L'\v' : y += lineSpacing * 4; continue;
|
||||
}
|
||||
|
||||
// Extract the current glyph's description
|
||||
const Glyph& curGlyph = myFont->GetGlyph(curChar, myCharacterSize);
|
||||
int advance = curGlyph.Advance;
|
||||
const IntRect& rect = curGlyph.Rectangle;
|
||||
const FloatRect& coord = curGlyph.TexCoords;
|
||||
|
||||
// Draw a textured quad for the current character
|
||||
queue.AddVertex(factor * (x + rect.Left - italicCoeff * rect.Top), factor * (y + rect.Top), coord.Left, coord.Top);
|
||||
queue.AddVertex(factor * (x + rect.Left - italicCoeff * rect.Bottom), factor * (y + rect.Bottom), coord.Left, coord.Bottom);
|
||||
queue.AddVertex(factor * (x + rect.Right - italicCoeff * rect.Bottom), factor * (y + rect.Bottom), coord.Right, coord.Bottom);
|
||||
queue.AddVertex(factor * (x + rect.Right - italicCoeff * rect.Top), factor * (y + rect.Top), coord.Right, coord.Top);
|
||||
queue.AddVertex(x + rect.Left - italicCoeff * rect.Top, y + rect.Top, coord.Left, coord.Top);
|
||||
queue.AddVertex(x + rect.Left - italicCoeff * rect.Bottom, y + rect.Bottom, coord.Left, coord.Bottom);
|
||||
queue.AddVertex(x + rect.Right - italicCoeff * rect.Bottom, y + rect.Bottom, coord.Right, coord.Bottom);
|
||||
queue.AddVertex(x + rect.Right - italicCoeff * rect.Top, y + rect.Top, coord.Right, coord.Top);
|
||||
|
||||
queue.AddTriangle(index + 0, index + 1, index + 3);
|
||||
queue.AddTriangle(index + 3, index + 1, index + 2);
|
||||
@ -277,7 +287,7 @@ void Text::Render(RenderTarget&, RenderQueue& queue) const
|
||||
// slightly offseted, to simulate a higher weight
|
||||
if (myStyle & Bold)
|
||||
{
|
||||
float offset = mySize * 0.02f;
|
||||
float offset = myCharacterSize * 0.02f;
|
||||
static const float offsetsX[] = {-offset, offset, 0.f, 0.f};
|
||||
static const float offsetsY[] = {0.f, 0.f, -offset, offset};
|
||||
|
||||
@ -285,32 +295,38 @@ void Text::Render(RenderTarget&, RenderQueue& queue) const
|
||||
{
|
||||
index = 0;
|
||||
x = 0.f;
|
||||
y = charSize;
|
||||
y = static_cast<float>(myCharacterSize);
|
||||
|
||||
Uint32 prevChar = 0;
|
||||
queue.BeginBatch();
|
||||
for (std::size_t i = 0; i < myString.GetSize(); ++i)
|
||||
{
|
||||
// Get the current character and its corresponding glyph
|
||||
Uint32 curChar = myString[i];
|
||||
const Glyph& curGlyph = myFont->GetGlyph(curChar);
|
||||
int advance = curGlyph.Advance;
|
||||
const IntRect& rect = curGlyph.Rectangle;
|
||||
const FloatRect& coord = curGlyph.TexCoords;
|
||||
|
||||
// Apply the kerning offset
|
||||
x += static_cast<float>(myFont->GetKerning(prevChar, curChar, myCharacterSize));
|
||||
prevChar = curChar;
|
||||
|
||||
// Handle special characters
|
||||
switch (curChar)
|
||||
{
|
||||
case L' ' : x += advance; continue;
|
||||
case L'\n' : y += charSize; x = 0; continue;
|
||||
case L'\t' : x += advance * 4; continue;
|
||||
case L'\v' : y += charSize * 4; continue;
|
||||
case L' ' : x += space; continue;
|
||||
case L'\t' : x += space * 4; continue;
|
||||
case L'\n' : y += lineSpacing; x = 0; continue;
|
||||
case L'\v' : y += lineSpacing * 4; continue;
|
||||
}
|
||||
|
||||
// Extract the current glyph's description
|
||||
const Glyph& curGlyph = myFont->GetGlyph(curChar, myCharacterSize);
|
||||
int advance = curGlyph.Advance;
|
||||
const IntRect& rect = curGlyph.Rectangle;
|
||||
const FloatRect& coord = curGlyph.TexCoords;
|
||||
|
||||
// Draw a textured quad for the current character
|
||||
queue.AddVertex(factor * (x + offsetsX[j] + rect.Left - italicCoeff * rect.Top), factor * (y + offsetsY[j] + rect.Top), coord.Left, coord.Top);
|
||||
queue.AddVertex(factor * (x + offsetsX[j] + rect.Left - italicCoeff * rect.Bottom), factor * (y + offsetsY[j] + rect.Bottom), coord.Left, coord.Bottom);
|
||||
queue.AddVertex(factor * (x + offsetsX[j] + rect.Right - italicCoeff * rect.Bottom), factor * (y + offsetsY[j] + rect.Bottom), coord.Right, coord.Bottom);
|
||||
queue.AddVertex(factor * (x + offsetsX[j] + rect.Right - italicCoeff * rect.Top), factor * (y + offsetsY[j] + rect.Top), coord.Right, coord.Top);
|
||||
queue.AddVertex(x + offsetsX[j] + rect.Left - italicCoeff * rect.Top, y + offsetsY[j] + rect.Top, coord.Left, coord.Top);
|
||||
queue.AddVertex(x + offsetsX[j] + rect.Left - italicCoeff * rect.Bottom, y + offsetsY[j] + rect.Bottom, coord.Left, coord.Bottom);
|
||||
queue.AddVertex(x + offsetsX[j] + rect.Right - italicCoeff * rect.Bottom, y + offsetsY[j] + rect.Bottom, coord.Right, coord.Bottom);
|
||||
queue.AddVertex(x + offsetsX[j] + rect.Right - italicCoeff * rect.Top, y + offsetsY[j] + rect.Top, coord.Right, coord.Top);
|
||||
|
||||
queue.AddTriangle(index + 0, index + 1, index + 3);
|
||||
queue.AddTriangle(index + 3, index + 1, index + 2);
|
||||
@ -338,10 +354,10 @@ void Text::Render(RenderTarget&, RenderQueue& queue) const
|
||||
queue.BeginBatch();
|
||||
for (std::size_t i = 0; i < underlineCoords.size(); i += 2)
|
||||
{
|
||||
queue.AddVertex(factor * (0), factor * (underlineCoords[i + 1]));
|
||||
queue.AddVertex(factor * (0), factor * (underlineCoords[i + 1] + thickness));
|
||||
queue.AddVertex(factor * (underlineCoords[i]), factor * (underlineCoords[i + 1] + thickness));
|
||||
queue.AddVertex(factor * (underlineCoords[i]), factor * (underlineCoords[i + 1]));
|
||||
queue.AddVertex(0, underlineCoords[i + 1]);
|
||||
queue.AddVertex(0, underlineCoords[i + 1] + thickness);
|
||||
queue.AddVertex(underlineCoords[i], underlineCoords[i + 1] + thickness);
|
||||
queue.AddVertex(underlineCoords[i], underlineCoords[i + 1]);
|
||||
|
||||
queue.AddTriangle(index + 0, index + 1, index + 3);
|
||||
queue.AddTriangle(index + 3, index + 1, index + 2);
|
||||
@ -356,41 +372,51 @@ void Text::Render(RenderTarget&, RenderQueue& queue) const
|
||||
////////////////////////////////////////////////////////////
|
||||
void Text::RecomputeRect()
|
||||
{
|
||||
// Reset the "need update" state
|
||||
// Reset the previous states
|
||||
myNeedRectUpdate = false;
|
||||
|
||||
// No text, empty box :)
|
||||
if (myString.IsEmpty())
|
||||
{
|
||||
myBaseRect = FloatRect(0, 0, 0, 0);
|
||||
|
||||
// No text or not font: empty box
|
||||
if (!myFont || myString.IsEmpty())
|
||||
return;
|
||||
}
|
||||
|
||||
// Initial values
|
||||
float charSize = static_cast<float>(myCharacterSize);
|
||||
float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize).Advance);
|
||||
float lineSpacing = static_cast<float>(myFont->GetLineSpacing(myCharacterSize));
|
||||
float curWidth = 0;
|
||||
float curHeight = 0;
|
||||
float width = 0;
|
||||
float height = 0;
|
||||
float factor = mySize / myFont->GetCharacterSize();
|
||||
Uint32 prevChar = 0;
|
||||
|
||||
// Go through each character
|
||||
for (std::size_t i = 0; i < myString.GetSize(); ++i)
|
||||
{
|
||||
// Get the current character and its corresponding glyph
|
||||
Uint32 curChar = myString[i];
|
||||
const Glyph& curGlyph = myFont->GetGlyph(curChar);
|
||||
float advance = curGlyph.Advance * factor;
|
||||
const IntRect& rect = curGlyph.Rectangle;
|
||||
|
||||
// Apply the kerning offset
|
||||
curWidth += static_cast<float>(myFont->GetKerning(prevChar, curChar, myCharacterSize));
|
||||
prevChar = curChar;
|
||||
|
||||
// Handle special characters
|
||||
switch (curChar)
|
||||
{
|
||||
case L' ' : curWidth += advance; continue;
|
||||
case L'\t' : curWidth += advance * 4; continue;
|
||||
case L'\v' : height += mySize * 4; curHeight = 0; continue;
|
||||
case L' ' :
|
||||
curWidth += space;
|
||||
continue;
|
||||
|
||||
case L'\t' :
|
||||
curWidth += space * 4;
|
||||
continue;
|
||||
|
||||
case L'\v' :
|
||||
height += lineSpacing * 4;
|
||||
curHeight = 0;
|
||||
continue;
|
||||
|
||||
case L'\n' :
|
||||
height += mySize;
|
||||
height += lineSpacing;
|
||||
curHeight = 0;
|
||||
if (curWidth > width)
|
||||
width = curWidth;
|
||||
@ -398,11 +424,14 @@ void Text::RecomputeRect()
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract the current glyph's description
|
||||
const Glyph& curGlyph = myFont->GetGlyph(curChar, myCharacterSize);
|
||||
|
||||
// Advance to the next character
|
||||
curWidth += advance;
|
||||
curWidth += static_cast<float>(curGlyph.Advance);
|
||||
|
||||
// Update the maximum height
|
||||
float charHeight = (myFont->GetCharacterSize() + rect.Bottom) * factor;
|
||||
float charHeight = charSize + curGlyph.Rectangle.Bottom;
|
||||
if (charHeight > curHeight)
|
||||
curHeight = charHeight;
|
||||
}
|
||||
@ -415,21 +444,21 @@ void Text::RecomputeRect()
|
||||
// Add a slight width / height if we're using the bold style
|
||||
if (myStyle & Bold)
|
||||
{
|
||||
width += 1 * factor;
|
||||
height += 1 * factor;
|
||||
width += 1.f;
|
||||
height += 1.f;
|
||||
}
|
||||
|
||||
// Add a slight width if we're using the italic style
|
||||
if (myStyle & Italic)
|
||||
{
|
||||
width += 0.208f * mySize;
|
||||
width += 0.208f * charSize;
|
||||
}
|
||||
|
||||
// Add a slight height if we're using the underlined style
|
||||
if (myStyle & Underlined)
|
||||
{
|
||||
if (curHeight < mySize + 4 * factor)
|
||||
height += 4 * factor;
|
||||
if (curHeight < charSize + 4.f)
|
||||
height += 4.f;
|
||||
}
|
||||
|
||||
// Finally update the rectangle
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -244,10 +244,6 @@ Socket::Status SocketUDP::Send(Packet& packet, const IPAddress& address, unsigne
|
||||
////////////////////////////////////////////////////////////
|
||||
Socket::Status SocketUDP::Receive(Packet& packet, IPAddress& address, unsigned short& port)
|
||||
{
|
||||
// This is not safe at all, as data can be lost, duplicated, or arrive in a different order.
|
||||
// So if a packet is split into more than one chunk, nobody knows what could happen...
|
||||
// Conclusion : we shouldn't use packets with UDP, unless we build a more complex protocol on top of it.
|
||||
|
||||
// We start by getting the size of the incoming packet
|
||||
Uint32 packetSize = 0;
|
||||
std::size_t received = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user