LCOV - code coverage report
Current view: top level - src/rendering - window.hh (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 55 58 94.8 %
Date: 2022-06-15 20:16:21 Functions: 8 8 100.0 %
Branches: 35 42 83.3 %

           Branch data     Line data    Source code
       1                 :            : #ifndef bqtRenderingScreenHH
       2                 :            : #define bqtRenderingScreenHH
       3                 :            : /** @file rendering/window.hh
       4                 :            :  * @brief Defines Window, a renderer and manager of screen contents.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <cstdint>
       8                 :            : #include <vector>
       9                 :            : #include <tuple>
      10                 :            : #include <cstring>
      11                 :            : 
      12                 :            : #include "cset.hh"
      13                 :            : #include "cell.hh"
      14                 :            : 
      15                 :            : /** Window: A two-dimensional storage for cells. */
      16                 :        407 : struct Window
      17                 :            : {
      18                 :            :     std::vector<Cell> cells; ///< Storage for cells. Indexed row-first. Size: xsize*ysize */
      19                 :            :     std::size_t       xsize; ///< Width of window in cells
      20                 :            :     std::size_t       ysize; ///< Height of window in cells
      21                 :            :     std::size_t       cursx=0; ///< Cursor location (horizontal)
      22                 :            :     std::size_t       cursy=0; ///< Cursor location (vertical)
      23                 :            :     bool              inverse   = false;            ///< Whether screen-wide inverse effect is in effect
      24                 :            :     bool              cursorvis = true;             ///< Whether cursor is visible
      25                 :            :     unsigned          cursorcolor = 0xFFFFFF;       ///< Color of cursor
      26                 :            :     unsigned          mousecolor1 = 0xFFFFFF;       ///< Ignored
      27                 :            :     unsigned          mousecolor2 = 0xFFFFFF;       ///< Ignored
      28                 :            :     unsigned          mouseselectcolor = 0xFFFFFF;  ///< Ignored
      29                 :            :     Cell blank {}; ///< The current "blank" cell. It is used as the model cell for inserting empty rows.
      30                 :            : private:
      31                 :            :     std::size_t lastcursx, lastcursy;
      32                 :            :     unsigned    lasttimer=0;
      33                 :            : public:
      34                 :            :     /** Initializes the window to the given size. Each cell is default-initialized. */
      35                 :        407 :     Window(std::size_t xs, std::size_t ys) : cells(xs*ys), xsize(xs), ysize(ys)
      36                 :            :     {
      37         [ +  - ]:        407 :         Dirtify();
      38                 :        407 :     }
      39                 :            : 
      40                 :            :     /** Used in scrolling: Fills the given region with the blank character. */
      41                 :         32 :     void FillBox(std::size_t x, std::size_t y, std::size_t width, std::size_t height)
      42                 :            :     {
      43         [ +  + ]:         88 :         for(std::size_t h=0; h<height; ++h)
      44         [ +  + ]:       4167 :             for(std::size_t w=0; w<width; ++w)
      45                 :            :             {
      46                 :       4111 :                 auto tx = x+w, ty = y+h;
      47                 :       4111 :                 PutCh(tx, ty, blank);
      48                 :            :             }
      49                 :         32 :     }
      50                 :            :     /** Used in erasing: Fills the given region with the given character,
      51                 :            :      * but does not change protected cells.
      52                 :            :      */
      53                 :        416 :     void FillBox(std::size_t x, std::size_t y, std::size_t width, std::size_t height, Cell with)
      54                 :            :     {
      55         [ +  + ]:       9424 :         for(std::size_t h=0; h<height; ++h)
      56         [ +  + ]:     713282 :             for(std::size_t w=0; w<width; ++w)
      57                 :            :             {
      58                 :     704274 :                 auto tx = x+w, ty = y+h;
      59   [ +  +  +  - ]:     704274 :                 if(with.ch != blank.ch || !cells[ty*xsize+tx].protect)
      60                 :     704274 :                     PutCh(tx, ty, with);
      61                 :            :             }
      62                 :        416 :     }
      63                 :            :     /** Copies a rectangle from given coordinates to the target coordinates.
      64                 :            :      * @param tgtx Target X-coordinate
      65                 :            :      * @param tgty Target Y-coordinate
      66                 :            :      * @param srcx Source X-coordinate
      67                 :            :      * @param srcy Source Y-coordinate
      68                 :            :      * @param width Width of region to copy
      69                 :            :      * @param height Height of region to copy
      70                 :            :      */
      71                 :         35 :     void CopyText(std::size_t tgtx,std::size_t tgty, std::size_t srcx,std::size_t srcy,
      72                 :            :                                                      std::size_t width,std::size_t height)
      73                 :            :     {
      74                 :        715 :         auto hcopy_oneline = [&](std::size_t ty, std::size_t sy)
      75                 :            :         {
      76         [ +  + ]:        680 :             if(tgtx < srcx)
      77         [ +  + ]:        240 :                 for(std::size_t w=0; w<width; ++w)
      78                 :        229 :                     PutCh(tgtx+w, ty, cells[sy*xsize+(srcx+w)]);
      79                 :            :             else
      80         [ +  + ]:      51293 :                 for(std::size_t w=width; w-- > 0; )
      81                 :      50624 :                     PutCh(tgtx+w, ty, cells[sy*xsize+(srcx+w)]);
      82                 :        715 :         };
      83         [ +  + ]:         35 :         if(tgty < srcy)
      84         [ +  + ]:        615 :             for(std::size_t h=0; h<height; ++h)
      85                 :        589 :                 hcopy_oneline(tgty+h, srcy+h);
      86                 :            :         else
      87         [ +  + ]:        100 :             for(std::size_t h=height; h-- > 0; )
      88                 :         91 :                 hcopy_oneline(tgty+h, srcy+h);
      89                 :         35 :     }
      90                 :            : 
      91                 :            :     /** Marks the given cell as dirty and places an invalid character there. */
      92                 :         32 :     void Dirtify(std::size_t x, std::size_t y)
      93                 :            :     {
      94         [ -  + ]:         32 :         auto& tgt = cells[y*xsize+x];
      95                 :            :         // Write an invalid character, to make sure it gets properly
      96                 :            :         // cleared when a valid character gets written instead.
      97                 :            :         // This glyph must _not_ register as doublewidth.
      98                 :         32 :         tgt.ch    = 0xFFFE;
      99         [ -  + ]:         32 :         tgt.dirty = true;
     100                 :            :     }
     101                 :            :     /** Marks entire screen as dirty (without changing ch)
     102                 :            :      * and forgets the cursor's last known position.
     103                 :            :       */
     104                 :            :     void Dirtify();
     105                 :            : 
     106                 :            :     /** Places a cell at the given position on screen.
     107                 :            :      * If the cell changed, it is marked dirty.
     108                 :            :      */
     109                 :     765374 :     void PutCh(std::size_t x, std::size_t y, const Cell& c)
     110                 :            :     {
     111         [ +  + ]:     765374 :         auto& tgt = cells[y*xsize+x];
     112         [ +  + ]:     765374 :         if(tgt != c)
     113                 :            :         {
     114                 :      49004 :             tgt = c;
     115                 :      49004 :             tgt.dirty = true;
     116                 :            :         }
     117                 :     765374 :     }
     118                 :            : 
     119                 :            :     /** Places a character at the given position on screen.
     120                 :            :      * Attributes are copied from the blank cell,
     121                 :            :      * except render_size which is kept unchanged.
     122                 :            :      */
     123                 :       6136 :     void PutCh(std::size_t x, std::size_t y, char32_t c, int cset = 0)
     124                 :            :     {
     125                 :            :         /*
     126                 :            :         cset options:
     127                 :            :         0 = ascii
     128                 :            :         1 = dec graphics
     129                 :            :         */
     130                 :       6136 :         Cell ch = blank;
     131         [ +  + ]:       6136 :         if(cset)
     132                 :            :         {
     133                 :          1 :             c = TranslateCSet(c, cset);
     134                 :            :         }
     135                 :       6136 :         ch.ch = c;
     136                 :       6136 :         ch.render_size = cells[y*xsize+x].render_size;
     137                 :            :         /*if(c != U' ')
     138                 :            :         {
     139                 :            :             fprintf(stderr, "Ch at (%zu,%zu): <%c>\n", x,y, int(c));
     140                 :            :         }*/
     141                 :       6136 :         PutCh(x, y, ch);
     142                 :       6136 :     }
     143                 :            :     /** Same as PutCh(x,y,c,cset), but instead of taking attributes from the blank
     144                 :            :      * cell, preserves existing attributes on screen.
     145                 :            :      */
     146                 :          1 :     void PutCh_KeepAttr(std::size_t x, std::size_t y, char32_t c, int cset = 0)
     147                 :            :     {
     148         [ -  + ]:          1 :         auto& cell = cells[y*xsize+x];
     149                 :          1 :         Cell temp = cell;
     150         [ -  + ]:          1 :         if(cset)
     151                 :          0 :             c = TranslateCSet(c, cset);
     152         [ -  + ]:          1 :         if(temp != cell)
     153                 :            :         {
     154                 :          0 :             cell = temp;
     155                 :          0 :             cell.dirty = true;
     156                 :            :         }
     157                 :          1 :     }
     158                 :            :     /** Same as PutCh(x,y,c), but preserves existing character symbol on screen. */
     159                 :            :     void PutCh_KeepChar(std::size_t x, std::size_t y, const Cell& c)
     160                 :            :     {
     161                 :            :         auto& cell = cells[y*xsize+x];
     162                 :            :         Cell temp = c;
     163                 :            :         temp.ch = cell.ch;
     164                 :            :         if(temp != cell)
     165                 :            :         {
     166                 :            :             cell = temp;
     167                 :            :             cell.dirty = true;
     168                 :            :         }
     169                 :            :     }
     170                 :            : 
     171                 :            :     /** Renders the screen into a pixel buffer using given font size.
     172                 :            :      * Only changed regions are rendered. Variables that are used to optimize
     173                 :            :      * the rendering (to save work) are the dirty flag in cells, lastcurs, lastcury and lasttimer.
     174                 :            :      *
     175                 :            :      * @param fx Font width in pixels.
     176                 :            :      * @param fy Font height in pixels.
     177                 :            :      * @param pixels Target buffer which must have room for at least fx*xsize*fy*ysize pixels.
     178                 :            :      */
     179                 :            :     void Render(std::size_t fx, std::size_t fy, std::uint32_t* pixels);
     180                 :            : 
     181                 :            :     /** Resizes the window to the new size, keeping existing contents.
     182                 :            :      * The entire screen is marked dirty. If the cursor is outside
     183                 :            :      * the new boundaries of the window, it is placed in the bottom row
     184                 :            :      * or rightmost column where necessary to keep it inside the boundaries.
     185                 :            :      */
     186                 :            :     void Resize(std::size_t newsx, std::size_t newsy);
     187                 :            : 
     188                 :            :     /** Changes the render_size attribute on current cursor line (cursy)
     189                 :            :      * to the specified value.
     190                 :            :      * @param val Value to be copied to the render_size attribute on the cells of that row.
     191                 :            :      *            0=normal, 1=doublewidth, 2=doublewidth+topline, 3=doublewidth+bottomline
     192                 :            :      */
     193                 :            :     void LineSetRenderSize(unsigned val);
     194                 :            : };
     195                 :            : 
     196                 :            : #endif

Generated by: LCOV version 1.16