Logo Search packages:      
Sourcecode: wine-unstable version File versions  Download package

cards.c

/*
 * Cards dll implementation
 *
 * Copyright (C) 2004 Sami Nopanen
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"

#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wingdi.h"

#include "cards.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(cards);


void WINAPI cdtTerm(void);


static HINSTANCE hInst;
static int cardWidth;
static int cardHeight;
static HBITMAP cardBitmaps[CARD_MAX + 1];


/***********************************************************************
 * Initializes the cards.dll library. Loads the card bitmaps from the
 * resources, and initializes the card size variables.
 */
BOOL WINAPI cdtInit(int *width, int *height)
{
      BITMAP bm;
      int i;

      TRACE("(%p, %p)\n", width, height);

      for(i = 0; i <= CARD_MAX; i++)
            cardBitmaps[i] = 0;

      for(i = 0; i <= CARD_MAX; i++)
      {
            cardBitmaps[i] = LoadBitmapA(hInst, MAKEINTRESOURCEA(i));
            if(cardBitmaps[i] == 0)
            {
                  cdtTerm();
                  return FALSE;
            }
      }

      GetObjectA(cardBitmaps[0], sizeof(BITMAP), &bm);
      *width = cardWidth = bm.bmWidth;
      *height = cardHeight = bm.bmHeight;
      return TRUE;
}

static DWORD do_blt(HDC hdc, int x, int y, int dx, int dy, HDC hMemoryDC, DWORD rasterOp )
{
      if((cardWidth == dx) && (cardHeight == dy))
            return BitBlt(hdc, x, y, cardWidth, cardHeight, hMemoryDC, 0, 0, rasterOp);
      return StretchBlt(hdc, x, y, dx, dy, hMemoryDC, 0, 0, cardWidth, cardHeight, rasterOp);
}

/***********************************************************************
 * Draw a card. Unlike cdtDrawCard, this version allows you to stretch
 * card bitmaps to the size you specify (dx, dy). See cdtDraw for info
 * on card, mode and color parameters.
 */
BOOL WINAPI cdtDrawExt(HDC hdc, int x, int y, int dx, int dy, int card, int mode, DWORD color)
{
      HDC hMemoryDC;
      HBITMAP hCardBitmap;
      HGDIOBJ result;
      DWORD rasterOp = SRCCOPY;
      BOOL roundCornersFlag;
      BOOL eraseFlag = FALSE;
      BOOL drawFlag = TRUE;

      TRACE("(%p, %d, %d, %d, %d, %d, %d, %d)\n", hdc, x, y, dx, dy, card, mode, color);

      roundCornersFlag = !(mode & MODEFLAG_DONT_ROUND_CORNERS) &&
                     (dx == cardWidth) && (dy == cardHeight);
      mode &= ~MODEFLAG_DONT_ROUND_CORNERS;

      if((card < 0) || (card > CARD_MAX))
      {
            FIXME("Unexpected card: %d\n", card);
            return FALSE;
      }

      if((mode < MODE_FACEUP) || (mode > MODE_DECKO))
      {
            FIXME("Unexpected mode: %d\n", mode);
            return FALSE;
      }

      switch(mode)
      {
      case MODE_FACEUP:
            break;
      case MODE_FACEDOWN:
            break;
      case MODE_HILITE:
            rasterOp = NOTSRCCOPY;
            break;
      case MODE_GHOST:
            card = CARD_FREE_MASK;
            eraseFlag = TRUE;
            rasterOp = SRCAND;
            break;
      case MODE_REMOVE:
            eraseFlag = TRUE;
            drawFlag = FALSE;
            break;
      case MODE_INVISIBLEGHOST:
            card = CARD_FREE_MASK;
            rasterOp = SRCAND;
            break;
      case MODE_DECKX:
            card = CARD_BACK_THE_X;
            break;
      case MODE_DECKO:
            card = CARD_BACK_THE_O;
            break;
      }

      hMemoryDC = CreateCompatibleDC(hdc);
      if(hMemoryDC == 0)
            return FALSE;

      if(eraseFlag)
      {
            HBRUSH hBrush;
            RECT rect;
            hBrush = CreateSolidBrush(color);
            rect.left = x;
            rect.top = y;
            rect.right = x + cardWidth - 1;
            rect.bottom = y + cardHeight - 1;
            FillRect(hdc, &rect, hBrush);
      }

      if(drawFlag)
      {
            hCardBitmap = cardBitmaps[card];
            if(hCardBitmap == 0)
                  return FALSE;

            result = SelectObject(hMemoryDC, hCardBitmap);
            if((result == 0) || (result == HGDI_ERROR))
            {
                  DeleteDC(hMemoryDC);
                  return FALSE;
            }

            SetBkColor(hdc, color);

            if(roundCornersFlag)
            {
                    /* NOTE: native uses Get/SetPixel for corners, but that really
                     * hurts on X11 since it needs a server round-trip for each pixel.
                     * So we use a clip region instead. */
                    HRGN saved = CreateRectRgn( 0, 0, 0, 0 );
                    HRGN line = CreateRectRgn( x + 2, y, x + dx - 2, y + 1 );
                    HRGN clip = CreateRectRgn( x, y + 2, x + dx, y + dy - 2 );

                    CombineRgn( clip, clip, line, RGN_OR );
                    SetRectRgn( line, x + 1, y + 1, x + dx - 1, y + 2 );
                    CombineRgn( clip, clip, line, RGN_OR );
                    SetRectRgn( line, x + 1, y + dy - 2, x + dx - 1, y + dy - 1 );
                    CombineRgn( clip, clip, line, RGN_OR );
                    SetRectRgn( line, x + 2, y + dy - 1, x + dx - 2, y + dy );
                    CombineRgn( clip, clip, line, RGN_OR );
                    DeleteObject( line );

                    if (!GetClipRgn( hdc, saved ))
                    {
                        DeleteObject( saved );
                        saved = 0;
                    }
                    ExtSelectClipRgn( hdc, clip, RGN_AND );
                    DeleteObject( clip );

                    do_blt(hdc, x, y, dx, dy, hMemoryDC, rasterOp);

                    SelectClipRgn( hdc, saved );
                    if (saved) DeleteObject( saved );
            }
            else
                  do_blt(hdc, x, y, dx, dy, hMemoryDC, rasterOp);
      }

      DeleteDC(hMemoryDC);

      return TRUE;
}


