20#include <boost/range/adaptor/reversed.hpp>
21#include <glibmm/i18n.h>
52 if (
auto group = cast<SPGroup>(
item)) {
53 for (
auto &
child : group->children) {
54 if (
auto childitem = cast<SPItem>(&
child)) {
59 out.emplace_back(
item);
66 std::vector<SPItem*> out;
76 auto items_copy = std::vector<SPItem*>(
items().begin(),
items().
end());
78 if (items_copy.empty()) {
95 std::vector<SPItem*> to_paths;
96 for (
auto item : boost::adaptors::reverse(items_copy)) {
97 if (!is<SPPath>(
item) && !is<SPGroup>(
item)) {
98 to_paths.emplace_back(
item);
101 std::vector<Inkscape::XML::Node*> converted;
103 for (
auto node : converted) {
104 items_copy.emplace_back(
static_cast<SPItem*
>(doc->getObjectByRepr(
node)));
109 std::sort(items_copy.begin(), items_copy.end(), [] (
auto a,
auto b) {
110 return sp_repr_compare_position(a->getRepr(), b->getRepr()) < 0;
112 assert(!items_copy.empty());
116 char const *transform =
nullptr;
117 char const *path_effect =
nullptr;
127 for (
auto item : boost::adaptors::reverse(items_copy)) {
128 auto path = cast<SPPath>(
item);
138 auto c = *path->curveForEdit();
150 curve.append(std::move(
c));
175 repr->
setAttribute(
"inkscape:path-effect", path_effect);
187 parent->addChildAtPos(repr, position > 0 ? position : 0);
196 }
else if (
desktop() && !silent) {
223 std::vector<SPItem*> itemlist(
items().begin(),
items().
end());
224 for (
auto item : itemlist){
226 auto path = cast<SPPath>(
item);
231 if (!path->curveForEdit()) {
234 auto pathv = path->curveForEdit()->get_pathvector();
255 std::vector<Inkscape::XML::Node*> reprs;
256 for (
auto const &
curve : list) {
261 repr->
setAttribute(
"inkscape:path-effect", path_effect);
272 parent->addChildAtPos(repr, pos);
278 if (&
curve == &list.front())
281 reprs.push_back(repr);
299 }
else if (
desktop() && !silent) {
318 if (!clonesjustunlink) {
321 std::vector<SPItem*> selected(
items().begin(),
items().
end());
322 std::vector<Inkscape::XML::Node*> to_select;
323 std::vector<SPItem*>
items(selected);
330 if (clonesjustunlink) {
337 if (did && !skip_undo) {
354 std::vector<SPItem*> selected(
items().begin(),
items().
end());
355 std::vector<Inkscape::XML::Node*> to_select;
357 std::vector<SPItem*>
items(selected);
368 for (
auto &
child :
object->children) {
369 if (
auto child_item = cast<SPItem>(&
child)) {
370 items.push_back(child_item);
378sp_item_list_to_curves(
const std::vector<SPItem*> &
items, std::vector<SPItem*>& selected, std::vector<Inkscape::XML::Node*> &to_select,
bool skip_all_lpeitems)
382 g_assert(
item !=
nullptr);
385 auto group = cast<SPGroup>(
item);
386 if ( skip_all_lpeitems &&
387 cast<SPLPEItem>(
item) &&
393 if (
auto box = cast<SPBox3D>(
item)) {
398 to_select.insert(to_select.begin(),repr);
400 selected.erase(
remove(selected.begin(), selected.end(),
item), selected.end());
408 auto lpeitem = cast<SPLPEItem>(
item);
409 if (lpeitem && lpeitem->hasPathEffect()) {
410 lpeitem->removeAllPathEffects(
true);
412 if (elemref !=
item) {
413 selected.erase(
remove(selected.begin(), selected.end(),
item), selected.end());
417 item = cast<SPItem>(elemref);
418 selected.push_back(
item);
423 }
else if (!lpeitem->hasPathEffect()) {
428 if (is<SPPath>(
item)) {
443 std::vector<SPItem*> item_list;
446 std::vector<Inkscape::XML::Node*> item_to_select;
447 std::vector<SPItem*> item_selected;
461 selected.erase(
remove(selected.begin(), selected.end(),
item), selected.end());
478 parent->addChildAtPos(repr, pos);
482 to_select.insert(to_select.begin(),repr);
493 if (is<SPText>(
item) || is<SPFlowtext>(
item)) {
496 if (is<SPGroup>(
item)) {
507 std::vector<SPItem *>
items;
515 std::vector<SPItem *> selected;
516 std::vector<Inkscape::XML::Node *> to_select;
529 if (is<SPText>(
item) || is<SPFlowtext>(
item)) {
538 std::vector<std::pair<Geom::PathVector, SPStyle *>> curves;
544 if (iter == iter_next)
549 layout->getSourceOfCharacter(iter, &pos_obj);
552 while (is<SPString>(pos_obj) && pos_obj->
parent) {
553 pos_obj = pos_obj->
parent;
557 auto curve = layout->convertToCurves(iter, iter_next);
559 if (
curve.is_empty()) {
565 if (!prev_parent || prev_parent != pos_obj) {
567 auto style = pos_obj->
style;
569 style->
merge(sp->style);
571 curves.emplace_back(
curve.get_pathvector(), style);
573 for (
auto &path :
curve.get_pathvector()) {
574 curves.back().first.push_back(path);
578 prev_parent = pos_obj;
579 if (iter == layout->end())
590 for (
auto &[pathv, style] : curves) {
591 Glib::ustring glyph_style = style->writeIfDiff(
item->
style);
595 if (curves.size() == 1) {
597 result_style->
merge(style);
599 result->appendChild(new_path);
609 result->setAttributeOrRemoveIfEmpty(
"style",
css);
612 if (!original_text.empty()) {
613 result->setAttribute(
"aria-label", original_text);
620 if (
auto shape = cast<SPShape>(
item); shape && shape->curveForEdit()) {
621 curve = *shape->curveForEdit();
628 if(
curve.is_empty()) {
640 Glib::ustring style_str =
668 for (
auto i =
items().begin(); i !=
items().end(); ++i){
670 auto path = cast<SPPath>(*i);
678 if ( path->hasPathEffectRecursive() ) {
679 path->setAttribute(
"inkscape:original-d", str);
681 path->setAttribute(
"d", str);
685 gchar *nodetypes = g_strdup(path->getRepr()->attribute(
"sodipodi:nodetypes"));
687 path->setAttribute(
"sodipodi:nodetypes", g_strreverse(nodetypes));
691 path->update_patheffect(
false);
716 static char const *
const keys[] = {
729 "inkscape:highlight-color",
731 "inkscape:transform-center-x",
732 "inkscape:transform-center-y",
746 for (
auto *
key : keys) {
768 static std::set<std::string>
const names{
777 (
child->name() && names.count(
child->name())))) {
FillRule to_livarot(SPWindRule fill_rule)
3x3 matrix representing an affine transformation.
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
MessageId flash(MessageType type, char const *message)
Temporarily pushes a message onto the stack.
SPDesktop * desktop()
Returns the desktop the selection is bound to.
void breakApart(bool skip_undo=false, bool overlapping=true, bool silent=false)
SPItemRange items()
Returns a range of selected SPItems.
void setReprList(std::vector< XML::Node * > const &list)
Selects the objects with the same IDs as those in list.
void clear()
Unselects all selected objects.
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 toLPEItems()
Converts the selected items to LPEItems if they are not already so; e.g.
bool isEmpty()
Returns true if no items are selected.
SPDocument * document()
Returns the document the selection is bound to.
void toCurves(bool skip_undo=false, bool clonesjustunlink=false)
void combine(bool skip_undo=false, bool silent=false)
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...
Holds a position within the glyph output of Layout.
Interface for refcounted XML nodes.
virtual Node * parent()=0
Get the parent of this node.
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 setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
virtual Node * firstChild()=0
Get the first child 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 Document * document()=0
Get the node's associated document.
Wrapper around a Geom::PathVector object.
Inkscape::MessageStack * messageStack() const
void clearWaitingCursor()
Typed SVG document implementation.
SPRoot * getRoot()
Returns our SPRoot.
SPObject * getObjectById(std::string const &id) const
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
Base class for visual SVG elements.
Geom::Affine getRelativeTransform(SPObject const *obj) const
bool forkPathEffectsIfNecessary(unsigned int nr_of_allowed_users=1, bool recursive=true, bool force=false)
Check all effects in the stack if they are used by other items, and fork them if so.
SPObject is an abstract base class of all of the document nodes at the SVG document level.
void removeAttribute(char const *key)
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
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 merge(SPStyle const *parent)
Combine style and parent style specifications into a single style specification that preserves (as mu...
Glib::ustring writeIfDiff(SPStyle const *base) const
Get CSS string for set properties which are different from the given base style.
T< SPAttr::FILL_RULE, SPIEnum< SPWindRule > > fill_rule
fill-rule: 0 nonzero, 1 evenodd
std::shared_ptr< Css const > css
Editable view implementation.
static char const *const parent
TODO: insert short description here.
Macro for icon names used in Inkscape.
Inkscape::XML::Node * node
Raw stack of active status messages.
static R & release(R &r)
Decrements the reference count of a anchored object.
@ COMMENT_NODE
Comment node, e.g. <!– some comment –>.
void copy_object_properties(XML::Node *dest, XML::Node const *src)
Copy generic object properties, like:
std::vector< Geom::PathVector > split_non_intersecting_paths(Geom::PathVector &&paths, FillRule fill_rule)
Split a pathvector into its connected components when filled using the given fill rule.
void convert_text_to_curves(SPDocument *)
Convert all text in the document to path, in-place.
static cairo_user_data_key_t key
void list_text_items_recursive(SPItem *root, std::vector< SPItem * > &items)
static void ink_copy_generic_attributes(Inkscape::XML::Node *dest, Inkscape::XML::Node const *src)
Copy generic attributes, like those from the "Object Properties" dialog, but also style and transform...
static std::vector< SPItem * > sp_degroup_list(std::vector< SPItem * > const &items)
Replace all groups in the list with their member objects, recursively.
static void collect_object_items(SPObject *object, std::vector< SPItem * > &items)
static void sp_degroup_list_recursive(std::vector< SPItem * > &out, SPItem *item)
Inkscape::XML::Node * sp_selected_item_to_curved_repr(SPItem *item, guint32)
bool sp_item_list_to_curves(const std::vector< SPItem * > &items, std::vector< SPItem * > &selected, std::vector< Inkscape::XML::Node * > &to_select, bool skip_all_lpeitems)
static void ink_copy_generic_children(Inkscape::XML::Node *dest, Inkscape::XML::Node const *src)
Copy generic child elements, like those from the "Object Properties" dialog (title and description) b...
C facade to Inkscape::XML::Node.
void remove(std::vector< T > &vec, T const &val)
TODO: insert short description here.
SPRoot: SVG <svg> implementation.
Interface for XML documents.
virtual Node * createElement(char const *name)=0
SPStyle - a style object for SPItem objects.
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 te_update_layout_now_recursive(SPItem *item)
Glib::ustring sp_te_get_string_multiline(SPItem const *text)
Gets a text-only representation of the given text or flowroot object, replacing line break elements w...
Inkscape::Text::Layout const * te_get_layout(SPItem const *item)