├── .gitignore ├── README.md ├── circle.awk ├── makefile ├── tplot.c └── tplot.h /.gitignore: -------------------------------------------------------------------------------- 1 | tplot 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tplot 2 | terminal plotter using braille characters 3 | 4 | ![scrot](https://i.imgur.com/u2lNqK9.png) 5 | 6 | ### input formats 7 | 8 | `1 1 to 25 25` for drawing lines. 9 | 10 | `1 1` for setting a "dot". 11 | -------------------------------------------------------------------------------- /circle.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | 3 | BEGIN { 4 | pi = 3.14159; 5 | c = 50; 6 | r = 45; 7 | 8 | for (i=0; i < pi * 2; i += pi/10) { 9 | x = cos(i) * r; 10 | y = sin(i) * r; 11 | 12 | printf("%d %d to %d %d\n", c + x, c + y, c, c); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -g -Wextra 2 | 3 | tplot: tplot.c 4 | 5 | clean: 6 | rm tplot 7 | -------------------------------------------------------------------------------- /tplot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "tplot.h" 9 | 10 | static unsigned char *cells; 11 | static struct winsize ws; 12 | 13 | /* 14 | * print a braille "pixel" 15 | */ 16 | void 17 | dot(int rx, int ry) { 18 | int y, x; 19 | unsigned char *p; 20 | 21 | if (rx > (ws.ws_col * 2) || rx < 1 || ry > (ws.ws_row * 4) || ry < 1) { 22 | warnx("out of bounds"); 23 | return; 24 | } 25 | 26 | x = (rx - 1) / 2; 27 | y = (ry - 1) / 4; 28 | 29 | /* A B 30 | * C D 31 | * E F 32 | * G H 33 | */ 34 | 35 | p = cells; 36 | p += (y * ws.ws_col) + x; 37 | 38 | 39 | switch (ry % 4) { 40 | case 1: /* A B */ 41 | *p |= rx & 1 ? FIELD_A : FIELD_B; 42 | break; 43 | case 2: /* C D */ 44 | *p |= rx & 1 ? FIELD_C : FIELD_D; 45 | break; 46 | case 3: /* E F */ 47 | *p |= rx & 1 ? FIELD_E : FIELD_F; 48 | break; 49 | case 0: /* G H */ 50 | *p |= rx & 1 ? FIELD_G : FIELD_H; 51 | break; 52 | } 53 | 54 | /* find the right char to print via table */ 55 | printf("\033[%u;%uH%lc", y + 1, x + 1, *p | BRAILLE_EMPTY); 56 | } 57 | 58 | /* 59 | * dot() a line from x0, y0 to x1, y1 60 | */ 61 | void 62 | line(int x0, int y0, int x1, int y1) { 63 | int dx = abs(x1 - x0); 64 | int dy = abs(y1 - y0); 65 | int sx = x0 < x1 ? 1 : -1; 66 | int sy = y0 < y1 ? 1 : -1; 67 | int er = (dx > dy ? dx : -dy) / 2; 68 | int e2; 69 | 70 | for (;;) { 71 | dot(x0, y0); 72 | 73 | if (x0 == x1 && y0 == y1) 74 | break; 75 | 76 | e2 = er; 77 | 78 | if (e2 > -dx) { 79 | er -= dy; 80 | x0 += sx; 81 | } 82 | 83 | if (e2 < dy) { 84 | er += dx; 85 | y0 += sy; 86 | } 87 | } 88 | } 89 | 90 | 91 | int 92 | main(void) { 93 | char buf[BUFSIZ]; 94 | int x1, x2, y1, y2; 95 | 96 | if (ioctl(1, TIOCGWINSZ, &ws) < 0) 97 | err(1, "ioctl()"); 98 | 99 | cells = malloc(sizeof(unsigned char) * (ws.ws_col * ws.ws_row)); 100 | if (cells == NULL) 101 | err(1, "malloc()"); 102 | 103 | setlocale(LC_ALL, ""); 104 | setbuf(stdout, NULL); 105 | 106 | while (fgets(buf, BUFSIZ, stdin)) { 107 | sscanf(buf, "%u %u %*s %u %u", &x1, &y1, &x2, &y2); 108 | 109 | if (x2 && y2) 110 | line(x1, y1, x2, y2); 111 | else if (x1 && y1) 112 | dot(x1, y1); 113 | else 114 | /* if input is not valid, quit */ 115 | break; 116 | 117 | x1 = x2 = y1 = y2 = 0; 118 | } 119 | 120 | free(cells); 121 | 122 | return 0; 123 | } 124 | -------------------------------------------------------------------------------- /tplot.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 6-dot cell patterns 3 | * 0 1 2 3 4 5 6 7 8 9 A B C D E F 4 | * U+280x ⠀ ⠁ ⠂ ⠃ ⠄ ⠅ ⠆ ⠇ ⠈ ⠉ ⠊ ⠋ ⠌ ⠍ ⠎ ⠏ 5 | * U+281x ⠐ ⠑ ⠒ ⠓ ⠔ ⠕ ⠖ ⠗ ⠘ ⠙ ⠚ ⠛ ⠜ ⠝ ⠞ ⠟ 6 | * U+282x ⠠ ⠡ ⠢ ⠣ ⠤ ⠥ ⠦ ⠧ ⠨ ⠩ ⠪ ⠫ ⠬ ⠭ ⠮ ⠯ 7 | * U+283x ⠰ ⠱ ⠲ ⠳ ⠴ ⠵ ⠶ ⠷ ⠸ ⠹ ⠺ ⠻ ⠼ ⠽ ⠾ ⠿ 8 | * 9 | * 8-dot cell patterns 10 | * U+284x ⡀ ⡁ ⡂ ⡃ ⡄ ⡅ ⡆ ⡇ ⡈ ⡉ ⡊ ⡋ ⡌ ⡍ ⡎ ⡏ 11 | * U+285x ⡐ ⡑ ⡒ ⡓ ⡔ ⡕ ⡖ ⡗ ⡘ ⡙ ⡚ ⡛ ⡜ ⡝ ⡞ ⡟ 12 | * U+286x ⡠ ⡡ ⡢ ⡣ ⡤ ⡥ ⡦ ⡧ ⡨ ⡩ ⡪ ⡫ ⡬ ⡭ ⡮ ⡯ 13 | * U+287x ⡰ ⡱ ⡲ ⡳ ⡴ ⡵ ⡶ ⡷ ⡸ ⡹ ⡺ ⡻ ⡼ ⡽ ⡾ ⡿ 14 | * U+288x ⢀ ⢁ ⢂ ⢃ ⢄ ⢅ ⢆ ⢇ ⢈ ⢉ ⢊ ⢋ ⢌ ⢍ ⢎ ⢏ 15 | * U+289x ⢐ ⢑ ⢒ ⢓ ⢔ ⢕ ⢖ ⢗ ⢘ ⢙ ⢚ ⢛ ⢜ ⢝ ⢞ ⢟ 16 | * U+28Ax ⢠ ⢡ ⢢ ⢣ ⢤ ⢥ ⢦ ⢧ ⢨ ⢩ ⢪ ⢫ ⢬ ⢭ ⢮ ⢯ 17 | * U+28Bx ⢰ ⢱ ⢲ ⢳ ⢴ ⢵ ⢶ ⢷ ⢸ ⢹ ⢺ ⢻ ⢼ ⢽ ⢾ ⢿ 18 | * U+28Cx ⣀ ⣁ ⣂ ⣃ ⣄ ⣅ ⣆ ⣇ ⣈ ⣉ ⣊ ⣋ ⣌ ⣍ ⣎ ⣏ 19 | * U+28Dx ⣐ ⣑ ⣒ ⣓ ⣔ ⣕ ⣖ ⣗ ⣘ ⣙ ⣚ ⣛ ⣜ ⣝ ⣞ ⣟ 20 | * U+28Ex ⣠ ⣡ ⣢ ⣣ ⣤ ⣥ ⣦ ⣧ ⣨ ⣩ ⣪ ⣫ ⣬ ⣭ ⣮ ⣯ 21 | * U+28Fx ⣰ ⣱ ⣲ ⣳ ⣴ ⣵ ⣶ ⣷ ⣸ ⣹ ⣺ ⣻ ⣼ ⣽ ⣾ ⣿ 22 | * 23 | **/ 24 | 25 | #define LEN(X) (sizeof(X) / sizeof(X[0])) 26 | #define BRAILLE_EMPTY 0x2800 27 | 28 | void line(int, int, int, int); 29 | void dot(int, int); 30 | 31 | enum { 32 | FIELD_A = 1 << 0, 33 | FIELD_B = 1 << 3, 34 | FIELD_C = 1 << 1, 35 | FIELD_D = 1 << 4, 36 | FIELD_E = 1 << 2, 37 | FIELD_F = 1 << 5, 38 | FIELD_G = 1 << 6, 39 | FIELD_H = 1 << 7, 40 | }; 41 | --------------------------------------------------------------------------------