summaryrefslogtreecommitdiffstats
path: root/kmahjongg/Tileset.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmahjongg/Tileset.cpp')
-rw-r--r--kmahjongg/Tileset.cpp281
1 files changed, 281 insertions, 0 deletions
diff --git a/kmahjongg/Tileset.cpp b/kmahjongg/Tileset.cpp
new file mode 100644
index 00000000..c29f9701
--- /dev/null
+++ b/kmahjongg/Tileset.cpp
@@ -0,0 +1,281 @@
+
+#include <stdlib.h>
+#include "Tileset.h"
+#include <qimage.h>
+
+
+#define mini_width 20
+#define mini_height 28
+static unsigned char mini_bits[] = {
+ 0xfc, 0xff, 0x0f, 0xfe, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f,
+ 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x07, 0xff, 0xff, 0x03,
+ };
+
+#define mask_width 40
+#define mask_height 56
+static unsigned char mask_bits[] = {
+ 0xf0, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff,
+ 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff,
+ 0xff, 0xff, 0xff, 0x0f, };
+
+
+// ---------------------------------------------------------
+
+Tileset::Tileset(bool scale):
+ maskBits(mask_width, mask_height, mask_bits, true),
+ maskBitsMini(mini_width, mini_height, mini_bits, true)
+{
+ isScaled = scale;
+ divisor = (isScaled) ? 2 : 1;
+
+ // set up tile metrics (fixed for now)
+ ss = 4; // left/bottom shadow width
+ bs = 1; // tile boarder width
+ w = 40; // tile width (inc boarder & shadow)
+ h = 56; // tile height (inc boarder and shadow)
+ s = w*h; // RGBA's required per tile
+
+ // Allocate memory for the 9*5 tile arrays
+ tiles = new QRgb [9*5*s];
+ selectedTiles = new QRgb [9*5*s];
+
+ // allocate memory for single tile storage
+ selectedFace = new QRgb [s];
+ unselectedFace = new QRgb [s];
+
+ // quarter widths are used as an offset when
+ // overlaying tiles in 3 dimensions.
+ qw = ((w-ss)/2) ;
+ qh = ((h-ss)/2) ;
+
+ filename = "";
+}
+
+
+// ---------------------------------------------------------
+
+Tileset::~Tileset() {
+
+ // deallocate all memory
+ delete [] tiles;
+ delete [] selectedTiles;
+ delete [] selectedFace;
+ delete [] unselectedFace;
+}
+
+// ---------------------------------------------------------
+// copy a tile from a qimage into a linear array of bytes. This
+// method returns the address of the byte after the copied image
+// and can be used to fill a larger array of tiles.
+
+QRgb *Tileset::copyTileImage(short tileX, short tileY, QRgb *to, QImage &from) {
+ QRgb *dest = to;
+ QRgb *src;
+
+ src = (QRgb *) from.scanLine(tileY * h)
+ +(tileX * w);
+ for (short pos=0; pos < h; pos++) {
+ memcpy(dest, src, w*sizeof(QRgb));
+ dest+=w;
+ src += from.width();
+ }
+ return(dest);
+}
+
+// ----------------------------------------------------------
+// Create a tile. Take a specified tile background a tile face
+// (specified as an x,y coord) and a destination buffer (location
+// in which is calculated from the x,y) and copy in the
+// tile background, overlaying the foreground with transparency
+// (the foregrounds top/left pixel is taken as the transparent
+// color).
+
+
+QRgb *Tileset::createTile(short x, short y,
+ QRgb *det, QImage &allTiles , QRgb *face) {
+ QRgb *image ;
+ QRgb *to = det;
+
+ // Alloc the space
+ image = new QRgb[s];
+
+ // copy in the background
+ memcpy(to, face, s*sizeof(QRgb));
+
+ // get the tile gylph
+ copyTileImage(x, y , image, allTiles);
+
+ // copy the image over the background using the
+ // top left colour as the transparency. We step over
+ // the shadow and the boarder
+
+ QRgb* src = image+ // image
+ ss+ // past the left shadow
+ bs+ // then the tile border
+ (bs * w); // then step past the top border
+
+
+ to += (((ss+bs))+(bs*w));
+
+
+ QRgb trans = *src;
+
+ // start after the top border rows and go through all rows
+ for( short YP=0; YP < h-ss - (2*bs); YP++) {
+ // start after the shadow and border and iterate over x
+ for (short xpos=0; xpos < w-ss -(2*bs) ; xpos++) {
+ // skip transparent pixels
+ if (*src != trans)
+ *to = *src;
+ src++;
+ to++;
+ }
+ // step over the border to get to the next row
+ src += ss + (2 * bs);
+ to += ss + (2 * bs);
+ }
+
+ // Free allocated space
+ delete [] image;
+
+ // calculate the address of the next tile
+ return(det+s);
+}
+
+// --------------------------------------------------------
+// create a pixmap for a tile. Optionally create a scalled
+// version, which can be used for mini tile requirements.
+// this gives us a small tile for previews and showing
+// removed tiles.
+void Tileset::createPixmap(QRgb *src, QPixmap &dest, bool scale, bool shadow)
+{
+
+ QImage buff;
+ QRgb *line;
+
+ buff.create(w, h, 32);
+
+ for (int y=0; y<h; y++) {
+ line = (QRgb *) buff.scanLine(y);
+ memcpy( line, src, w*sizeof(QRgb));
+
+ if (shadow) {
+ for (int spos=0; spos <w; spos++) {
+ line[spos] = QColor(line[spos]).dark(133).rgb();
+ }
+ }
+
+ src += w;
+ }
+
+
+ // create the pixmap and initialise the drawing mask
+ if (!scale) {
+ dest.convertFromImage(buff);
+ dest.setMask(maskBits);
+ } else {
+ dest.convertFromImage(buff.smoothScale(w/2, h/2));
+ dest.setMask(maskBitsMini);
+ }
+
+}
+
+
+// ---------------------------------------------------------
+bool Tileset::loadTileset( const QString& tilesetPath, const bool isPreview)
+{
+
+ QImage qiTiles;
+ QRgb *unsel;
+ QRgb *sel;
+ QRgb *nextSel=0;
+ QRgb *nextUnsel=0;
+
+ if (filename == tilesetPath) {
+ return true;
+ }
+
+
+ // try to load it
+ if( ! qiTiles.load( tilesetPath) )
+ return( false );
+
+
+
+ // we deal only with 32 bit images
+ if (qiTiles.depth() != 32)
+ qiTiles = qiTiles.convertDepth(32);
+
+
+
+ // Read in the unselected and selected tile backgrounds
+ copyTileImage(7, 4 , unselectedFace, qiTiles);
+ copyTileImage(8, 4, selectedFace, qiTiles);
+
+
+
+ // Read in the 9*5 tiles. Each tile is overlayed onto
+ // the selected and unselected tile backgrounds and
+ // stored.
+ sel = selectedTiles;
+ unsel = tiles;
+ for (short atY=0; atY<5; atY++) {
+ for (short atX=0; atX<9; atX++) {
+
+
+ nextUnsel = createTile(atX, atY, unsel , qiTiles, unselectedFace);
+
+ // for the preview dialog we do not create selected tiles
+ if (!isPreview)
+ nextSel = createTile(atX, atY, sel , qiTiles, selectedFace);
+ int pixNo = atX+(atY*9);
+
+ // for the preview dialog we only create the unselected mini pix
+ if (!isPreview) {
+ createPixmap(sel, selectedPix[pixNo], false, false);
+ createPixmap(unsel, unselectedPix[pixNo], false, false);
+ createPixmap(sel, selectedMiniPix[pixNo], true, false);
+
+ createPixmap(sel, selectedShadowPix[pixNo], false, true);
+ createPixmap(unsel, unselectedShadowPix[pixNo], false, true);
+ createPixmap(sel, selectedShadowMiniPix[pixNo], true, true);
+ createPixmap(unsel, unselectedShadowMiniPix[pixNo], true, true);
+ }
+
+ createPixmap(unsel, unselectedMiniPix[pixNo], true, false);
+ sel = nextSel;
+ unsel= nextUnsel;
+ }
+ }
+
+ filename = tilesetPath;
+ return( true );
+}
+
+