#define _ISOC99_SOURCE #include #include const char *xml_header = "\n", *svg_dtd = "\n"; #define DEPTH_INCR(x) if ((x) != NULL) (*(x))++; #define DEPTH_DECR(x) if ((x) != NULL) (*(x))--; // thanks to LordHavoc for inspiration here double ticklen(double frac, int divs) { int x, n, iter = 0; double len; len = log2(divs) + 1; x = rint(frac * divs); for (n = divs; n > 0; n >>= 1, iter++) { if ((x % n) == 0) return (len - iter) / len; } return 0.0; } void indent(int *depth) { int x; if (depth) { for (x = 0; x < *depth; x++) printf("\t"); } } void svg_start(int *depth) { indent(depth); printf("\n"); DEPTH_INCR(depth); } void svg_end(int *depth) { DEPTH_DECR(depth); indent(depth); printf("\n"); } void svg_group_start(int *depth, const char *attrib) { indent(depth); printf("\n", attrib ? " " : "", attrib ? attrib : ""); DEPTH_INCR(depth); } void svg_group_end(int *depth) { DEPTH_DECR(depth); indent(depth); printf("\n"); } void svg_line(int *depth, double x1, double y1, double x2, double y2, const char *xu, const char *yu) { indent(depth); printf("\n", x1, xu, y1, yu, x2, xu, y2, yu); } void svg_text(int *depth, double x, double y, const char *xu, const char *yu, const char *text) { indent(depth); printf("%s\n", x, xu, y, yu, text); } void ruler_inches(int *depth, double x, double y, double len) { int tick = 0; double inchticks[] = { 0.5, 0.25, 0.35, 0.25, 0.45, 0.25, 0.35, 0.25 }; double cur; char buf[128]; svg_group_start(depth, "stroke=\"black\" stroke-width=\"1\""); svg_line(depth, x, y + 0.65, x + len, y + 0.65, "in", "in"); for (cur = 0.0; cur <= len; cur += 1.0/8.0) { if (!tick) { if ((int)cur == 0) snprintf(buf, sizeof(buf), "INCHES"); else snprintf(buf, sizeof(buf), "%d", (int)cur); svg_text(depth, x + cur, y, "in", "in", buf); } svg_line(depth, x + cur, y + 0.65 - inchticks[tick], x + cur, y + 0.65, "in", "in"); tick++; tick %= 8; } svg_group_end(depth); } #define HEIGHT 0.65 #define TICKOFS 0.15 #define TICKHEIGHT 0.50 #define PRECISION 0.0000001 // real unit (cm, in); divisions (8 for in, 2 sizes) void ruler(int *depth, double x, double y, double bias, double unitlen, double rulerlen, double subdiv, const char *baseunit) { double cur, baselen; char buf[128]; baselen = rulerlen * unitlen; svg_group_start(depth, "stroke=\"black\" stroke-width=\"1\""); // draw the bottom line - x to x + bias + length (base units) svg_line(depth, x, y + HEIGHT, x + bias + baselen, y + HEIGHT, baseunit, baseunit); // draw first tick if bias != 0 if (bias != 0.0) svg_line(depth, x, y + TICKOFS, x, y + HEIGHT, baseunit, "in"); for (cur = 0.0; cur <= rulerlen * unitlen + PRECISION; cur += unitlen / subdiv) { if (fabs(rint(cur / unitlen) - (cur / unitlen)) < PRECISION) { snprintf(buf, sizeof(buf), "%.0f", rint(cur / unitlen)); svg_text(depth, x + bias + cur, y, baseunit, baseunit, buf); } svg_line(depth, x + bias + cur, y + TICKOFS + (TICKHEIGHT - (TICKHEIGHT * ticklen(cur / unitlen, subdiv))), x + bias + cur, y + HEIGHT, baseunit, "in"); } svg_group_end(depth); } #define CM 2.54 // subtract 11/12" for foot size vs. shoe size #define SHOEBIAS -(11.0/12.0) int main(int argc, char *argv[]) { int depth = 0; printf(xml_header); printf(svg_dtd); svg_start(&depth); // + 11/12" for shoe size from foot size // draw a normal ruler (inches) ruler(&depth, 1.0, 1.0, 0.0, 1.0, 14.0, 16.0, "in"); // // USA, Men's - 7 1/3" + 1/3" per size // USA, Men's - 8 1/4" + 1/3" per size // ruler(&depth, 1.0, 2.0, 7.0 + (1.0/3.0), 1.0/3.0, 19.0, 2.0, "in"); ruler(&depth, 1.0, 2.0, 8.0 + (1.0/4.0) + SHOEBIAS, 1.0/3.0, 19.0, 2.0, "in"); // USA, Women's - 7 11/12" + 1/3" per size ruler(&depth, 1.0, 3.0, 7.0 + (11.0/12.0) + SHOEBIAS, 1.0/3.0, 19.0, 2.0, "in"); // // USA, "Junior" - 3 1/4" + 1/3" per size // USA, "Junior" - // ruler(&depth, 1.0, 4.0, 3.0 + (1.0/4.0), 1.0/3.0, 20.0, 2.0, "in"); // USA, Boy's - 3 11/12" + 1/3" per size ruler(&depth, 1.0, 4.0, 3.0 + (11.0/12.0) + SHOEBIAS, 1.0/3.0, 20.0, 2.0, "in"); // USA, Girl's - 3 7/12" + 1/3" per size ruler(&depth, 1.0, 5.0, 3.0 + (7.0/12.0) + SHOEBIAS, 1.0/3.0, 20.0, 2.0, "in"); // UK, Adult - 7 1/2" + 1/3" per size ruler(&depth, 1.0, 6.0, 7.0 + (1.0/2.0) + SHOEBIAS, 1.0/3.0, 18.0, 2.0, "in"); // UK, "Junior" - 4 3/8" + 1/3" per size ruler(&depth, 1.0, 7.0, 4.0 + (3.0/8.0) + SHOEBIAS, 1.0/3.0, 18.0, 2.0, "in"); // Europe, Adult - 2/3 cm per size ruler(&depth, 1.0, 8.0, 0.0 + SHOEBIAS, (2.0/3.0)/CM, 50.0, 2.0, "in"); // Europe, Junior - -2/3cm + 2/3 cm per size ruler(&depth, 1.0, 9.0, -(2.0/3.0)/CM + SHOEBIAS, (2.0/3.0)/CM, 50.0, 2.0, "in"); // Mondopoint, 1 mm/size svg_end(&depth); return 0; }