//*****************************************************************************
// 
// Blackjack - an X windows program of the casino game.
// Copyright (C) 1997  Tom Daley 
// 
// 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 the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// This program 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 General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// 
// The license is in the file COPYING.
// 
// Tom Daley
// 1309 W. Lorraine Ave.
// Woodland Park, CO  80863-2329
// 
// daley@codenet.net (Tom Daley)
// http://users.codenet.net/daley
// 
//*****************************************************************************

#include <stream.h>
#include <qpainter.h>

typedef unsigned char uchar;	// this is needed by the bitmap files

#include "rank.bm"
#include "suit.bm"
#include "newface.bm"
#include "logo.bm"

#include "card.h"

//*****************************************************************************
//
//	Card::init() should be called early in application startup.
//	Card::init() makes 52 card face pixmaps and one cardback pixmap.
//	If init() is not called, the first call to getPixmap() will call
//	init().  This may cause a delay on the first getPixmap() call.
//
//*****************************************************************************

#define CARD_W	79
#define CARD_H	123

// pip location coordinates
//
//        col1 col2 col3
//       ----------------
//       |              |
// row1  |              |
//       |              |
// row2  |              |
//       |              |
// row3  |              |
//       |              |                                                .
//       |              |  Lower pips are made by rotating upper pips 180
//       |              |
//       |              |
//       |              |
//       ----------------

#define COL_1		17
#define COL_2		32
#define COL_3		48

#define ROW_1		16
#define ROW_2		40
#define ROW_3		52

#define SEVEN_8_Y	34

#define TEN_Y		28

// Royalty index defines

#define J_IX   (JACK - JACK) 
#define Q_IX   (QUEEN - JACK)
#define K_IX   (KING - JACK) 

//*****************************************************************************
// static class variables

int Card::_init_flag = 0;

QBitmap *Card::_suit_bitmaps[CLUB + 1];
QBitmap *Card::_small_suit_bitmaps[CLUB + 1];
QBitmap *Card::_large_spade_bitmap;
QBitmap *Card::_rank_bitmaps[KING + 1];
QBitmap *Card::_royalty_bitmaps[KING - JACK + 1][CLUB + 1];

QPixmap *Card::_card_back_pixmaps[USER + 1];
QPixmap *Card::_card_pixmaps[KING + 1][CLUB + 1];

//*****************************************************************************
//
//	Make 52 QPixmaps representing all the cards in a deck.
//	This improves performance when drawing.
//

