Code

Avoid crash by uninitialized perspectives.
[inkscape.git] / src / livarot / ShapeMisc.cpp
index d9bb665f056a18704f6be0c1ae3ed54516963706..d6ca8c5333861da6117494c56aa34d62a8322b07 100644 (file)
@@ -7,10 +7,14 @@
  */
 
 #include "livarot/Shape.h"
+#include <libnr/nr-matrix-fns.h>
 #include <libnr/nr-point-fns.h>
 #include "livarot/Path.h"
 #include "livarot/path-description.h"
 #include <glib.h>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
 
 /*
  * polygon offset and polyline to path reassembling (when using back data)
@@ -35,8 +39,6 @@ Shape::ConvertToForme (Path * dest)
 {
   if (numberOfPoints() <= 1 || numberOfEdges() <= 1)
     return;
-  if (directedEulerian(this) == false)
-    return;
   
   // prepare
   dest->Reset ();
@@ -524,16 +526,204 @@ Shape::ConvertToFormeNested (Path * dest, int nbP, Path * *orig, int wildPath,in
   MakeSweepDestData (false);
 }
 
+
+int
+Shape::MakeTweak (int mode, Shape *a, double power, JoinType join, double miter, bool do_profile, Geom::Point c, Geom::Point vector, double radius, Geom::Matrix *i2doc)
+{
+  Reset (0, 0);
+  MakeBackData(a->_has_back_data);
+
+       bool done_something = false;
+
+  if (power == 0)
+  {
+    _pts = a->_pts;
+    if (numberOfPoints() > maxPt)
+    {
+      maxPt = numberOfPoints();
+      if (_has_points_data) {
+        pData.resize(maxPt);
+        _point_data_initialised = false;
+        _bbox_up_to_date = false;
+        }
+    }
+    
+    _aretes = a->_aretes;
+    if (numberOfEdges() > maxAr)
+    {
+      maxAr = numberOfEdges();
+      if (_has_edges_data)
+             eData.resize(maxAr);
+      if (_has_sweep_src_data)
+        swsData.resize(maxAr);
+      if (_has_sweep_dest_data)
+        swdData.resize(maxAr);
+      if (_has_raster_data)
+        swrData.resize(maxAr);
+      if (_has_back_data)
+        ebData.resize(maxAr);
+    }
+    return 0;
+  }
+  if (a->numberOfPoints() <= 1 || a->numberOfEdges() <= 1 || a->type != shape_polygon)
+    return shape_input_err;
+  
+  a->SortEdges ();
+  
+  a->MakeSweepDestData (true);
+  a->MakeSweepSrcData (true);
+  
+  for (int i = 0; i < a->numberOfEdges(); i++)
+  {
+    int stB = -1, enB = -1;
+    if (power <= 0 || mode == tweak_mode_push || mode == tweak_mode_repel || mode == tweak_mode_roughen)  {
+      stB = a->CyclePrevAt (a->getEdge(i).st, i);
+      enB = a->CycleNextAt (a->getEdge(i).en, i);
+    } else {
+      stB = a->CycleNextAt (a->getEdge(i).st, i);
+      enB = a->CyclePrevAt (a->getEdge(i).en, i);
+    }
+    
+    Geom::Point stD, seD, enD;
+    double stL, seL, enL;
+    stD = a->getEdge(stB).dx;
+    seD = a->getEdge(i).dx;
+    enD = a->getEdge(enB).dx;
+
+    stL = sqrt (dot(stD,stD));
+    seL = sqrt (dot(seD,seD));
+    enL = sqrt (dot(enD,enD));
+    MiscNormalize (stD);
+    MiscNormalize (enD);
+    MiscNormalize (seD);
+    
+    Geom::Point ptP;
+    int stNo, enNo;
+    ptP = a->getPoint(a->getEdge(i).st).x;
+
+       Geom::Point to_center = ptP * (*i2doc) - c;
+       Geom::Point to_center_normalized = (1/Geom::L2(to_center)) * to_center;
+
+               double this_power;
+               if (do_profile && i2doc) {
+                       double alpha = 1;
+                       double x;
+               if (mode == tweak_mode_repel) {
+                               x = (Geom::L2(to_center)/radius);
+                       } else {
+                               x = (Geom::L2(ptP * (*i2doc) - c)/radius);
+                       }
+                       if (x > 1) {
+                               this_power = 0;
+                       } else if (x <= 0) {
+               if (mode == tweak_mode_repel) {
+                                       this_power = 0;
+                               } else {
+                                       this_power = power;
+                               }
+                       } else {
+                               this_power = power * (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5);
+                       }
+               } else {
+               if (mode == tweak_mode_repel) {
+                               this_power = 0;
+                       } else {
+                               this_power = power;
+                       }
+               }
+
+               if (this_power != 0)
+                       done_something = true;
+
+               double scaler = 1 / (*i2doc).descrim();
+
+               Geom::Point this_vec(0,0);
+    if (mode == tweak_mode_push) {
+                       Geom::Matrix tovec (*i2doc);
+                       tovec[4] = tovec[5] = 0;
+                       tovec = tovec.inverse();
+                       this_vec = this_power * (vector * tovec) ;
+               } else if (mode == tweak_mode_repel) {
+                       this_vec = this_power * scaler * to_center_normalized;
+               } else if (mode == tweak_mode_roughen) {
+               double angle = g_random_double_range(0, 2*M_PI);
+               this_vec = g_random_double_range(0, 1) * this_power * scaler * Geom::Point(sin(angle), cos(angle));
+               }
+
+    int   usePathID=-1;
+    int   usePieceID=0;
+    double useT=0.0;
+    if ( a->_has_back_data ) {
+      if ( a->ebData[i].pathID >= 0 && a->ebData[stB].pathID == a->ebData[i].pathID && a->ebData[stB].pieceID == a->ebData[i].pieceID
+           && a->ebData[stB].tEn == a->ebData[i].tSt ) {
+        usePathID=a->ebData[i].pathID;
+        usePieceID=a->ebData[i].pieceID;
+        useT=a->ebData[i].tSt;
+      } else {
+        usePathID=a->ebData[i].pathID;
+        usePieceID=0;
+        useT=0;
+      }
+    }
+
+               if (mode == tweak_mode_push || mode == tweak_mode_repel || mode == tweak_mode_roughen) {
+                       Path::DoLeftJoin (this, 0, join, ptP+this_vec, stD+this_vec, seD+this_vec, miter, stL, seL,
+                                                                                               stNo, enNo,usePathID,usePieceID,useT);
+                       a->swsData[i].stPt = enNo;
+                       a->swsData[stB].enPt = stNo;
+               } else {
+                       if (power > 0) {
+                               Path::DoRightJoin (this, this_power * scaler, join, ptP, stD, seD, miter, stL, seL,
+                                                                                                        stNo, enNo,usePathID,usePieceID,useT);
+                               a->swsData[i].stPt = enNo;
+                               a->swsData[stB].enPt = stNo;
+                       } else {
+                               Path::DoLeftJoin (this, -this_power * scaler, join, ptP, stD, seD, miter, stL, seL,
+                                                                                                       stNo, enNo,usePathID,usePieceID,useT);
+                               a->swsData[i].stPt = enNo;
+                               a->swsData[stB].enPt = stNo;
+                       }
+               }
+  }
+
+  if (power < 0 || mode == tweak_mode_push || mode == tweak_mode_repel || mode == tweak_mode_roughen)
+  {
+    for (int i = 0; i < numberOfEdges(); i++)
+      Inverse (i);
+  }
+
+  if ( _has_back_data ) {
+    for (int i = 0; i < a->numberOfEdges(); i++)
+    {
+      int nEd=AddEdge (a->swsData[i].stPt, a->swsData[i].enPt);
+      ebData[nEd]=a->ebData[i];
+    }
+  } else {
+    for (int i = 0; i < a->numberOfEdges(); i++)
+    {
+      AddEdge (a->swsData[i].stPt, a->swsData[i].enPt);
+    }
+  }
+
+  a->MakeSweepSrcData (false);
+  a->MakeSweepDestData (false);
+  
+  return (done_something? 0 : shape_nothing_to_do);
+}
+
+
 // offsets
 // take each edge, offset it, and make joins with previous at edge start and next at edge end (previous and
 // next being with respect to the clockwise order)
-// you gotta be very careful with the join, has anything but the right one will fuck everything up
+// you gotta be very careful with the join, as anything but the right one will fuck everything up
 // see PathStroke.cpp for the "right" joins
 int
-Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter)
+Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_profile, double cx, double cy, double radius, Geom::Matrix *i2doc)
 {
   Reset (0, 0);
   MakeBackData(a->_has_back_data);
+
+       bool done_something = false;
   
   if (dec == 0)
   {
@@ -541,8 +731,11 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter)
     if (numberOfPoints() > maxPt)
     {
       maxPt = numberOfPoints();
-      if (_has_points_data)
+      if (_has_points_data) {
         pData.resize(maxPt);
+        _point_data_initialised = false;
+        _bbox_up_to_date = false;
+        }
     }
     
     _aretes = a->_aretes;
@@ -585,12 +778,12 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter)
       enB = a->CycleNextAt (a->getEdge(i).en, i);
     }
     
-    NR::Point stD, seD, enD;
+    Geom::Point stD, seD, enD;
     double stL, seL, enL;
     stD = a->getEdge(stB).dx;
     seD = a->getEdge(i).dx;
     enD = a->getEdge(enB).dx;
-    
+
     stL = sqrt (dot(stD,stD));
     seL = sqrt (dot(seD,seD));
     enL = sqrt (dot(enD,enD));
@@ -598,9 +791,28 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter)
     MiscNormalize (enD);
     MiscNormalize (seD);
     
-    NR::Point ptP;
+    Geom::Point ptP;
     int stNo, enNo;
     ptP = a->getPoint(a->getEdge(i).st).x;
+
+               double this_dec;
+               if (do_profile && i2doc) {
+                       double alpha = 1;
+                       double x = (Geom::L2(ptP * (*i2doc) - Geom::Point(cx,cy))/radius);
+                       if (x > 1) {
+                               this_dec = 0;
+                       } else if (x <= 0) {
+                               this_dec = dec;
+                       } else {
+                               this_dec = dec * (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5);
+                       }
+               } else {
+                       this_dec = dec;
+               }
+
+               if (this_dec != 0)
+                       done_something = true;
+
     int   usePathID=-1;
     int   usePieceID=0;
     double useT=0.0;
@@ -618,24 +830,26 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter)
     }
     if (dec > 0)
     {
-      Path::DoRightJoin (this, dec, join, ptP, stD, seD, miter, stL, seL,
+      Path::DoRightJoin (this, this_dec, join, ptP, stD, seD, miter, stL, seL,
                          stNo, enNo,usePathID,usePieceID,useT);
       a->swsData[i].stPt = enNo;
       a->swsData[stB].enPt = stNo;
     }
     else
     {
-      Path::DoLeftJoin (this, -dec, join, ptP, stD, seD, miter, stL, seL,
+      Path::DoLeftJoin (this, -this_dec, join, ptP, stD, seD, miter, stL, seL,
                         stNo, enNo,usePathID,usePieceID,useT);
       a->swsData[i].stPt = enNo;
       a->swsData[stB].enPt = stNo;
     }
   }
+
   if (dec < 0)
   {
     for (int i = 0; i < numberOfEdges(); i++)
       Inverse (i);
   }
+
   if ( _has_back_data ) {
     for (int i = 0; i < a->numberOfEdges(); i++)
     {
@@ -648,12 +862,15 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter)
       AddEdge (a->swsData[i].stPt, a->swsData[i].enPt);
     }
   }
+
   a->MakeSweepSrcData (false);
   a->MakeSweepDestData (false);
   
-  return 0;
+  return (done_something? 0 : shape_nothing_to_do);
 }
 
+
+
 // we found a contour, now reassemble the edges on it, instead of dumping them in the Path "dest" as a
 // polyline. since it was a DFS, the precParc and suivParc make a nice doubly-linked list of the edges in
 // the contour. the first and last edges of the contour are startBord and curBord
@@ -765,12 +982,12 @@ Shape::AddContour (Path * dest, int nbP, Path * *orig, int startBord, int curBor
 }
 
 int
-Shape::ReFormeLineTo (int bord, int curBord, Path * dest, Path * orig)
+Shape::ReFormeLineTo (int bord, int /*curBord*/, Path * dest, Path * /*orig*/)
 {
   int nPiece = ebData[bord].pieceID;
   int nPath = ebData[bord].pathID;
   double /*ts=ebData[bord].tSt, */ te = ebData[bord].tEn;
-  NR::Point nx = getPoint(getEdge(bord).en).x;
+  Geom::Point nx = getPoint(getEdge(bord).en).x;
   bord = swdData[bord].suivParc;
   while (bord >= 0)
   {
@@ -799,13 +1016,13 @@ Shape::ReFormeLineTo (int bord, int curBord, Path * dest, Path * orig)
 }
 
 int
-Shape::ReFormeArcTo (int bord, int curBord, Path * dest, Path * from)
+Shape::ReFormeArcTo (int bord, int /*curBord*/, Path * dest, Path * from)
 {
   int nPiece = ebData[bord].pieceID;
   int nPath = ebData[bord].pathID;
   double ts = ebData[bord].tSt, te = ebData[bord].tEn;
   //      double  px=pts[getEdge(bord).st].x,py=pts[getEdge(bord).st].y;
-  NR::Point nx = getPoint(getEdge(bord).en).x;
+  Geom::Point nx = getPoint(getEdge(bord).en).x;
   bord = swdData[bord].suivParc;
   while (bord >= 0)
   {
@@ -877,12 +1094,12 @@ Shape::ReFormeArcTo (int bord, int curBord, Path * dest, Path * from)
 }
 
 int
-Shape::ReFormeCubicTo (int bord, int curBord, Path * dest, Path * from)
+Shape::ReFormeCubicTo (int bord, int /*curBord*/, Path * dest, Path * from)
 {
   int nPiece = ebData[bord].pieceID;
   int nPath = ebData[bord].pathID;
   double ts = ebData[bord].tSt, te = ebData[bord].tEn;
-  NR::Point nx = getPoint(getEdge(bord).en).x;
+  Geom::Point nx = getPoint(getEdge(bord).en).x;
   bord = swdData[bord].suivParc;
   while (bord >= 0)
   {
@@ -906,9 +1123,9 @@ Shape::ReFormeCubicTo (int bord, int curBord, Path * dest, Path * from)
     }
     bord = swdData[bord].suivParc;
   }
-  NR::Point prevx = from->PrevPoint (nPiece - 1);
+  Geom::Point prevx = from->PrevPoint (nPiece - 1);
   
-  NR::Point sDx, eDx;
+  Geom::Point sDx, eDx;
   {
     PathDescrCubicTo *nData = dynamic_cast<PathDescrCubicTo *>(from->descr_cmd[nPiece]);
     Path::CubicTangent (ts, sDx, prevx,nData->start,nData->p,nData->end);
@@ -923,14 +1140,14 @@ Shape::ReFormeCubicTo (int bord, int curBord, Path * dest, Path * from)
 }
 
 int
-Shape::ReFormeBezierTo (int bord, int curBord, Path * dest, Path * from)
+Shape::ReFormeBezierTo (int bord, int /*curBord*/, Path * dest, Path * from)
 {
   int nPiece = ebData[bord].pieceID;
   int nPath = ebData[bord].pathID;
   double ts = ebData[bord].tSt, te = ebData[bord].tEn;
   int ps = nPiece, pe = nPiece;
-  NR::Point px = getPoint(getEdge(bord).st).x;
-  NR::Point nx = getPoint(getEdge(bord).en).x;
+  Geom::Point px = getPoint(getEdge(bord).st).x;
+  Geom::Point nx = getPoint(getEdge(bord).en).x;
   int inBezier = -1, nbInterm = -1;
   int typ;
   typ = from->descr_cmd[nPiece]->getType();
@@ -1018,7 +1235,7 @@ Shape::ReFormeBezierTo (int bord, int curBord, Path * dest, Path * from)
       }
       else
       {
-        NR::Point tx;
+        Geom::Point tx;
         {
           PathDescrIntermBezierTo* psData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[pe]);
           PathDescrIntermBezierTo* pnData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[pe+1]);
@@ -1039,7 +1256,7 @@ Shape::ReFormeBezierTo (int bord, int curBord, Path * dest, Path * from)
     {
       if (te > 0.9999)
       {
-        NR::Point tx;
+        Geom::Point tx;
         {
           PathDescrIntermBezierTo* psData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[ps+1]);
           PathDescrIntermBezierTo* pnData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[ps+2]);
@@ -1057,7 +1274,7 @@ Shape::ReFormeBezierTo (int bord, int curBord, Path * dest, Path * from)
       }
       else
       {
-        NR::Point tx;
+        Geom::Point tx;
         {
           PathDescrIntermBezierTo* psData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[ps+1]);
           PathDescrIntermBezierTo* pnData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[ps+2]);
@@ -1098,7 +1315,7 @@ Shape::ReFormeBezierTo (int bord, int curBord, Path * dest, Path * from)
       }
       else
       {
-        NR::Point tx;
+        Geom::Point tx;
         {
           PathDescrIntermBezierTo* psData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[pe+1]);
           PathDescrIntermBezierTo* pnData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[pe+2]);
@@ -1119,7 +1336,7 @@ Shape::ReFormeBezierTo (int bord, int curBord, Path * dest, Path * from)
     {
       if (te < 0.0001)
       {
-        NR::Point tx;
+        Geom::Point tx;
         {
           PathDescrIntermBezierTo* psData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[ps]);
           PathDescrIntermBezierTo* pnData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[ps+1]);
@@ -1137,7 +1354,7 @@ Shape::ReFormeBezierTo (int bord, int curBord, Path * dest, Path * from)
       }
       else
       {
-        NR::Point tx;
+        Geom::Point tx;
         {
           PathDescrIntermBezierTo* psData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[ps]);
           PathDescrIntermBezierTo* pnData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[ps+1]);
@@ -1166,15 +1383,15 @@ Shape::ReFormeBezierTo (int bord, int curBord, Path * dest, Path * from)
 }
 
 void
-Shape::ReFormeBezierChunk (NR::Point px, NR::Point nx,
+Shape::ReFormeBezierChunk (Geom::Point px, Geom::Point nx,
                            Path * dest, int inBezier, int nbInterm,
                            Path * from, int p, double ts, double te)
 {
   PathDescrBezierTo* nBData = dynamic_cast<PathDescrBezierTo*>(from->descr_cmd[inBezier]);
-  NR::Point bstx = from->PrevPoint (inBezier - 1);
-  NR::Point benx = nBData->p;
+  Geom::Point bstx = from->PrevPoint (inBezier - 1);
+  Geom::Point benx = nBData->p;
   
-  NR::Point mx;
+  Geom::Point mx;
   if (p == inBezier)
   {
     // premier bout
@@ -1213,7 +1430,7 @@ Shape::ReFormeBezierChunk (NR::Point px, NR::Point nx,
     nData = dynamic_cast<PathDescrIntermBezierTo*>(from->descr_cmd[p+2]);
     benx = (nData->p + mx) / 2;
   }
-  NR::Point cx;
+  Geom::Point cx;
   {
     Path::QuadraticPoint ((ts + te) / 2, cx, bstx, mx, benx);
   }