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

Fridrich Å trba fridrich.strba at bluewin.ch
Thu Jul 11 08:43:36 PDT 2013


 src/lib/CDRContentCollector.cpp |   38 ++++
 src/lib/CDRParser.cpp           |    9 -
 src/lib/CDRPath.cpp             |  325 ++++++++++++++++++++++++++++++++++++++++
 src/lib/CDRPath.h               |    1 
 4 files changed, 369 insertions(+), 4 deletions(-)

New commits:
commit 3d46ffb3840898d303777fee0f8900101eead9e2
Author: Fridrich Å trba <fridrich.strba at bluewin.ch>
Date:   Thu Jul 11 17:43:10 2013 +0200

    Some fixes of parser

diff --git a/src/lib/CDRContentCollector.cpp b/src/lib/CDRContentCollector.cpp
index 5dd33e2..e7722d5 100644
--- a/src/lib/CDRContentCollector.cpp
+++ b/src/lib/CDRContentCollector.cpp
@@ -1044,7 +1044,7 @@ void libcdr::CDRContentCollector::_lineProperties(WPXPropertyList &propList)
     startMarker.writeOut(path, viewBox, width);
     propList.insert("draw:marker-start-viewbox", viewBox);
     propList.insert("draw:marker-start-path", path);
-    propList.insert("draw:marker-start-width", width);
+    // propList.insert("draw:marker-start-width", width);
   }
   if (!m_currentLineStyle.endMarker.empty())
   {
@@ -1061,7 +1061,7 @@ void libcdr::CDRContentCollector::_lineProperties(WPXPropertyList &propList)
     endMarker.writeOut(path, viewBox, width);
     propList.insert("draw:marker-end-viewbox", viewBox);
     propList.insert("draw:marker-end-path", path);
-    propList.insert("draw:marker-end-width", width);
+    // propList.insert("draw:marker-end-width", width);
   }
 
 
diff --git a/src/lib/CDRParser.cpp b/src/lib/CDRParser.cpp
index c9bab09..ec76a21 100644
--- a/src/lib/CDRParser.cpp
+++ b/src/lib/CDRParser.cpp
@@ -1492,17 +1492,18 @@ void libcdr::CDRParser::readArrw(WPXInputStream *input, unsigned length)
   input->seek(4, WPX_SEEK_CUR);
   unsigned short pointNum = readU16(input);
   input->seek(4, WPX_SEEK_CUR);
-  std::vector<std::pair<double, double> > points;
   std::vector<unsigned char> pointTypes;
+  for (unsigned k=0; k<pointNum; k++)
+    pointTypes.push_back(readU8(input));
+  input->seek(1, WPX_SEEK_CUR);
+  std::vector<std::pair<double, double> > points;
   for (unsigned j=0; j<pointNum; j++)
   {
     std::pair<double, double> point;
-    point.first = (double)readCoordinate(input);
     point.second = (double)readCoordinate(input);
+    point.first = (double)readCoordinate(input);
     points.push_back(point);
   }
-  for (unsigned k=0; k<pointNum; k++)
-    pointTypes.push_back(readU8(input));
   CDRPath path;
   processPath(points, pointTypes, path);
   m_arrows[arrowId] = path;
commit 20179ba61a98c1b9896c751d847838383e968d23
Author: Fridrich Å trba <fridrich.strba at bluewin.ch>
Date:   Thu Jul 11 17:12:32 2013 +0200

    Some more code towards handling arrw

diff --git a/src/lib/CDRContentCollector.cpp b/src/lib/CDRContentCollector.cpp
index ee82c3a..5dd33e2 100644
--- a/src/lib/CDRContentCollector.cpp
+++ b/src/lib/CDRContentCollector.cpp
@@ -1026,8 +1026,46 @@ void libcdr::CDRContentCollector::_lineProperties(WPXPropertyList &propList)
       propList.insert("svg:stroke-width", 0.0);
       propList.insert("svg:stroke-color", "#000000");
     }
+  }
 
