void SPStar::set_shape() { // perhaps we should convert all our shapes into LPEs without source path // and with knotholders for parameters, then this situation will be handled automatically // by disabling the entire stack (including the shape LPE) if (hasBrokenPathEffect()) { g_warning ("The star shape has unknown LPE on it! Convert to path to make it editable preserving the appearance; editing it as star will remove the bad LPE"); if (this->getRepr()->attribute("d")) { // unconditionally read the curve from d, if any, to preserve appearance Geom::PathVector pv = sp_svg_read_pathv(this->getRepr()->attribute("d")); SPCurve *cold = new SPCurve(pv); this->setCurveInsync( cold, TRUE); this->setCurveBeforeLPE(cold); cold->unref(); } return; } SPCurve *c = new SPCurve (); bool not_rounded = (fabs (this->rounded) < 1e-4); // note that we pass randomized=true to sp_star_get_xy, because the curve must be randomized; // other places that call that function (e.g. the knotholder) need the exact point // draw 1st segment c->moveto(sp_star_get_xy (this, SP_STAR_POINT_KNOT1, 0, true)); if (this->flatsided == false) { if (not_rounded) { c->lineto(sp_star_get_xy (this, SP_STAR_POINT_KNOT2, 0, true)); } else { c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, 0, NEXT), sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT2, 0, PREV), sp_star_get_xy (this, SP_STAR_POINT_KNOT2, 0, true)); } } // draw all middle segments for (gint i = 1; i < sides; i++) { if (not_rounded) { c->lineto(sp_star_get_xy (this, SP_STAR_POINT_KNOT1, i, true)); } else { if (this->flatsided == false) { c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT2, i - 1, NEXT), sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, i, PREV), sp_star_get_xy (this, SP_STAR_POINT_KNOT1, i, true)); } else { c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, i - 1, NEXT), sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, i, PREV), sp_star_get_xy (this, SP_STAR_POINT_KNOT1, i, true)); } } if (this->flatsided == false) { if (not_rounded) { c->lineto(sp_star_get_xy (this, SP_STAR_POINT_KNOT2, i, true)); } else { c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, i, NEXT), sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT2, i, PREV), sp_star_get_xy (this, SP_STAR_POINT_KNOT2, i, true)); } } } // draw last segment if (!not_rounded) { if (this->flatsided == false) { c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT2, sides - 1, NEXT), sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, 0, PREV), sp_star_get_xy (this, SP_STAR_POINT_KNOT1, 0, true)); } else { c->curveto(sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, sides - 1, NEXT), sp_star_get_curvepoint (this, SP_STAR_POINT_KNOT1, 0, PREV), sp_star_get_xy (this, SP_STAR_POINT_KNOT1, 0, true)); } } c->closepath(); /* Reset the shape'scurve to the "original_curve" * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/ this->setCurveInsync( c, TRUE); this->setCurveBeforeLPE( c ); if (hasPathEffect() && pathEffectsEnabled()) { SPCurve *c_lpe = c->copy(); bool success = this->performPathEffect(c_lpe); if (success) { this->setCurveInsync( c_lpe, TRUE); } c_lpe->unref(); } c->unref(); }
// Create path for rendering shape on screen void SPGenericEllipse::set_shape() { // std::cout << "SPGenericEllipse::set_shape: Entrance" << std::endl; if (hasBrokenPathEffect()) { g_warning("The ellipse shape has unknown LPE on it! Convert to path to make it editable preserving the appearance; editing it as ellipse will remove the bad LPE"); if (this->getRepr()->attribute("d")) { // unconditionally read the curve from d, if any, to preserve appearance Geom::PathVector pv = sp_svg_read_pathv(this->getRepr()->attribute("d")); SPCurve *cold = new SPCurve(pv); this->setCurveInsync(cold, TRUE); cold->unref(); } return; } if (Geom::are_near(this->rx.computed, 0) || Geom::are_near(this->ry.computed, 0)) { return; } this->normalize(); SPCurve *curve = NULL; // For simplicity, we use a circle with center (0, 0) and radius 1 for our calculations. Geom::Circle circle(0, 0, 1); if (!this->_isSlice()) { start = 0.0; end = 2.0*M_PI; } double incr = end - start; // arc angle if (incr < 0.0) incr += 2.0*M_PI; int numsegs = 1 + int(incr*2.0/M_PI); // number of arc segments if (numsegs > 4) numsegs = 4; incr = incr/numsegs; // limit arc angle to less than 90 degrees Geom::Path path(Geom::Point::polar(start)); Geom::EllipticalArc* arc; for (int seg = 0; seg < numsegs; seg++) { arc = circle.arc(Geom::Point::polar(start + seg*incr), Geom::Point::polar(start + (seg + 0.5)*incr), Geom::Point::polar(start + (seg + 1.0)*incr)); path.append(*arc); delete arc; } Geom::PathBuilder pb; pb.append(path); if (this->_isSlice() && this->_closed) { pb.lineTo(Geom::Point(0, 0)); } if (this->_closed) { pb.closePath(); } else { pb.flush(); } curve = new SPCurve(pb.peek()); // gchar *str = sp_svg_write_path(curve->get_pathvector()); // std::cout << " path: " << str << std::endl; // g_free(str); // Stretching / moving the calculated shape to fit the actual dimensions. Geom::Affine aff = Geom::Scale(rx.computed, ry.computed) * Geom::Translate(cx.computed, cy.computed); curve->transform(aff); /* Reset the shape's curve to the "original_curve" * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/ this->setCurveInsync(curve, TRUE); this->setCurveBeforeLPE(curve); if (hasPathEffect() && pathEffectsEnabled()) { SPCurve *c_lpe = curve->copy(); bool success = this->performPathEffect(c_lpe); if (success) { this->setCurveInsync(c_lpe, TRUE); } c_lpe->unref(); } curve->unref(); // std::cout << "SPGenericEllipse::set_shape: Exit" << std::endl; }