1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
/* Copyright (C) 2001-2019 Peter Selinger.
This file is part of Potrace. It is free software and it is covered
by the GNU General Public License. See the file COPYING for details. */
/* operations on potrace_progress_t objects, which are defined in
potracelib.h. Note: the code attempts to minimize runtime overhead
when no progress monitoring was requested. It also tries to
minimize excessive progress calculations beneath the "epsilon"
threshold. */
#ifndef PROGRESS_H
#define PROGRESS_H
/* structure to hold progress bar callback data */
struct progress_s {
void (*callback)(double progress, void *privdata); /* callback fn */
void *data; /* callback function's private data */
double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
double epsilon; /* granularity: can skip smaller increments */
double b; /* upper limit of subrange in superrange units */
double d_prev; /* previous value of d */
};
typedef struct progress_s progress_t;
/* notify given progress object of current progress. Note that d is
given in the 0.0-1.0 range, which will be scaled and translated to
the progress object's range. */
static inline void progress_update(double d, progress_t *prog) {
double d_scaled;
if (prog != NULL && prog->callback != NULL) {
d_scaled = prog->min * (1-d) + prog->max * d;
if (d == 1.0 || d_scaled >= prog->d_prev + prog->epsilon) {
prog->callback(prog->min * (1-d) + prog->max * d, prog->data);
prog->d_prev = d_scaled;
}
}
}
/* start a subrange of the given progress object. The range is
narrowed to [a..b], relative to 0.0-1.0 coordinates. If new range
is below granularity threshold, disable further subdivisions. */
static inline void progress_subrange_start(double a, double b, const progress_t *prog, progress_t *sub) {
double min, max;
if (prog == NULL || prog->callback == NULL) {
sub->callback = NULL;
return;
}
min = prog->min * (1-a) + prog->max * a;
max = prog->min * (1-b) + prog->max * b;
if (max - min < prog->epsilon) {
sub->callback = NULL; /* no further progress info in subrange */
sub->b = b;
return;
}
sub->callback = prog->callback;
sub->data = prog->data;
sub->epsilon = prog->epsilon;
sub->min = min;
sub->max = max;
sub->d_prev = prog->d_prev;
return;
}
static inline void progress_subrange_end(progress_t *prog, progress_t *sub) {
if (prog != NULL && prog->callback != NULL) {
if (sub->callback == NULL) {
progress_update(sub->b, prog);
} else {
prog->d_prev = sub->d_prev;
}
}
}
#endif /* PROGRESS_H */
|