Merge lp:~inkscape.dev/inkscape/clip_eraser into lp:~inkscape.dev/inkscape/trunk
- clip_eraser
- Merge into trunk
Proposed by
Jabiertxof
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 15143 | ||||
Proposed branch: | lp:~inkscape.dev/inkscape/clip_eraser | ||||
Merge into: | lp:~inkscape.dev/inkscape/trunk | ||||
Diff against target: |
731 lines (+298/-82) 6 files modified
src/selection-chemistry.cpp (+19/-13) src/selection-chemistry.h (+3/-3) src/sp-lpe-item.cpp (+21/-15) src/ui/tools/eraser-tool.cpp (+108/-38) src/widgets/eraser-toolbar.cpp (+140/-13) src/widgets/toolbox.cpp (+7/-0) |
||||
To merge this branch: | bzr merge lp:~inkscape.dev/inkscape/clip_eraser | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Owens | code | Approve | |
Review via email:
|
Commit message
Description of the change
Add new mode to eraser tool.
Demo: https:/
To post a comment you must log in.
- 14876. By Jabiertxof <email address hidden>
-
first attem to work throught layers
- 14877. By Jabiertxof
-
Speed improvements
- 14878. By Jabiertxof
-
Added some widgets from caligraphic tool
- 14879. By Jabiertxof
-
Update to trunk and some fixes
Revision history for this message

