21#include <glibmm/i18n.h>
50 if (is<SPText>(
item)) {
51 return &(cast<SPText>(
item)->layout);
52 }
else if (is<SPFlowtext>(
item)) {
53 return &(cast<SPFlowtext>(
item)->layout);
61 cast<SPText>(
item)->rebuildLayout();
62 else if (is<SPFlowtext>(
item))
63 cast<SPFlowtext>(
item)->rebuildLayout();
69 if (is<SPGroup>(
item)) {
70 std::vector<SPItem*> item_list = cast<SPGroup>(
item)->item_list();
71 for(
auto list_item : item_list){
74 }
else if (is<SPText>(
item))
75 cast<SPText>(
item)->rebuildLayout();
76 else if (is<SPFlowtext>(
item))
77 cast<SPFlowtext>(
item)->rebuildLayout();
84 return layout->
begin() == layout->
end();
90 if (is<SPString>(
item)) {
91 empty = cast<SPString>(
item)->string.empty();
117 return std::vector<Geom::Point>();
119 if (layout ==
nullptr)
120 return std::vector<Geom::Point>();
144 if (layout ==
nullptr) {
150 if (pos_obj ==
nullptr) {
153 while (pos_obj->
style ==
nullptr) {
154 pos_obj = pos_obj->
parent;
187 bool is_line_break =
false;
190 if (is<SPText>(
object)
192 || is<SPTextPath>(
object)
193 || is<SPFlowdiv>(
object)
194 || is<SPFlowpara>(
object)
195 || is<SPFlowline>(
object)
196 || is<SPFlowregionbreak>(
object)) {
198 is_line_break =
true;
202 return is_line_break;
209 if (is<SPTSpan>(
object))
211 if (is<SPText>(
object))
212 return &cast<SPText>(
object)->attributes;
213 if (is<SPTRef>(
object))
214 return &cast<SPTRef>(
object)->attributes;
215 if (is<SPTextPath>(
object))
216 return &cast<SPTextPath>(
object)->attributes;
222 if (is<SPText>(
object))
return "svg:tspan";
223 else if (is<SPFlowtext>(
object))
return "svg:flowSpan";
231 if (is<SPString>(
item)) {
232 length = cast<SPString>(
item)->string.length();
239 if (is<SPString>(&
child)) {
240 length += cast<SPString>(&
child)->string.length();
255 if (is<SPString>(
item)) {
256 return cast<SPString>(
item)->string.length();
269 if (upto && &
child == upto) {
273 if (is<SPString>(&
child)) {
274 length += cast<SPString>(&
child)->string.length();
292 switch (old_node->
type()) {
295 GQuark const id_key = g_quark_from_string(
"id");
297 if (attr.key == id_key)
continue;
298 new_node->
setAttribute(g_quark_to_string(attr.key), attr.value);
322 unsigned char_index = 0;
324 if (&sibling ==
item) {
338 if (first_attrs && second_attrs)
339 first_attrs->
split(char_index, second_attrs);
357 }
else if (!is<SPTSpan>(split_obj) &&
358 !is<SPFlowtspan>(split_obj) &&
359 !is<SPString>(split_obj)) {
360 std::cerr <<
"split_text_object_tree_at: Illegal split object type! (Illegal document structure.)" << std::endl;
367 if (duplicate_obj ==
nullptr) {
381 split_obj = split_obj->
getNext();
390 split_obj = next_obj;
410 bool need_to_wrap =
false;
411 auto text_object = cast<SPText>(
item);
412 if (text_object && !text_object->has_shape_inside() && !text_object->has_inline_size()) {
416 auto tspan = cast<SPTSpan>(
child);
419 need_to_wrap =
false;
441 text_object->rebuildLayout();
449 Glib::ustring::iterator split_text_iter;
450 if (position != layout->
end()) {
458 if (is<SPTRef>(split_obj)) {
472 }
else if (is<SPString>(split_obj)) {
475 if (is<SPTRef>(split_obj->
parent)) {
480 Glib::ustring *
string = &cast<SPString>(split_obj)->string;
481 unsigned char_index = 0;
482 for (Glib::ustring::iterator it = string->begin() ; it != split_text_iter ; ++it)
487 if (
object ==
nullptr) {
492 auto new_string = cast<SPString>(
object);
493 new_string->getRepr()->setContent(&*split_text_iter.base());
494 string->erase(split_text_iter, string->end());
518 if (is<SPString>(start_obj)) {
519 return cast<SPString>(start_obj);
521 start_obj = start_obj->
getNext();
533 unsigned char_index = 0;
534 unsigned char_count = g_utf8_strlen(utf8, -1);
535 Glib::ustring *
string = &string_item->
string;
537 for (Glib::ustring::iterator it = string->begin() ; it != iter_at ; ++it)
539 string->replace(iter_at, iter_at, utf8);
541 SPObject *parent_item = string_item;
544 parent_item = parent_item->
parent;
546 if (!attributes)
break;
547 attributes->
insert(char_index, char_count);
557 if (!g_utf8_validate(utf8,-1,
nullptr)) {
558 g_warning(
"Trying to insert invalid utf8");
565 Glib::ustring::iterator iter_text;
570 bool cursor_at_end = position == layout->
end();
573 if (is<SPString>(source_obj)) {
575 if (is<SPTRef>(source_obj->
parent)) {
581 if (!cursor_at_start){
584 auto string_item = cast<SPString>(source_obj);
589 if (cursor_at_start) {
593 if (is<SPFlowtext>(
item)) {
594 while (is<SPFlowregion>(source_obj) || is<SPFlowregionExclude>(source_obj)) {
595 source_obj = source_obj->
getNext();
597 if (source_obj ==
nullptr) {
602 if (source_obj ==
item && is<SPFlowtext>(
item)) {
608 source_obj = source_obj->
getNext();
612 if (string_item ==
nullptr) {
617 g_assert(is<SPString>(source_obj->
firstChild()));
618 string_item = cast<SPString>(source_obj->
firstChild());
621 if (is<SPTRef>(string_item->
parent)) {
659 if (one ==
nullptr || two ==
nullptr)
662 if (is<SPString>(common_ancestor))
663 common_ancestor = common_ancestor->
parent;
664 while (!(common_ancestor == two || common_ancestor->
isAncestorOf(two))) {
665 g_assert(common_ancestor != text);
666 common_ancestor = common_ancestor->
parent;
668 return common_ancestor;
676 while ((*para_obj)->hasChildren())
678 if (is<SPString>(*para_obj))
679 *text_iter = cast<SPString>(*para_obj)->string.end();
704 while (following_item->
getNext() ==
nullptr) {
705 following_item = following_item->
parent;
706 g_assert(following_item !=
root);
708 following_item = following_item->
getNext();
711 if (is<SPString>(following_item)) {
712 new_parent_item = following_item->
parent;
715 *next_is_sibling =
true;
717 new_parent_item = following_item;
719 *next_is_sibling =
true;
722 *next_is_sibling =
false;
734 gchar
const *
key = g_quark_to_string(attr.key);
735 gchar
const *this_attr = this_node_attrs_inherited->
attribute(
key);
736 if ((this_attr ==
nullptr || strcmp(attr.value, this_attr)) && this_node_attrs->
attribute(
key) ==
nullptr)
746 attributes->
insert(0, moved_char_count);
756 unsigned char_index = 0;
757 unsigned char_count = 0;
758 Glib::ustring *
string = &string_item->
string;
760 for (Glib::ustring::iterator it = string->begin() ; it != iter_from ; ++it){
763 for (Glib::ustring::iterator it = iter_from ; it != iter_to ; ++it){
766 string->erase(iter_from, iter_to);
769 SPObject *parent_item = string_item;
772 parent_item = parent_item->
parent;
774 if (attributes ==
nullptr) {
778 attributes->
erase(char_index, char_count);
792 bool success =
false;
794 iter_pair.first =
start;
795 iter_pair.second =
end;
800 iter_pair.first =
end;
801 iter_pair.second =
start;
807 SPObject *start_item =
nullptr, *end_item =
nullptr;
808 Glib::ustring::iterator start_text_iter, end_text_iter;
811 if (start_item ==
nullptr) {
817 if (end_item ==
nullptr) {
826 bool has_text_decoration =
false;
827 gchar
const *root_style = (
item)->getRepr()->attribute(
"style");
828 if(root_style && strstr(root_style,
"text-decoration"))has_text_decoration =
true;
830 if (start_item == end_item) {
832 if (is<SPString>(start_item)) {
834 if (is<SPTRef>(start_item->
parent)) {
844 while (sub_item !=
item) {
845 if (sub_item == end_item) {
846 if (is<SPString>(sub_item)) {
848 if (is<SPTRef>(sub_item->
parent)) {
853 Glib::ustring *
string = &cast<SPString>(sub_item)->string;
859 if (is<SPString>(sub_item)) {
860 auto string = cast<SPString>(sub_item);
861 if (sub_item == start_item)
873 bool is_sibling =
true;
884 if (is_sibling)
break;
886 }
while (sub_item !=
item && sub_item != end_item);
907 if (*pending_line_break) {
909 *pending_line_break =
false;
912 if (is<SPString>(&
child)) {
913 *
string += cast<SPString>(&
child)->string;
919 *pending_line_break =
true;
928 Glib::ustring string;
929 bool pending_line_break =
false;
931 if (is<SPText>(text) || is<SPFlowtext>(text)) {
957 Glib::ustring::iterator text_iter;
959 if (is<SPString>(char_item)) {
971 g_return_if_fail (text !=
nullptr);
972 g_return_if_fail (is<SPText>(text) || is<SPFlowtext>(text));
977 bool is_textpath =
false;
990 gchar *content = g_strdup (str);
993 for (
auto&
child:
object->childList(
false)) {
994 if (!is<SPFlowregion>(
child) && !is<SPFlowregionExclude>(
child)) {
1001 while (*p !=
'\0') {
1011 auto sptext = cast<SPText>(text);
1012 if (sptext && (sptext->has_inline_size() || sptext->has_shape_inside())) {
1021 gchar *e = strchr (p,
'\n');
1024 if (is<SPText>(text)) {
1036 p = (e) ? e + 1 :
nullptr;
1051 if (
item ==
nullptr || char_index ==
nullptr || !is<SPText>(
item)) {
1054 auto text = cast<SPText>(
item);
1057 Glib::ustring::iterator source_text_iter;
1058 text->layout.getSourceOfCharacter(position, &source_item, &source_text_iter);
1060 if (!is<SPString>(source_item)) {
1063 Glib::ustring *
string = &cast<SPString>(source_item)->string;
1065 for (Glib::ustring::iterator it = string->begin() ; it != source_text_iter ; ++it) {
1079 factor = factor / t.
descrim();
1082 unsigned char_index;
1084 if (attributes) attributes->
addToDxDy(char_index, by);
1087 if (attributes) attributes->
addToDxDy(char_index, -by);
1096 unsigned char_index = 0;
1114 unsigned char_index = 0;
1137 factor = factor / t.
descrim();
1139 if (layout ==
nullptr)
return;
1142 if (source_item ==
nullptr) {
1145 gdouble degrees = (180/M_PI) * atan2(pixels, source_item->
parent->
style->
font_size.computed / factor);
1153 unsigned char_index;
1155 if (attributes ==
nullptr)
return;
1160 if (attributes) attributes->
addToRotate(char_index, degrees);
1171 unsigned char_index = 0;
1173 if (attributes !=
nullptr) {
1178 attributes->
setRotate(char_index, degrees);
1182 attributes->
setRotate(char_index, degrees);
1193 g_return_if_fail (text !=
nullptr);
1194 g_return_if_fail (is<SPText>(text) || is<SPFlowtext>(text));
1203 if (source_obj ==
nullptr) {
1206 if (is<SPString>(source_obj)) {
1207 source_obj = source_obj->
parent;
1229 source_obj = source_obj->
parent;
1239 gdouble
const zby = (by
1240 / (zoom * (nb_let > 1 ? nb_let - 1 : 1))
1241 / cast<SPItem>(source_obj)->i2doc_affine().descrim());
1261 char string_val[40];
1262 g_snprintf(string_val,
sizeof(string_val),
"%f", val);
1280 unsigned line_count = layout->
lineIndex(layout->
end());
1285 double average_line_height = all_lines_height / (line_count == 0 ? 1 : line_count);
1287 average_line_height = -average_line_height;
1289 return average_line_height;
1299 SPStyle *style =
object->style;
1321 style->
line_height.computed = amount < 0.0 ? -0.001 : 0.001;
1324 style->
line_height.computed *= (average + amount) / average;
1335 style->
line_height.value = amount < 0.0 ? -0.001 : 0.001;
1337 style->
line_height.value *= (average + amount) / average;
1368 object->updateRepr();
1371 std::vector<SPObject*> children =
object->childList(
false);
1372 for (
auto child: children) {
1381 g_return_if_fail (text !=
nullptr);
1382 g_return_if_fail (is<SPText>(text) || is<SPFlowtext>(text));
1387 if (fabs(average_line_height) < 0.001) average_line_height = 0.001;
1391 unsigned line_count = layout->
lineIndex(layout->
end());
1413 for (Glib::ustring::const_iterator it =
string.begin() ; it !=
string.end() && it != text_iter ; ++it)
1427 if (item_style_string && *item_style_string) {
1430 Glib::ustring new_style_string = style.
write();
1455 Glib::ustring child_style_construction;
1458 char const *style_text =
child->getRepr()->attribute(
"style");
1459 if (style_text && *style_text) {
1460 child_style_construction.insert(0, style_text);
1461 child_style_construction.insert(0, 1,
';');
1465 child_style_construction.insert(0, parent_style);
1468 child_spstyle.
mergeString(child_style_construction.c_str());
1471 bool equal = (child_style == parent_style);
1482 gchar
const *other_attr = second->
attribute(g_quark_to_string(attr.key));
1483 if (other_attr ==
nullptr || strcmp(attr.value, other_attr))
1487 gchar
const *other_attr = first->
attribute(g_quark_to_string(attr.key));
1488 if (other_attr ==
nullptr || strcmp(attr.value, other_attr))
1523 bool passed_start = start_item ==
nullptr ? true :
false;
1527 if (start_item ==
child) {
1528 passed_start =
true;
1540 if (is<SPString>(
child)) {
1541 auto string_item = cast<SPString>(
child);
1542 bool surround_entire_string =
true;
1549 if (
child == start_item ||
child == end_item) {
1550 surround_entire_string =
false;
1551 if (start_item == end_item && start_text_iter != string_item->string.begin()) {
1563 child->getRepr()->setContent(string_item->string.substr(end_char_index).c_str());
1564 }
else if (
child == end_item) {
1574 child->getRepr()->setContent(string_item->string.substr(end_char_index).c_str());
1575 }
else if (start_text_iter != string_item->string.begin()) {
1586 child->deleteObject();
1590 surround_entire_string =
true;
1592 if (surround_entire_string) {
1603 }
else if (
child != end_item) {
1608 if (
child->isAncestorOf(start_item)) {
1612 passed_start =
true;
1616 if (end_item ==
child)
1631 if (
item == common_ancestor)
1633 if (is<SPString>(
item))
1634 if (text_iter != cast<SPString>(
item)->
string.begin())
1638 if (
parent == common_ancestor) {
1655 if ( !(*item)->hasChildren()
1657 && !(is<SPString>(*
item) && !cast_unsafe<SPString>(*item)->string.empty())
1676 if (is<SPString>(*
item)) {
1690 while ((*item)->hasChildren()) {
1693 (*item)->getRepr()->removeChild(repr);
1694 (*item)->parent->getRepr()->addChild(repr, next->
getRepr());
1709 if (second ==
nullptr)
return false;
1714 if (first_repr->
type() != second_repr->
type())
return false;
1716 if (is<SPString>(first) && is<SPString>(second)) {
1718 Glib::ustring merged_string = cast<SPString>(first)->string + cast<SPString>(second)->string;
1726 if (strcmp(first_repr->
name(), second_repr->
name()) != 0)
return false;
1728 gchar
const *first_style = first_repr->
attribute(
"style");
1729 gchar
const *second_style = second_repr->
attribute(
"style");
1730 if (!((first_style ==
nullptr && second_style ==
nullptr)
1731 || (first_style !=
nullptr && second_style !=
nullptr && !strcmp(first_style, second_style))))
1737 if (attributes_first && attributes_second && attributes_second->
anyAttributesSet()) {
1753 if (!(*item)->hasChildren()) {
1756 if ((*item)->firstChild() != (*item)->lastChild()) {
1759 if (is<SPFlowregion>((*item)->firstChild()) || is<SPFlowregionExclude>((*item)->firstChild())) {
1762 if (is<SPString>((*item)->firstChild())) {
1772 gchar
const *child_style = (*item)->firstChild()->getRepr()->attribute(
"style");
1773 if (child_style && *child_style) {
1777 (*item)->firstChild()->deleteObject();
1784 if (is<SPFlowregion>(
child) || is<SPFlowregionExclude>(
child)) {
1787 if (is<SPString>(
child)) {
1806 insert_after_repr = (*item)->getRepr();
1807 }
else if ((*item)->getPrev()) {
1808 insert_after_repr = (*item)->getPrev()->getRepr();
1810 while (
child->getRepr()->childCount()) {
1813 child->getRepr()->removeChild(move_repr);
1814 (*item)->parent->getRepr()->addChild(move_repr, insert_after_repr);
1816 insert_after_repr = move_repr;
1818 child->deleteObject();
1831 if (!(*item)->hasChildren())
return false;
1832 if ((*item)->firstChild() == (*item)->lastChild())
return false;
1845 if (is<SPFlowregion>(
child) || is<SPFlowregionExclude>(
child))
1847 if (is<SPString>(
child))
return false;
1857 gchar
const *item_style = (*item)->getRepr()->attribute(
"style");
1858 if (item_style && *item_style) {
1861 gchar
const *child_style =
child->getRepr()->attribute(
"style");
1862 if (child_style && *child_style) {
1869 if (!equal)
return false;
1877 (*item)->parent->getRepr()->addChild(new_span, (*item)->getRepr());
1882 child->deleteObject();
1892 if (!(*item)->hasChildren())
return false;
1893 if ((*item)->firstChild() == (*item)->lastChild())
return false;
1915 if (
child == not_obj)
continue;
1916 if (
child->hasChildren()) {
1918 if (ret)
return ret;
1919 }
else if (is<SPString>(
child))
1920 return cast<SPString>(
child);
1939 if (!is<SPString>(*
item) || has_text_decoration ) {
1942 Glib::ustring
const &str = cast<SPString>(*item)->string;
1943 for (Glib::ustring::const_iterator it = str.begin() ; it != str.end() ; ++it) {
1944 if (!g_unichar_isspace(*it)) {
1955 next_string->
string.insert(0, str);
1959 test_item = test_item->
parent;
1963 if (is<SPFlowtext>(test_item)) {
1974 if (next_string == NULL) {
2014 gchar
const *root_style = (
root)->getRepr()->attribute(
"style");
2015 if(root_style && strstr(root_style,
"text-decoration"))has_text_decoration =
true;
2016 static bool (*
const tidy_operators[])(
SPObject**, bool) = {
2024 bool changes =
false;
2027 if (is<SPFlowregion>(
child) || is<SPFlowregionExclude>(
child) || is<SPTRef>(
child)) {
2031 if (
child->hasChildren()) {
2036 for (i = 0 ; i <
sizeof(tidy_operators) /
sizeof(tidy_operators[0]) ; i++) {
2037 if (tidy_operators[i](&
child, has_text_decoration)) {
2042 if (i ==
sizeof(tidy_operators) /
sizeof(tidy_operators[0])) {
2065 SPObject *start_item =
nullptr, *end_item =
nullptr;
2066 Glib::ustring::iterator start_text_iter, end_text_iter;
2069 if (start_item ==
nullptr) {
2073 start_item = start_item->
getNext();
2076 end_item = end_item->
getNext();
2078 if (end_item ==
nullptr) {
2107 Geom::Affine const local(cast<SPItem>(common_ancestor)->i2doc_affine());
2108 double const ex(local.
descrim());
2132 bool has_text_decoration =
false;
2133 gchar
const *root_style = (text)->getRepr()->attribute(
"style");
2134 if(root_style && strstr(root_style,
"text-decoration")) has_text_decoration =
true;
2150 return is<SPTSpan>(obj)
2152 || is<SPFlowtext>(obj)
2153 || is<SPFlowtspan>(obj)
2154 || is<SPFlowdiv>(obj)
2155 || is<SPFlowpara>(obj)
2156 || is<SPFlowline>(obj)
2157 || is<SPFlowregionbreak>(obj);
2162 return is<SPText>(obj)
2163 || is<SPFlowtext>(obj);
2168 bool hasVisible =
false;
2170 if (is<SPString>(obj) && !cast_unsafe<SPString>(obj)->
string.empty()) {
TODO: insert short description here.
3x3 matrix representing an affine transformation.
Coord descrim() const
Calculate the descriminant.
Affine inverse() const
Compute the inverse matrix.
Two-dimensional point that doubles as a vector.
MessageId flash(MessageType type, char const *message)
Temporarily pushes a message onto the stack.
Holds a position within the glyph output of Layout.
Generates the layout for either wrapped or non-wrapped text and stores the result.
std::vector< Geom::Point > createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Affine const &transform) const
Basically uses characterBoundingBox() on all the characters from start to end and returns the union o...
iterator charIndexToIterator(int char_index) const
Returns an iterator pointing at the given character index.
void queryCursorShape(iterator const &it, Geom::Point &position, double &height, double &rotation) const
Gets the ideal cursor shape for a given iterator.
unsigned lineIndex(iterator const &it) const
Returns the zero-based line number of the character pointed to by it.
void validateIterator(iterator *it) const
Checks the validity of the given iterator over the current layout.
static const double LINE_HEIGHT_NORMAL
The CSS spec allows line-height:normal to be whatever the user agent thinks will look good.
Geom::Point characterAnchorPoint(iterator const &it) const
For latin text, the left side of the character, on the baseline.
int iteratorToCharIndex(iterator const &it) const
Returns the character index from the start of the flow represented by the given iterator.
iterator end() const
Returns an iterator pointing just past the end of the last glyph, which is also just past the end of ...
void getSourceOfCharacter(iterator const &it, SPObject **source, Glib::ustring::iterator *text_iterator=nullptr) const
Discovers where the character pointed to by it came from, by retrieving the object that was passed to...
iterator getNearestCursorPositionTo(double x, double y) const
Returns an iterator pointing to the cursor position for a mouse click at the given coordinates.
iterator begin() const
Returns an iterator pointing at the first glyph of the flowed output.
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 appendChild(Node *child)=0
Append a node as the last child of this node.
virtual char const * name() const =0
Get the name of the element node.
virtual const AttributeVector & attributeList() const =0
Get a list of the node's attributes.
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 void setContent(char const *value)=0
Set the content of a text or comment node.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
virtual char const * content() const =0
Get the content of a text or comment node.
virtual Document * document()=0
Get the node's associated document.
virtual void removeChild(Node *child)=0
Remove a child of this node.
virtual unsigned childCount() const =0
Get the number of children of this node.
virtual NodeType type() const =0
Get the type of the node.
virtual Node * lastChild()=0
Get the last child of this node.
To do: update description of desktop.
double current_zoom() const
Inkscape::MessageStack * messageStack() const
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
Base class for visual SVG elements.
Geom::Affine i2dt_affine() const
Returns the transformation from item to desktop coords.
Geom::Affine i2doc_affine() const
Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
SPObject is an abstract base class of all of the document nodes at the SVG document level.
void setAttributeOrRemoveIfEmpty(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
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,...
SPObject * get_child_by_repr(Inkscape::XML::Node *repr)
Return object's child whose node pointer equals repr.
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 deleteObject(bool propagate, bool propagate_descendants)
Deletes an object, unparenting it from its parent.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
bool isAncestorOf(SPObject const *object) const
True if object is non-NULL and this is some in/direct parent of object.
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
T< SPAttr::LINE_HEIGHT, SPILengthOrNormal > line_height
Line height (css2 10.8.1)
T< SPAttr::LETTER_SPACING, SPILengthOrNormal > letter_spacing
letter spacing (css2 16.4)
Glib::ustring write(unsigned flags, SPStyleSrc style_src_req, SPStyle const *base=nullptr) const
void mergeString(char const *p)
Parses a style="..." string and merges it with an existing SPStyle.
T< SPAttr::WRITING_MODE, SPIEnum< SPCSSWritingMode > > writing_mode
Writing mode (svg1.1 10.7.2, CSS Writing Modes 3)
T< SPAttr::FONT_SIZE, SPIFontSize > font_size
Size of the font.
void split(unsigned index, TextTagAttributes *second)
Divides the stored attributes into two, at the given index.
void setRotate(unsigned index, double angle)
Sets rotate vector at the given index.
void addToDy(unsigned index, double delta)
Adds the given value to the dy vector at the given index.
void addToDxDy(unsigned index, Geom::Point const &adjust)
Adds the given values to the dx and dy vectors at the given index.
void addToRotate(unsigned index, double delta)
Adds the given value to the rotate vector at the given index.
void erase(unsigned start_index, unsigned n)
Deletes all the values from all the vectors beginning at start_index and extending for n fields.
bool anyAttributesSet() const
Returns false if all of the vectors are zero length.
void writeTo(Inkscape::XML::Node *node) const
Write out all the contents of attributes to the given node.
Inkscape::Text::Layout::OptionalTextTagAttrs attributes
This holds the actual values.
void insert(unsigned start_index, unsigned n)
Inserts n new values in all the stored vectors at start_index.
void addToDx(unsigned index, double delta)
Adds the given value to the dx vector at the given index.
void join(TextTagAttributes const &first, TextTagAttributes const &second, unsigned second_index)
Overwrites all the attributes contained in this object with the given parameters by putting first at ...
std::shared_ptr< Css const > css
Editable view implementation.
static char const *const parent
Raw stack of active status messages.
static R & anchor(R &r)
Increments the reference count of a anchored object.
static R & release(R &r)
Decrements the reference count of a anchored object.
@ DOCUMENT_NODE
Top-level document node. Do not confuse with the root node.
@ PI_NODE
Processing instruction node, e.g. <?xml version="1.0" encoding="utf-8" standalone="no"?...
@ COMMENT_NODE
Comment node, e.g. <!– some comment –>.
@ ELEMENT_NODE
Regular element node, e.g. <group />.
@ TEXT_NODE
Text node, e.g. "Some text" in <group>Some text</group> is represented by a text node.
static cairo_user_data_key_t key
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_attr_unref(SPCSSAttr *css)
Unreferences an SPCSSAttr (will be garbage collected if no references remain).
SPCSSAttr * sp_repr_css_attr(Node const *repr, gchar const *attr)
Creates a new SPCSSAttr with one attribute (i.e.
char const * sp_repr_css_property(SPCSSAttr *css, gchar const *name, gchar const *defval)
Returns a character string of the value of a given style property or a default value if the attribute...
void sp_repr_css_set_property(SPCSSAttr *css, gchar const *name, gchar const *value)
Set a style property to a new value (e.g.
void sp_repr_css_attr_add_from_string(SPCSSAttr *css, gchar const *p)
Use libcroco to parse a string for CSS properties and then merge them into an existing SPCSSAttr.
bool sp_repr_is_meta_element(const Inkscape::XML::Node *node)
Determine if the node is a 'title', 'desc' or 'metadata' element.
SPItem * next_item(SPDesktop *desktop, std::vector< SPObject * > &path, SPObject *root, bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive)
SPCSSAttr - interface for CSS Attributes.
TODO: insert short description here.
TODO: insert short description here.
TODO: insert short description here.
TODO: insert short description here.
bool SP_IS_TEXT_TEXTPATH(SPObject const *obj)
bool sp_tref_fully_contained(SPObject *start_item, Glib::ustring::iterator &start, SPObject *end_item, Glib::ustring::iterator &end)
Returns true if a tref is fully contained in the confines of the given iterators and layout (or if th...
SVG <tref> implementation, see sp-tref.cpp.
TODO: insert short description here.
@ SP_TSPAN_ROLE_UNSPECIFIED
Interface for XML documents.
virtual Node * createTextNode(char const *content)=0
virtual Node * createElement(char const *name)=0
virtual Node * createComment(char const *content)=0
virtual Node * createPI(char const *target, char const *content)=0
@ SP_CSS_WRITING_MODE_TB_RL
@ SP_CSS_WRITING_MODE_LR_TB
@ SP_CSS_WRITING_MODE_RL_TB
static const unsigned SP_STYLE_FLAG_ALWAYS(1<< 2)
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.
Inkscape::Text::Layout::iterator sp_te_insert_line(SPItem *item, Inkscape::Text::Layout::iterator &position)
inserts a new line break at the given position in a text or flowtext object.
static bool redundant_double_nesting_processor(SPObject **item, SPObject *child, bool prepend)
helper for tidy_operator_redundant_double_nesting()
static void overwrite_style_with_string(SPObject *item, gchar const *style_string)
applies the given style string on top of the existing styles for item, as opposed to sp_style_merge_f...
static bool is_line_break_object(SPObject const *object)
SPObject const * sp_te_object_at_position(SPItem const *text, Inkscape::Text::Layout::iterator const &position)
static unsigned sum_sibling_text_lengths_before(SPObject const *item)
returns the sum of the (recursive) lengths of all the SPStrings prior to item at the same level.
Inkscape::Text::Layout::iterator sp_te_get_position_by_coords(SPItem const *item, Geom::Point const &i_p)
static SPObject * split_text_object_tree_at(SPObject *split_obj, unsigned char_index)
recursively divides the XML node tree into two objects: the original will contain all objects up to a...
void sp_te_adjust_rotation(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *, gdouble degrees)
static SPObject * ascend_while_first(SPObject *item, Glib::ustring::iterator text_iter, SPObject *common_ancestor)
static bool css_attrs_are_equal(SPCSSAttr const *first, SPCSSAttr const *second)
returns true if first and second contain all the same attributes with the same values as each other.
void sp_te_adjust_rotation_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble pixels)
void sp_te_adjust_dx(SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *, double delta)
void sp_te_adjust_tspan_letterspacing_screen(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, gdouble by)
SPStyle const * sp_te_style_at_position(SPItem const *text, Inkscape::Text::Layout::iterator const &position)
unsigned sp_text_get_length_upto(SPObject const *item, SPObject const *upto)
Recursively gets the length of all the SPStrings at or below the given item, before and not including...
static bool tidy_operator_redundant_semi_nesting(SPObject **item, bool)
redundant semi-nesting: <font a><font b>abc</font>def</font> -> <font b>abc</font><font>def</font> te...
static void apply_css_recursive(SPObject *o, SPCSSAttr const *css)
sets the given css attribute on this object and all its descendants.
static Inkscape::XML::Node * duplicate_node_without_children(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node const *old_node)
void te_update_layout_now_recursive(SPItem *item)
double sp_te_get_average_linespacing(SPItem *text)
bool has_visible_text(SPObject const *obj)
void sp_te_get_cursor_coords(SPItem const *item, Inkscape::Text::Layout::iterator const &position, Geom::Point &p0, Geom::Point &p1)
unsigned sp_text_get_length(SPObject const *item)
Recursively gets the length of all the SPStrings at or below the given item.
bool sp_te_output_is_empty(SPItem const *item)
Returns true if there are no visible characters on the canvas.
static const char * span_name_for_text_object(SPObject const *object)
static unsigned char_index_of_iterator(Glib::ustring const &string, Glib::ustring::const_iterator text_iter)
converts an iterator to a character index, mainly because ustring::substr() doesn't have a version th...
static void sp_te_get_ustring_multiline(SPObject const *root, Glib::ustring *string, bool *pending_line_break)
Gets a text-only representation of the given text or flowroot object, replacing line break elements w...
static void split_attributes(SPObject *first_item, SPObject *second_item, unsigned char_index)
splits the attributes for the first object at the given char_index and moves the ones after that poin...
std::vector< Geom::Point > sp_te_create_selection_quads(SPItem const *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, Geom::Affine const &transform)
static void move_child_nodes(Inkscape::XML::Node *from_repr, Inkscape::XML::Node *to_repr, bool prepend=false)
moves all the children of from_repr to to_repr, either before the existing children or after them.
static bool tidy_operator_excessive_nesting(SPObject **item, bool)
redundant nesting: <font a><font b>abc</font></font> -> <font b>abc</font> excessive nesting: <font a...
void sp_te_adjust_linespacing_screen(SPItem *text, Inkscape::Text::Layout::iterator const &, Inkscape::Text::Layout::iterator const &, SPDesktop *desktop, gdouble by)
static SPObject * get_common_ancestor(SPObject *text, SPObject *one, SPObject *two)
returns the object in the tree which is the closest ancestor of both one and two.
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...
bool is_part_of_text_subtree(SPObject const *obj)
void sp_te_adjust_line_height(SPObject *object, double amount, double average, bool top_level=true)
Adjust the line height by 'amount'.
static SPString * find_last_string_child_not_equal_to(SPObject *root, SPObject *not_obj)
helper for tidy_operator_styled_whitespace(), finds the last string object in a paragraph which is no...
static void move_to_end_of_paragraph(SPObject **para_obj, Glib::ustring::iterator *text_iter)
positions para_obj and text_iter to be pointing at the end of the last string in the last leaf object...
TextTagAttributes * text_tag_attributes_at_position(SPItem *item, Inkscape::Text::Layout::iterator const &position, unsigned *char_index)
Returns the attributes block and the character index within that block which represents the iterator ...
static void te_update_layout_now(SPItem *item)
static bool tidy_operator_styled_whitespace(SPObject **item, bool has_text_decoration)
whitespace-only spans: abc<font> </font>def -> abc<font></font> def abcdef ghi -> abcdef ghi
static SPObject * delete_line_break(SPObject *root, SPObject *item, bool *next_is_sibling)
delete the line break pointed to by item by merging its children into the next suitable object and de...
void sp_te_adjust_dy(SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *, double delta)
Inkscape::Text::Layout const * te_get_layout(SPItem const *item)
bool sp_te_delete(SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, iterator_pair &iter_pair)
static const gchar * tref_edit_message
void sp_te_apply_style(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPCSSAttr const *css)
Applies the given CSS fragment to the characters of the given text or flowtext object between start a...
static void erase_from_spstring(SPString *string_item, Glib::ustring::iterator iter_from, Glib::ustring::iterator iter_to)
erases the given characters from the given string and deletes the corresponding x/y/dx/dy/rotate attr...
static bool redundant_semi_nesting_processor(SPObject **item, SPObject *child, bool prepend)
helper for tidy_operator_redundant_semi_nesting().
static bool objects_have_equal_style(SPObject const *parent, SPObject const *child)
Returns true if the style of parent and the style of child are equivalent (and hence the children of ...
static bool tidy_operator_inexplicable_spans(SPObject **item, bool)
inexplicable spans: abcdefghi -> "abc""def""ghi" the repeated strings will be merged by another opera...
void sp_te_adjust_kerning_screen(SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *desktop, Geom::Point by)
Inkscape::Text::Layout::iterator sp_te_replace(SPItem *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, gchar const *utf8)
static void insert_into_spstring(SPString *string_item, Glib::ustring::iterator iter_at, gchar const *utf8)
inserts the given characters into the given string and inserts corresponding new x/y/dx/dy/rotate att...
static bool tidy_operator_repeated_spans(SPObject **item, bool)
repeated spans: <font a>abc</font><font a>def</font> -> <font a>abcdef</font>
void sp_te_set_rotation(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPDesktop *, gdouble degrees)
bool is_top_level_text_object(SPObject const *obj)
static void recursively_apply_style(SPObject *common_ancestor, SPCSSAttr const *css, SPObject *start_item, Glib::ustring::iterator start_text_iter, SPObject *end_item, Glib::ustring::iterator end_text_iter, char const *span_object_name)
applies the given style to all the objects at the given level and below which are between start_item ...
static bool tidy_operator_empty_spans(SPObject **item, bool)
empty spans: abc<span>def -> abcdef
static TextTagAttributes * attributes_for_object(SPObject *object)
returns the attributes for an object, or NULL if it isn't a text, tspan, tref, or textpath.
static SPString * sp_te_seek_next_string_recursive(SPObject *start_obj)
finds the first SPString after the given position, including children, excluding parents
static bool tidy_xml_tree_recursively(SPObject *root, bool has_text_decoration)
Recursively walks the xml tree calling a set of cleanup operations on every child.
static bool tidy_operator_redundant_double_nesting(SPObject **item, bool)
redundant double nesting: <font b><font a><font b>abc</font>def</font>ghi</font> -> <font b>abc<font ...
Inkscape::Text::Layout::iterator sp_te_insert(SPItem *item, Inkscape::Text::Layout::iterator const &position, gchar const *utf8)
Inserts the given text into a text or flowroot object.
void sp_te_set_repr_text_multiline(SPItem *text, gchar const *str)
bool sp_te_input_is_empty(SPObject const *item)
Returns true if the user has typed nothing in the text box.
std::pair< Inkscape::Text::Layout::iterator, Inkscape::Text::Layout::iterator > iterator_pair