scummvm/engines/saga2/gdraw.h
2021-07-10 00:56:14 +02:00

436 lines
12 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
* Based on the original sources
* Faery Tale II -- The Halls of the Dead
* (c) 1993-1996 The Wyrmkeep Entertainment Co.
*/
#ifndef SAGA2_GDRAW_H
#define SAGA2_GDRAW_H
#include "saga2/rect.h"
namespace Saga2 {
/* ===================================================================== *
Drawing Pens
* ===================================================================== */
// A drawing pen. Note that this should later be a class?
typedef uint8 gPen; // a pen index number
/* ============================================================================ *
PixelMap: defines a chunky bitmap
* ============================================================================ */
// A general purpose image
class gPixelMap {
public:
Extent16 size; // image size
uint8 *data;
// Compute the number of bytes in the pixel map
int32 bytes(void) {
return size.x * size.y;
}
};
// The simplest kind of pixel map is a static image
class gStaticImage : public gPixelMap {
public:
// constructors:
gStaticImage(void) {
size.x = size.y = 0;
data = NULL;
}
gStaticImage(int w, int h, uint8 *buffer) {
size.x = w;
size.y = h;
data = buffer;
}
};
// Automatically-remapped images: Eacn image adds itself to a
// chain at the time it is constructed, and will automatically
// remap to a new palette by calling the global remap() function.
class gMappedImage : public gPixelMap {
static gMappedImage *head; // first image in map chain
gMappedImage *next; // next image to remap
gPixelMap original;
public:
// Constructor and destructor
gMappedImage(int w, int h, uint8 *buffer);
virtual ~gMappedImage() {
if (data) free(data);
}
static void remap(gPen[]);
};
/* ============================================================================ *
gFont: A bitmapped font structure
* ============================================================================ */
struct gFont {
uint16 height; // height of the font
uint16 baseLine; // baseline of the font
uint16 rowMod; // row modulus for char data
uint16 charXOffset[256]; // offset of each char in data
int8 charWidth[256], // width of character in pixels
charKern[256], // character kern value
charSpace[256]; // character space value
// followed by (row_mod * height) bytes of character data
byte *fontdata;
};
// Prototypes
gFont *LoadFont(char *fontname);
void DisposeFont(gFont *font);
int16 TextWidth(gFont *font, const char *s, int16 length, int16 styles);
int16 WhichChar(gFont *font, uint8 *s, int16 length, int16 maxLen);
int16 WhichIChar(gFont *font, uint8 *s, int16 length, int16 maxLen);
int32 GTextWrap(gFont *font, char *mark, uint16 &count, uint16 width, int16 styles);
/* ============================================================================ *
gPenState: Used by gPorts to save the current state
* ============================================================================ */
struct gPenState {
gPen fgPen, // current foregroung pen
bgPen, // current drawing mode
olPen, // text outline pen
shPen; // text shadow pen
uint8 drawMode; // current drawing mode
};
/* ============================================================================ *
gPort: Facilitates redering operations on PixelMaps
* ============================================================================ */
enum draw_modes {
drawModeMatte = 0, // use transparency
drawModeColor, // solid color, use transparency
drawModeReplace, // don't use transparency
drawModeComplement, // blit in complement mode
numDrawModes
};
enum text_styles {
textStyleOutline = (1 << 0), // outline the characters
textStyleShadow = (1 << 1), // drop shadow the characters
textStyleUnderScore = (1 << 2), // underscore all chars
textStyleUnderBar = (1 << 3), // underscore char after a '_'
textStyleHiLiteBar = (1 << 4), // highlight char after a '_'
textStyleThickOutline = (1 << 5), // extra-thick outline
textStyleBold = (1 << 6), // bold
textStyleItalics = (1 << 7) // italic
};
enum text_positions {
textPosLeft = (1 << 0),
textPosRight = (1 << 1),
textPosHigh = (1 << 2),
textPosLow = (1 << 3)
};
class gPort {
public:
gPixelMap *map; // pointer to map
// Added by Talin to speed up rendering and allow inverted
// gPorts for WinG compatibility
uint8 *baseRow; // address of row 0
int16 rowMod; // modulus or row
Point16 origin; // origin drawing point
Rect16 clip; // clip region DrawPort
gPen fgPen, // current foregroung pen
bgPen, // current drawing mode
olPen, // text outline pen
shPen; // text shadow pen
gPen *penMap; // indirect pen map
enum draw_modes drawMode; // current drawing mode
Point16 penPos; // current pen position
gFont *font; // current font
int16 textSpacing; // extra space between characters
uint16 textStyles; // text style bits
// Constructor
gPort(void) {
map = nullptr;
baseRow = nullptr;
rowMod = 0;
penMap = nullptr;
drawMode = drawModeMatte;
font = nullptr;
textSpacing = 0;
textStyles = 0;
fgPen = bgPen = olPen = shPen = 0;
}
virtual ~gPort() {}
// Set attributes
virtual void setMap(gPixelMap *newmap, bool inverted = false);
// Direct colors
void setColor(gPen color) {
fgPen = color;
}
void setBgColor(gPen color) {
bgPen = color;
}
void setShadowColor(gPen color) {
shPen = color;
}
void setOutlineColor(gPen color) {
olPen = color;
}
// Indirect colors
void setPenMap(gPen *pmap) {
penMap = pmap;
}
void setIndirectColor(uint8 color) {
fgPen = penMap[color];
}
void setIndirectBgColor(uint8 color) {
bgPen = penMap[color];
}
void setIndirectShColor(uint8 color) {
shPen = penMap[color];
}
void setIndirectOLColor(uint8 color) {
olPen = penMap[color];
}
// modes & styles
void setMode(enum draw_modes mode) {
drawMode = mode;
}
void setStyle(int style) {
textStyles = style;
}
// Pen states
void setState(gPenState &);
void getState(gPenState &);
// REM: calc intersection of pixel map rect...
void setClip(const Rect16 &newclip) {
clip = newclip;
}
void getClip(Rect16 &r) {
r = clip;
}
void setOrigin(Point16 pt) {
origin = pt;
}
Point16 getOrigin(void) {
return origin;
}
// Pen position movement
void move(int16 x, int16 y) {
penPos.x += x;
penPos.y += y;
}
void move(Vector16 v) {
penPos += v;
}
void moveTo(int16 x, int16 y) {
penPos.x = x;
penPos.y = y;
}
void moveTo(Point16 p) {
penPos = p;
}
// Simple drawing functions
// REM: This should clip!
virtual void clear(void) {
memset(map->data, (int)fgPen, (int)map->bytes());
}
// Functions to set a single pixel
// NOTE: should this actually be a function pointer to deal
// with drawing mode?
virtual void setPixel(int16 x, int16 y, gPen color) {
if (x >= clip.x && x < clip.x + clip.width
&& y >= clip.y && y < clip.y + clip.height) {
baseRow[(y + origin.y) * rowMod + x + origin.x] = color;
}
}
void setPixel(int16 x, int16 y) {
setPixel(x, y, fgPen);
}
void setPixel(Point16 p, gPen color) {
setPixel(p.x, p.y, color);
}
void setPixel(Point16 p) {
setPixel(p.x, p.y, fgPen);
}
// pixel query functions
virtual gPen getPixel(int16 x, int16 y) {
return baseRow[(y + origin.y) * rowMod + x + origin.x];
}
virtual gPen getPixel(Point16 p) {
return baseRow[(p.y + origin.y) * rowMod + p.x + origin.x];
}
// Rectangle fill functions
virtual void fillRect(const Rect16 r);
void fillRect(int16 x, int16 y, int16 w, int16 h) {
fillRect(Rect16(x, y, w, h));
}
// Rectangle frame functions //
virtual void frameRect(const Rect16 r, int16 thick);
void frameRect(int16 x, int16 y, int16 w, int16 h, int16 thick) {
frameRect(Rect16(x, y, w, h), thick);
}
// Horiztonal and vertical lines
virtual void hLine(int16 x, int16 y, int16 width);
virtual void vLine(int16 x, int16 y, int16 height);
// Bresenham line-drawing functions
virtual void line(int16 x1, int16 y1, int16 x2, int16 y2);
void line(Point16 from, Point16 to) {
line(from.x, from.y, to.x, to.y);
}
void drawTo(int16 x, int16 y) {
line(penPos.x, penPos.y, x, y);
penPos.x = x;
penPos.y = y;
}
void drawTo(Point16 to) {
line(penPos, to);
penPos = to;
}
void draw(int16 x, int16 y) {
line(penPos.x, penPos.y, penPos.x + x, penPos.y + y);
penPos.x += x;
penPos.y += y;
}
void draw(Vector16 v) {
line(penPos, v);
penPos += v;
}
// Blitting functions
virtual void bltPixels(const gPixelMap &src,
int src_x, int src_y,
int dst_x, int dst_y,
int width, int height);
virtual void bltPixelMask(gPixelMap &src,
gPixelMap &msk,
int src_x, int src_y,
int dst_x, int dst_y,
int width, int height);
virtual void scrollPixels(const Rect16 r, int dx, int dy);
// Text rendering functions
void setFont(gFont *newFont) {
font = newFont;
}
void setTextSpacing(int16 fs) {
textSpacing = fs;
}
private:
// Unclipped text rendering
void drawStringChars(const char *, int16, gPixelMap &, int, int);
// Clipped but still low-level
int16 drawClippedString(const char *str, int16 len, int xpos, int ypos);
public:
// Draw a text string with the current settings at the
// current pen position. If the length is < 0, then use the
// natural string length.
void drawText(const char *str, int16 length = -1);
void drawTextInBox(const char *str, int16 length,
const Rect16 &r, int16 pos,
Point16 borders);
};
void mapImage(gPort &from, gPort &to, gPen map[]);
void mapImage(gPixelMap &from, gPixelMap &to, gPen map[]);
bool NewTempPort(gPort &, int width, int height);
void DisposeTempPort(gPort &);
/* ============================================================================ *
gSavePort: a class which auto-saves and auto-restores the port state
* ============================================================================ */
struct gSavePort {
gPenState state; // saved state of port
public:
gPort &port; // port which was saved
gSavePort(gPort &p) : port(p) {
port.getState(state);
}
~gSavePort() {
port.setState(state);
}
};
#define SAVE_GPORT_STATE(p) gSavePort sp( p )
} // end of namespace Saga2
#endif