+  // Deal with line markers (arrows, etc.)
+  if (!m_currentLineStyle.startMarker.empty())
+  {
+    CDRPath startMarker(m_currentLineStyle.startMarker);
+    startMarker.transform(m_currentTransforms);
+    if (!m_groupTransforms.empty())
+      startMarker.transform(m_groupTransforms.top());
+    CDRTransform tmpTrafo(1.0, 0.0, -m_page.offsetX, 0.0, 1.0, -m_page.offsetY);
+    startMarker.transform(tmpTrafo);
+    tmpTrafo = CDRTransform(1.0, 0.0, 0.0, 0.0, -1.0, m_page.height);
+    startMarker.transform(tmpTrafo);
+    WPXString path, viewBox;
+    double width;
+    startMarker.writeOut(path, viewBox, width);
+    propList.insert("draw:marker-start-viewbox", viewBox);
+    propList.insert("draw:marker-start-path", path);
+    propList.insert("draw:marker-start-width", width);
   }
+  if (!m_currentLineStyle.endMarker.empty())
+  {
+    CDRPath endMarker(m_currentLineStyle.endMarker);
+    endMarker.transform(m_currentTransforms);
+    if (!m_groupTransforms.empty())
+      endMarker.transform(m_groupTransforms.top());
+    CDRTransform tmpTrafo(1.0, 0.0, -m_page.offsetX, 0.0, 1.0, -m_page.offsetY);
+    endMarker.transform(tmpTrafo);
+    tmpTrafo = CDRTransform(1.0, 0.0, 0.0, 0.0, -1.0, m_page.height);
+    endMarker.transform(tmpTrafo);
+    WPXString path, viewBox;
+    double width;
+    endMarker.writeOut(path, viewBox, width);
+    propList.insert("draw:marker-end-viewbox", viewBox);
+    propList.insert("draw:marker-end-path", path);
+    propList.insert("draw:marker-end-width", width);
+  }
+
+
+
 }
 
 void libcdr::CDRContentCollector::_generateBitmapFromPattern(WPXBinaryData &bitmap, const CDRPattern &pattern, const CDRColor &fgColor, const CDRColor &bgColor)
diff --git a/src/lib/CDRPath.cpp b/src/lib/CDRPath.cpp
index c9e86db..6446096 100644
--- a/src/lib/CDRPath.cpp
+++ b/src/lib/CDRPath.cpp
@@ -40,6 +40,206 @@
 #define DEBUG_SPLINES 0
 #endif
 
