X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Flivarot%2FShapeMisc.cpp;h=d6ca8c5333861da6117494c56aa34d62a8322b07;hb=530f7fc7cfa4351ec33163abd795460bbc351609;hp=b269c1c9cf8dcfb6bd7b321f5d75cf3a7cd2d2ba;hpb=9750c2b6fc6843862effd2be59402193fe7171a1;p=inkscape.git diff --git a/src/livarot/ShapeMisc.cpp b/src/livarot/ShapeMisc.cpp index b269c1c9c..d6ca8c533 100644 --- a/src/livarot/ShapeMisc.cpp +++ b/src/livarot/ShapeMisc.cpp @@ -7,10 +7,14 @@ */ #include "livarot/Shape.h" +#include #include #include "livarot/Path.h" #include "livarot/path-description.h" #include +#include +#include +#include /* * polygon offset and polyline to path reassembling (when using back data) @@ -522,13 +526,199 @@ 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, 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, bool do_profile, double cx, double cy, double radius, NR::Matrix *i2doc) +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); @@ -588,7 +778,7 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_p 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; @@ -601,14 +791,14 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_p 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 = (NR::L2(ptP * (*i2doc) - NR::Point(cx,cy))/radius); + double x = (Geom::L2(ptP * (*i2doc) - Geom::Point(cx,cy))/radius); if (x > 1) { this_dec = 0; } else if (x <= 0) { @@ -679,6 +869,8 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_p 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 @@ -790,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) { @@ -824,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) { @@ -902,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) { @@ -931,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(from->descr_cmd[nPiece]); Path::CubicTangent (ts, sDx, prevx,nData->start,nData->p,nData->end); @@ -948,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(); @@ -1043,7 +1235,7 @@ Shape::ReFormeBezierTo (int bord, int curBord, Path * dest, Path * from) } else { - NR::Point tx; + Geom::Point tx; { PathDescrIntermBezierTo* psData = dynamic_cast(from->descr_cmd[pe]); PathDescrIntermBezierTo* pnData = dynamic_cast(from->descr_cmd[pe+1]); @@ -1064,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(from->descr_cmd[ps+1]); PathDescrIntermBezierTo* pnData = dynamic_cast(from->descr_cmd[ps+2]); @@ -1082,7 +1274,7 @@ Shape::ReFormeBezierTo (int bord, int curBord, Path * dest, Path * from) } else { - NR::Point tx; + Geom::Point tx; { PathDescrIntermBezierTo* psData = dynamic_cast(from->descr_cmd[ps+1]); PathDescrIntermBezierTo* pnData = dynamic_cast(from->descr_cmd[ps+2]); @@ -1123,7 +1315,7 @@ Shape::ReFormeBezierTo (int bord, int curBord, Path * dest, Path * from) } else { - NR::Point tx; + Geom::Point tx; { PathDescrIntermBezierTo* psData = dynamic_cast(from->descr_cmd[pe+1]); PathDescrIntermBezierTo* pnData = dynamic_cast(from->descr_cmd[pe+2]); @@ -1144,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(from->descr_cmd[ps]); PathDescrIntermBezierTo* pnData = dynamic_cast(from->descr_cmd[ps+1]); @@ -1162,7 +1354,7 @@ Shape::ReFormeBezierTo (int bord, int curBord, Path * dest, Path * from) } else { - NR::Point tx; + Geom::Point tx; { PathDescrIntermBezierTo* psData = dynamic_cast(from->descr_cmd[ps]); PathDescrIntermBezierTo* pnData = dynamic_cast(from->descr_cmd[ps+1]); @@ -1191,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(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 @@ -1238,7 +1430,7 @@ Shape::ReFormeBezierChunk (NR::Point px, NR::Point nx, nData = dynamic_cast(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); }