diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp index d5d7f614c4a..598e13861bd 100644 --- a/graphics/managed_surface.cpp +++ b/graphics/managed_surface.cpp @@ -361,17 +361,62 @@ void ManagedSurface::transBlitFrom(const ManagedSurface &src, const Common::Rect srcAlpha, palette, mask, maskOnly); } +template +void transBlitPixel(TSRC srcVal, TDEST &destVal, const Graphics::PixelFormat &srcFormat, const Graphics::PixelFormat &destFormat, + uint overrideColor, uint srcAlpha, const uint32 *palette) { + if (srcFormat == destFormat && srcAlpha == 0xff) { + // Matching formats, so we can do a straight copy + destVal = overrideColor ? overrideColor : srcVal; + return; + } + + // Otherwise we have to manually decode and re-encode each pixel + byte aSrc, rSrc, gSrc, bSrc; + if (srcFormat.bytesPerPixel == 1) { + assert(palette != nullptr); // Catch the cases when palette is missing + + // Get the palette color + const uint32 col = palette[srcVal]; + rSrc = col & 0xff; + gSrc = (col >> 8) & 0xff; + bSrc = (col >> 16) & 0xff; + aSrc = (col >> 24) & 0xff; + } else { + srcFormat.colorToARGB(srcVal, aSrc, rSrc, gSrc, bSrc); + } + + byte rDest, gDest, bDest; + destFormat.colorToRGB(destVal, rDest, gDest, bDest); + + if (srcAlpha != 0xff) { + aSrc = aSrc * srcAlpha / 255; + } + + if (aSrc == 0) { + // Completely transparent, so skip + return; + } else if (aSrc == 0xff) { + // Completely opaque, so copy RGB values over + rDest = rSrc; + gDest = gSrc; + bDest = bSrc; + } else { + // Partially transparent, so calculate new pixel colors + double alpha = (double)aSrc / 255.0; + rDest = static_cast((rSrc * alpha) + (rDest * (1.0 - alpha))); + gDest = static_cast((gSrc * alpha) + (gDest * (1.0 - alpha))); + bDest = static_cast((bSrc * alpha) + (bDest * (1.0 - alpha))); + } + + destVal = destFormat.ARGBToColor(0xff, rDest, gDest, bDest); +} + template void transBlit(const Surface &src, const Common::Rect &srcRect, Surface &dest, const Common::Rect &destRect, TSRC transColor, bool flipped, uint overrideColor, uint srcAlpha, const uint32 *palette, const Surface *mask, bool maskOnly) { int scaleX = SCALE_THRESHOLD * srcRect.width() / destRect.width(); int scaleY = SCALE_THRESHOLD * srcRect.height() / destRect.height(); - const Graphics::PixelFormat &srcFormat = src.format; - const Graphics::PixelFormat &destFormat = dest.format; - byte aSrc, rSrc, gSrc, bSrc; - byte rDest, gDest, bDest; - double alpha; // Loop through drawing output lines for (int destY = destRect.top, scaleYCtr = 0; destY < destRect.bottom; ++destY, scaleYCtr += scaleY) { @@ -398,50 +443,10 @@ void transBlit(const Surface &src, const Common::Rect &srcRect, Surface &dest, c TSRC mskVal = mskLine[flipped ? src.w - scaleXCtr / SCALE_THRESHOLD - 1 : scaleXCtr / SCALE_THRESHOLD]; if (!mskVal) continue; - } - if (srcFormat == destFormat && srcAlpha == 0xff) { - // Matching formats, so we can do a straight copy - destLine[xCtr] = overrideColor ? overrideColor : srcVal; + transBlitPixel(srcVal, destLine[xCtr], src.format, dest.format, overrideColor, mskVal, palette); } else { - // Otherwise we have to manually decode and re-encode each pixel - if (srcFormat.bytesPerPixel == 1) { - assert(palette != nullptr); // Catch the cases when palette is missing - - // Get the palette color - const uint32 col = palette[srcVal]; - rSrc = col & 0xff; - gSrc = (col >> 8) & 0xff; - bSrc = (col >> 16) & 0xff; - aSrc = (col >> 24) & 0xff; - } else { - srcFormat.colorToARGB(srcVal, aSrc, rSrc, gSrc, bSrc); - } - destFormat.colorToRGB(destLine[xCtr], rDest, gDest, bDest); - - if (srcAlpha != 0xff) { - aSrc = aSrc * srcAlpha / 255; - } - - if (aSrc == 0) { - // Completely transparent, so skip - continue; - } - else if (aSrc == 0xff) { - // Completely opaque, so copy RGB values over - rDest = rSrc; - gDest = gSrc; - bDest = bSrc; - } - else { - // Partially transparent, so calculate new pixel colors - alpha = (double)aSrc / 255.0; - rDest = static_cast((rSrc * alpha) + (rDest * (1.0 - alpha))); - gDest = static_cast((gSrc * alpha) + (gDest * (1.0 - alpha))); - bDest = static_cast((bSrc * alpha) + (bDest * (1.0 - alpha))); - } - - destLine[xCtr] = destFormat.ARGBToColor(0xff, rDest, gDest, bDest); + transBlitPixel(srcVal, destLine[xCtr], src.format, dest.format, overrideColor, srcAlpha, palette); } } } diff --git a/graphics/managed_surface.h b/graphics/managed_surface.h index 290b04aba4b..40d66f27319 100644 --- a/graphics/managed_surface.h +++ b/graphics/managed_surface.h @@ -299,7 +299,7 @@ public: * Copies another surface into this one ignoring pixels of a designated transparent color * @param src Source surface * @param destPos Destination position to draw the surface - * @param mask Mask definition (0-skip, other-copy) + * @param mask Mask definition */ void transBlitFrom(const Surface &src, const Common::Point &destPos, const ManagedSurface &mask); @@ -308,7 +308,7 @@ public: * Copies another surface into this one ignoring pixels of a designated transparent color * @param src Source surface * @param destPos Destination position to draw the surface - * @param mask Mask definition (0-skip, other-copy) + * @param mask Mask definition */ void transBlitFrom(const Surface &src, const Common::Point &destPos, const Surface &mask); @@ -323,8 +323,6 @@ public: * @param overrideColor Optional color to use instead of non-transparent pixels from * the source surface * @param srcAlpha Optional additional transparency applied to src - * @param mask Optional parameter with mask definition (0-skip, other-copy) - * @param maskOnly Optional parameter for using mask over transColor */ void transBlitFrom(const Surface &src, const Common::Rect &srcRect, const Common::Point &destPos, uint transColor = 0, bool flipped = false, uint overrideColor = 0, uint srcAlpha = 0xff); @@ -340,7 +338,7 @@ public: * @param overrideColor Optional color to use instead of non-transparent pixels from * the source surface * @param srcAlpha Optional additional transparency applied to src - * @param mask Optional parameter with mask definition (0-skip, other-copy) + * @param mask Optional parameter with mask definition * @param maskOnly Optional parameter for using mask over transColor */ void transBlitFrom(const Surface &src, const Common::Rect &srcRect, const Common::Rect &destRect, @@ -376,7 +374,7 @@ public: * Copies another surface into this one ignoring pixels of a designated transparent color * @param src Source surface * @param destPos Destination position to draw the surface - * @param mask Mask definition (0-skip, other-copy) + * @param mask Mask definition */ void transBlitFrom(const ManagedSurface &src, const Common::Point &destPos, const ManagedSurface &mask); @@ -406,6 +404,8 @@ public: * @param overrideColor Optional color to use instead of non-transparent pixels from * the source surface * @param srcAlpha Optional additional transparency applied to src + * @param mask Optional parameter with mask definition + * @param maskOnly Optional parameter for using mask over transColor */ void transBlitFrom(const ManagedSurface &src, const Common::Rect &srcRect, const Common::Rect &destRect, uint transColor = 0, bool flipped = false, uint overrideColor = 0, uint srcAlpha = 0xff,