File indexing completed on 2024-12-22 04:04:14
0001 /* Copyright (C) 2001-2019 Peter Selinger. 0002 This file is part of Potrace. It is free software and it is covered 0003 by the GNU General Public License. See the file COPYING for details. */ 0004 0005 /* functions to render a progress bar for main.c. We provide a 0006 standard and a simplified progress bar. */ 0007 0008 #ifdef HAVE_CONFIG_H 0009 #include <config.h> 0010 #endif 0011 0012 #include <stdio.h> 0013 #include <math.h> 0014 #include <stdlib.h> 0015 #include <string.h> 0016 0017 #include "potracelib.h" 0018 #include "progress_bar.h" 0019 0020 /* ---------------------------------------------------------------------- */ 0021 /* vt100 progress bar */ 0022 0023 #define COL0 "\033[G" /* reset cursor to column 0 */ 0024 0025 struct vt100_progress_s { 0026 char name[22]; /* filename for status bar */ 0027 double dnext; /* threshold value for next tick */ 0028 }; 0029 typedef struct vt100_progress_s vt100_progress_t; 0030 0031 /* print a progress bar using vt100 control characters. This is a 0032 callback function that is potentially called often; thus, it has 0033 been optimized for the typical case, which is when the progress bar 0034 does not need updating. */ 0035 static void vt100_progress(double d, void *data) { 0036 vt100_progress_t *p = (vt100_progress_t *)data; 0037 static char b[] = "========================================"; 0038 int tick; /* number of visible tickmarks, 0..40 */ 0039 int perc; /* visible percentage, 0..100 */ 0040 0041 /* note: the 0.01 and 0.025 ensure that we always end on 40 0042 tickmarks and 100%, despite any rounding errors. The 0.995 0043 ensures that tick always increases when d >= p->dnext. */ 0044 if (d >= p->dnext) { 0045 tick = (int) floor(d*40+0.01); 0046 perc = (int) floor(d*100+0.025); 0047 fprintf(stderr, "%-21s |%-40s| %d%% " COL0 "", p->name, b+40-tick, perc); 0048 fflush(stderr); 0049 p->dnext = (tick+0.995) / 40.0; 0050 } 0051 } 0052 0053 /* Initialize progress bar. Return 0 on success or 1 on failure with 0054 errno set. */ 0055 static int init_vt100_progress(potrace_progress_t *prog, const char *filename, int count) { 0056 vt100_progress_t *p; 0057 const char *q, *s; 0058 int len; 0059 0060 p = (vt100_progress_t *) malloc(sizeof(vt100_progress_t)); 0061 if (!p) { 0062 return 1; 0063 } 0064 0065 /* initialize callback function's data */ 0066 p->dnext = 0; 0067 0068 if (count != 0) { 0069 sprintf(p->name, " (p.%d):", count+1); 0070 } else { 0071 s = filename; 0072 if ((q = strrchr(s, '/')) != NULL) { 0073 s = q+1; 0074 } 0075 len = strlen(s); 0076 strncpy(p->name, s, 21); 0077 p->name[20] = 0; 0078 if (len > 20) { 0079 p->name[17] = '.'; 0080 p->name[18] = '.'; 0081 p->name[19] = '.'; 0082 } 0083 strcat(p->name, ":"); 0084 } 0085 0086 /* initialize progress parameters */ 0087 prog->callback = &vt100_progress; 0088 prog->data = (void *)p; 0089 prog->min = 0.0; 0090 prog->max = 1.0; 0091 prog->epsilon = 0.0; 0092 0093 /* draw first progress bar */ 0094 vt100_progress(0.0, prog->data); 0095 return 0; 0096 } 0097 0098 /* Finalize the progress bar. */ 0099 static void term_vt100_progress(potrace_progress_t *prog) { 0100 fprintf(stderr, "\n"); 0101 fflush(stderr); 0102 free(prog->data); 0103 return; 0104 } 0105 0106 /* progress bar interface structure */ 0107 static progress_bar_t progress_bar_vt100_struct = { 0108 init_vt100_progress, 0109 term_vt100_progress, 0110 }; 0111 progress_bar_t *progress_bar_vt100 = &progress_bar_vt100_struct; 0112 0113 /* ---------------------------------------------------------------------- */ 0114 /* another progress bar for dumb terminals */ 0115 0116 struct simplified_progress_s { 0117 int n; /* number of ticks displayed so far */ 0118 double dnext; /* threshold value for next tick */ 0119 }; 0120 typedef struct simplified_progress_s simplified_progress_t; 0121 0122 /* print a simplified progress bar, not using any special tty control 0123 codes. Optimized for frequent calling. */ 0124 static void simplified_progress(double d, void *data) { 0125 simplified_progress_t *p = (simplified_progress_t *)data; 0126 int tick; /* number of visible tickmarks, 0..40 */ 0127 0128 /* note: the 0.01 and 0.025 ensure that we always end on 40 0129 tickmarks and 100%, despite any rounding errors. The 0.995 0130 ensures that tick always increases when d >= p->dnext. */ 0131 if (d >= p->dnext) { 0132 tick = (int) floor(d*40+0.01); 0133 while (p->n < tick) { 0134 fputc('=', stderr); 0135 p->n++; 0136 } 0137 fflush(stderr); 0138 p->dnext = (tick+0.995) / 40.0; 0139 } 0140 } 0141 0142 /* Initialize parameters for simplified progress bar. Return 0 on 0143 success or 1 on error with errno set. */ 0144 static int init_simplified_progress(potrace_progress_t *prog, const char *filename, int count) { 0145 simplified_progress_t *p; 0146 const char *q, *s; 0147 int len; 0148 char buf[22]; 0149 0150 p = (simplified_progress_t *) malloc(sizeof(simplified_progress_t)); 0151 if (!p) { 0152 return 1; 0153 } 0154 0155 /* initialize callback function's data */ 0156 p->n = 0; 0157 p->dnext = 0; 0158 0159 if (count != 0) { 0160 sprintf(buf, " (p.%d):", count+1); 0161 } else { 0162 s = filename; 0163 if ((q = strrchr(s, '/')) != NULL) { 0164 s = q+1; 0165 } 0166 len = strlen(s); 0167 strncpy(buf, s, 21); 0168 buf[20] = 0; 0169 if (len > 20) { 0170 buf[17] = '.'; 0171 buf[18] = '.'; 0172 buf[19] = '.'; 0173 } 0174 strcat(buf, ":"); 0175 } 0176 0177 fprintf(stderr, "%-21s |", buf); 0178 0179 /* initialize progress parameters */ 0180 prog->callback = &simplified_progress; 0181 prog->data = (void *)p; 0182 prog->min = 0.0; 0183 prog->max = 1.0; 0184 prog->epsilon = 0.0; 0185 0186 /* draw first progress bar */ 0187 simplified_progress(0.0, prog->data); 0188 return 0; 0189 } 0190 0191 static void term_simplified_progress(potrace_progress_t *prog) { 0192 simplified_progress_t *p = (simplified_progress_t *)prog->data; 0193 0194 simplified_progress(1.0, (void *)p); 0195 fprintf(stderr, "| 100%%\n"); 0196 fflush(stderr); 0197 free(p); 0198 return; 0199 } 0200 0201 /* progress bar interface structure */ 0202 static progress_bar_t progress_bar_simplified_struct = { 0203 init_simplified_progress, 0204 term_simplified_progress, 0205 }; 0206 progress_bar_t *progress_bar_simplified = &progress_bar_simplified_struct; 0207