|
|
tdrawille.c - ploot - simple plotting tools |
|
|
 |
git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ploot (git://bitreich.org) |
|
|
 |
Log |
|
|
 |
Files |
|
|
 |
Refs |
|
|
 |
Tags |
|
|
 |
README |
|
|
|
--- |
|
|
|
tdrawille.c (3892B) |
|
|
|
--- |
|
|
|
1 #include "drawille.h" |
|
|
|
2 |
|
|
|
3 #include <stdint.h> |
|
|
|
4 #include <stdio.h> |
|
|
|
5 #include <stdlib.h> |
|
|
|
6 #include <string.h> |
|
|
|
7 #include <math.h> |
|
|
|
8 |
|
|
|
9 #include "font.h" |
|
|
|
10 |
|
|
|
11 #include "log.h" /* XXX */ |
|
|
|
12 |
|
|
|
13 /* |
|
|
|
14 * Terminal-based plotting using drawille character, aka drawille. |
|
|
|
15 */ |
|
|
|
16 |
|
|
|
17 /* parameters used to draw a line */ |
|
|
|
18 struct line { |
|
|
|
19 int x0, y0, x1, y1; /* point of the line */ |
|
|
|
20 int dx, dy, sx, sy, err; /* parameters for the algorythm */ |
|
|
|
21 }; |
|
|
|
22 |
|
|
|
23 /* |
|
|
|
24 * Turn on the bit at position (row, col) of a single cell. The |
|
|
|
25 * pattern is not linear (1-4-2-5-3-6-7-8), because it matches the |
|
|
|
26 * drawille pattern. |
|
|
|
27 */ |
|
|
|
28 static void |
|
|
|
29 drawille_cell_dot(uint8_t *cell, int row, int col) |
|
|
|
30 { |
|
|
|
31 uint8_t flags[4][2] = { |
|
|
|
32 { 0x01, 0x08 }, |
|
|
|
33 { 0x02, 0x10 }, |
|
|
|
34 { 0x04, 0x20 }, |
|
|
|
35 { 0x40, 0x80 }, |
|
|
|
36 }; |
|
|
|
37 |
|
|
|
38 *cell |= flags[row][col]; |
|
|
|
39 } |
|
|
|
40 |
|
|
|
41 static size_t |
|
|
|
42 drawille_cell_utf(uint8_t cell, char *utf) |
|
|
|
43 { |
|
|
|
44 long rune; |
|
|
|
45 |
|
|
|
46 rune = 10240 + cell; |
|
|
|
47 utf[0] = (char)(0xe0 | (0x0f & (rune >> 12))); /* 1110xxxx */ |
|
|
|
48 utf[1] = (char)(0x80 | (0x3f & (rune >> 6))); /* 10xxxxxx */ |
|
|
|
49 utf[2] = (char)(0x80 | (0x3f & (rune))); /* 10xxxxxx */ |
|
|
|
50 return 3; |
|
|
|
51 } |
|
|
|
52 |
|
|
|
53 static uint8_t |
|
|
|
54 drawille_get(struct drawille *drw, int row, int col) |
|
|
|
55 { |
|
|
|
56 return drw->buf[row * drw->col + col]; |
|
|
|
57 } |
|
|
|
58 |
|
|
|
59 size_t |
|
|
|
60 drawille_put_row(FILE *fp, struct drawille *drw, int row) |
|
|
|
61 { |
|
|
|
62 char txt[] = "xxx"; |
|
|
|
63 size_t n; |
|
|
|
64 |
|
|
|
65 n = 0; |
|
|
|
66 for (int col = 0; col < drw->col; col++) { |
|
|
|
67 drawille_cell_utf(drawille_get(drw, row, col), txt); |
|
|
|
68 n += fputs(txt, fp); |
|
|
|
69 } |
|
|
|
70 return n; |
|
|
|
71 } |
|
|
|
72 |
|
|
|
73 /* |
|
|
|
74 * Coordinates are passed as (x, y), but the canvas stores bits as |
|
|
|
75 * (row, col). Conversion is made by this function. |
|
|
|
76 */ |
|
|
|
77 void |
|
|
|
78 drawille_dot(struct drawille *drw, int x, int y) |
|
|
|
79 { |
|
|
|
80 if (x < 0 || x / 2 >= drw->col || y < 0 || y / 4 >= drw->row) |
|
|
|
81 return; |
|
|
|
82 drawille_cell_dot(drw->buf + (drw->row - y / 4 - 1) * drw->col + (x / 2), |
|
|
|
83 3 - y % 4, |
|
|
|
84 x % 2); |
|
|
|
85 } |
|
|
|
86 |
|
|
|
87 struct drawille * |
|
|
|
88 drawille_new(int row, int col) |
|
|
|
89 { |
|
|
|
90 struct drawille *drw; |
|
|
|
91 |
|
|
|
92 if ((drw = calloc(sizeof(struct drawille) + row * col, 1)) == NULL) |
|
|
|
93 return NULL; |
|
|
|
94 drw->row = row; |
|
|
|
95 drw->col = col; |
|
|
|
96 return drw; |
|
|
|
97 } |
|
|
|
98 |
|
|
|
99 static void |
|
|
|
100 drawille_line_init(struct line *l, int x0, int y0, int x1, int y1) |
|
|
|
101 { |
|
|
|
102 l->x0 = x0; |
|
|
|
103 l->y0 = y0; |
|
|
|
104 l->x1 = x1; |
|
|
|
105 l->y1 = y1; |
|
|
|
106 l->sx = x0 < x1 ? 1 : -1; |
|
|
|
107 l->sy = y0 < y1 ? 1 : -1; |
|
|
|
108 l->dx = abs(x1 - x0); |
|
|
|
109 l->dy = abs(y1 - y0); |
|
|
|
110 l->err = (l->dx > l->dy ? l->dx : -l->dy) / 2; |
|
|
|
111 } |
|
|
|
112 |
|
|
|
113 static int |
|
|
|
114 drawille_line_next(struct line *l) |
|
|
|
115 { |
|
|
|
116 int e; |
|
|
|
117 |
|
|
|
118 if (l->x0 == l->x1 && l->y0 == l->y1) |
|
|
|
119 return 0; |
|
|
|
120 |
|
|
|
121 e = l->err; |
|
|
|
122 if (e > -l->dx) { |
|
|
|
123 l->x0 += l->sx; |
|
|
|
124 l->err -= l->dy; |
|
|
|
125 } |
|
|
|
126 if (e < l->dy) { |
|
|
|
127 l->y0 += l->sy; |
|
|
|
128 l->err += l->dx; |
|
|
|
129 } |
|
|
|
130 return 1; |
|
|
|
131 } |
|
|
|
132 |
|
|
|
133 void |
|
|
|
134 drawille_line(struct drawille *drw, int x0, int y0, int x1, int y1) |
|
|
|
135 { |
|
|
|
136 struct line l; |
|
|
|
137 |
|
|
|
138 drawille_line_init(&l, x0, y0, x1, y1); |
|
|
|
139 do { |
|
|
|
140 drawille_dot(drw, l.x0, l.y0); |
|
|
|
141 } while (drawille_line_next(&l)); |
|
|
|
142 } |
|
|
|
143 |
|
|
|
144 void |
|
|
|
145 drawille_histogram_dot(struct drawille *drw, int x, int y, int zero) |
|
|
|
146 { |
|
|
|
147 int sign; |
|
|
|
148 |
|
|
|
149 sign = (y > zero) ? (+1) : (-1); |
|
|
|
150 for (; y != zero; y -= sign) |
|
|
|
151 drawille_dot(drw, x, y); |
|
|
|
152 drawille_dot(drw, x, y); |
|
|
|
153 } |
|
|
|
154 |
|
|
|
155 void |
|
|
|
156 drawille_histogram_line(struct drawille *drw, int x0, int y0, int x1, int y1, int zero) |
|
|
|
157 { |
|
|
|
158 struct line l; |
|
|
|
159 |
|
|
|
160 drawille_line_init(&l, x0, y0, x1, y1); |
|
|
|
161 do { |
|
|
|
162 drawille_histogram_dot(drw, l.x0, l.y0, zero); |
|
|
|
163 } while (drawille_line_next(&l)); |
|
|
|
164 } |
|
|
|
165 |
|
|
|
166 static int |
|
|
|
167 drawille_text_glyph(struct drawille *drw, int x, int y, struct font *font, char c) |
|
|
|
168 { |
|
|
|
169 int width; |
|
|
|
170 char *glyph; |
|
|
|
171 |
|
|
|
172 if ((unsigned)c > 127) |
|
|
|
173 glyph = font->glyph[0]; |
|
|
|
174 else |
|
|
|
175 glyph = font->glyph[(unsigned)c]; |
|
|
|
176 |
|
|
|
177 width = strlen(glyph) / font->height; |
|
|
|
178 |
|
|
|
179 for (int ix = 0; ix < width; ix++) |
|
|
|
180 for (int iy = 0; iy < font->height; iy++) { |
|
|
|
181 if (glyph[ix + (font->height - 1) * width - iy * width] == 3) |
|
|
|
182 drawille_dot(drw, x + ix, y + iy); |
|
|
|
183 } |
|
|
|
184 |
|
|
|
185 return width; |
|
|
|
186 } |
|
|
|
187 |
|
|
|
188 char * |
|
|
|
189 drawille_text(struct drawille *drw, int x, int y, struct font *font, char *s) |
|
|
|
190 { |
|
|
|
191 if (drw->row*4 < font->height) |
|
|
|
192 return NULL; |
|
|
|
193 for (; *s != '\0' && x < drw->col * 2; s++, x++) |
|
|
|
194 x += drawille_text_glyph(drw, x, y, font, *s); |
|
|
|
195 return s; |
|
|
|
196 } |
|