Allowing optional arguments can be risky. The recent glyph changes added a new argument to the routine that constructs a mirror image of a tile but not to the call to that routine. Because an existing argument was optional, the compiler didn't complain about the new one being missing. Obsolete optional 'fem' argument ought to removed but this doesn't tackle that.
246 lines
7.7 KiB
C++
246 lines
7.7 KiB
C++
// Copyright (c) Warwick Allison, 1999.
|
|
// Qt4 conversion copyright (c) Ray Chason, 2012-2014.
|
|
// NetHack may be freely redistributed. See license for details.
|
|
|
|
// qt_glyph.cpp -- class to manage the glyphs in a tile set
|
|
|
|
extern "C" {
|
|
#include "hack.h"
|
|
#include "tile2x11.h" /* x11tiles is potential fallback for nhtiles.bmp */
|
|
}
|
|
|
|
#include "qt_pre.h"
|
|
#include <QtGui/QtGui>
|
|
#if QT_VERSION >= 0x050000
|
|
#include <QtWidgets/QtWidgets>
|
|
#endif
|
|
#include "qt_post.h"
|
|
#include "qt_glyph.h"
|
|
#include "qt_bind.h"
|
|
#include "qt_set.h"
|
|
#include "qt_inv.h"
|
|
#include "qt_map.h"
|
|
#include "qt_str.h"
|
|
|
|
extern short glyph2tile[]; // from tile.c
|
|
|
|
namespace nethack_qt_ {
|
|
|
|
static int tilefile_tile_W=16;
|
|
static int tilefile_tile_H=16;
|
|
|
|
// Debian uses a separate PIXMAPDIR
|
|
#ifndef PIXMAPDIR
|
|
# ifdef HACKDIR
|
|
# define PIXMAPDIR HACKDIR
|
|
# else
|
|
# define PIXMAPDIR "."
|
|
# endif
|
|
#endif
|
|
|
|
NetHackQtGlyphs::NetHackQtGlyphs()
|
|
{
|
|
const char* tile_file = PIXMAPDIR "/nhtiles.bmp";
|
|
|
|
if (iflags.wc_tile_file)
|
|
tile_file = iflags.wc_tile_file;
|
|
|
|
if (!img.load(tile_file)) {
|
|
tiles_per_row = TILES_PER_ROW;
|
|
|
|
tile_file = PIXMAPDIR "/x11tiles";
|
|
if (!img.load(tile_file)) {
|
|
QString msg = QString::asprintf("Cannot load 'nhtiles.bmp' or 'x11tiles'.");
|
|
QMessageBox::warning(0, "IO Error", msg);
|
|
iflags.wc_ascii_map = 1;
|
|
iflags.wc_tiled_map = 0;
|
|
} else {
|
|
if (img.width() % tiles_per_row) {
|
|
impossible(
|
|
"Tile file \"%s\" has %d columns, not multiple of row count (%d)",
|
|
tile_file, img.width(), tiles_per_row);
|
|
}
|
|
}
|
|
} else {
|
|
tiles_per_row = 40;
|
|
}
|
|
|
|
if (iflags.wc_tile_width)
|
|
tilefile_tile_W = iflags.wc_tile_width;
|
|
else if (iflags.wc_ascii_map)
|
|
tilefile_tile_W = 16;
|
|
else
|
|
tilefile_tile_W = img.width() / tiles_per_row;
|
|
|
|
if (iflags.wc_tile_height)
|
|
tilefile_tile_H = iflags.wc_tile_height;
|
|
else
|
|
tilefile_tile_H = tilefile_tile_W;
|
|
|
|
setSize(tilefile_tile_W, tilefile_tile_H);
|
|
}
|
|
|
|
void NetHackQtGlyphs::drawGlyph(QPainter& painter, int glyph, int tileidx,
|
|
int x, int y, bool fem, bool reversed)
|
|
{
|
|
if (!reversed) {
|
|
#if 0
|
|
int tile = glyph2tile[glyph];
|
|
/* this is not required with the new glyph representation */
|
|
if (fem)
|
|
++tile;
|
|
#else
|
|
int tile = tileidx;
|
|
#endif
|
|
int px = (tile % tiles_per_row) * width();
|
|
int py = tile / tiles_per_row * height();
|
|
|
|
painter.drawPixmap(x, y, pm, px, py, width(), height());
|
|
} else {
|
|
// for paper doll; mirrored image for left side of two-handed weapon
|
|
painter.drawPixmap(x, y, reversed_pixmap(glyph, tileidx, fem),
|
|
0, 0, width(), height());
|
|
}
|
|
}
|
|
|
|
void NetHackQtGlyphs::drawCell(QPainter& painter, int glyph, int tileidx,
|
|
int cellx, int celly, bool fem)
|
|
{
|
|
drawGlyph(painter, glyph, tileidx, cellx * width(), celly * height(),
|
|
fem, false);
|
|
}
|
|
|
|
void NetHackQtGlyphs::drawBorderedCell(QPainter& painter, int glyph,
|
|
int tileidx, int cellx, int celly,
|
|
int border, bool reversed, bool fem)
|
|
{
|
|
int wd = width(),
|
|
ht = height(),
|
|
yoffset = 1, // tiny extra margin at top
|
|
lox = cellx * (wd + 2),
|
|
loy = celly * (ht + 2) + yoffset;
|
|
|
|
drawGlyph(painter, glyph, tileidx, lox + 1, loy + 1, fem, reversed);
|
|
|
|
#ifdef TEXTCOLOR
|
|
if (border != NO_BORDER) {
|
|
// gray would be a better mid-point between red and cyan but it
|
|
// doesn't show up well enough against the wall tile background
|
|
painter.setPen((border == BORDER_CURSED) ? Qt::red
|
|
: (border == BORDER_UNCURSED) ? Qt::yellow
|
|
: (border == BORDER_BLESSED) ? Qt::cyan
|
|
: Qt::white); // BORDER_DEFAULT
|
|
// assuming 32x32, draw 34x34 rectangle from 0..33x0..33, outside glyph
|
|
#if 0 /* Qt 5.11 drawRect(x,y,width,height) seems to have an off by 1 bug;
|
|
* drawRect(0,0,34,34) is drawing at 0..34x0..34 which is 35x35;
|
|
* should subtract 1 when adding width and/or height to base coord;
|
|
* the relevant code in QtCore/QRect.h is correct so this observable
|
|
* misbehavior is a mystery... */
|
|
painter.drawRect(lox, loy, wd + 2, ht + 2);
|
|
#else
|
|
painter.drawLine(lox, loy, lox + wd + 1, loy); // 0,0->33,0
|
|
painter.drawLine(lox, loy + ht + 1, lox + wd + 1, loy + ht + 1);
|
|
painter.drawLine(lox, loy, lox, loy + ht + 1); // 0,0->0,33
|
|
painter.drawLine(lox + wd + 1, loy, lox + wd + 1, loy + ht + 1);
|
|
#endif
|
|
if (border != BORDER_DEFAULT) {
|
|
// assuming 32x32, draw rectangle from 1..32x1..32, inside glyph
|
|
#if 0 /* (see above) */
|
|
painter.drawRect(lox + 1, loy + 1, wd, ht);
|
|
#else
|
|
painter.drawLine(lox + 1, loy + 1, lox + wd, loy + 1); // 1,1->32,1
|
|
painter.drawLine(lox + 1, loy + ht, lox + wd, loy + ht);
|
|
painter.drawLine(lox + 1, loy + 1, lox + 1, loy + ht); // 1,1->1,32
|
|
painter.drawLine(lox + wd, loy + 1, lox + wd, loy + ht);
|
|
#endif
|
|
for (int i = lox + 2; i < lox + wd - 1; i += 2) {
|
|
// assuming 32x32, draw points along <2..31,2> and <2..31,31>
|
|
painter.drawPoint(i, loy + 2);
|
|
painter.drawPoint(i + 1, loy + ht - 1);
|
|
}
|
|
for (int j = loy + 2; j < loy + ht - 1; j += 2) {
|
|
// assuming 32x32, draw points along <2,2..31> and <31,2..31>
|
|
painter.drawPoint(lox + 2, j);
|
|
painter.drawPoint(lox + wd - 1, j + 1);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
nhUse(border);
|
|
#endif
|
|
}
|
|
|
|
// mis-named routine to get the pixmap for a particular glyph
|
|
QPixmap NetHackQtGlyphs::glyph(int glyphindx UNUSED, int tileidx, bool fem UNUSED)
|
|
{
|
|
#if 0
|
|
int tile = glyph2tile[glyphindx];
|
|
if (fem)
|
|
++tile;
|
|
#else
|
|
int tile = tileidx;
|
|
#endif
|
|
int px = (tile % tiles_per_row) * tilefile_tile_W;
|
|
int py = tile / tiles_per_row * tilefile_tile_H;
|
|
|
|
return QPixmap::fromImage(img.copy(px, py,
|
|
tilefile_tile_W, tilefile_tile_H));
|
|
}
|
|
|
|
// transpose a glyph's tile horizontally, scaled for use in paper doll
|
|
QPixmap NetHackQtGlyphs::reversed_pixmap(int glyphindx, int tileidx, bool fem)
|
|
{
|
|
QPixmap pxmp = glyph(glyphindx, tileidx, fem);
|
|
#ifdef ENHANCED_PAPERDOLL
|
|
qreal wid = (qreal) pxmp.width(),
|
|
//hgt = (qreal) pxmp.height(),
|
|
xscale = (qreal) qt_settings->dollWidth / (qreal) tilefile_tile_W,
|
|
yscale = (qreal) qt_settings->dollHeight / (qreal) tilefile_tile_H;
|
|
QTransform *mirrormatrix = new QTransform(
|
|
// negate x coordinates to flip the image across the y-axis
|
|
-1.0 * xscale, 0.0, 0.0, yscale,
|
|
// slide flipped image to the right to make things positive again
|
|
wid * xscale, 0.0
|
|
);
|
|
return pxmp.transformed(*mirrormatrix);
|
|
#else
|
|
return pxmp;
|
|
#endif
|
|
}
|
|
|
|
void NetHackQtGlyphs::setSize(int w, int h)
|
|
{
|
|
if (size == QSize(w, h))
|
|
return;
|
|
size = QSize(w, h);
|
|
if (!w || !h)
|
|
return; // Still not decided
|
|
|
|
if (size == pm1.size()) { // not zoomed
|
|
pm = pm1;
|
|
return;
|
|
}
|
|
if (size == pm2.size()) { // zoomed
|
|
pm = pm2;
|
|
return;
|
|
}
|
|
|
|
bool was1 = (size == pm1.size());
|
|
if (w == tilefile_tile_W && h == tilefile_tile_H) {
|
|
pm.convertFromImage(img);
|
|
} else {
|
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
QImage scaled = img.scaled(
|
|
w * img.width() / tilefile_tile_W,
|
|
h * img.height() / tilefile_tile_H,
|
|
Qt::IgnoreAspectRatio,
|
|
Qt::FastTransformation
|
|
);
|
|
pm.convertFromImage(scaled, Qt::ThresholdDither | Qt::PreferDither);
|
|
QApplication::restoreOverrideCursor();
|
|
}
|
|
(was1 ? pm2 : pm1) = pm;
|
|
}
|
|
|
|
} // namespace nethack_qt_
|