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:
LaurentGom 2010-03-19 16:06:18 +00:00
parent dcdf39bf74
commit 6b23d15a14
10 changed files with 124 additions and 132 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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