Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 1 | pmbaty | 1 | /* | 
| 2 |  * Portions of this file are copyright Rebirth contributors and licensed as | ||
| 3 |  * described in COPYING.txt. | ||
| 4 |  * Portions of this file are copyright Parallax Software and licensed | ||
| 5 |  * according to the Parallax license below. | ||
| 6 |  * See COPYING.txt for license details. | ||
| 7 | |||
| 8 | THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX | ||
| 9 | SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO | ||
| 10 | END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A | ||
| 11 | ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS | ||
| 12 | IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS | ||
| 13 | SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE | ||
| 14 | FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE | ||
| 15 | CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS | ||
| 16 | AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. | ||
| 17 | COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED. | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* | ||
| 21 |  * | ||
| 22 |  * Definitions for graphics lib. | ||
| 23 |  * | ||
| 24 |  */ | ||
| 25 | |||
| 26 | #pragma once | ||
| 27 | |||
| 28 | #include <cassert> | ||
| 29 | #include "fwd-gr.h" | ||
| 30 | #include "pstypes.h" | ||
| 31 | #include "maths.h" | ||
| 32 | #include "palette.h" | ||
| 33 | #include "dxxsconf.h" | ||
| 34 | #include "dsx-ns.h" | ||
| 35 | #include "fmtcheck.h" | ||
| 36 | #include "pack.h" | ||
| 37 | #include <array> | ||
| 38 | |||
| 39 | struct grs_point | ||
| 40 | { | ||
| 41 |         fix x,y; | ||
| 42 | }; | ||
| 43 | |||
| 44 | struct grs_bitmap : prohibit_void_ptr<grs_bitmap> | ||
| 45 | { | ||
| 46 | uint16_t bm_x,bm_y; // Offset from parent's origin | ||
| 47 | uint16_t bm_w,bm_h; // width,height | ||
| 48 | private: | ||
| 49 | uint8_t bm_type; | ||
| 50 | uint8_t bm_flags; | ||
| 51 | public: | ||
| 52 | uint8_t get_type() const | ||
| 53 |         { | ||
| 54 | return bm_type; | ||
| 55 |         } | ||
| 56 | void set_type(uint8_t t) | ||
| 57 |         { | ||
| 58 | bm_type = t; | ||
| 59 |         } | ||
| 60 | uint8_t get_flags() const | ||
| 61 |         { | ||
| 62 | return bm_flags; | ||
| 63 |         } | ||
| 64 | uint8_t get_flag_mask(const uint8_t mask) const | ||
| 65 |         { | ||
| 66 | return get_flags() & mask; | ||
| 67 |         } | ||
| 68 | void set_flags(const uint8_t f) | ||
| 69 |         { | ||
| 70 | bm_flags = f; | ||
| 71 |         } | ||
| 72 | void clear_flags() | ||
| 73 |         { | ||
| 74 | set_flags(0); | ||
| 75 |         } | ||
| 76 | void set_flag_mask(const bool set, const uint8_t mask) | ||
| 77 |         { | ||
| 78 | const auto f = get_flags(); | ||
| 79 | set_flags(set ? f | mask : f & ~mask); | ||
| 80 |         } | ||
| 81 | void add_flags(const uint8_t f) | ||
| 82 |         { | ||
| 83 | bm_flags |= f; | ||
| 84 |         } | ||
| 85 |                             // bit 1 on means it has supertransparency | ||
| 86 |                             // bit 2 on means it doesn't get passed through lighting. | ||
| 87 | short bm_rowsize; // unsigned char offset to next row | ||
| 88 | std::array<fix, 3> avg_color_rgb; // same as above but real rgb value to be used to textured objects that should emit light | ||
| 89 | union { | ||
| 90 | const color_palette_index *bm_data; // ptr to pixel data... | ||
| 91 |                                         //   Linear = *parent+(rowsize*y+x) | ||
| 92 |                                         //   ModeX = *parent+(rowsize*y+x/4) | ||
| 93 |                                         //   SVGA = *parent+(rowsize*y+x) | ||
| 94 | color_palette_index *bm_mdata; | ||
| 95 | }; | ||
| 96 | const color_palette_index *get_bitmap_data() const { return bm_data; } | ||
| 97 | color_palette_index *get_bitmap_data() { return bm_mdata; } | ||
| 98 | struct grs_bitmap *bm_parent; | ||
| 99 | #if DXX_USE_OGL | ||
| 100 | struct ogl_texture *gltexture; | ||
| 101 | #else | ||
| 102 | uint8_t avg_color; // Average color of all pixels in texture map. | ||
| 103 | #endif /* def OGL */ | ||
| 104 | }; | ||
| 105 | |||
| 106 | struct grs_canvas : prohibit_void_ptr<grs_canvas> | ||
| 107 | { | ||
| 108 | ~grs_canvas() | ||
| 109 |         { | ||
| 110 |                 /* `grd_curcanv` points to the currently active canvas.  If it | ||
| 111 |                  * points to `this` when the destructor runs, then any further | ||
| 112 |                  * attempts to use the referenced canvas will access an | ||
| 113 |                  * out-of-scope variable, leading to undefined behavior.  Assert | ||
| 114 |                  * that `grd_curcanv` does not point to the expiring variable so | ||
| 115 |                  * that potential misuses are detected before they manifest as | ||
| 116 |                  * undefined behavior. | ||
| 117 |                  * | ||
| 118 |                  * If you get an assertion failure here, enable | ||
| 119 |                  * `DXX_DEBUG_CURRENT_CANVAS_ORIGIN` to trace where the canvas | ||
| 120 |                  * was most recently set. | ||
| 121 |                  * | ||
| 122 |                  * Eventually, `grd_curcanv` will be removed and this test will | ||
| 123 |                  * become obsolete. | ||
| 124 |                  */ | ||
| 125 | assert(this != grd_curcanv); | ||
| 126 |                 /* If the canvas is reset before next use, then no crash. | ||
| 127 |                  * If the canvas is not reset, then crash instead of accessing | ||
| 128 |                  * freed memory. | ||
| 129 |                  */ | ||
| 130 | if (grd_curcanv == this) | ||
| 131 | grd_curcanv = nullptr; | ||
| 132 |         } | ||
| 133 | grs_bitmap cv_bitmap; // the bitmap for this canvas | ||
| 134 | const grs_font * cv_font; // the currently selected font | ||
| 135 | short cv_font_fg_color; // current font foreground color (-1==Invisible) | ||
| 136 | short cv_font_bg_color; // current font background color (-1==Invisible) | ||
| 137 | unsigned cv_fade_level; // transparency level | ||
| 138 | }; | ||
| 139 | |||
| 140 | |||
| 141 | //========================================================================= | ||
| 142 | // System functions: | ||
| 143 | // setup and set mode. this creates a grs_screen structure and sets | ||
| 144 | // grd_curscreen to point to it.  grs_curcanv points to this screen's | ||
| 145 | // canvas.  Saves the current VGA state and screen mode. | ||
| 146 | |||
| 147 | #ifdef __cplusplus | ||
| 148 | union screen_mode | ||
| 149 | { | ||
| 150 | private: | ||
| 151 | uint32_t wh; | ||
| 152 | public: | ||
| 153 | struct { | ||
| 154 | uint16_t width, height; | ||
| 155 | }; | ||
| 156 | bool operator==(const screen_mode &rhs) | ||
| 157 |         { | ||
| 158 | return wh == rhs.wh; | ||
| 159 |         } | ||
| 160 | bool operator!=(const screen_mode &rhs) | ||
| 161 |         { | ||
| 162 | return !(*this == rhs); | ||
| 163 |         } | ||
| 164 | screen_mode() = default; | ||
| 165 | constexpr screen_mode(uint16_t &&w, uint16_t &&h) : | ||
| 166 | width(w), height(h) | ||
| 167 |         { | ||
| 168 |         } | ||
| 169 | }; | ||
| 170 | |||
| 171 | static inline uint16_t SM_W(const screen_mode &s) | ||
| 172 | { | ||
| 173 | return s.width; | ||
| 174 | } | ||
| 175 | |||
| 176 | static inline uint16_t SM_H(const screen_mode &s) | ||
| 177 | { | ||
| 178 | return s.height; | ||
| 179 | } | ||
| 180 | |||
| 181 | class grs_screen : prohibit_void_ptr<grs_screen> | ||
| 182 | { // This is a video screen | ||
| 183 |         screen_mode sc_mode; | ||
| 184 | public: | ||
| 185 | grs_canvas sc_canvas; // Represents the entire screen | ||
| 186 | fix sc_aspect; //aspect ratio (w/h) for this screen | ||
| 187 | uint16_t get_screen_width() const | ||
| 188 |         { | ||
| 189 | return SM_W(sc_mode); | ||
| 190 |         } | ||
| 191 | uint16_t get_screen_height() const | ||
| 192 |         { | ||
| 193 | return SM_H(sc_mode); | ||
| 194 |         } | ||
| 195 | screen_mode get_screen_mode() const | ||
| 196 |         { | ||
| 197 | return sc_mode; | ||
| 198 |         } | ||
| 199 | void set_screen_width_height(uint16_t w, uint16_t h) | ||
| 200 |         { | ||
| 201 | sc_mode.width = w; | ||
| 202 | sc_mode.height = h; | ||
| 203 |         } | ||
| 204 | }; | ||
| 205 | |||
| 206 | //========================================================================= | ||
| 207 | // Canvas functions: | ||
| 208 | |||
| 209 | // Makes a new canvas. allocates memory for the canvas and its bitmap, | ||
| 210 | // including the raw pixel buffer. | ||
| 211 | |||
| 212 | namespace dcx { | ||
| 213 | |||
| 214 | struct grs_main_canvas : grs_canvas | ||
| 215 | { | ||
| 216 | ~grs_main_canvas(); | ||
| 217 | }; | ||
| 218 | |||
| 219 | // Creates a canvas that is part of another canvas.  this can be used to make | ||
| 220 | // a window on the screen.  the canvas structure is malloc'd; the address of | ||
| 221 | // the raw pixel data is inherited from the parent canvas. | ||
| 222 | |||
| 223 | struct grs_subcanvas : grs_canvas {}; | ||
| 224 | |||
| 225 | // Free the bitmap and its pixel data | ||
| 226 | class grs_main_bitmap : public grs_bitmap | ||
| 227 | { | ||
| 228 | public: | ||
| 229 | grs_main_bitmap(); | ||
| 230 | grs_main_bitmap(const grs_main_bitmap &) = delete; | ||
| 231 | grs_main_bitmap &operator=(const grs_main_bitmap &) = delete; | ||
| 232 | grs_main_bitmap(grs_main_bitmap &&r) : | ||
| 233 | grs_bitmap(std::move(static_cast<grs_bitmap &>(r))) | ||
| 234 |         { | ||
| 235 | r.bm_data = nullptr; | ||
| 236 | #if DXX_USE_OGL | ||
| 237 | r.gltexture = nullptr; | ||
| 238 | #endif | ||
| 239 |         } | ||
| 240 | grs_main_bitmap &operator=(grs_main_bitmap &&r) | ||
| 241 |         { | ||
| 242 | if (this == &r) | ||
| 243 | return *this; | ||
| 244 | reset(); | ||
| 245 | grs_bitmap::operator=(std::move(static_cast<grs_bitmap &>(r))); | ||
| 246 | r.bm_data = nullptr; | ||
| 247 | #if DXX_USE_OGL | ||
| 248 | r.gltexture = nullptr; | ||
| 249 | #endif | ||
| 250 | return *this; | ||
| 251 |         } | ||
| 252 | ~grs_main_bitmap() | ||
| 253 |         { | ||
| 254 | reset(); | ||
| 255 |         } | ||
| 256 | void reset() | ||
| 257 |         { | ||
| 258 | gr_free_bitmap_data(*this); | ||
| 259 |         } | ||
| 260 | }; | ||
| 261 | |||
| 262 | // Free the bitmap, but not the pixel data buffer | ||
| 263 | class grs_subbitmap : public grs_bitmap | ||
| 264 | { | ||
| 265 | }; | ||
| 266 | |||
| 267 | //font structure | ||
| 268 | struct grs_font : public prohibit_void_ptr<grs_font> | ||
| 269 | { | ||
| 270 | int16_t ft_w; // Width in pixels | ||
| 271 | int16_t ft_h; // Height in pixels | ||
| 272 | int16_t ft_flags; // Proportional? | ||
| 273 | int16_t ft_baseline; // | ||
| 274 | uint8_t ft_minchar; // First char defined by this font | ||
| 275 | uint8_t ft_maxchar; // Last char defined by this font | ||
| 276 | std::array<char, 13> ft_filename; | ||
| 277 | const uint8_t *ft_data = nullptr; // Ptr to raw data. | ||
| 278 | const uint8_t *const *ft_chars = nullptr; // Ptrs to data for each char (required for prop font) | ||
| 279 | const int16_t *ft_widths = nullptr; // Array of widths (required for prop font) | ||
| 280 | const uint8_t *ft_kerndata = nullptr; // Array of kerning triplet data | ||
| 281 | std::unique_ptr<uint8_t[]> ft_allocdata; | ||
| 282 | #if DXX_USE_OGL | ||
| 283 |         // These fields do not participate in disk i/o! | ||
| 284 | std::unique_ptr<grs_bitmap[]> ft_bitmaps; | ||
| 285 |         grs_main_bitmap ft_parent_bitmap; | ||
| 286 | #endif /* def OGL */ | ||
| 287 | }; | ||
| 288 | |||
| 289 | } | ||
| 290 | |||
| 291 | static inline void gr_set_bitmap_flags(grs_bitmap &bm, uint8_t flags) | ||
| 292 | { | ||
| 293 | bm.set_flags(flags); | ||
| 294 | } | ||
| 295 | |||
| 296 | static inline void gr_set_transparent(grs_bitmap &bm, bool bTransparent) | ||
| 297 | { | ||
| 298 | bm.set_flag_mask(bTransparent, BM_FLAG_TRANSPARENT); | ||
| 299 | } | ||
| 300 | |||
| 301 | namespace dcx { | ||
| 302 | |||
| 303 | static inline void gr_set_font_fg_color(grs_canvas &canvas, int fg_color) | ||
| 304 | { | ||
| 305 | canvas.cv_font_fg_color = fg_color; | ||
| 306 | } | ||
| 307 | |||
| 308 | static inline void gr_set_font_fg_color(grs_canvas &canvas, color_palette_index fg_color) | ||
| 309 | { | ||
| 310 | canvas.cv_font_fg_color = static_cast<int>(fg_color); | ||
| 311 | } | ||
| 312 | |||
| 313 | static inline void gr_set_font_bg_color(grs_canvas &canvas, int bg_color) | ||
| 314 | { | ||
| 315 | canvas.cv_font_bg_color = bg_color; | ||
| 316 | } | ||
| 317 | |||
| 318 | static inline void gr_set_font_bg_color(grs_canvas &canvas, color_palette_index bg_color) | ||
| 319 | { | ||
| 320 | canvas.cv_font_bg_color = static_cast<int>(bg_color); | ||
| 321 | } | ||
| 322 | |||
| 323 | #define gr_set_fontcolor(C,F,B) \ | ||
| 324 |         ( DXX_BEGIN_COMPOUND_STATEMENT {        \ | ||
| 325 |                 auto &gr_set_fontcolor = C;     \ | ||
| 326 |                 gr_set_font_fg_color(gr_set_fontcolor, F);      \ | ||
| 327 |                 gr_set_font_bg_color(gr_set_fontcolor, B);      \ | ||
| 328 |                 } DXX_END_COMPOUND_STATEMENT ) | ||
| 329 | |||
| 330 | struct font_delete | ||
| 331 | { | ||
| 332 | void operator()(grs_font *p) const | ||
| 333 |         { | ||
| 334 | gr_close_font(std::unique_ptr<grs_font>(p)); | ||
| 335 |         } | ||
| 336 | }; | ||
| 337 | } | ||
| 338 | |||
| 339 | // Writes a string using current font. Returns the next column after last char. | ||
| 340 | static inline void gr_set_curfont(grs_canvas &canvas, const grs_font_ptr &p) | ||
| 341 | { | ||
| 342 | gr_set_curfont(canvas, p.get()); | ||
| 343 | } | ||
| 344 | |||
| 345 | static inline void (gr_set_current_canvas)(grs_canvas_ptr &canv DXX_DEBUG_CURRENT_CANVAS_FILE_LINE_COMMA_L_DECL_VARS) | ||
| 346 | { | ||
| 347 | (gr_set_current_canvas)(canv.get() DXX_DEBUG_CURRENT_CANVAS_FILE_LINE_COMMA_L_PASS_VARS); | ||
| 348 | } | ||
| 349 | |||
| 350 | static inline void (gr_set_current_canvas)(grs_subcanvas_ptr &canv DXX_DEBUG_CURRENT_CANVAS_FILE_LINE_COMMA_L_DECL_VARS) | ||
| 351 | { | ||
| 352 | (gr_set_current_canvas)(canv.get() DXX_DEBUG_CURRENT_CANVAS_FILE_LINE_COMMA_L_PASS_VARS); | ||
| 353 | } | ||
| 354 | |||
| 355 | #endif |