/***********************************************************************
 * Draws a card at position x, y in its default size (as returned by
 * cdtInit.
 *
 * Mode controls how the card gets drawn:
 *   MODE_FACEUP                ; draw card facing up
 *   MODE_FACEDOWN              ; draw card facing down
 *   MODE_HILITE                ; draw face up, with NOTSRCCOPY
 *   MODE_GHOST                 ; draw 'ghost' card
 *   MODE_REMOVE                ; draw with background color
 *   MODE_INVISIBLEGHOST        ; draw 'ghost' card, without clearing background
 *   MODE_DECKX                 ; draw X
 *   MODE_DECKO                 ; draw O
 *
 * The card parameter defines the card graphic to be drawn. If we are
 * drawing fronts of cards, card should have a value from 0 through 51
 * to represent the card face. If we are drawing card backs, 53 through
 * 68 represent different card backs.
 *
 * When drawing card faces, two lowest bits represent the card suit
 * (clubs, diamonds, hearts, spades), and the bits above that define the
 * card value (ace, 2, ..., king). That is,
 *   card = face * 4 + suit.
 *
 * Color parameter defines the background color, used when drawing some
 * card backs.
 */
BOOL WINAPI cdtDraw(HDC hdc, int x, int y, int card, int mode, DWORD color)
{
      TRACE("(%p, %d, %d, %d, %d, %d)\n", hdc, x, y, card, mode, color);

      return cdtDrawExt(hdc, x, y, cardWidth, cardHeight, card, mode, color);
}


/***********************************************************************
 * Animates the card backs, e.g. blinking lights on the robot, the sun
 * donning sunglasses, bats flying across the caste, etc.. Works only
 * for cards of normal size (as drawn with cdtDraw). To draw frames of
 * the card back animation, start with frame = 0, and increment the
 * frame by one, until cdtAnimate returns FALSE (to indicate that we
 * have gone through all frames of animation).
 */
BOOL WINAPI cdtAnimate(HDC hdc, int cardback, int x, int y, int frame)
{
      TRACE("(%p, %d, %d, %d, %d)\n", hdc, cardback, x, y, frame);
      FIXME("Implement me.\n");

      return FALSE;
}


/***********************************************************************
 * Frees resources reserved by cdtInitialize.
 */
void WINAPI cdtTerm(void)
{
      int i;

      TRACE("()\n");

      for(i = 0; i <= CARD_MAX; i++)
      {
            if(cardBitmaps[i] != 0)
                  DeleteObject(cardBitmaps[i]);
            cardBitmaps[i] = 0;
      }
}


/***********************************************************************
 * DllMain.
 */
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
{
    switch (reason)
    {
    case DLL_PROCESS_ATTACH:
        hInst = inst;
        DisableThreadLibraryCalls( inst );
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Generated by  Doxygen 1.6.0   Back to index