1 // -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 // (c) 2016 Henner Zeller <h.zeller@acm.org>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation version 2.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program.  If not, see <http://gnu.org/licenses/gpl-2.0.txt>
15 
16 #ifndef UNICODE_BLOCK_CANVAS_H_
17 #define UNICODE_BLOCK_CANVAS_H_
18 
19 #include "terminal-canvas.h"
20 
21 #include <stddef.h>
22 #include <sys/types.h>
23 
24 namespace timg {
25 
26 // Canvas that can send a framebuffer to a terminal with either half
27 // or quarter blocks.
28 class UnicodeBlockCanvas final : public TerminalCanvas {
29 public:
30     // Create a terminal canvas, sending to given file-descriptor "fd".
31     // If "use_quarter" is set, use quarter blocks instead of half-blocks.
32     // if "use_upper_half_block" is set, uses the upper instead of the
33     // lower block (only for use_quarter == false).
34     // "use_256_color" is for terminals that can't do 24 bit colors.
35     UnicodeBlockCanvas(BufferedWriteSequencer *ws,
36                        bool use_quarter, bool use_upper_half_block,
37                        bool use_256_color);
38     ~UnicodeBlockCanvas() override;
39 
40     void Send(int x, int dy, const Framebuffer &framebuffer,
41               SeqType seq_type, Duration end_of_frame) override;
42 
43 private:
44     struct GlyphPick;
45     const bool use_quarter_blocks_;
46     const bool use_upper_half_block_;
47     const bool use_256_color_;
48 
49     // Ensure that all buffers needed for emitting the framebuffer have
50     // enough space.
51     // Return a buffer large enough to hold the whole ANSI-color encoded text
52     // to be used with the write sequencer.
53     char *RequestBuffers(int width, int height);
54 
55     template <int N, int colorbits>
56     char *AppendDoubleRow(char *pos, int indent, int width,
57                           const rgba_t *top_line,
58                           const rgba_t *bottom_line,
59                           bool emit_difference, int *y_skip);
60 
61     // Find best glyph for two rows of color.
62     template <int N>
63     GlyphPick FindBestGlyph(const rgba_t *top, const rgba_t *bottom) const;
64 
65     // Backing buffer stores a flattened view of last frame, storing top and
66     // bottom pixel linearly.
67     rgba_t *backing_buffer_ = nullptr;  // Remembering last frame
68     size_t backing_buffer_size_ = 0;
69     rgba_t *prev_content_it_;
70     int last_framebuffer_height_ = 0;
71     int last_x_indent_ = 0;
72 
73     rgba_t *empty_line_ = nullptr;
74     size_t empty_line_size_ = 0;
75 };
76 }  // namespace timg
77 
78 #endif  // UNICODE_BLOCK_CANVAS_H_
79