Пример #1
0
void
SPLPEItem::apply_to_clippath(SPItem *item)
{
    SPClipPath *clipPath = item->clip_ref->getObject();
    if(clipPath) {
        SPObject * clip_data = clipPath->firstChild();
        SPCurve * clip_curve = NULL;

        if (SP_IS_PATH(clip_data)) {
            clip_curve = SP_PATH(clip_data)->get_original_curve();
        } else if(SP_IS_SHAPE(clip_data)) {
            clip_curve = SP_SHAPE(clip_data)->getCurve();
        } else if(SP_IS_GROUP(clip_data)) {
            apply_to_clip_or_mask_group(SP_ITEM(clip_data), item);
            return;
        }
        if(clip_curve) {
            bool success = false;
            if(SP_IS_GROUP(this)){
                clip_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)));
                success = this->performPathEffect(clip_curve);
                clip_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)).inverse());
            } else {
                success = this->performPathEffect(clip_curve);
            }
            Inkscape::XML::Node *reprClip = clip_data->getRepr();
            if (success) {
                gchar *str = sp_svg_write_path(clip_curve->get_pathvector());
                reprClip->setAttribute("d", str);
                g_free(str);
            } else {
                // LPE was unsuccesfull. Read the old 'd'-attribute.
                if (gchar const * value = reprClip->attribute("d")) {
                    Geom::PathVector pv = sp_svg_read_pathv(value);
                    SPCurve *oldcurve = new SPCurve(pv);
                    if (oldcurve) {
                        SP_SHAPE(clip_data)->setCurve(oldcurve, TRUE);
                        oldcurve->unref();
                    }
                }
            }
            clip_curve->unref();
        }
    }
    if(SP_IS_GROUP(item)){
        GSList const *item_list = sp_item_group_item_list(SP_GROUP(item));
        for ( GSList const *iter = item_list; iter; iter = iter->next ) {
            SPObject *subitem = static_cast<SPObject *>(iter->data);
            apply_to_clippath(SP_ITEM(subitem));
        }
    }
}
Пример #2
0
static Inkscape::XML::Node *sp_polygon_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
{
    SPShape *shape = SP_SHAPE(object);
    // Tolerable workaround: we need to update the object's curve before we set points=
    // because it's out of sync when e.g. some extension attrs of the polygon or star are changed in XML editor
    sp_shape_set_shape(shape);

    if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
        repr = xml_doc->createElement("svg:polygon");
    }

    /* We can safely write points here, because all subclasses require it too (Lauris) */
    /* While saving polygon element without points attribute _curve is NULL (see bug 1202753) */
    if (shape->curve != NULL) {
        gchar *str = sp_svg_write_polygon(shape->curve->get_pathvector());
        repr->setAttribute("points", str);
        g_free(str);
    }

    if (((SPObjectClass *) (parent_class))->write) {
        ((SPObjectClass *) (parent_class))->write(object, xml_doc, repr, flags);
    }

    return repr;
}
Пример #3
0
Inkscape::XML::Node* SPUse::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
    if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
        repr = xml_doc->createElement("svg:use");
    }

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

    sp_repr_set_svg_double(repr, "x", this->x.computed);
    sp_repr_set_svg_double(repr, "y", this->y.computed);
    repr->setAttribute("width", sp_svg_length_write_with_units(this->width).c_str());
    repr->setAttribute("height", sp_svg_length_write_with_units(this->height).c_str());

    if (this->ref->getURI()) {
        gchar *uri_string = this->ref->getURI()->toString();
        repr->setAttribute("xlink:href", uri_string);
        g_free(uri_string);
    }

    if (SP_IS_SHAPE(this->child)) {
        SP_SHAPE(this->child)->set_shape(); // evaluate SPCurve of child
    } else if (SP_IS_TEXT(this->child)) {
        SP_TEXT(this->child)->rebuildLayout(); // refresh Layout, LP Bug 1339305
    } else if (SP_IS_FLOWTEXT(this->child)) {
        if (SP_IS_FLOWREGION(SP_FLOWTEXT(this->child)->firstChild()))
            SP_FLOWREGION(SP_FLOWTEXT(this->child)->firstChild())->UpdateComputed();
        SP_FLOWTEXT(this->child)->rebuildLayout();
    }

    return repr;
}
Пример #4
0
void SPUsePath::refresh_source()
{
    sourceDirty = false;
    delete originalPath;
    originalPath = NULL;

    // le mauvais cas: pas d'attribut d => il faut verifier que c'est une SPShape puis prendre le contour
    // [tr: The bad case: no d attribute.  Must check that it's a SPShape and then take the outline.]
    SPObject *refobj = sourceObject;
    if ( refobj == NULL ) return;
    
    SPItem *item = SP_ITEM(refobj);
    SPCurve *curve = NULL;

    if (SP_IS_SHAPE(item))
    {
        curve = SP_SHAPE(item)->getCurve();
    }
    else if (SP_IS_TEXT(item))
    {
        curve = SP_TEXT(item)->getNormalizedBpath();
    }
    else
    {
        return;
    }
        
    if (curve == NULL)
        return;

    originalPath = new Path;
    originalPath->LoadPathVector(curve->get_pathvector(), item->transform, true);
    curve->unref();
}
Пример #5
0
void SPPolyLine::set(SPObject *object, unsigned int key, const gchar *value)
{
    SPPolyLine *polyline = SP_POLYLINE(object);

    switch (key) {
	case SP_ATTR_POINTS: {
            SPCurve * curve;
            const gchar * cptr;
            char * eptr;
            gboolean hascpt;

            if (!value) break;
            curve = new SPCurve ();
            hascpt = FALSE;

            cptr = value;
            eptr = NULL;

            while (TRUE) {
                gdouble x, y;

                while (*cptr != '\0' && (*cptr == ',' || *cptr == '\x20' || *cptr == '\x9' || *cptr == '\xD' || *cptr == '\xA')) {
                    cptr++;
                }
                if (!*cptr) break;

                x = g_ascii_strtod (cptr, &eptr);
                if (eptr == cptr) break;
                cptr = eptr;

                while (*cptr != '\0' && (*cptr == ',' || *cptr == '\x20' || *cptr == '\x9' || *cptr == '\xD' || *cptr == '\xA')) {
                    cptr++;
                }
                if (!*cptr) break;

                y = g_ascii_strtod (cptr, &eptr);
                if (eptr == cptr) break;
                cptr = eptr;
                if (hascpt) {
                    curve->lineto(x, y);
                } else {
                    curve->moveto(x, y);
                    hascpt = TRUE;
                }
            }
		
            (SP_SHAPE (polyline))->setCurve (curve, TRUE);
            curve->unref();
            break;
	}
	default:
            if (((SPObjectClass *) SPPolyLineClass::static_parent_class)->set) {
                ((SPObjectClass *) SPPolyLineClass::static_parent_class)->set (object, key, value);
            }
            break;
    }
}
Пример #6
0
static void
knot_moved_handler (SPKnot *knot, NRPointF *p, guint state, gpointer data)
{
	SPKnotHolder *knot_holder;
	SPItem *item;
	SPObject *object;
	NRMatrixF i2d;
	GSList *el;

	knot_holder = (SPKnotHolder *) data;
	item  = SP_ITEM (knot_holder->item);
	object = SP_OBJECT (item);

	for (el = knot_holder->entity; el; el = el->next) {
		SPKnotHolderEntity *e = (SPKnotHolderEntity *)el->data;
		if (e->knot == knot) {
			NRMatrixF d2i;
			NRPointF q;

			sp_item_i2d_affine(item, &i2d);
			nr_matrix_f_invert (&d2i, &i2d);
			q.x = NR_MATRIX_DF_TRANSFORM_X (&d2i, p->x, p->y);
			q.y = NR_MATRIX_DF_TRANSFORM_Y (&d2i, p->x, p->y);

			e->knot_set (item, &q, state);

			break;
		}
	}
	
	sp_shape_set_shape (SP_SHAPE (item));

	sp_item_i2d_affine(item, &i2d);

	for (el = knot_holder->entity; el; el = el->next) {
		SPKnotHolderEntity *e = (SPKnotHolderEntity *)el->data;
		NRPointF sp, dp;
		GObject *kob;
		
		kob = G_OBJECT (e->knot);

		e->knot_get (item, &sp);

		dp.x = NR_MATRIX_DF_TRANSFORM_X (&i2d, sp.x, sp.y);
		dp.y = NR_MATRIX_DF_TRANSFORM_Y (&i2d, sp.x, sp.y);

		g_signal_handler_block (kob, e->handler_id);
		sp_knot_set_position (e->knot, &dp, SP_KNOT_STATE_NORMAL);
		g_signal_handler_unblock (kob, e->handler_id);
	}
}
Пример #7
0
static bool try_get_intersect_point_with_item_recursive(Geom::PathVector& conn_pv, SPItem* item,
        const Geom::Affine& item_transform, double& intersect_pos) {

    double initial_pos = intersect_pos;
    // if this is a group...
    if (SP_IS_GROUP(item)) {
        SPGroup* group = SP_GROUP(item);

        // consider all first-order children
        double child_pos = 0.0;
        std::vector<SPItem*> g = sp_item_group_item_list(group);
        for (std::vector<SPItem*>::const_iterator i = g.begin();i!=g.end();i++) {
            SPItem* child_item = *i;
            try_get_intersect_point_with_item_recursive(conn_pv, child_item,
                    item_transform * child_item->transform, child_pos);
            if (intersect_pos < child_pos)
                intersect_pos = child_pos;
        }
        return intersect_pos != initial_pos;
    }

    // if this is not a shape, nothing to be done
    if (!SP_IS_SHAPE(item)) return false;

    // make sure it has an associated curve
    SPCurve* item_curve = SP_SHAPE(item)->getCurve();
    if (!item_curve) return false;

    // apply transformations (up to common ancestor)
    item_curve->transform(item_transform);

    const Geom::PathVector& curve_pv = item_curve->get_pathvector();
    Geom::CrossingSet cross = crossings(conn_pv, curve_pv);
    // iterate over all Crossings
    //TODO: check correctness of the following code: inner loop uses loop variable
    //      with a name identical to the loop variable of the outer loop. Then rename.
    for (Geom::CrossingSet::const_iterator i = cross.begin(); i != cross.end(); ++i) {
        const Geom::Crossings& cr = *i;

        for (Geom::Crossings::const_iterator i = cr.begin(); i != cr.end(); ++i) {
            const Geom::Crossing& cr_pt = *i;
            if ( intersect_pos < cr_pt.ta)
                intersect_pos = cr_pt.ta;
        }
    }

    item_curve->unref();

    return intersect_pos != initial_pos;
}
Пример #8
0
static bool try_get_intersect_point_with_item_recursive(Geom::PathVector& conn_pv, SPItem* item,
        const Geom::Matrix& item_transform, double& intersect_pos) {

    double initial_pos = intersect_pos;
    // if this is a group...
    if (SP_IS_GROUP(item)) {
        SPGroup* group = SP_GROUP(item);

        // consider all first-order children
        double child_pos = 0.0;
        for (GSList const* i = sp_item_group_item_list(group); i != NULL; i = i->next) {
            SPItem* child_item = SP_ITEM(i->data);
            try_get_intersect_point_with_item_recursive(conn_pv, child_item,
                    item_transform * child_item->transform, child_pos);
            if (intersect_pos < child_pos)
                intersect_pos = child_pos;
        }
        return intersect_pos != initial_pos;
    }

    // if this is not a shape, nothing to be done
    if (!SP_IS_SHAPE(item)) return false;

    // make sure it has an associated curve
    SPCurve* item_curve = sp_shape_get_curve(SP_SHAPE(item));
    if (!item_curve) return false;

    // apply transformations (up to common ancestor)
    item_curve->transform(item_transform);

    const Geom::PathVector& curve_pv = item_curve->get_pathvector();
    Geom::CrossingSet cross = crossings(conn_pv, curve_pv);
    // iterate over all Crossings
    for (Geom::CrossingSet::const_iterator i = cross.begin(); i != cross.end(); i++) {
        const Geom::Crossings& cr = *i;

        for (Geom::Crossings::const_iterator i = cr.begin(); i != cr.end(); i++) {
            const Geom::Crossing& cr_pt = *i;
            if ( intersect_pos < cr_pt.ta)
                intersect_pos = cr_pt.ta;
        }
    }

    item_curve->unref();

    return intersect_pos != initial_pos;
}
Пример #9
0
static void
spdc_attach_selection (SPDrawContext *dc, SPSelection *sel)
{
	SPItem *item;

	/* We reset white and forget white/start/end anchors */
	spdc_reset_white (dc);
	dc->sa = NULL;
	dc->ea = NULL;

	item = sp_selection_item (dc->selection);

	if (item && SP_IS_PATH (item)) {
		SPCurve *norm;
		NRMatrixD i2dt;
		GSList *l;
		/* Create new white data */
		/* Item */
		dc->white_item = item;
		/* Curve list */
		/* We keep it in desktop coordinates to eliminate calculation errors */
		norm = sp_shape_get_curve (SP_SHAPE (item));
		sp_item_i2d_affine_d (dc->white_item, &i2dt);
		norm = sp_curve_transform (norm, NR_MATRIX_D_TO_DOUBLE (&i2dt));
		g_return_if_fail (norm != NULL);
		dc->white_curves = sp_curve_split (norm);
		sp_curve_unref (norm);
		/* Anchor list */
		for (l = dc->white_curves; l != NULL; l = l->next) {
			SPCurve *c;
			c = (SPCurve*)l->data;
			g_return_if_fail (c->end > 1);
			if (c->bpath->code == ART_MOVETO_OPEN) {
				ArtBpath *s, *e;
				SPDrawAnchor *a;
				s = sp_curve_first_bpath (c);
				e = sp_curve_last_bpath (c);
				a = sp_draw_anchor_new (dc, c, TRUE, s->x3, s->y3);
				dc->white_anchors = g_slist_prepend (dc->white_anchors, a);
				a = sp_draw_anchor_new (dc, c, FALSE, e->x3, e->y3);
				dc->white_anchors = g_slist_prepend (dc->white_anchors, a);
			}
		}
		/* fixme: recalculate active anchor? */
	}
}
Пример #10
0
static void         GetDest(SPObject* child,Shape **computed)
{
	if ( child == NULL ) return;

	SPCurve *curve=NULL;
	Geom::Matrix tr_mat;

	SPObject* u_child=child;
	if ( SP_IS_USE(u_child) ) {
		u_child=SP_USE(u_child)->child;
		tr_mat = SP_ITEM(u_child)->getRelativeTransform(SP_OBJECT_PARENT(child));
	} else {
		tr_mat = SP_ITEM(u_child)->transform;
	}
	if ( SP_IS_SHAPE (u_child) ) {
		curve = sp_shape_get_curve (SP_SHAPE (u_child));
	} else if ( SP_IS_TEXT (u_child) ) {
	curve = SP_TEXT (u_child)->getNormalizedBpath ();
	}

	if ( curve ) {
		Path*   temp=new Path;
        temp->LoadPathVector(curve->get_pathvector(), tr_mat, true);
		Shape*  n_shp=new Shape;
		temp->Convert(0.25);
		temp->Fill(n_shp,0);
		Shape*  uncross=new Shape;
		SPStyle* style=SP_OBJECT_STYLE(u_child);
		if ( style && style->fill_rule.computed == SP_WIND_RULE_EVENODD ) {
			uncross->ConvertToShape(n_shp,fill_oddEven);
		} else {
			uncross->ConvertToShape(n_shp,fill_nonZero);
		}
		UnionShape(computed, uncross);
		delete uncross;
		delete n_shp;
		delete temp;
		curve->unref();
	} else {
//		printf("no curve\n");
	}
}
Пример #11
0
static void
sp_star_finish (SPStarContext * sc)
{
	if (sc->item != NULL) {
		SPDesktop *desktop;
		SPObject  *object;

		desktop = SP_EVENT_CONTEXT (sc)->desktop;
		object  = SP_OBJECT(sc->item);
		
                sp_shape_set_shape (SP_SHAPE (sc->item));

		sp_object_invoke_write (object, NULL, SP_OBJECT_WRITE_EXT);

		sp_selection_set_item (SP_DT_SELECTION (desktop), sc->item);
		sp_document_done (SP_DT_DOCUMENT (desktop));

		sc->item = NULL;
	}
}
Пример #12
0
static void
sp_spiral_finish(SPSpiralContext *sc)
{
    sc->_message_context->clear();

    if (sc->item != NULL) {
        SPDesktop *desktop = SP_EVENT_CONTEXT(sc)->desktop;
        SPSpiral  *spiral = SP_SPIRAL(sc->item);

        sp_shape_set_shape(SP_SHAPE(spiral));
        SP_OBJECT(spiral)->updateRepr(SP_OBJECT_WRITE_EXT);

        sp_canvas_end_forced_full_redraws(desktop->canvas);

        sp_desktop_selection(desktop)->set(sc->item);
        sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SPIRAL, 
                         _("Create spiral"));

        sc->item = NULL;
    }
}
Пример #13
0
void
OriginalPathParam::linked_modified_callback(SPObject *linked_obj, guint /*flags*/)
{
    SPCurve *curve = NULL;
    if (SP_IS_SHAPE(linked_obj)) {
        curve = SP_SHAPE(linked_obj)->getCurveBeforeLPE();
    }
    if (SP_IS_TEXT(linked_obj)) {
        curve = SP_TEXT(linked_obj)->getNormalizedBpath();
    }

    if (curve == NULL) {
        // curve invalid, set empty pathvector
        _pathvector = Geom::PathVector();
    } else {
        _pathvector = curve->get_pathvector();
        curve->unref();
    }

    must_recalculate_pwd2 = true;
    emit_changed();
    SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
Пример #14
0
static void
sp_spiral_set (SPObject *object, unsigned int key, const gchar *value)
{
	SPSpiral *spiral;
	SPShape  *shape;
	gulong unit;

	spiral = SP_SPIRAL (object);
	shape  = SP_SHAPE (object);

	/* fixme: we should really collect updates */
	switch (key) {
	case SP_ATTR_SODIPODI_CX:
		if (!sp_svg_length_read_lff (value, &unit, NULL, &spiral->cx) ||
		    (unit == SP_SVG_UNIT_EM) ||
		    (unit == SP_SVG_UNIT_EX) ||
		    (unit == SP_SVG_UNIT_PERCENT)) {
			spiral->cx = 0.0;
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	case SP_ATTR_SODIPODI_CY:
		if (!sp_svg_length_read_lff (value, &unit, NULL, &spiral->cy) ||
		    (unit == SP_SVG_UNIT_EM) ||
		    (unit == SP_SVG_UNIT_EX) ||
		    (unit == SP_SVG_UNIT_PERCENT)) {
			spiral->cy = 0.0;
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	case SP_ATTR_SODIPODI_EXPANSION:
		if (value) {
			spiral->exp = atof (value);
			spiral->exp = CLAMP (spiral->exp, 0.0, 1000.0);
		} else {
			spiral->exp = 1.0;
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	case SP_ATTR_SODIPODI_REVOLUTION:
		if (value) {
			spiral->revo = atof (value);
			spiral->revo = CLAMP (spiral->revo, 0.05, 20.0);
		} else {
			spiral->revo = 3.0;
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	case SP_ATTR_SODIPODI_RADIUS:
		if (!sp_svg_length_read_lff (value, &unit, NULL, &spiral->rad) ||
		    (unit != SP_SVG_UNIT_EM) ||
		    (unit != SP_SVG_UNIT_EX) ||
		    (unit != SP_SVG_UNIT_PERCENT)) {
			spiral->rad = MAX (spiral->rad, 0.001);
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	case SP_ATTR_SODIPODI_ARGUMENT:
		if (value) {
			spiral->arg = atof (value);
		} else {
			spiral->arg = 0.0;
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	case SP_ATTR_SODIPODI_T0:
		if (value) {
			spiral->t0 = atof (value);
			spiral->t0 = CLAMP (spiral->t0, -1.0, 0.999);
		} else {
			spiral->t0 = 0.0;
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	default:
		if (((SPObjectClass *) parent_class)->set)
			((SPObjectClass *) parent_class)->set (object, key, value);
		break;
	}
}
Пример #15
0
Inkscape::XML::Node *
sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/)
{
    if (!item)
        return NULL;

    Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(item)->document();

    if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
        // Special treatment for text: convert each glyph to separate path, then group the paths
        Inkscape::XML::Node *g_repr = xml_doc->createElement("svg:g");
        g_repr->setAttribute("transform", SP_OBJECT_REPR(item)->attribute("transform"));
        /* Mask */
        gchar *mask_str = (gchar *) SP_OBJECT_REPR(item)->attribute("mask");
        if ( mask_str )
            g_repr->setAttribute("mask", mask_str);
        /* Clip path */
        gchar *clip_path_str = (gchar *) SP_OBJECT_REPR(item)->attribute("clip-path");
        if ( clip_path_str )
            g_repr->setAttribute("clip-path", clip_path_str);
        /* Rotation center */
        g_repr->setAttribute("inkscape:transform-center-x", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-x"), false);
        g_repr->setAttribute("inkscape:transform-center-y", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-y"), false);
        /* Whole text's style */
        gchar *style_str = sp_style_write_difference(SP_OBJECT_STYLE(item),
                                             SP_OBJECT_STYLE(SP_OBJECT_PARENT(item)));
        g_repr->setAttribute("style", style_str);
        g_free(style_str);
        Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin(); 
        do {
            Inkscape::Text::Layout::iterator iter_next = iter;
            iter_next.nextGlyph(); // iter_next is one glyph ahead from iter
            if (iter == iter_next)
                break;

            /* This glyph's style */
            SPObject const *pos_obj = 0;
            void *rawptr = 0;
            te_get_layout(item)->getSourceOfCharacter(iter, &rawptr);
            if (!rawptr || !SP_IS_OBJECT(rawptr)) // no source for glyph, abort
                break;
            pos_obj = SP_OBJECT(rawptr);
            while (SP_IS_STRING(pos_obj) && SP_OBJECT_PARENT(pos_obj)) {
               pos_obj = SP_OBJECT_PARENT(pos_obj);   // SPStrings don't have style
            }
            gchar *style_str = sp_style_write_difference(SP_OBJECT_STYLE(pos_obj),
                                                 SP_OBJECT_STYLE(SP_OBJECT_PARENT(pos_obj)));

            // get path from iter to iter_next:
            SPCurve *curve = te_get_layout(item)->convertToCurves(iter, iter_next);
            iter = iter_next; // shift to next glyph
            if (!curve) { // error converting this glyph
                g_free (style_str);
                continue;
            }
            if (curve->is_empty()) { // whitespace glyph?
                curve->unref();
                g_free (style_str);
                continue;
            }

            Inkscape::XML::Node *p_repr = xml_doc->createElement("svg:path");

            gchar *def_str = sp_svg_write_path(curve->get_pathvector());
            p_repr->setAttribute("d", def_str);
            g_free(def_str);
            curve->unref();

            p_repr->setAttribute("style", style_str);
            g_free(style_str);

            g_repr->appendChild(p_repr);
            Inkscape::GC::release(p_repr);

            if (iter == te_get_layout(item)->end())
                break;

        } while (true);

        return g_repr;
    }

    SPCurve *curve = NULL;
    if (SP_IS_SHAPE(item)) {
        curve = sp_shape_get_curve(SP_SHAPE(item));
    } 

    if (!curve)
        return NULL;

    // Prevent empty paths from being added to the document
    // otherwise we end up with zomby markup in the SVG file
    if(curve->is_empty())
    {
        curve->unref();
        return NULL;
    }

    Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
    /* Transformation */
    repr->setAttribute("transform", SP_OBJECT_REPR(item)->attribute("transform"));
    /* Style */
    gchar *style_str = sp_style_write_difference(SP_OBJECT_STYLE(item),
                                                 SP_OBJECT_STYLE(SP_OBJECT_PARENT(item)));
    repr->setAttribute("style", style_str);
    g_free(style_str);

    /* Mask */
    gchar *mask_str = (gchar *) SP_OBJECT_REPR(item)->attribute("mask");
    if ( mask_str )
        repr->setAttribute("mask", mask_str);

    /* Clip path */
    gchar *clip_path_str = (gchar *) SP_OBJECT_REPR(item)->attribute("clip-path");
    if ( clip_path_str )
        repr->setAttribute("clip-path", clip_path_str);

    /* Rotation center */
    repr->setAttribute("inkscape:transform-center-x", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-x"), false);
    repr->setAttribute("inkscape:transform-center-y", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-y"), false);

    /* Definition */
    gchar *def_str = sp_svg_write_path(curve->get_pathvector());
    repr->setAttribute("d", def_str);
    g_free(def_str);
    curve->unref();
    return repr;
}
Пример #16
0
/// @todo investigate why Geom::Point p is passed in but ignored.
void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/,
                                         SnapSourceType const source_type,
                                         bool const &first_point) const
{
    // Now, let's first collect all paths to snap to. If we have a whole bunch of points to snap,
    // e.g. when translating an item using the selector tool, then we will only do this for the
    // first point and store the collection for later use. This significantly improves the performance
    if (first_point) {
        _clear_paths();

        // Determine the type of bounding box we should snap to
        SPItem::BBoxType bbox_type = SPItem::GEOMETRIC_BBOX;

        bool p_is_a_node = source_type & SNAPSOURCE_NODE_CATEGORY;
        bool p_is_a_bbox = source_type & SNAPSOURCE_BBOX_CATEGORY;
        bool p_is_other = (source_type & SNAPSOURCE_OTHERS_CATEGORY) || (source_type & SNAPSOURCE_DATUMS_CATEGORY);

        if (_snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_BBOX_EDGE)) {
            Preferences *prefs = Preferences::get();
            int prefs_bbox = prefs->getBool("/tools/bounding_box", 0);
            bbox_type = !prefs_bbox ?
                SPItem::VISUAL_BBOX : SPItem::GEOMETRIC_BBOX;
        }

        // Consider the page border for snapping
        if (_snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PAGE_BORDER) && _snapmanager->snapprefs.isAnyCategorySnappable()) {
            Geom::PathVector *border_path = _getBorderPathv();
            if (border_path != NULL) {
                _paths_to_snap_to->push_back(SnapCandidatePath(border_path, SNAPTARGET_PAGE_BORDER, Geom::OptRect()));
            }
        }

        for (std::vector<SnapCandidateItem>::const_iterator i = _candidates->begin(); i != _candidates->end(); ++i) {

            /* Transform the requested snap point to this item's coordinates */
            Geom::Affine i2doc(Geom::identity());
            SPItem *root_item = NULL;
            /* We might have a clone at hand, so make sure we get the root item */
            if (SP_IS_USE((*i).item)) {
                i2doc = SP_USE((*i).item)->get_root_transform();
                root_item = SP_USE((*i).item)->root();
                g_return_if_fail(root_item);
            } else {
                i2doc = (*i).item->i2doc_affine();
                root_item = (*i).item;
            }

            //Build a list of all paths considered for snapping to

            //Add the item's path to snap to
            if (_snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PATH, SNAPTARGET_PATH_INTERSECTION, SNAPTARGET_TEXT_BASELINE)) {
                if (p_is_other || p_is_a_node || (!_snapmanager->snapprefs.getStrictSnapping() && p_is_a_bbox)) {
                    if (SP_IS_TEXT(root_item) || SP_IS_FLOWTEXT(root_item)) {
                        if (_snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_TEXT_BASELINE)) {
                            // Snap to the text baseline
                            Text::Layout const *layout = te_get_layout(static_cast<SPItem *>(root_item));
                            if (layout != NULL && layout->outputExists()) {
                                Geom::PathVector *pv = new Geom::PathVector();
                                pv->push_back(layout->baseline() * root_item->i2dt_affine() * (*i).additional_affine * _snapmanager->getDesktop()->doc2dt());
                                _paths_to_snap_to->push_back(SnapCandidatePath(pv, SNAPTARGET_TEXT_BASELINE, Geom::OptRect()));
                            }
                        }
                    } else {
                        // Snapping for example to a traced bitmap is very stressing for
                        // the CPU, so we'll only snap to paths having no more than 500 nodes
                        // This also leads to a lag of approx. 500 msec (in my lousy test set-up).
                        bool very_complex_path = false;
                        if (SP_IS_PATH(root_item)) {
                            very_complex_path = SP_PATH(root_item)->nodesInPath() > 500;
                        }

                        if (!very_complex_path && root_item && _snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PATH, SNAPTARGET_PATH_INTERSECTION)) {
                            SPCurve *curve = NULL;
                            if (SP_IS_SHAPE(root_item)) {
                               curve = SP_SHAPE(root_item)->getCurve();
                            }/* else if (SP_IS_TEXT(root_item) || SP_IS_FLOWTEXT(root_item)) {
                               curve = te_get_layout(root_item)->convertToCurves();
                            }*/
                            if (curve) {
                                // We will get our own copy of the pathvector, which must be freed at some point

                                // Geom::PathVector *pv = pathvector_for_curve(root_item, curve, true, true, Geom::identity(), (*i).additional_affine);

                                Geom::PathVector *pv = new Geom::PathVector(curve->get_pathvector());
                                (*pv) *= root_item->i2dt_affine() * (*i).additional_affine * _snapmanager->getDesktop()->doc2dt(); // (_edit_transform * _i2d_transform);

                                _paths_to_snap_to->push_back(SnapCandidatePath(pv, SNAPTARGET_PATH, Geom::OptRect())); // Perhaps for speed, get a reference to the Geom::pathvector, and store the transformation besides it.
                                curve->unref();
                            }
                        }
                    }
                }
            }

            //Add the item's bounding box to snap to
            if (_snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_BBOX_EDGE)) {
                if (p_is_other || p_is_a_bbox || (!_snapmanager->snapprefs.getStrictSnapping() && p_is_a_node)) {
                    // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox
                    // of the item AND the bbox of the clipping path at the same time
                    if (!(*i).clip_or_mask) {
                        Geom::OptRect rect = root_item->bounds(bbox_type, i2doc);
                        if (rect) {
                            Geom::PathVector *path = _getPathvFromRect(*rect);
                            rect = root_item->desktopBounds(bbox_type);
                            _paths_to_snap_to->push_back(SnapCandidatePath(path, SNAPTARGET_BBOX_EDGE, rect));
                        }
                    }
                }
            }
        }
    }
}
Пример #17
0
void sp_polygon_set(SPObject *object, unsigned int key, const gchar *value)
{
    SPPolygon *polygon = SP_POLYGON(object);

    switch (key) {
        case SP_ATTR_POINTS: {
            if (!value) {
                /* fixme: The points attribute is required.  We should handle its absence as per
                 * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing. */
                break;
            }
            SPCurve *curve = new SPCurve();
            gboolean hascpt = FALSE;

            gchar const *cptr = value;
            bool has_error = false;

            while (TRUE) {
                gdouble x;
                if (!polygon_get_value(&cptr, &x)) {
                    break;
                }

                gdouble y;
                if (!polygon_get_value(&cptr, &y)) {
                    /* fixme: It is an error for an odd number of points to be specified.  We
                     * should display the points up to now (as we currently do, though perhaps
                     * without the closepath: the spec isn't quite clear on whether to do a
                     * closepath or not, though I'd guess it's best not to do a closepath), but
                     * then flag the document as in error, as per
                     * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing.
                     *
                     * (Ref: http://www.w3.org/TR/SVG11/shapes.html#PolygonElement.) */
                    has_error = true;
                    break;
                }

                if (hascpt) {
                    curve->lineto(x, y);
                } else {
                    curve->moveto(x, y);
                    hascpt = TRUE;
                }
            }

            if (has_error || *cptr != '\0') {
                /* TODO: Flag the document as in error, as per
                 * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing. */
            } else if (hascpt) {
                /* We might have done a moveto but no lineto.  I'm not sure how we're supposed to represent
                 * a single-point polygon in SPCurve. TODO: add a testcase with only one coordinate pair */
                curve->closepath();
            }
            sp_shape_set_curve(SP_SHAPE(polygon), curve, TRUE);
            curve->unref();
            break;
        }
        default:
            if (((SPObjectClass *) parent_class)->set) {
                ((SPObjectClass *) parent_class)->set(object, key, value);
            }
            break;
    }
}
Пример #18
0
/**
 * Get the selected image.  Also check for any SPItems over it, in
 * case the user wants SIOX pre-processing.
 */
SPImage *
Tracer::getSelectedSPImage()
{

    SPDesktop *desktop = SP_ACTIVE_DESKTOP;
    if (!desktop)
        {
        g_warning("Trace: No active desktop");
        return NULL;
        }

    Inkscape::MessageStack *msgStack = sp_desktop_message_stack(desktop);

    Inkscape::Selection *sel = sp_desktop_selection(desktop);
    if (!sel)
        {
        char *msg = _("Select an <b>image</b> to trace");
        msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
        //g_warning(msg);
        return NULL;
        }

    if (sioxEnabled)
        {
        SPImage *img = NULL;
        GSList const *list = sel->itemList();
        std::vector<SPItem *> items;
        sioxShapes.clear();

        /*
           First, things are selected top-to-bottom, so we need to invert
           them as bottom-to-top so that we can discover the image and any
           SPItems above it
        */
        for ( ; list ; list=list->next)
            {
            if (!SP_IS_ITEM(list->data))
                {
                continue;
                }
            SPItem *item = SP_ITEM(list->data);
            items.insert(items.begin(), item);
            }
        std::vector<SPItem *>::iterator iter;
        for (iter = items.begin() ; iter!= items.end() ; iter++)
            {
            SPItem *item = *iter;
            if (SP_IS_IMAGE(item))
                {
                if (img) //we want only one
                    {
                    char *msg = _("Select only one <b>image</b> to trace");
                    msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
                    return NULL;
                    }
                img = SP_IMAGE(item);
                }
            else // if (img) //# items -after- the image in tree (above it in Z)
                {
                if (SP_IS_SHAPE(item))
                    {
                    SPShape *shape = SP_SHAPE(item);
                    sioxShapes.push_back(shape);
                    }
                }
            }

        if (!img || sioxShapes.size() < 1)
            {
            char *msg = _("Select one image and one or more shapes above it");
            msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
            return NULL;
            }
        return img;
        }
    else
        //### SIOX not enabled.  We want exactly one image selected
        {
        SPItem *item = sel->singleItem();
        if (!item)
            {
            char *msg = _("Select an <b>image</b> to trace");  //same as above
            msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
            //g_warning(msg);
            return NULL;
            }

        if (!SP_IS_IMAGE(item))
            {
            char *msg = _("Select an <b>image</b> to trace");
            msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
            //g_warning(msg);
            return NULL;
            }

        SPImage *img = SP_IMAGE(item);

        return img;
        }

}