Changed the internal storage of pixels in sf::Image (vector<Color> --> vector<Uint8>)
Changed the Glyph structure to allow using sprites to display glyphs git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1473 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
parent
dcdf39bf74
commit
6b23d15a14
@ -36,9 +36,9 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int Advance; ///< Offset to move horizontically to the next character
|
int Advance; ///< Offset to move horizontically to the next character
|
||||||
sfIntRect Rectangle; ///< Bounding rectangle of the glyph, in relative coordinates
|
sfIntRect Bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline
|
||||||
sfFloatRect TexCoords; ///< Texture coordinates of the glyph inside the bitmap font
|
sfIntRect SubRect; ///< Texture coordinates of the glyph inside the font's image
|
||||||
} sfGlyph;
|
} sfGlyph;
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,15 +92,15 @@ sfGlyph sfFont_GetGlyph(sfFont* font, sfUint32 codePoint, unsigned int character
|
|||||||
|
|
||||||
sf::Glyph SFMLGlyph = font->This.GetGlyph(codePoint, characterSize, bold == sfTrue);
|
sf::Glyph SFMLGlyph = font->This.GetGlyph(codePoint, characterSize, bold == sfTrue);
|
||||||
|
|
||||||
glyph.Advance = SFMLGlyph.Advance;
|
glyph.Advance = SFMLGlyph.Advance;
|
||||||
glyph.Rectangle.Left = SFMLGlyph.Rectangle.Left;
|
glyph.Bounds.Left = SFMLGlyph.Bounds.Left;
|
||||||
glyph.Rectangle.Top = SFMLGlyph.Rectangle.Top;
|
glyph.Bounds.Top = SFMLGlyph.Bounds.Top;
|
||||||
glyph.Rectangle.Right = SFMLGlyph.Rectangle.Right;
|
glyph.Bounds.Right = SFMLGlyph.Bounds.Right;
|
||||||
glyph.Rectangle.Bottom = SFMLGlyph.Rectangle.Bottom;
|
glyph.Bounds.Bottom = SFMLGlyph.Bounds.Bottom;
|
||||||
glyph.TexCoords.Left = SFMLGlyph.TexCoords.Left;
|
glyph.SubRect.Left = SFMLGlyph.SubRect.Left;
|
||||||
glyph.TexCoords.Top = SFMLGlyph.TexCoords.Top;
|
glyph.SubRect.Top = SFMLGlyph.SubRect.Top;
|
||||||
glyph.TexCoords.Right = SFMLGlyph.TexCoords.Right;
|
glyph.SubRect.Right = SFMLGlyph.SubRect.Right;
|
||||||
glyph.TexCoords.Bottom = SFMLGlyph.TexCoords.Bottom;
|
glyph.SubRect.Bottom = SFMLGlyph.SubRect.Bottom;
|
||||||
|
|
||||||
return glyph;
|
return glyph;
|
||||||
}
|
}
|
||||||
|
@ -193,17 +193,6 @@ public :
|
|||||||
|
|
||||||
private :
|
private :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Structure storing a glyph together with its
|
|
||||||
/// rectangle in the texture
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
struct GlyphInfo
|
|
||||||
{
|
|
||||||
Glyph GlyphDesc;
|
|
||||||
IntRect TextureRect;
|
|
||||||
};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Structure defining a row of glyphs
|
/// \brief Structure defining a row of glyphs
|
||||||
///
|
///
|
||||||
@ -220,7 +209,7 @@ private :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Types
|
// Types
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
typedef std::map<Uint32, GlyphInfo> GlyphTable; ///< Table mapping a codepoint to its glyph
|
typedef std::map<Uint32, Glyph> GlyphTable; ///< Table mapping a codepoint to its glyph
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Structure defining a page if glyphs
|
/// \brief Structure defining a page if glyphs
|
||||||
@ -252,7 +241,7 @@ private :
|
|||||||
/// \return The glyph corresponding to \a codePoint and \a characterSize
|
/// \return The glyph corresponding to \a codePoint and \a characterSize
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
GlyphInfo LoadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const;
|
Glyph LoadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Find a suitable rectangle within the texture for a glyph
|
/// \brief Find a suitable rectangle within the texture for a glyph
|
||||||
|
@ -50,9 +50,9 @@ public :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
int Advance; ///< Offset to move horizontically to the next character
|
int Advance; ///< Offset to move horizontically to the next character
|
||||||
IntRect Rectangle; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline
|
IntRect Bounds; ///< Bounding rectangle of the glyph, in coordinates relative to the baseline
|
||||||
FloatRect TexCoords; ///< Texture coordinates of the glyph inside the font's image
|
IntRect SubRect; ///< Texture coordinates of the glyph inside the font's image
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -127,11 +127,11 @@ public :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Create transparency mask from a specified colorkey
|
/// Create transparency mask from a specified colorkey
|
||||||
///
|
///
|
||||||
/// \param transparentColor : Color to become transparent
|
/// \param color : Color to become transparent
|
||||||
/// \param alpha : Alpha value to assign to transparent pixels
|
/// \param alpha : Alpha value to assign to transparent pixels
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void CreateMaskFromColor(const Color& transparentColor, Uint8 alpha = 0);
|
void CreateMaskFromColor(const Color& color, Uint8 alpha = 0);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Copy pixels from another image onto this one.
|
/// Copy pixels from another image onto this one.
|
||||||
@ -178,7 +178,7 @@ public :
|
|||||||
/// \return Color of pixel (x, y)
|
/// \return Color of pixel (x, y)
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const Color& GetPixel(unsigned int x, unsigned int y) const;
|
Color GetPixel(unsigned int x, unsigned int y) const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get a read-only pointer to the array of pixels (RGBA 8 bits integers components)
|
/// Get a read-only pointer to the array of pixels (RGBA 8 bits integers components)
|
||||||
@ -338,7 +338,7 @@ private :
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Types
|
// Types
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
typedef std::vector<Color> ColorArray; ///< Array of colors
|
typedef std::vector<Uint8> ColorArray; ///< Array of colors
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
|
@ -165,13 +165,13 @@ const Glyph& Font::GetGlyph(Uint32 codePoint, unsigned int characterSize, bool b
|
|||||||
if (it != glyphs.end())
|
if (it != glyphs.end())
|
||||||
{
|
{
|
||||||
// Found: just return it
|
// Found: just return it
|
||||||
return it->second.GlyphDesc;
|
return it->second;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Not found: we have to load it
|
// Not found: we have to load it
|
||||||
GlyphInfo glyph = LoadGlyph(codePoint, characterSize, bold);
|
Glyph glyph = LoadGlyph(codePoint, characterSize, bold);
|
||||||
return glyphs.insert(std::make_pair(key, glyph)).first->second.GlyphDesc;
|
return glyphs.insert(std::make_pair(key, glyph)).first->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,28 +303,28 @@ void Font::Cleanup()
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Font::GlyphInfo Font::LoadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const
|
Glyph Font::LoadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const
|
||||||
{
|
{
|
||||||
// The glyph to return
|
// The glyph to return
|
||||||
GlyphInfo glyphInfo;
|
Glyph glyph;
|
||||||
|
|
||||||
// First, transform our ugly void* to a FT_Face
|
// First, transform our ugly void* to a FT_Face
|
||||||
FT_Face face = static_cast<FT_Face>(myFace);
|
FT_Face face = static_cast<FT_Face>(myFace);
|
||||||
if (!face)
|
if (!face)
|
||||||
return glyphInfo;
|
return glyph;
|
||||||
|
|
||||||
// Set the character size
|
// Set the character size
|
||||||
if (!SetCurrentSize(characterSize))
|
if (!SetCurrentSize(characterSize))
|
||||||
return glyphInfo;
|
return glyph;
|
||||||
|
|
||||||
// Load the glyph corresponding to the code point
|
// Load the glyph corresponding to the code point
|
||||||
if (FT_Load_Char(face, codePoint, FT_LOAD_TARGET_NORMAL) != 0)
|
if (FT_Load_Char(face, codePoint, FT_LOAD_TARGET_NORMAL) != 0)
|
||||||
return glyphInfo;
|
return glyph;
|
||||||
|
|
||||||
// Retrieve the glyph
|
// Retrieve the glyph
|
||||||
FT_Glyph glyphDesc;
|
FT_Glyph glyphDesc;
|
||||||
if (FT_Get_Glyph(face->glyph, &glyphDesc) != 0)
|
if (FT_Get_Glyph(face->glyph, &glyphDesc) != 0)
|
||||||
return glyphInfo;
|
return glyph;
|
||||||
|
|
||||||
// Apply bold if necessary -- first technique using outline (highest quality)
|
// Apply bold if necessary -- first technique using outline (highest quality)
|
||||||
FT_Pos weight = 1 << 6;
|
FT_Pos weight = 1 << 6;
|
||||||
@ -347,9 +347,9 @@ Font::GlyphInfo Font::LoadGlyph(Uint32 codePoint, unsigned int characterSize, bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute the glyph's advance offset
|
// Compute the glyph's advance offset
|
||||||
glyphInfo.GlyphDesc.Advance = glyphDesc->advance.x >> 16;
|
glyph.Advance = glyphDesc->advance.x >> 16;
|
||||||
if (bold)
|
if (bold)
|
||||||
glyphInfo.GlyphDesc.Advance += weight >> 6;
|
glyph.Advance += weight >> 6;
|
||||||
|
|
||||||
int width = bitmap.width;
|
int width = bitmap.width;
|
||||||
int height = bitmap.rows;
|
int height = bitmap.rows;
|
||||||
@ -363,14 +363,13 @@ Font::GlyphInfo Font::LoadGlyph(Uint32 codePoint, unsigned int characterSize, bo
|
|||||||
Page& page = myPages[characterSize];
|
Page& page = myPages[characterSize];
|
||||||
|
|
||||||
// Find a good position for the new glyph into the texture
|
// Find a good position for the new glyph into the texture
|
||||||
glyphInfo.TextureRect = FindGlyphRect(page, width + 2 * padding, height + 2 * padding);
|
glyph.SubRect = FindGlyphRect(page, width + 2 * padding, height + 2 * padding);
|
||||||
|
|
||||||
// Compute the glyph's texture coordinates and bounding box
|
// Compute the glyph's bounding box
|
||||||
glyphInfo.GlyphDesc.TexCoords = page.Texture.GetTexCoords(glyphInfo.TextureRect);
|
glyph.Bounds.Left = bitmapGlyph->left - padding;
|
||||||
glyphInfo.GlyphDesc.Rectangle.Left = bitmapGlyph->left - padding;
|
glyph.Bounds.Top = -bitmapGlyph->top - padding;
|
||||||
glyphInfo.GlyphDesc.Rectangle.Top = -bitmapGlyph->top - padding;
|
glyph.Bounds.Right = bitmapGlyph->left + width + padding;
|
||||||
glyphInfo.GlyphDesc.Rectangle.Right = bitmapGlyph->left + width + padding;
|
glyph.Bounds.Bottom = -bitmapGlyph->top + height + padding;
|
||||||
glyphInfo.GlyphDesc.Rectangle.Bottom = -bitmapGlyph->top + height + padding;
|
|
||||||
|
|
||||||
// Extract the glyph's pixels from the bitmap
|
// Extract the glyph's pixels from the bitmap
|
||||||
myPixelBuffer.resize(width * height * 4, 255);
|
myPixelBuffer.resize(width * height * 4, 255);
|
||||||
@ -390,7 +389,7 @@ Font::GlyphInfo Font::LoadGlyph(Uint32 codePoint, unsigned int characterSize, bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write the pixels to the texture
|
// Write the pixels to the texture
|
||||||
IntRect subrect = glyphInfo.TextureRect;
|
IntRect subrect = glyph.SubRect;
|
||||||
subrect.Left += padding;
|
subrect.Left += padding;
|
||||||
subrect.Top += padding;
|
subrect.Top += padding;
|
||||||
subrect.Right -= padding;
|
subrect.Right -= padding;
|
||||||
@ -402,7 +401,7 @@ Font::GlyphInfo Font::LoadGlyph(Uint32 codePoint, unsigned int characterSize, bo
|
|||||||
FT_Done_Glyph(glyphDesc);
|
FT_Done_Glyph(glyphDesc);
|
||||||
|
|
||||||
// Done :)
|
// Done :)
|
||||||
return glyphInfo;
|
return glyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -450,12 +449,6 @@ IntRect Font::FindGlyphRect(Page& page, unsigned int width, unsigned int height)
|
|||||||
memcpy(&pixels[0], page.Texture.GetPixelsPtr(), size);
|
memcpy(&pixels[0], page.Texture.GetPixelsPtr(), size);
|
||||||
page.Texture.Create(textureWidth * 2, textureHeight * 2, Color(255, 255, 255, 0));
|
page.Texture.Create(textureWidth * 2, textureHeight * 2, Color(255, 255, 255, 0));
|
||||||
page.Texture.UpdatePixels(&pixels[0], IntRect(0, 0, textureWidth, textureHeight));
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -154,8 +154,8 @@ bool Image::LoadFromPixels(unsigned int width, unsigned int height, const Uint8*
|
|||||||
myHeight = height;
|
myHeight = height;
|
||||||
|
|
||||||
// Fill the pixel buffer with the specified raw data
|
// Fill the pixel buffer with the specified raw data
|
||||||
const Color* ptr = reinterpret_cast<const Color*>(data);
|
myPixels.resize(width * height * 4);
|
||||||
myPixels.assign(ptr, ptr + width * height);
|
memcpy(&myPixels[0], data, myPixels.size());
|
||||||
|
|
||||||
// We can create the texture
|
// We can create the texture
|
||||||
if (CreateTexture())
|
if (CreateTexture())
|
||||||
@ -199,9 +199,19 @@ bool Image::Create(unsigned int width, unsigned int height, const Color& color)
|
|||||||
myWidth = width;
|
myWidth = width;
|
||||||
myHeight = height;
|
myHeight = height;
|
||||||
|
|
||||||
// Recreate the pixel buffer and fill it with the specified color
|
// Resize the pixel buffer
|
||||||
myPixels.clear();
|
myPixels.resize(myWidth * myHeight * 4);
|
||||||
myPixels.resize(width * height, color);
|
|
||||||
|
// Fill it with the specified color
|
||||||
|
Uint8* p = &myPixels[0];
|
||||||
|
Uint8* end = p + myWidth * myHeight * 4;
|
||||||
|
while (p < end)
|
||||||
|
{
|
||||||
|
*p++ = color.r;
|
||||||
|
*p++ = color.g;
|
||||||
|
*p++ = color.b;
|
||||||
|
*p++ = color.a;
|
||||||
|
}
|
||||||
|
|
||||||
// We can create the texture
|
// We can create the texture
|
||||||
if (CreateTexture())
|
if (CreateTexture())
|
||||||
@ -220,16 +230,24 @@ bool Image::Create(unsigned int width, unsigned int height, const Color& color)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Create transparency mask from a specified colorkey
|
/// Create transparency mask from a specified colorkey
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Image::CreateMaskFromColor(const Color& transparentColor, Uint8 alpha)
|
void Image::CreateMaskFromColor(const Color& color, Uint8 alpha)
|
||||||
{
|
{
|
||||||
|
// No pixels to replace
|
||||||
|
if (myPixels.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
// Check if the array of pixels needs to be updated
|
// Check if the array of pixels needs to be updated
|
||||||
EnsureArrayUpdate();
|
EnsureArrayUpdate();
|
||||||
|
|
||||||
// Calculate the new color (old color with no alpha)
|
// Replace the alpha of the pixels that match the transparent color
|
||||||
Color newColor(transparentColor.r, transparentColor.g, transparentColor.b, alpha);
|
Uint8* p = &myPixels[0];
|
||||||
|
Uint8* end = p + myWidth * myHeight * 4;
|
||||||
// Replace the old color with the new one
|
while (p < end)
|
||||||
std::replace(myPixels.begin(), myPixels.end(), transparentColor, newColor);
|
{
|
||||||
|
if ((p[0] == color.r) && (p[1] == color.g) && (p[2] == color.b) && (p[3] == color.a))
|
||||||
|
p[3] = alpha;
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
|
||||||
// The texture will need to be updated
|
// The texture will need to be updated
|
||||||
myTextureUpdated = false;
|
myTextureUpdated = false;
|
||||||
@ -283,8 +301,8 @@ void Image::Copy(const Image& source, unsigned int destX, unsigned int destY, co
|
|||||||
int rows = height;
|
int rows = height;
|
||||||
int srcStride = source.myWidth * 4;
|
int srcStride = source.myWidth * 4;
|
||||||
int dstStride = myWidth * 4;
|
int dstStride = myWidth * 4;
|
||||||
const Uint8* srcPixels = source.GetPixelsPtr() + (srcRect.Left + srcRect.Top * source.myWidth) * 4;
|
const Uint8* srcPixels = &source.myPixels[0] + (srcRect.Left + srcRect.Top * source.myWidth) * 4;
|
||||||
Uint8* dstPixels = reinterpret_cast<Uint8*>(&myPixels[0]) + (destX + destY * myWidth) * 4;
|
Uint8* dstPixels = &myPixels[0] + (destX + destY * myWidth) * 4;
|
||||||
|
|
||||||
// Copy the pixels
|
// Copy the pixels
|
||||||
if (applyAlpha)
|
if (applyAlpha)
|
||||||
@ -386,15 +404,12 @@ void Image::SetPixel(unsigned int x, unsigned int y, const Color& color)
|
|||||||
// First check if the array of pixels needs to be updated
|
// First check if the array of pixels needs to be updated
|
||||||
EnsureArrayUpdate();
|
EnsureArrayUpdate();
|
||||||
|
|
||||||
// Check if pixel is whithin the image bounds
|
// Copy the color components
|
||||||
/*if ((x >= myWidth) || (y >= myHeight))
|
Uint8* pixel = &myPixels[(x + y * myWidth) * 4];
|
||||||
{
|
*pixel++ = color.r;
|
||||||
Err() << "Cannot set pixel (" << x << "," << y << ") for image "
|
*pixel++ = color.g;
|
||||||
<< "(width = " << myWidth << ", height = " << myHeight << ")" << std::endl;
|
*pixel++ = color.b;
|
||||||
return;
|
*pixel++ = color.a;
|
||||||
}*/
|
|
||||||
|
|
||||||
myPixels[x + y * myWidth] = color;
|
|
||||||
|
|
||||||
// The texture will need to be updated
|
// The texture will need to be updated
|
||||||
myTextureUpdated = false;
|
myTextureUpdated = false;
|
||||||
@ -404,20 +419,15 @@ void Image::SetPixel(unsigned int x, unsigned int y, const Color& color)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get a pixel from the image
|
/// Get a pixel from the image
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
const Color& Image::GetPixel(unsigned int x, unsigned int y) const
|
Color Image::GetPixel(unsigned int x, unsigned int y) const
|
||||||
{
|
{
|
||||||
// First check if the array of pixels needs to be updated
|
// First check if the array of pixels needs to be updated
|
||||||
EnsureArrayUpdate();
|
EnsureArrayUpdate();
|
||||||
|
|
||||||
// Check if pixel is whithin the image bounds
|
// Get the color at (x, y)
|
||||||
if ((x >= myWidth) || (y >= myHeight))
|
const Uint8* pixel = &myPixels[(x + y * myWidth) * 4];
|
||||||
{
|
|
||||||
Err() << "Cannot get pixel (" << x << "," << y << ") for image "
|
|
||||||
<< "(width = " << myWidth << ", height = " << myHeight << ")" << std::endl;
|
|
||||||
return Color::Black;
|
|
||||||
}
|
|
||||||
|
|
||||||
return myPixels[x + y * myWidth];
|
return Color(pixel[0], pixel[1], pixel[2], pixel[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -433,7 +443,7 @@ const Uint8* Image::GetPixelsPtr() const
|
|||||||
|
|
||||||
if (!myPixels.empty())
|
if (!myPixels.empty())
|
||||||
{
|
{
|
||||||
return reinterpret_cast<const Uint8*>(&myPixels[0]);
|
return &myPixels[0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -728,7 +738,7 @@ void Image::EnsureArrayUpdate() const
|
|||||||
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
|
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
|
||||||
|
|
||||||
// Resize the destination array of pixels
|
// Resize the destination array of pixels
|
||||||
myPixels.resize(myWidth * myHeight);
|
myPixels.resize(myWidth * myHeight * 4);
|
||||||
|
|
||||||
if ((myWidth == myTextureWidth) && (myHeight == myTextureHeight) && !myPixelsFlipped)
|
if ((myWidth == myTextureWidth) && (myHeight == myTextureHeight) && !myPixelsFlipped)
|
||||||
{
|
{
|
||||||
@ -743,27 +753,28 @@ void Image::EnsureArrayUpdate() const
|
|||||||
// Texture and array don't have the same size, we have to use a slower algorithm
|
// Texture and array don't have the same size, we have to use a slower algorithm
|
||||||
|
|
||||||
// All the pixels will first be copied to a temporary array
|
// All the pixels will first be copied to a temporary array
|
||||||
ColorArray allPixels(myTextureWidth * myTextureHeight);
|
ColorArray allPixels(myTextureWidth * myTextureHeight * 4);
|
||||||
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
|
GLCheck(glBindTexture(GL_TEXTURE_2D, myTexture));
|
||||||
GLCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &allPixels[0]));
|
GLCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &allPixels[0]));
|
||||||
|
|
||||||
// Then we copy the useful pixels from the temporary array to the final one
|
// Then we copy the useful pixels from the temporary array to the final one
|
||||||
const Color* src = &allPixels[0];
|
const Uint8* src = &allPixels[0];
|
||||||
Color* dst = &myPixels[0];
|
Uint8* dst = &myPixels[0];
|
||||||
int srcPitch = myTextureWidth;
|
int srcPitch = myTextureWidth * 4;
|
||||||
|
int dstPitch = myWidth * 4;
|
||||||
|
|
||||||
// Handle the case where source pixels are flipped vertically
|
// Handle the case where source pixels are flipped vertically
|
||||||
if (myPixelsFlipped)
|
if (myPixelsFlipped)
|
||||||
{
|
{
|
||||||
src += myTextureWidth * (myHeight - 1);
|
src += srcPitch * (myHeight - 1);
|
||||||
srcPitch = -srcPitch;
|
srcPitch = -srcPitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < myHeight; ++i)
|
for (unsigned int i = 0; i < myHeight; ++i)
|
||||||
{
|
{
|
||||||
std::copy(src, src + myWidth, dst);
|
memcpy(dst, src, dstPitch);
|
||||||
src += srcPitch;
|
src += srcPitch;
|
||||||
dst += myWidth;
|
dst += dstPitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ ImageLoader::~ImageLoader()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Load pixels from an image file
|
/// Load pixels from an image file
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool ImageLoader::LoadImageFromFile(const std::string& filename, std::vector<Color>& pixels, unsigned int& width, unsigned int& height)
|
bool ImageLoader::LoadImageFromFile(const std::string& filename, std::vector<Uint8>& pixels, unsigned int& width, unsigned int& height)
|
||||||
{
|
{
|
||||||
// Clear the array (just in case)
|
// Clear the array (just in case)
|
||||||
pixels.clear();
|
pixels.clear();
|
||||||
@ -101,8 +101,8 @@ bool ImageLoader::LoadImageFromFile(const std::string& filename, std::vector<Col
|
|||||||
height = imgHeight;
|
height = imgHeight;
|
||||||
|
|
||||||
// Copy the loaded pixels to the pixel buffer
|
// Copy the loaded pixels to the pixel buffer
|
||||||
pixels.resize(width * height);
|
pixels.resize(width * height * 4);
|
||||||
memcpy(&pixels[0], ptr, width * height * 4);
|
memcpy(&pixels[0], ptr, pixels.size());
|
||||||
|
|
||||||
// Free the loaded pixels (they are now in our own pixel buffer)
|
// Free the loaded pixels (they are now in our own pixel buffer)
|
||||||
SOIL_free_image_data(ptr);
|
SOIL_free_image_data(ptr);
|
||||||
@ -122,13 +122,13 @@ bool ImageLoader::LoadImageFromFile(const std::string& filename, std::vector<Col
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Load pixels from an image file in memory
|
/// Load pixels from an image file in memory
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool ImageLoader::LoadImageFromMemory(const void* data, std::size_t sizeInBytes, std::vector<Color>& pixels, unsigned int& width, unsigned int& height)
|
bool ImageLoader::LoadImageFromMemory(const void* data, std::size_t sizeInBytes, std::vector<Uint8>& pixels, unsigned int& width, unsigned int& height)
|
||||||
{
|
{
|
||||||
// Clear the array (just in case)
|
// Clear the array (just in case)
|
||||||
pixels.clear();
|
pixels.clear();
|
||||||
|
|
||||||
// Load the image and get a pointer to the pixels in memory
|
// Load the image and get a pointer to the pixels in memory
|
||||||
const unsigned char* buffer = reinterpret_cast<const unsigned char*>(data);
|
const unsigned char* buffer = static_cast<const unsigned char*>(data);
|
||||||
int size = static_cast<int>(sizeInBytes);
|
int size = static_cast<int>(sizeInBytes);
|
||||||
int imgWidth, imgHeight, imgChannels;
|
int imgWidth, imgHeight, imgChannels;
|
||||||
unsigned char* ptr = SOIL_load_image_from_memory(buffer, size, &imgWidth, &imgHeight, &imgChannels, SOIL_LOAD_RGBA);
|
unsigned char* ptr = SOIL_load_image_from_memory(buffer, size, &imgWidth, &imgHeight, &imgChannels, SOIL_LOAD_RGBA);
|
||||||
@ -140,8 +140,8 @@ bool ImageLoader::LoadImageFromMemory(const void* data, std::size_t sizeInBytes,
|
|||||||
height = imgHeight;
|
height = imgHeight;
|
||||||
|
|
||||||
// Copy the loaded pixels to the pixel buffer
|
// Copy the loaded pixels to the pixel buffer
|
||||||
pixels.resize(width * height);
|
pixels.resize(width * height * 4);
|
||||||
memcpy(&pixels[0], ptr, width * height * 4);
|
memcpy(&pixels[0], ptr, pixels.size());
|
||||||
|
|
||||||
// Free the loaded pixels (they are now in our own pixel buffer)
|
// Free the loaded pixels (they are now in our own pixel buffer)
|
||||||
SOIL_free_image_data(ptr);
|
SOIL_free_image_data(ptr);
|
||||||
@ -161,7 +161,7 @@ bool ImageLoader::LoadImageFromMemory(const void* data, std::size_t sizeInBytes,
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Save pixels to an image file
|
/// Save pixels to an image file
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool ImageLoader::SaveImageToFile(const std::string& filename, const std::vector<Color>& pixels, unsigned int width, unsigned int height)
|
bool ImageLoader::SaveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height)
|
||||||
{
|
{
|
||||||
// Deduce the image type from its extension
|
// Deduce the image type from its extension
|
||||||
int type = -1;
|
int type = -1;
|
||||||
@ -185,8 +185,7 @@ bool ImageLoader::SaveImageToFile(const std::string& filename, const std::vector
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finally save the image
|
// Finally save the image
|
||||||
const unsigned char* ptr = reinterpret_cast<const unsigned char*>(&pixels[0]);
|
if (!SOIL_save_image(filename.c_str(), type, static_cast<int>(width), static_cast<int>(height), 4, &pixels[0]))
|
||||||
if (!SOIL_save_image(filename.c_str(), type, static_cast<int>(width), static_cast<int>(height), 4, ptr))
|
|
||||||
{
|
{
|
||||||
// Error, failed to save the image
|
// Error, failed to save the image
|
||||||
Err() << "Failed to save image \"" << filename << "\". Reason: " << SOIL_last_result() << std::endl;
|
Err() << "Failed to save image \"" << filename << "\". Reason: " << SOIL_last_result() << std::endl;
|
||||||
@ -200,7 +199,7 @@ bool ImageLoader::SaveImageToFile(const std::string& filename, const std::vector
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Save a JPG image file
|
/// Save a JPG image file
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool ImageLoader::WriteJpg(const std::string& filename, const std::vector<Color>& pixels, unsigned int width, unsigned int height)
|
bool ImageLoader::WriteJpg(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height)
|
||||||
{
|
{
|
||||||
// Open the file to write in
|
// Open the file to write in
|
||||||
FILE* file = fopen(filename.c_str(), "wb");
|
FILE* file = fopen(filename.c_str(), "wb");
|
||||||
@ -227,11 +226,11 @@ bool ImageLoader::WriteJpg(const std::string& filename, const std::vector<Color>
|
|||||||
|
|
||||||
// Get rid of the aplha channel
|
// Get rid of the aplha channel
|
||||||
std::vector<Uint8> buffer(width * height * 3);
|
std::vector<Uint8> buffer(width * height * 3);
|
||||||
for (std::size_t i = 0; i < pixels.size(); ++i)
|
for (std::size_t i = 0; i < width * height; ++i)
|
||||||
{
|
{
|
||||||
buffer[i * 3 + 0] = pixels[i].r;
|
buffer[i * 3 + 0] = pixels[i * 3 + 0];
|
||||||
buffer[i * 3 + 1] = pixels[i].g;
|
buffer[i * 3 + 1] = pixels[i * 3 + 1];
|
||||||
buffer[i * 3 + 2] = pixels[i].b;
|
buffer[i * 3 + 2] = pixels[i * 3 + 2];
|
||||||
}
|
}
|
||||||
Uint8* ptr = &buffer[0];
|
Uint8* ptr = &buffer[0];
|
||||||
|
|
||||||
@ -259,7 +258,7 @@ bool ImageLoader::WriteJpg(const std::string& filename, const std::vector<Color>
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Save a PNG image file
|
/// Save a PNG image file
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool ImageLoader::WritePng(const std::string& filename, const std::vector<Color>& pixels, unsigned int width, unsigned int height)
|
bool ImageLoader::WritePng(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height)
|
||||||
{
|
{
|
||||||
// Open the file to write in
|
// Open the file to write in
|
||||||
FILE* file = fopen(filename.c_str(), "wb");
|
FILE* file = fopen(filename.c_str(), "wb");
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Graphics/Color.hpp>
|
|
||||||
#include <SFML/System/NonCopyable.hpp>
|
#include <SFML/System/NonCopyable.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -65,7 +64,7 @@ public :
|
|||||||
/// \return True if loading was successful
|
/// \return True if loading was successful
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool LoadImageFromFile(const std::string& filename, std::vector<Color>& pixels, unsigned int& width, unsigned int& height);
|
bool LoadImageFromFile(const std::string& filename, std::vector<Uint8>& pixels, unsigned int& width, unsigned int& height);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Load pixels from an image file in memory
|
/// Load pixels from an image file in memory
|
||||||
@ -79,7 +78,7 @@ public :
|
|||||||
/// \return True if loading was successful
|
/// \return True if loading was successful
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool LoadImageFromMemory(const void* data, std::size_t sizeInBytes, std::vector<Color>& pixels, unsigned int& width, unsigned int& height);
|
bool LoadImageFromMemory(const void* data, std::size_t sizeInBytes, std::vector<Uint8>& pixels, unsigned int& width, unsigned int& height);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Save pixels to an image file
|
/// Save pixels to an image file
|
||||||
@ -92,7 +91,7 @@ public :
|
|||||||
/// \return True if saving was successful
|
/// \return True if saving was successful
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool SaveImageToFile(const std::string& filename, const std::vector<Color>& pixels, unsigned int width, unsigned int height);
|
bool SaveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height);
|
||||||
|
|
||||||
private :
|
private :
|
||||||
|
|
||||||
@ -119,7 +118,7 @@ private :
|
|||||||
/// \return True if saving was successful
|
/// \return True if saving was successful
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool WriteJpg(const std::string& filename, const std::vector<Color>& pixels, unsigned int width, unsigned int height);
|
bool WriteJpg(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Save a PNG image file
|
/// Save a PNG image file
|
||||||
@ -132,7 +131,7 @@ private :
|
|||||||
/// \return True if saving was successful
|
/// \return True if saving was successful
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool WritePng(const std::string& filename, const std::vector<Color>& pixels, unsigned int width, unsigned int height);
|
bool WritePng(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
@ -219,7 +219,8 @@ void Text::Render(RenderTarget&, Renderer& renderer) const
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Bind the font texture
|
// Bind the font texture
|
||||||
renderer.SetTexture(&myFont->GetImage(myCharacterSize));
|
const Image& texture = myFont->GetImage(myCharacterSize);
|
||||||
|
renderer.SetTexture(&texture);
|
||||||
|
|
||||||
// Computes values related to the text style
|
// Computes values related to the text style
|
||||||
bool bold = (myStyle & Bold) != 0;
|
bool bold = (myStyle & Bold) != 0;
|
||||||
@ -227,7 +228,7 @@ void Text::Render(RenderTarget&, Renderer& renderer) const
|
|||||||
float italicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees
|
float italicCoeff = (myStyle & Italic) ? 0.208f : 0.f; // 12 degrees
|
||||||
float underlineOffset = myCharacterSize * 0.1f;
|
float underlineOffset = myCharacterSize * 0.1f;
|
||||||
float underlineThickness = myCharacterSize * (bold ? 0.1f : 0.07f);
|
float underlineThickness = myCharacterSize * (bold ? 0.1f : 0.07f);
|
||||||
FloatRect underlineCoords = myFont->GetImage(myCharacterSize).GetTexCoords(IntRect(1, 1, 1, 1));
|
FloatRect underlineCoords = texture.GetTexCoords(IntRect(1, 1, 1, 1));
|
||||||
|
|
||||||
// Initialize the rendering coordinates
|
// Initialize the rendering coordinates
|
||||||
float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance);
|
float space = static_cast<float>(myFont->GetGlyph(L' ', myCharacterSize, bold).Advance);
|
||||||
@ -273,17 +274,17 @@ void Text::Render(RenderTarget&, Renderer& renderer) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract the current glyph's description
|
// Extract the current glyph's description
|
||||||
const Glyph& curGlyph = myFont->GetGlyph(curChar, myCharacterSize, bold);
|
const Glyph& glyph = myFont->GetGlyph(curChar, myCharacterSize, bold);
|
||||||
int advance = curGlyph.Advance;
|
int advance = glyph.Advance;
|
||||||
const IntRect& rect = curGlyph.Rectangle;
|
const IntRect& bounds = glyph.Bounds;
|
||||||
const FloatRect& coord = curGlyph.TexCoords;
|
const FloatRect& coords = texture.GetTexCoords(glyph.SubRect);
|
||||||
|
|
||||||
// Draw a textured quad for the current character
|
// Draw a textured quad for the current character
|
||||||
renderer.Begin(Renderer::QuadList);
|
renderer.Begin(Renderer::QuadList);
|
||||||
renderer.AddVertex(x + rect.Left - italicCoeff * rect.Top, y + rect.Top, coord.Left, coord.Top);
|
renderer.AddVertex(x + bounds.Left - italicCoeff * bounds.Top, y + bounds.Top, coords.Left, coords.Top);
|
||||||
renderer.AddVertex(x + rect.Right - italicCoeff * rect.Top, y + rect.Top, coord.Right, coord.Top);
|
renderer.AddVertex(x + bounds.Right - italicCoeff * bounds.Top, y + bounds.Top, coords.Right, coords.Top);
|
||||||
renderer.AddVertex(x + rect.Right - italicCoeff * rect.Bottom, y + rect.Bottom, coord.Right, coord.Bottom);
|
renderer.AddVertex(x + bounds.Right - italicCoeff * bounds.Bottom, y + bounds.Bottom, coords.Right, coords.Bottom);
|
||||||
renderer.AddVertex(x + rect.Left - italicCoeff * rect.Bottom, y + rect.Bottom, coord.Left, coord.Bottom);
|
renderer.AddVertex(x + bounds.Left - italicCoeff * bounds.Bottom, y + bounds.Bottom, coords.Left, coords.Bottom);
|
||||||
renderer.End();
|
renderer.End();
|
||||||
|
|
||||||
// Advance to the next character
|
// Advance to the next character
|
||||||
@ -374,7 +375,7 @@ void Text::UpdateRect() const
|
|||||||
curWidth += static_cast<float>(curGlyph.Advance);
|
curWidth += static_cast<float>(curGlyph.Advance);
|
||||||
|
|
||||||
// Update the maximum height
|
// Update the maximum height
|
||||||
float charHeight = charSize + curGlyph.Rectangle.Bottom;
|
float charHeight = charSize + curGlyph.Bounds.Bottom;
|
||||||
if (charHeight > curHeight)
|
if (charHeight > curHeight)
|
||||||
curHeight = charHeight;
|
curHeight = charHeight;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user