+namespace
+{
+
+static inline double getAngle(double bx, double by)
+{
+  return fmod(2*M_PI + (by > 0.0 ? 1.0 : -1.0) * acos( bx / sqrt(bx * bx + by * by) ), 2*M_PI);
+}
+
+static void getEllipticalArcBBox(double x0, double y0,
+                                 double rx, double ry, double phi, bool largeArc, bool sweep, double x, double y,
+                                 double &xmin, double &ymin, double &xmax, double &ymax)
+{
+  phi *= M_PI/180;
+  if (rx < 0.0)
+    rx *= -1.0;
+  if (ry < 0.0)
+    ry *= -1.0;
+
+  if (rx == 0.0 || ry == 0.0)
+  {
+    xmin = (x0 < x ? x0 : x);
+    xmax = (x0 > x ? x0 : x);
+    ymin = (y0 < y ? y0 : y);
+    ymax = (y0 > y ? y0 : y);
+    return;
+  }
+
+  const double x1prime = cos(phi)*(x0 - x)/2 + sin(phi)*(y0 - y)/2;
+  const double y1prime = -sin(phi)*(x0 - x)/2 + cos(phi)*(y0 - y)/2;
+
+  double radicant = (rx*rx*ry*ry - rx*rx*y1prime*y1prime - ry*ry*x1prime*x1prime)/(rx*rx*y1prime*y1prime + ry*ry*x1prime*x1prime);
+  double cxprime = 0.0;
+  double cyprime = 0.0;
+  if (radicant < 0.0)
+  {
+    double ratio = rx/ry;
+    radicant = y1prime*y1prime + x1prime*x1prime/(ratio*ratio);
+    if (radicant < 0.0)
+    {
+      xmin = (x0 < x ? x0 : x);
+      xmax = (x0 > x ? x0 : x);
+      ymin = (y0 < y ? y0 : y);
+      ymax = (y0 > y ? y0 : y);
+      return;
+    }
+    ry=sqrt(radicant);
+    rx=ratio*ry;
+  }
+  else
+  {
+    double factor = (largeArc==sweep ? -1.0 : 1.0)*sqrt(radicant);
+
+    cxprime = factor*rx*y1prime/ry;
+    cyprime = -factor*ry*x1prime/rx;
+  }
+
+  double cx = cxprime*cos(phi) - cyprime*sin(phi) + (x0 + x)/2;
+  double cy = cxprime*sin(phi) + cyprime*cos(phi) + (y0 + y)/2;
+
+  double txmin, txmax, tymin, tymax;
+
+  if (phi == 0 || phi == M_PI)
+  {
+    xmin = cx - rx;
+    txmin = getAngle(-rx, 0);
+    xmax = cx + rx;
+    txmax = getAngle(rx, 0);
+    ymin = cy - ry;
+    tymin = getAngle(0, -ry);
+    ymax = cy + ry;
+    tymax = getAngle(0, ry);
+  }
+  else if (phi == M_PI / 2.0 || phi == 3.0*M_PI/2.0)
+  {
+    xmin = cx - ry;
+    txmin = getAngle(-ry, 0);
+    xmax = cx + ry;
+    txmax = getAngle(ry, 0);
+    ymin = cy - rx;
+    tymin = getAngle(0, -rx);
+    ymax = cy + rx;
+    tymax = getAngle(0, rx);
+  }
+  else
+  {
+    txmin = -atan(ry*tan(phi)/rx);
+    txmax = M_PI - atan (ry*tan(phi)/rx);
+    xmin = cx + rx*cos(txmin)*cos(phi) - ry*sin(txmin)*sin(phi);
+    xmax = cx + rx*cos(txmax)*cos(phi) - ry*sin(txmax)*sin(phi);
+    double tmpY = cy + rx*cos(txmin)*sin(phi) + ry*sin(txmin)*cos(phi);
+    txmin = getAngle(xmin - cx, tmpY - cy);
+    tmpY = cy + rx*cos(txmax)*sin(phi) + ry*sin(txmax)*cos(phi);
+    txmax = getAngle(xmax - cx, tmpY - cy);
+
+    tymin = atan(ry/(tan(phi)*rx));
+    tymax = atan(ry/(tan(phi)*rx))+M_PI;
+    ymin = cy + rx*cos(tymin)*sin(phi) + ry*sin(tymin)*cos(phi);
+    ymax = cy + rx*cos(tymax)*sin(phi) + ry*sin(tymax)*cos(phi);
+    double tmpX = cx + rx*cos(tymin)*cos(phi) - ry*sin(tymin)*sin(phi);
+    tymin = getAngle(tmpX - cx, ymin - cy);
+    tmpX = cx + rx*cos(tymax)*cos(phi) - ry*sin(tymax)*sin(phi);
+    tymax = getAngle(tmpX - cx, ymax - cy);
+  }
+  if (xmin > xmax)
+  {
+    std::swap(xmin,xmax);
+    std::swap(txmin,txmax);
+  }
+  if (ymin > ymax)
+  {
+    std::swap(ymin,ymax);
+    std::swap(tymin,tymax);
+  }
+  double angle1 = getAngle(x0 - cx, y0 - cy);
+  double angle2 = getAngle(x - cx, y - cy);
+
+  if (!sweep)
+    std::swap(angle1, angle2);
+
+  bool otherArc = false;
+  if (angle1 > angle2)
+  {
+    std::swap(angle1, angle2);
+    otherArc = true;
+  }
+
+  if ((!otherArc && (angle1 > txmin || angle2 < txmin)) || (otherArc && !(angle1 > txmin || angle2 < txmin)))
+    xmin = x0 < x ? x0 : x;
+  if ((!otherArc && (angle1 > txmax || angle2 < txmax)) || (otherArc && !(angle1 > txmax || angle2 < txmax)))
+    xmax = x0 > x ? x0 : x;
+  if ((!otherArc && (angle1 > tymin || angle2 < tymin)) || (otherArc && !(angle1 > tymin || angle2 < tymin)))
+    ymin = y0 < y ? y0 : y;
+  if ((!otherArc && (angle1 > tymax || angle2 < tymax)) || (otherArc && !(angle1 > tymax || angle2 < tymax)))
+    ymax = y0 > y ? y0 : y;
+}
+
+static inline double quadraticExtreme(double t, double a, double b, double c)
+{
+  return (1.0-t)*(1.0-t)*a + 2.0*(1.0-t)*t*b + t*t*c;
+}
+
+static inline double quadraticDerivative(double a, double b, double c)
+{
+  double denominator = a - 2.0*b + c;
+  if (fabs(denominator) != 0.0)
+    return (a - b)/denominator;
+  return -1.0;
+}
+
+static void getQuadraticBezierBBox(double x0, double y0, double x1, double y1, double x, double y,
+                                   double &xmin, double &ymin, double &xmax, double &ymax)
+{
+  xmin = x0 < x ? x0 : x;
+  xmax = x0 > x ? x0 : x;
+  ymin = y0 < y ? y0 : y;
+  ymax = y0 > y ? y0 : y;
+
+  double t = quadraticDerivative(x0, x1, x);
+  if(t>=0 && t<=1)
+  {
+    double tmpx = quadraticExtreme(t, x0, x1, x);
+    xmin = tmpx < xmin ? tmpx : xmin;
+    xmax = tmpx > xmax ? tmpx : xmax;
+  }
+
+  t = quadraticDerivative(y0, y1, y);
+  if(t>=0 && t<=1)
+  {
+    double tmpy = quadraticExtreme(t, y0, y1, y);
+    ymin = tmpy < ymin ? tmpy : ymin;
+    ymax = tmpy > ymax ? tmpy : ymax;
+  }
+}
+
+static inline double cubicBase(double t, double a, double b, double c, double d)
+{
+  return (1.0-t)*(1.0-t)*(1.0-t)*a + 3.0*(1.0-t)*(1.0-t)*t*b + 3.0*(1.0-t)*t*t*c + t*t*t*d;
+}
+
+static void getCubicBezierBBox(double x0, double y0, double x1, double y1, double x2, double y2, double x, double y,
+                               double &xmin, double &ymin, double &xmax, double &ymax)
+{
+  xmin = x0 < x ? x0 : x;
+  xmax = x0 > x ? x0 : x;
+  ymin = y0 < y ? y0 : y;
+  ymax = y0 > y ? y0 : y;
+
+  for (double t = 0.0; t <= 1.0; t+=0.01)
+  {
+    double tmpx = cubicBase(t, x0, x1, x2, x);
+    xmin = tmpx < xmin ? tmpx : xmin;
+    xmax = tmpx > xmax ? tmpx : xmax;
+    double tmpy = cubicBase(t, y0, y1, y2, y);
+    ymin = tmpy < ymin ? tmpy : ymin;
+    ymax = tmpy > ymax ? tmpy : ymax;
+  }
+}
+
+} // anonymous namespace
+
 namespace libcdr
 {
 
@@ -500,6 +700,131 @@ void libcdr::CDRPath::writeOut(WPXPropertyListVector &vec) const
     (*iter)->writeOut(vec);
 }
 
