diff -r 01f88c3b7b66 -r 1b2b84315d27 hedgewars/uRenderUtils.pas --- a/hedgewars/uRenderUtils.pas Thu Aug 11 23:05:14 2016 +0300 +++ b/hedgewars/uRenderUtils.pas Sun Dec 17 00:09:24 2017 +0100 @@ -144,38 +144,74 @@ procedure copyToXY(src, dest: PSDL_Surface; destX, destY: LongInt); inline; begin + // copy from complete src copyToXYFromRect(src, dest, 0, 0, src^.w, src^.h, destX, destY); end; procedure copyToXYFromRect(src, dest: PSDL_Surface; srcX, srcY, srcW, srcH, destX, destY: LongInt); -var i, j, maxDest, maxSrc, iX, iY: LongInt; +var spi, dpi, iX, iY, dX, dY, lX, lY, aT: LongInt; srcPixels, destPixels: PLongWordArray; - r0, g0, b0, a0, r1, g1, b1, a1: Byte; + rD, gD, bD, aD, rT, gT, bT: Byte; begin - maxDest:= (dest^.pitch div 4) * dest^.h; - maxSrc:= (src^.pitch div 4) * src^.h; - SDL_LockSurface(src); SDL_LockSurface(dest); srcPixels:= src^.pixels; destPixels:= dest^.pixels; - for iX:= 0 to srcW - 1 do - for iY:= 0 to srcH - 1 do + // what's the offset between src and dest coords? + dX:= destX - srcX; + dY:= destY - srcY; + + // let's figure out where the rectangle we can actually copy ends + lX:= min(srcX + srcW, src^.w) - 1; + if lX + dx >= dest^.w then lX:= dest^.w - dx - 1; + lY:= min(srcY + srcH, src^.h) - 1; + if lY + dy >= dest^.h then lY:= dest^.h - dy - 1; + + for iX:= srcX to lX do + for iY:= srcY to lY do begin - i:= (destY + iY) * (dest^.pitch div 4) + (destX + iX); - j:= (srcY + iY) * (src^.pitch div 4) + (srcX + iX); - if (i < maxDest) and (j < maxSrc) and (srcPixels^[j] and AMask <> 0) then + // src pixel index + spi:= iY * src^.w + iX; + // dest pixel index + dpi:= (iY + dY) * dest^.w + (iX + dX); + + // get src alpha (and set it as target alpha for now) + aT:= (srcPixels^[spi] and AMask) shr AShift; + + // src pixel opaque? + if aT = 255 then begin - SDL_GetRGBA(destPixels^[i], dest^.format, @r0, @g0, @b0, @a0); - SDL_GetRGBA(srcPixels^[j], src^.format, @r1, @g1, @b1, @a1); - r0:= (r0 * (255 - LongInt(a1)) + r1 * LongInt(a1)) div 255; - g0:= (g0 * (255 - LongInt(a1)) + g1 * LongInt(a1)) div 255; - b0:= (b0 * (255 - LongInt(a1)) + b1 * LongInt(a1)) div 255; - a0:= a0 + ((255 - LongInt(a0)) * a1 div 255); - destPixels^[i]:= SDL_MapRGBA(dest^.format, r0, g0, b0, a0); + // just copy full pixel + destPixels^[dpi]:= srcPixels^[spi]; + continue; + end; + + // get dst alpha (without shift for now) + aD:= (destPixels^[dpi] and AMask) shr AShift; + + // dest completely transparent? + if aD = 0 then + begin + // just copy src pixel + destPixels^[dpi]:= srcPixels^[spi]; + continue; end; + + // looks like some blending is necessary + + // set color of target RGB to src for now + SDL_GetRGB(srcPixels^[spi], src^.format, @rT, @gT, @bT); + SDL_GetRGB(destPixels^[dpi], dest^.format, @rD, @gD, @bD); + // note: this is not how to correctly blend RGB, just sayin' (R,G,B are not linear...) + rT:= (rD * (255 - aT) + rT * aT) div 255; + gT:= (gD * (255 - aT) + gT * aT) div 255; + bT:= (bD * (255 - aT) + bT * aT) div 255; + aT:= aD + ((255 - LongInt(aD)) * aT div 255); + + destPixels^[dpi]:= SDL_MapRGBA(dest^.format, rT, gT, bT, Byte(aT)); + end; SDL_UnlockSurface(src); @@ -184,7 +220,7 @@ procedure DrawSprite2Surf(sprite: TSprite; dest: PSDL_Surface; x,y: LongInt); inline; begin - DrawSpriteFrame2Surf(sprite, dest, x, y, 0); + DrawSpriteFrame2Surf(sprite, dest, x, y, 0); end; procedure DrawSpriteFrame2Surf(sprite: TSprite; dest: PSDL_Surface; x,y,frame: LongInt); @@ -300,7 +336,7 @@ WriteInRoundRect(finalSurface, 0, 0, Color, font, s, maxLength); - checkFails(SDL_SetColorKey(finalSurface, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, false); + checkFails(SDL_SetColorKey(finalSurface, SDL_TRUE, 0) = 0, errmsgTransparentSet, false); RenderStringTexLim:= Surface2Tex(finalSurface, false);