Make Piececolor options work on png pieces
authorH.G. Muller <h.g.muller@hccnet.nl>
Sat, 6 Oct 2012 17:54:50 +0000 (19:54 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Sun, 21 Oct 2012 09:28:17 +0000 (11:28 +0200)
The scaled, antialiased bitmaps are now colored according to the option
settings. This is done by decomposing every pixel in a white, black and
transparency component, which is possible because the opacity is
directly give in the alpha channel, and black originally was a hard zero.
So what you se in the red channel must be white (as the original white
was #FFFFCC), and the rest of the opacity must be due to black.
  The color to be replaced (white for the white pieces, black for the black
pieces) is then replaced by the original weight of this color times the
color from the option.

draw.c

diff --git a/draw.c b/draw.c
index 8f7b546..20553e2 100644 (file)
--- a/draw.c
+++ b/draw.c
@@ -255,8 +255,8 @@ ConvertPixmap (int color, int piece)
   for(i=0; i<f; i++) {
     ch[i] = pixels[i+1][0];
     colcode[i] = 0;
-    if(strstr(pixels[i+1], "black")) colcode[i] = 0xFF000000 + (color ? b : 0);
-    if(strstr(pixels[i+1], "white")) colcode[i] = 0xFF000000 + w;
+    if(strstr(pixels[i+1], "black")) colcode[i] = 0xFF000000; // 0xFF000000 + (color ? b : 0);
+    if(strstr(pixels[i+1], "white")) colcode[i] = 0xFFFFFFCC; // 0xFF000000 + w;
   }
   for(i=0; i<p->size; i++) {
     for(j=0; j<p->size; j++) {
@@ -299,6 +299,24 @@ ScaleOnePiece (char *name, int color, int piece)
   cairo_set_source_surface (cr, img, 0, 0);
   cairo_paint (cr);
   cairo_destroy (cr);
+  { // operate on bitmap to color it (king-size hack...)
+    int stride = cairo_image_surface_get_stride(cs)/4;
+    int *buf = (int *) cairo_image_surface_get_data(cs);
+    int i, j, p;
+    sscanf(color ? appData.blackPieceColor+1 : appData.whitePieceColor+1, "%x", &p); // replacement color
+    cairo_surface_flush(cs);
+    for(i=0; i<squareSize; i++) for(j=0; j<squareSize; j++) {
+       int r, a;
+       float f;
+       unsigned int c = buf[i*stride + j];
+       a = c >> 24; r = c >> 16 & 255;     // alpha and red, where red is the 'white' weight, since white is #FFFFCC in the source images
+        f = (color ? a - r : r)/255.;       // fraction of black or white in the mix that has to be replaced
+       buf[i*stride + j] = c & 0xFF000000; // alpha channel is kept at same opacity
+       buf[i*stride + j] += ((int)(f*(p&0xFF0000)) & 0xFF0000) + ((int)(f*(p&0xFF00)) & 0xFF00) + (int)(f*(p&0xFF)); // add desired fraction of new color
+       if(color) buf[i*stride + j] += r | r << 8 | r << 16; // details on black pieces get their weight added in pure white
+    }
+    cairo_surface_mark_dirty(cs);
+  }
 }
 
 void