]> Dogcows Code - chaz/openbox/blobdiff - render/image.c
1) translate all of openbox's output
[chaz/openbox] / render / image.c
index 0479f39b81dd59ccec3e78a5cf06b2939bb166cd..f878933274d88a25345c261269e21153abcb6ab6 100644 (file)
@@ -1,7 +1,8 @@
 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
 
    image.c for the Openbox window manager
-   Copyright (c) 2003        Ben Jansens
+   Copyright (c) 2006        Mikael Magnusson
+   Copyright (c) 2003-2007   Dana Jansens
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
 #include <glib.h>
 
-#define AVERAGE(a, b)   ( ((((a) ^ (b)) & 0xfefefefeL) >> 1) + ((a) & (b)) )
+#define FRACTION        12
+#define FLOOR(i)        ((i) & (~0UL << FRACTION))
+#define AVERAGE(a, b)   (((((a) ^ (b)) & 0xfefefefeL) >> 1) + ((a) & (b)))
 
-static void scale_line(RrPixel32 *dest, RrPixel32 *source, gint w, gint dw)
+static void ImageCopyResampled(RrPixel32 *dst, RrPixel32 *src,
+                               gulong dstW, gulong dstH,
+                               gulong srcW, gulong srcH)
 {
-    gint num_pixels = dw;
-    gint int_part = w / dw;
-    gint fract_part = w % dw;
-    gint err = 0;
-
-    while (num_pixels-- > 0) {
-        *dest++ = *source;
-        source += int_part;
-        err += fract_part;
-        if (err >= dw) {
-            err -= dw;
-            source++;
-        }
-    }
-}
-
-static RrPixel32* scale_half(RrPixel32 *source, gint w, gint h)
-{
-    RrPixel32 *out, *dest, *sourceline, *sourceline2;
-    gint dw, dh, x, y;
-
-    sourceline = source;
-    sourceline2 = source + w;
-
-    dw = w >> 1;
-    dh = h >> 1;
-
-    out = dest = g_new(RrPixel32, dw * dh);
-
-    for (y = 0; y < dh; ++y) {
-        RrPixel32 *s, *s2;
-
-        s = sourceline;
-        s2 = sourceline2;
-
-        for (x = 0; x < dw; ++x) {
-            *dest++ = AVERAGE(AVERAGE(*s, *(s+1)),
-                              AVERAGE(*s2, *(s2+1)));
-            s += 2;
-            s2 += 2;
-        }
-        sourceline += w << 1;
-        sourceline2 += w << 1;
-    }
-    return out;
-}
-
-static RrPixel32* scale_rect(RrPixel32 *fullsource,
-                             gint w, gint h, gint dw, gint dh)
-{
-    RrPixel32 *out, *dest;
-    RrPixel32 *source = fullsource;
-    RrPixel32 *oldsource = NULL;
-    RrPixel32 *prev_source = NULL;
-    gint num_pixels;
-    gint int_part;
-    gint fract_part;
-    gint err = 0;
-
-    while (dw <= (w >> 1) && dh <= (h >> 1)) {
-        source = scale_half(source, w, h);
-        w >>= 1; h >>= 1;
-        g_free(oldsource);
-        oldsource = source;
-    }
-
-    num_pixels = dh;
-    int_part = (h / dh) * w;
-    fract_part = h % dh;
-
-    out = dest = g_new(RrPixel32, dw * dh);
-
-    while (num_pixels-- > 0) {
-        if (source == prev_source) {
-            memcpy(dest, dest - dw, dw * sizeof(RrPixel32));
-        } else {
-            scale_line(dest, source, w, dw);
-            prev_source = source;
-        }
-        dest += dw;
-        source += int_part;
-        err += fract_part;
-        if (err >= dh) {
-            err -= dh;
-            source += w;
+    gulong dstX, dstY, srcX, srcY;
+    gulong srcX1, srcX2, srcY1, srcY2;
+    gulong ratioX, ratioY;
+    
+    ratioX = (srcW << FRACTION) / dstW;
+    ratioY = (srcH << FRACTION) / dstH;
+    
+    srcY2 = 0;
+    for (dstY = 0; dstY < dstH; dstY++) {
+        srcY1 = srcY2;
+        srcY2 += ratioY;
+        
+        srcX2 = 0;
+        for (dstX = 0; dstX < dstW; dstX++) {
+            gulong red = 0, green = 0, blue = 0, alpha = 0;
+            gulong portionX, portionY, portionXY, sumXY = 0;
+            RrPixel32 pixel;
+            
+            srcX1 = srcX2;
+            srcX2 += ratioX;
+            
+            for (srcY = srcY1; srcY < srcY2; srcY += (1UL << FRACTION)) {
+                if (srcY == srcY1) {
+                    srcY = FLOOR(srcY);
+                    portionY = (1UL << FRACTION) - (srcY1 - srcY);
+                    if (portionY > srcY2 - srcY1)
+                        portionY = srcY2 - srcY1;
+                }
+                else if (srcY == FLOOR(srcY2))
+                    portionY = srcY2 - srcY;
+                else
+                    portionY = (1UL << FRACTION);
+                
+                for (srcX = srcX1; srcX < srcX2; srcX += (1UL << FRACTION)) {
+                    if (srcX == srcX1) {
+                        srcX = FLOOR(srcX);
+                        portionX = (1UL << FRACTION) - (srcX1 - srcX);
+                        if (portionX > srcX2 - srcX1)
+                            portionX = srcX2 - srcX1;
+                    }
+                    else if (srcX == FLOOR(srcX2))
+                        portionX = srcX2 - srcX;
+                    else
+                        portionX = (1UL << FRACTION);
+                    
+                    portionXY = (portionX * portionY) >> FRACTION;
+                    sumXY += portionXY;
+                    
+                    pixel = *(src + (srcY >> FRACTION) * srcW
+                            + (srcX >> FRACTION));
+                    red   += ((pixel >> RrDefaultRedOffset)   & 0xFF)
+                             * portionXY;
+                    green += ((pixel >> RrDefaultGreenOffset) & 0xFF)
+                             * portionXY;
+                    blue  += ((pixel >> RrDefaultBlueOffset)  & 0xFF)
+                             * portionXY;
+                    alpha += ((pixel >> RrDefaultAlphaOffset) & 0xFF)
+                             * portionXY;
+                }
+            }
+            
+            g_assert(sumXY != 0);
+            red   /= sumXY;
+            green /= sumXY;
+            blue  /= sumXY;
+            alpha /= sumXY;
+            
+            *dst++ = (red   << RrDefaultRedOffset)   |
+                     (green << RrDefaultGreenOffset) |
+                     (blue  << RrDefaultBlueOffset)  |
+                     (alpha << RrDefaultAlphaOffset);
         }
     }
-
-    g_free(oldsource);
-
-    return out;
 }
 
 void RrImageDraw(RrPixel32 *target, RrTextureRGBA *rgba,
@@ -145,7 +132,8 @@ void RrImageDraw(RrPixel32 *target, RrTextureRGBA *rgba,
     if (sw != dw || sh != dh) {
         /*if (!(rgba->cache && dw == rgba->cwidth && dh == rgba->cheight))*/ {
             g_free(rgba->cache);
-            rgba->cache = scale_rect(rgba->data, sw, sh, dw, dh);
+            rgba->cache = g_new(RrPixel32, dw * dh);
+            ImageCopyResampled(rgba->cache, rgba->data, dw, dh, sw, sh);
             rgba->cwidth = dw;
             rgba->cheight = dh;
         }
@@ -165,7 +153,7 @@ void RrImageDraw(RrPixel32 *target, RrTextureRGBA *rgba,
         r = *source >> RrDefaultRedOffset;
         g = *source >> RrDefaultGreenOffset;
         b = *source >> RrDefaultBlueOffset;
-        
+
         /* background color */
         bgr = *dest >> RrDefaultRedOffset;
         bgg = *dest >> RrDefaultGreenOffset;
This page took 0.02529 seconds and 4 git commands to generate.