Debug("Bezier data...");
LoadStructVector<Bezier>(file, chunk_size/sizeof(Bezier), m_objects.beziers);
break;
+
+ case CT_OBJGROUPS:
+ Debug("Group data...");
+ Warn("Not handled because lazy");
+ break;
}
}
Debug("Successfully loaded %u objects from \"%s\"", ObjectCount(), filename.c_str());
#endif
}
-void Document::Add(ObjectType type, const Rect & bounds, unsigned data_index)
+unsigned Document::AddGroup(unsigned start_index, unsigned end_index)
+{
+ Real xmin = 0; Real ymin = 0;
+ Real xmax = 0; Real ymax = 0;
+
+ for (unsigned i = start_index; i <= end_index; ++i)
+ {
+ Rect & objb = m_objects.bounds[i];
+
+ if (i == start_index || objb.x < xmin)
+ xmin = objb.x;
+ if (i == start_index || (objb.x+objb.w) > xmax)
+ xmax = (objb.x+objb.w);
+
+ if (i == start_index || objb.y < ymin)
+ ymin = objb.y;
+ if (i == start_index || (objb.y+objb.h) > ymax)
+ ymax = objb.y;
+ }
+
+ Rect bounds(xmin,ymin, xmax-xmin, ymax-ymin);
+ unsigned result = Add(GROUP, bounds,0);
+ m_objects.groups[m_count-1].first = start_index;
+ m_objects.groups[m_count-1].second = end_index;
+ return result;
+}
+
+unsigned Document::AddBezier(const Bezier & bezier)
+{
+ unsigned index = AddBezierData(bezier);
+ return Add(BEZIER, bezier.SolveBounds(), index);
+}
+
+unsigned Document::Add(ObjectType type, const Rect & bounds, unsigned data_index)
{
m_objects.types.push_back(type);
m_objects.bounds.push_back(bounds);
m_objects.data_indices.push_back(data_index);
- ++m_count; // Why can't we just use the size of types or something?
+ m_objects.groups.push_back(pair<unsigned, unsigned>(data_index, data_index));
+ return (m_count++); // Why can't we just use the size of types or something?
}
unsigned Document::AddBezierData(const Bezier & bezier)
{
string d = child.attribute("d").as_string();
Debug("Path data attribute is \"%s\"", d.c_str());
- ParseSVGPathData(d, transform);
+ pair<unsigned, unsigned> range = ParseSVGPathData(d, transform);
+ AddGroup(range.first, range.second);
+
}
else if (strcmp(child.name(), "line") == 0)
{
Real y1(child.attribute("y2").as_float());
TransformXYPair(x0,y0,transform);
TransformXYPair(x1,y1,transform);
- unsigned index = AddBezierData(Bezier(x0,y0,x1,y1,x1,y1,x1,y1));
- Add(BEZIER, Rect(0,0,1,1), index);
+ AddBezier(Bezier(x0,y0,x1,y1,x1,y1,x1,y1));
}
else if (strcmp(child.name(), "rect") == 0)
{
// Fear the wrath of the tokenizing svg data
// Seriously this isn't really very DOM-like at all is it?
-void Document::ParseSVGPathData(const string & d, const SVGMatrix & transform)
+pair<unsigned, unsigned> Document::ParseSVGPathData(const string & d, const SVGMatrix & transform)
{
Real x[4] = {0,0,0,0};
Real y[4] = {0,0,0,0};
bool start = false;
- static string delims("()[],{}<>;:=LlmMqQzZcC");
+
+ static string delims("()[],{}<>;:=LlHhVvmMqQzZcC");
+
+ pair<unsigned, unsigned> range(m_count, m_count);
- while (i < d.size() && GetToken(d, token, i).size() > 0)
+ while (i < d.size() && GetToken(d, token, i, delims).size() > 0)
{
if (isalpha(token[0]))
command = token;
for (int j = 0; j < 4; ++j)
TransformXYPair(x[j],y[j], transform);
- unsigned index = AddBezierData(Bezier(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]));
- Add(BEZIER,Rect(0,0,1,1),index);
-
+ range.second = AddBezier(Bezier(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]));
//Debug("[%u] curveto %f,%f %f,%f %f,%f", index, Float(x[1]),Float(y[1]),Float(x[2]),Float(y[2]),Float(x[3]),Float(y[3]));
}
- else if (command == "l" || command == "L")
+ else if (command == "l" || command == "L" || command == "h" || command == "H" || command == "v" || command == "V")
{
Debug("Construct lineto command, relative %d", relative);
Real dx = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
- assert(GetToken(d,token,i,delims) == ",");
- Real dy = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+ Real dy;
+ if (command == "l" || command == "L")
+ {
+ assert(GetToken(d,token,i,delims) == ",");
+ dy = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
+ }
+ else if (command == "v" || command == "V")
+ {
+ swap(dx,dy);
+ }
x[1] = (relative) ? x[0] + dx : dx;
y[1] = (relative) ? y[0] + dy : dy;
+ if (command == "v" || command == "V")
+ {
+ x[1] = x[0];
+ }
+ else if (command == "h" || command == "H")
+ {
+ y[1] = y[0];
+ }
Real x1(x[1]);
Real y1(y[1]);
TransformXYPair(x[1],y[1],transform);
- unsigned index = AddBezierData(Bezier(x[0],y[0],x[1],y[1],x[1],y[1],x[1],y[1]));
- Add(BEZIER,Rect(0,0,1,1),index);
+ range.second = AddBezier(Bezier(x[0],y[0],x[1],y[1],x[1],y[1],x[1],y[1]));
//Debug("[%u] lineto %f,%f %f,%f", index, Float(x[0]),Float(y[0]),Float(x[1]),Float(y[1]));
for (int j = 0; j < 4; ++j)
TransformXYPair(x[j],y[j], transform);
- unsigned index = AddBezierData(Bezier(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]));
- Add(BEZIER,Rect(0,0,1,1),index);
-
+ range.second = AddBezier(Bezier(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]));
//Debug("[%u] returnto %f,%f %f,%f", index, Float(x[0]),Float(y[0]),Float(x[1]),Float(y[1]));
x[0] = x3;
}
prev_i = i;
}
+ return range;
}
void Document::SetFont(const string & font_filename)
// - Endpoints are the same.
// - cubic1 = quad0+(2/3)*(quad1-quad0)
// - cubic2 = quad2+(2/3)*(quad1-quad2)
- bezier_index = AddBezierData(Bezier(old_x + x, old_y + y, old_x + Real(2)*(inst_cx-old_x)/Real(3) + x, old_y + Real(2)*(inst_cy-old_y)/Real(3) + y,
+ bezier_index = AddBezier(Bezier(old_x + x, old_y + y, old_x + Real(2)*(inst_cx-old_x)/Real(3) + x, old_y + Real(2)*(inst_cy-old_y)/Real(3) + y,
current_x + Real(2)*(inst_cx-current_x)/Real(3) + x, current_y + Real(2)*(inst_cy-current_y)/Real(3) + y, current_x + x, current_y + y));
- Add(BEZIER,Rect(0,0,1,1),bezier_index);
break;
}
}