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