~centralelyon2010/inkscape/imagelinks2

« back to all changes in this revision

Viewing changes to src/nodepath.cpp

  • Committer: Ted Gould
  • Date: 2008-11-21 05:24:08 UTC
  • Revision ID: ted@canonical.com-20081121052408-tilucis2pjrrpzxx
MergeĀ fromĀ fe-moved

Show diffs side-by-side

added added

removed removed

Lines of Context:
126
126
static void node_clicked(SPKnot *knot, guint state, gpointer data);
127
127
static void node_grabbed(SPKnot *knot, guint state, gpointer data);
128
128
static void node_ungrabbed(SPKnot *knot, guint state, gpointer data);
129
 
static gboolean node_request(SPKnot *knot, Geom::Point *p, guint state, gpointer data);
 
129
static gboolean node_request(SPKnot *knot, Geom::Point const &p, guint state, gpointer data);
130
130
 
131
131
/* Handle event callbacks */
132
132
static void node_handle_clicked(SPKnot *knot, guint state, gpointer data);
133
133
static void node_handle_grabbed(SPKnot *knot, guint state, gpointer data);
134
134
static void node_handle_ungrabbed(SPKnot *knot, guint state, gpointer data);
135
 
static gboolean node_handle_request(SPKnot *knot, Geom::Point *p, guint state, gpointer data);
136
 
static void node_handle_moved(SPKnot *knot, Geom::Point *p, guint state, gpointer data);
 
135
static gboolean node_handle_request(SPKnot *knot, Geom::Point const &p, guint state, gpointer data);
 
136
static void node_handle_moved(SPKnot *knot, Geom::Point const &p, guint state, gpointer data);
137
137
static gboolean node_handle_event(SPKnot *knot, GdkEvent *event, Inkscape::NodePath::Node *n);
138
138
 
139
139
/* Constructors and destructors */
181
181
 
182
182
static void
183
183
sp_nodepath_create_helperpaths(Inkscape::NodePath::Path *np) {
184
 
    //std::map<Inkscape::LivePathEffect::Effect *, std::vector<SPCanvasItem *> >* helper_path_vec;
 
184
    //std::map<Inkscape::LivePathEffect::Effect *, std::vector<SPCanvasItem *> > helper_path_vec;
185
185
    if (!SP_IS_LPE_ITEM(np->item)) {
186
186
        g_print ("Only LPEItems can have helperpaths!\n");
187
187
        return;
196
196
            // create new canvas items from the effect's helper paths
197
197
            std::vector<Geom::PathVector> hpaths = lpe->getHelperPaths(lpeitem);
198
198
            for (std::vector<Geom::PathVector>::iterator j = hpaths.begin(); j != hpaths.end(); ++j) {
199
 
                (*np->helper_path_vec)[lpe].push_back(canvasitem_from_pathvec(np, *j, true));
 
199
                np->helper_path_vec[lpe].push_back(canvasitem_from_pathvec(np, *j, true));
200
200
            }
201
201
        }
202
202
    }
204
204
 
205
205
void
206
206
sp_nodepath_update_helperpaths(Inkscape::NodePath::Path *np) {
207
 
    //std::map<Inkscape::LivePathEffect::Effect *, std::vector<SPCanvasItem *> >* helper_path_vec;
 
207
    //std::map<Inkscape::LivePathEffect::Effect *, std::vector<SPCanvasItem *> > helper_path_vec;
208
208
    if (!SP_IS_LPE_ITEM(np->item)) {
209
209
        g_print ("Only LPEItems can have helperpaths!\n");
210
210
        return;
223
223
            for (unsigned int j = 0; j < hpaths.size(); ++j) {
224
224
                SPCurve *curve = new SPCurve(hpaths[j]);
225
225
                curve->transform(np->i2d);
226
 
                sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(((*np->helper_path_vec)[lpe])[j]), curve);
 
226
                sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH((np->helper_path_vec[lpe])[j]), curve);
227
227
                curve = curve->unref();
228
228
            }
229
229
        }
232
232
 
