Descent3/2dlib/gr.h
Jan Engelhardt 71772b9c9c Add "final" marker to a number of classes
Devirtualization is an optimization in the generated assembly: when a
class C is polymorphic but also final, ``((C *)ptr)->func()`` can be
turned from an indirect into a static call.
2024-11-03 23:39:37 +01:00

567 lines
18 KiB
C++

/*
* Descent 3
* Copyright (C) 2024 Parallax Software
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
--- HISTORICAL COMMENTS FOLLOW ---
* $Logfile: /DescentIII/Main/Lib/gr.h $
* $Revision: 18 $
* $Date: 4/17/99 6:15p $
* $Author: Samir $
*
* the 2d lib main header
*
* $Log: /DescentIII/Main/Lib/gr.h $
*
* 18 4/17/99 6:15p Samir
* replaced gr.h with grdefs.h and fixed resulting compile bugs.
*
* 17 4/14/99 3:59a Jeff
* fixed case mismatches in #includes
*
* 16 11/30/98 5:50p Jason
* added 4444 bitmap support
*
* 15 12/29/97 5:50p Samir
* Moved GR_COLOR_CHAR to grdefs.h from gr.h.
*
* 14 12/22/97 7:39p Samir
* Moved color constants from gr.h to grdefs.h
*
* 13 12/22/97 7:13p Samir
* Moved constants to grdefs.h
*
* 12 12/19/97 12:33p Samir
* Added alpha for text and took out abilitiy to create viewports inside
* viewports.
*
* 11 12/12/97 6:40p Samir
* Some viewport font functions.
*
* 10 11/16/97 6:54p Samir
* Added font::get_name function.
*
* 9 11/16/97 2:20p Samir
* Added macro to draw a bitmap to a viewport.
*
* 8 11/11/97 1:27p Samir
* Added functions to set text alpha values.
*
* 7 11/04/97 4:57p Samir
* Added get_text_color.
*
* 6 10/13/97 3:56p Jason
* made a better 3d bitmap system
*
* 5 10/03/97 11:59a Samir
* Added some color constants.
*
* 4 9/19/97 5:37p Samir
* Software font coloring works.
*
* 1 6/23/97 9:25p Samir
* added because source safe sucks
*
* 39 6/16/97 3:01p Samir
* Changed font system to work better with renderer. Fonts are rendered
* on bitmaps of 128x128 at load time.
*
* 38 6/12/97 6:30p Samir
* DDGR v2.0 Changes in 2d system implemented.
*
* 37 6/09/97 3:47p Jason
* fixed some color mapping problems
*
* 36 5/21/97 3:39p Jason
* added terrain editing stuff
*
* 35 5/21/97 1:08p Samir
* added conversion from 565 to ddgr_color format.
*
* 34 5/15/97 2:08p Samir
* Added grSurface::get_surface_desc and grViewport::get_parent.
*
* 33 5/13/97 6:36p Samir
* added lock_clear functions.
*
*
* $NoKeywords: $
*/
#ifndef _GR_H
#define _GR_H
#include "Ddgr.h"
#include "fix.h"
#include "pserror.h"
class grMemorySurface;
class grViewport;
class grSurface;
class grPen;
// a 'pen' structure used by the 2d system to draw things.
struct gr_pen {
char *data;
int rowsize;
ddgr_color rgbcolor;
ddgr_color color;
ddgr_surface *sf;
};
enum grTextAlign { // used to align text along viewport
grTextUnjustified,
grTextLeft,
grTextCentered,
grTextRight,
grTextWordWrap
};
struct tCharProperties {
uint8_t alpha;
ddgr_color col[4];
};
#define GR_VPCP_ALPHA 1 // alpha value is valid in CharProperties
#define GR_VPCP_COLOR 2 // color values are valid in CharProperties.
#define GR_VPCP_ALL (1 + 2)
// ----------------------------------------------------------------------------
// class grFont
// will load and manage a font's capabilities.
// all fonts are stored in a 16bit hicolor format, or bitmasked.
// ----------------------------------------------------------------------------
const int MAX_FONTS = 16, MAX_FONT_BITMAPS = 12;
#define DEFAULT_FONT 0
struct gr_font_file_record {
int16_t width, height; // width of widest character and height of longest char
int16_t flags; // flags used by the character renderer
int16_t baseline; // pixels given to lowercase below script line start at baseline
uint8_t min_ascii; // minimum ascii value used by font
uint8_t max_ascii; // max ascii value used by the font
int16_t byte_width; // width of a character in the font in bytes
uint8_t *raw_data; // pixel, map data.
uint8_t **char_data; // pointers to each character
int16_t *char_widths; // individual pixel widths of each character
uint8_t *kern_data; // kerning information for specific letter combos
};
struct gr_font_record {
char name[32];
char filename[32]; // filename of font
int references; // number of references of that font
int bmps[MAX_FONT_BITMAPS]; // font bitmap handles
grMemorySurface *surfs[MAX_FONT_BITMAPS];
uint8_t *ch_u, *ch_v, *ch_w, *ch_h, *ch_surf;
float *ch_uf, *ch_vf, *ch_wf, *ch_hf;
gr_font_file_record font;
};
class grFont {
static gr_font_record m_FontList[MAX_FONTS];
static grMemorySurface *m_CharSurf;
int m_FontHandle; // offset into m_FontList
public:
grFont();
~grFont();
grFont(const grFont &font) { m_FontHandle = font.m_FontHandle; };
const grFont &operator=(const grFont &font) {
m_FontHandle = font.m_FontHandle;
return *this;
};
public: // Manipulation functions
static void init_system();
static void close_system();
static int register_font(char *fontname, char *filename);
void init(const char *fontname);
void free();
// draw_char returns the next x value taking spacing and kerning into consideration.
int draw_char(grSurface *sf, int x, int y, int ch, tCharProperties *chprop);
int draw_char(grSurface *sf, int x, int y, int ch, int sx, int sy, int sw, int sh, tCharProperties *chprop);
private:
static void free_font(gr_font_record *ft);
static void load(char *filename, int slot);
static void translate_to_surfaces(int slot);
static void translate_mono_char(grSurface *sf, int x, int y, int index, gr_font_file_record *ft, int width);
uint8_t *get_kern_info(uint8_t c1, uint8_t c2);
void charblt16(grSurface *dsf, ddgr_color col, int dx, int dy, grSurface *ssf, int sx, int sy, int sw, int sh);
public: // Accessor functions
char *get_name() const {
if (m_FontHandle == -1)
return NULL;
else
return m_FontList[m_FontHandle].name;
};
int min_ascii() const {
ASSERT(m_FontHandle > -1);
return m_FontList[m_FontHandle].font.min_ascii;
};
int max_ascii() const {
ASSERT(m_FontHandle > -1);
return m_FontList[m_FontHandle].font.max_ascii;
};
int height() const {
ASSERT(m_FontHandle > -1);
return m_FontList[m_FontHandle].font.height;
};
int get_char_info(int ch, int *width);
};
// ----------------------------------------------------------------------------
// class grSurface
// contains a ddgr_bitmap object and allows for blting
// ----------------------------------------------------------------------------
struct ddgr_surface_node {
ddgr_surface *sf;
ddgr_surface_node *prev;
};
const int SURFTYPE_MEMORY = 256;
const int SURFFLAG_RENDERER = 256; // SURFACE will use renderer functions.
class grSurface {
public:
static void init_system(); // initializes some global stuff for surface system
static void close_system();
private:
friend class grViewport;
int surf_Locked; // same value for all grViewport objects
int m_SurfInit; // surface initialized
char *m_OrigDataPtr; // non-adjusted data pointer
char *m_DataPtr; // adjusted data pointer
int m_DataRowsize; // Data rowsize
static ddgr_surface_node *surf_list; // the surface list
static ddgr_surface_node *surf_list_cur; // current node on list.
static ddgr_surface *scratch_mem_surf; // use as temporary memory surface
private:
// coversion blts.
void xlat8_16(char *data, int w, int h, char *pal);
void xlat16_16(char *data, int w, int h, int format = 0);
void xlat16_24(char *data, int w, int h);
void xlat24_16(char *data, int w, int h);
void xlat32_16(char *data, int w, int h);
void uniblt(int dx, int dy, grSurface *ssf, int sx, int sy, int sw, int sh);
protected:
ddgr_surface ddsfObj; // Used to call ddgr_surf_ functions
protected:
void add_to_list(ddgr_surface *sf); // used for surface heap management
void remove_from_list(ddgr_surface *sf);
int surf_init() const { return m_SurfInit; };
void surf_init(int init) { m_SurfInit = init; };
public:
grSurface();
virtual ~grSurface();
// creates a surface, allocates memory based off of parameters.
grSurface(int w, int h, int bpp, unsigned type, unsigned flags = 0, const char *name = NULL);
public:
unsigned get_flags() const { return ddsfObj.flags; };
void create(int w, int h, int bpp, unsigned type, unsigned flags = 0, const char *name = NULL);
void load(char *data, int w, int h, int bpp, int format = 0);
void load(int handle);
void load(char *data, int w, int h, char *pal);
void load(int handle, char *pal);
void free(); // non-dynamic version
int width() const {
ASSERT(m_SurfInit);
return ddsfObj.w;
};
int height() const {
ASSERT(m_SurfInit);
return ddsfObj.h;
};
int bpp() const {
ASSERT(m_SurfInit);
return ddsfObj.bpp;
};
unsigned flags() const {
ASSERT(m_SurfInit);
return ddsfObj.flags;
};
int rowsize() const {
ASSERT(m_SurfInit);
return m_DataRowsize;
};
char *data() const {
ASSERT(m_SurfInit);
return m_DataPtr;
};
void clear(ddgr_color col = 0);
void clear(int l, int t, int w, int h, ddgr_color col = 0);
void replace_color(ddgr_color sc, ddgr_color dc);
void blt(int dx, int dy, grSurface *ssf);
void blt(int dx, int dy, grSurface *ssf, int sx, int sy, int sw, int sh);
char *lock(int *rowsize);
char *lock(int x, int y, int *rowsize);
void unlock();
void get_surface_desc(ddgr_surface *surf) { *surf = ddsfObj; };
// This is VERY system dependent when called, sorry but I think this may be necessary
void attach_to_window(unsigned handle);
};
// ----------------------------------------------------------------------------
// class grMemorySurface
// this is a software bitmap not video driver dependant
// ----------------------------------------------------------------------------
class grMemorySurface final : public grSurface {
bool m_FirstTimeInit; // do special stuff if we are initializing for first time
bool m_AllowInit; // we only allow initialization if we didn't create it.
public:
grMemorySurface();
virtual ~grMemorySurface();
// allocates a surface from system memory (quicker version of grSurface)
grMemorySurface(int w, int h, int bpp, unsigned flags = 0, const char *name = NULL);
// initializes a surface using a bitmap handle (no allocation)
grMemorySurface(int bm);
// inititalizes a surface using raw data,width,rowsize info information.
bool init(int w, int h, int bpp, char *data, int rowsize, unsigned flags = 0, const char *name = NULL);
};
// ----------------------------------------------------------------------------
// class grHardwareSurface
// this is a hardware bitmap allocated from the video driver
// ----------------------------------------------------------------------------
class grHardwareSurface final : public grSurface {
public:
grHardwareSurface();
grHardwareSurface(int w, int h, int bpp, unsigned flags = 0, const char *name = NULL);
virtual ~grHardwareSurface();
bool create(int w, int h, int bpp, unsigned flags = 0, const char *name = NULL);
};
// ----------------------------------------------------------------------------
// class grScreen
// child class of grSurface. Handles initializing the screen, and
// is used by the grViewport class to draw onto the screen
// ----------------------------------------------------------------------------
class grScreen final : public grSurface {
friend class grViewport;
public:
grScreen(int w, int h, int bpp, const char *name = NULL);
virtual ~grScreen();
void flip();
};
// ----------------------------------------------------------------------------
// class grViewport
// a viewport is a bounded rectangle on either a screen or bitmap.
// one should be able to draw any 2d object on a viewport region.
// ----------------------------------------------------------------------------
// contains state information for a viewport.
struct tVPState {
grFont font;
int text_spacing;
int text_line_spacing;
tCharProperties chprops;
};
class grViewport {
static int vp_Locked; // tells us if any viewport is locked
static grViewport *vp_Current_VP; // current locked viewport
grFont text_Font;
int text_Spacing;
int text_Line_spacing;
tCharProperties char_Props;
private:
void draw_text_line(int x, int y, char *str);
void draw_text_line_clip(int x, int y, char *str);
int clip_rect(int &x1, int &y1, int &x2, int &y2);
protected:
int vp_Left, vp_Top, vp_Right, // viewport's global screen/bitmap bounds
vp_Bottom;
int vp_InitLeft, vp_InitTop, vp_InitRight, vp_InitBottom; // viewport's initial global screen coords
grSurface *sf_Parent; // bitmap where viewport points to
gr_pen pen_Obj;
public:
grViewport(grScreen *scr_parent);
grViewport(grSurface *sf_parent);
~grViewport();
grSurface *get_parent() const { return sf_Parent; };
// these are the viewport's initial bounds with respect to parent surface
// these can't be changed.
int width() const { return (vp_InitRight - vp_InitLeft) + 1; };
int height() const { return (vp_InitBottom - vp_InitTop) + 1; };
int left() const { return vp_InitLeft; };
int top() const { return vp_InitTop; };
int right() const { return vp_InitRight; };
int bottom() const { return vp_InitBottom; };
// these clipping coordinates are local to the viewports initial rectangle, based off
// of parent surface. All 2d functions use these coords to base their drawing.
// If we draw at (0,0) and the clip region is at (80,90,200,160) then we will draw at 80,90.
int clip_width() const { return (vp_Right - vp_Left) + 1; };
int clip_height() const { return (vp_Bottom - vp_Top) + 1; };
int clip_left() const { return vp_Left; };
int clip_top() const { return vp_Top; };
int clip_right() const { return vp_Right; };
int clip_bottom() const { return vp_Bottom; };
void set_clipping_rect(int left, int top, int right, int bottom);
// these convert local viewport coords to global screen/surface coords
int global_x(int lx) const { return vp_InitLeft + vp_Left + lx; };
int global_y(int ly) const { return vp_InitTop + vp_Top + ly; };
int local_x(int gx) const { return gx - vp_Left - vp_InitLeft; };
int local_y(int gy) const { return gy - vp_Top - vp_InitTop; };
// these functions set and restore the state of the viewport (font, colors, etc.)
void get_state(tVPState *state);
void set_state(const tVPState *state);
// bltting functions on viewport
void clear(ddgr_color col = 0); // clear with background color
void lock_clear(ddgr_color col = 0); // software clear. must be used in lock
void lock_clear(ddgr_color col, int l, int t, int w, int h);
void blt(int dx, int dy, grSurface *ssf);
void blt(int dx, int dy, grSurface *ssf, int sx, int sy, int sw, int sh);
public:
grSurface *lock(); // lock and
void unlock(); // unlock (implicitly locks surface)
// these functions only work on locked surfaces.
void hline(ddgr_color, int x1, int x2, int y1);
void line(ddgr_color color, int x1, int y1, int x2, int y2);
void rect(ddgr_color color, int l, int t, int r, int b);
void fillrect(ddgr_color color, int l, int t, int r, int b);
void setpixel(ddgr_color col, int x, int y);
void setpixelc(ddgr_color col, int x, int y);
ddgr_color getpixel(int x, int y);
ddgr_color getpixelc(int x, int y);
void circle(ddgr_color col, int xc, int yc, int r);
void fillcircle(ddgr_color col, int xc, int yc, int r);
// end
public:
// These functions only work on locked surfaces
int printf(grTextAlign align, int x, int y, char *fmt, ...);
int printf(int x, int y, char *fmt, ...);
int puts(grTextAlign align, int x, int y, char *str);
int puts(int x, int y, char *str);
// text formatting functions
public:
int get_text_line_width(char *text);
void set_font(const char *fontname);
void get_font(char *fontname, int size);
int get_current_font_height() const { return text_Font.height(); };
int get_text_spacing() const { return text_Spacing; };
int get_text_line_spacing() const { return text_Line_spacing; };
void set_text_spacing(int spacing) { text_Spacing = spacing; };
void set_text_line_spacing(int spacing) { text_Line_spacing = spacing; };
// visual properties of text functions
public:
void set_text_color(ddgr_color color);
ddgr_color get_text_color() const;
void set_char_properties(unsigned flags, const tCharProperties *props);
void get_char_properties(tCharProperties *props) const;
// end
};
// inline definitions for grViewport functions
inline void grViewport::set_text_color(ddgr_color color) {
char_Props.col[0] = color;
char_Props.col[1] = color;
char_Props.col[2] = color;
char_Props.col[3] = color;
}
inline ddgr_color grViewport::get_text_color() const { return char_Props.col[0]; }
inline void grViewport::set_char_properties(unsigned flags, const tCharProperties *props) {
if (flags & GR_VPCP_COLOR) {
char_Props.col[0] = props->col[0];
char_Props.col[1] = props->col[1];
char_Props.col[2] = props->col[2];
char_Props.col[3] = props->col[3];
}
if (flags & GR_VPCP_ALPHA) {
char_Props.alpha = props->alpha;
}
}
inline void grViewport::get_char_properties(tCharProperties *props) const {
props->col[0] = char_Props.col[0];
props->col[1] = char_Props.col[1];
props->col[2] = char_Props.col[2];
props->col[3] = char_Props.col[3];
props->alpha = char_Props.alpha;
}
// useful macros
static inline void VP_BITBLT(grViewport *vp, int dx, int dy, int bm) {
grMemorySurface surf(bm);
vp->blt(dx, dy, &surf);
}
#endif