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 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
#include "contour_test.h"
#include <string>
#include <vector>
#include <iostream>
/************************************************
**A few global variables for genuine ugliness.**
************************************************/
/** Generate only the file with this name (range). */
std::vector<std::pair<int, int>> test_only_this_one;
/** For every picture where we generate more things (multiple arrowheads, contours, etc.)
* draw only these items (inclusive ranges). If empty we draw all.
* It impacts all such tests, can be combined with test_only_this_one.*/
std::vector<std::pair<int, int>> draw_only_these;
/**Counts which item is drawn on a specific output image.
* Incremented by shall_draw() below, zeroed by shouldnt_do() below.*/
thread_local int seq_ = 0;
/** Call this at the beginning of each test output image
* to see if the test shall be skipped */
bool shouldnt_do(int i) noexcept {
seq_ = 0;
return test_only_this_one.size()
&& std::ranges::none_of(test_only_this_one,
[i](auto p) {return p.first<=i && i<=p.second; });
}
/** Call this at the beginning of each section with an (inclusive)
* range of tests to see if all of them shall be skipped. */
bool shouldnt_do(int i, int j) noexcept {
seq_ = 0;
return test_only_this_one.size()
&& std::ranges::none_of(test_only_this_one,
[i, j](auto p) {return p.first<=j && i<=p.second; });
}
/** Call this before drawing every item on a test image to see if that shall be drawn or not. */
bool shall_draw() noexcept {
seq_++;
return draw_only_these.empty()
|| std::ranges::any_of(draw_only_these, [](std::pair<int, int> a) { return a.first<=seq_ && seq_<=a.second; });
}
//This throws on error
std::pair<int, int> parse_range(const std::string& a) {
if (const size_t dash = a.find_last_of('-'); dash!=std::string::npos) {
const int f = dash==0 ? 1 : std::stoi(a.substr(0, dash));
const int t = dash==a.size()-1 ? 100000 : std::stoi(a.substr(dash+1));
return {f, t};
} else {
const int e = std::stoi(a);
return {e, e};
}
}
int main(int n, char** argv) {
int max_threads = 1;
bool experiment = false;
for (int i = 1; i<n; i++) {
const std::string a{argv[i]};
try {
if (a=="-e")
experiment = true;
else if (a.starts_with("-j"))
max_threads = std::stoi(a.substr(2));
else if (a.starts_with("-o"))
test_only_this_one.push_back(parse_range(a.substr(2)));
else if (a.starts_with("-d"))
draw_only_these.push_back(parse_range(a.substr(2)));
else if (a.starts_with("-F"))
CairoContext::font_face = a.substr(2);
else
throw 1; //sorry to use exceptions for flow control
} catch (...) {
std::cerr<<
"Bad argument: "<<a<<"\n"
"Possible arguments:\n"
"-e Run only the experiment\n"
"-o<M>-<N> Generate only these output images. Can specify multiple -o.\n"
" To get test123.png, use -o123, to get test123_004, use -o1234\n"
"-d<M>-<N> Generate only items of output images in this range. Can specify\n"
" multiple -d options. You can omit any of the numbers or just have\n"
" a single number.\n"
"-F<font_face>\n"
" Set the font face to use when generating test images.\n";
return 1;
}
}
if (experiment) contour_test_experiment();
else contour_test(max_threads);
return 0;
}
|