hedgewars/uRenderUtils.pas
branchqmlfrontend
changeset 12855 1b2b84315d27
parent 12591 7bae1fab444b
child 13489 8935dcc0e130
--- 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);