233
233
static void
234
234
sp_nodepath_destroy_helperpaths(Inkscape::NodePath::Path *np) {
235
 
    for (HelperPathList::iterator i = np->helper_path_vec->begin(); i != np->helper_path_vec->end(); ++i) {
 
235
    for (HelperPathList::iterator i = np->helper_path_vec.begin(); i != np->helper_path_vec.end(); ++i) {
236
236
        for (std::vector<SPCanvasItem *>::iterator j = (*i).second.begin(); j != (*i).second.end(); ++j) {
237
237
            GtkObject *temp = *j;
238
238
            *j = NULL;
239
239
            gtk_object_destroy(temp);
240
240
        }
241
241
    }
 
242
    np->helper_path_vec.clear();
242
243
}
243
244
 
244
245
 
245
246
/**
246
247
 * \brief Creates new nodepath from item
 
248
 *
 
249
 * \todo create proper constructor for nodepath::path, this method returns null a constructor cannot so this cannot be simply converted to constructor.
247
250
 */
248
251
Inkscape::NodePath::Path *sp_nodepath_new(SPDesktop *desktop, SPObject *object, bool show_handles, const char * repr_key_in, SPItem *item)
249
252
{
278
281
    }
279
282
 
280
283
    //Create new nodepath
281
 
    Inkscape::NodePath::Path *np = g_new(Inkscape::NodePath::Path, 1);
 
284
    Inkscape::NodePath::Path *np = new Inkscape::NodePath::Path();
282
285
    if (!np) {
283
286
        curve->unref();
284
287
        return NULL;
295
298
    np->local_change = 0;
296
299
    np->show_handles = show_handles;
297
300
    np->helper_path = NULL;
298
 
    np->helper_path_vec = new HelperPathList;
299
301
    np->helperpath_rgba = prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff);
300
302
    np->helperpath_width = 1.0;
301
303
    np->curve = curve->copy();
328
330
        Inkscape::LivePathEffect::Effect * lpe = LIVEPATHEFFECT(object)->get_lpe();
329
331
        if (!lpe) {
330
332
            g_error("sp_nodepath_new: lpeobject without real lpe passed as argument!");
331
 
            sp_nodepath_destroy(np);
 
333
            delete np;
332
334
        }
333
335
        Inkscape::LivePathEffect::Parameter *lpeparam = lpe->getParameter(repr_key_in);
334
336
        if (lpeparam) {
383
385
/**
384
386
 * Destroys nodepath's subpaths, then itself, also tell parent ShapeEditor about it.
385
387
 */
386
 
void sp_nodepath_destroy(Inkscape::NodePath::Path *np) {
387
 
 
388
 
    if (!np) {  //soft fail, like delete
389
 
        return;
390
 
    }
391
 
 
392
 
    while (np->subpaths) {
393
 
        sp_nodepath_subpath_destroy((Inkscape::NodePath::SubPath *) np->subpaths->data);
 
388
Inkscape::NodePath::Path::~Path() {
 
389
    while (this->subpaths) {
 
390
        sp_nodepath_subpath_destroy((Inkscape::NodePath::SubPath *) this->subpaths->data);
394
391
    }
395
392
 
396
393
    //Inform the ShapeEditor that made me, if any, that I am gone.
397
 
    if (np->shape_editor)
398
 
        np->shape_editor->nodepath_destroyed();
399
 
 
400
 
    g_assert(!np->selected);
401
 
 
402
 
    if (np->helper_path) {
403
 
        GtkObject *temp = np->helper_path;
404
 
        np->helper_path = NULL;
 
394
    if (this->shape_editor)
 
395
        this->shape_editor->nodepath_destroyed();
 
396
 
 
397
    g_assert(!this->selected);
 
398
 
 
399
    if (this->helper_path) {
 
400
        GtkObject *temp = this->helper_path;
 
401
        this->helper_path = NULL;
405
402
        gtk_object_destroy(temp);
406
403
    }
407
 
    if (np->curve) {
408
 
        np->curve->unref();
409
 
        np->curve = NULL;
410
 
    }
411
 
 
412
 
    if (np->repr_key) {
413
 
        g_free(np->repr_key);
414
 
        np->repr_key = NULL;
415
 
    }
416
 
    if (np->repr_nodetypes_key) {
417
 
        g_free(np->repr_nodetypes_key);
418
 
        np->repr_nodetypes_key = NULL;
419
 
    }
420
 
 
421
 
    sp_nodepath_destroy_helperpaths(np);
422
 
    delete np->helper_path_vec;
423
 
    np->helper_path_vec = NULL;
424
 
 
425
 
    np->desktop = NULL;
426
 
 
427
 
    g_free(np);
 
404
    if (this->curve) {
 
405
        this->curve->unref();
 
406
        this->curve = NULL;
 
407
    }
 
408
 
 
409
    if (this->repr_key) {
 
410
        g_free(this->repr_key);
 
411
        this->repr_key = NULL;
 
412
    }
 
413
    if (this->repr_nodetypes_key) {
 
414
        g_free(this->repr_nodetypes_key);
 
415
        this->repr_nodetypes_key = NULL;
 
416
    }
 
417
 
 
418
    sp_nodepath_destroy_helperpaths(this);
 
419
 
 
420
    this->desktop = NULL;
428
421
}
429
422
 
430
423
/**
771
764
       Inkscape::NodePath::Node *n = sp->first->n.other;
772
765
        while (n) {
773
766
            Geom::Point const end_pt = n->pos * np->d2i;
 
767
            if (!IS_FINITE(n->pos[0]) || !IS_FINITE(n->pos[1])){
 
768
                g_message("niet finite");
 
769
            }
774
770
            switch (n->code) {
775
771
                case NR_LINETO:
776
772
                    curve->lineto(end_pt);
2067
2063
 
2068
2064
    //find segment to split
2069
2065
    Inkscape::NodePath::Node *e = sp_nodepath_get_node_by_index(nodepath, segment_index);
 
2066
    if (!e) {
 
2067
        return;
 
2068
    }
2070
2069
 
2071
2070
    //don't know why but t seems to flip for lines
2072
2071
    if (sp_node_path_code_from_side(e, sp_node_get_side(e, -1)) == NR_LINETO) {
3609
3608
 * \todo fixme: This goes to "moved" event? (lauris)
3610
3609
 */
3611
3610
static gboolean
3612
 
node_request(SPKnot */*knot*/, Geom::Point *p, guint state, gpointer data)
 
3611
node_request(SPKnot */*knot*/, Geom::Point const &p, guint state, gpointer data)
3613
3612
{
3614
3613
    double yn, xn, yp, xp;
3615
3614
    double an, ap, na, pa;
3627
3626
         ( ((state & GDK_SHIFT_MASK) && ((n->n.other && n->n.pos == n->pos) || (n->p.other && n->p.pos == n->pos)))
3628
3627
           || n->dragging_out ) )
3629
3628
    {
3630
 
       Geom::Point mouse = (*p);
 
3629
       Geom::Point mouse = p;
3631
3630
 
3632
3631
       if (!n->dragging_out) {
3633
3632
           // This is the first drag-out event; find out which handle to drag out
3634
 
           double appr_n = (n->n.other ? Geom::L2(n->n.other->pos - n->pos) - Geom::L2(n->n.other->pos - (*p)) : -HUGE_VAL);
3635
 
           double appr_p = (n->p.other ? Geom::L2(n->p.other->pos - n->pos) - Geom::L2(n->p.other->pos - (*p)) : -HUGE_VAL);
 
3633
           double appr_n = (n->n.other ? Geom::L2(n->n.other->pos - n->pos) - Geom::L2(n->n.other->pos - p) : -HUGE_VAL);
 
3634
           double appr_p = (n->p.other ? Geom::L2(n->p.other->pos - n->pos) - Geom::L2(n->p.other->pos - p) : -HUGE_VAL);
3636
3635
 
3637
3636
           if (appr_p == -HUGE_VAL && appr_n == -HUGE_VAL) // orphan node?
3638
3637
               return FALSE;
3656
3655
                   opposite = &n->p;
3657
3656
                   n->n.other->code = NR_CURVETO;
3658
3657
               } else { // find out to which handle of the adjacent node we're closer; note that n->n.other == n->p.other
3659
 
                   double appr_other_n = (n->n.other ? Geom::L2(n->n.other->n.pos - n->pos) - Geom::L2(n->n.other->n.pos - (*p)) : -HUGE_VAL);
3660
 
                   double appr_other_p = (n->n.other ? Geom::L2(n->n.other->p.pos - n->pos) - Geom::L2(n->n.other->p.pos - (*p)) : -HUGE_VAL);
 
3658
                   double appr_other_n = (n->n.other ? Geom::L2(n->n.other->n.pos - n->pos) - Geom::L2(n->n.other->n.pos - p) : -HUGE_VAL);
 
3659
                   double appr_other_p = (n->n.other ? Geom::L2(n->n.other->p.pos - n->pos) - Geom::L2(n->n.other->p.pos - p) : -HUGE_VAL);
3661
3660
                   if (appr_other_p > appr_other_n) { // closer to other's p handle
3662
3661
                       n->dragging_out = &n->n;
3663
3662
                       opposite = &n->p;
3681
3680
       }
3682
3681
 
3683
3682
       // pass this on to the handle-moved callback
3684
 
       node_handle_moved(n->dragging_out->knot, &mouse, state, (gpointer) n);
 
3683
       node_handle_moved(n->dragging_out->knot, mouse, state, (gpointer) n);
3685
3684
       sp_node_update_handles(n);
3686
3685
       return TRUE;
3687
3686
   }
3744
3743
            if (ap == 0) pa = HUGE_VAL; else pa = -1/ap;
3745
3744
 
3746
3745
            // mouse point relative to the node's original pos
3747
 
            pr = (*p) - n->origin;
 
3746
            pr = p - n->origin;
3748
3747
 
3749
3748
            // distances to the four lines (two handles and two perpendiculars)
3750
3749
            d_an = point_line_distance(&pr, an);
3771
3770
 
3772
3771
        } else {  // constraining to hor/vert
3773
3772
 
3774
 
            if (fabs((*p)[Geom::X] - n->origin[Geom::X]) > fabs((*p)[Geom::Y] - n->origin[Geom::Y])) { // snap to hor
 
3773
            if (fabs(p[Geom::X] - n->origin[Geom::X]) > fabs(p[Geom::Y] - n->origin[Geom::Y])) { // snap to hor
3775
3774
                sp_nodepath_selected_nodes_move(n->subpath->nodepath,
3776
 
                                                (*p)[Geom::X] - n->pos[Geom::X], 
 
3775
                                                p[Geom::X] - n->pos[Geom::X], 
3777
3776
                                                n->origin[Geom::Y] - n->pos[Geom::Y],
3778
3777
                                                true, 
3779
3778
                                                true, Inkscape::Snapper::ConstraintLine(component_vectors[Geom::X]));
3780
3779
            } else { // snap to vert
3781
3780
                sp_nodepath_selected_nodes_move(n->subpath->nodepath,
3782
3781
                                                n->origin[Geom::X] - n->pos[Geom::X],
3783
 
                                                (*p)[Geom::Y] - n->pos[Geom::Y],
 
3782
                                                p[Geom::Y] - n->pos[Geom::Y],
3784
3783
                                                true,
3785
3784
                                                true, Inkscape::Snapper::ConstraintLine(component_vectors[Geom::Y]));
3786
3785
            }
3788
3787
    } else { // move freely
3789
3788
        if (n->is_dragging) {
3790
3789
            if (state & GDK_MOD1_MASK) { // sculpt
3791
 
                sp_nodepath_selected_nodes_sculpt(n->subpath->nodepath, n, (*p) - n->origin);
 
3790
                sp_nodepath_selected_nodes_sculpt(n->subpath->nodepath, n, p - n->origin);
3792
3791
            } else {
3793
3792
                sp_nodepath_selected_nodes_move(n->subpath->nodepath,
3794
 
                                            (*p)[Geom::X] - n->pos[Geom::X],
3795
 
                                            (*p)[Geom::Y] - n->pos[Geom::Y],
 
3793
                                            p[Geom::X] - n->pos[Geom::X],
 
3794
                                            p[Geom::Y] - n->pos[Geom::Y],
3796
3795
                                            (state & GDK_SHIFT_MASK) == 0);
3797
3796
            }
3798
3797
        }
3799
3798
    }
3800
3799
 
3801
 
    n->subpath->nodepath->desktop->scroll_to_point(*p);
 
3800
    n->subpath->nodepath->desktop->scroll_to_point(p);
3802
3801
 
3803
3802
    return TRUE;
3804
3803
}
3879
3878
/**
3880
3879
 * Node handle "request" signal callback.
3881
3880
 */
3882
 
static gboolean node_handle_request(SPKnot *knot, Geom::Point *p, guint state, gpointer data)
 
3881
static gboolean node_handle_request(SPKnot *knot, Geom::Point const &p, guint state, gpointer data)
3883
3882
{
3884
3883
    Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) data;
3885
3884
 
3907
3906
    if ((state & GDK_SHIFT_MASK) != 0) {
3908
3907
        // We will not try to snap when the shift-key is pressed
3909
3908
        // so remove the old snap indicator and don't wait for it to time-out  
3910
 
        desktop->snapindicator->remove_snappoint();     
 
3909
        desktop->snapindicator->remove_snappoint();
3911
3910
    }
3912
3911
 
3913
3912
    Inkscape::NodePath::Node *othernode = opposite->other;
3914
3913
    if (othernode) {
3915
3914
        if ((n->type != Inkscape::NodePath::NODE_CUSP) && sp_node_side_is_line(n, opposite)) {
3916
3915
            /* We are smooth node adjacent with line */
3917
 
            Geom::Point const delta = *p - n->pos;
 
3916
            Geom::Point const delta = p - n->pos;
3918
3917
            Geom::Coord const len = Geom::L2(delta);
3919
3918
            Inkscape::NodePath::Node *othernode = opposite->other;
3920
3919
            Geom::Point const ndelta = n->pos - othernode->pos;
3921
3920
            Geom::Coord const linelen = Geom::L2(ndelta);
 
3921
            Geom::Point ptemp = p;
3922
3922
            if (len > NR_EPSILON && linelen > NR_EPSILON) {
3923
3923
                Geom::Coord const scal = dot(delta, ndelta) / linelen;
3924
 
                (*p) = n->pos + (scal / linelen) * ndelta;
 
3924
                ptemp = n->pos + (scal / linelen) * ndelta;
3925
3925
            }
3926
3926
            if ((state & GDK_SHIFT_MASK) == 0) {
3927
 
                s = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(*p), Inkscape::Snapper::ConstraintLine(*p, ndelta));
 
3927
                s = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, ptemp, Inkscape::Snapper::ConstraintLine(ptemp, ndelta));
3928
3928
            }
3929
3929
        } else {
3930
 
                if ((state & GDK_SHIFT_MASK) == 0) {
3931
 
                        s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(*p));
3932
 
                }
 
3930
            if ((state & GDK_SHIFT_MASK) == 0) {
 
3931
                s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p);
 
3932
            }
3933
3933
        }
3934
3934
    } else {
3935
 
        if ((state & GDK_SHIFT_MASK) == 0) {
3936
 
                s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(*p));
3937
 
        }
 
3935
        if ((state & GDK_SHIFT_MASK) == 0) {
 
3936
            s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p);
 
3937
        }