Martin Owens (doctormo) wrote : | # |
I've removed the std::cout and made the modes a defined set of constants to make reading the code a bit easier.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/selection-chemistry.cpp' |
2 | --- src/selection-chemistry.cpp 2016-09-15 22:31:44 +0000 |
3 | +++ src/selection-chemistry.cpp 2016-10-02 22:45:50 +0000 |
4 | @@ -1021,6 +1021,7 @@ |
5 | C_("Undo action", "Raise")); |
6 | } |
7 | |
8 | + |
9 | void sp_object_set_raise_to_top(ObjectSet *set) { |
10 | std::vector<Inkscape::XML::Node*> rl(set->xmlNodes().begin(), set->xmlNodes().end()); |
11 | sort(rl.begin(),rl.end(),sp_repr_compare_position_bool); |
12 | @@ -1031,7 +1032,7 @@ |
13 | } |
14 | } |
15 | |
16 | -void sp_selection_raise_to_top(Inkscape::Selection *selection, SPDesktop *desktop) |
17 | +void sp_selection_raise_to_top(Inkscape::Selection *selection, SPDesktop *desktop, bool skip_undo) |
18 | { |
19 | SPDocument *document = selection->layers()->getDocument(); |
20 | |
21 | @@ -1048,8 +1049,10 @@ |
22 | |
23 | sp_object_set_raise_to_top(selection); |
24 | |
25 | - DocumentUndo::done(document, SP_VERB_SELECTION_TO_FRONT, |
26 | - _("Raise to top")); |
27 | + if (!skip_undo) { |
28 | + DocumentUndo::done(document, SP_VERB_SELECTION_TO_FRONT, |
29 | + _("Raise to top")); |
30 | + } |
31 | } |
32 | |
33 | void sp_object_set_lower(ObjectSet *set) { |
34 | @@ -1111,6 +1114,7 @@ |
35 | C_("Undo action", "Lower")); |
36 | } |
37 | |
38 | + |
39 | void sp_object_set_lower_to_bottom(ObjectSet *set) { |
40 | std::vector<Inkscape::XML::Node*> rl(set->xmlNodes().begin(), set->xmlNodes().end()); |
41 | sort(rl.begin(),rl.end(),sp_repr_compare_position_bool); |
42 | @@ -1132,7 +1136,7 @@ |
43 | } |
44 | } |
45 | |
46 | -void sp_selection_lower_to_bottom(Inkscape::Selection *selection, SPDesktop *desktop) |
47 | +void sp_selection_lower_to_bottom(Inkscape::Selection *selection, SPDesktop *desktop, bool skip_undo) |
48 | { |
49 | if (selection->isEmpty()) { |
50 | selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to lower to bottom.")); |
51 | @@ -1146,9 +1150,10 @@ |
52 | } |
53 | |
54 | sp_object_set_lower_to_bottom(selection); |
55 | - |
56 | - DocumentUndo::done(selection->layers()->getDocument(), SP_VERB_SELECTION_TO_BACK, |
57 | - _("Lower to bottom")); |
58 | + if (!skip_undo) { |
59 | + DocumentUndo::done(desktop->getDocument(), SP_VERB_SELECTION_TO_BACK, |
60 | + _("Lower to bottom")); |
61 | + } |
62 | } |
63 | |
64 | void |
65 | @@ -3859,7 +3864,7 @@ |
66 | * If \a apply_clip_path parameter is true, clipPath is created, otherwise mask |
67 | * |
68 | */ |
69 | -void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_layer) |
70 | +void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_layer, bool skip_undo) |
71 | { |
72 | if (desktop == NULL) { |
73 | return; |
74 | @@ -4017,11 +4022,12 @@ |
75 | } |
76 | |
77 | selection->addList(items_to_select); |
78 | - |
79 | - if (apply_clip_path) { |
80 | - DocumentUndo::done(doc, SP_VERB_OBJECT_SET_CLIPPATH, _("Set clipping path")); |
81 | - } else { |
82 | - DocumentUndo::done(doc, SP_VERB_OBJECT_SET_MASK, _("Set mask")); |
83 | + if (!skip_undo) { |
84 | + if (apply_clip_path) { |
85 | + DocumentUndo::done(doc, SP_VERB_OBJECT_SET_CLIPPATH, _("Set clipping path")); |
86 | + } else { |
87 | + DocumentUndo::done(doc, SP_VERB_OBJECT_SET_MASK, _("Set mask")); |
88 | + } |
89 | } |
90 | } |
91 | |
92 | |
93 | === modified file 'src/selection-chemistry.h' |
94 | --- src/selection-chemistry.h 2016-07-27 10:19:03 +0000 |
95 | +++ src/selection-chemistry.h 2016-10-02 22:45:50 +0000 |
96 | @@ -85,9 +85,9 @@ |
97 | void sp_object_set_lower_to_bottom(Inkscape::ObjectSet *set); |
98 | |
99 | void sp_selection_raise(Inkscape::Selection *selection, SPDesktop *desktop); |
100 | -void sp_selection_raise_to_top(Inkscape::Selection *selection, SPDesktop *desktop); |
101 | +void sp_selection_raise_to_top(Inkscape::Selection *selection, SPDesktop *desktop, bool skip_undo = false); |
102 | void sp_selection_lower(Inkscape::Selection *selection, SPDesktop *desktop); |
103 | -void sp_selection_lower_to_bottom(Inkscape::Selection *selection, SPDesktop *desktop); |
104 | +void sp_selection_lower_to_bottom(Inkscape::Selection *selection, SPDesktop *desktop, bool skip_undo = false); |
105 | |
106 | SPCSSAttr *take_style_from_item (SPObject *object); |
107 | |
108 | @@ -164,7 +164,7 @@ |
109 | void sp_selection_create_bitmap_copy (SPDesktop *desktop); |
110 | |
111 | void sp_selection_set_clipgroup(SPDesktop *desktop); |
112 | -void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_layer); |
113 | +void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_layer, bool skip_undo = false); |
114 | void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path); |
115 | |
116 | bool fit_canvas_to_selection(SPDesktop *, bool with_margins = false); |
117 | |
118 | === modified file 'src/sp-lpe-item.cpp' |
119 | --- src/sp-lpe-item.cpp 2016-09-04 09:22:09 +0000 |
120 | +++ src/sp-lpe-item.cpp 2016-10-02 22:45:50 +0000 |
121 | @@ -337,10 +337,10 @@ |
122 | { |
123 | sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(mask->firstChild())); |
124 | } |
125 | - SPClipPath * clipPath = lpeitem->clip_ref->getObject(); |
126 | - if(clipPath) |
127 | + SPClipPath * clip_path = lpeitem->clip_ref->getObject(); |
128 | + if(clip_path) |
129 | { |
130 | - sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(clipPath->firstChild())); |
131 | + sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild())); |
132 | } |
133 | if (SP_IS_GROUP(lpeitem)) { |
134 | std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(lpeitem)); |
135 | @@ -371,10 +371,10 @@ |
136 | { |
137 | sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild())); |
138 | } |
139 | - SPClipPath * clipPath = lpeitem->clip_ref->getObject(); |
140 | - if(clipPath) |
141 | + SPClipPath * clip_path = lpeitem->clip_ref->getObject(); |
142 | + if(clip_path) |
143 | { |
144 | - sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clipPath->firstChild())); |
145 | + sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild())); |
146 | } |
147 | } |
148 | std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(lpeitem)); |
149 | @@ -393,10 +393,10 @@ |
150 | { |
151 | sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild())); |
152 | } |
153 | - SPClipPath * clipPath = lpeitem->clip_ref->getObject(); |
154 | - if(clipPath) |
155 | + SPClipPath * clip_path = lpeitem->clip_ref->getObject(); |
156 | + if(clip_path) |
157 | { |
158 | - sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clipPath->firstChild())); |
159 | + sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild())); |
160 | } |
161 | repr->setAttribute("d", repr->attribute("inkscape:original-d")); |
162 | repr->setAttribute("inkscape:original-d", NULL); |
163 | @@ -628,10 +628,13 @@ |
164 | void |
165 | SPLPEItem::apply_to_clippath(SPItem *item) |
166 | { |
167 | - SPClipPath *clipPath = item->clip_ref->getObject(); |
168 | - if(clipPath) { |
169 | - SPObject * clip_data = clipPath->firstChild(); |
170 | - apply_to_clip_or_mask(SP_ITEM(clip_data), item); |
171 | + SPClipPath *clip_path = item->clip_ref->getObject(); |
172 | + if(clip_path) { |
173 | + std::vector<SPObject*> clip_path_list = clip_path->childList(true); |
174 | + for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) { |
175 | + SPObject * clip_data = *iter; |
176 | + apply_to_clip_or_mask(SP_ITEM(clip_data), item); |
177 | + } |
178 | } |
179 | if(SP_IS_GROUP(item)){ |
180 | std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(item)); |
181 | @@ -647,8 +650,11 @@ |
182 | { |
183 | SPMask *mask = item->mask_ref->getObject(); |
184 | if(mask) { |
185 | - SPObject *mask_data = mask->firstChild(); |
186 | - apply_to_clip_or_mask(SP_ITEM(mask_data), item); |
187 | + std::vector<SPObject*> mask_list = mask->childList(true); |
188 | + for ( std::vector<SPObject*>::const_iterator iter=mask_list.begin();iter!=mask_list.end();++iter) { |
189 | + SPObject * mask_data = *iter; |
190 | + apply_to_clip_or_mask(SP_ITEM(mask_data), item); |
191 | + } |
192 | } |
193 | if(SP_IS_GROUP(item)){ |
194 | std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(item)); |
195 | |
196 | === modified file 'src/ui/tools/eraser-tool.cpp' |
197 | --- src/ui/tools/eraser-tool.cpp 2016-08-29 20:39:07 +0000 |
198 | +++ src/ui/tools/eraser-tool.cpp 2016-10-02 22:45:50 +0000 |
199 | @@ -51,15 +51,21 @@ |
200 | #include "sp-item-group.h" |
201 | #include "sp-shape.h" |
202 | #include "sp-path.h" |
203 | +#include "sp-clippath.h" |
204 | +#include "sp-rect.h" |
205 | #include "sp-text.h" |
206 | +#include "sp-root.h" |
207 | +#include "display/canvas-bpath.h" |
208 | #include "display/canvas-arena.h" |
209 | #include "document-undo.h" |
210 | #include "verbs.h" |
211 | #include "style.h" |
212 | #include <2geom/pathvector.h> |
213 | #include "path-chemistry.h" |
214 | +#include "selection-chemistry.h" |
215 | #include "display/curve.h" |
216 | - |
217 | +#include "layer-model.h" |
218 | +#include "layer-manager.h" |
219 | #include "ui/tools/eraser-tool.h" |
220 | |
221 | using Inkscape::DocumentUndo; |
222 | @@ -369,7 +375,7 @@ |
223 | bool EraserTool::root_handler(GdkEvent* event) { |
224 | gint ret = FALSE; |
225 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
226 | - gint eraserMode = prefs->getBool("/tools/eraser/mode") ? 1 : 0; |
227 | + gint eraser_mode = prefs->getInt("/tools/eraser/mode", 2); |
228 | switch (event->type) { |
229 | case GDK_BUTTON_PRESS: |
230 | if (event->button.button == 1 && !this->space_panning) { |
231 | @@ -389,7 +395,7 @@ |
232 | if (this->repr) { |
233 | this->repr = NULL; |
234 | } |
235 | - if ( ! eraserMode ) { |
236 | + if ( eraser_mode == 0 ) { |
237 | Inkscape::Rubberband::get(desktop)->start(desktop, button_dt); |
238 | Inkscape::Rubberband::get(desktop)->setMode(RUBBERBAND_MODE_TOUCHPATH); |
239 | } |
240 | @@ -437,7 +443,7 @@ |
241 | |
242 | ret = TRUE; |
243 | } |
244 | - if ( !eraserMode ) { |
245 | + if ( eraser_mode == 0 ) { |
246 | this->accumulated->reset(); |
247 | Inkscape::Rubberband::get(desktop)->move(motion_dt); |
248 | } |
249 | @@ -480,7 +486,7 @@ |
250 | ret = TRUE; |
251 | } |
252 | |
253 | - if (!eraserMode && Inkscape::Rubberband::get(desktop)->is_started()) { |
254 | + if (eraser_mode == 0 && Inkscape::Rubberband::get(desktop)->is_started()) { |
255 | Inkscape::Rubberband::get(desktop)->stop(); |
256 | } |
257 | |
258 | @@ -567,7 +573,7 @@ |
259 | break; |
260 | |
261 | case GDK_KEY_Escape: |
262 | - if ( !eraserMode ) { |
263 | + if ( eraser_mode == 0 ) { |
264 | Inkscape::Rubberband::get(desktop)->stop(); |
265 | } |
266 | if (this->is_drawing) { |
267 | @@ -629,52 +635,54 @@ |
268 | |
269 | void EraserTool::set_to_accumulated() { |
270 | bool workDone = false; |
271 | - |
272 | + SPDocument *document = this->desktop->doc(); |
273 | if (!this->accumulated->is_empty()) { |
274 | if (!this->repr) { |
275 | /* Create object */ |
276 | - Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); |
277 | + Inkscape::XML::Document *xml_doc = this->desktop->doc()->getReprDoc(); |
278 | Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); |
279 | |
280 | /* Set style */ |
281 | - sp_desktop_apply_style_tool (desktop, repr, "/tools/eraser", false); |
282 | + sp_desktop_apply_style_tool (this->desktop, repr, "/tools/eraser", false); |
283 | |
284 | this->repr = repr; |
285 | } |
286 | - SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(this->repr)); |
287 | + SPObject * top_layer = desktop->layer_manager->nthChildOf(desktop->layers->currentRoot(), 0); |
288 | + SPItem *item_repr = SP_ITEM(top_layer->appendChildRepr(this->repr)); |
289 | + std::cout << "asffafa\n"; |
290 | Inkscape::GC::release(this->repr); |
291 | - item->updateRepr(); |
292 | - Geom::PathVector pathv = this->accumulated->get_pathvector() * desktop->dt2doc(); |
293 | - pathv *= item->i2doc_affine().inverse(); |
294 | + item_repr->updateRepr(); |
295 | + Geom::PathVector pathv = this->accumulated->get_pathvector() * this->desktop->dt2doc(); |
296 | + pathv *= item_repr->i2doc_affine().inverse(); |
297 | gchar *str = sp_svg_write_path(pathv); |
298 | g_assert( str != NULL ); |
299 | this->repr->setAttribute("d", str); |
300 | g_free(str); |
301 | - |
302 | + Geom::OptRect eraserBbox; |
303 | if ( this->repr ) { |
304 | bool wasSelection = false; |
305 | - Inkscape::Selection *selection = desktop->getSelection(); |
306 | + Inkscape::Selection *selection = this->desktop->getSelection(); |
307 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
308 | - gint eraserMode = prefs->getBool("/tools/eraser/mode") ? 1 : 0; |
309 | - Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); |
310 | + gint eraser_mode = prefs->getInt("/tools/eraser/mode", 2); |
311 | + Inkscape::XML::Document *xml_doc = this->desktop->doc()->getReprDoc(); |
312 | |
313 | - SPItem* acid = SP_ITEM(desktop->doc()->getObjectByRepr(this->repr)); |
314 | - Geom::OptRect eraserBbox = acid->desktopVisualBounds(); |
315 | + SPItem* acid = SP_ITEM(this->desktop->doc()->getObjectByRepr(this->repr)); |
316 | + eraserBbox = acid->desktopVisualBounds(); |
317 | std::vector<SPItem*> remainingItems; |
318 | std::vector<SPItem*> toWorkOn; |
319 | if (selection->isEmpty()) { |
320 | - if ( eraserMode ) { |
321 | - toWorkOn = desktop->getDocument()->getItemsPartiallyInBox(desktop->dkey, *eraserBbox); |
322 | + if ( eraser_mode == 1 || eraser_mode == 2) { |
323 | + toWorkOn = document->getItemsPartiallyInBox(this->desktop->dkey, *eraserBbox); |
324 | } else { |
325 | - Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop); |
326 | - toWorkOn = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints()); |
327 | + Inkscape::Rubberband *r = Inkscape::Rubberband::get(this->desktop); |
328 | + toWorkOn = document->getItemsAtPoints(this->desktop->dkey, r->getPoints()); |
329 | } |
330 | toWorkOn.erase(std::remove(toWorkOn.begin(), toWorkOn.end(), acid), toWorkOn.end()); |
331 | } else { |
332 | - if ( !eraserMode ) { |
333 | - Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop); |
334 | + if ( eraser_mode == 0 ) { |
335 | + Inkscape::Rubberband *r = Inkscape::Rubberband::get(this->desktop); |
336 | std::vector<SPItem*> touched; |
337 | - touched = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints()); |
338 | + touched = document->getItemsAtPoints(this->desktop->dkey, r->getPoints()); |
339 | for (std::vector<SPItem*>::const_iterator i = touched.begin();i!=touched.end();++i) { |
340 | if(selection->includes(*i)){ |
341 | toWorkOn.push_back((*i)); |
342 | @@ -687,7 +695,7 @@ |
343 | } |
344 | |
345 | if ( !toWorkOn.empty() ) { |
346 | - if ( eraserMode ) { |
347 | + if ( eraser_mode == 1 ) { |
348 | for (std::vector<SPItem*>::const_iterator i = toWorkOn.begin(); i != toWorkOn.end(); ++i){ |
349 | SPItem *item = *i; |
350 | SPUse *use = dynamic_cast<SPUse *>(item); |
351 | @@ -713,7 +721,7 @@ |
352 | if(item->style->fill_rule.value == SP_WIND_RULE_EVENODD){ |
353 | SPCSSAttr *css = sp_repr_css_attr_new(); |
354 | sp_repr_css_set_property(css, "fill-rule", "evenodd"); |
355 | - sp_desktop_set_style(desktop, css); |
356 | + sp_desktop_set_style(this->desktop, css); |
357 | sp_repr_css_attr_unref(css); |
358 | css = 0; |
359 | } |
360 | @@ -725,10 +733,10 @@ |
361 | workDone = true; // TODO set this only if something was cut. |
362 | bool break_apart = prefs->getBool("/tools/eraser/break_apart", false); |
363 | if(!break_apart){ |
364 | - sp_selected_path_combine(desktop, true); |
365 | + sp_selected_path_combine(this->desktop, true); |
366 | } else { |
367 | if(!this->nowidth){ |
368 | - sp_selected_path_break_apart(desktop, true); |
369 | + sp_selected_path_break_apart(this->desktop, true); |
370 | } |
371 | } |
372 | if ( !selection->isEmpty() ) { |
373 | @@ -743,6 +751,70 @@ |
374 | } |
375 | } |
376 | } |
377 | + } else if ( eraser_mode == 2 ) { |
378 | + if (!this->nowidth) { |
379 | + remainingItems.clear(); |
380 | + for (std::vector<SPItem*>::const_iterator i = toWorkOn.begin(); i != toWorkOn.end(); ++i){ |
381 | + selection->clear(); |
382 | + SPItem *item = *i; |
383 | + Geom::OptRect bbox = item->desktopVisualBounds(); |
384 | + Inkscape::XML::Document *xml_doc = this->desktop->doc()->getReprDoc(); |
385 | + Inkscape::XML::Node* dup = this->repr->duplicate(xml_doc); |
386 | + this->repr->parent()->appendChild(dup); |
387 | + Inkscape::GC::release(dup); // parent takes over |
388 | + selection->set(dup); |
389 | + sp_selected_path_union_skip_undo(selection); |
390 | + if (bbox && bbox->intersects(*eraserBbox)) { |
391 | + SPClipPath *clip_path = item->clip_ref->getObject(); |
392 | + if (clip_path) { |
393 | + SPPath *clip_data = SP_PATH(clip_path->firstChild()); |
394 | + if (clip_data) { |
395 | + Inkscape::XML::Node *dup_clip = SP_OBJECT(clip_data)->getRepr()->duplicate(xml_doc); |
396 | + if (dup_clip) { |
397 | + SPItem * dup_clip_obj = SP_ITEM(item_repr->parent->appendChildRepr(dup_clip)); |
398 | + if (dup_clip_obj) { |
399 | + dup_clip_obj->doWriteTransform(dup_clip, item->transform); |
400 | + sp_object_ref(clip_path, 0); |
401 | + clip_path->deleteObject(true); |
402 | + sp_object_unref(clip_path); |
403 | + sp_selection_raise_to_top(selection, this->desktop, true); |
404 | + selection->add(dup_clip); |
405 | + sp_selected_path_diff_skip_undo(selection); |
406 | + SPItem * clip = SP_ITEM(*(selection->items().begin())); |
407 | + } |
408 | + } |
409 | + } |
410 | + } else { |
411 | + Inkscape::XML::Node *rect_repr = xml_doc->createElement("svg:rect"); |
412 | + sp_desktop_apply_style_tool (this->desktop, rect_repr, "/tools/eraser", false); |
413 | + SPRect * rect = SP_RECT(item_repr->parent->appendChildRepr(rect_repr)); |
414 | + Inkscape::GC::release(rect_repr); |
415 | + rect->setPosition (bbox->left(), bbox->top(), bbox->width(), bbox->height()); |
416 | + rect->transform = SP_ITEM(rect->parent)->i2dt_affine().inverse(); |
417 | + rect->updateRepr(); |
418 | + rect->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); |
419 | + sp_selection_raise_to_top(selection, this->desktop, true); |
420 | + selection->add(rect); |
421 | + sp_selected_path_diff_skip_undo(selection); |
422 | + } |
423 | + sp_selection_raise_to_top(selection, this->desktop, true); |
424 | + selection->add(item); |
425 | + sp_selection_set_mask(this->desktop, true, false, true); |
426 | + } else { |
427 | + SPItem *erase_clip = selection->singleItem(); |
428 | + if (erase_clip) { |
429 | + sp_object_ref(erase_clip, 0); |
430 | + erase_clip->deleteObject(true); |
431 | + sp_object_unref(erase_clip); |
432 | + } |
433 | + } |
434 | + workDone = true; |
435 | + selection->clear(); |
436 | + if (wasSelection) { |
437 | + remainingItems.push_back(item); |
438 | + } |
439 | + } |
440 | + } |
441 | } else { |
442 | for (std::vector<SPItem*> ::const_iterator i = toWorkOn.begin();i!=toWorkOn.end();++i) { |
443 | sp_object_ref( *i, 0 ); |
444 | @@ -756,8 +828,8 @@ |
445 | } |
446 | } |
447 | |
448 | - if ( !eraserMode ) { |
449 | - //sp_selection_delete(desktop); |
450 | + if ( eraser_mode == 0 ) { |
451 | + sp_selection_delete(this->desktop); |
452 | remainingItems.clear(); |
453 | } |
454 | |
455 | @@ -779,12 +851,10 @@ |
456 | this->repr = 0; |
457 | } |
458 | } |
459 | - |
460 | - |
461 | if ( workDone ) { |
462 | - DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_ERASER, _("Draw eraser stroke")); |
463 | + DocumentUndo::done(document, SP_VERB_CONTEXT_ERASER, _("Draw eraser stroke")); |
464 | } else { |
465 | - DocumentUndo::cancel(desktop->getDocument()); |
466 | + DocumentUndo::cancel(document); |
467 | } |
468 | } |
469 | |
470 | @@ -975,7 +1045,7 @@ |
471 | g_print("[%d]Yup\n", this->npoints); |
472 | #endif |
473 | if (!release) { |
474 | - gint eraserMode = prefs->getBool("/tools/eraser/mode") ? 1 : 0; |
475 | + gint eraser_mode = prefs->getInt("/tools/eraser/mode",2); |
476 | g_assert(!this->currentcurve->is_empty()); |
477 | |
478 | SPCanvasItem *cbp = sp_canvas_item_new(desktop->getSketch(), SP_TYPE_CANVAS_BPATH, NULL); |
479 | @@ -997,7 +1067,7 @@ |
480 | |
481 | this->segments = g_slist_prepend(this->segments, cbp); |
482 | |
483 | - if ( !eraserMode ) { |
484 | + if ( eraser_mode == 0 ) { |
485 | sp_canvas_item_hide(cbp); |
486 | sp_canvas_item_hide(this->currentshape); |
487 | } |
488 | |
489 | === modified file 'src/widgets/eraser-toolbar.cpp' |
490 | --- src/widgets/eraser-toolbar.cpp 2016-08-05 18:07:48 +0000 |
491 | +++ src/widgets/eraser-toolbar.cpp 2016-10-02 22:45:50 +0000 |
492 | @@ -65,22 +65,60 @@ |
493 | update_presets_list(tbl); |
494 | } |
495 | |
496 | +static void sp_erc_velthin_value_changed( GtkAdjustment *adj, GObject* tbl ) |
497 | +{ |
498 | + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
499 | + prefs->setDouble("/tools/eraser/thinning", gtk_adjustment_get_value(adj) ); |
500 | + update_presets_list(tbl); |
501 | +} |
502 | + |
503 | +static void sp_erc_cap_rounding_value_changed( GtkAdjustment *adj, GObject* tbl ) |
504 | +{ |
505 | + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
506 | + prefs->setDouble( "/tools/eraser/cap_rounding", gtk_adjustment_get_value(adj) ); |
507 | + update_presets_list(tbl); |
508 | +} |
509 | + |
510 | +static void sp_erc_tremor_value_changed( GtkAdjustment *adj, GObject* tbl ) |
511 | +{ |
512 | + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
513 | + prefs->setDouble( "/tools/eraser/tremor", gtk_adjustment_get_value(adj) ); |
514 | + update_presets_list(tbl); |
515 | +} |
516 | + |
517 | + |
518 | static void sp_erasertb_mode_changed( EgeSelectOneAction *act, GObject *tbl ) |
519 | { |
520 | SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data( tbl, "desktop" )); |
521 | - bool eraserMode = ege_select_one_action_get_active( act ) != 0; |
522 | + guint eraser_mode = ege_select_one_action_get_active( act ); |
523 | if (DocumentUndo::getUndoSensitive(desktop->getDocument())) { |
524 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
525 | - prefs->setBool( "/tools/eraser/mode", eraserMode ); |
526 | + prefs->setInt( "/tools/eraser/mode", eraser_mode ); |
527 | } |
528 | GtkAction *split = GTK_ACTION( g_object_get_data(tbl, "split") ); |
529 | GtkAction *mass = GTK_ACTION( g_object_get_data(tbl, "mass") ); |
530 | GtkAction *width = GTK_ACTION( g_object_get_data(tbl, "width") ); |
531 | - if(eraserMode == TRUE){ |
532 | - gtk_action_set_visible( split, TRUE ); |
533 | + GtkAction *usepressure = GTK_ACTION( g_object_get_data(tbl, "usepressure") ); |
534 | + GtkAction *cap_rounding = GTK_ACTION( g_object_get_data(tbl, "cap_rounding") ); |
535 | + GtkAction *thinning = GTK_ACTION( g_object_get_data(tbl, "thinning") ); |
536 | + GtkAction *tremor = GTK_ACTION( g_object_get_data(tbl, "tremor") ); |
537 | + if (eraser_mode != 0) { |
538 | + if(eraser_mode == 1) { |
539 | + gtk_action_set_visible( split, TRUE ); |
540 | + } else { |
541 | + gtk_action_set_visible( split, FALSE ); |
542 | + } |
543 | + gtk_action_set_visible(usepressure, TRUE ); |
544 | + gtk_action_set_visible(tremor, TRUE ); |
545 | + gtk_action_set_visible(cap_rounding, TRUE ); |
546 | + gtk_action_set_visible(thinning, TRUE ); |
547 | gtk_action_set_visible( mass, TRUE ); |
548 | gtk_action_set_visible( width, TRUE ); |
549 | } else { |
550 | + gtk_action_set_visible(usepressure, FALSE ); |
551 | + gtk_action_set_visible(tremor, FALSE ); |
552 | + gtk_action_set_visible(cap_rounding, FALSE ); |
553 | + gtk_action_set_visible(thinning, FALSE ); |
554 | gtk_action_set_visible( split, FALSE ); |
555 | gtk_action_set_visible( mass, FALSE ); |
556 | gtk_action_set_visible( width, FALSE ); |
557 | @@ -91,7 +129,7 @@ |
558 | g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); |
559 | |
560 | /* |
561 | - if ( eraserMode != 0 ) { |
562 | + if ( eraser_mode != 0 ) { |
563 | } else { |
564 | } |
565 | */ |
566 | @@ -112,7 +150,7 @@ |
567 | { |
568 | Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1); |
569 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
570 | - gint eraserMode = FALSE; |
571 | + gint eraser_mode = FALSE; |
572 | { |
573 | GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); |
574 | GtkTreeIter iter; |
575 | @@ -126,10 +164,17 @@ |
576 | gtk_list_store_append( model, &iter ); |
577 | gtk_list_store_set( model, &iter, |
578 | 0, _("Cut"), |
579 | - 1, _("Cut out from objects"), |
580 | + 1, _("Cut out from paths and shapes"), |
581 | 2, INKSCAPE_ICON("path-difference"), |
582 | -1 ); |
583 | |
584 | + gtk_list_store_append( model, &iter ); |
585 | + gtk_list_store_set( model, &iter, |
586 | + 0, _("Clip"), |
587 | + 1, _("Clip from objects"), |
588 | + 2, INKSCAPE_ICON("path-intersection"), |
589 | + -1 ); |
590 | + |
591 | EgeSelectOneAction* act = ege_select_one_action_new( "EraserModeAction", (""), (""), NULL, GTK_TREE_MODEL(model) ); |
592 | g_object_set( act, "short_label", _("Mode:"), NULL ); |
593 | gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); |
594 | @@ -138,12 +183,13 @@ |
595 | ege_select_one_action_set_appearance( act, "full" ); |
596 | ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE ); |
597 | g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL ); |
598 | - ege_select_one_action_set_icon_column( act, 2 ); |
599 | - ege_select_one_action_set_tooltip_column( act, 1 ); |
600 | + ege_select_one_action_set_icon_column( act, 2); |
601 | + ege_select_one_action_set_icon_size( act, secondarySize ); |
602 | + ege_select_one_action_set_tooltip_column( act, 1); |
603 | |
604 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
605 | - eraserMode = prefs->getBool("/tools/eraser/mode") ? TRUE : FALSE; |
606 | - ege_select_one_action_set_active( act, eraserMode ); |
607 | + eraser_mode = prefs->getInt("/tools/eraser/mode", 2); |
608 | + ege_select_one_action_set_active( act, eraser_mode ); |
609 | g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_erasertb_mode_changed), holder ); |
610 | } |
611 | |
612 | @@ -164,6 +210,71 @@ |
613 | g_object_set_data( holder, "width", eact ); |
614 | gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); |
615 | } |
616 | + /* Use Pressure button */ |
617 | + { |
618 | + InkToggleAction* act = ink_toggle_action_new( "EraserPressureAction", |
619 | + _("Eraser Pressure"), |
620 | + _("Use the pressure of the input device to alter the width of the pen"), |
621 | + INKSCAPE_ICON("draw-use-pressure"), |
622 | + Inkscape::ICON_SIZE_DECORATION ); |
623 | + gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); |
624 | + PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/eraser/usepressure", update_presets_list, holder); |
625 | + g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher); |
626 | + g_object_set_data( holder, "usepressure", act ); |
627 | + } |
628 | + { |
629 | + |
630 | + /* Thinning */ |
631 | + gchar const* labels[] = {_("(speed blows up stroke)"), 0, 0, _("(slight widening)"), _("(constant width)"), _("(slight thinning, default)"), 0, 0, _("(speed deflates stroke)")}; |
632 | + gdouble values[] = {-100, -40, -20, -10, 0, 10, 20, 40, 100}; |
633 | + EgeAdjustmentAction* eact = create_adjustment_action( "EraserThinningAction", |
634 | + _("Eraser Stroke Thinning"), _("Thinning:"), |
635 | + _("How much velocity thins the stroke (> 0 makes fast strokes thinner, < 0 makes them broader, 0 makes width independent of velocity)"), |
636 | + "/tools/eraser/thinning", 10, |
637 | + GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, |
638 | + -100, 100, 1, 10.0, |
639 | + labels, values, G_N_ELEMENTS(labels), |
640 | + sp_erc_velthin_value_changed, NULL /*unit tracker*/, 1, 0); |
641 | + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); |
642 | + g_object_set_data( holder, "thinning", eact ); |
643 | + gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); |
644 | + } |
645 | + { |
646 | + /* Cap Rounding */ |
647 | + gchar const* labels[] = {_("(blunt caps, default)"), _("(slightly bulging)"), 0, 0, _("(approximately round)"), _("(long protruding caps)")}; |
648 | + gdouble values[] = {0, 0.3, 0.5, 1.0, 1.4, 5.0}; |
649 | + // TRANSLATORS: "cap" means "end" (both start and finish) here |
650 | + EgeAdjustmentAction* eact = create_adjustment_action( "EraserCapRoundingAction", |
651 | + _("Eraser Cap rounding"), _("Caps:"), |
652 | + _("Increase to make caps at the ends of strokes protrude more (0 = no caps, 1 = round caps)"), |
653 | + "/tools/eraser/cap_rounding", 0.0, |
654 | + GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, |
655 | + 0.0, 5.0, 0.01, 0.1, |
656 | + labels, values, G_N_ELEMENTS(labels), |
657 | + sp_erc_cap_rounding_value_changed, NULL /*unit tracker*/, 0.01, 2 ); |
658 | + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); |
659 | + g_object_set_data( holder, "cap_rounding", eact ); |
660 | + gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); |
661 | + } |
662 | + |
663 | + { |
664 | + /* Tremor */ |
665 | + gchar const* labels[] = {_("(smooth line)"), _("(slight tremor)"), _("(noticeable tremor)"), 0, 0, _("(maximum tremor)")}; |
666 | + gdouble values[] = {0, 10, 20, 40, 60, 100}; |
667 | + EgeAdjustmentAction* eact = create_adjustment_action( "EraserTremorAction", |
668 | + _("EraserStroke Tremor"), _("Tremor:"), |
669 | + _("Increase to make strokes rugged and trembling"), |
670 | + "/tools/eraser/tremor", 0.0, |
671 | + GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, |
672 | + 0.0, 100, 1, 10.0, |
673 | + labels, values, G_N_ELEMENTS(labels), |
674 | + sp_erc_tremor_value_changed, NULL /*unit tracker*/, 1, 0); |
675 | + |
676 | + ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT ); |
677 | + g_object_set_data( holder, "tremor", eact ); |
678 | + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); |
679 | + gtk_action_set_sensitive( GTK_ACTION(eact), TRUE ); |
680 | + } |
681 | { |
682 | /* Mass */ |
683 | gchar const* labels[] = {_("(no inertia)"), _("(slight smoothing, default)"), _("(noticeable lagging)"), 0, 0, _("(maximum inertia)")}; |
684 | @@ -196,11 +307,27 @@ |
685 | GtkAction *split = GTK_ACTION( g_object_get_data(holder, "split") ); |
686 | GtkAction *mass = GTK_ACTION( g_object_get_data(holder, "mass") ); |
687 | GtkAction *width = GTK_ACTION( g_object_get_data(holder, "width") ); |
688 | - if(eraserMode == TRUE){ |
689 | - gtk_action_set_visible( split, TRUE ); |
690 | + GtkAction *usepressure = GTK_ACTION( g_object_get_data(holder, "usepressure") ); |
691 | + GtkAction *cap_rounding = GTK_ACTION( g_object_get_data(holder, "cap_rounding") ); |
692 | + GtkAction *thinning = GTK_ACTION( g_object_get_data(holder, "thinning") ); |
693 | + GtkAction *tremor = GTK_ACTION( g_object_get_data(holder, "tremor") ); |
694 | + if (eraser_mode != 0) { |
695 | + if(eraser_mode == 1) { |
696 | + gtk_action_set_visible( split, TRUE ); |
697 | + } else { |
698 | + gtk_action_set_visible( split, FALSE ); |
699 | + } |
700 | + gtk_action_set_visible(usepressure, TRUE ); |
701 | + gtk_action_set_visible(tremor, TRUE ); |
702 | + gtk_action_set_visible(cap_rounding, TRUE ); |
703 | + gtk_action_set_visible(thinning, TRUE ); |
704 | gtk_action_set_visible( mass, TRUE ); |
705 | gtk_action_set_visible( width, TRUE ); |
706 | } else { |
707 | + gtk_action_set_visible(usepressure, FALSE ); |
708 | + gtk_action_set_visible(tremor, FALSE ); |
709 | + gtk_action_set_visible(cap_rounding, FALSE ); |
710 | + gtk_action_set_visible(thinning, FALSE ); |
711 | gtk_action_set_visible( split, FALSE ); |
712 | gtk_action_set_visible( mass, FALSE ); |
713 | gtk_action_set_visible( width, FALSE ); |
714 | |
715 | === modified file 'src/widgets/toolbox.cpp' |
716 | --- src/widgets/toolbox.cpp 2016-08-05 18:07:48 +0000 |
717 | +++ src/widgets/toolbox.cpp 2016-10-02 22:45:50 +0000 |
718 | @@ -493,6 +493,13 @@ |
719 | " <toolitem action='EraserModeAction' />" |
720 | " <separator />" |
721 | " <toolitem action='EraserWidthAction' />" |
722 | + " <toolitem action='EraserPressureAction' />" |
723 | + " <separator />" |
724 | + " <toolitem action='EraserThinningAction' />" |
725 | + " <separator />" |
726 | + " <toolitem action='EraserCapRoundingAction' />" |
727 | + " <separator />" |
728 | + " <toolitem action='EraserTremorAction' />" |
729 | " <separator />" |
730 | " <toolitem action='EraserMassAction' />" |
731 | " <separator />" |
The new feature works really well, the code increases the complexity of the eraser, but that was to be expected with the clipping process.
Approved and merged.