diff --git a/include/SFML/Graphics/Font.hpp b/include/SFML/Graphics/Font.hpp index f0cd18e16..ce9bda6f8 100644 --- a/include/SFML/Graphics/Font.hpp +++ b/include/SFML/Graphics/Font.hpp @@ -355,7 +355,7 @@ private: //////////////////////////////////////////////////////////// struct Page { - Page(); + explicit Page(bool smooth); GlyphTable glyphs; //!< Table mapping code points to their corresponding glyph Texture texture; //!< Texture containing the pixels of the glyphs @@ -369,6 +369,16 @@ private: //////////////////////////////////////////////////////////// void cleanup(); + //////////////////////////////////////////////////////////// + /// \brief Find or create the glyphs page corresponding to the given character size + /// + /// \param characterSize Reference character size + /// + /// \return The glyphs page corresponding to \a characterSize + /// + //////////////////////////////////////////////////////////// + Page& loadPage(unsigned int characterSize) const; + //////////////////////////////////////////////////////////// /// \brief Load a new glyph and store it in the cache /// diff --git a/include/SFML/Graphics/Image.hpp b/include/SFML/Graphics/Image.hpp index d58989135..309058a1c 100644 --- a/include/SFML/Graphics/Image.hpp +++ b/include/SFML/Graphics/Image.hpp @@ -228,9 +228,13 @@ public: /// kind of feature in real-time you'd better use sf::RenderTexture. /// /// If \a sourceRect is empty, the whole image is copied. - /// If \a applyAlpha is set to true, the transparency of - /// source pixels is applied. If it is false, the pixels are - /// copied unchanged with their alpha value. + /// If \a applyAlpha is set to true, alpha blending is + /// applied from the source pixels to the destination pixels + /// using the \b over operator. If it is false, the source + /// pixels are copied unchanged with their alpha value. + /// + /// See https://en.wikipedia.org/wiki/Alpha_compositing for + /// details on the \b over operator. /// /// \param source Source image to copy /// \param destX X coordinate of the destination position diff --git a/src/SFML/Graphics/Font.cpp b/src/SFML/Graphics/Font.cpp index 0457c809c..08a73cdc5 100644 --- a/src/SFML/Graphics/Font.cpp +++ b/src/SFML/Graphics/Font.cpp @@ -349,7 +349,7 @@ const Font::Info& Font::getInfo() const const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, float outlineThickness) const { // Get the page corresponding to the character size - GlyphTable& glyphs = m_pages[characterSize].glyphs; + GlyphTable& glyphs = loadPage(characterSize).glyphs; // Build the key by combining the glyph index (based on code point), bold flag, and outline thickness Uint64 key = combine(outlineThickness, bold, FT_Get_Char_Index(m_fontHandles ? m_fontHandles->face.get() : nullptr, codePoint)); @@ -476,7 +476,7 @@ float Font::getUnderlineThickness(unsigned int characterSize) const //////////////////////////////////////////////////////////// const Texture& Font::getTexture(unsigned int characterSize) const { - return m_pages[characterSize].texture; + return loadPage(characterSize).texture; } //////////////////////////////////////////////////////////// @@ -531,6 +531,18 @@ void Font::cleanup() } +//////////////////////////////////////////////////////////// +Font::Page& Font::loadPage(unsigned int characterSize) const +{ + // TODO: Remove this method and use try_emplace instead when updating to C++17 + PageTable::iterator pageIterator = m_pages.find(characterSize); + if (pageIterator == m_pages.end()) + pageIterator = m_pages.insert(std::make_pair(characterSize, Page(m_isSmooth))).first; + + return pageIterator->second; +} + + //////////////////////////////////////////////////////////// Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, float outlineThickness) const { @@ -620,7 +632,7 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f height += 2 * padding; // Get the glyphs page corresponding to the character size - Page& page = m_pages[characterSize]; + Page& page = loadPage(characterSize); // Find a good position for the new glyph into the texture glyph.textureRect = findGlyphRect(page, width, height); @@ -816,7 +828,7 @@ bool Font::setCurrentSize(unsigned int characterSize) const //////////////////////////////////////////////////////////// -Font::Page::Page() : +Font::Page::Page(bool smooth) : nextRow(3) { // Make sure that the texture is initialized by default @@ -834,7 +846,7 @@ nextRow(3) err() << "Failed to load font page texture" << std::endl; } - texture.setSmooth(true); + texture.setSmooth(smooth); } } // namespace sf diff --git a/src/SFML/Graphics/Image.cpp b/src/SFML/Graphics/Image.cpp index 010023c5f..d6dfe6b50 100644 --- a/src/SFML/Graphics/Image.cpp +++ b/src/SFML/Graphics/Image.cpp @@ -257,12 +257,19 @@ void Image::copy(const Image& source, unsigned int destX, unsigned int destY, co const Uint8* src = srcPixels + j * 4; Uint8* dst = dstPixels + j * 4; - // Interpolate RGBA components using the alpha value of the source pixel - Uint8 alpha = src[3]; - dst[0] = static_cast((src[0] * alpha + dst[0] * (255 - alpha)) / 255); - dst[1] = static_cast((src[1] * alpha + dst[1] * (255 - alpha)) / 255); - dst[2] = static_cast((src[2] * alpha + dst[2] * (255 - alpha)) / 255); - dst[3] = static_cast(alpha + dst[3] * (255 - alpha) / 255); + // Interpolate RGBA components using the alpha values of the destination and source pixels + Uint8 src_alpha = src[3]; + Uint8 dst_alpha = dst[3]; + Uint8 out_alpha = static_cast(src_alpha + dst_alpha - src_alpha * dst_alpha / 255); + + dst[3] = out_alpha; + + if (out_alpha) + for (int k = 0; k < 3; k++) + dst[k] = static_cast((src[k] * src_alpha + dst[k] * (out_alpha - src_alpha)) / out_alpha); + else + for (int k = 0; k < 3; k++) + dst[k] = src[k]; } srcPixels += srcStride; diff --git a/src/SFML/Window/Unix/CursorImpl.cpp b/src/SFML/Window/Unix/CursorImpl.cpp index d8f979f0e..f550b9979 100644 --- a/src/SFML/Window/Unix/CursorImpl.cpp +++ b/src/SFML/Window/Unix/CursorImpl.cpp @@ -80,10 +80,10 @@ bool CursorImpl::loadFromPixelsARGB(const Uint8* pixels, Vector2u size, Vector2u const std::size_t numPixels = static_cast(size.x) * static_cast(size.y); for (std::size_t pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) { - cursorImage->pixels[pixelIndex] = static_cast(pixels[pixelIndex * 4 + 2] + - (pixels[pixelIndex * 4 + 1] << 8) + - (pixels[pixelIndex * 4 + 0] << 16) + - (pixels[pixelIndex * 4 + 3] << 24)); + cursorImage->pixels[pixelIndex] = static_cast(pixels[pixelIndex * 4 + 2] + + (pixels[pixelIndex * 4 + 1] << 8) + + (pixels[pixelIndex * 4 + 0] << 16) + + (pixels[pixelIndex * 4 + 3] << 24)); } // Create the cursor.