void Card::
init(void) {
   if (_init_flag == 0) {
      _init_flag = 1;		// allocate bitmaps to make QPixmaps for card
      _suit_bitmaps[SPADE]   = new QBitmap(spade_width, spade_height, 
                                           spade_bits, TRUE);
      _suit_bitmaps[HEART]   = new QBitmap(heart_width, heart_height, 
                                           heart_bits, TRUE);
      _suit_bitmaps[DIAMOND] = new QBitmap(diamond_width, diamond_height, 
                                           diamond_bits, TRUE);
      _suit_bitmaps[CLUB]    = new QBitmap(club_width, club_height, 
                                           club_bits, TRUE);

      _small_suit_bitmaps[SPADE]   = new QBitmap(spade_sm_width, 
                                     spade_sm_height, spade_sm_bits, TRUE);
      _small_suit_bitmaps[HEART]   = new QBitmap(heart_sm_width, 
                                     heart_sm_height, heart_sm_bits, TRUE);
      _small_suit_bitmaps[DIAMOND] = new QBitmap(diamond_sm_width, 
                                     diamond_sm_height, diamond_sm_bits, TRUE);
      _small_suit_bitmaps[CLUB]    = new QBitmap(club_sm_width, club_sm_height, 
                                                 club_sm_bits, TRUE);

      _large_spade_bitmap = new QBitmap(spade_lg_width, spade_lg_height, 
                                        spade_lg_bits, TRUE);

      for (int rank = ACE; rank <= KING; rank++)
         _rank_bitmaps[rank] = new QBitmap (rank_width, rank_height, 
                                            rank_bits[rank - 1], TRUE);

      _royalty_bitmaps[J_IX][SPADE] = new QBitmap(jack_s_width, jack_s_height, 
                                                  jack_s_bits, TRUE); 
      _royalty_bitmaps[J_IX][HEART] = new QBitmap(jack_h_width, jack_h_height, 
                                                  jack_h_bits, TRUE); 
      _royalty_bitmaps[J_IX][DIAMOND] = new QBitmap(jack_d_width, jack_d_height,
                                                  jack_d_bits, TRUE); 
      _royalty_bitmaps[J_IX][CLUB]  = new QBitmap(jack_c_width, jack_c_height, 
                                                  jack_c_bits, TRUE); 
 
      _royalty_bitmaps[Q_IX][SPADE] = new QBitmap(queen_s_width, queen_s_height,
                                                  queen_s_bits, TRUE); 
      _royalty_bitmaps[Q_IX][HEART] = new QBitmap(queen_h_width, queen_h_height,
                                                  queen_h_bits, TRUE); 
      _royalty_bitmaps[Q_IX][DIAMOND] = new QBitmap(queen_d_width, 
                                        queen_d_height, queen_d_bits, TRUE); 
      _royalty_bitmaps[Q_IX][CLUB]  = new QBitmap(queen_c_width, queen_c_height,
                                                  queen_c_bits, TRUE); 

      _royalty_bitmaps[K_IX][SPADE] = new QBitmap(king_s_width, king_s_height, 
                                                  king_s_bits, TRUE); 
      _royalty_bitmaps[K_IX][HEART] = new QBitmap(king_h_width, king_h_height, 
                                                  king_h_bits, TRUE); 
      _royalty_bitmaps[K_IX][DIAMOND] = new QBitmap(king_d_width, king_d_height,
                                                  king_d_bits, TRUE); 
      _royalty_bitmaps[K_IX][CLUB]  = new QBitmap(king_c_width, king_c_height, 
                                                  king_c_bits, TRUE); 

      Card *card_p;				// make all card QPixmaps
      int r, s; 				// save ptr in _card_pixmaps
      for (r = ACE; r <= KING; r++) {
         for (s = SPADE; s <= CLUB; s++) {
            card_p = new Card((RankType)r, (SuitType)s);
            _card_pixmaps[r][s] = card_p->makePixmap();
            delete (card_p);
         }
      }

      for (s = SPADE; s <= CLUB; s++) {		// delete bitmaps used to make
         delete(_suit_bitmaps[s]);		// QPixmaps
         delete(_small_suit_bitmaps[s]);
      }

      delete(_large_spade_bitmap);
      for (r = ACE; r <= KING; r++)
         delete(_rank_bitmaps[r]);
 
      for (r = JACK - JACK; r <= KING - JACK; r++)
         for (s = SPADE; s <= CLUB; s++)
            delete(_royalty_bitmaps[r][s]); 

      _card_back_pixmaps[DEFAULT] = Card::makeCardbackPixmap();
      _card_back_pixmaps[USER] = NULL;
   }
}

//*****************************************************************************

