drawille.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 DIR 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))); /* 1110xxxx */ 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 + (x / 2), 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)) == NULL) 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, int y1, int zero) 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 *font, int c) 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] == 3) 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, char *s) 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 }