Ejemplo n.º 1
0
bool SPLPEItem::hasPathEffectRecursive() const
{
    if (parent && SP_IS_LPE_ITEM(parent)) {
        return hasPathEffect() || SP_LPE_ITEM(parent)->hasPathEffectRecursive();
    }
    else {
        return hasPathEffect();
    }
}
Ejemplo n.º 2
0
Geom::Affine SPGenericEllipse::set_transform(Geom::Affine const &xform)
{
    // Allow live effects
    if (hasPathEffect() && pathEffectsEnabled()) {
        return xform;
    }

    /* Calculate ellipse start in parent coords. */
    Geom::Point pos(Geom::Point(this->cx.computed, this->cy.computed) * xform);

    /* This function takes care of translation and scaling, we return whatever parts we can't
       handle. */
    Geom::Affine ret(Geom::Affine(xform).withoutTranslation());
    gdouble const sw = hypot(ret[0], ret[1]);
    gdouble const sh = hypot(ret[2], ret[3]);

    if (sw > 1e-9) {
        ret[0] /= sw;
        ret[1] /= sw;
    } else {
        ret[0] = 1.0;
        ret[1] = 0.0;
    }

    if (sh > 1e-9) {
        ret[2] /= sh;
        ret[3] /= sh;
    } else {
        ret[2] = 0.0;
        ret[3] = 1.0;
    }

    if (this->rx._set) {
        this->rx = this->rx.computed * sw;
    }

    if (this->ry._set) {
        this->ry = this->ry.computed * sh;
    }

    /* Find start in item coords */
    pos = pos * ret.inverse();
    this->cx = pos[Geom::X];
    this->cy = pos[Geom::Y];

    this->set_shape();

    // Adjust stroke width
    this->adjust_stroke(sqrt(fabs(sw * sh)));

    // Adjust pattern fill
    this->adjust_pattern(xform * ret.inverse());

    // Adjust gradient fill
    this->adjust_gradient(xform * ret.inverse());

    this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);

    return ret;
}
Ejemplo n.º 3
0
Geom::Affine SPStar::set_transform(Geom::Affine const &xform)
{
    bool opt_trans = (randomized == 0);
    // Only set transform with proportional scaling
    if (!xform.withoutTranslation().isUniformScale()) {
        return xform;
    }

    // Allow live effects
    if (hasPathEffect() && pathEffectsEnabled()) {
        return xform;
    }

    /* Calculate star start in parent coords. */
    Geom::Point pos( this->center * xform );

    /* This function takes care of translation and scaling, we return whatever parts we can't
       handle. */
    Geom::Affine ret(opt_trans ? xform.withoutTranslation() : xform);
    gdouble const s = hypot(ret[0], ret[1]);
    if (s > 1e-9) {
        ret[0] /= s;
        ret[1] /= s;
        ret[2] /= s;
        ret[3] /= s;
    } else {
        ret[0] = 1.0;
        ret[1] = 0.0;
        ret[2] = 0.0;
        ret[3] = 1.0;
    }

    this->r[0] *= s;
    this->r[1] *= s;

    /* Find start in item coords */
    pos = pos * ret.inverse();
    this->center = pos;

    this->set_shape();

    // Adjust stroke width
    this->adjust_stroke(s);

    // Adjust pattern fill
    this->adjust_pattern(xform * ret.inverse());

    // Adjust gradient fill
    this->adjust_gradient(xform * ret.inverse());

    this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);

    return ret;
}
Ejemplo n.º 4
0
Inkscape::XML::Node* SPLPEItem::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
    if (flags & SP_OBJECT_WRITE_EXT) {
        if ( hasPathEffect() ) {
            std::string href = patheffectlist_write_svg(*this->path_effect_list);
            repr->setAttribute("inkscape:path-effect", href.c_str());
        } else {
            repr->setAttribute("inkscape:path-effect", NULL);
        }
    }

    SPItem::write(xml_doc, repr, flags);

    return repr;
}
Ejemplo n.º 5
0
/**
 * Return duplicate of curve *before* LPE (if any exists) or NULL if there is no curve
 */
