+// Behold my amazing tokenizing abilities
+static string & GetToken(const string & d, string & token, unsigned & i, const string & delims = "()[],{}<>;:=")
+{
+ token.clear();
+ while (i < d.size() && iswspace(d[i]))
+ {
+ ++i;
+ }
+
+ while (i < d.size())
+ {
+ if (iswspace(d[i]) || strchr(delims.c_str(),d[i]) != NULL)
+ {
+ if (token.size() == 0 && !iswspace(d[i]))
+ {
+ token += d[i++];
+ }
+ break;
+ }
+ token += d[i++];
+ }
+ //Debug("Got token \"%s\"", token.c_str());
+ return token;
+}
+
+static void GetXYPair(const string & d, Real & x, Real & y, unsigned & i,const string & delims = "()[],{}<>;:=")
+{
+ string token("");
+ x = strtod(GetToken(d, token, i, delims).c_str(),NULL);
+ if (GetToken(d, token, i, delims) != ",")
+ {
+ Fatal("Expected \",\" seperating x,y pair");
+ }
+ y = strtod(GetToken(d, token, i, delims).c_str(),NULL);
+}
+
+static void TransformXYPair(Real & x, Real & y, SVGMatrix & transform)
+{
+ Real x0(x);
+ x = transform.a * x + transform.c * y + transform.e;
+ y = transform.b * x0 + transform.d * y + transform.f;
+}
+
+void Document::ParseSVGTransform(const string & s, SVGMatrix & transform)
+{
+ Debug("Parsing transform %s", s.c_str());
+ string token;
+ string command;
+ unsigned i = 0;
+ GetToken(s, command, i);
+ Debug("Token is \"%s\"", command.c_str());
+
+ SVGMatrix delta = {1,0,0,1,0,0};
+
+
+ assert(GetToken(s,token, i) == "(");
+ if (command == "translate")
+ {
+ GetXYPair(s, delta.e, delta.f, i);
+ assert(GetToken(s,token, i) == ")");
+ }
+ else if (command == "matrix")
+ {
+ GetXYPair(s, delta.a, delta.b,i);
+ GetXYPair(s, delta.c, delta.d,i);
+ GetXYPair(s, delta.e, delta.f,i);
+ assert(GetToken(s,token, i) == ")");
+ }
+ else if (command == "scale")
+ {
+ delta.a = (strtod(GetToken(s,token,i).c_str(), NULL));
+ GetToken(s, token, i);
+ if (token != ")")
+ {
+ delta.b = (strtod(token.c_str(), NULL));
+ }
+ else
+ {
+ delta.b = delta.a;
+ }
+
+ }
+ else
+ {
+ Warn("Unrecognised transform \"%s\", using identity", command.c_str());
+ }
+
+ Debug("Old transform is {%f,%f,%f,%f,%f,%f}", transform.a, transform.b, transform.c, transform.d,transform.e,transform.f);
+ Debug("Delta transform is {%f,%f,%f,%f,%f,%f}", delta.a, delta.b, delta.c, delta.d,delta.e,delta.f);
+
+ SVGMatrix old(transform);
+ transform.a = old.a * delta.a + old.c * delta.b;
+ transform.c = old.a * delta.c + old.c * delta.d;
+ transform.e = old.a * delta.e + old.c * delta.f + old.e;
+
+ transform.b = old.b * delta.a + old.d * delta.b;
+ transform.d = old.b * delta.c + old.d * delta.d;
+ transform.f = old.b * delta.e + old.d * delta.f + old.f;
+
+ Debug("New transform is {%f,%f,%f,%f,%f,%f}", transform.a, transform.b, transform.c, transform.d,transform.e,transform.f);
+}