diff --git a/ext/import-svg.cpp b/ext/import-svg.cpp index 6ae3134..63d3061 100644 --- a/ext/import-svg.cpp +++ b/ext/import-svg.cpp @@ -151,7 +151,7 @@ static bool buildFromPath(Shape &shape, const char *pathDef) { return true; } -bool loadSvgShape(Shape &output, const char *filename, Vector2 *dimensions) { +bool loadSvgShape(Shape &output, const char *filename, int pathIndex, Vector2 *dimensions) { tinyxml2::XMLDocument doc; if (doc.LoadFile(filename)) return false; @@ -159,11 +159,29 @@ bool loadSvgShape(Shape &output, const char *filename, Vector2 *dimensions) { if (!root) return false; - tinyxml2::XMLElement *path = root->FirstChildElement("path"); - if (!path) { - tinyxml2::XMLElement *g = root->FirstChildElement("g"); - if (g) - path = g->FirstChildElement("path"); + tinyxml2::XMLElement *path = NULL; + if( pathIndex > 0 ) { + path = root->FirstChildElement("path"); + if (!path) { + tinyxml2::XMLElement *g = root->FirstChildElement("g"); + if (g) + path = g->FirstChildElement("path"); + } + while (path && --pathIndex > 0) + path = path->NextSiblingElement("path"); + } + else { + // A pathIndex of 0 means "default", which is the same as specifying a -1 (i.e. last). + + path = root->LastChildElement("path"); + if (!path) { + tinyxml2::XMLElement *g = root->LastChildElement("g"); + if (g) + path = g->LastChildElement("path"); + } + while (path && ++pathIndex < 0) { + path = path->PreviousSiblingElement("path"); + } } if (!path) return false; diff --git a/ext/import-svg.h b/ext/import-svg.h index 405ab69..62b0398 100644 --- a/ext/import-svg.h +++ b/ext/import-svg.h @@ -7,6 +7,6 @@ namespace msdfgen { /// Reads the first path found in the specified SVG file and stores it as a Shape in output. -bool loadSvgShape(Shape &output, const char *filename, Vector2 *dimensions = NULL); +bool loadSvgShape(Shape &output, const char *filename, int pathIndex, Vector2 *dimensions = NULL); } diff --git a/main.cpp b/main.cpp index 93452d3..d75c24b 100644 --- a/main.cpp +++ b/main.cpp @@ -44,6 +44,11 @@ static bool parseUnsigned(unsigned &value, const char *arg) { return sscanf(arg, "%u%c", &value, &c) == 1; } +static bool parseInteger(int &value, const char *arg) { + static char c; + return sscanf(arg, "%d%c", &value, &c) == 1; +} + static bool parseUnsignedLL(unsigned long long &value, const char *arg) { static char c; return sscanf(arg, "%llu%c", &value, &c) == 1; @@ -280,8 +285,10 @@ static const char *helpText = "\tLoads text shape description from a file.\n" " -stdin\n" "\tReads text shape description from the standard input.\n" - " -svg \n" - "\tLoads the first vector path encountered in the specified SVG file.\n" + " -svg []\n" + "\tLoads a vector element from the specified SVG file. The optional index specifies a sibling\n" + "\tto use. E.g. 1 = first element, 2 = second element, -1 = last element, -2 = second to last, etc.\n" + "\tDefault: -1 (i.e. last path element).\n" "\n" "OPTIONS\n" " -angle \n" @@ -359,6 +366,7 @@ int main(int argc, const char * const *argv) { const char *testRenderMulti = NULL; bool outputSpecified = false; int unicode = 0; + int svgPathIndex = 0; int width = 64, height = 64; int testWidth = 0, testHeight = 0; @@ -404,6 +412,10 @@ int main(int argc, const char * const *argv) { inputType = SVG; input = argv[argPos+1]; argPos += 2; + // Optional path specifier + if( argPos+1 < argc && parseInteger(svgPathIndex, argv[argPos]) ) { + argPos += 1; + } continue; } ARG_CASE("-font", 2) { @@ -618,7 +630,7 @@ int main(int argc, const char * const *argv) { Shape shape; switch (inputType) { case SVG: { - if (!loadSvgShape(shape, input, &svgDims)) + if (!loadSvgShape(shape, input, svgPathIndex, &svgDims)) ABORT("Failed to load shape from SVG file."); break; }