vector: implement vpathmesure 32/184632/3
authorJaeun Choi <jaeun12.choi@samsung.com>
Thu, 19 Jul 2018 10:22:19 +0000 (19:22 +0900)
committerHermet Park <chuneon.park@samsung.com>
Fri, 20 Jul 2018 05:07:07 +0000 (05:07 +0000)
Change-Id: I562df481e72b4e356821b1a44b7749c29ea0b1ca

src/vector/vpathmesure.cpp
src/vector/vpathmesure.h

index cabbe42..52e93e8 100644 (file)
 #include"vpathmesure.h"
+#include"vbezier.h"
 
 V_BEGIN_NAMESPACE
 
-class VPathMesureData
+struct VPathMesureData
 {
-   VPath      *path;
+   void        setPath(const VPath &path) { mPath = path; }
+   VPath&      getPath() { return mPath; }
+   VPath       mPath;
 };
 
 V_END_NAMESPACE
+
+static const struct VPathMesureData shared_empty = {VPath()};
+
+VPathMesure::~VPathMesure()
+{
+}
+
+VPathMesure::VPathMesure()
+   : d(const_cast<VPathMesureData*>(&shared_empty))
+{
+}
+
+VPathMesure::VPathMesure(const VPath *p, bool foceClose)
+{
+}
+
+void VPathMesure::setStart(float pos)
+{
+   VPath &path = d->getPath();
+   const std::vector<VPath::Element> &elm = path.elements();
+   const std::vector<VPointF> &pts  = path.points();
+   std::vector<float> len;
+
+   std::vector<VPath::Element> elm_copy;
+
+   int i = 0, idx = 0;
+   float totlen = 0.0;
+   float startlen = 0.0;
+   bool cut = false;
+
+   for (auto e : elm) {
+        elm_copy.push_back(e);
+        switch(e) {
+           case VPath::Element::MoveTo:
+              break;
+           case VPath::Element::LineTo:
+                {
+                   VPointF p0 = pts[i - 1];
+                   VPointF p = pts[i++];
+
+                   VBezier b = VBezier::fromPoints(p0, p0, p, p);
+                   totlen += b.length();
+                   len.push_back(b.length());
+                   break;
+                }
+           case VPath::Element::CubicTo:
+                {
+                   VPointF p0 = pts[i - 1];
+                   VPointF p = pts[i++];
+                   VPointF p1 = pts[i++];
+                   VPointF p2 = pts[i++];
+
+                   VBezier b = VBezier::fromPoints(p0, p, p1, p2);
+                   totlen += b.length();
+                   len.push_back(b.length());
+
+                   break;
+                }
+           case VPath::Element::Close:
+              break;
+        }
+   }
+
+   startlen = totlen * (pos / 100);
+   i = 0;
+   path.reset();
+
+   for (auto e : elm_copy) {
+        switch(e) {
+           case VPath::Element::MoveTo:
+                {
+                   VPointF p = pts[i++];
+                   path.moveTo(p.x(), p.y());
+                   break;
+                }
+           case VPath::Element::LineTo:
+                {
+                   VPointF p0 = pts[i - 1];
+                   VPointF p = pts[i++];
+
+                   if (!cut)
+                     {
+                        if (len.at(idx) < startlen)
+                          {
+                             startlen -= len.at(idx);
+                          }
+                        else if (len.at(idx) == startlen)
+                          {
+                             path.moveTo(p.x(), p.y());
+                             cut = true;
+                          }
+                        else
+                          {
+                             VBezier b, bleft;
+                             float ratio = (startlen/len.at(idx));
+                             b = VBezier::fromPoints(p0, p0, p, p);
+                             b.parameterSplitLeft(ratio, &bleft);
+
+                             path.moveTo(b.pt1().x(), b.pt1().y());
+                             path.lineTo(b.pt4().x(), b.pt4().y());
+                             cut = true;
+                          }
+                        idx++;
+                     }
+                   else
+                     {
+                        path.lineTo(p.x(), p.y());
+                     }
+                   break;
+                }
+           case VPath::Element::CubicTo:
+                {
+                   VPointF p0 = pts[i - 1];
+                   VPointF p = pts[i++];
+                   VPointF p1 = pts[i++];
+                   VPointF p2 = pts[i++];
+
+                   if (!cut)
+                     {
+                        if (len.at(idx) < startlen)
+                          {
+                             startlen -= len.at(idx);
+                          }
+                        else if (len.at(idx) == startlen)
+                          {
+                             path.moveTo(p2.x(), p2.y());
+                             cut = true;
+                          }
+                        else
+                          {
+                             VBezier b, bleft;
+                             float ratio = (startlen/len.at(idx));
+                             b = VBezier::fromPoints(p0, p, p1, p2);
+                             b.parameterSplitLeft(ratio, &bleft);
+
+                             path.moveTo(b.pt1().x(), b.pt1().y());
+                             path.cubicTo(b.pt2().x(), b.pt2().y(),
+                                             b.pt3().x(), b.pt3().y(),
+                                             b.pt4().x(), b.pt4().y());
+                             cut = true;
+                          }
+                        idx++;
+                     }
+                   else
+                     {
+                        path.cubicTo(p.x(), p.y(), p1.x(), p1.y(), p2.x(), p2.y());
+                     }
+                   break;
+                }
+           case VPath::Element::Close:
+              break;
+        }
+   }
+}
+
+void VPathMesure::setEnd(float pos)
+{
+   VPath &path = d->getPath();
+   const std::vector<VPath::Element> &elm = path.elements();
+   const std::vector<VPointF> &pts  = path.points();
+   std::vector<float> len;
+
+   std::vector<VPath::Element> elm_copy;
+
+   int i = 0, idx = 0;
+   float totlen = 0.0;
+   float endlen = 0.0;
+   bool cut = false;
+
+   for (auto e : elm) {
+        elm_copy.push_back(e);
+        switch(e) {
+           case VPath::Element::MoveTo:
+              break;
+           case VPath::Element::LineTo:
+                {
+                   VPointF p0 = pts[i - 1];
+                   VPointF p = pts[i++];
+
+                   VBezier b = VBezier::fromPoints(p0, p0, p, p);
+                   totlen += b.length();
+                   len.push_back(b.length());
+                   break;
+                }
+           case VPath::Element::CubicTo:
+                {
+                   VPointF p0 = pts[i - 1];
+                   VPointF p = pts[i++];
+                   VPointF p1 = pts[i++];
+                   VPointF p2 = pts[i++];
+
+                   VBezier b = VBezier::fromPoints(p0, p, p1, p2);
+                   totlen += b.length();
+                   len.push_back(b.length());
+
+                   break;
+                }
+           case VPath::Element::Close:
+              break;
+        }
+   }
+
+   endlen = totlen * (pos / 100);
+   i = 0;
+   path.reset();
+
+   for (auto e : elm_copy) {
+        switch(e) {
+           case VPath::Element::MoveTo:
+                {
+                   VPointF p = pts[i++];
+                   path.moveTo(p.x(), p.y());
+                   break;
+                }
+           case VPath::Element::LineTo:
+                {
+                   VPointF p0 = pts[i - 1];
+                   VPointF p = pts[i++];
+
+                   if (!cut)
+                     {
+                        if (len.at(idx) < endlen)
+                          {
+                             path.lineTo(p.x(), p.y());
+                             endlen -= len.at(idx);
+                          }
+                        else if (len.at(idx) == endlen)
+                          {
+                             path.lineTo(p.x(), p.y());
+                             cut = true;
+                          }
+                        else
+                          {
+                             VBezier b, bleft;
+                             float ratio = (endlen/len.at(idx));
+                             b = VBezier::fromPoints(p0, p0, p, p);
+                             b.parameterSplitLeft(ratio, &bleft);
+
+                             path.lineTo(bleft.pt4().x(), bleft.pt4().y());
+                             cut = true;
+                          }
+                        idx++;
+                     }
+                   break;
+                }
+           case VPath::Element::CubicTo:
+                {
+                   VPointF p0 = pts[i - 1];
+                   VPointF p = pts[i++];
+                   VPointF p1 = pts[i++];
+                   VPointF p2 = pts[i++];
+
+                   if (!cut)
+                     {
+                        if (len.at(idx) < endlen)
+                          {
+                             path.cubicTo(p.x(), p.y(), p1.x(), p1.y(), p2.x(), p2.y());
+                             endlen -= len.at(idx);
+                          }
+                        else if (len.at(idx) == endlen)
+                          {
+                             path.cubicTo(p.x(), p.y(), p1.x(), p1.y(), p2.x(), p2.y());
+                             cut = true;
+                          }
+                        else
+                          {
+                             VBezier b, bleft;
+                             float ratio = (endlen/len.at(idx));
+                             b = VBezier::fromPoints(p0, p, p1, p2);
+                             b.parameterSplitLeft(ratio, &bleft);
+
+                             path.cubicTo(bleft.pt2().x(), bleft.pt2().y(),
+                                             bleft.pt3().x(), bleft.pt3().y(),
+                                             bleft.pt4().x(), bleft.pt4().y());
+                             cut = true;
+                          }
+                        idx++;
+                     }
+                   break;
+                }
+           case VPath::Element::Close:
+              break;
+        }
+   }
+}
+
+void VPathMesure::setPath(const VPath &path)
+{
+   d->setPath(path);
+}
+
+VPath VPathMesure::getPath()
+{
+   return d->getPath();
+}
index 0a97fc1..88fc9fd 100644 (file)
@@ -13,6 +13,10 @@ public:
     VPathMesure();
     VPathMesure(const VPath *path, bool foceClose);
     int getLength() const;
+    void setPath(const VPath &path);
+    VPath getPath();
+    void setStart(float pos);
+    void setEnd(float pos);
 private:
     VPathMesureData *d;
 };