Exemple #1
0
static void svgParsePath(struct SVGParser* p, const char** attr)
{
	const char* s;
	char cmd;
	float args[10];
	int nargs;
	int rargs;
	float cpx, cpy, cpx2, cpy2;
	const char* tmp[4];
	char closedFlag;
	int i;
	char item[64];

	for (i = 0; attr[i]; i += 2)
	{
		if (strcmp(attr[i], "d") == 0)
		{
			s = attr[i + 1];

			svgResetPath(p);
			closedFlag = 0;
			nargs = 0;

			while (*s)
			{
				s = getNextPathItem(s, item);
				if (!*item) break;

				if (isnum(item[0]))
				{
					if (nargs < 10)
						args[nargs++] = (float)atof(item);
					if (nargs >= rargs)
					{
						switch (cmd)
						{
							case 'm':
							case 'M':
							case 'l':
							case 'L':
								pathLineTo(p, &cpx, &cpy, args, (cmd == 'm' || cmd == 'l') ? 1 : 0);
								break;
							case 'H':
							case 'h':
								pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);
								break;
							case 'V':
							case 'v':
								pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);
								break;
							case 'C':
							case 'c':
								pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
								break;
							case 'S':
							case 's':
								pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
								break;
							case 'Q':
							case 'q':
								pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
								break;
							case 'T':
							case 't':
								pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
								break;
							default:
								if (nargs >= 2)
								{
									cpx = args[nargs-2];
									cpy = args[nargs-1];
								}
								break;
						}
						nargs = 0;
					}
				}
				else
				{
					cmd = item[0];
					rargs = getArgsPerElement(cmd);
					if (cmd == 'M' || cmd == 'm')
					{
						// Commit path.
						if (p->nbuf)
							svgCreatePath(p, closedFlag);
						// Start new subpath.
						svgResetPath(p);
						closedFlag = 0;
						nargs = 0;
						cpx = 0; cpy = 0;
					}
					else if (cmd == 'Z' || cmd == 'z')
					{
						closedFlag = 1;
						// Commit path.
						if (p->nbuf)
							svgCreatePath(p, closedFlag);
						// Start new subpath.
						svgResetPath(p);
						closedFlag = 0;
						nargs = 0;
					}
				}
			}

			// Commit path.
			if (p->nbuf)
				svgCreatePath(p, closedFlag);

		}
		else
		{
			tmp[0] = attr[i];
			tmp[1] = attr[i + 1];
			tmp[2] = 0;
			tmp[3] = 0;
			svgParseAttribs(p, tmp);
		}
	}
}
void ofxSVGPathParser::parse(string& path)
{
	nbuf = 0;
	char cmd;
	float args[10];
	int nargs;
	int rargs;
	float cpx, cpy, cpx2, cpy2;
	const char* tmp[4];
	char closedFlag;
	int i;
	char item[64];
	
	string::iterator s = path.begin();
	
	pathInstance->newSubPath();
	closedFlag = 0;
	nargs = 0;
	
	while (s != path.end())
	{
		getNextPathItem(s, item);
		if (!*item) break;
		
		if (isnum(item[0]))
		{
			if (nargs < 10) {
				args[nargs++] = (float) atof(item);
			}
			
			if (nargs >= rargs)
			{
				cout << " command " << cmd << endl;
				switch (cmd)
				{
					case 'm':
					case 'M':
					case 'l':
					case 'L':
						pathLineTo(&cpx, &cpy, args, (cmd == 'm' || cmd == 'l') ? 1 : 0);
						break;
					case 'H':
					case 'h':
						pathHLineTo(&cpx, &cpy, args, cmd == 'h' ? 1 : 0);
						break;
					case 'V':
					case 'v':
						pathVLineTo(&cpx, &cpy, args, cmd == 'v' ? 1 : 0);
						break;
					case 'C':
					case 'c':
						pathCubicBezTo(&cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
						break;
					case 'S':
					case 's':
						pathCubicBezShortTo(&cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
						break;
					case 'Q':
					case 'q':
						pathQuadBezTo(&cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
						break;
					case 'T':
					case 't':
						pathQuadBezShortTo(&cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
						break;
					default:
						if (nargs >= 2)
						{
							cpx = args[nargs-2];
							cpy = args[nargs-1];
						}
						break;
				}
				nargs = 0;
			}
		}
		else
		{
			cmd = item[0];
			rargs = getArgsPerElement(cmd);
			if (cmd == 'M' || cmd == 'm')
			{
				// Commit path->	
				// TODO get all the transform/translate/etc data from the parent?
				// or just return out of this and handle in the parent?
				//path = new vector<ofVec2f*>();
				// Start new subpath->
				//svgResetPath();
				pathInstance->close();
				closedFlag = 0;
				nargs = 0;
				cpx = 0; cpy = 0;
			}
			else if (cmd == 'Z' || cmd == 'z')
			{
				closedFlag = 1;
				// Commit path->
				//path = new vector<ofVec2f*>();
				// Start new subpath->
				pathInstance->close();
				closedFlag = 0;
				nargs = 0;
			}
		}
	}
	pathInstance->close();
}