[Scummvm-git-logs] scummvm master -> 97387c745cda25d6be49a92c3aa330b5a0207199
bluegr
noreply at scummvm.org
Sun Jun 15 12:10:24 UTC 2025
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
6767fe7dbb GRAPHICS: Add variants of Font::drawChar that preserve the alpha channel
97387c745c WINTERMUTE: Switch to Font::drawAlphaString
Commit: 6767fe7dbb9739e4217792a909114c61857484e1
https://github.com/scummvm/scummvm/commit/6767fe7dbb9739e4217792a909114c61857484e1
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2025-06-15T15:10:21+03:00
Commit Message:
GRAPHICS: Add variants of Font::drawChar that preserve the alpha channel
Changed paths:
graphics/font.cpp
graphics/font.h
graphics/fonts/ttf.cpp
diff --git a/graphics/font.cpp b/graphics/font.cpp
index 38cb0482767..ceb6d8181c1 100644
--- a/graphics/font.cpp
+++ b/graphics/font.cpp
@@ -106,7 +106,7 @@ int getStringWidthImpl(const Font &font, const StringType &str) {
}
template<class SurfaceType, class StringType>
-void drawStringImpl(const Font &font, SurfaceType *dst, const StringType &str, int x, int y, int w, uint32 color, TextAlign align, int deltax) {
+void drawStringImpl(const Font &font, SurfaceType *dst, const StringType &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool alpha) {
// The logic in getBoundingImpl is the same as we use here. In case we
// ever change something here we will need to change it there too.
assert(dst != 0);
@@ -129,8 +129,12 @@ void drawStringImpl(const Font &font, SurfaceType *dst, const StringType &str, i
Common::Rect charBox = font.getBoundingBox(cur);
if (x + charBox.right > rightX)
break;
- if (x + charBox.right >= leftX)
- font.drawChar(dst, cur, x, y, color);
+ if (x + charBox.right >= leftX) {
+ if (alpha)
+ font.drawAlphaChar(dst, cur, x, y, color);
+ else
+ font.drawChar(dst, cur, x, y, color);
+ }
x += font.getCharWidth(cur);
}
@@ -469,19 +473,40 @@ void Font::drawChar(ManagedSurface *dst, uint32 chr, int x, int y, uint32 color)
dst->addDirtyRect(charBox);
}
+void Font::drawAlphaChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const {
+ // Generic implementation for 1bpp fonts. Fonts with alpha blending
+ // should override this function.
+
+ uint32 aMask = (0xFF >> dst->format.aLoss) << dst->format.aShift;
+
+ Common::Rect charBox = getBoundingBox(chr);
+ charBox.translate(x, y);
+ dst->fillRect(charBox, color & ~aMask);
+
+ drawChar(dst, chr, x, y, color | aMask);
+}
+
+void Font::drawAlphaChar(ManagedSurface *dst, uint32 chr, int x, int y, uint32 color) const {
+ drawAlphaChar(dst->surfacePtr(), chr, x, y, color);
+
+ Common::Rect charBox = getBoundingBox(chr);
+ charBox.translate(x, y);
+ dst->addDirtyRect(charBox);
+}
+
void Font::drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
Common::String renderStr = useEllipsis ? handleEllipsis(*this, str, w) : str;
- drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax);
+ drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax, false);
}
void Font::drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
Common::U32String renderStr = useEllipsis ? handleEllipsis(*this, str, w) : str;
- drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax);
+ drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax, false);
}
void Font::drawString(ManagedSurface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
Common::String renderStr = useEllipsis ? handleEllipsis(*this, str, w) : str;
- drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax);
+ drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax, false);
if (w != 0) {
dst->addDirtyRect(getBoundingBox(str, x, y, w, align, deltax, useEllipsis));
@@ -490,7 +515,35 @@ void Font::drawString(ManagedSurface *dst, const Common::String &str, int x, int
void Font::drawString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
Common::U32String renderStr = useEllipsis ? handleEllipsis(*this, str, w) : str;
- drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax);
+ drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax, false);
+
+ if (w != 0) {
+ dst->addDirtyRect(getBoundingBox(str, x, y, w, align, useEllipsis));
+ }
+}
+
+void Font::drawAlphaString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
+ Common::String renderStr = useEllipsis ? handleEllipsis(*this, str, w) : str;
+ drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax, true);
+}
+
+void Font::drawAlphaString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
+ Common::U32String renderStr = useEllipsis ? handleEllipsis(*this, str, w) : str;
+ drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax, true);
+}
+
+void Font::drawAlphaString(ManagedSurface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
+ Common::String renderStr = useEllipsis ? handleEllipsis(*this, str, w) : str;
+ drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax, true);
+
+ if (w != 0) {
+ dst->addDirtyRect(getBoundingBox(str, x, y, w, align, deltax, useEllipsis));
+ }
+}
+
+void Font::drawAlphaString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
+ Common::U32String renderStr = useEllipsis ? handleEllipsis(*this, str, w) : str;
+ drawStringImpl(*this, dst, renderStr, x, y, w, color, align, deltax, true);
if (w != 0) {
dst->addDirtyRect(getBoundingBox(str, x, y, w, align, useEllipsis));
diff --git a/graphics/font.h b/graphics/font.h
index 58c7fa6b3fb..8562c59ba7c 100644
--- a/graphics/font.h
+++ b/graphics/font.h
@@ -213,6 +213,34 @@ public:
virtual void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const = 0;
virtual void drawChar(ManagedSurface *dst, uint32 chr, int x, int y, uint32 color) const;
+ /**
+ * Draw a character at a specific point on the surface.
+ *
+ * Unlike drawChar(), this stores the alpha channel for fonts
+ * that would normally blend characters with the contents of
+ * the surface. This is useful for 3D games, or for games that
+ * require text on a separate surface to be blitted later.
+ *
+ * Note that the point describes the top left edge point where to draw
+ * the character. This can be different from the top left edge point of the
+ * character's bounding box. For example, TTF fonts sometimes move
+ * characters like 't' by one (or more) pixels to the left to create better
+ * visual results. To query the actual bounding box of a character, use
+ * getBoundingBox.
+ * @see getBoundingBox
+ *
+ * The Font implementation should take care of not drawing outside of the
+ * specified surface.
+ *
+ * @param dst The surface to draw on.
+ * @param chr The character to draw.
+ * @param x The x coordinate where to draw the character.
+ * @param y The y coordinate where to draw the character.
+ * @param color The color of the character.
+ */
+ virtual void drawAlphaChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const;
+ virtual void drawAlphaChar(ManagedSurface *dst, uint32 chr, int x, int y, uint32 color) const;
+
/** @overload */
/**
@@ -237,6 +265,33 @@ public:
/** @overload */
void drawString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = false) const;
+ /**
+ * Draw the given @p str string to the given @p dst surface.
+ *
+ * Unlike drawString(), this stores the alpha channel for fonts
+ * that would normally blend characters with the contents of
+ * the surface. This is useful for 3D games, or for games that
+ * require text on a separate surface to be blitted later.
+ *
+ * @param dst The surface on which to draw the string.
+ * @param str The string to draw.
+ * @param x The x position where to start drawing.
+ * @param y The y position where to start drawing.
+ * @param w Width of the text area.
+ * @param color The color with which to draw the string.
+ * @param align Text alignment. This can be used to center the string in the given area or to align it to the right.
+ * @param deltax Offset to the x starting position of the string.
+ * @param useEllipsis Use ellipsis if needed to fit the string in the area.
+ *
+ */
+ void drawAlphaString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = false) const;
+ /** @overload */
+ void drawAlphaString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = false) const;
+ /** @overload */
+ void drawAlphaString(ManagedSurface *dst, const Common::String &str, int x, int _y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = false) const;
+ /** @overload */
+ void drawAlphaString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = false) const;
+
/**
* Compute and return the width of the string @p str when rendered using this font.
*
diff --git a/graphics/fonts/ttf.cpp b/graphics/fonts/ttf.cpp
index 53c3d664555..9646e2a4d8c 100644
--- a/graphics/fonts/ttf.cpp
+++ b/graphics/fonts/ttf.cpp
@@ -179,6 +179,8 @@ public:
void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
void drawChar(ManagedSurface *dst, uint32 chr, int x, int y, uint32 color) const override;
+ void drawAlphaChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const override;
+ void drawAlphaChar(ManagedSurface *dst, uint32 chr, int x, int y, uint32 color) const override;
private:
bool _initialized;
@@ -209,8 +211,8 @@ private:
int computePointSize(int size, TTFSizeMode sizeMode) const;
int readPointSizeFromVDMXTable(int height) const;
int computePointSizeFromHeaders(int height) const;
- void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color,
- const uint32 *transparentColor) const;
+ void drawCharIntern(Surface *dst, uint32 chr, int x, int y, uint32 color,
+ const uint32 *transparentColor, bool alpha) const;
FT_Int32 _loadFlags;
FT_Render_Mode _renderMode;
@@ -646,18 +648,40 @@ static void renderGlyph(uint8 *dstPos, const int dstPitch, const uint8 *srcPos,
}
}
+template<typename ColorType>
+static void renderAlphaGlyph(uint8 *dstPos, const int dstPitch, const uint8 *srcPos,
+ const int srcPitch, const int w, const int h, ColorType color,
+ const PixelFormat &dstFormat) {
+ uint8 sR, sG, sB;
+ dstFormat.colorToRGB(color, sR, sG, sB);
+
+ for (int y = 0; y < h; ++y) {
+ ColorType *rDst = (ColorType *)dstPos;
+ const uint8 *src = srcPos;
+
+ for (int x = 0; x < w; ++x) {
+ *rDst = dstFormat.ARGBToColor(*src, sR, sG, sB);
+ ++rDst;
+ ++src;
+ }
+
+ dstPos += dstPitch;
+ srcPos += srcPitch;
+ }
+}
+
} // End of anonymous namespace
void TTFFont::drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const {
- drawChar(dst, chr, x, y, color, nullptr);
+ drawCharIntern(dst, chr, x, y, color, nullptr, false);
}
void TTFFont::drawChar(ManagedSurface *dst, uint32 chr, int x, int y, uint32 color) const {
if (dst->hasTransparentColor()) {
uint32 transColor = dst->getTransparentColor();
- drawChar(dst->surfacePtr(), chr, x, y, color, &transColor);
+ drawCharIntern(dst->surfacePtr(), chr, x, y, color, &transColor, false);
} else {
- drawChar(dst->surfacePtr(), chr, x, y, color, nullptr);
+ drawCharIntern(dst->surfacePtr(), chr, x, y, color, nullptr, false);
}
Common::Rect charBox = getBoundingBox(chr);
@@ -665,8 +689,20 @@ void TTFFont::drawChar(ManagedSurface *dst, uint32 chr, int x, int y, uint32 col
dst->addDirtyRect(charBox);
}
-void TTFFont::drawChar(Surface * dst, uint32 chr, int x, int y, uint32 color,
- const uint32 *transparentColor) const {
+void TTFFont::drawAlphaChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const {
+ drawCharIntern(dst, chr, x, y, color, nullptr, true);
+}
+
+void TTFFont::drawAlphaChar(ManagedSurface *dst, uint32 chr, int x, int y, uint32 color) const {
+ drawCharIntern(dst->surfacePtr(), chr, x, y, color, nullptr, true);
+
+ Common::Rect charBox = getBoundingBox(chr);
+ charBox.translate(x, y);
+ dst->addDirtyRect(charBox);
+}
+
+void TTFFont::drawCharIntern(Surface * dst, uint32 chr, int x, int y, uint32 color,
+ const uint32 *transparentColor, bool alpha) const {
assureCached(chr);
GlyphCache::const_iterator glyphEntry = _glyphs.find(chr);
if (glyphEntry == _glyphs.end())
@@ -714,30 +750,40 @@ void TTFFont::drawChar(Surface * dst, uint32 chr, int x, int y, uint32 color,
uint8 *dstPos = (uint8 *)dst->getBasePtr(x, y);
- if (dst->format.isCLUT8()) {
- for (int cy = 0; cy < h; ++cy) {
- uint8 *rDst = dstPos;
- const uint8 *src = srcPos;
-
- for (int cx = 0; cx < w; ++cx) {
- // We assume a 1Bpp mode is a color indexed mode, thus we can
- // not take advantage of anti-aliasing here.
- if (*src >= 0x80)
- *rDst = color;
+ if (alpha) {
+ if (dst->format.bytesPerPixel == 1) {
+ renderAlphaGlyph<uint8>(dstPos, dst->pitch, srcPos, glyph.image.pitch, w, h, color, dst->format);
+ } else if (dst->format.bytesPerPixel == 2) {
+ renderAlphaGlyph<uint16>(dstPos, dst->pitch, srcPos, glyph.image.pitch, w, h, color, dst->format);
+ } else if (dst->format.bytesPerPixel == 4) {
+ renderAlphaGlyph<uint32>(dstPos, dst->pitch, srcPos, glyph.image.pitch, w, h, color, dst->format);
+ }
+ } else {
+ if (dst->format.isCLUT8()) {
+ for (int cy = 0; cy < h; ++cy) {
+ uint8 *rDst = dstPos;
+ const uint8 *src = srcPos;
+
+ for (int cx = 0; cx < w; ++cx) {
+ // We assume a 1Bpp mode is a color indexed mode, thus we can
+ // not take advantage of anti-aliasing here.
+ if (*src >= 0x80)
+ *rDst = color;
+
+ ++rDst;
+ ++src;
+ }
- ++rDst;
- ++src;
+ dstPos += dst->pitch;
+ srcPos += glyph.image.pitch;
}
-
- dstPos += dst->pitch;
- srcPos += glyph.image.pitch;
+ } else if (dst->format.bytesPerPixel == 1) {
+ renderGlyph<uint8>(dstPos, dst->pitch, srcPos, glyph.image.pitch, w, h, color, dst->format, transparentColor);
+ } else if (dst->format.bytesPerPixel == 2) {
+ renderGlyph<uint16>(dstPos, dst->pitch, srcPos, glyph.image.pitch, w, h, color, dst->format, transparentColor);
+ } else if (dst->format.bytesPerPixel == 4) {
+ renderGlyph<uint32>(dstPos, dst->pitch, srcPos, glyph.image.pitch, w, h, color, dst->format, transparentColor);
}
- } else if (dst->format.bytesPerPixel == 1) {
- renderGlyph<uint8>(dstPos, dst->pitch, srcPos, glyph.image.pitch, w, h, color, dst->format, transparentColor);
- } else if (dst->format.bytesPerPixel == 2) {
- renderGlyph<uint16>(dstPos, dst->pitch, srcPos, glyph.image.pitch, w, h, color, dst->format, transparentColor);
- } else if (dst->format.bytesPerPixel == 4) {
- renderGlyph<uint32>(dstPos, dst->pitch, srcPos, glyph.image.pitch, w, h, color, dst->format, transparentColor);
}
}
Commit: 97387c745cda25d6be49a92c3aa330b5a0207199
https://github.com/scummvm/scummvm/commit/97387c745cda25d6be49a92c3aa330b5a0207199
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2025-06-15T15:10:21+03:00
Commit Message:
WINTERMUTE: Switch to Font::drawAlphaString
Changed paths:
engines/wintermute/base/font/base_font_truetype.cpp
diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp
index 69063d6c4f8..71dc41dcea7 100644
--- a/engines/wintermute/base/font/base_font_truetype.cpp
+++ b/engines/wintermute/base/font/base_font_truetype.cpp
@@ -269,7 +269,7 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
// TODO: This debug call does not work with WideString because text.c_str() returns an uint32 array.
//debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color));
-// void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
+// void drawAlphaString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
Graphics::Surface *surface = new Graphics::Surface();
surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _gameRef->_renderer->getPixelFormat());
uint32 useColor = 0xffffffff;
@@ -282,33 +282,11 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
} else {
str = Common::convertBiDiU32String(*it, Common::BIDI_PAR_LTR);
}
- _font->drawString(surface, str, 0, heightOffset, width, useColor, alignment);
+ _font->drawAlphaString(surface, str, 0, heightOffset, width, useColor, alignment);
heightOffset += (int)_lineHeight;
}
BaseSurface *retSurface = _gameRef->_renderer->createSurface();
-
- if (_deletableFont) {
- // Reconstruct the alpha channel of the font.
-
- // Since we painted it with color 0xFFFFFFFF onto a black background,
- // the alpha channel is gone, but the color value of each pixel corresponds
- // to its original alpha value.
-
- Graphics::PixelFormat format = _gameRef->_renderer->getPixelFormat();
- uint32 *pixels = (uint32 *)surface->getPixels();
-
- assert(surface->pitch == surface->w * 4);
- assert(surface->format.bytesPerPixel == 4);
-
- for (int i = 0; i < surface->w * surface->h; ++i) {
- uint8 a, r, g, b;
- format.colorToRGB(*pixels, r, g, b);
- a = r;
- *pixels++ = format.ARGBToColor(a, r, g, b);
- }
- }
-
retSurface->putSurface(*surface, true);
surface->free();
delete surface;
More information about the Scummvm-git-logs
mailing list