123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- #define _CRT_SECURE_NO_WARNINGS
- #include "shape-description.h"
- namespace msdfgen {
- int readCharF(FILE *input) {
- int c = '\0';
- do {
- c = fgetc(input);
- } while (c == ' ' || c == '\t' || c == '\r' || c == '\n');
- return c;
- }
- int readCharS(const char **input) {
- int c = '\0';
- do {
- c = *(*input)++;
- } while (c == ' ' || c == '\t' || c == '\r' || c == '\n');
- if (!c) {
- --c;
- return EOF;
- }
- return c;
- }
- int readCoordF(FILE *input, Point2 &coord) {
- return fscanf(input, "%lf,%lf", &coord.x, &coord.y);
- }
- int readCoordS(const char **input, Point2 &coord) {
- int read = 0;
- int result = sscanf(*input, "%lf,%lf%n", &coord.x, &coord.y, &read);
- *input += read;
- return result;
- }
- static bool writeCoord(FILE *output, Point2 coord) {
- fprintf(output, "%.12g, %.12g", coord.x, coord.y);
- return true;
- }
- template <typename T, int (*readChar)(T *), int (*readCoord)(T *, Point2 &)>
- static int readControlPoints(T *input, Point2 *output) {
- int result = readCoord(input, output[0]);
- if (result == 2) {
- switch (readChar(input)) {
- case ')':
- return 1;
- case ';':
- break;
- default:
- return -1;
- }
- result = readCoord(input, output[1]);
- if (result == 2 && readChar(input) == ')')
- return 2;
- } else if (result != 1 && readChar(input) == ')')
- return 0;
- return -1;
- }
- template <typename T, int (*readChar)(T *), int (*readCoord)(T *, Point2 &)>
- static bool readContour(T *input, Contour &output, const Point2 *first, int terminator, bool &colorsSpecified) {
- Point2 p[4], start;
- if (first)
- p[0] = *first;
- else {
- int result = readCoord(input, p[0]);
- if (result != 2)
- return result != 1 && readChar(input) == terminator;
- }
- start = p[0];
- int c = '\0';
- while ((c = readChar(input)) != terminator) {
- if (c != ';')
- return false;
- EdgeColor color = WHITE;
- int result = readCoord(input, p[1]);
- if (result == 2) {
- output.addEdge(EdgeHolder(p[0], p[1], color));
- p[0] = p[1];
- continue;
- } else if (result == 1)
- return false;
- else {
- int controlPoints = 0;
- switch ((c = readChar(input))) {
- case '#':
- output.addEdge(EdgeHolder(p[0], start, color));
- p[0] = start;
- continue;
- case ';':
- goto FINISH_EDGE;
- case '(':
- goto READ_CONTROL_POINTS;
- case 'C': case 'c':
- color = CYAN;
- colorsSpecified = true;
- break;
- case 'M': case 'm':
- color = MAGENTA;
- colorsSpecified = true;
- break;
- case 'Y': case 'y':
- color = YELLOW;
- colorsSpecified = true;
- break;
- case 'W': case 'w':
- color = WHITE;
- colorsSpecified = true;
- break;
- default:
- return c == terminator;
- }
- switch (readChar(input)) {
- case ';':
- goto FINISH_EDGE;
- case '(':
- READ_CONTROL_POINTS:
- if ((controlPoints = readControlPoints<T, readChar, readCoord>(input, p+1)) < 0)
- return false;
- break;
- default:
- return false;
- }
- if (readChar(input) != ';')
- return false;
- FINISH_EDGE:
- result = readCoord(input, p[1+controlPoints]);
- if (result != 2) {
- if (result == 1)
- return false;
- else {
- if (readChar(input) == '#')
- p[1+controlPoints] = start;
- else
- return false;
- }
- }
- switch (controlPoints) {
- case 0:
- output.addEdge(EdgeHolder(p[0], p[1], color));
- p[0] = p[1];
- continue;
- case 1:
- output.addEdge(EdgeHolder(p[0], p[1], p[2], color));
- p[0] = p[2];
- continue;
- case 2:
- output.addEdge(EdgeHolder(p[0], p[1], p[2], p[3], color));
- p[0] = p[3];
- continue;
- }
- }
- }
- return true;
- }
- bool readShapeDescription(FILE *input, Shape &output, bool *colorsSpecified) {
- bool locColorsSpec = false;
- output.contours.clear();
- output.inverseYAxis = false;
- Point2 p;
- int result = readCoordF(input, p);
- if (result == 2) {
- return readContour<FILE, readCharF, readCoordF>(input, output.addContour(), &p, EOF, locColorsSpec);
- } else if (result == 1)
- return false;
- else {
- int c = readCharF(input);
- if (c == '@') {
- char after = '\0';
- if (fscanf(input, "invert-y%c", &after) != 1)
- return feof(input) != 0;
- output.inverseYAxis = true;
- c = after;
- if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
- c = readCharF(input);
- }
- for (; c == '{'; c = readCharF(input))
- if (!readContour<FILE, readCharF, readCoordF>(input, output.addContour(), NULL, '}', locColorsSpec))
- return false;
- if (colorsSpecified)
- *colorsSpecified = locColorsSpec;
- return c == EOF && feof(input);
- }
- }
- bool readShapeDescription(const char *input, Shape &output, bool *colorsSpecified) {
- bool locColorsSpec = false;
- output.contours.clear();
- output.inverseYAxis = false;
- Point2 p;
- int result = readCoordS(&input, p);
- if (result == 2) {
- return readContour<const char *, readCharS, readCoordS>(&input, output.addContour(), &p, EOF, locColorsSpec);
- } else if (result == 1)
- return false;
- else {
- int c = readCharS(&input);
- if (c == '@') {
- for (int i = 0; i < (int) sizeof("invert-y")-1; ++i)
- if (input[i] != "invert-y"[i])
- return false;
- output.inverseYAxis = true;
- input += sizeof("invert-y")-1;
- c = readCharS(&input);
- }
- for (; c == '{'; c = readCharS(&input))
- if (!readContour<const char *, readCharS, readCoordS>(&input, output.addContour(), NULL, '}', locColorsSpec))
- return false;
- if (colorsSpecified)
- *colorsSpecified = locColorsSpec;
- return c == EOF;
- }
- }
- static bool isColored(const Shape &shape) {
- for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)
- for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge)
- if ((*edge)->color != WHITE)
- return true;
- return false;
- }
- bool writeShapeDescription(FILE *output, const Shape &shape) {
- if (!shape.validate())
- return false;
- bool writeColors = isColored(shape);
- if (shape.inverseYAxis)
- fprintf(output, "@invert-y\n");
- for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) {
- fprintf(output, "{\n");
- if (!contour->edges.empty()) {
- for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
- char colorCode = '\0';
- if (writeColors) {
- switch ((*edge)->color) {
- case YELLOW: colorCode = 'y'; break;
- case MAGENTA: colorCode = 'm'; break;
- case CYAN: colorCode = 'c'; break;
- case WHITE: colorCode = 'w'; break;
- default:;
- }
- }
- if (const LinearSegment *e = dynamic_cast<const LinearSegment *>(&**edge)) {
- fprintf(output, "\t");
- writeCoord(output, e->p[0]);
- fprintf(output, ";\n");
- if (colorCode)
- fprintf(output, "\t\t%c;\n", colorCode);
- }
- if (const QuadraticSegment *e = dynamic_cast<const QuadraticSegment *>(&**edge)) {
- fprintf(output, "\t");
- writeCoord(output, e->p[0]);
- fprintf(output, ";\n\t\t");
- if (colorCode)
- fprintf(output, "%c", colorCode);
- fprintf(output, "(");
- writeCoord(output, e->p[1]);
- fprintf(output, ");\n");
- }
- if (const CubicSegment *e = dynamic_cast<const CubicSegment *>(&**edge)) {
- fprintf(output, "\t");
- writeCoord(output, e->p[0]);
- fprintf(output, ";\n\t\t");
- if (colorCode)
- fprintf(output, "%c", colorCode);
- fprintf(output, "(");
- writeCoord(output, e->p[1]);
- fprintf(output, "; ");
- writeCoord(output, e->p[2]);
- fprintf(output, ");\n");
- }
- }
- fprintf(output, "\t#\n");
- }
- fprintf(output, "}\n");
- }
- return true;
- }
- }
|