X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdyna-draw-context.cpp;h=f6f59fe6b375d5fdab3247be36dec9573905f69d;hb=5ab9f562e7106ca0cfcdaf845092dae3644edeab;hp=56890b7677dc38e3b05254edf86d9ead21f53284;hpb=5cac7c6f8743714a17f26f7ee86244e38aa37a45;p=inkscape.git diff --git a/src/dyna-draw-context.cpp b/src/dyna-draw-context.cpp index 56890b767..f6f59fe6b 100644 --- a/src/dyna-draw-context.cpp +++ b/src/dyna-draw-context.cpp @@ -58,6 +58,7 @@ #include "inkscape.h" #include "color.h" #include "splivarot.h" +#include "sp-item-group.h" #include "sp-shape.h" #include "sp-path.h" #include "sp-text.h" @@ -197,6 +198,7 @@ sp_dyna_draw_context_init(SPDynaDrawContext *ddc) ddc->keep_selected = true; ddc->hatch_spacing = 0; + ddc->hatch_spacing_step = 0; new (&ddc->hatch_pointer_past) std::list(); new (&ddc->hatch_nearest_past) std::list(); ddc->hatch_last_nearest = NR::Point(0,0); @@ -210,6 +212,7 @@ sp_dyna_draw_context_init(SPDynaDrawContext *ddc) ddc->trace_bg = false; ddc->is_dilating = false; + ddc->has_dilated = false; } static void @@ -599,50 +602,46 @@ get_dilate_radius (SPDynaDrawContext *dc) double get_dilate_force (SPDynaDrawContext *dc) { - return 8 * dc->pressure/SP_EVENT_CONTEXT(dc)->desktop->current_zoom(); + double force = 4 * dc->pressure/SP_EVENT_CONTEXT(dc)->desktop->current_zoom(); + if (force > 3) { + force += 8 * (force - 3); + } + return force; } bool -sp_ddc_dilate (SPDynaDrawContext *dc, NR::Point p, bool expand) +sp_ddc_dilate_recursive (SPItem *item, NR::Point p, bool expand, double radius, double offset) { - Inkscape::Selection *selection = sp_desktop_selection(SP_EVENT_CONTEXT(dc)->desktop); - - if (selection->isEmpty()) { - return false; - } - bool did = false; - double radius = get_dilate_radius(dc); - double offset = get_dilate_force(dc); - for (GSList *items = g_slist_copy((GSList *) selection->itemList()); - items != NULL; - items = items->next) { - - SPItem *item = (SPItem *) items->data; + if (SP_IS_GROUP(item)) { + for (SPObject *child = sp_object_first_child(SP_OBJECT(item)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { + if (SP_IS_ITEM(child)) { + if (sp_ddc_dilate_recursive (SP_ITEM(child), p, expand, radius, offset)) + did = true; + } + } - // only paths - if (!SP_IS_PATH(item)) - continue; + } else if (SP_IS_PATH(item)) { SPCurve *curve = NULL; curve = sp_shape_get_curve(SP_SHAPE(item)); if (curve == NULL) - continue; + return false; // skip those paths whose bboxes are entirely out of reach with our radius NR::Maybe bbox = item->getBounds(sp_item_i2doc_affine(item)); if (bbox) { bbox->growBy(radius); if (!bbox->contains(p)) { - continue; + return false; } } Path *orig = Path_for_item(item, false); if (orig == NULL) { sp_curve_unref(curve); - continue; + return false; } Path *res = new Path; res->SetBackData(false); @@ -669,10 +668,11 @@ sp_ddc_dilate (SPDynaDrawContext *dc, NR::Point p, bool expand) } bool did_this = false; + NR::Matrix i2doc(sp_item_i2doc_affine(item)); if (theShape->MakeOffset(theRes, - expand? offset : -offset, - join_straight, butt_straight, - true, p[NR::X], p[NR::Y], radius) == 0) // 0 means the shape was actually changed + expand? offset : -offset, + join_straight, butt_straight, + true, p[NR::X], p[NR::Y], radius, &i2doc) == 0) // 0 means the shape was actually changed did_this = true; // the rest only makes sense if we actually changed the path @@ -715,6 +715,37 @@ sp_ddc_dilate (SPDynaDrawContext *dc, NR::Point p, bool expand) return did; } + +bool +sp_ddc_dilate (SPDynaDrawContext *dc, NR::Point p, bool expand) +{ + Inkscape::Selection *selection = sp_desktop_selection(SP_EVENT_CONTEXT(dc)->desktop); + + if (selection->isEmpty()) { + return false; + } + + bool did = false; + double radius = get_dilate_radius(dc); + double offset = get_dilate_force(dc); + if (radius == 0 || offset == 0) { + return false; + } + + for (GSList *items = g_slist_copy((GSList *) selection->itemList()); + items != NULL; + items = items->next) { + + SPItem *item = (SPItem *) items->data; + + if (sp_ddc_dilate_recursive (item, p, expand, radius, offset)) + did = true; + + } + + return did; +} + void sp_ddc_update_cursors (SPDynaDrawContext *dc) { @@ -797,7 +828,12 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, ret = TRUE; + sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 3); dc->is_drawing = true; + if (event->button.state & GDK_MOD1_MASK) { + dc->is_dilating = true; + dc->has_dilated = false; + } } break; case GDK_MOTION_NOTIFY: @@ -805,6 +841,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, NR::Point const motion_w(event->motion.x, event->motion.y); NR::Point motion_dt(desktop->w2d(motion_w)); + sp_dyna_draw_extinput(dc, event); // draw the dilating cursor if (event->motion.state & GDK_MOD1_MASK) { @@ -823,8 +860,8 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, } else { dc->_message_context->setF(Inkscape::NORMAL_MESSAGE, event->motion.state & GDK_SHIFT_MASK? - _("Thickening %d selected paths; without Shift to thin") : - _("Thinning %d selected paths; with Shift to thicken"), num); + _("Thickening %d selected objects; without Shift to thin") : + _("Thinning %d selected objects; with Shift to thicken"), num); } } else { @@ -835,7 +872,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, // dilating: if (dc->is_drawing && ( event->motion.state & GDK_BUTTON1_MASK ) && event->motion.state & GDK_MOD1_MASK) { sp_ddc_dilate (dc, desktop->dt2doc(motion_dt), event->motion.state & GDK_SHIFT_MASK? true : false); - dc->is_dilating = true; + dc->has_dilated = true; // it's slow, so prevent clogging up with events gobble_motion_events(GDK_BUTTON1_MASK); return TRUE; @@ -937,9 +974,6 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, // We are NOT attracted to the guide! //g_print ("\nlast_nearest %g %g nearest %g %g pointer %g %g pos %d %g\n", dc->last_nearest[NR::X], dc->last_nearest[NR::Y], nearest[NR::X], nearest[NR::Y], pointer[NR::X], pointer[NR::Y], position->piece, position->t); - //g_print ("------nm %g pm %g ratio %g\n", nearest_moved, pointer_moved, ratio); - //g_print ("------dist %g spacing %g\n", dist, dc->spacing); - //g_print ("acting up: %s dist %g \n", position_is_ok? (dc->hatch_escaped? "escaped" : "dist") : "livarot", dist/dc->hatch_spacing); // Remember hatch_escaped so we don't get // attracted again until the end of this stroke @@ -965,12 +999,10 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, } if (!isNaN(dot) && dot < -0.5) {// flip target = -target; - //g_print ("FLIP\n"); } // This is the track pointer that we will use instead of the real one NR::Point new_pointer = nearest + target * hatch_unit_vector; - //g_print ("NEW %g %g\n", new_point[NR::X], new_point[NR::Y]); // some limited feedback: allow persistent pulling to slightly change // the spacing @@ -996,7 +1028,6 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, dc->_message_context->set(Inkscape::NORMAL_MESSAGE, _("Drawing a calligraphic stroke")); } - sp_dyna_draw_extinput(dc, event); if (!sp_dyna_draw_apply(dc, motion_dt)) { ret = TRUE; break; @@ -1052,20 +1083,30 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, case GDK_BUTTON_RELEASE: + { + NR::Point const motion_w(event->button.x, event->button.y); + NR::Point const motion_dt(desktop->w2d(motion_w)); + sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), event->button.time); + sp_canvas_end_forced_full_redraws(desktop->canvas); dc->is_drawing = false; if ( dc->is_dilating && event->button.button == 1 ) { + if (!dc->has_dilated) { + // if we did not rub, do a light tap + dc->pressure = 0.03; + sp_ddc_dilate (dc, desktop->dt2doc(motion_dt), event->button.state & GDK_SHIFT_MASK? true : false); + } dc->is_dilating = false; + dc->has_dilated = false; sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(dc)->desktop), SP_VERB_CONTEXT_CALLIGRAPHIC, (event->button.state & GDK_SHIFT_MASK ? _("Thicken paths") : _("Thin paths"))); ret = TRUE; + } else if ( dc->dragging && event->button.button == 1 ) { dc->dragging = FALSE; - NR::Point const motion_w(event->button.x, event->button.y); - NR::Point const motion_dt(desktop->w2d(motion_w)); sp_dyna_draw_apply(dc, motion_dt); /* Remove all temporary line segments */ @@ -1096,10 +1137,19 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, dc->hatch_item = NULL; dc->hatch_livarot_path = NULL; + if (dc->hatch_spacing != 0 && !dc->keep_selected) { + // we do not select the newly drawn path, so increase spacing by step + if (dc->hatch_spacing_step == 0) { + dc->hatch_spacing_step = dc->hatch_spacing; + } + dc->hatch_spacing += dc->hatch_spacing_step; + } + dc->_message_context->clear(); ret = TRUE; } break; + } case GDK_KEY_PRESS: switch (get_group0_keyval (&event->key)) { @@ -1214,6 +1264,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, case GDK_Control_R: dc->_message_context->clear(); dc->hatch_spacing = 0; + dc->hatch_spacing_step = 0; break; case GDK_Alt_L: case GDK_Alt_R: @@ -1300,9 +1351,7 @@ set_to_accumulated(SPDynaDrawContext *dc, bool unionize) } else { if (dc->keep_selected) { sp_desktop_selection(desktop)->set(dc->repr); - } else { - sp_desktop_selection(desktop)->clear(); - } + } } } else {