/* * 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 . --- 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() = default; grHardwareSurface(int w, int h, int bpp, unsigned flags = 0, const char *name = NULL); virtual ~grHardwareSurface() = default; 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() = default; 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