SPCurve * SPShape::getCurveBeforeLPE() const
{
    if (hasPathEffect()) {
        if (_curve_before_lpe) {
            return this->_curve_before_lpe->copy();
        }
    } else {
        if (_curve) {
            return _curve->copy();
        }
    }

    return NULL;
}
Ejemplo n.º 6
0
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();
}
Ejemplo n.º 7
0
// 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;
}
Ejemplo n.º 8
0
Inkscape::XML::Node *SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
{
    // std::cout << "\nSPGenericEllipse::write: Entrance ("
    //           << (repr == NULL ? " NULL" : g_quark_to_string(repr->code()))
    //           << ")" << std::endl;

    GenericEllipseType new_type = SP_GENERIC_ELLIPSE_UNDEFINED;
    if (this->_isSlice() || hasPathEffect() ) {
        new_type = SP_GENERIC_ELLIPSE_ARC;
    } else if ( rx.computed == ry.computed ) {
        new_type = SP_GENERIC_ELLIPSE_CIRCLE;
    } else {
        new_type = SP_GENERIC_ELLIPSE_ELLIPSE;
    }
    // std::cout << "  new_type: " << new_type << std::endl;

    if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {

        switch ( new_type ) {

            case SP_GENERIC_ELLIPSE_ARC:
                repr = xml_doc->createElement("svg:path");
                break;
            case SP_GENERIC_ELLIPSE_CIRCLE:
                repr = xml_doc->createElement("svg:circle");
                break;
            case SP_GENERIC_ELLIPSE_ELLIPSE:
                repr = xml_doc->createElement("svg:ellipse");
                break;
            case SP_GENERIC_ELLIPSE_UNDEFINED:
            default:
                std::cerr << "SPGenericEllipse::write(): unknown type." << std::endl;
        }
    }

    if( type != new_type ) {
        switch( new_type ) {
            case SP_GENERIC_ELLIPSE_ARC:
                repr->setCodeUnsafe(g_quark_from_string("svg:path"));
                break;
            case SP_GENERIC_ELLIPSE_CIRCLE:
                repr->setCodeUnsafe(g_quark_from_string("svg:circle"));
                break;
            case SP_GENERIC_ELLIPSE_ELLIPSE:
                repr->setCodeUnsafe(g_quark_from_string("svg:ellipse"));
                break;
            default:
                std::cerr << "SPGenericEllipse::write(): unknown type." << std::endl;
        }
        type = new_type;

        // FIXME: The XML dialog won't update the element name. We need
        // a notifyElementNameChanged callback added to the XML observers
        // to trigger a refresh.
    }

    // std::cout << "  type: " << g_quark_to_string( repr->code() ) << std::endl;
    // std::cout << "  cx: " << cx.computed
    //           << "  cy: " << cy.computed
    //           << "  rx: " << rx.computed
    //           << "  ry: " << ry.computed << std::endl;

    switch ( type ) {
        case SP_GENERIC_ELLIPSE_UNDEFINED:
        case SP_GENERIC_ELLIPSE_ARC:

            repr->setAttribute("cx", NULL );
            repr->setAttribute("cy", NULL );
            repr->setAttribute("rx", NULL );
            repr->setAttribute("ry", NULL );
            repr->setAttribute("r", NULL );

            if (flags & SP_OBJECT_WRITE_EXT) {

                repr->setAttribute("sodipodi:type", "arc");
                sp_repr_set_svg_double(repr, "sodipodi:cx", this->cx.computed);
                sp_repr_set_svg_double(repr, "sodipodi:cy", this->cy.computed);
                sp_repr_set_svg_double(repr, "sodipodi:rx", this->rx.computed);
                sp_repr_set_svg_double(repr, "sodipodi:ry", this->ry.computed);

                // write start and end only if they are non-trivial; otherwise remove
                if (this->_isSlice()) {
                    sp_repr_set_svg_double(repr, "sodipodi:start", this->start);
                    sp_repr_set_svg_double(repr, "sodipodi:end", this->end);

                    repr->setAttribute("sodipodi:open", (!this->_closed) ? "true" : NULL);
                } else {
                    repr->setAttribute("sodipodi:end", NULL);
                    repr->setAttribute("sodipodi:start", NULL);
                    repr->setAttribute("sodipodi:open", NULL);
                }
            }

            // write d=
            this->set_elliptical_path_attribute(repr);
            break;

        case SP_GENERIC_ELLIPSE_CIRCLE:
            sp_repr_set_svg_double(repr, "cx", this->cx.computed);
            sp_repr_set_svg_double(repr, "cy", this->cy.computed);
            sp_repr_set_svg_double(repr, "r",  this->rx.computed);
            repr->setAttribute("rx", NULL );
            repr->setAttribute("ry", NULL );
            repr->setAttribute("sodipodi:cx", NULL );
            repr->setAttribute("sodipodi:cy", NULL );
            repr->setAttribute("sodipodi:rx", NULL );
            repr->setAttribute("sodipodi:ry", NULL );
            repr->setAttribute("sodipodi:end", NULL );
            repr->setAttribute("sodipodi:start", NULL );
            repr->setAttribute("sodipodi:open", NULL );
            repr->setAttribute("sodipodi:type", NULL );
            repr->setAttribute("d", NULL );
            break;

        case SP_GENERIC_ELLIPSE_ELLIPSE:
            sp_repr_set_svg_double(repr, "cx", this->cx.computed);
            sp_repr_set_svg_double(repr, "cy", this->cy.computed);
            sp_repr_set_svg_double(repr, "rx", this->rx.computed);
            sp_repr_set_svg_double(repr, "ry", this->ry.computed);
            repr->setAttribute("r", NULL );
            repr->setAttribute("sodipodi:cx", NULL );
            repr->setAttribute("sodipodi:cy", NULL );
            repr->setAttribute("sodipodi:rx", NULL );
            repr->setAttribute("sodipodi:ry", NULL );
            repr->setAttribute("sodipodi:end", NULL );
            repr->setAttribute("sodipodi:start", NULL );
            repr->setAttribute("sodipodi:open", NULL );
            repr->setAttribute("sodipodi:type", NULL );
            repr->setAttribute("d", NULL );
            break;

        default:
            std::cerr << "SPGenericEllipse::write: unknown type." << std::endl;
    }

    this->set_shape(); // evaluate SPCurve

    SPShape::write(xml_doc, repr, flags);

    // std::cout << "SPGenericEllipse::write: Exit: " << g_quark_to_string(repr->code()) << "\n" << std::endl;
    return repr;
}
Ejemplo n.º 9
0
void Box3DSide::set_shape() {
    if (!this->document->getRoot()) {
        // avoid a warning caused by sp_document_height() (which is called from sp_item_i2d_affine() below)
        // when reading a file containing 3D boxes
        return;
    }

    SPObject *parent = this->parent;

    if (!SP_IS_BOX3D(parent)) {
        g_warning("Parent of 3D box side is not a 3D box.\n");
        return;
    }

    SPBox3D *box = SP_BOX3D(parent);

    Persp3D *persp = box3d_side_perspective(this);

    if (!persp) {
        return;
    }

    // TODO: Draw the correct quadrangle here
    //       To do this, determine the perspective of the box, the orientation of the side (e.g., XY-FRONT)
    //       compute the coordinates of the corners in P^3, project them onto the canvas, and draw the
    //       resulting path.

    unsigned int corners[4];
    box3d_side_compute_corner_ids(this, corners);

    SPCurve *c = new SPCurve();

    if (!box3d_get_corner_screen(box, corners[0]).isFinite() ||
        !box3d_get_corner_screen(box, corners[1]).isFinite() ||
        !box3d_get_corner_screen(box, corners[2]).isFinite() ||
        !box3d_get_corner_screen(box, corners[3]).isFinite() )
    {
        g_warning ("Trying to draw a 3D box side with invalid coordinates.\n");
        return;
    }

    c->moveto(box3d_get_corner_screen(box, corners[0]));
    c->lineto(box3d_get_corner_screen(box, corners[1]));
    c->lineto(box3d_get_corner_screen(box, corners[2]));
    c->lineto(box3d_get_corner_screen(box, corners[3]));
    c->closepath();

    /* Reset the this'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);

    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();
}