static SPDrawAnchor * sp_draw_anchor_new (SPDrawContext *dc, SPCurve *curve, gboolean start, gdouble dx, gdouble dy) { SPDrawAnchor *a; g_print ("Creating anchor at %g %g\n", dx, dy); a = g_new (SPDrawAnchor, 1); a->dc = dc; a->curve = curve; a->start = start; a->active = FALSE; a->dp.x = dx; a->dp.y = dy; sp_desktop_d2w_xy_point (SP_EVENT_CONTEXT_DESKTOP (dc), &a->wp, dx, dy); a->ctrl = sp_canvas_item_new (SP_DT_CONTROLS (SP_EVENT_CONTEXT_DESKTOP (dc)), SP_TYPE_CTRL, "size", 4.0, "filled", 0, "fill_color", 0xff00007f, "stroked", 1, "stroke_color", 0x000000ff, NULL); sp_ctrl_moveto (SP_CTRL (a->ctrl), dx, dy); return a; }
static void sp_pen_context_setup (SPEventContext *ec) { SPPenContext *pc; pc = SP_PEN_CONTEXT (ec); if (((SPEventContextClass *) pen_parent_class)->setup) ((SPEventContextClass *) pen_parent_class)->setup (ec); /* Pen indicators */ pc->c0 = sp_canvas_item_new (SP_DT_CONTROLS (SP_EVENT_CONTEXT_DESKTOP (ec)), SP_TYPE_CTRL, "shape", SP_CTRL_SHAPE_CIRCLE, "size", 4.0, "filled", 0, "fill_color", 0xff00007f, "stroked", 1, "stroke_color", 0x0000ff7f, NULL); pc->c1 = sp_canvas_item_new (SP_DT_CONTROLS (SP_EVENT_CONTEXT_DESKTOP (ec)), SP_TYPE_CTRL, "shape", SP_CTRL_SHAPE_CIRCLE, "size", 4.0, "filled", 0, "fill_color", 0xff00007f, "stroked", 1, "stroke_color", 0x0000ff7f, NULL); pc->cl0 = sp_canvas_item_new (SP_DT_CONTROLS (SP_EVENT_CONTEXT_DESKTOP (ec)), SP_TYPE_CTRLLINE, NULL); sp_ctrlline_set_rgba32 (SP_CTRLLINE (pc->cl0), 0x0000007f); pc->cl1 = sp_canvas_item_new (SP_DT_CONTROLS (SP_EVENT_CONTEXT_DESKTOP (ec)), SP_TYPE_CTRLLINE, NULL); sp_ctrlline_set_rgba32 (SP_CTRLLINE (pc->cl1), 0x0000007f); sp_canvas_item_hide (pc->c0); sp_canvas_item_hide (pc->c1); sp_canvas_item_hide (pc->cl0); sp_canvas_item_hide (pc->cl1); sp_event_context_read (ec, "mode"); }
static void spdc_set_attach (SPDrawContext *dc, gboolean attach) { if (attach) { dc->attach = TRUE; spdc_attach_selection (dc, dc->selection); sp_view_set_status (SP_VIEW (SP_EVENT_CONTEXT_DESKTOP (dc)), _("Appending to selection. Press 'a' to toggle Append/New."), FALSE); } else { dc->attach = FALSE; spdc_detach_selection (dc, dc->selection); sp_view_set_status (SP_VIEW (SP_EVENT_CONTEXT_DESKTOP (dc)), _("Creating new curve. Press 'a' to toggle Append/New."), FALSE); } }
static void sp_box3d_finish(Box3DContext *bc) { bc->_message_context->clear(); bc->ctrl_dragged = false; bc->extruded = false; if ( bc->item != NULL ) { SPDesktop * desktop = SP_EVENT_CONTEXT_DESKTOP(bc); SPDocument *doc = sp_desktop_document(desktop); if (!doc || !doc->getCurrentPersp3D()) return; SPBox3D *box = SP_BOX3D(bc->item); box->orig_corner0 = bc->drag_origin_proj; box->orig_corner7 = bc->drag_ptC_proj; box->updateRepr(); box3d_relabel_corners(box); desktop->canvas->end_forced_full_redraws(); sp_desktop_selection(desktop)->set(bc->item); sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX, _("Create 3D box")); bc->item = NULL; } }
/** * Creates an anchor object and initializes it. */ SPDrawAnchor *sp_draw_anchor_new(SPDrawContext *dc, SPCurve *curve, gboolean start, Geom::Point delta) { if (SP_IS_LPETOOL_CONTEXT(dc)) { // suppress all kinds of anchors in LPEToolContext return NULL; } SPDesktop *dt = SP_EVENT_CONTEXT_DESKTOP(dc); SPDrawAnchor *a = g_new(SPDrawAnchor, 1); a->dc = dc; a->curve = curve; curve->ref(); a->start = start; a->active = FALSE; a->dp = delta; a->ctrl = sp_canvas_item_new(sp_desktop_controls(dt), SP_TYPE_CTRL, "size", 6.0, "filled", 1, "fill_color", FILL_COLOR_NORMAL, "stroked", 1, "stroke_color", 0x000000ff, NULL); SP_CTRL(a->ctrl)->moveto(delta); return a; }
static void spdc_endpoint_snap (SPDrawContext *dc, NRPointF *p, guint state) { if (state & GDK_CONTROL_MASK) { /* Constrained motion */ /* mirrored by fabs, so this corresponds to 15 degrees */ double bx = 0, by = 0; /* best solution */ double bn = 1e18; /* best normal */ double bdot = 0; double vx = 0, vy = 1; double r00 = cos (M_PI / NUMBER_OF_TURNS), r01 = sin (M_PI / NUMBER_OF_TURNS); double r10 = -r01, r11 = r00; double dx = p->x - dc->p[0].x; double dy = p->y - dc->p[0].y; int i; for(i = 0; i < NUMBER_OF_TURNS; i++) { double ndot = fabs(vy*dx-vx*dy); double tx = r00*vx + r01*vy; double ty = r10*vx + r11*vy; if (ndot < bn) { /* I think it is better numerically to use the normal, rather than the */ /* dot product to assess solutions, but I haven't proven it */ bn = ndot; bx = vx; by = vy; bdot = vx*dx + vy*dy; } vx = tx; vy = ty; } if (fabs (bdot) > 0) { p->x = dc->p[0].x + bdot * bx; p->y = dc->p[0].y + bdot * by; /* Snap it along best vector */ sp_desktop_vector_snap (SP_EVENT_CONTEXT_DESKTOP (dc), p, bx, by); } } else { /* Free */ sp_desktop_free_snap (SP_EVENT_CONTEXT_DESKTOP (dc), p); } }
static void spdc_set_startpoint (SPPencilContext *pc, NRPointF *p, guint state) { SPDrawContext *dc; dc = SP_DRAW_CONTEXT (pc); sp_desktop_free_snap (SP_EVENT_CONTEXT_DESKTOP (dc), p); dc->npoints = 0; dc->p[dc->npoints++] = *p; }
/** * Test if point is near anchor, if so fill anchor on canvas and return * pointer to it or NULL. */ SPDrawAnchor *sp_draw_anchor_test(SPDrawAnchor *anchor, Geom::Point w, gboolean activate) { SPDesktop *dt = SP_EVENT_CONTEXT_DESKTOP(anchor->dc); if ( activate && ( Geom::LInfty( w - dt->d2w(anchor->dp) ) <= A_SNAP ) ) { if (!anchor->active) { sp_canvas_item_set((GtkObject *) anchor->ctrl, "fill_color", FILL_COLOR_MOUSEOVER, NULL); anchor->active = TRUE; } return anchor; } if (anchor->active) { sp_canvas_item_set((GtkObject *) anchor->ctrl, "fill_color", FILL_COLOR_NORMAL, NULL); anchor->active = FALSE; } return NULL; }
static gint pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &bevent) { gint ret = FALSE; SPEventContext *event_context = SP_EVENT_CONTEXT(pc); if ( bevent.button == 1 && !event_context->space_panning) { SPDrawContext *dc = SP_DRAW_CONTEXT (pc); SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(dc); Inkscape::Selection *selection = sp_desktop_selection(desktop); if (Inkscape::have_viable_layer(desktop, dc->_message_context) == false) { return TRUE; } Geom::Point const button_w(bevent.x, bevent.y); /* Find desktop coordinates */ Geom::Point p = pc->desktop->w2d(button_w); /* Test whether we hit any anchor. */ SPDrawAnchor *anchor = spdc_test_inside(pc, button_w); pencil_drag_origin_w = Geom::Point(bevent.x,bevent.y); pencil_within_tolerance = true; switch (pc->state) { case SP_PENCIL_CONTEXT_ADDLINE: /* Current segment will be finished with release */ ret = TRUE; break; default: /* Set first point of sequence */ if (bevent.state & GDK_CONTROL_MASK) { spdc_create_single_dot(event_context, p, "/tools/freehand/pencil", bevent.state); ret = true; break; } if (anchor) { p = anchor->dp; desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Continuing selected path")); } else { if (!(bevent.state & GDK_SHIFT_MASK)) { // This is the first click of a new curve; deselect item so that // this curve is not combined with it (unless it is drawn from its // anchor, which is handled by the sibling branch above) selection->clear(); desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating new path")); SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); Inkscape::SnappedPoint const s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p); if (s.getSnapped()) { s.getPoint(p); pc->prev_snap_was_succesful = true; } else { pc->prev_snap_was_succesful = false; } } else if (selection->singleItem() && SP_IS_PATH(selection->singleItem())) { desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Appending to selected path")); } } pc->sa = anchor; spdc_set_startpoint(pc, p); ret = TRUE; break; } pc->is_drawing = true; } return ret; }
static void spdc_flush_white (SPDrawContext *dc, SPCurve *gc) { SPCurve *c; if (dc->white_curves) { g_assert (dc->white_item); c = sp_curve_concat (dc->white_curves); g_slist_free (dc->white_curves); dc->white_curves = NULL; if (gc) { sp_curve_append (c, gc, FALSE); } } else if (gc) { c = gc; sp_curve_ref (c); } else { return; } /* Now we have to go back to item coordinates at last */ if (dc->white_item) { NRMatrixD d2itemd; sp_item_dt2i_affine_d (dc->white_item, SP_EVENT_CONTEXT_DESKTOP (dc), &d2itemd); c = sp_curve_transform (c, NR_MATRIX_D_TO_DOUBLE (&d2itemd)); } else { gdouble d2item[6]; sp_desktop_dt2root_affine (SP_EVENT_CONTEXT_DESKTOP (dc), (NRMatrixD *) d2item); c = sp_curve_transform (c, d2item); } if (c && !sp_curve_empty (c)) { SPDesktop *dt; SPDocument *doc; SPRepr *repr; gchar *str; /* We actually have something to write */ dt = SP_EVENT_CONTEXT_DESKTOP (dc); doc = SP_DT_DOCUMENT (dt); if (dc->white_item) { repr = SP_OBJECT_REPR (dc->white_item); } else { SPRepr *style; repr = sp_repr_new ("path"); /* fixme: Pen and pencil need separate style (Lauris) */ style = inkscape_get_repr (INKSCAPE, "tools.freehand"); if (style) { SPCSSAttr *css; css = sp_repr_css_attr_inherited (style, "style"); sp_repr_css_set (repr, css, "style"); sp_repr_css_attr_unref (css); } } str = sp_svg_write_path (SP_CURVE_BPATH (c)); g_assert (str != NULL); sp_repr_set_attr (repr, "d", str); g_free (str); if (!dc->white_item) { /* Attach repr */ sp_document_add_repr (SP_DT_DOCUMENT (dt), repr); sp_selection_set_repr (dc->selection, repr); sp_repr_unref (repr); } sp_document_done (doc); } sp_curve_unref (c); /* Flush pending updates */ sp_document_ensure_up_to_date (SP_DT_DOCUMENT (SP_EVENT_CONTEXT_DESKTOP (dc))); }