#include "Painter.h"

namespace Upp {

bool Painter::ReadBool(CParser& p)
{
	while(p.Char(','));
	if(p.Char('1')) return true;
	p.Char('0');
	return false;
}

double Painter::ReadDouble(CParser& p)
{
	while(p.Char(','));
	return p.IsDouble2() ? p.ReadDouble() : 0;
}

Pointf Painter::ReadPoint(CParser& p, Pointf current, bool rel)
{
	Pointf t;
	t.x = ReadDouble(p);
	t.y = ReadDouble(p);
	if(rel)
		t += current;
	return t;
}

Painter& Painter::Path(CParser& p)
{
	Pointf current(0, 0);
	while(!p.IsEof()) {
		int c = p.GetChar();
		p.Spaces();
		bool rel = IsLower(c);
		Pointf t, t1, t2;
		switch(ToUpper(c)) {
		case 'M':
			current = ReadPoint(p, current, rel);
			Move(current);
		case 'L':
			while(p.IsDouble2()) {
				current = ReadPoint(p, current, rel);
				Line(current);
			}
			break;
		case 'Z':
			Close();
			break;
		case 'H':
			while(p.IsDouble2()) {
				current.x = p.ReadDouble() + rel * current.x;
				Line(current);
			}
			break;
		case 'V':
			while(p.IsDouble2()) {
				current.y = p.ReadDouble() + rel * current.y;
				Line(current);
			}
			break;
		case 'C':
			while(p.IsDouble2()) {
				t1 = ReadPoint(p, current, rel);
				t2 = ReadPoint(p, current, rel);
				current = ReadPoint(p, current, rel);
				Cubic(t1, t2, current);
			}
			break;
		case 'S':
			while(p.IsDouble2()) {
				t2 = ReadPoint(p, current, rel);
				current = ReadPoint(p, current, rel);
				Cubic(t2, current);
			}
			break;
		case 'Q':
			while(p.IsDouble2()) {
				t1 = ReadPoint(p, current, rel);
				current = ReadPoint(p, current, rel);
				Quadratic(t1, current);
			}
			break;
		case 'T':
			while(p.IsDouble2()) {
				current = ReadPoint(p, current, rel);
				Quadratic(current);
			}
			break;
		case 'A':
			while(p.IsDouble2()) {
				t1 = ReadPoint(p, Pointf(0, 0), false);
				double xangle = ReadDouble(p);
				bool large = ReadBool(p);
				bool sweep = ReadBool(p);
				current = ReadPoint(p, current, rel);
				SvgArc(t1, xangle * M_PI / 180.0, large, sweep, current);
			}
			break;
		default:
			return *this;
		}
	}
	return *this;
}

Painter& Painter::Path(const char *path)
{
	try {
		CParser p(path);
		Path(p);
	}
	catch(CParser::Error) {}
	return *this;
}

}
