Allow WinBoard to use bitmaps with alpha channel
authorH.G.Muller <hgm@hgm-xboard.(none)>
Wed, 30 Nov 2016 21:27:35 +0000 (22:27 +0100)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Fri, 13 Jan 2017 15:39:24 +0000 (16:39 +0100)
When the primary image of a piece (*o.bmp or *s.bmp) has a format with
32 bit/pixel, it is assumed to be in ARGB format, with transparent
background. It is then drawn over the board accordingly by new code
(using the Win API AlphaBlend routine). This code ignores the allWhite
and flipBlack options for the moment.
  The cascade for loading bitmaps has been changed as well: WinBoard
now first tries to load an image with name like piece0_49o.bmp from the
pieceImageDirectory if the traditional name (like p49o.bmp) is not found,
before falling back on built-in images.

winboard/winboard.c

index 96bebcb..293b643 100644 (file)
  *------------------------------------------------------------------------\r
  ** See the file ChangeLog for a revision history.  */\r
 \r
+#ifndef WINVER\r
+#define WINVER 0x0500\r
+#endif\r
+\r
 #include "config.h"\r
 \r
 #include <windows.h>\r
@@ -2193,7 +2197,7 @@ void CreatePiecesFromFont()
 HBITMAP\r
 DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)\r
 {\r
-  char name[128], buf[MSG_SIZ];\r
+  char name[128], buf[MSG_SIZ], *ids = "pnbrqfeicwmohajgdvlsukaacvdklnwpwnwlwswolfgnuzebracameltowersword", *p;\r
 \r
     snprintf(name, sizeof(name)/sizeof(name[0]), "%s%d%s", piece, squareSize, suffix);\r
   if(appData.pieceDirectory[0]) {\r
@@ -2201,6 +2205,30 @@ DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)
     snprintf(buf, MSG_SIZ, "%s\\%s.bmp", appData.pieceDirectory, name);\r
     res = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
     if(res) return res;\r
+    p = strstr(ids, piece);\r
+    if(p) { // if we could reconstruct canonical piece number, try the pieceNNN_ format before falling back on built-ins\r
+      int n = p - ids;\r
+      switch(n) {\r
+       case 21: n = WhiteKing; break;\r
+       case 22: n = WhiteAngel; break;\r
+       case 24: n = WhiteSilver; break;\r
+       case 26: n = WhiteDragon; break;\r
+       case 28: n = WhiteLion; break;\r
+       case 30: n = WhiteTokin; break;\r
+       case 32: n = WhitePKnight; break;\r
+       case 34: n = WhitePLance; break;\r
+       case 36: n = WhitePSilver; break;\r
+       case 38: n = WhiteWolf; break;\r
+       case 42: n = WhiteGnu; break;\r
+       case 45: n = WhiteZebra; break;\r
+       case 50: n = WhiteCamel; break;\r
+       case 55: n = WhiteTower; break;\r
+       case 60: n = WhiteSword; break;\r
+      }\r
+      snprintf(buf, MSG_SIZ, "%s\\piece%d_%d%s.bmp", appData.pieceDirectory, n, squareSize, suffix);\r
+      res = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
+      if(res) return res;\r
+    }\r
   }\r
   if (gameInfo.event &&\r
       strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&\r
@@ -2992,7 +3020,7 @@ VOID
 DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, HDC tmphdc)\r
 {\r
   HBITMAP oldBitmap;\r
-  HBRUSH oldBrush;\r
+  HBRUSH oldBrush = NULL;\r
   int tmpSize;\r
 \r
   if (appData.blindfold) return;\r
@@ -3051,6 +3079,20 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
       y += squareSize - minorSize - 2;\r
       tmpSize = minorSize;\r
     }\r
+#if WINVER >= 0x0500\r
+    HBITMAP pbm = PieceBitmap(piece, color ? OUTLINE_PIECE : SOLID_PIECE);\r
+    BITMAP b;\r
+    GetObject(pbm, sizeof(BITMAP), &b);\r
+    if(b.bmBitsPixel == 32) { // for now this is a kludge to indicate bitmaps with alpha channel\r
+       BLENDFUNCTION bf;\r
+       bf.BlendOp = AC_SRC_OVER;\r
+       bf.BlendFlags = 0;\r
+       bf.SourceConstantAlpha = 0xFF;\r
+       bf.AlphaFormat = AC_SRC_ALPHA;\r
+       oldBitmap = SelectObject(tmphdc, pbm);\r
+       AlphaBlend(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, bf);\r
+    } else\r
+#endif\r
     if (color || appData.allWhite ) {\r
       oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, WHITE_PIECE));\r
       if( color )\r
@@ -3087,7 +3129,7 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
       else\r
         BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
     }\r
-    SelectObject(hdc, oldBrush);\r
+    if(oldBrush) SelectObject(hdc, oldBrush);\r
     SelectObject(tmphdc, oldBitmap);\r
   }\r
 }\r