3938
3938
    }
3939
3939
    
3940
 
    Geom::Point pt2g = *p;
3941
 
    s.getPoint(pt2g);
3942
 
    *p = pt2g;
3943
 
    
3944
3940
    sp_node_adjust_handle(n, -which);
3945
3941
 
3946
3942
    return FALSE;
3949
3945
/**
3950
3946
 * Node handle moved callback.
3951
3947
 */
3952
 
static void node_handle_moved(SPKnot *knot, Geom::Point *p, guint state, gpointer data)
 
3948
static void node_handle_moved(SPKnot *knot, Geom::Point const &p, guint state, gpointer data)
3953
3949
{
3954
3950
   Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) data;
3955
3951
   Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3971
3967
    // calculate radial coordinates of the grabbed handle, its other handle, and the mouse point
3972
3968
    Radial rme(me->pos - n->pos);
3973
3969
    Radial rother(other->pos - n->pos);
3974
 
    Radial rnew(*p - n->pos);
 
3970
    Radial rnew(p - n->pos);
3975
3971
 
3976
3972
    if (state & GDK_CONTROL_MASK && rnew.a != HUGE_VAL) {
3977
3973
        int const snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);
4362
4358
            box.expandTo (n->pos); // contain all selected nodes
4363
4359
        }
4364
4360
 
 
4361
        if ( Geom::are_near(box.maxExtent(), 0) ) {
 
4362
            SPEventContext *ec = nodepath->desktop->event_context;
 
4363
            if (!ec) return;
 
4364
            Inkscape::MessageContext *mc = get_message_context(ec);
 
4365
            if (!mc) return;
 
4366
            mc->setF(Inkscape::WARNING_MESSAGE,
 
4367
                             _("Cannot scale nodes when all are at the same location."));
 
4368
            return;
 
4369
        }
4365
4370
        double scale = (box.maxExtent() + grow)/box.maxExtent();
4366
4371
 
 
4372
 
4367
4373
        Geom::Point scale_center;
4368
4374
        if (Inkscape::NodePath::Path::active_node == NULL)
4369
4375
            scale_center = box.midpoint();
4371
4377
            scale_center = Inkscape::NodePath::Path::active_node->pos;
4372
4378
 
4373
4379
        Geom::Matrix t =
4374
 
            Geom::Matrix (Geom::Translate(-scale_center)) *
4375
 
            Geom::Matrix (Geom::Scale(scale, scale)) *
4376
 
            Geom::Matrix (Geom::Translate(scale_center));
 
4380
            Geom::Translate(-scale_center) *
 
4381
            Geom::Scale(scale, scale) *
 
4382
            Geom::Translate(scale_center);
4377
4383
 
4378
4384
        for (GList *l = nodepath->selected; l != NULL; l = l->next) {
4379
4385
            Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;