From 748ffce08bb6250c87adabb64f45bff02509e9e7 Mon Sep 17 00:00:00 2001 From: Markus Engel Date: Fri, 5 Apr 2013 00:27:58 +0200 Subject: Combined some classes. (bzr r11608.1.75) --- src/sp-offset.cpp | 531 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 345 insertions(+), 186 deletions(-) (limited to 'src/sp-offset.cpp') 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(this->originalPath)->LoadPathVector(pv); - Geom::PathVector pv = sp_svg_read_pathv(offset->original); - offset->originalPath = new Path; - reinterpret_cast(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(_("Linked offset, %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(_("Dynamic offset, %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;iSurface(); 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;jnbPt;j++) theShape->AddPoint(onePart->pts[j].x); for (int j=0;jnbAr;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;jnbAr;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;iConvertWithBackData(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;iCopy(parts[0]); - for (int i=0;iReset(); } @@ -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 &p, Inkscape::SnapPreferences const *snapprefs) { +void SPOffset::snappoints(std::vector &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(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; } -- cgit v1.2.3