summaryrefslogtreecommitdiffstats
path: root/src/sp-offset.cpp
diff options
context:
space:
mode:
authorMarkus Engel <markus.engel@tum.de>2013-04-04 22:27:58 +0000
committerMarkus Engel <markus.engel@tum.de>2013-04-04 22:27:58 +0000
commit748ffce08bb6250c87adabb64f45bff02509e9e7 (patch)
tree42c279594149e045b4de61f90f0829bb1d408f22 /src/sp-offset.cpp
parentMerged SPSpiral and CSpiral. (diff)
downloadinkscape-748ffce08bb6250c87adabb64f45bff02509e9e7.tar.gz
inkscape-748ffce08bb6250c87adabb64f45bff02509e9e7.zip
Combined some classes.
(bzr r11608.1.75)
Diffstat (limited to 'src/sp-offset.cpp')
-rw-r--r--src/sp-offset.cpp531
1 files changed, 345 insertions, 186 deletions
diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp
index f812ad931..ede1ab39b 100644
--- a/src/sp-offset.cpp
+++ b/src/sp-offset.cpp
@@ -95,42 +95,32 @@ static void sp_offset_source_modified (SPObject *iSource, guint flags, SPItem *i
// reappearing in offset when the radius becomes too large
static bool use_slow_but_correct_offset_method=false;
-COffset::COffset(SPOffset* offset) : CShape(offset) {
- this->spoffset = offset;
-}
-
-COffset::~COffset() {
-}
-
-SPOffset::SPOffset() : SPShape() {
- SPOffset* offset = this;
-
- offset->coffset = new COffset(offset);
- offset->typeHierarchy.insert(typeid(SPOffset));
+SPOffset::SPOffset() : SPShape(), CShape(this) {
+ delete this->cshape;
+ this->cshape = this;
+ this->clpeitem = this;
+ this->citem = this;
+ this->cobject = this;
+
+ this->rad = 1.0;
+ this->original = NULL;
+ this->originalPath = NULL;
+ this->knotSet = false;
+ this->sourceDirty=false;
+ this->isUpdating=false;
+ // init various connections
+ this->sourceHref = NULL;
+ this->sourceRepr = NULL;
+ this->sourceObject = NULL;
- delete offset->cshape;
- offset->cshape = offset->coffset;
- offset->clpeitem = offset->coffset;
- offset->citem = offset->coffset;
- offset->cobject = offset->coffset;
+ new (&this->_modified_connection) sigc::connection();
+ new (&this->_delete_connection) sigc::connection();
+ new (&this->_changed_connection) sigc::connection();
+ new (&this->_transformed_connection) sigc::connection();
- offset->rad = 1.0;
- offset->original = NULL;
- offset->originalPath = NULL;
- offset->knotSet = false;
- offset->sourceDirty=false;
- offset->isUpdating=false;
- // init various connections
- offset->sourceHref = NULL;
- offset->sourceRepr = NULL;
- offset->sourceObject = NULL;
- new (&offset->_modified_connection) sigc::connection();
- new (&offset->_delete_connection) sigc::connection();
- new (&offset->_changed_connection) sigc::connection();
- new (&offset->_transformed_connection) sigc::connection();
// set up the uri reference
- offset->sourceRef = new SPUseReference(offset);
- offset->_changed_connection = offset->sourceRef->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_offset_href_changed), offset));
+ this->sourceRef = new SPUseReference(this);
+ this->_changed_connection = this->sourceRef->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_offset_href_changed), this));
}
SPOffset::~SPOffset() {
@@ -142,54 +132,58 @@ SPOffset::~SPOffset() {
this->_transformed_connection.disconnect();
}
-void COffset::build(SPDocument *document, Inkscape::XML::Node *repr) {
- SPOffset* object = this->spoffset;
-
+void SPOffset::build(SPDocument *document, Inkscape::XML::Node *repr) {
CShape::build(document, repr);
//XML Tree being used directly here while it shouldn't be.
- if (object->getRepr()->attribute("inkscape:radius")) {
- object->readAttr( "inkscape:radius" );
+ if (this->getRepr()->attribute("inkscape:radius")) {
+ this->readAttr( "inkscape:radius" );
} else {
//XML Tree being used directly here (as object->getRepr)
//in all the below lines in the block while it shouldn't be.
- gchar const *oldA = object->getRepr()->attribute("sodipodi:radius");
- object->getRepr()->setAttribute("inkscape:radius",oldA);
- object->getRepr()->setAttribute("sodipodi:radius",NULL);
+ gchar const *oldA = this->getRepr()->attribute("sodipodi:radius");
+ this->getRepr()->setAttribute("inkscape:radius",oldA);
+ this->getRepr()->setAttribute("sodipodi:radius",NULL);
- object->readAttr( "inkscape:radius" );
+ this->readAttr( "inkscape:radius" );
}
- if (object->getRepr()->attribute("inkscape:original")) {
- object->readAttr( "inkscape:original" );
+
+ if (this->getRepr()->attribute("inkscape:original")) {
+ this->readAttr( "inkscape:original" );
} else {
- gchar const *oldA = object->getRepr()->attribute("sodipodi:original");
- object->getRepr()->setAttribute("inkscape:original",oldA);
- object->getRepr()->setAttribute("sodipodi:original",NULL);
+ gchar const *oldA = this->getRepr()->attribute("sodipodi:original");
+ this->getRepr()->setAttribute("inkscape:original",oldA);
+ this->getRepr()->setAttribute("sodipodi:original",NULL);
- object->readAttr( "inkscape:original" );
+ this->readAttr( "inkscape:original" );
}
- if (object->getRepr()->attribute("xlink:href")) {
- object->readAttr( "xlink:href" );
+
+ if (this->getRepr()->attribute("xlink:href")) {
+ this->readAttr( "xlink:href" );
} else {
- gchar const *oldA = object->getRepr()->attribute("inkscape:href");
+ gchar const *oldA = this->getRepr()->attribute("inkscape:href");
+
if (oldA) {
size_t lA = strlen(oldA);
char *nA=(char*)malloc((1+lA+1)*sizeof(char));
+
memcpy(nA+1,oldA,lA*sizeof(char));
+
nA[0]='#';
nA[lA+1]=0;
- object->getRepr()->setAttribute("xlink:href",nA);
+
+ this->getRepr()->setAttribute("xlink:href",nA);
+
free(nA);
- object->getRepr()->setAttribute("inkscape:href",NULL);
+
+ this->getRepr()->setAttribute("inkscape:href",NULL);
}
- object->readAttr( "xlink:href" );
+
+ this->readAttr( "xlink:href" );
}
}
-Inkscape::XML::Node* COffset::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
- SPOffset* object = this->spoffset;
- SPOffset *offset = object;
-
+Inkscape::XML::Node* SPOffset::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
repr = xml_doc->createElement("svg:path");
}
@@ -200,20 +194,21 @@ Inkscape::XML::Node* COffset::write(Inkscape::XML::Document *xml_doc, Inkscape::
* inkscape:offset="cx cy exp revo rad arg t0"
*/
repr->setAttribute("sodipodi:type", "inkscape:offset");
- sp_repr_set_svg_double(repr, "inkscape:radius", offset->rad);
- repr->setAttribute("inkscape:original", offset->original);
- repr->setAttribute("inkscape:href", offset->sourceHref);
+ sp_repr_set_svg_double(repr, "inkscape:radius", this->rad);
+ repr->setAttribute("inkscape:original", this->original);
+ repr->setAttribute("inkscape:href", this->sourceHref);
}
- // Make sure the object has curve
- SPCurve *curve = SP_SHAPE (offset)->getCurve();
+ // Make sure the offset has curve
+ SPCurve *curve = SP_SHAPE (this)->getCurve();
+
if (curve == NULL) {
this->set_shape();
}
// write that curve to "d"
- char *d = sp_svg_write_path (offset->_curve->get_pathvector());
+ char *d = sp_svg_write_path (this->_curve->get_pathvector());
repr->setAttribute("d", d);
g_free (d);
@@ -222,30 +217,34 @@ Inkscape::XML::Node* COffset::write(Inkscape::XML::Document *xml_doc, Inkscape::
return repr;
}
-void COffset::release() {
- SPOffset* object = this->spoffset;
- SPOffset *offset = (SPOffset *) object;
+void SPOffset::release() {
+ if (this->original) {
+ free (this->original);
+ }
- if (offset->original) free (offset->original);
- if (offset->originalPath) delete ((Path *) offset->originalPath);
- offset->original = NULL;
- offset->originalPath = NULL;
+ if (this->originalPath) {
+ delete ((Path *) this->originalPath);
+ }
- sp_offset_quit_listening(offset);
+ this->original = NULL;
+ this->originalPath = NULL;
+
+ sp_offset_quit_listening(this);
+
+ this->_changed_connection.disconnect();
- offset->_changed_connection.disconnect();
- g_free(offset->sourceHref);
- offset->sourceHref = NULL;
- offset->sourceRef->detach();
+ g_free(this->sourceHref);
+
+ this->sourceHref = NULL;
+ this->sourceRef->detach();
CShape::release();
}
-void COffset::set(unsigned int key, const gchar* value) {
- SPOffset* object = this->spoffset;
- SPOffset *offset = object;
-
- if ( offset->sourceDirty ) refresh_offset_source(offset);
+void SPOffset::set(unsigned int key, const gchar* value) {
+ if ( this->sourceDirty ) {
+ refresh_offset_source(this);
+ }
/* fixme: we should really collect updates */
switch (key)
@@ -254,95 +253,112 @@ void COffset::set(unsigned int key, const gchar* value) {
case SP_ATTR_SODIPODI_ORIGINAL:
if (value == NULL) {
} else {
- if (offset->original) {
- free (offset->original);
- delete ((Path *) offset->originalPath);
- offset->original = NULL;
- offset->originalPath = NULL;
+ if (this->original) {
+ free (this->original);
+ delete ((Path *) this->originalPath);
+
+ this->original = NULL;
+ this->originalPath = NULL;
}
- offset->original = strdup (value);
+ this->original = strdup (value);
+
+ Geom::PathVector pv = sp_svg_read_pathv(this->original);
+
+ this->originalPath = new Path;
+ reinterpret_cast<Path *>(this->originalPath)->LoadPathVector(pv);
- Geom::PathVector pv = sp_svg_read_pathv(offset->original);
- offset->originalPath = new Path;
- reinterpret_cast<Path *>(offset->originalPath)->LoadPathVector(pv);
+ this->knotSet = false;
- offset->knotSet = false;
- if ( offset->isUpdating == false ) object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ if ( this->isUpdating == false ) {
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
}
break;
+
case SP_ATTR_INKSCAPE_RADIUS:
case SP_ATTR_SODIPODI_RADIUS:
- if (!sp_svg_length_read_computed_absolute (value, &offset->rad)) {
- if (fabs (offset->rad) < 0.01)
- offset->rad = (offset->rad < 0) ? -0.01 : 0.01;
- offset->knotSet = false; // knotset=false because it's not set from the context
+ if (!sp_svg_length_read_computed_absolute (value, &this->rad)) {
+ if (fabs (this->rad) < 0.01) {
+ this->rad = (this->rad < 0) ? -0.01 : 0.01;
+ }
+
+ this->knotSet = false; // knotset=false because it's not set from the context
+ }
+
+ if ( this->isUpdating == false ) {
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
- if ( offset->isUpdating == false ) object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
+
case SP_ATTR_INKSCAPE_HREF:
case SP_ATTR_XLINK_HREF:
if ( value == NULL ) {
- sp_offset_quit_listening(offset);
- if ( offset->sourceHref ) g_free(offset->sourceHref);
- offset->sourceHref = NULL;
- offset->sourceRef->detach();
+ sp_offset_quit_listening(this);
+ if ( this->sourceHref ) {
+ g_free(this->sourceHref);
+ }
+
+ this->sourceHref = NULL;
+ this->sourceRef->detach();
} else {
- if ( offset->sourceHref && ( strcmp(value, offset->sourceHref) == 0 ) ) {
+ if ( this->sourceHref && ( strcmp(value, this->sourceHref) == 0 ) ) {
} else {
- if ( offset->sourceHref ) g_free(offset->sourceHref);
- offset->sourceHref = g_strdup(value);
+ if ( this->sourceHref ) {
+ g_free(this->sourceHref);
+ }
+
+ this->sourceHref = g_strdup(value);
+
try {
- offset->sourceRef->attach(Inkscape::URI(value));
+ this->sourceRef->attach(Inkscape::URI(value));
} catch (Inkscape::BadURIException &e) {
g_warning("%s", e.what());
- offset->sourceRef->detach();
+ this->sourceRef->detach();
}
}
}
break;
+
default:
CShape::set(key, value);
break;
}
}
-void COffset::update(SPCtx *ctx, guint flags) {
- SPOffset* object = this->spoffset;
- SPOffset* offset = object;
-
- offset->isUpdating=true; // prevent sp_offset_set from requesting updates
- if ( offset->sourceDirty ) refresh_offset_source(offset);
+void SPOffset::update(SPCtx *ctx, guint flags) {
+ this->isUpdating=true; // prevent sp_offset_set from requesting updates
+
+ if ( this->sourceDirty ) {
+ refresh_offset_source(this);
+ }
+
if (flags &
(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
- ((SPShape *) object)->setShape ();
+
+ this->setShape ();
}
- offset->isUpdating=false;
+
+ this->isUpdating=false;
CShape::update(ctx, flags);
}
-gchar* COffset::description() {
- SPOffset* item = this->spoffset;
- SPOffset *offset = item;
-
- if ( offset->sourceHref ) {
+gchar* SPOffset::description() {
+ if ( this->sourceHref ) {
// TRANSLATORS COMMENT: %s is either "outset" or "inset" depending on sign
return g_strdup_printf(_("<b>Linked offset</b>, %s by %f pt"),
- (offset->rad >= 0)? _("outset") : _("inset"), fabs (offset->rad));
+ (this->rad >= 0)? _("outset") : _("inset"), fabs (this->rad));
} else {
// TRANSLATORS COMMENT: %s is either "outset" or "inset" depending on sign
return g_strdup_printf(_("<b>Dynamic offset</b>, %s by %f pt"),
- (offset->rad >= 0)? _("outset") : _("inset"), fabs (offset->rad));
+ (this->rad >= 0)? _("outset") : _("inset"), fabs (this->rad));
}
}
-void COffset::set_shape() {
- SPOffset* shape = this->spoffset;
- SPOffset *offset = shape;
-
- if ( offset->originalPath == NULL ) {
+void SPOffset::set_shape() {
+ if ( this->originalPath == NULL ) {
// oops : no path?! (the offset object should do harakiri)
return;
}
@@ -351,30 +367,35 @@ void COffset::set_shape() {
#endif
// au boulot
- if ( fabs(offset->rad) < 0.01 ) {
+ if ( fabs(this->rad) < 0.01 ) {
// grosso modo: 0
- // just put the source shape as the offseted one, no one will notice
+ // just put the source this as the offseted one, no one will notice
// it's also useless to compute the offset with a 0 radius
//XML Tree being used directly here while it shouldn't be.
- const char *res_d = shape->getRepr()->attribute("inkscape:original");
+ const char *res_d = this->getRepr()->attribute("inkscape:original");
+
if ( res_d ) {
Geom::PathVector pv = sp_svg_read_pathv(res_d);
SPCurve *c = new SPCurve(pv);
g_assert(c != NULL);
- ((SPShape *) offset)->setCurveInsync (c, TRUE);
- ((SPShape *) offset)->setCurveBeforeLPE(c);
+
+ this->setCurveInsync (c, TRUE);
+ this->setCurveBeforeLPE(c);
+
c->unref();
}
+
return;
}
// extra paraniac careful check. the preceding if () should take care of this case
- if (fabs (offset->rad) < 0.01)
- offset->rad = (offset->rad < 0) ? -0.01 : 0.01;
+ if (fabs (this->rad) < 0.01) {
+ this->rad = (this->rad < 0) ? -0.01 : 0.01;
+ }
Path *orig = new Path;
- orig->Copy ((Path *) offset->originalPath);
+ orig->Copy ((Path *)this->originalPath);
if ( use_slow_but_correct_offset_method == false ) {
// version par outline
@@ -386,14 +407,14 @@ void COffset::set_shape() {
// and now: offset
float o_width;
- if (offset->rad >= 0)
+ if (this->rad >= 0)
{
- o_width = offset->rad;
+ o_width = this->rad;
orig->OutsideOutline (res, o_width, join_round, butt_straight, 20.0);
}
else
{
- o_width = -offset->rad;
+ o_width = -this->rad;
orig->OutsideOutline (res, -o_width, join_round, butt_straight, 20.0);
}
@@ -413,13 +434,16 @@ void COffset::set_shape() {
theRes->ConvertToForme (orig, 1, originaux);
- SPItem *item = shape;
- Geom::OptRect bbox = item->desktopVisualBounds();
+ Geom::OptRect bbox = this->desktopVisualBounds();
+
if ( bbox ) {
gdouble size = L2(bbox->dimensions());
- gdouble const exp = item->transform.descrim();
- if (exp != 0)
+ gdouble const exp = this->transform.descrim();
+
+ if (exp != 0) {
size /= exp;
+ }
+
orig->Coalesce (size * 0.001);
//g_print ("coa %g exp %g item %p\n", size * 0.001, exp, item);
}
@@ -450,13 +474,13 @@ void COffset::set_shape() {
// and now: offset
float o_width;
- if (offset->rad >= 0)
+ if (this->rad >= 0)
{
- o_width = offset->rad;
+ o_width = this->rad;
}
else
{
- o_width = -offset->rad;
+ o_width = -this->rad;
}
// one has to have a measure of the details
@@ -468,24 +492,32 @@ void COffset::set_shape() {
{
orig->ConvertWithBackData (0.5*o_width);
}
+
orig->Fill (theShape, 0);
theRes->ConvertToShape (theShape, fill_positive);
+
Path *originaux[1];
originaux[0]=orig;
+
Path *res = new Path;
theRes->ConvertToForme (res, 1, originaux);
+
int nbPart=0;
Path** parts=res->SubPaths(nbPart,true);
char *holes=(char*)malloc(nbPart*sizeof(char));
+
// we offset contours separately, because we can.
// this way, we avoid doing a unique big ConvertToShape when dealing with big shapes with lots of holes
{
Shape* onePart=new Shape;
Shape* oneCleanPart=new Shape;
+
theShape->Reset();
+
for (int i=0;i<nbPart;i++) {
double partSurf=parts[i]->Surface();
parts[i]->Convert(1.0);
+
{
// raffiner si besoin
double bL,bT,bR,bB;
@@ -495,29 +527,41 @@ void COffset::set_shape() {
parts[i]->Convert(0.02*mesure);
}
}
+
if ( partSurf < 0 ) { // inverse par rapport a la realite
// plein
holes[i]=0;
parts[i]->Fill(oneCleanPart,0);
onePart->ConvertToShape(oneCleanPart,fill_positive); // there aren't intersections in that one, but maybe duplicate points and null edges
- oneCleanPart->MakeOffset(onePart,offset->rad,join_round,20.0);
+ oneCleanPart->MakeOffset(onePart,this->rad,join_round,20.0);
onePart->ConvertToShape(oneCleanPart,fill_positive);
onePart->CalcBBox();
double typicalSize=0.5*((onePart->rightX-onePart->leftX)+(onePart->bottomY-onePart->topY));
- if ( typicalSize < 0.05 ) typicalSize=0.05;
+
+ if ( typicalSize < 0.05 ) {
+ typicalSize=0.05;
+ }
+
typicalSize*=0.01;
- if ( typicalSize > 1.0 ) typicalSize=1.0;
+
+ if ( typicalSize > 1.0 ) {
+ typicalSize=1.0;
+ }
+
onePart->ConvertToForme (parts[i]);
parts[i]->ConvertEvenLines (typicalSize);
parts[i]->Simplify (typicalSize);
+
double nPartSurf=parts[i]->Surface();
+
if ( nPartSurf >= 0 ) {
// inversion de la surface -> disparait
delete parts[i];
parts[i]=NULL;
} else {
}
+
/* int firstP=theShape->nbPt;
for (int j=0;j<onePart->nbPt;j++) theShape->AddPoint(onePart->pts[j].x);
for (int j=0;j<onePart->nbAr;j++) theShape->AddEdge(firstP+onePart->aretes[j].st,firstP+onePart->aretes[j].en);*/
@@ -526,19 +570,28 @@ void COffset::set_shape() {
holes[i]=1;
parts[i]->Fill(oneCleanPart,0,false,true,true);
onePart->ConvertToShape(oneCleanPart,fill_positive);
- oneCleanPart->MakeOffset(onePart,-offset->rad,join_round,20.0);
+ oneCleanPart->MakeOffset(onePart,-this->rad,join_round,20.0);
onePart->ConvertToShape(oneCleanPart,fill_positive);
// for (int j=0;j<onePart->nbAr;j++) onePart->Inverse(j); // pas oublier de reinverser
onePart->CalcBBox();
double typicalSize=0.5*((onePart->rightX-onePart->leftX)+(onePart->bottomY-onePart->topY));
- if ( typicalSize < 0.05 ) typicalSize=0.05;
+
+ if ( typicalSize < 0.05 ) {
+ typicalSize=0.05;
+ }
+
typicalSize*=0.01;
- if ( typicalSize > 1.0 ) typicalSize=1.0;
+
+ if ( typicalSize > 1.0 ) {
+ typicalSize=1.0;
+ }
+
onePart->ConvertToForme (parts[i]);
parts[i]->ConvertEvenLines (typicalSize);
parts[i]->Simplify (typicalSize);
double nPartSurf=parts[i]->Surface();
+
if ( nPartSurf >= 0 ) {
// inversion de la surface -> disparait
delete parts[i];
@@ -556,11 +609,14 @@ void COffset::set_shape() {
delete onePart;
delete oneCleanPart;
}
+
if ( nbPart > 1 ) {
theShape->Reset();
+
for (int i=0;i<nbPart;i++) {
if ( parts[i] ) {
parts[i]->ConvertWithBackData(1.0);
+
if ( holes[i] ) {
parts[i]->Fill(theShape,i,true,true,true);
} else {
@@ -568,12 +624,23 @@ void COffset::set_shape() {
}
}
}
+
theRes->ConvertToShape (theShape, fill_positive);
theRes->ConvertToForme (orig,nbPart,parts);
- for (int i=0;i<nbPart;i++) if ( parts[i] ) delete parts[i];
+
+ for (int i=0;i<nbPart;i++) {
+ if ( parts[i] ) {
+ delete parts[i];
+ }
+ }
} else if ( nbPart == 1 ) {
orig->Copy(parts[0]);
- for (int i=0;i<nbPart;i++) if ( parts[i] ) delete parts[i];
+
+ for (int i=0;i<nbPart;i++) {
+ if ( parts[i] ) {
+ delete parts[i];
+ }
+ }
} else {
orig->Reset();
}
@@ -588,14 +655,21 @@ void COffset::set_shape() {
orig->Simplify (1.0 * o_width);
}*/
- if ( parts ) free(parts);
- if ( holes ) free(holes);
+ if ( parts ) {
+ free(parts);
+ }
+
+ if ( holes ) {
+ free(holes);
+ }
+
delete res;
delete theShape;
delete theRes;
}
{
char *res_d = NULL;
+
if (orig->descr_cmd.size() <= 1)
{
// Aie.... nothing left.
@@ -607,20 +681,22 @@ void COffset::set_shape() {
res_d = orig->svg_dump_path ();
}
+
delete orig;
Geom::PathVector pv = sp_svg_read_pathv(res_d);
SPCurve *c = new SPCurve(pv);
g_assert(c != NULL);
- ((SPShape *) offset)->setCurveInsync (c, TRUE);
- ((SPShape *) offset)->setCurveBeforeLPE(c);
+
+ this->setCurveInsync (c, TRUE);
+ this->setCurveBeforeLPE(c);
c->unref();
free (res_d);
}
}
-void COffset::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) {
+void SPOffset::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) {
CShape::snappoints(p, snapprefs);
}
@@ -656,31 +732,53 @@ vectors_are_clockwise (Geom::Point A, Geom::Point B, Geom::Point C)
double ca_c = dot(C, A);
double ab_a = acos (ab_c);
- if (ab_c <= -1.0)
+
+ if (ab_c <= -1.0) {
ab_a = M_PI;
- if (ab_c >= 1.0)
+ }
+
+ if (ab_c >= 1.0) {
ab_a = 0;
- if (ab_s < 0)
+ }
+
+ if (ab_s < 0) {
ab_a = 2 * M_PI - ab_a;
+ }
+
double bc_a = acos (bc_c);
- if (bc_c <= -1.0)
+
+ if (bc_c <= -1.0) {
bc_a = M_PI;
- if (bc_c >= 1.0)
+ }
+
+ if (bc_c >= 1.0) {
bc_a = 0;
- if (bc_s < 0)
+ }
+
+ if (bc_s < 0) {
bc_a = 2 * M_PI - bc_a;
+ }
+
double ca_a = acos (ca_c);
- if (ca_c <= -1.0)
+
+ if (ca_c <= -1.0) {
ca_a = M_PI;
- if (ca_c >= 1.0)
+ }
+
+ if (ca_c >= 1.0) {
ca_a = 0;
- if (ca_s < 0)
+ }
+
+ if (ca_s < 0) {
ca_a = 2 * M_PI - ca_a;
+ }
double lim = 2 * M_PI - ca_a;
- if (ab_a < lim)
+ if (ab_a < lim) {
return true;
+ }
+
return false;
}
@@ -695,9 +793,10 @@ vectors_are_clockwise (Geom::Point A, Geom::Point B, Geom::Point C)
double
sp_offset_distance_to_original (SPOffset * offset, Geom::Point px)
{
- if (offset == NULL || offset->originalPath == NULL
- || ((Path *) offset->originalPath)->descr_cmd.size() <= 1)
+ if (offset == NULL || offset->originalPath == NULL || ((Path *) offset->originalPath)->descr_cmd.size() <= 1) {
return 1.0;
+ }
+
double dist = 1.0;
Shape *theShape = new Shape;
Shape *theRes = new Shape;
@@ -726,14 +825,16 @@ sp_offset_distance_to_original (SPOffset * offset, Geom::Point px)
bool ptSet = false;
double arDist = -1.0;
bool arSet = false;
+
// first get the minimum distance to the points
for (int i = 0; i < theRes->numberOfPoints(); i++)
{
if (theRes->getPoint(i).totalDegree() > 0)
- {
+ {
Geom::Point nx = theRes->getPoint(i).x;
Geom::Point nxpx = px-nx;
double ndist = sqrt (dot(nxpx,nxpx));
+
if (ptSet == false || fabs (ndist) < fabs (ptDist))
{
// we have a new minimum distance
@@ -745,6 +846,7 @@ sp_offset_distance_to_original (SPOffset * offset, Geom::Point px)
fb = theRes->getPoint(i).incidentEdge[LAST];
pb = theRes->getPoint(i).incidentEdge[LAST];
cb = theRes->getPoint(i).incidentEdge[FIRST];
+
do
{
// one angle
@@ -755,10 +857,12 @@ sp_offset_distance_to_original (SPOffset * offset, Geom::Point px)
nex = theRes->getEdge(cb).dx;
nlen = sqrt (dot(nex , nex));
nex /= nlen;
+
if (theRes->getEdge(pb).en == i)
{
prx = -prx;
}
+
if (theRes->getEdge(cb).en == i)
{
nex = -nex;
@@ -779,13 +883,16 @@ sp_offset_distance_to_original (SPOffset * offset, Geom::Point px)
}
break;
}
+
pb = cb;
cb = theRes->NextAt (i, cb);
}
+
while (cb >= 0 && pb >= 0 && pb != fb);
}
}
}
+
// loop over the edges to try to improve the distance
for (int i = 0; i < theRes->numberOfEdges(); i++)
{
@@ -793,14 +900,17 @@ sp_offset_distance_to_original (SPOffset * offset, Geom::Point px)
Geom::Point ex = theRes->getPoint(theRes->getEdge(i).en).x;
Geom::Point nx = ex - sx;
double len = sqrt (dot(nx,nx));
+
if (len > 0.0001)
{
Geom::Point pxsx=px-sx;
double ab = dot(nx,pxsx);
+
if (ab > 0 && ab < len * len)
{
// we're in the zone of influence of the segment
double ndist = (cross(pxsx,nx)) / len;
+
if (arSet == false || fabs (ndist) < fabs (arDist))
{
arDist = ndist;
@@ -809,16 +919,22 @@ sp_offset_distance_to_original (SPOffset * offset, Geom::Point px)
}
}
}
+
if (arSet || ptSet)
{
- if (arSet == false)
+ if (arSet == false) {
arDist = ptDist;
- if (ptSet == false)
+ }
+
+ if (ptSet == false) {
ptDist = arDist;
- if (fabs (ptDist) < fabs (arDist))
+ }
+
+ if (fabs (ptDist) < fabs (arDist)) {
dist = ptDist;
- else
+ } else {
dist = arDist;
+ }
}
}
@@ -838,8 +954,10 @@ void
sp_offset_top_point (SPOffset const * offset, Geom::Point *px)
{
(*px) = Geom::Point(0, 0);
- if (offset == NULL)
+
+ if (offset == NULL) {
return;
+ }
if (offset->knotSet)
{
@@ -848,13 +966,19 @@ sp_offset_top_point (SPOffset const * offset, Geom::Point *px)
}
SPCurve *curve = SP_SHAPE (offset)->getCurve();
+
if (curve == NULL)
{
- offset->coffset->set_shape();
+ // CPPIFY
+ //offset->set_shape();
+ const_cast<SPOffset*>(offset)->set_shape();
+
curve = SP_SHAPE (offset)->getCurve();
+
if (curve == NULL)
return;
}
+
if (curve->is_empty())
{
curve->unref();
@@ -897,8 +1021,9 @@ static void sp_offset_start_listening(SPOffset *offset,SPObject* to)
static void sp_offset_quit_listening(SPOffset *offset)
{
- if ( offset->sourceObject == NULL )
+ if ( offset->sourceObject == NULL ) {
return;
+ }
offset->_modified_connection.disconnect();
offset->_delete_connection.disconnect();
@@ -912,9 +1037,14 @@ static void
sp_offset_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPOffset *offset)
{
sp_offset_quit_listening(offset);
+
if (offset->sourceRef) {
SPItem *refobj = offset->sourceRef->getObject();
- if (refobj) sp_offset_start_listening(offset,refobj);
+
+ if (refobj) {
+ sp_offset_start_listening(offset,refobj);
+ }
+
offset->sourceDirty=true;
offset->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
@@ -926,6 +1056,7 @@ static void sp_offset_move_compensate(Geom::Affine const *mp, SPItem */*original
guint mode = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_PARALLEL);
Geom::Affine m(*mp);
+
if (!(m.isTranslation()) || mode == SP_CLONE_COMPENSATION_NONE) {
self->sourceDirty=true;
self->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
@@ -966,7 +1097,11 @@ sp_offset_delete_self(SPObject */*deleted*/, SPOffset *offset)
if (mode == SP_CLONE_ORPHANS_UNLINK) {
// leave it be. just forget about the source
sp_offset_quit_listening(offset);
- if ( offset->sourceHref ) g_free(offset->sourceHref);
+
+ if ( offset->sourceHref ) {
+ g_free(offset->sourceHref);
+ }
+
offset->sourceHref = NULL;
offset->sourceRef->detach();
} else if (mode == SP_CLONE_ORPHANS_DELETE) {
@@ -979,6 +1114,7 @@ sp_offset_source_modified (SPObject */*iSource*/, guint flags, SPItem *item)
{
SPOffset *offset = SP_OFFSET(item);
offset->sourceDirty=true;
+
if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG)) {
offset->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
@@ -987,35 +1123,54 @@ sp_offset_source_modified (SPObject */*iSource*/, guint flags, SPItem *item)
static void
refresh_offset_source(SPOffset* offset)
{
- if ( offset == NULL ) return;
+ if ( offset == NULL ) {
+ return;
+ }
+
offset->sourceDirty=false;
// le mauvais cas: pas d'attribut d => il faut verifier que c'est une SPShape puis prendre le contour
// The bad case: no d attribute. Must check that it's an SPShape and then take the outline.
SPObject *refobj=offset->sourceObject;
- if ( refobj == NULL ) return;
+
+ if ( refobj == NULL ) {
+ return;
+ }
+
SPItem *item = SP_ITEM (refobj);
SPCurve *curve=NULL;
- if (!SP_IS_SHAPE (item) && !SP_IS_TEXT (item)) return;
+
+ if (!SP_IS_SHAPE (item) && !SP_IS_TEXT (item)) {
+ return;
+ }
+
if (SP_IS_SHAPE (item)) {
curve = SP_SHAPE (item)->getCurve ();
- if (curve == NULL)
+
+ if (curve == NULL) {
return;
+ }
}
+
if (SP_IS_TEXT (item)) {
curve = SP_TEXT (item)->getNormalizedBpath ();
- if (curve == NULL)
- return;
+
+ if (curve == NULL) {
+ return;
+ }
}
+
Path *orig = new Path;
orig->LoadPathVector(curve->get_pathvector());
curve->unref();
if (!item->transform.isIdentity()) {
gchar const *t_attr = item->getRepr()->attribute("transform");
+
if (t_attr) {
Geom::Affine t;
+
if (sp_svg_transform_read(t_attr, &t)) {
orig->Transform(t);
}
@@ -1034,6 +1189,7 @@ refresh_offset_source(SPOffset* offset)
css = sp_repr_css_attr (offset->sourceRepr , "style");
val = sp_repr_css_property (css, "fill-rule", NULL);
+
if (val && strcmp (val, "nonzero") == 0)
{
theRes->ConvertToShape (theShape, fill_nonZero);
@@ -1072,9 +1228,12 @@ sp_offset_get_source (SPOffset *offset)
{
if (offset && offset->sourceRef) {
SPItem *refobj = offset->sourceRef->getObject();
- if (SP_IS_ITEM (refobj))
+
+ if (SP_IS_ITEM (refobj)) {
return (SPItem *) refobj;
+ }
}
+
return NULL;
}