+void libcdr::CDRPath::writeOut(WPXString &path, WPXString &viewBox, double &width) const
+{
+  WPXPropertyListVector vec;
+  writeOut(vec);
+  if(vec.count() == 0)
+    return;
+  // This must be a mistake and we do not want to crash lower
+  if(vec[0]["libwpg:path-action"]->getStr() == "Z")
+    return;
+
+  // try to find the bounding box
+  bool isFirstPoint = true;
+
+  double px = 0.0, py = 0.0, qx = 0.0, qy = 0.0;
+  double lastX = 0.0;
+  double lastY = 0.0;
+
+  for(unsigned k = 0; k < vec.count(); ++k)
+  {
+    if (!vec[k]["svg:x"] || !vec[k]["svg:y"])
+      continue;
+    if (isFirstPoint)
+    {
+      px = vec[k]["svg:x"]->getDouble();
+      py = vec[k]["svg:y"]->getDouble();
+      qx = px;
+      qy = py;
+      lastX = px;
+      lastY = py;
+      isFirstPoint = false;
+    }
+    px = (px > vec[k]["svg:x"]->getDouble()) ? vec[k]["svg:x"]->getDouble() : px;
+    py = (py > vec[k]["svg:y"]->getDouble()) ? vec[k]["svg:y"]->getDouble() : py;
+    qx = (qx < vec[k]["svg:x"]->getDouble()) ? vec[k]["svg:x"]->getDouble() : qx;
+    qy = (qy < vec[k]["svg:y"]->getDouble()) ? vec[k]["svg:y"]->getDouble() : qy;
+
+    double xmin, xmax, ymin, ymax;
+
+    if(vec[k]["libwpg:path-action"]->getStr() == "C")
+    {
+      getCubicBezierBBox(lastX, lastY, vec[k]["svg:x1"]->getDouble(), vec[k]["svg:y1"]->getDouble(),
+                         vec[k]["svg:x2"]->getDouble(), vec[k]["svg:y2"]->getDouble(),
+                         vec[k]["svg:x"]->getDouble(), vec[k]["svg:y"]->getDouble(), xmin, ymin, xmax, ymax);
+
+      px = (px > xmin ? xmin : px);
+      py = (py > ymin ? ymin : py);
+      qx = (qx < xmax ? xmax : qx);
+      qy = (qy < ymax ? ymax : qy);
+    }
+    if(vec[k]["libwpg:path-action"]->getStr() == "Q")
+    {
+      getQuadraticBezierBBox(lastX, lastY, vec[k]["svg:x1"]->getDouble(), vec[k]["svg:y1"]->getDouble(),
+                             vec[k]["svg:x"]->getDouble(), vec[k]["svg:y"]->getDouble(), xmin, ymin, xmax, ymax);
+
+      px = (px > xmin ? xmin : px);
+      py = (py > ymin ? ymin : py);
+      qx = (qx < xmax ? xmax : qx);
+      qy = (qy < ymax ? ymax : qy);
+    }
+    if(vec[k]["libwpg:path-action"]->getStr() == "A")
+    {
+      getEllipticalArcBBox(lastX, lastY, vec[k]["svg:rx"]->getDouble(), vec[k]["svg:ry"]->getDouble(),
+                           vec[k]["libwpg:rotate"] ? vec[k]["libwpg:rotate"]->getDouble() : 0.0,
+                           vec[k]["libwpg:large-arc"] ? vec[k]["libwpg:large-arc"]->getInt() : 1,
+                           vec[k]["libwpg:sweep"] ? vec[k]["libwpg:sweep"]->getInt() : 1,
+                           vec[k]["svg:x"]->getDouble(), vec[k]["svg:y"]->getDouble(), xmin, ymin, xmax, ymax);
+
+      px = (px > xmin ? xmin : px);
+      py = (py > ymin ? ymin : py);
+      qx = (qx < xmax ? xmax : qx);
+      qy = (qy < ymax ? ymax : qy);
+    }
+    lastX = vec[k]["svg:x"]->getDouble();
+    lastY = vec[k]["svg:y"]->getDouble();
+  }
+
+
+  width = qx - px;
+  viewBox.sprintf("%i %i %i %i", 0, 0, (unsigned)(2540*(qx - px)), (unsigned)(2540*(qy - py)));
+
+  for(unsigned i = 0; i < vec.count(); ++i)
+  {
+    WPXString sElement;
+    if (vec[i]["libwpg:path-action"]->getStr() == "M")
+    {
+      // 2540 is 2.54*1000, 2.54 in = 1 inch
+      sElement.sprintf("M%i %i", (unsigned)((vec[i]["svg:x"]->getDouble()-px)*2540),
+                       (unsigned)((vec[i]["svg:y"]->getDouble()-py)*2540));
+      path.append(sElement);
+    }
+    else if (vec[i]["libwpg:path-action"]->getStr() == "L")
+    {
+      sElement.sprintf("L%i %i", (unsigned)((vec[i]["svg:x"]->getDouble()-px)*2540),
+                       (unsigned)((vec[i]["svg:y"]->getDouble()-py)*2540));
+      path.append(sElement);
+    }
+    else if (vec[i]["libwpg:path-action"]->getStr() == "C")
+    {
+      sElement.sprintf("C%i %i %i %i %i %i", (unsigned)((vec[i]["svg:x1"]->getDouble()-px)*2540),
+                       (unsigned)((vec[i]["svg:y1"]->getDouble()-py)*2540), (unsigned)((vec[i]["svg:x2"]->getDouble()-px)*2540),
+                       (unsigned)((vec[i]["svg:y2"]->getDouble()-py)*2540), (unsigned)((vec[i]["svg:x"]->getDouble()-px)*2540),
+                       (unsigned)((vec[i]["svg:y"]->getDouble()-py)*2540));
+      path.append(sElement);
+    }
+    else if (vec[i]["libwpg:path-action"]->getStr() == "Q")
+    {
+      sElement.sprintf("Q%i %i %i %i", (unsigned)((vec[i]["svg:x1"]->getDouble()-px)*2540),
+                       (unsigned)((vec[i]["svg:y1"]->getDouble()-py)*2540), (unsigned)((vec[i]["svg:x"]->getDouble()-px)*2540),
+                       (unsigned)((vec[i]["svg:y"]->getDouble()-py)*2540));
+      path.append(sElement);
+    }
+    else if (vec[i]["libwpg:path-action"]->getStr() == "A")
+    {
+      sElement.sprintf("A%i %i %i %i %i %i %i", (unsigned)((vec[i]["svg:rx"]->getDouble())*2540),
+                       (unsigned)((vec[i]["svg:ry"]->getDouble())*2540), (vec[i]["libwpg:rotate"] ? vec[i]["libwpg:rotate"]->getInt() : 0),
+                       (vec[i]["libwpg:large-arc"] ? vec[i]["libwpg:large-arc"]->getInt() : 1),
+                       (vec[i]["libwpg:sweep"] ? vec[i]["libwpg:sweep"]->getInt() : 1),
+                       (unsigned)((vec[i]["svg:x"]->getDouble()-px)*2540), (unsigned)((vec[i]["svg:y"]->getDouble()-py)*2540));
+      path.append(sElement);
+    }
+    else if (vec[i]["libwpg:path-action"]->getStr() == "Z")
+      path.append(" Z");
+  }
+}
+
 void libcdr::CDRPath::transform(const CDRTransforms &trafos)
 {
   for (std::vector<CDRPathElement *>::iterator iter = m_elements.begin(); iter != m_elements.end(); ++iter)
diff --git a/src/lib/CDRPath.h b/src/lib/CDRPath.h
index ccff6d2..5faa4a5 100644
--- a/src/lib/CDRPath.h
+++ b/src/lib/CDRPath.h
@@ -70,6 +70,7 @@ public:
   void appendPath(const CDRPath &path);
 
   void writeOut(WPXPropertyListVector &vec) const;
+  void writeOut(WPXString &path, WPXString &viewBox, double &width) const;
   void transform(const CDRTransforms &trafos);
   void transform(const CDRTransform &trafo);
   CDRPathElement *clone();


More information about the Libreoffice-commits mailing list