QPixmap *Card::
makeCardbackPixmap(void) {
   int x_round = 12, y_round = 6;
   QColor color;
   QPixmap *pixmap_p = new QPixmap(CARD_W, CARD_H);
   QBitmap *bitmap_p = new QBitmap(CARD_W, CARD_H, TRUE);
   QBitmap *back_bitmap_p = new QBitmap(logo_width, logo_height, logo_bits, 
                                        TRUE);
   QBrush fill(Qt::white);
   QBrush pattern(Qt::CustomPattern);
   QPainter painter;
   
   if ((painter.begin(bitmap_p)) == FALSE) {
      cerr << "card::makeCardbackPixmap(): Can't open bitmap paint device\n";
      delete (bitmap_p);
      bitmap_p = NULL;
   } else {
      QBrush fill_ones(Qt::color1);// make a mask so we don't paint the corners
      painter.setBrush(fill_ones);	// make pixmap mask for card
      painter.drawRoundRect(0, 0, CARD_W, CARD_H, x_round, y_round);
      painter.end();
   }

   if ((painter.begin(pixmap_p)) == FALSE) {
      cerr << "card::makeCardbackPixmap(): Can't open pixmap paint device\n";
      delete (pixmap_p);
      pixmap_p = NULL;
   } else {
      painter.setPen(Qt::black);

   if (bitmap_p) 			// if we made a mask bitmap
      pixmap_p->setMask(*bitmap_p);	// set the mask for the pixmap

      painter.setBrush(fill);
      painter.drawRoundRect(0, 0, CARD_W, CARD_H, x_round, y_round);
      pattern.setPixmap(*back_bitmap_p);
      pattern.setColor(Qt::red);
      painter.setBrush(pattern);	// set up some painter options
      painter.drawRoundRect(0, 0, CARD_W, CARD_H, x_round, y_round);
      painter.end();
   }   

   delete (bitmap_p);
   delete (back_bitmap_p);

   return (pixmap_p);
}

//*****************************************************************************
//
//	I use hard coded numbers from the defines above.  
//	If the card needs to be scaled in a resize, the resulting pixmap 
//	could be scaled.
//
//*****************************************************************************

