[Libreoffice-commits] libvisio.git: 2 commits - src/lib

Fridrich Štrba fridrich.strba at bluewin.ch
Tue Dec 29 07:30:03 PST 2015


 src/lib/VSDContentCollector.cpp |  132 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 125 insertions(+), 7 deletions(-)

New commits:
commit 53f7dacb2869feaa959f56a701f123839fbb8a80
Author: Fridrich Štrba <fridrich.strba at bluewin.ch>
Date:   Tue Dec 29 16:29:36 2015 +0100

    Avoid equality comparison of doubles, which is prone to rounding errors
    
    Change-Id: I37ba61b95c6850ea008fd6f7ac042bea783249d7

diff --git a/src/lib/VSDContentCollector.cpp b/src/lib/VSDContentCollector.cpp
index e6e3268..da6b073 100644
--- a/src/lib/VSDContentCollector.cpp
+++ b/src/lib/VSDContentCollector.cpp
@@ -301,7 +301,7 @@ void libvisio::VSDContentCollector::_flushCurrentPath()
         {
           if (!wasMove)
           {
-            if ((x == prevX) && (y == prevY))
+            if (VSD_ALMOST_ZERO(x - prevX) && VSD_ALMOST_ZERO(y - prevY))
             {
               if (tmpPath.back()["librevenge:path-action"]->getStr() != "Z")
               {
@@ -332,7 +332,7 @@ void libvisio::VSDContentCollector::_flushCurrentPath()
     {
       if (!wasMove)
       {
-        if ((x == prevX) && (y == prevY))
+        if (VSD_ALMOST_ZERO(x - prevX) && VSD_ALMOST_ZERO(y - prevY))
         {
           if (tmpPath.back()["librevenge:path-action"]->getStr() != "Z")
           {
commit d62d8b5f13b31b55706ad35fe69a871847a163e1
Author: Fridrich Štrba <fridrich.strba at bluewin.ch>
Date:   Tue Dec 29 16:15:48 2015 +0100

    A horrendous hack to emulate line rounding property
    
    It needs some annotation not to forget the reasons behind
    the mess. I will do it later, since still tracking down
    little imperfections.
    
    Change-Id: Ic6f9d58d69047e3926cc62b899fbc379ebbd58cf

diff --git a/src/lib/VSDContentCollector.cpp b/src/lib/VSDContentCollector.cpp
index 1a34b51..e6e3268 100644
--- a/src/lib/VSDContentCollector.cpp
+++ b/src/lib/VSDContentCollector.cpp
@@ -267,7 +267,7 @@ void libvisio::VSDContentCollector::_flushCurrentPath()
     if (!tmpPath.empty())
     {
       librevenge::RVNGPropertyListVector path;
-      _convertToPath(tmpPath, path, m_lineStyle.rounding);
+      _convertToPath(tmpPath, path, m_scale*m_lineStyle.rounding);
       m_shapeOutputDrawing->addStyle(fillPathProps);
       librevenge::RVNGPropertyList propList;
       propList.insert("svg:d", path);
@@ -350,7 +350,7 @@ void libvisio::VSDContentCollector::_flushCurrentPath()
     if (!tmpPath.empty())
     {
       librevenge::RVNGPropertyListVector path;
-      _convertToPath(tmpPath, path, m_lineStyle.rounding);
+      _convertToPath(tmpPath, path, m_scale*m_lineStyle.rounding);
       m_shapeOutputDrawing->addStyle(linePathProps);
       librevenge::RVNGPropertyList propList;
       propList.insert("svg:d", path);
@@ -362,10 +362,128 @@ void libvisio::VSDContentCollector::_flushCurrentPath()
 }
 
 void libvisio::VSDContentCollector::_convertToPath(const std::vector<librevenge::RVNGPropertyList> &segmentVector,
-                                                   librevenge::RVNGPropertyListVector &path, double /* rounding */)
+                                                   librevenge::RVNGPropertyListVector &path, double rounding)
 {
-  for (unsigned i = 0; i < segmentVector.size(); ++i)
-    path.append(segmentVector[i]);
+  if (segmentVector.empty())
+    return;
+  if (rounding > 0.0)
+  {
+    double prevX = segmentVector[0]["svg:x"] ? segmentVector[0]["svg:x"]->getDouble() : 0.0;
+    double prevY = segmentVector[0]["svg:y"] ? segmentVector[0]["svg:y"]->getDouble() : 0.0;
+    unsigned moveIndex = 0;
+    double maxRounding = DBL_MAX;
+    std::vector<librevenge::RVNGPropertyList> tmpSegment;
+    for (unsigned i = 0; i < segmentVector.size(); ++i)
+    {
+      if (segmentVector[i]["librevenge:path-action"] && segmentVector[i]["librevenge:path-action"]->getStr() == "M")
+      {
+        _convertToPath(tmpSegment, path, 0.0);
+        tmpSegment.clear();
+      }
+      tmpSegment.push_back(segmentVector[i]);
+      if (segmentVector[i]["librevenge:path-action"] && segmentVector[i]["librevenge:path-action"]->getStr() == "M")
+      {
+        prevX = segmentVector[i]["svg:x"] ? segmentVector[i]["svg:x"]->getDouble() : 0.0;
+        prevY = segmentVector[i]["svg:y"] ? segmentVector[i]["svg:y"]->getDouble() : 0.0;
+        moveIndex = i;
+        maxRounding = DBL_MAX;
+      }
+      else if (segmentVector[i]["librevenge:path-action"] && segmentVector[i]["librevenge:path-action"]->getStr() == "L")
+      {
+        double x0 = segmentVector[i]["svg:x"] ? segmentVector[i]["svg:x"]->getDouble() : 0.0;
+        double y0 = segmentVector[i]["svg:y"] ? segmentVector[i]["svg:y"]->getDouble() : 0.0;
+        if (i+1 < segmentVector.size() && segmentVector[i+1]["librevenge:path-action"] && segmentVector[i+1]["librevenge:path-action"]->getStr() == "L")
+        {
+          double x = segmentVector[i+1]["svg:x"] ? segmentVector[i+1]["svg:x"]->getDouble() : 0.0;
+          double y = segmentVector[i+1]["svg:y"] ? segmentVector[i+1]["svg:y"]->getDouble() : 0.0;
+          if (maxRounding > rounding)
+            maxRounding = sqrt((y0-prevY)*(y0-prevY) + (x0-prevX)*(x0-prevX)) / 2.0;
+          double halfLength = sqrt((y-y0)*(y-y0)+(x-x0)*(x-x0)) / 2.0;
+          if (maxRounding > halfLength)
+            maxRounding = halfLength;
+          if (maxRounding > rounding)
+            maxRounding = rounding;
+          double lambda = atan2(y0-prevY, x0-prevX);
+          double newX0 = x0-maxRounding*cos(lambda);
+          double newY0 = y0-maxRounding*sin(lambda);
+          lambda = atan2(y-y0, x-x0);
+          double newX = x0+maxRounding*cos(lambda);
+          double newY = y0+maxRounding*sin(lambda);
+          tmpSegment.back().insert("svg:x", newX0);
+          tmpSegment.back().insert("svg:y", newY0);
+          librevenge::RVNGPropertyList q;
+          q.insert("librevenge:path-action", "Q");
+          q.insert("svg:x1", x0);
+          q.insert("svg:y1", y0);
+          q.insert("svg:x", newX);
+          q.insert("svg:y", newY);
+          tmpSegment.push_back(q);
+          prevX = newX;
+          prevY = newY;
+          maxRounding = halfLength;
+        }
+        else if (i+1 < segmentVector.size() && segmentVector[i+1]["librevenge:path-action"] && segmentVector[i+1]["librevenge:path-action"]->getStr() == "Z")
+        {
+          if (tmpSegment.size() >= 2 &&
+              tmpSegment[0]["librevenge:path-action"] &&
+              tmpSegment[0]["librevenge:path-action"]->getStr() == "M" &&
+              tmpSegment[1]["librevenge:path-action"] &&
+              tmpSegment[1]["librevenge:path-action"]->getStr() == "L")
+          {
+            double lineX = segmentVector[moveIndex+1]["svg:x"] ? segmentVector[moveIndex+1]["svg:x"]->getDouble() : 0.0;
+            double lineY = segmentVector[moveIndex+1]["svg:y"] ? segmentVector[moveIndex+1]["svg:y"]->getDouble() : 0.0;
+            double halfLength = sqrt((lineY-y0)*(lineY-y0)+(lineX-x0)*(lineX-x0)) / 2.0;
+            if (maxRounding > halfLength)
+              maxRounding = halfLength;
+            if (maxRounding > rounding)
+              maxRounding = rounding;
+            double lambda = atan2(y0-prevY, x0-prevX);
+            double newX0 = x0-maxRounding*cos(lambda);
+            double newY0 = y0-maxRounding*sin(lambda);
+            lambda = atan2(lineY-y0, lineX-x0);
+            double newX = x0+maxRounding*cos(lambda);
+            double newY = y0+maxRounding*sin(lambda);
+            tmpSegment.back().insert("svg:x", newX0);
+            tmpSegment.back().insert("svg:y", newY0);
+            librevenge::RVNGPropertyList q;
+            q.insert("librevenge:path-action", "Q");
+            q.insert("svg:x1", x0);
+            q.insert("svg:y1", y0);
+            q.insert("svg:x", newX);
+            q.insert("svg:y", newY);
+            tmpSegment.push_back(q);
+            tmpSegment[0].insert("svg:x", newX) ;
+            tmpSegment[0].insert("svg:y", newY);
+            prevX = newX;
+            prevY = newY;
+            maxRounding = halfLength;
+          }
+          else
+            maxRounding = DBL_MAX;
+        }
+        else
+          maxRounding = DBL_MAX;
+      }
+      else if (segmentVector[i]["librevenge:path-action"] && segmentVector[i]["librevenge:path-action"]->getStr() == "Z")
+      {
+        prevX = segmentVector[moveIndex]["svg:x"] ? segmentVector[moveIndex]["svg:x"]->getDouble() : 0.0;
+        prevY = segmentVector[moveIndex]["svg:y"] ? segmentVector[moveIndex]["svg:y"]->getDouble() : 0.0;
+        maxRounding = DBL_MAX;
+      }
+      else
+      {
+        prevX = segmentVector[i]["svg:x"] ? segmentVector[i]["svg:x"]->getDouble() : 0.0;
+        prevY = segmentVector[i]["svg:y"] ? segmentVector[i]["svg:y"]->getDouble() : 0.0;
+        maxRounding = DBL_MAX;
+      }
+    }
+    _convertToPath(tmpSegment, path, 0.0);
+  }
+  else
+  {
+    for (unsigned i = 0; i < segmentVector.size(); ++i)
+      path.append(segmentVector[i]);
+  }
 }
 
 void libvisio::VSDContentCollector::_flushText()


More information about the Libreoffice-commits mailing list