tdrawille.c - ploot - simple plotting tools HTML git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ploot DIR Log DIR Files DIR Refs DIR Tags DIR 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 }