QPixmap *Card::
makePixmap(void) {
   int x_round = 12, y_round = 6;
   QColor color;
   QPixmap *pixmap_p = new QPixmap(CARD_W, CARD_H);
   QBitmap *bitmap_p = new QBitmap(CARD_W, CARD_H, TRUE);
   QBrush fill(Qt::white);		// make two brushes, fill and no_fill 
   QBrush no_fill(Qt::NoBrush);
   QPainter painter;

   if (_suit == HEART || _suit == DIAMOND)
      color = Qt::red;
   else
      color = Qt::black;

   if ((painter.begin(bitmap_p)) == FALSE) {
      cerr << "card::makePixmap(): Can't open bitmap paint device\n";
      delete (bitmap_p);
      bitmap_p = NULL;
   } else {
      QBrush fill_ones(Qt::color1);// make a mask so we don't paint the corners
      painter.setBrush(fill_ones);	// make pixmap mask for card 
      painter.drawRoundRect(0, 0, CARD_W, CARD_H, x_round, y_round); 
      painter.end();
   }

   if ((painter.begin(pixmap_p)) == FALSE) {
      cerr << "card::makePixmap(): Can't open pixmap paint device\n";
      delete (pixmap_p);
      pixmap_p = NULL;
   } else {
      painter.setBrush(fill);		// set up some painter options 
      painter.setPen(Qt::black);

      if (bitmap_p) 			// if we made a mask bitmap
         pixmap_p->setMask(*bitmap_p);	// set the mask for the pixmap

      painter.drawRoundRect(0, 0, CARD_W, CARD_H, x_round, y_round);

      QWMatrix flip;			// set up matrix to rotate 180 degrees
      flip.rotate(180);
      flip.translate(-CARD_W + 1, -CARD_H + 1);
      painter.setWorldMatrix(flip);
      painter.setWorldXForm(FALSE);	// disable transformation for now

      painter.setPen(color);		// draw rank and suit in corners
      painter.setBackgroundColor(Qt::white);
      painter.drawPixmap(4, 6, *_rank_bitmaps[_rank]);
      painter.drawPixmap(4, 23, *_small_suit_bitmaps[_suit]);
      painter.setWorldXForm(TRUE);	// now draw flipped rank and suit 
      painter.drawPixmap(4, 6, *_rank_bitmaps[_rank]);
      painter.drawPixmap(4, 23, *_small_suit_bitmaps[_suit]);
      painter.setWorldXForm(FALSE);	// turn off flip transformation

      if (_rank >= JACK && _rank <= KING) {	// if royalty, draw picture
         painter.drawPixmap(16, 16, *_royalty_bitmaps[_rank - JACK][_suit]);
         painter.setBrush(no_fill);
         painter.drawRect (15, 15, 49, 94);
      } else {				// else draw pips on card
         // if card needs center pip, draw it
         if (_rank == ACE || _rank == THREE || _rank == FIVE || _rank == NINE) {
            if (_rank == ACE && _suit == SPADE)
               painter.drawPixmap(COL_2 - 11, ROW_3 - 17, *_large_spade_bitmap);
            else
               painter.drawPixmap(COL_2, ROW_3, *_suit_bitmaps[_suit]);
         }
         // The two and three need an upper and lower center pip
         if (_rank == TWO || _rank == THREE) {
            painter.drawPixmap(COL_2, ROW_1, *_suit_bitmaps[_suit]);
            painter.setWorldXForm(TRUE);
            painter.drawPixmap(COL_2, ROW_1, *_suit_bitmaps[_suit]);
            painter.setWorldXForm(FALSE);
         }
         // four corner pips
         if (_rank >= FOUR && _rank <= TEN) {
            painter.drawPixmap(COL_1, ROW_1, *_suit_bitmaps[_suit]);
            painter.drawPixmap(COL_3, ROW_1, *_suit_bitmaps[_suit]);
            painter.setWorldXForm(TRUE);
            painter.drawPixmap(COL_1, ROW_1, *_suit_bitmaps[_suit]);
            painter.drawPixmap(COL_3, ROW_1, *_suit_bitmaps[_suit]);
            painter.setWorldXForm(FALSE);
         }
         if (_rank >= SIX && _rank <= EIGHT) { 	// mid-pips on sides
            painter.drawPixmap(COL_1, ROW_3, *_suit_bitmaps[_suit]);
            painter.drawPixmap(COL_3, ROW_3, *_suit_bitmaps[_suit]);
            if (_rank == SEVEN || _rank == EIGHT) {  // upper pips in mid col
               painter.drawPixmap(COL_2, SEVEN_8_Y, *_suit_bitmaps[_suit]);
               if (_rank == EIGHT) {
                  painter.setWorldXForm(TRUE);
                  painter.drawPixmap(COL_2, SEVEN_8_Y, *_suit_bitmaps[_suit]);
                  painter.setWorldXForm(FALSE);
               }
            }
         }
         if (_rank == NINE || _rank == TEN) { 	// side pips for 9 and 10 
            painter.drawPixmap(COL_1, ROW_2, *_suit_bitmaps[_suit]);
            painter.drawPixmap(COL_3, ROW_2, *_suit_bitmaps[_suit]);
            painter.setWorldXForm(TRUE);
            painter.drawPixmap(COL_1, ROW_2, *_suit_bitmaps[_suit]);
            painter.drawPixmap(COL_3, ROW_2, *_suit_bitmaps[_suit]);
            painter.setWorldXForm(FALSE);
            if (_rank == TEN) {
               painter.drawPixmap(COL_2, TEN_Y, *_suit_bitmaps[_suit]);
               painter.setWorldXForm(TRUE);
               painter.drawPixmap(COL_2, TEN_Y, *_suit_bitmaps[_suit]);
               painter.setWorldXForm(FALSE);
            }
         }
      }
      painter.end();
   }
   delete(bitmap_p);

   return(pixmap_p);
}

//*****************************************************************************

QPixmap *Card::
getPixmap(void) {
   QPixmap *result = NULL;

   if (! _init_flag)
      init();

   if (_dir == FACE_UP)
      result = _card_pixmaps[_rank][_suit];
   else {
      if (_card_back_pixmaps[USER])
         result = _card_back_pixmaps[USER];
      else
         result = _card_back_pixmaps[DEFAULT];
   }

   return(result);
}

//*****************************************************************************
