1 /*
2  * Copyright (C) 2014 haru <uobikiemukot at gmail dot com>
3  * Copyright (C) 2014 Hayaki Saito <user@zuse.jp>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "config.h"
20 #include "yaft.h"
21 #include "util.h"
22 #include "pseudo.h"
23 
24 #if HAVE_STRING_H
25 # include <string.h>
26 #endif
27 
28 #if !defined(HAVE_MEMCPY)
29 # define memcpy(d, s, n) (bcopy ((s), (d), (n)))
30 #endif
31 
draw_sixel(struct pseudobuffer * pb,int line,int col,uint8_t * bitmap)32 static void draw_sixel(struct pseudobuffer *pb, int line, int col, uint8_t *bitmap)
33 {
34     int h, w, src_offset, dst_offset;
35     uint32_t pixel, color = 0;
36 
37     for (h = 0; h < CELL_HEIGHT; h++) {
38         for (w = 0; w < CELL_WIDTH; w++) {
39             src_offset = BYTES_PER_PIXEL * (h * CELL_WIDTH + w);
40             memcpy(&color, bitmap + src_offset, BYTES_PER_PIXEL);
41 
42             dst_offset = (line * CELL_HEIGHT + h) * pb->line_length + (col * CELL_WIDTH + w) * pb->bytes_per_pixel;
43             //pixel = color2pixel(&pb->vinfo, color);
44             pixel = color;
45             memcpy(pb->buf + dst_offset, &pixel, pb->bytes_per_pixel);
46         }
47     }
48 }
49 
draw_line(struct pseudobuffer * pb,struct terminal * term,int line)50 static void draw_line(struct pseudobuffer *pb, struct terminal *term, int line)
51 {
52     int pos, bdf_padding, glyph_width, margin_right;
53     int col, w, h;
54     uint32_t pixel;
55     struct color_pair_t color_pair;
56     struct cell_t *cellp;
57 
58     for (col = term->cols - 1; col >= 0; col--) {
59         margin_right = (term->cols - 1 - col) * CELL_WIDTH;
60 
61         /* target cell */
62         cellp = &term->cells[col + line * term->cols];
63 
64         /* draw sixel bitmap */
65         if (cellp->has_bitmap) {
66             draw_sixel(pb, line, col, cellp->bitmap);
67             continue;
68         }
69 
70         /* copy current color_pair (maybe changed) */
71         color_pair = cellp->color_pair;
72 
73         /* check wide character or not */
74         glyph_width = (cellp->width == HALF) ? CELL_WIDTH: CELL_WIDTH * 2;
75         bdf_padding = my_ceil(glyph_width, BITS_PER_BYTE) * BITS_PER_BYTE - glyph_width;
76         if (cellp->width == WIDE)
77             bdf_padding += CELL_WIDTH;
78 
79         /* check cursor positon */
80         if ((term->mode & MODE_CURSOR && line == term->cursor.y)
81             && (col == term->cursor.x
82             || (cellp->width == WIDE && (col + 1) == term->cursor.x)
83             || (cellp->width == NEXT_TO_WIDE && (col - 1) == term->cursor.x))) {
84             color_pair.fg = term->default_bg;
85             color_pair.bg = term->cursor_color;
86         }
87 
88         for (h = 0; h < CELL_HEIGHT; h++) {
89             /* if UNDERLINE attribute on, swap bg/fg */
90             if ((h == (CELL_HEIGHT - 1)) && (cellp->attribute & attr_mask[ATTR_UNDERLINE]))
91                 color_pair.bg = color_pair.fg;
92 
93             for (w = 0; w < CELL_WIDTH; w++) {
94                 pos = (term->width - 1 - margin_right - w) * pb->bytes_per_pixel
95                     + (line * CELL_HEIGHT + h) * pb->line_length;
96 
97                 /* set color palette */
98                 if (cellp->glyphp->bitmap[h] & (0x01 << (bdf_padding + w)))
99                     pixel = color_list[color_pair.fg];
100                 else
101                     pixel = color_list[color_pair.bg];
102 
103                 /* update copy buffer only */
104                 memcpy(pb->buf + pos, &pixel, pb->bytes_per_pixel);
105             }
106         }
107     }
108     term->line_dirty[line] = ((term->mode & MODE_CURSOR) && term->cursor.y == line) ? true: false;
109 }
110 
refresh(struct pseudobuffer * pb,struct terminal * term)111 void refresh(struct pseudobuffer *pb, struct terminal *term)
112 {
113     int line;
114 
115     if (term->mode & MODE_CURSOR)
116         term->line_dirty[term->cursor.y] = true;
117 
118     for (line = 0; line < term->lines; line++) {
119         if (term->line_dirty[line])
120             draw_line(pb, term, line);
121     }
122 }
123 
124 /* emacs, -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
125 /* vim: set expandtab ts=4 : */
126 /* EOF */
127