X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Flivarot%2FShapeMisc.cpp;h=d6ca8c5333861da6117494c56aa34d62a8322b07;hb=530f7fc7cfa4351ec33163abd795460bbc351609;hp=7590500af08fbdd8c0ae4a170641b80a1df16bef;hpb=16a0c1b758e414746ce693cdd8d9694135f3ba87;p=inkscape.git diff --git a/src/livarot/ShapeMisc.cpp b/src/livarot/ShapeMisc.cpp index 7590500af..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,20 +526,16 @@ Shape::ConvertToFormeNested (Path * dest, int nbP, Path * *orig, int wildPath,in MakeSweepDestData (false); } -// 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::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 (dec == 0) + + if (power == 0) { _pts = a->_pts; if (numberOfPoints() > maxPt) @@ -553,7 +553,7 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_p { maxAr = numberOfEdges(); if (_has_edges_data) - eData.resize(maxAr); + eData.resize(maxAr); if (_has_sweep_src_data) swsData.resize(maxAr); if (_has_sweep_dest_data) @@ -575,20 +575,16 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_p for (int i = 0; i < a->numberOfEdges(); i++) { - // int stP=a->swsData[i].stPt/*,enP=a->swsData[i].enPt*/; int stB = -1, enB = -1; - if (dec > 0) - { - stB = a->CycleNextAt (a->getEdge(i).st, i); - enB = a->CyclePrevAt (a->getEdge(i).en, i); - } - else - { + 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); } - 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,28 +597,59 @@ 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; + 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 = (NR::L2(ptP * (*i2doc) - NR::Point(cx,cy))/radius); + 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_dec = 0; + this_power = 0; } else if (x <= 0) { - this_dec = dec; + if (mode == tweak_mode_repel) { + this_power = 0; + } else { + this_power = power; + } } else { - this_dec = dec * (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5); + this_power = power * (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5); } } else { - this_dec = dec; + if (mode == tweak_mode_repel) { + this_power = 0; + } else { + this_power = power; + } } - if (this_dec != 0) + 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; @@ -638,23 +665,28 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_p useT=0; } } - if (dec > 0) - { - 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, -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 (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 (dec < 0) + if (power < 0 || mode == tweak_mode_push || mode == tweak_mode_repel || mode == tweak_mode_roughen) { for (int i = 0; i < numberOfEdges(); i++) Inverse (i); @@ -679,17 +711,21 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_p return (done_something? 0 : shape_nothing_to_do); } -// pushing -// modeled after MakeOffset black magic, the only difference being in the DoRight/LeftJoin parameters + +// 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::MakePush (Shape * a, JoinType join, double miter, bool do_profile, NR::Point c, NR::Point vector, 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); bool done_something = false; - - if (NR::L2(vector) == 0) + + if (dec == 0) { _pts = a->_pts; if (numberOfPoints() > maxPt) @@ -729,11 +765,20 @@ Shape::MakePush (Shape * a, JoinType join, double miter, bool do_profile, NR::Po for (int i = 0; i < a->numberOfEdges(); i++) { + // int stP=a->swsData[i].stPt/*,enP=a->swsData[i].enPt*/; int stB = -1, enB = -1; - stB = a->CyclePrevAt (a->getEdge(i).st, i); - enB = a->CycleNextAt (a->getEdge(i).en, i); + if (dec > 0) + { + stB = a->CycleNextAt (a->getEdge(i).st, i); + enB = a->CyclePrevAt (a->getEdge(i).en, i); + } + else + { + stB = a->CyclePrevAt (a->getEdge(i).st, i); + 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; @@ -746,26 +791,26 @@ Shape::MakePush (Shape * a, JoinType join, double miter, bool do_profile, NR::Po MiscNormalize (enD); MiscNormalize (seD); - NR::Point ptP; + Geom::Point ptP; int stNo, enNo; ptP = a->getPoint(a->getEdge(i).st).x; - NR::Point this_vec; + double this_dec; if (do_profile && i2doc) { double alpha = 1; - double x = (NR::L2(ptP * (*i2doc) - c)/radius); + double x = (Geom::L2(ptP * (*i2doc) - Geom::Point(cx,cy))/radius); if (x > 1) { - this_vec = NR::Point(0,0); + this_dec = 0; } else if (x <= 0) { - this_vec = vector; + this_dec = dec; } else { - this_vec = (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5) * vector; + this_dec = dec * (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5); } } else { - this_vec = vector; + this_dec = dec; } - if (NR::L2(this_vec) != 0) + if (this_dec != 0) done_something = true; int usePathID=-1; @@ -783,152 +828,27 @@ Shape::MakePush (Shape * a, JoinType join, double miter, bool do_profile, NR::Po useT=0; } } - 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; - } - - - for (int i = 0; i < numberOfEdges(); i++) - Inverse (i); - - if ( _has_back_data ) { - for (int i = 0; i < a->numberOfEdges(); i++) + if (dec > 0) { - int nEd=AddEdge (a->swsData[i].stPt, a->swsData[i].enPt); - ebData[nEd]=a->ebData[i]; + 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 { - for (int i = 0; i < a->numberOfEdges(); i++) + else { - AddEdge (a->swsData[i].stPt, a->swsData[i].enPt); + 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; } } - a->MakeSweepSrcData (false); - a->MakeSweepDestData (false); - - return (done_something? 0 : shape_nothing_to_do); -} - -// pushing -// modeled after MakeOffset black magic, the only difference being in the DoRight/LeftJoin parameters -int -Shape::MakeJitter (Shape * a, JoinType join, double miter, bool do_profile, NR::Point c, double power, double radius, NR::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++) + if (dec < 0) { - int stB = -1, enB = -1; - stB = a->CyclePrevAt (a->getEdge(i).st, i); - enB = a->CycleNextAt (a->getEdge(i).en, i); - - NR::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); - - NR::Point ptP; - int stNo, enNo; - ptP = a->getPoint(a->getEdge(i).st).x; - - double this_power; - if (do_profile && i2doc) { - double alpha = 1; - double x = (NR::L2(ptP * (*i2doc) - c)/radius); - if (x > 1) { - this_power = 0; - } else if (x <= 0) { - this_power = power; - } else { - this_power = (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5) * power; - } - } else { - this_power = power; - } - - if (this_power != 0) - done_something = true; - - double angle = g_random_double_range(0, 2*M_PI); - NR::Point this_vec = g_random_double_range(0, 1) * this_power * NR::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; - } - } - 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; - } - - - for (int i = 0; i < numberOfEdges(); i++) + for (int i = 0; i < numberOfEdges(); i++) Inverse (i); + } if ( _has_back_data ) { for (int i = 0; i < a->numberOfEdges(); i++) @@ -945,11 +865,12 @@ Shape::MakeJitter (Shape * a, JoinType join, double miter, bool do_profile, NR:: a->MakeSweepSrcData (false); a->MakeSweepDestData (false); - + 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 @@ -1061,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) { @@ -1095,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) { @@ -1173,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) { @@ -1202,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); @@ -1219,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(); @@ -1314,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]); @@ -1335,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]); @@ -1353,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]); @@ -1394,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]); @@ -1415,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]); @@ -1433,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]); @@ -1462,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 @@ -1509,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); }