27#include <boost/range/adaptor/reversed.hpp>
29#include <glibmm/i18n.h>
129 g_printerr(
"%s\n",
msg.c_str());
238 std::vector<SPItem*>
items;
240 auto selList = selection->
items();
242 for (
auto item : selList | boost::adaptors::reversed) {
280 std::vector<SPItem*> sorted_items(
items);
284 for (
auto item : sorted_items) {
288 g_assert_not_reached();
296 std::vector<Inkscape::XML::Node *> &
clip,
299 assert(!after || after->parent() ==
parent->getRepr());
304 auto parentItem = cast<SPItem>(
parent);
305 g_assert(parentItem);
307 std::vector<Inkscape::XML::Node*> copied;
309 for (
auto repr :
clip) {
313 auto const local = parentItem->i2doc_affine();
314 if (!local.isIdentity()) {
315 char const *t_str = copy->attribute(
"transform");
323 if (copy->attribute(
"inkscape:original-d")) {
324 copy->setAttribute(
"d", copy->attribute(
"inkscape:original-d"));
328 parent->getRepr()->addChild(copy, after);
331 copied.push_back(copy);
355 std::vector<SPItem*> selected(
items().begin(),
items().
end());
364 dt->layerManager().currentLayer()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
373 dt->setTool(std::string{dt->getTool()->getPrefsPath()});
386 ids.push_back(obj->
getId());
388 if (is<SPGroup>(obj)) {
398 if(duplicateLayer && !
desktop() ){
411 if (
isEmpty() && !duplicateLayer) {
419 reprs.push_back(
desktop()->layerManager().currentLayer()->getRepr());
424 std::vector<SPItem *>
items;
425 for(
auto old_repr : reprs) {
429 auto lpeitem = cast<SPLPEItem>(
item);
431 for (
auto satellite : lpeitem->get_satellites(
false,
true,
true)) {
433 auto item2 = cast<SPItem>(satellite);
434 if (item2 && std::find(
items.begin(),
items.end(), item2) ==
items.end()) {
435 items.push_back(item2);
443 if (std::find(reprs.begin(), reprs.end(),
item->
getRepr()) == reprs.end()) {
451 std::vector<const gchar *> old_ids;
452 std::vector<const gchar *> new_ids;
454 bool relink_clones = prefs->
getBool(
"/options/relinkclonesonduplicate/value");
455 const bool fork_livepatheffects = prefs->
getBool(
"/options/forklpeonduplicate/value",
true);
461 for (
auto const &
ref : text_refs) {
467 std::vector<Inkscape::XML::Node*> copies;
468 for(
auto old_repr : reprs) {
480 copies[0]->appendChild(
copy);
484 if (old_obj && new_obj) {
492 copies.push_back(
copy);
500 std::vector<Inkscape::XML::Node*> newsel;
501 if (!duplicateLayer) {
503 for (
auto node : copies) {
510 newsel.push_back(
node);
517 g_assert(old_ids.size() == new_ids.size());
519 for (
unsigned int i = 0; i < old_ids.size(); i++) {
520 const gchar *
id = old_ids[i];
522 auto use = cast<SPUse>(old_clone);
523 auto offset = cast<SPOffset>(old_clone);
524 auto text = cast<SPText>(old_clone);
525 auto path = cast<SPPath>(old_clone);
530 for (
unsigned int j = 0; j < old_ids.size(); j++) {
531 if (!strcmp(
orig->getId(), old_ids[j])) {
535 new_clone->setAttribute(
"xlink:href", Glib::ustring(
"#") + new_ids[j]);
536 new_clone->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
540 gchar *source_href =
offset->sourceHref;
541 for (guint j = 0; j < old_ids.size(); j++) {
542 if (source_href && source_href[0]==
'#' && !strcmp(source_href+1, old_ids[j])) {
547 auto textpath = cast<SPTextPath>(text->firstChild());
548 if (!textpath)
continue;
550 for (guint j = 0; j < old_ids.size(); j++) {
551 if (!strcmp(source_href, old_ids[j])) {
556 if (old_clone->
getAttribute(
"inkscape:connection-start") !=
nullptr) {
557 const char *old_start = old_clone->
getAttribute(
"inkscape:connection-start");
558 const char *old_end = old_clone->
getAttribute(
"inkscape:connection-end");
560 for (guint j = 0; j < old_ids.size(); j++) {
561 if(old_start == Glib::ustring(
"#") + old_ids[j]) {
562 new_clone->setAttribute(
"inkscape:connection-start", Glib::ustring(
"#") + new_ids[j]);
564 if(old_end == Glib::ustring(
"#") + old_ids[j]) {
565 new_clone->setAttribute(
"inkscape:connection-end", Glib::ustring(
"#") + new_ids[j]);
572 for (
auto node : copies) {
573 if (fork_livepatheffects) {
575 auto newLPEObj = cast<SPLPEItem>(new_obj);
578 newLPEObj->forkPathEffectsIfNecessary(1,
true,
true);
583 for(
auto old_repr : reprs) {
591 if (!duplicateLayer) {
593 if ( !suppressDone ) {
597 if ( !suppressDone ) {
603 if (std::string(
label).find(
"copy") == std::string::npos) {
604 gchar*
name = g_strdup_printf(_(
"%s copy"),
label);
623 g_return_if_fail(group);
624 std::vector<SPItem*>
items = group->item_list();
651 (exclude.empty() || std::find(exclude.begin(), exclude.end(), &
child) == exclude.end()))
653 list.emplace_back(
item);
664 std::vector<SPItem*> list;
666 std::reverse(list.begin(), list.end());
678 g_return_if_fail(layer);
682 bool onlyvisible = prefs->
getBool(
"/options/kbselection/onlyvisible",
true);
683 bool onlysensitive = prefs->
getBool(
"/options/kbselection/onlysensitive",
true);
685 std::vector<SPItem*>
items ;
687 std::vector<SPItem*> exclude;
689 exclude.insert(exclude.end(), selection->
items().begin(), selection->
items().end());
692 if (force_all_layers)
697 if ((onlysensitive && layer->isLocked()) || (onlyvisible && dt->
itemIsHidden(layer))) {
701 auto const item_list = layer->item_list();
702 for (
auto item : item_list | boost::adaptors::reversed) {
706 if (!
invert || exclude.end() == std::find(exclude.begin(),exclude.end(),
item)) {
770 if (
current->parent() == topmost_parent) {
780 if (
current->parent() == topmost_parent) {
788 std::vector<Inkscape::XML::Node*> temp_clip;
792 gchar
const *t_str =
current->attribute(
"transform");
798 item_t *= parent_item->i2doc_affine();
811 if (!temp_clip.empty())temp_clip.clear() ;
812 if (!copied.empty()) {
838 std::set<SPObject*> grandparents;
840 for (
auto *obj :
items()) {
841 auto parent_group = cast<SPGroup>(obj->parent);
842 if (!parent_group || !parent_group->parent ||
SP_IS_LAYER(parent_group)) {
846 grandparents.insert(parent_group->parent);
849 assert(!grandparents.empty());
851 if (grandparents.size() > 1) {
853 _(
"Objects in selection must have the same grandparents."));
857 toLayer(*grandparents.begin());
869template <
typename Objects>
872 assert(!groups.count(
nullptr));
874 for (
auto *obj : objects) {
875 if (
auto *use = cast<SPUse>(obj)) {
876 if (
auto root = use->root()) {
877 if (groups.count(cast_unsafe<SPGroup>(
root->clone_original))) {
902 std::set<SPGroup *>
const groups(
set->groups().begin(),
set->groups().end());
905 bool const readd =
set->includes(use);
906 auto const unlinked = use->unlink();
908 set->add(unlinked,
true);
912 std::vector<SPItem *> children;
914 for (
auto *group : groups) {
918 set->addList(children);
929 if (boost::distance(
groups()) == 0) {
945 std::size_t last = 0;
946 while (
size() != last) {
961 if (!is<SPGroup>(
parent)) {
973 return cast<SPGroup>(
parent);
980 g_assert(!
items.empty());
993 if (
child && cast<SPGroup>(
child->parent) ) {
1013 std::vector<SPItem*> items_copy(
items().begin(),
items().
end());
1017 std::vector<SPItem*> rev(items_copy);
1025 for (
auto child : rev) {
1029 auto newItem = cast<SPItem>(newref);
1031 Geom::OptRect newref_bbox = newItem->documentVisualBounds();
1032 if ( newref_bbox && selected->
intersects(*newref_bbox) ) {
1034 if ( std::find(items_copy.begin(),items_copy.end(),newref)==items_copy.end()) {
1065 for (
auto repr : rl) {
1066 repr->setPosition(-1);
1086 std::vector<SPItem*> items_copy(
items().begin(),
items().
end());
1093 std::vector<SPItem*> rev(items_copy);
1098 for (
auto child : rev | boost::adaptors::reversed) {
1102 auto newItem = cast<SPItem>(newref);
1105 if ( ref_bbox && selected->
intersects(*ref_bbox) ) {
1107 if (std::find(items_copy.begin(), items_copy.end(), newref) == items_copy.end()) {
1112 child->getRepr()->setPosition(0);
1143 for (
auto const repr : rl | boost::adaptors::reversed) {
1146 g_assert(is<SPGroup>(pp));
1147 for (
auto &pc : pp->children) {
1148 if (is<SPItem>(&pc)) {
1153 repr->setPosition(minpos);
1166 std::vector<SPItem*> selection(
items().begin(),
items().
end());
1169 for (
auto item : selection | boost::adaptors::reversed) {
1188 std::vector<SPItem*> selection(
items().begin(),
items().
end());
1191 for (
auto item: selection) {
1211 if (text_tool->deleteSelection()) {
1218 if (node_tool && node_tool->_selected_nodes) {
1243 if ((is<SPGroup>(
object) && object->
firstChild()) ||
1247 for (
auto &element :
object->children | boost::adaptors::reversed) {
1248 if (element.style) {
1261 if (!(is<SPText>(
object) || is<SPTSpan>(
object) || is<SPTRef>(
object) || is<SPString>(
object))) {
1267 auto item = cast<SPItem>(
object);
1312 if (
auto lpeitem = cast<SPLPEItem>(
item) ) {
1313 if ( lpeitem->hasPathEffect() ) {
1314 lpeitem->removeAllPathEffects(
false);
1329 for (
auto itemlist=list.begin();itemlist!=list.end();++itemlist) {
1359 auto list =
items();
1360 for (
auto itemlist=list.begin();itemlist!=list.end();++itemlist) {
1374 if (cm->
pasteSize(
this,
false, apply_x, apply_y)) {
1382 if (cm->
pasteSize(
this,
true, apply_x, apply_y)) {
1396 auto newparent = cast<SPItem>(where);
1398 (oldparent->i2doc_affine())
1399 *((newparent->i2doc_affine()).inverse()));
1417 std::vector<SPItem*> items_copy(
items().begin(),
items().
end());
1419 bool no_more =
false;
1424 std::vector<Inkscape::XML::Node*> temp_clip;
1428 std::vector<Inkscape::XML::Node*> copied;
1463 std::vector<SPItem*> items_copy(
items().begin(),
items().
end());
1465 bool no_more =
false;
1470 std::vector<Inkscape::XML::Node*> temp_clip;
1474 std::vector<Inkscape::XML::Node*> copied;
1508 if (!moveto || !moveto->
getRepr()) {
1509 g_warning(
"%s moveto is NULL", __func__);
1510 g_assert_not_reached();
1540 after = after->
prev();
1543 std::vector<SPItem*> items_copy(
items().begin(),
items().
end());
1548 std::vector<Inkscape::XML::Node*> temp_clip;
1554 if (!temp_clip.empty()) temp_clip.clear();
1562 bool contains_original =
false;
1566 auto use = cast<SPUse>(item_use);
1567 while (use && item_use && !contains_original)
1569 item_use = use->get_original();
1570 use = cast<SPUse>(item_use);
1571 contains_original |=
set->includes(item_use);
1572 if (item_use == item_use_first)
1578 auto tref = cast<SPTRef>(
item);
1579 if (!contains_original && tref) {
1580 contains_original =
set->includes(tref->getObjectReferredTo());
1583 return contains_original;
1590 bool clone_with_original =
false;
1592 for (
auto l=
items.begin();l!=
items.end() ;++l) {
1596 if (clone_with_original)
1600 return clone_with_original;
1626 bool adjust_transf_center)
1637 std::list<Persp3D *> plist =
perspList();
1638 for (
auto & i : plist) {
1646 std::list<SPBox3D *> selboxes =
box3DList(persp);
1648 for (
auto & selboxe : selboxes) {
1649 selboxe->switch_perspectives(persp, transf_persp);
1652 transf_persp = persp;
1658 auto items_copy =
items();
1659 std::vector<SPItem *> ordered_items;
1660 for (
auto l=items_copy.begin();l!=items_copy.end() ;++l) {
1662 auto clonelpe = cast<SPLPEItem>(
item);
1664 ordered_items.insert(ordered_items.begin(),
item);
1666 ordered_items.push_back(
item);
1669 for (
auto item : ordered_items) {
1670 if (is<SPRoot>(
item) ) {
1686 auto path = cast<SPPath>(
item);
1688 SPItem *attItem[2] = {
nullptr,
nullptr};
1689 path->connEndPair.getAttachedItems(attItem);
1690 for (
int n = 0; n < 2; ++n) {
1696 g_assert_not_reached();
1722 if (is<SPFlowregion>(®ion) || is<SPFlowregionExclude>(®ion)) {
1723 for (
auto& itm: region.children) {
1724 auto use = cast<SPUse>(&itm);
1742 auto parentItem = cast<SPItem>(
item->
parent);
1744 parent2dt = parentItem->i2dt_affine();
1746 g_assert_not_reached();
1759 auto use = cast<SPUse>(
item);
1761 parent = use->get_parent_transform();
1763 g_assert_not_reached();
1768 if (prefs_parallel) {
1772 }
else if (prefs_unmoved) {
1783 if (prefs_parallel) {
1787 }
else if (prefs_unmoved) {
1806 if (adjust_transf_center) {
1820 for (
auto l=
items.begin();l!=
items.end() ;++l) {
1821 (*l)->removeAttribute(
"transform");
1918 if (!fill && !stroke && !style) {
1925 bool inlayersame = prefs->
getBool(
"/options/selection/samelikeall",
false);
1926 bool onlyvisible = prefs->
getBool(
"/options/kbselection/onlyvisible",
true);
1927 bool onlysensitive = prefs->
getBool(
"/options/kbselection/onlysensitive",
true);
1930 bool ingroup =
true;
1942 std::vector<SPItem*> all_matches;
1946 std::vector<SPItem*> tmp;
1947 for (
auto iter : all_list) {
1948 if(!is<SPGroup>(iter)){
1949 tmp.push_back(iter);
1954 for (
auto sel_iter=
items.begin();sel_iter!=
items.end();++sel_iter) {
1956 std::vector<SPItem*> matches = all_list;
1957 if (fill && stroke && style) {
1969 all_matches.insert(all_matches.end(), matches.begin(),matches.end());
1973 selection->
setList(all_matches);
1992 bool onlyvisible = prefs->
getBool(
"/options/kbselection/onlyvisible",
true);
1993 bool onlysensitive = prefs->
getBool(
"/options/kbselection/onlysensitive",
true);
1994 bool ingroups = TRUE;
2000 for (
auto sel_iter=
items.begin();sel_iter!=
items.end();++sel_iter) {
2005 g_assert_not_reached();
2022 std::vector<SPItem*> matches ;
2023 gboolean match =
false;
2027 for (std::vector<SPItem*>::const_reverse_iterator i=src.rbegin();i!=src.rend();++i) {
2042 auto check_gradient = [] (
SPGradient const *g) {
2043 return is<SPLinearGradient>(g) || is<SPRadialGradient>(g) || g->getVector()->
isSwatch();
2049 if ((sel_gradient = cast<SPGradient>(sel_server)) &&
2050 (iter_gradient = cast<SPGradient>(iter_server)) &&
2051 check_gradient(sel_gradient) &&
2052 check_gradient(iter_gradient))
2056 if (sel_vector == iter_vector) {
2060 }
else if ((sel_pattern = cast<SPPattern>(sel_server)) &&
2061 (iter_pattern = cast<SPPattern>(iter_server))) {
2064 if (sel_pat == iter_pat) {
2068 }
else if (sel_paint->
isNone() && iter_paint->
isNone()) {
2075 matches.push_back(iter);
2078 g_assert_not_reached();
2087 if (is<SPRect>(i)) {
2088 return ( is<SPRect>(j) );
2090 }
else if (is<SPGenericEllipse>(i)) {
2091 return (is<SPGenericEllipse>(j));
2093 }
else if (is<SPStar>(i) || is<SPPolygon>(i)) {
2094 return (is<SPStar>(j) || is<SPPolygon>(j)) ;
2096 }
else if (is<SPSpiral>(i)) {
2097 return (is<SPSpiral>(j));
2099 }
else if (is<SPPath>(i) || is<SPLine>(i) || is<SPPolyLine>(i)) {
2100 return (is<SPPath>(j) || is<SPLine>(j) || is<SPPolyLine>(j));
2102 }
else if (is<SPText>(i) || is<SPFlowtext>(i) || is<SPTSpan>(i) || is<SPTRef>(i)) {
2103 return (is<SPText>(j) || is<SPFlowtext>(j) || is<SPTSpan>(j) || is<SPTRef>(j));
2105 }
else if (is<SPUse>(i)) {
2106 return (is<SPUse>(j)) ;
2108 }
else if (is<SPImage>(i)) {
2109 return (is<SPImage>(j));
2111 }
else if (is<SPOffset>(i) && cast_unsafe<SPOffset>(i)->sourceHref) {
2112 return (is<SPOffset>(j) && cast_unsafe<SPOffset>(j)->sourceHref);
2114 }
else if (is<SPOffset>(i) && !cast_unsafe<SPOffset>(i)->sourceHref) {
2115 return is<SPOffset>(j) && !cast_unsafe<SPOffset>(j)->sourceHref;
2128 std::vector<SPItem*> matches;
2130 for (std::vector<SPItem*>::const_reverse_iterator i=src.rbegin();i!=src.rend();++i) {
2133 matches.push_back(
item);
2145 std::vector<SPItem*> matches;
2161 std::vector<SPItem*> objects;
2162 SPStyle *sel_style_for_width =
nullptr;
2164 objects.push_back(sel);
2165 sel_style_for_width =
new SPStyle(SP_ACTIVE_DOCUMENT);
2169 for (
auto iter : src) {
2172 SPStyle *iter_style = iter->style;
2178 std::vector<SPItem*> objects;
2179 objects.insert(objects.begin(),iter);
2180 SPStyle tmp_style(SP_ACTIVE_DOCUMENT);
2183 if (sel_style_for_width) {
2188 match_g = match_g && match;
2195 match_g = match_g && match;
2199 for (
int i = 0; i <
len; i++) {
2207 match_g = match_g && match;
2209 while (iter->cloned) iter=cast<SPItem>(iter->parent);
2210 matches.insert(matches.begin(),iter);
2213 g_assert_not_reached();
2217 if( sel_style_for_width !=
nullptr )
delete sel_style_for_width;
2232 }
else if (dy == 0) {
2244 double const rdx = std::cos(rotation) * dx + std::sin(rotation) * dy;
2245 double const rdy = -std::sin(rotation) * dx + std::cos(rotation) * dy;
2258 move(dx, dy, rotated);
2270 gdouble
const zdx = dx / zoom;
2271 gdouble
const zdy = dy / zoom;
2276 DocumentUndo::maybeDone(doc,
"selector:move:vertical", _(
"Move vertically by pixels"), INKSCAPE_ICON(
"tool-pointer"));
2277 }
else if (dy == 0) {
2278 DocumentUndo::maybeDone(doc,
"selector:move:horizontal", _(
"Move horizontally by pixels"), INKSCAPE_ICON(
"tool-pointer"));
2288 double const rdx = std::cos(rotation) * dx + std::sin(rotation) * dy;
2289 double const rdy = -std::sin(rotation) * dx + std::cos(rotation) * dy;
2302 static void dispose(Iterator i) {}
2304 static SPObject *object(Iterator i) {
return i; }
2305 static Iterator next(Iterator i) {
return i->
getNext(); }
2306 static bool isNull(Iterator i) {
return (!i);}
2310 typedef std::list<SPObject *> *Iterator;
2312 static Iterator children(
SPObject *o) {
2313 return make_list(o,
nullptr);
2315 static Iterator siblings_after(
SPObject *o) {
2316 return make_list(o->
parent, o);
2318 static void dispose(Iterator i) {
2322 static SPObject *object(Iterator i) {
2323 return *(i->begin());
2325 static Iterator next(Iterator i) { i->pop_front();
return i; }
2327 static bool isNull(Iterator i) {
return i->empty();}
2331 auto list =
new std::list<SPObject *>;
2332 for (
auto &
child: object->children) {
2336 list->push_front(&
child);
2344template <
typename D>
2348 typename D::Iterator children;
2349 typename D::Iterator iter;
2353 if (!path.empty()) {
2358 found = next_item<D>(
desktop, path,
object, only_in_viewport, inlayer, onlyvisible, onlysensitive);
2360 iter = children = D::siblings_after(
object);
2362 iter = children = D::children(
root);
2365 while ( !D::isNull(iter) && !found ) {
2369 std::vector<SPObject *> empt;
2370 found = next_item<D>(
desktop, empt,
object, only_in_viewport, inlayer, onlyvisible, onlysensitive);
2373 auto item = cast<SPItem>(
object);
2383 iter = D::next(iter);
2386 D::dispose(children);
2392template <
typename D>
2406 std::vector<SPObject *> path;
2414 next = next_item<D>(
desktop, path,
root, only_in_viewport, inlayer, onlyvisible, onlysensitive);
2417 std::vector<SPObject *> empt;
2418 next = next_item<D>(
desktop, empt,
root, only_in_viewport, inlayer, onlyvisible, onlysensitive);
2427 g_return_if_fail(
desktop !=
nullptr);
2432 bool onlyvisible = prefs->
getBool(
"/options/kbselection/onlyvisible",
true);
2433 bool onlysensitive = prefs->
getBool(
"/options/kbselection/onlysensitive",
true);
2442 std::vector<SPItem *> vec(selection->
items().begin(), selection->
items().end());
2457 g_return_if_fail(document !=
nullptr);
2458 g_return_if_fail(
desktop !=
nullptr);
2463 bool onlyvisible = prefs->
getBool(
"/options/kbselection/onlyvisible",
true);
2464 bool onlysensitive = prefs->
getBool(
"/options/kbselection/onlysensitive",
true);
2473 std::vector<SPItem *> vec(selection->
items().begin(), selection->
items().end());
2489 if ( selection && !selection->
isEmpty() ) {
2491 if (
auto lpeitem = cast<SPLPEItem>(
item) ) {
2492 if (lpeitem->hasPathEffect()) {
2493 lpeitem->editNextParamOncanvas(dt);
2518 if ( sbox && dbox.
contains(*sbox) ==
false ) {
2553 std::vector<Inkscape::XML::Node*> newsel;
2555 for(
auto sel_repr : reprs){
2560 clone->setAttribute(
"y",
"0");
2561 gchar *href_str = g_strdup_printf(
"#%s", sel_repr->attribute(
"id"));
2562 clone->setAttribute(
"xlink:href", href_str);
2565 clone->setAttribute(
"inkscape:transform-center-x", sel_repr->attribute(
"inkscape:transform-center-x"));
2566 clone->setAttribute(
"inkscape:transform-center-y", sel_repr->attribute(
"inkscape:transform-center-y"));
2571 newsel.push_back(
clone);
2591 if (newid.empty()) {
2596 auto newrefAttribute =
"#" + newid;
2599 bool relinked =
false;
2600 auto items_=
items();
2601 for (
auto i=items_.begin();i!=items_.end();++i){
2604 if (
auto use = cast<SPUse>(
item)) {
2608 SPItem *newref = use->get_original();
2610 if (
ref && newref) {
2668 std::vector<SPItem*> new_select;
2669 bool unlinked =
false;
2670 std::vector<SPItem *> items_(
items().begin(),
items().
end());
2672 for (
auto i=items_.rbegin();i!=items_.rend();++i){
2686 unlinked = tmp_set.
unlink(
true) || unlinked;
2687 tmp_set.
setMask(
true,
false,
true);
2690 }
else if (mask_obj) {
2694 unlinked = tmp_set.
unlink(
true) || unlinked;
2695 tmp_set.
setMask(
false,
false,
true);
2699 if (is<SPText>(
item)) {
2711 if (!(is<SPUse>(
item) || is<SPTRef>(
item))) {
2713 new_select.push_back(
item);
2718 auto use = cast<SPUse>(
item);
2723 new_select.push_back(
item);
2728 g_assert(
unlink !=
nullptr);
2733 new_select.push_back(
unlink);
2737 if (!new_select.empty()) {
2759 bool pathoperationsunlink = prefs->
getBool(
"/options/pathoperationsunlink/value",
true);
2760 if (!force && !pathoperationsunlink) {
2761 if (
desktop() && !pathoperationsunlink && !silent) {
2766 bool unlinked =
false;
2768 std::vector<SPItem*> items_(
items().begin(),
items().
end());
2769 for (
auto& it:items_) {
2771 unlinked = tmp_set.
unlink(
true, silent) || unlinked;
2773 if (is<SPGroup>(it)) {
2774 std::vector<SPObject*>
c = it->
childList(
false);
2776 unlinked = tmp_set.
unlinkRecursive(skip_undo, force, silent) || unlinked;
2796 std::vector<SPItem *> items_(
items().begin(),
items().
end());
2797 std::vector<SPItem *> itemsdone_;
2798 for (
auto& it:items_) {
2799 auto splpeitem = cast<SPLPEItem>(it);
2800 auto spgroup = cast<SPGroup>(it);
2802 std::vector<SPObject*>
c = spgroup->childList(
false);
2809 char const *
id = splpeitem->getAttribute(
"id");
2811 splpeitem->removeAllPathEffects(keep_paths);
2814 itemsdone_.push_back(upditem);
2817 itemsdone_.push_back(it);
2828 gchar
const *error = _(
"Select a <b>clone</b> to go to its original. Select a <b>linked offset</b> to go to its source. Select a <b>text on path</b> to go to the path. Select a <b>flowed text</b> to go to its frame.");
2832 auto items_=
items();
2833 if (boost::distance(items_) != 1 || !
item) {
2840 auto use = cast<SPUse>(
item);
2843 }
else if (
auto offset = cast<SPOffset>(
item)) {
2845 }
else if (
auto text = cast<SPText>(
item)) {
2846 original = text->get_first_shape_dependency();
2847 }
else if (
auto flowtext = cast<SPFlowtext>(
item)) {
2848 original = flowtext->get_frame(
nullptr);
2864 if (is<SPDefs>(o)) {
2873 bool highlight = prefs->
getBool(
"/options/highlightoriginal/value");
2880 curve.moveto(a->midpoint());
2881 curve.lineto(b->midpoint());
2885 canvas_item_bpath->set_stroke(0x0000ddff);
2886 canvas_item_bpath->set_dashes({5.0, 3.0});
2887 canvas_item_bpath->set_visible(
true);
2908 auto items_=
items();
2909 bool multiple =
false;
2910 for (
auto *
item : items_) {
2911 if (is<SPShape>(
item) || is<SPText>(
item) || is<SPGroup>(
item)) {
2936 gchar
const *method_str = allow_transforms ?
"d" :
"bsplinespiro";
2938 gchar
const *allow_transforms_str = allow_transforms ?
"true" :
"false";
2939 lpe_repr->
setAttribute(
"allow_transforms", allow_transforms_str);
2941 std::string lpe_id_href = std::string(
"#") + lpe_repr->
attribute(
"id");
2944 auto firstgroup = cast<SPGroup>(
firstItem);
2949 clone = firstgroup->getRepr()->duplicate(xml_doc);
2954 if (
sync && !multiple && shape) {
2962 clone->setAttribute(
"d",
"M 0 0");
2965 clone->setAttribute(
"d",
"M 0 0");
2976 auto clone_lpeitem = cast<SPLPEItem>(clone_obj);
2977 if (clone_lpeitem) {
2978 if (
sync && !multiple) {
2979 lpe_repr->
setAttribute(
"attributes",
"style,clip-path,mask");
2982 clone_lpeitem->addPathEffect(lpe_id_href,
false);
3009 _(
"Select <b>object(s)</b> to convert to marker."));
3019 std::vector<SPItem*> items_(
items().begin(),
items().
end());
3027 auto parentItem = cast<SPItem>(
parent);
3029 parent_transform = parentItem->i2doc_affine();
3031 g_assert_not_reached();
3036 std::vector<Inkscape::XML::Node*> repr_copies;
3037 for (
auto *
item : items_) {
3039 repr_copies.push_back(dup);
3052 for (
auto item : items_){
3068 prefs->
setInt(
"/options/clonecompensation/value", saved_compensation);
3076 auto group = cast<SPGroup>(
item);
3077 if (group && !is<SPBox3D>(
item) && !wholegroups) {
3078 std::vector<SPItem*>
items=group->item_list();
3091 std::vector<SPItem*> items_(
items().begin(),
items().
end());
3100 bool deleteitems = !prefs->
getBool(
"/tools/cvg_keep_objects",
false);
3101 bool wholegroups = prefs->
getBool(
"/tools/cvg_convert_whole_groups",
false);
3107 for (
auto item : items_){
3161 bool single_group =
false;
3164 if( items_.size() == 1 ) {
3166 the_group = cast<SPGroup>(
object);
3168 single_group =
true;
3176 items_ =
object->childList(
false);
3189 prefs->
setInt(
"/options/clonecompensation/value", saved_compensation);
3199 bool settitle =
false;
3201 if( single_group ) {
3210 symbol_repr->
setAttribute(
"inkscape:transform-center-x",
3211 the_group->
getAttribute(
"inkscape:transform-center-x"));
3212 symbol_repr->
setAttribute(
"inkscape:transform-center-y",
3213 the_group->
getAttribute(
"inkscape:transform-center-y"));
3220 for (std::vector<SPObject*>::const_reverse_iterator i=items_.rbegin();i!=items_.rend();++i){
3221 gchar* title = (*i)->title();
3222 if (!single_group && !settitle && title) {
3227 gchar * desc = (*i)->desc();
3240 symbol_repr->
addChild(repr,
nullptr);
3272 for (
const auto obj:
items()) {
3273 auto use = cast<SPUse>(obj);
3275 auto sym = cast<SPSymbol>(use->root());
3295 _(
"Select <b>object(s)</b> to convert to pattern."));
3305 std::vector<SPItem*> items_(
items().begin(),
items().
end());
3315 auto parentItem = cast<SPItem>(
parent);
3317 parent_transform = parentItem->i2doc_affine();
3319 g_assert_not_reached();
3324 gint pos = items_[0]->getRepr()->position();
3327 std::vector<Inkscape::XML::Node*> repr_copies;
3328 for (
auto item : items_){
3330 repr_copies.push_back(dup);
3337 for (
auto item : items_){
3352 parent_transform *
move);
3355 prefs->
setInt(
"/options/clonecompensation/value", saved_compensation);
3359 gchar *style_str = g_strdup_printf(
"stroke:none;fill:url(#%s)", pat_id);
3371 parent->getRepr()->addChildAtPos(rect, pos);
3397 std::vector<SPItem*> new_select;
3401 std::vector<SPItem*> items_(
items().begin(),
items().
end());
3402 for (std::vector<SPItem*>::const_reverse_iterator i=items_.rbegin();i!=items_.rend();++i){
3407 if (!style || !style->
fill.isPaintserver())
3412 auto basePat = cast<SPPattern>(server);
3425 if (is<SPItem>(&
child)) {
3436 Geom::Affine transform( i->transform * pat_transform );
3437 i->doWriteTransform(transform);
3439 new_select.push_back(i);
3441 g_assert_not_reached();
3489 std::vector<SPItem const *> items_{
items().begin(),
items().end()};
3495 gint pos = items_.back()->getRepr()->position();
3502 int const prefs_res = prefs->
getInt(
"/options/createbitmap/resolution", 0);
3503 int const prefs_min = prefs->
getInt(
"/options/createbitmap/minsize", 0);
3504 if (0 < prefs_res) {
3507 }
else if (0 < prefs_min) {
3514 for (
auto &
item : items_) {
3530 bbox = bbox->roundOutwards();
3534 std::optional<Antialiasing> antialias;
3537 if (!nv->antialias_rendering) {
3552 auto parentItem = cast<SPItem>(parent_object);
3559 parent->addChildAtPos(repr, pos + 1);
3570 DocumentUndo::done(doc, _(
"Create bitmap"), INKSCAPE_ICON(
"selection-make-bitmap-copy"));
3601 int topmost = (p.back())->position();
3608 if (
current->parent() == topmost_parent) {
3611 inner->appendChild(spnew);
3615 std::vector<Inkscape::XML::Node*> temp_clip;
3619 gchar
const *t_str =
current->attribute(
"transform");
3636 if (!copied.empty()) {
3644 inner->appendChild(spnew);
3656 clone->setAttribute(
"y",
"0");
3657 clone->setAttribute(
"xlink:href", g_strdup_printf(
"#%s",
inner->attribute(
"id")));
3659 clone->setAttribute(
"inkscape:transform-center-x",
inner->attribute(
"inkscape:transform-center-x"));
3660 clone->setAttribute(
"inkscape:transform-center-y",
inner->attribute(
"inkscape:transform-center-y"));
3662 std::vector<Inkscape::XML::Node*> templist;
3663 templist.push_back(
clone);
3667 char* tmp = g_strdup_printf(
"url(#%s)", mask_id);
3680 doc->ensureUpToDate();
3685 auto root = doc->getRoot()->invoke_show(drawing, dkey, SP_ITEM_SHOW_DISPLAY);
3697 if (
auto shape = cast<SPShape>(
item)) {
3699 if (
auto curve = shape->curve()) {
3700 auto color = drawing.
averageColor(
curve->get_pathvector() * shape->i2dt_affine(), evenodd);
3711 doc->getRoot()->invoke_hide(dkey);
3727 if(!
desktop() && apply_to_layer)
3735 if ( apply_to_layer && is_empty) {
3739 }
else if (!apply_to_layer && ( is_empty || boost::distance(
items())==1 )) {
3748 if (clone_with_original) {
3749 g_warning(
"Unable to clip/mask an object with its own clone");
3756 std::vector<SPItem*> items_(
items().begin(),
items().
end());
3764 std::vector<std::pair<Inkscape::XML::Node*, Geom::Affine>> mask_items;
3765 std::vector<SPItem*> apply_to_items;
3766 std::vector<SPItem*> items_to_delete;
3767 std::vector<SPItem*> items_to_select;
3770 bool topmost = prefs->
getBool(
"/options/maskobject/topmost",
true);
3773 if (apply_to_layer) {
3775 apply_to_items.push_back(
desktop()->layerManager().currentLayer());
3778 for (
auto i : items_) {
3779 if((!topmost && !apply_to_layer && i == items_.front())
3780 || (topmost && !apply_to_layer && i == items_.back())
3784 mask_items.emplace_back(dup, i->i2doc_affine());
3786 if (remove_original) {
3787 items_to_delete.push_back(i);
3790 items_to_select.push_back(i);
3794 apply_to_items.push_back(i);
3795 items_to_select.push_back(i);
3805 set.add(apply_to_items.begin(), apply_to_items.end());
3807 items_to_select.clear();
3813 apply_to_items.clear();
3821 items_to_select.clear();
3824 gchar
const *attributeName = apply_clip_path ?
"clip-path" :
"mask";
3825 for (
auto item : apply_to_items | boost::adaptors::reversed) {
3826 std::vector<Inkscape::XML::Node*> mask_items_dup;
3827 std::map<Inkscape::XML::Node*, Geom::Affine> dup_transf;
3828 for (
auto const &mask_item : mask_items) {
3830 mask_items_dup.push_back(dup);
3831 dup_transf[dup] = mask_item.second;
3850 apply_mask_to =
group;
3853 items_to_select.push_back(
item);
3858 char const *mask_id =
nullptr;
3859 if (apply_clip_path) {
3867 for (
auto const &it : mask_items_dup) {
3869 clip_item->doWriteTransform(dup_transf[it]);
3873 apply_mask_to->
setAttribute(attributeName, Glib::ustring(
"url(#") + mask_id +
')');
3876 for (
auto item : items_to_delete) {
3878 items_to_select.erase(std::remove(items_to_select.begin(), items_to_select.end(),
item), items_to_select.end());
3885 const bool delete_helper_group,
3886 const bool remove_original)
3899 bool ungroup_masked = prefs->
getBool(
"/options/maskobject/ungrouping",
true);
3902 gchar
const *attributeName = apply_clip_path ?
"clip-path" :
"mask";
3903 std::map<SPObject*,SPItem*> referenced_objects;
3905 std::vector<SPItem*> items_(
items().begin(),
items().
end());
3908 std::vector<SPGroup *> items_to_ungroup;
3909 std::vector<SPItem*> items_to_select(items_);
3913 for (
auto i : items_){
3914 if (remove_original) {
3919 if (apply_clip_path) {
3927 referenced_objects[obj_ref] =
item;
3933 auto group = cast<SPGroup>(i);
3934 if (ungroup_masked &&
group && delete_helper_group) {
3940 items_to_ungroup.push_back(
group);
3946 for (
auto & referenced_object : referenced_objects) {
3947 SPObject *obj = referenced_object.first;
3948 std::vector<Inkscape::XML::Node *> items_to_move;
3952 if (
copy->attribute(
"inkscape:original-d") &&
copy->attribute(
"inkscape:path-effect")) {
3954 }
else if (
copy->attribute(
"inkscape:original-d")) {
3955 copy->setAttribute(
"d",
copy->attribute(
"inkscape:original-d"));
3956 copy->removeAttribute(
"inkscape:original-d");
3957 }
else if (!
copy->attribute(
"inkscape:path-effect") && !is<SPPath>(&
child)) {
3958 copy->removeAttribute(
"d");
3959 copy->removeAttribute(
"inkscape:original-d");
3961 items_to_move.push_back(
copy);
3974 for (
auto const repr : items_to_move | boost::adaptors::reversed) {
3978 auto mask_item = cast<SPItem>(
document()->getObjectByRepr(repr));
3982 items_to_select.push_back(mask_item);
3985 mask_item->doWriteTransform(mask_item->transform * referenced_object.second->transform);
3990 for (
auto group : items_to_ungroup | boost::adaptors::reversed) {
3992 items_to_select.erase(std::remove(items_to_select.begin(), items_to_select.end(),
group), items_to_select.end());
3993 std::vector<SPItem*> children;
3995 items_to_select.insert(items_to_select.end(),children.rbegin(),children.rend());
3997 g_assert_not_reached();
4012 g_return_val_if_fail(
document(),
false);
4035 Glib::ustring _paintserver_id;
4040 _paintserver_id.clear();
4049 else if (!paint->
set)
4052 server = SP_STYLE_FILL_SERVER(
item->
style);
4055 _paintserver_id +=
"url(#";
4056 _paintserver_id += srepr->
attribute(
"id");
4057 _paintserver_id +=
")";
4062 _paintserver_id.clear();
4071 else if (!paint->
set)
4074 server = SP_STYLE_STROKE_SERVER(
item->
style);
4077 _paintserver_id +=
"url(#";
4078 _paintserver_id += srepr->
attribute(
"id");
4079 _paintserver_id +=
")";
4128 Glib::ustring pathTarget;
4143 effectRepr->
setAttribute(
"effect",
"fill_between_many");
4150 pathTarget += effect->
getId();
4152 fillRepr->
setAttribute(
"inkscape:original-d",
"M 0,0");
4153 fillRepr->
setAttribute(
"inkscape:path-effect", pathTarget.c_str());
4157 auto&& items_ = std::vector<SPObject*>(
items().begin(),
items().
end());
4181 auto flowtext = cast<SPFlowtext>(
item);
4185 return check_item->second;
4200 }
else if (flowtext &&
includes(flowtext->get_frame(
nullptr))) {
4232 g_return_val_if_fail(doc,
false);
4255 if (
auto item = cast<SPItem>(
root)) {
void get_all_items_recursive(std::vector< SPObject * > &objects, SPObject *object, Glib::ustring &condition)
Cairo integration helpers.
3x3 matrix representing an affine transformation.
Coord descrim() const
Calculate the descriminant.
bool isIdentity(Coord eps=EPSILON) const
Check whether this matrix is an identity matrix.
bool isTranslation(Coord eps=EPSILON) const
Check whether this matrix represents a pure translation.
Affine inverse() const
Compute the inverse matrix.
Affine withoutTranslation() const
bool contains(CRect const &r) const
Check whether the rectangle includes all points in the given rectangle.
void unionWith(CRect const &b)
Enlarge the rectangle to contain the argument.
bool intersects(CRect const &r) const
Check whether the rectangles have any common points.
C top() const
Return top coordinate of the rectangle (+Y is downwards).
C left() const
Return leftmost coordinate of the rectangle (+X is to the right).
C height() const
Get the vertical extent of the rectangle.
C width() const
Get the horizontal extent of the rectangle.
CPoint min() const
Get the corner of the rectangle with smallest coordinate values.
CPoint dimensions() const
Get rectangle's width and height as a point.
Axis-aligned rectangle that can be empty.
Two-dimensional point that doubles as a vector.
constexpr Coord x() const noexcept
Axis aligned, non-empty rectangle.
Rotation around the origin.
static Rotate from_degrees(Coord deg)
Construct a rotation from its angle in degrees.
Translate inverse() const
Get the inverse translation.
bool addOpacity(double opacity=1.0)
bool isSimilar(Color const &other, double epsilon=EPSILON) const
Find out if a color is similar to another color, converting it first if it's a different type.
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
static void maybeDone(SPDocument *document, const gchar *keyconst, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
static void cancel(SPDocument *document)
void setRoot(DrawingItem *root)
Colors::Color averageColor(Geom::IntRect const &area) const
void update(Geom::IntRect const &area=Geom::IntRect::infinite(), Geom::Affine const &affine=Geom::identity(), unsigned flags=DrawingItem::STATE_ALL, unsigned reset=0)
void renameLayer(SPObject *obj, char const *label, bool uniquify)
void setCurrentLayer(SPObject *object, bool clear=false)
Sets the current layer of the desktop.
SPGroup * currentLayer() const
Returns current top layer.
SPGroup * currentRoot() const
Returns current root (=bottom) layer.
bool isLayer(SPObject *object) const
True if object is a layer.
MessageId flash(MessageType type, char const *message)
Temporarily pushes a message onto the stack.
void enforceIds()
Assign IDs to selected objects that don't have an ID attribute Checks if the object's id attribute is...
void moveScreen(double dx, double dy)
void pasteSize(bool apply_x, bool apply_y)
SPGroupRange groups()
Returns a range of selected groups.
Inkscape::XML::Node * group(bool is_anchor=false)
void stackDown(bool skip_undo=false)
void pasteSizeSeparately(bool apply_x, bool apply_y)
SPDesktop * desktop()
Returns the desktop the selection is bound to.
void toNextLayer(bool skip_undo=false)
bool unlink(const bool skip_undo=false, const bool silent=false)
Unlink all directly selected clones.
void move(double dx, double dy)
SPItemRange items()
Returns a range of selected SPItems.
void removeLPESRecursive(bool keep_paths)
void unsetMask(const bool apply_clip_path, const bool delete_helper_group, bool remove_original)
void cloneOriginalPathLPE(bool allow_transforms=false, bool sync=false, bool skip_undo=false)
This applies the Fill Between Many LPE, and has it refer to the selection.
void rotateRelative(const Geom::Point &, double)
bool add(SPObject *object, bool nosignal=false)
Add an SPObject to the set of selected objects.
boost::enable_if< boost::is_base_of< SPObject, T >, void >::type setList(const std::vector< T * > &objs)
Selects exactly the specified objects.
XMLNodeRange xmlNodes()
Returns a range of the xml nodes of all selected objects.
void raiseToTop(bool skip_undo=false)
void stackUp(bool skip_undo=false)
void setReprList(std::vector< XML::Node * > const &list)
Selects the objects with the same IDs as those in list.
void applyAffine(Geom::Affine const &affine, bool set_i2d=true, bool compensate=true, bool adjust_transf_center=true)
Apply matrix to the selection.
void moveRelative(const Geom::Point &move, bool compensate=true)
Geom::Affine _last_affine
void duplicate(bool suppressDone=false, bool duplicateLayer=false)
void toMarker(bool apply=true)
void toPrevLayer(bool skip_undo=false)
void reapplyAffine()
Reapply the same transform again.
std::optional< Geom::Point > center() const
Returns the rotation/skew center of the selection.
void clear()
Unselects all selected objects.
std::list< SPBox3D * > const box3DList(Persp3D *persp=nullptr)
Returns a list of all 3D boxes in the current selection which are associated to persp.
void ungroup_all(bool skip_undo=false)
Keep ungrouping until there are no more groups.
boost::enable_if< boost::is_base_of< SPObject, T >, void >::type addList(const std::vector< T * > &objs)
Adds the specified objects to selection, without deselecting first.
void deleteItems(bool skip_undo=false)
void ungroup(bool skip_undo=false)
void skewRelative(const Geom::Point &, double, double)
bool isEmpty()
Returns true if no items are selected.
void tile(bool apply=true)
std::map< SPObject *, SiblingState > _sibling_state
void set(SPObject *object, bool persist_selection_context=false)
Set the selection to a single specific object.
Geom::OptRect documentBounds(SPItem::BBoxType type) const
int size()
Returns size of the selection.
void scaleRelative(const Geom::Point &, const Geom::Scale &)
SPDocument * document()
Returns the document the selection is bound to.
void raise(bool skip_undo=false)
SPItem * firstItem() const
Returns the first selected item, returns nullptr if no items selected.
void clearSiblingStates()
void lowerToBottom(bool skip_undo=false)
void lower(bool skip_undo=false)
bool includes(SPObject *object, bool anyAncestor=false)
Returns true if the given object is selected.
SPItem * singleItem()
Returns a single selected item.
void setScaleAbsolute(double, double, double, double)
bool unlinkRecursive(const bool skip_undo=false, const bool force=false, const bool silent=false)
Recursively unlink any clones present in the current selection, including clones which are used to cl...
SPObjectRange objects()
Returns the list of selected objects.
void clone(bool skip_undo=false)
void toLayer(SPObject *layer)
Move selection to group moveto, after the last child of moveto (if it has any children).
void setMask(bool apply_clip_path, bool apply_to_layer, bool remove_original)
Creates a mask or clipPath from selection.
bool fitCanvas(bool with_margins, bool skip_undo=false)
Geom::OptRect visualBounds() const
std::list< Persp3D * > const perspList()
Returns a list of all perspectives which have a 3D box in the current selection.
void fillBetweenMany()
Creates a linked fill between all the objects in the current selection using the "Fill Between Many" ...
SiblingState getSiblingState(SPItem *item)
Associates the given SPItem with a SiblingState enum Needed for handling special cases while transfor...
Class to hold image data for raster images.
Preference storage class.
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
static Preferences * get()
Access the singleton Preferences object.
int getInt(Glib::ustring const &pref_path, int def=0)
Retrieve an integer.
void setInt(Glib::ustring const &pref_path, int value)
Set an integer value.
The set of selected SPObjects for a given document and layer model.
SPObject * activeContext()
Returns active layer for selection (currentLayer or its parent).
void set(XML::Node *repr)
Set the selection to an XML node's SPObject.
System-wide clipboard manager.
static ClipboardManager * get()
virtual bool pasteSize(ObjectSet *set, bool separately, bool apply_x, bool apply_y)=0
virtual bool pastePathEffect(ObjectSet *set)=0
virtual void copy(ObjectSet *set)=0
virtual Glib::ustring getFirstObjectID()=0
virtual bool paste(SPDesktop *desktop, bool in_place=false, bool on_page=false)=0
virtual bool pasteStyle(ObjectSet *set)=0
void invertSelection()
Unselect all selected points and select all unselected points.
void clear()
Remove all points from the selection, making it empty.
void selectAll()
Select all points that this selection can contain.
void invertSelectionInSubpaths()
static double convert(double from_dist, Unit const *from, Unit const *to)
Convert distances.
Interface for refcounted XML nodes.
virtual Node * parent()=0
Get the parent of this node.
virtual void addChild(Node *child, Node *after)=0
Insert another node as a child of this node.
virtual void changeOrder(Node *child, Node *after)=0
Move a given node in this node's child order.
virtual void appendChild(Node *child)=0
Append a node as the last child of this node.
void setAttributeOrRemoveIfEmpty(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
Change an attribute of this node.
void addChildAtPos(Node *child, unsigned pos)
Insert another node as a child of this node.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
virtual Node * duplicate(Document *doc) const =0
Create a duplicate of this node.
virtual unsigned position() const =0
Get the index of this node in parent's child order.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
virtual void removeChild(Node *child)=0
Remove a child of this node.
bool setAttributeSvgDouble(Util::const_char_ptr key, double val)
For attributes where an exponent is allowed.
virtual Node * lastChild()=0
Get the last child of this node.
static Persp3D * create_xml_element(SPDocument *document)
void apply_affine_transformation(Geom::Affine const &xform)
bool has_all_boxes_in_selection(Inkscape::ObjectSet *set) const
static char const * create(std::vector< Inkscape::XML::Node * > &reprs, SPDocument *document)
Wrapper around a Geom::PathVector object.
static std::optional< SPCurve > ptr_to_opt(T const &p)
To do: update description of desktop.
double current_zoom() const
Geom::Parallelogram get_display_area() const
Return canvas viewbox in desktop coordinates.
SPDocument * getDocument() const
Inkscape::Display::TemporaryItem * add_temporary_canvasitem(Inkscape::CanvasItem *item, int lifetime_msecs, bool move_to_bottom=true)
One should not keep a reference to the SPCanvasItem, the temporary item code will delete the object f...
bool itemIsHidden(SPItem const *item) const
Inkscape::MessageStack * messageStack() const
Geom::Affine const & d2w() const
Transformation from desktop to window coordinates.
bool isWithinViewport(SPItem const *item) const
True if desktop viewport intersects item's bbox.
void scroll_relative(Geom::Point const &delta)
Scroll canvas by specific coordinate amount (window coordinates).
Inkscape::Selection * getSelection() const
Geom::Rotate const & current_rotation() const
Inkscape::UI::Tools::ToolBase * getTool() const
void clearWaitingCursor()
Inkscape::LayerManager & layerManager()
Typed SVG document implementation.
SPRoot * getRoot()
Returns our SPRoot.
const Geom::Affine & dt2doc() const
Desktop to document coordinate transformation.
SPObject * getObjectById(std::string const &id) const
void fitToRect(Geom::Rect const &rect, bool with_margins=false)
Given a Geom::Rect that may, for example, correspond to the bbox of an object, this function fits the...
SPDefs * getDefs()
Return the main defs object for the document.
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
int ensureUpToDate(unsigned int object_modified_tag=0)
Repeatedly works on getting the document updated, since sometimes it takes more than one pass to get ...
SPObject * getObjectByRepr(Inkscape::XML::Node *repr) const
SPNamedView * getNamedView()
Get the namedview for this document, creates it if it's not found.
SPGradient * getVector(bool force_private=false)
Returns private vector of given gradient (the gradient at the end of the href chain which has stops),...
Paint type internal to SPStyle.
bool isPaintserver() const
Colors::Color const & getColor() const
String type internal to SPStyle.
char const * value() const
Get value if set, or inherited value, or default value (may be NULL)
Base class for visual SVG elements.
void set_i2d_affine(Geom::Affine const &transform)
Geom::Affine i2dt_affine() const
Returns the transformation from item to desktop coords.
Geom::OptRect documentVisualBounds() const
Get item's visual bbox in document coordinate system.
void set(SPAttr key, char const *value) override
Geom::Point getCenter(bool ensure_uptodate=true) const
SPMask * getMaskObject() const
void invoke_hide(unsigned int key)
Geom::OptRect desktopVisualBounds() const
Get item's visual bbox in desktop coordinate system.
Geom::Affine i2doc_affine() const
Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
static unsigned int display_key_new(unsigned numkeys)
Allocates unique integer keys.
virtual void convert_to_guides() const
void doWriteTransform(Geom::Affine const &transform, Geom::Affine const *adv=nullptr, bool compensate=true)
Set a new transform on an object.
void setLocked(bool lock)
void setExplicitlyHidden(bool val)
Sets the display CSS property to ‘hidden’ if val is true, otherwise makes it unset.
void setCenter(Geom::Point const &object_centre)
Sets the transform_center_x and transform_center_y properties to retain the rotation center.
SPClipPath * getClipObject() const
static char const * create(std::vector< Inkscape::XML::Node * > &reprs, SPDocument *document)
SPObject is an abstract base class of all of the document nodes at the SVG document level.
char const * label() const
Gets the author-visible label property for the object or a default if no label is defined.
void appendChild(Inkscape::XML::Node *child)
void setAttribute(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
void removeAttribute(char const *key)
Geom::Point getExportDpi() const
Get and set the exported DPI for this objet, if available.
std::vector< SPObject * > childList(bool add_ref, Action action=ActionGeneral)
Retrieves the children as a std vector object, optionally ref'ing the children in the process,...
void setTmpSuccessor(SPObject *tmpsuccessor)
Indicates that another object supercedes temporaty this one.
bool isReferenced()
Check if object is referenced by any other object.
char const * getId() const
Returns the objects current ID string.
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
SPObject * getPrev()
Returns previous object in sibling list or NULL.
Inkscape::XML::Node * updateRepr(unsigned int flags=SP_OBJECT_WRITE_EXT)
Updates the object's repr based on the object's state.
void readAttr(char const *key)
Read value of key attribute from XML node into object.
std::string generate_unique_id(char const *default_id=nullptr) const
Generate a document-wide unique id for this object.
void deleteObject(bool propagate, bool propagate_descendants)
Deletes an object, unparenting it from its parent.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
char const * getAttribute(char const *name) const
void fixTmpSuccessors()
Fix temporary successors in duple stamp.
SPObject * appendChildRepr(Inkscape::XML::Node *repr)
Append repr as child of this object.
void addChild(Inkscape::XML::Node *child, Inkscape::XML::Node *prev=nullptr)
void unsetTmpSuccessor()
Unset object supercedes.
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
static char const * produce(std::vector< Inkscape::XML::Node * > const &reprs, Geom::Rect const &bounds, SPDocument *document, Geom::Affine const &transform, Geom::Affine const &move)
create a new pattern in XML tree
SPPattern const * rootPattern() const
SPPaintServer * getFillPaintServer()
T< SPAttr::FILL, SPIPaint > fill
fill
T< SPAttr::STROKE_DASHARRAY, SPIDashArray > stroke_dasharray
stroke-dasharray
T< SPAttr::STROKE, SPIPaint > stroke
stroke
SPPaintServer * getStrokePaintServer()
T< SPAttr::STROKE_WIDTH, SPILength > stroke_width
stroke-width
T< SPAttr::FILL_OPACITY, SPIScale24 > fill_opacity
fill-opacity
SPIPaint * getFillOrStroke(bool fill_)
Get either the fill or the stroke property.
T< SPAttr::STROKE_OPACITY, SPIScale24 > stroke_opacity
stroke-opacity
T< SPAttr::MARKER, SPIString > marker
Marker list.
T< SPAttr::SHAPE_INSIDE, SPIShapes > shape_inside
SVG2 Text Wrapping.
SPIString * marker_ptrs[SP_MARKER_LOC_QTY]
System-wide clipboard management - class declaration.
double inner(valarray< double > const &x, valarray< double > const &y)
Control point selection - stores a set of control points and applies transformations to them.
std::shared_ptr< Css const > css
int objects_query_strokewidth(const std::vector< SPItem * > &objects, SPStyle *style_res)
Write to style_res the average stroke width of a list of objects.
void sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines)
Apply style on object and children, recursively.
void sp_desktop_set_style(SPDesktop *desktop, SPCSSAttr *css, bool change, bool write_current, bool switch_style)
Apply style on selection on desktop.
Editable view implementation.
static char const *const current
static char const *const parent
TODO: insert short description here.
@ PREFS_MASKOBJECT_GROUPING_ALL
@ PREFS_MASKOBJECT_GROUPING_SEPARATE
@ PREFS_MASKOBJECT_GROUPING_NONE
@ SP_CLONE_COMPENSATION_UNMOVED
@ SP_CLONE_COMPENSATION_PARALLEL
@ PREFS_SELECTION_LAYER_RECURSIVE
Macro for icon names used in Inkscape.
Inkscape::XML::Node * node
Raw stack of active status messages.
Multi path manipulator - a tool component that edits multiple paths at once.
Affine identity()
Create an identity matrix.
static R & release(R &r)
Decrements the reference count of a anchored object.
void invert(SPDesktop *desktop)
void reverse(SPDesktop *dt)
void selectSameFillStroke(SPDesktop *dt)
void selectSameStrokeColor(SPDesktop *dt)
void selectNone(SPDesktop *desktop)
void invertAllInAll(SPDesktop *desktop)
void selectAll(SPDesktop *desktop)
void selectSameObjectType(SPDesktop *dt)
void fixSelection(SPDesktop *desktop)
void selectAllInAll(SPDesktop *desktop)
void selectSameStrokeStyle(SPDesktop *dt)
void selectSameFillColor(SPDesktop *dt)
Helper class to stream background task notifications as a series of messages.
SPObject * next_layer(SPObject *root, SPObject *layer)
Finds the next layer under root, relative to layer in depth-first order.
ObjectSet::SPItemRange SPItemRange
SPObject * previous_layer(SPObject *root, SPObject *layer)
Finds the previous layer under root, relative to layer in depth-first order.
std::pair< char const *, char const * > getHrefAttribute(XML::Node const &node)
Get the 'href' or 'xlink:href' (fallback) attribute from an XML node.
MessageType
A hint about the meaning of a message; is it an ordinary message, a message advising the user of some...
static T clip(T const &v, T const &a, T const &b)
SiblingState
SiblingState enums are used to associate the current state while grabbing objects.
@ SIBLING_TEXT_SHAPE_INSIDE
@ SIBLING_TEXT_FLOW_FRAME
Path manipulator - a component that edits a single path on-canvas.
Inkscape::Pixbuf * sp_generate_internal_bitmap(SPDocument *document, Geom::Rect const &area, double dpi, std::vector< SPItem const * > items, bool opaque, uint32_t const *checkerboard_color, double device_scale, std::optional< Antialiasing > antialias)
Generates a bitmap from given items.
TODO: insert short description here.
SPCSSAttr * sp_repr_css_attr_new()
Creates an empty SPCSSAttr (a class for manipulating CSS style properties).
void sp_repr_css_merge(SPCSSAttr *dst, SPCSSAttr *src)
Merges two SPCSSAttr's.
SPCSSAttr * sp_repr_css_attr_inherited(Node const *repr, gchar const *attr)
Creates a new SPCSSAttr with one attribute whose value is determined by cascading.
void sp_repr_css_change(Node *repr, SPCSSAttr *css, gchar const *attr)
Creates a new SPCSAttr with the values filled from a repr, merges in properties from the given SPCSAt...
void sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr)
Sets an attribute (e.g.
void sp_repr_css_set_property_double(SPCSSAttr *css, gchar const *name, double value)
Set a style property to a new float value (e.g.
void sp_repr_css_attr_unref(SPCSSAttr *css)
Unreferences an SPCSSAttr (will be garbage collected if no references remain).
void sp_repr_css_set_property_string(SPCSSAttr *css, char const *name, std::string const &value)
Set a style property to a standard string.
void sp_repr_css_unset_property(SPCSSAttr *css, gchar const *name)
Set a style property to "inkscape:unset".
void sp_repr_css_set_property(SPCSSAttr *css, gchar const *name, gchar const *value)
Set a style property to a new value (e.g.
bool sp_repr_compare_position_bool(Inkscape::XML::Node const *first, Inkscape::XML::Node const *second)
bool sp_repr_is_def(Inkscape::XML::Node const *node)
void sp_repr_unparent(Inkscape::XML::Node *repr)
Remove repr from children of its parent node.
bool sp_repr_is_layer(Inkscape::XML::Node const *node)
void sp_edit_invert_in_all_layers(SPDesktop *desktop)
std::vector< SPItem * > sp_get_same_object_type(SPItem *sel, std::vector< SPItem * > &src)
static void sp_selection_to_guides_recursive(SPItem *item, bool wholegroups)
SPItem * next_item(SPDesktop *desktop, std::vector< SPObject * > &path, SPObject *root, bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive)
static void unhide(SPItem *item, SPDesktop *desktop)
std::vector< SPItem * > sp_get_same_style(SPItem *sel, std::vector< SPItem * > &src, SPSelectStrokeStyleType type)
static void sp_selection_copy_impl(std::vector< SPItem * > const &items, std::vector< Inkscape::XML::Node * > &clip, Inkscape::XML::Document *xml_doc)
static SPObject * prev_sibling(SPObject *child)
void sp_selection_change_layer_maintain_clones(std::vector< SPItem * > const &items, SPObject *where)
Ensures that the clones of objects are not modified when moving objects between layers.
void sp_edit_invert(SPDesktop *desktop)
static void sp_selection_delete_impl(std::vector< SPItem * > const &items, bool propagate=true, bool propagate_descendants=true)
static bool item_type_match(SPItem *i, SPItem *j)
static void unlock(SPItem *item, SPDesktop *)
void sp_selection_paste(SPDesktop *desktop, bool in_place, bool on_page)
static bool object_set_contains_both_clone_and_original(ObjectSet *set)
static void sp_edit_select_all_full(SPDesktop *dt, bool force_all_layers, bool invert)
static void selection_display_message(SPDesktop *desktop, Inkscape::MessageType msgType, Glib::ustring const &msg)
static Geom::OptRect enclose_items(std::vector< SPItem * > const &items)
Finds out the minimum common bbox of the selected items.
std::vector< SPItem * > sp_get_same_fill_or_stroke_color(SPItem *sel, std::vector< SPItem * > &src, SPSelectStrokeStyleType type)
std::vector< SPItem * > get_all_items(SPObject *from, SPDesktop *desktop, bool onlyvisible, bool onlysensitive, bool ingroups, std::vector< SPItem * > const &exclude)
void sp_selection_item_next(SPDesktop *desktop)
void scroll_to_show_item(SPDesktop *desktop, SPItem *item)
If item is not entirely visible then adjust visible area to centre on the centre on of item.
void sp_edit_select_all_in_all_layers(SPDesktop *desktop)
static void sp_selection_copy_one(Inkscape::XML::Node *repr, Geom::Affine full_t, std::vector< Inkscape::XML::Node * > &clip, Inkscape::XML::Document *xml_doc)
Copies repr and its inherited css style elements, along with the accumulated transform 'full_t',...
void sp_edit_clear_all(Inkscape::Selection *selection)
SPItem * next_item_from_list(SPDesktop *desktop, std::vector< SPItem * > const &items, SPObject *root, bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive)
SPCSSAttr * take_style_from_item(SPObject *object)
void sp_selection_item_prev(SPDesktop *desktop)
void unlock_all(SPDesktop *dt)
static void add_ids_recursive(std::vector< const gchar * > &ids, SPObject *obj)
void unlock_all_in_all_layers(SPDesktop *dt)
void sp_edit_select_all(SPDesktop *desktop)
void sp_selection_next_patheffect_param(SPDesktop *dt)
void unhide_all_in_all_layers(SPDesktop *dt)
static SPGroup * sp_item_list_common_parent_group(const SPItemRange &items)
If items in the list have a common parent, return it, otherwise return NULL.
static void ungroup_impl(ObjectSet *set)
Ungroup all groups in an object set.
bool fit_canvas_to_drawing(SPDocument *doc, bool with_margins)
static bool object_set_contains_original(SPItem *item, ObjectSet *set)
void unhide_all(SPDesktop *dt)
static void process_all(void(*f)(SPItem *, SPDesktop *), SPDesktop *dt, bool layer_only)
void sp_select_same_object_type(SPDesktop *desktop)
static void sp_selection_remove_livepatheffect_impl(SPItem *item)
static SPUse * find_clone_to_group(Objects const &objects, std::set< SPGroup * > const &groups)
Finds the first clone in objects which references an item in groups.
void sp_select_same_fill_stroke_style(SPDesktop *desktop, gboolean fill, gboolean stroke, gboolean style)
static std::vector< Inkscape::XML::Node * > sp_selection_paste_impl(SPDocument *doc, SPObject *parent, std::vector< Inkscape::XML::Node * > &clip, Inkscape::XML::Node *after=nullptr)
static void itemtree_map(void(*f)(SPItem *, SPDesktop *), SPObject *root, SPDesktop *desktop)
@ SP_STROKE_STYLE_MARKERS
void sp_conn_end_detach(SPObject *const owner, unsigned const handle_ix)
TODO: insert short description here.
TODO: insert short description here.
TODO: insert short description here.
void sp_embed_image(Inkscape::XML::Node *image_node, Inkscape::Pixbuf *pb)
SVG <image> implementation.
void sp_item_group_ungroup_handle_clones(SPItem *parent, Geom::Affine const g)
finds clones of a child of the group going out of the group; and inverse the group transform on its c...
void sp_item_group_ungroup(SPGroup *group, std::vector< SPItem * > &children)
bool SP_IS_LAYER(SPObject const *obj)
Some things pertinent to all visible shapes: SPItem, SPItemView, SPItemCtx.
bool sp_item_repr_compare_position_bool(SPObject const *first, SPObject const *second)
TODO: insert short description here.
void sp_lpe_item_update_patheffect(SPLPEItem *lpeitem, bool wholetree, bool write, bool with_satellites)
Calls any registered handlers for the update_patheffect action.
const gchar * generate_marker(std::vector< Inkscape::XML::Node * > &reprs, Geom::Rect bounds, SPDocument *document, Geom::Point center, Geom::Affine move)
void invert(const double v[16], double alpha[16])
bool sp_object_compare_position_bool(SPObject const *first, SPObject const *second)
SPObject * sp_object_unref(SPObject *object, SPObject *owner)
Decrease reference count of object, with possible debugging and finalization.
SPObject * sp_object_ref(SPObject *object, SPObject *owner)
Increase reference count of object, with possible debugging.
SPItem * sp_offset_get_source(SPOffset *offset)
SVG <pattern> implementation.
TODO: insert short description here.
TODO: insert short description here.
SPRoot: SVG <svg> implementation.
TODO: insert short description here.
SPItem * sp_textpath_get_path_item(SPTextPath const *tp)
SPObject * sp_tref_convert_to_tspan(SPObject *obj)
This function will create a new tspan element with the same attributes as the tref had and add the sa...
SVG <tref> implementation, see sp-tref.cpp.
TODO: insert short description here.
Interface for XML documents.
virtual Node * createTextNode(char const *content)=0
virtual Node * createElement(char const *name)=0
static const unsigned SP_STYLE_FLAG_IFSET(1<< 0)
SPCSSAttr * sp_css_attr_unset_blacklist(SPCSSAttr *css)
Unset properties that should not be set for default tool style.
SPCSSAttr * sp_css_attr_from_object(SPObject *object, guint const flags)
SPCSSAttr * sp_css_attr_unset_text(SPCSSAttr *css)
Unset any text-related properties.
SPCSSAttr * sp_css_attr_scale(SPCSSAttr *css, double ex)
Scale any properties that may hold <length> by ex.
SPStyle - a style object for SPItem objects.
bool sp_svg_transform_read(gchar const *str, Geom::Affine *transform)
std::string sp_svg_transform_write(Geom::Affine const &transform)
static void sp_svg_write_path(Inkscape::SVG::PathString &str, Geom::Path const &p, bool normalize=false)
void text_relink_refs(text_refs_t const &refs, InIterOrig origBegin, InIterOrig origEnd, InIterCopy copyBegin)
text_refs_t text_categorize_refs(SPDocument *doc, InIter begin, InIter end, text_ref_t which)