Merge branch 'master' of git.ucc.asn.au:ipdf/code
authorDavid Gow <[email protected]>
Mon, 25 Aug 2014 08:54:46 +0000 (16:54 +0800)
committerDavid Gow <[email protected]>
Mon, 25 Aug 2014 08:54:46 +0000 (16:54 +0800)
Conflicts:
src/document.cpp

1  2 
src/bezier.h
src/document.cpp

diff --combined src/bezier.h
@@@ -25,36 -25,20 +25,36 @@@ namespace IPD
                // See http://en.wikipedia.org/wiki/Cubic_function#General_formula_for_roots
  
                // delta = 18abcd - 4 b^3 d + b^2 c^2 - 4ac^3 - 27 a^2 d^2
 -              /*
 +              
                Real discriminant = Real(18) * a * b * c * d - Real(4) * (b * b * b) * d 
                                + (b * b) * (c * c) - Real(4) * a * (c * c * c)
                                - Real(27) * (a * a) * (d * d);
 -              */
 +              
 +              Debug("Trying to solve %fx^3 + %fx^2 + %fx + %f (Discriminant: %f)", a,b,c,d, discriminant);
                // discriminant > 0 => 3 distinct, real roots.
                // discriminant = 0 => a multiple root (1 or 2 real roots)
                // discriminant < 0 => 1 real root, 2 complex conjugate roots
  
 +              Real delta0 = (b*b) - Real(3) * a * c;
 +              Real delta1 = Real(2) * (b * b * b) - Real(9) * a * b * c + Real(27) * (a * a) * d;
 +
 +              std::vector<Real> roots;
 +
 +              Real C = pow((delta1 + Sqrt((delta1 * delta1) - 4 * (delta0 * delta0 * delta0)) ) / Real(2), 1/3);
 +
 +              if (false && discriminant < 0)
 +              {
 +                      Real real_root = (Real(-1) / (Real(3) * a)) * (b + C + delta0 / C);
 +
 +                      roots.push_back(real_root);
 +
 +                      return roots;
 +
 +              }
 +
                ////HACK: We know any roots we care about will be between 0 and 1, so...
 -              Debug("Trying to solve %fx^3 + %fx^2 + %fx + %f", a,b,c,d);
                Real maxi(100);
                Real prevRes(d);
 -              std::vector<Real> roots;
                for(int i = -1; i <= 100; ++i)
                {
                        Real x(i);
                Real x1; Real y1;
                Real x2; Real y2;
                Real x3; Real y3;
+               
+               typedef enum {LINE, QUADRATIC, CUSP, LOOP, SERPENTINE} Type;
+               Type type;
+               
                Bezier() = default; // Needed so we can fread/fwrite this struct... for now.
                Bezier(Real _x0, Real _y0, Real _x1, Real _y1, Real _x2, Real _y2, Real _x3, Real _y3) : x0(_x0), y0(_y0), x1(_x1), y1(_y1), x2(_x2), y2(_y2), x3(_x3), y3(_y3) 
                {
-                       
+                       //TODO: classify the curve
+                       type = SERPENTINE;
                }
                
-               Bezier(Real _x0, Real _y0, Real _x1, Real _y1, Real _x2, Real _y2) : x0(_x0), y0(_y0), x1(_x1), y1(_y1), x2(_x2), y2(_y2), x3(_x2), y3(_y2) {}
-               
                std::string Str() const
                {
                        std::stringstream s;
                 * Construct absolute control points using relative control points to a bounding rectangle
                 * ie: If cpy is relative to bounds rectangle, this will be absolute
                 */
-               Bezier(const Bezier & cpy, const Rect & t = Rect(0,0,1,1)) : x0(cpy.x0), y0(cpy.y0), x1(cpy.x1), y1(cpy.y1), x2(cpy.x2),y2(cpy.y2), x3(cpy.x3), y3(cpy.y3)
+               Bezier(const Bezier & cpy, const Rect & t = Rect(0,0,1,1)) : x0(cpy.x0), y0(cpy.y0), x1(cpy.x1), y1(cpy.y1), x2(cpy.x2),y2(cpy.y2), x3(cpy.x3), y3(cpy.y3), type(cpy.type)
                {
                        x0 *= t.w;
                        y0 *= t.h;
                        Debug("Clipping Bezier to Rect %s", r.Str().c_str());
  
                        // Convert bezier coefficients -> cubic coefficients
 -                      Real xa = x0-x1+x2-x3;
 -                      Real xb = x1 - Real(2)*x2 + Real(3)*x3;
 -                      Real xc = x2 - Real(3)*x3;
 -                      Real xd = x3 - r.x;
 +                      Real xd = x0 - r.x;
 +                      Real xc = Real(3)*(x1 - x0);
 +                      Real xb = Real(3)*(x2 - x1) - xc;
 +                      Real xa = x3 - x0 - xc - xb;
  
                        // Find its roots.
                        std::vector<Real> x_intersection = SolveCubic(xa, xb, xc, xd);
  
                        // And for the other side.
 -                      xd = x3 - r.x - r.w;
 +                      xd = x0 - r.x - r.w;
  
                        std::vector<Real> x_intersection_pt2 = SolveCubic(xa, xb, xc, xd);
                        x_intersection.insert(x_intersection.end(), x_intersection_pt2.begin(), x_intersection_pt2.end());
  
                        // Similarly for y-coordinates.
                        // Convert bezier coefficients -> cubic coefficients
 -                      Real ya = y0-y1+y2-y3;
 -                      Real yb = y1 - Real(2)*y2 + Real(3)*y3;
 -                      Real yc = y2 - Real(3)*y3;
 -                      Real yd = y3 - r.y;
 +                      Real yd = y0 - r.y;
 +                      Real yc = Real(3)*(y1 - y0);
 +                      Real yb = Real(3)*(y2 - y1) - yc;
 +                      Real ya = y3 - y0 - yc - yb;
  
                        // Find its roots.
                        std::vector<Real> y_intersection = SolveCubic(ya, yb, yc, yd);
  
                        // And for the other side.
 -                      yd = y3 - r.y - r.h;
 +                      yd = y0 - r.y - r.h;
  
                        std::vector<Real> y_intersection_pt2 = SolveCubic(ya, yb, yc, yd);
                        y_intersection.insert(y_intersection.end(), y_intersection_pt2.begin(), y_intersection_pt2.end());
                                {
                                        all_beziers.push_back(this->ReParametrise(t0, t1));
                                }
 +                              else
 +                              {
 +                                      Debug("Segment removed (point at %f, %f)", ptx, pty);
 +                              }
                                t0 = t1;
                        }
                        return all_beziers;
diff --combined src/document.cpp
@@@ -132,39 -132,13 +132,39 @@@ int Document::ClipObjectToQuadChild(in
                }
        case BEZIER:
                {
 -              Rect child_node_bounds = TransformFromQuadChild({0,0,1,1}, type);
 -              std::vector<Bezier> new_curves = m_objects.beziers[m_objects.data_indices[object_id]].ClipToRectangle(child_node_bounds);
                Rect obj_bounds = TransformToQuadChild(m_objects.bounds[object_id], type);
 +              if (obj_bounds.x < 0)
 +              {
 +                      obj_bounds.w += obj_bounds.x;
 +                      obj_bounds.x = 0;
 +              }
 +              if (obj_bounds.y < 0)
 +              {
 +                      obj_bounds.h += obj_bounds.y;
 +                      obj_bounds.y = 0;
 +              }
 +              if (obj_bounds.x + obj_bounds.w > 1)
 +              {
 +                      obj_bounds.w += (1 - (obj_bounds.x + obj_bounds.w));
 +              }
 +              if (obj_bounds.y + obj_bounds.h > 1)
 +              {
 +                      obj_bounds.h += (1 - (obj_bounds.y + obj_bounds.h));
 +              }
 +              Rect child_node_bounds = TransformFromQuadChild(obj_bounds, type);
 +              Rect clip_bezier_bounds;
 +              clip_bezier_bounds.x = (child_node_bounds.x - m_objects.bounds[object_id].x) / m_objects.bounds[object_id].w;
 +              clip_bezier_bounds.y = (child_node_bounds.y - m_objects.bounds[object_id].y) / m_objects.bounds[object_id].h;
 +              clip_bezier_bounds.w = child_node_bounds.w / m_objects.bounds[object_id].w;
 +              clip_bezier_bounds.h = child_node_bounds.h / m_objects.bounds[object_id].h;
 +              std::vector<Bezier> new_curves = Bezier(m_objects.beziers[m_objects.data_indices[object_id]], child_node_bounds).ClipToRectangle(clip_bezier_bounds);
                for (size_t i = 0; i < new_curves.size(); ++i)
                {
 -                      unsigned index = AddBezierData(new_curves[i]);
 -                      m_objects.bounds.push_back(obj_bounds);
 +                      Rect new_bounds = TransformToQuadChild(m_objects.bounds[object_id], type);
 +                      new_bounds = TransformToQuadChild(new_curves[i].SolveBounds(), type);
 +                      Bezier new_curve_data = new_curves[i].ToRelative(new_bounds);
 +                      unsigned index = AddBezierData(new_curve_data);
 +                      m_objects.bounds.push_back(new_bounds);
                        m_objects.types.push_back(BEZIER);
                        m_objects.data_indices.push_back(index);
                }
@@@ -310,7 -284,7 +310,7 @@@ void Document::Load(const string & file
  #endif
  }
  
- unsigned Document::AddGroup(unsigned start_index, unsigned end_index)
+ unsigned Document::AddGroup(unsigned start_index, unsigned end_index, const Colour & fill)
  {
        Real xmin = 0; Real ymin = 0; 
        Real xmax = 0; Real ymax = 0;
        }
        
        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;
+       
+       Group group(start_index, end_index, 0U, fill);
+       
+       unsigned data_index = AddGroupData(group);
+       unsigned result = Add(GROUP, bounds,data_index);
        return result;
  }
  
@@@ -353,7 -329,6 +355,6 @@@ unsigned Document::Add(ObjectType type
        m_objects.types.push_back(type);
        m_objects.bounds.push_back(bounds);
        m_objects.data_indices.push_back(data_index);
-       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?
  }
  
@@@ -363,6 -338,11 +364,11 @@@ unsigned Document::AddBezierData(const 
        return m_objects.beziers.size()-1;
  }
  
+ unsigned Document::AddGroupData(const Group & group)
+ {
+       m_objects.groups.push_back(group);
+       return m_objects.groups.size()-1;
+ }
  
  void Document::DebugDumpObjects()
  {
@@@ -420,6 -400,22 +426,22 @@@ static void GetXYPair(const string & d
        y = strtod(GetToken(d, token, i, delims).c_str(),NULL);
  }
  
+ static bool GetKeyValuePair(const string & d, string & key, string & value, unsigned & i, const string & delims = "()[],{}<>;:=")
+ {
+       key = "";
+       string token;
+       while (GetToken(d, token, i, delims) == ":" || token == ";");
+       key = token;
+       if (GetToken(d, token, i, delims) != ":")
+       {
+               Error("Expected \":\" seperating key:value pair");
+               return false;
+       }
+       value = "";
+       GetToken(d, value, i, delims);
+       return true;
+ }
  static void TransformXYPair(Real & x, Real & y, const SVGMatrix & transform)
  {
        Real x0(x);
@@@ -513,6 -509,8 +535,8 @@@ void Document::ParseSVGNode(pugi::xml_n
                        ParseSVGTransform(attrib_trans.as_string(), transform);
                }
                
+               
+               
                if (strcmp(child.name(), "svg") == 0 || strcmp(child.name(),"g") == 0
                        || strcmp(child.name(), "group") == 0)
                {
                else if (strcmp(child.name(), "path") == 0)
                {
                        string d = child.attribute("d").as_string();
-                       Debug("Path data attribute is \"%s\"", d.c_str());
-                       pair<unsigned, unsigned> range = ParseSVGPathData(d, transform);
-                       AddGroup(range.first, range.second);
+                       //Debug("Path data attribute is \"%s\"", d.c_str());
+                       bool closed = false;
+                       pair<unsigned, unsigned> range = ParseSVGPathData(d, transform, closed);
+                       if (closed)
+                       {
+                               Colour c(0,0,0,0);
+                               string colour_str("");
+                               map<string, string> style;
+                               if (child.attribute("style"))
+                               {
+                                       ParseSVGStyleData(child.attribute("style").as_string(), style);
+                               }
+                               
+                               // Determine shading colour
+                               if (child.attribute("fill"))
+                               {
+                                       colour_str = child.attribute("fill").as_string();
+                               }
+                               else if (style.find("fill") != style.end())
+                               {
+                                       colour_str = style["fill"];
+                               }
+                               if (colour_str == "red")
+                                       c = {1,0,0,1};
+                               else if (colour_str == "blue")
+                                       c = {0,0,1,1};
+                               else if (colour_str == "green")
+                                       c = {0,1,0,1};
+                               else if (colour_str == "black")
+                                       c = {0,0,0,1};
+                               else if (colour_str == "white")
+                                       c = {1,1,1,1};
+                               else if (colour_str.size() == 7 && colour_str[0] == '#')
+                               {
+                                       Debug("Parse colour string: \"%s\"", colour_str.c_str());
+                                       char comp[2] = {colour_str[1], colour_str[2]};
+                                       c.r = Real(strtoul(comp, NULL, 16))/Real(255);
+                                       comp[0] = colour_str[3]; comp[1] = colour_str[4];
+                                       c.g = Real(strtoul(comp, NULL, 16))/Real(255);
+                                       comp[0] = colour_str[5]; comp[1] = colour_str[6];
+                                       c.b = Real(strtoul(comp, NULL, 16))/Real(255);
+                                       c.a = 1;
+                                       Debug("Colour is: %f, %f, %f, %f", Float(c.r), Float(c.g), Float(c.b), Float(c.a));
+                               }
+                               
+                               // Determin shading alpha
+                               if (child.attribute("fill-opacity"))
+                               {
+                                       c.a = child.attribute("fill-opacity").as_float();
+                               }
+                               else if (style.find("fill-opacity") != style.end())
+                               {
+                                       c.a = strtod(style["fill-opacity"].c_str(), NULL);
+                               }
+                               
+                                       Debug("fill-opacity is %f", Float(c.a));
+                               AddGroup(range.first, range.second, c);
+                       }
                        
                }
                else if (strcmp(child.name(), "line") == 0)
        }
  }
  
+ void Document::ParseSVGStyleData(const string & style, map<string, string> & results)
+ {
+       unsigned i = 0;
+       string key;
+       string value;
+       while (i < style.size() && GetKeyValuePair(style, key, value, i))
+       {
+               results[key] = value;
+       }
+ }
  /**
   * Parse an SVG string into a rectangle
   */
@@@ -627,8 -691,9 +717,9 @@@ void Document::LoadSVG(const string & f
  
  // Fear the wrath of the tokenizing svg data
  // Seriously this isn't really very DOM-like at all is it?
- pair<unsigned, unsigned> Document::ParseSVGPathData(const string & d, const SVGMatrix & transform)
+ pair<unsigned, unsigned> Document::ParseSVGPathData(const string & d, const SVGMatrix & transform, bool & closed)
  {
+       closed = false;
        Real x[4] = {0,0,0,0};
        Real y[4] = {0,0,0,0};
        
                }
                else if (command == "l" || command == "L" || command == "h" || command == "H" || command == "v" || command == "V")
                {
-                       Debug("Construct lineto command, relative %d", relative);
+                       //Debug("Construct lineto command, relative %d", relative);
                
                        Real dx = Real(strtod(GetToken(d,token,i,delims).c_str(),NULL));
                        Real dy;
                        x[0] = x3;
                        y[0] = y3;
                        command = "m";
+                       closed = true;
                }
                else
                {

UCC git Repository :: git.ucc.asn.au