@@ -539,14 +539,11 @@ u32 TextureSource::getTextureId(const std::string &name)
539
539
540
540
// Draw an image on top of another one, using the alpha channel of the
541
541
// source image
542
+ // overlay: only modify destination pixels that are fully opaque.
543
+ template <bool overlay = false >
542
544
static void blit_with_alpha (video::IImage *src, video::IImage *dst,
543
545
v2s32 src_pos, v2s32 dst_pos, v2u32 size);
544
546
545
- // Like blit_with_alpha, but only modifies destination pixels that
546
- // are fully opaque
547
- static void blit_with_alpha_overlay (video::IImage *src, video::IImage *dst,
548
- v2s32 src_pos, v2s32 dst_pos, v2u32 size);
549
-
550
547
// Apply a color to an image. Uses an int (0-255) to calculate the ratio.
551
548
// If the ratio is 255 or -1 and keep_alpha is true, then it multiples the
552
549
// color alpha with the destination alpha.
@@ -2042,81 +2039,35 @@ static inline video::SColor blitPixel(const video::SColor src_c, const video::SC
2042
2039
This exists because IImage::copyToWithAlpha() doesn't seem to always
2043
2040
work.
2044
2041
*/
2042
+ template <bool overlay>
2045
2043
static void blit_with_alpha (video::IImage *src, video::IImage *dst,
2046
2044
v2s32 src_pos, v2s32 dst_pos, v2u32 size)
2047
2045
{
2048
- // FIXME: loop should be restricted to actual overlap
2049
- // (if dst smaller than size or dst_pos negative)
2050
- for (u32 y0 =0 ; y0 <size.Y ; y0 ++)
2051
- for (u32 x0=0 ; x0<size.X ; x0++)
2052
- {
2053
- s32 src_x = src_pos.X + x0;
2054
- s32 src_y = src_pos.Y + y0 ;
2055
- s32 dst_x = dst_pos.X + x0;
2056
- s32 dst_y = dst_pos.Y + y0 ;
2057
- video::SColor src_c = src->getPixel (src_x, src_y);
2058
- video::SColor dst_c = dst->getPixel (dst_x, dst_y);
2059
- dst_c = blitPixel (src_c, dst_c, src_c.getAlpha ());
2060
- dst->setPixel (dst_x, dst_y, dst_c);
2061
- }
2062
- }
2063
-
2064
- /*
2065
- Draw an image on top of another one, using the alpha channel of the
2066
- source image; only modify fully opaque pixels in destinaion
2067
- */
2068
- static void blit_with_alpha_overlay (video::IImage *src, video::IImage *dst,
2069
- v2s32 src_pos, v2s32 dst_pos, v2u32 size)
2070
- {
2071
- // FIXME: same as above here
2072
- for (u32 y0 =0 ; y0 <size.Y ; y0 ++)
2073
- for (u32 x0=0 ; x0<size.X ; x0++)
2046
+ auto src_dim = src->getDimension ();
2047
+ auto dst_dim = dst->getDimension ();
2048
+
2049
+ // Limit y and x to the overlapping ranges
2050
+ // s.t. the positions are all in bounds after offsetting.
2051
+ for (u32 y0 = std::max (0 , -dst_pos.Y );
2052
+ y0 < std::min<s64>({size.Y , src_dim.Height , dst_dim.Height - (s64) dst_pos.Y });
2053
+ ++y0 )
2054
+ for (u32 x0 = std::max (0 , -dst_pos.X );
2055
+ x0 < std::min<s64>({size.X , src_dim.Width , dst_dim.Width - (s64) dst_pos.X });
2056
+ ++x0)
2074
2057
{
2075
2058
s32 src_x = src_pos.X + x0;
2076
2059
s32 src_y = src_pos.Y + y0 ;
2077
2060
s32 dst_x = dst_pos.X + x0;
2078
2061
s32 dst_y = dst_pos.Y + y0 ;
2079
2062
video::SColor src_c = src->getPixel (src_x, src_y);
2080
2063
video::SColor dst_c = dst->getPixel (dst_x, dst_y);
2081
- if (dst_c.getAlpha () == 255 && src_c.getAlpha () != 0 )
2082
- {
2064
+ if (!overlay || (dst_c.getAlpha () == 255 && src_c.getAlpha () != 0 )) {
2083
2065
dst_c = blitPixel (src_c, dst_c, src_c.getAlpha ());
2084
2066
dst->setPixel (dst_x, dst_y, dst_c);
2085
2067
}
2086
2068
}
2087
2069
}
2088
2070
2089
- // This function has been disabled because it is currently unused.
2090
- // Feel free to re-enable if you find it handy.
2091
- #if 0
2092
- /*
2093
- Draw an image on top of another one, using the specified ratio
2094
- modify all partially-opaque pixels in the destination.
2095
- */
2096
- static void blit_with_interpolate_overlay(video::IImage *src, video::IImage *dst,
2097
- v2s32 src_pos, v2s32 dst_pos, v2u32 size, int ratio)
2098
- {
2099
- for (u32 y0 = 0; y0 < size.Y; y0++)
2100
- for (u32 x0 = 0; x0 < size.X; x0++)
2101
- {
2102
- s32 src_x = src_pos.X + x0;
2103
- s32 src_y = src_pos.Y + y0;
2104
- s32 dst_x = dst_pos.X + x0;
2105
- s32 dst_y = dst_pos.Y + y0;
2106
- video::SColor src_c = src->getPixel(src_x, src_y);
2107
- video::SColor dst_c = dst->getPixel(dst_x, dst_y);
2108
- if (dst_c.getAlpha() > 0 && src_c.getAlpha() != 0)
2109
- {
2110
- if (ratio == -1)
2111
- dst_c = src_c.getInterpolated(dst_c, (float)src_c.getAlpha()/255.0f);
2112
- else
2113
- dst_c = src_c.getInterpolated(dst_c, (float)ratio/255.0f);
2114
- dst->setPixel(dst_x, dst_y, dst_c);
2115
- }
2116
- }
2117
- }
2118
- #endif
2119
-
2120
2071
/*
2121
2072
Apply color to destination, using a weighted interpolation blend
2122
2073
*/
@@ -2455,7 +2406,7 @@ static void draw_crack(video::IImage *crack, video::IImage *dst,
2455
2406
if (!crack_scaled)
2456
2407
return ;
2457
2408
2458
- auto blit = use_overlay ? blit_with_alpha_overlay : blit_with_alpha;
2409
+ auto blit = use_overlay ? blit_with_alpha< true > : blit_with_alpha< false > ;
2459
2410
for (s32 i = 0 ; i < frame_count; ++i) {
2460
2411
v2s32 dst_pos (0 , frame_size.Height * i);
2461
2412
blit (crack_scaled, dst, v2s32 (0 ,0 ), dst_pos, frame_size);
0 commit comments