17#include <glibmm/i18n.h>
18#include <glibmm/regex.h>
49 if (is<SPText>(*i) || is<SPFlowtext>(*i))
80 if (!text || !shape || boost::distance(selection->
items()) != 2) {
91 if (is<SPFlowtext>(text)) {
93 if (!cast_unsafe<SPFlowtext>(text)->layout.outputExists()) {
96 _(
"The flowed text(s) must be <b>visible</b> in order to be put on a path."));
120 if (
auto textitem = cast<SPText>(text)) {
122 textitem->remove_newlines();
129 cast<SPText>(text)->_adjustFontsizeRecursive (text, text->
transform.
descrim());
133 std::vector<Inkscape::XML::Node *> text_reprs;
135 text_reprs.push_back(o.getRepr());
141 gchar *href_str = g_strdup_printf(
"#%s", shape->
getRepr()->
attribute(
"id"));
151 for (
auto i=text_reprs.rbegin();i!=text_reprs.rend();++i) {
155 if (!strcmp(copy->name(),
"svg:tspan")) {
156 copy->removeAttribute(
"sodipodi:role");
157 copy->removeAttribute(
"x");
158 copy->removeAttribute(
"y");
203 std::vector<SPItem *> vec(selection->
items().begin(), selection->
items().end());
218 gchar **xa_space = g_strsplit(x,
" ", 0);
219 gchar **xa_comma = g_strsplit(x,
",", 0);
220 if (xa_space && *xa_space && *(xa_space + 1)) {
222 }
else if (xa_comma && *xa_comma && *(xa_comma + 1)) {
225 g_strfreev(xa_space);
226 g_strfreev(xa_comma);
231 i.requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_TEXT_LAYOUT_MODIFIED_FLAG);
254 if (!is<SPText>(obj) && !is<SPTSpan>(obj) && !is<SPFlowtext>(obj)) {
281 if (is<SPText>(text)) {
283 Glib::ustring shapes;
286 if (is<SPShape>(
item)) {
287 if (!shapes.empty()) shapes +=
" ";
318 if (!text || !shape || boost::distance(selection->
items()) < 2) {
324 if (prefs->getBool(
"/tools/text/use_svg2",
true)) {
327 if (is<SPText>(text)) {
329 Glib::ustring shapes;
332 if (is<SPShape>(
item)) {
333 if (!shapes.empty()) {
340 static_cast<SPText *
>(text)->_adjustFontsizeRecursive(text, ex);
356 if (is<SPText>(text) || is<SPFlowtext>(text)) {
359 cast<SPText>(text)->_adjustFontsizeRecursive(text, ex);
368 g_return_if_fail(is<SPFlowtext>(root_object));
373 g_return_if_fail(is<SPFlowregion>(
object));
379 if (is<SPShape>(
item)){
381 clone->setAttribute(
"x",
"0");
382 clone->setAttribute(
"y",
"0");
384 clone->setAttribute(
"xlink:href", href_str);
392 if (is<SPText>(text)) {
396 g_return_if_fail(is<SPFlowpara>(
object));
409 if (is<SPFlowpara>(&o)) {
413 g_return_if_fail(is<SPFlowpara>(
object));
447 std::vector<SPItem*> new_objs;
448 std::vector<SPItem *> old_objs;
451 for (
auto i :
items) {
453 auto flowtext = cast<SPFlowtext>(i);
454 auto text = cast<SPText>(i);
460 double ex = (flowtext->transform).descrim();
463 if (text_string.empty()) {
472 rtext->
setAttribute(
"style", flowtext->getRepr()->attribute(
"style"));
475 Geom::OptRect bbox = flowtext->geometricBounds(flowtext->i2doc_affine());
490 flowtext->parent->getRepr()->appendChild(rtext);
494 auto text = cast<SPText>(text_object);
495 text->_adjustFontsizeRecursive(text, ex);
497 new_objs.push_back((
SPItem *)text_object);
498 old_objs.push_back(flowtext);
505 if (text->has_shape_inside()) {
507 auto old_point = text->getBaselinePoint();
511 Geom::OptRect bbox = text->geometricBounds(text->i2doc_affine());
529 for (
auto j : text->childList(
false)) {
530 auto tspan = cast<SPTSpan>(j);
532 tspan->getRepr()->removeAttribute(
"x");
533 tspan->getRepr()->removeAttribute(
"y");
534 tspan->getRepr()->removeAttribute(
"sodipodi:role");
538 text->rebuildLayout();
539 auto new_point = text->getBaselinePoint();
540 if (old_point && new_point) {
541 auto move =
Geom::Translate(*old_point - *new_point) * text->transform;
542 text->doWriteTransform(move, &move,
false);
549 if (new_objs.size() != 0) {
553 reverse(new_objs.begin(), new_objs.end());
557 for (
auto i : old_objs) {
558 i->deleteObject(
true);
568 auto desktop = SP_ACTIVE_DESKTOP;
570 std::vector<SPText*> results;
571 std::vector<SPText*> to_delete;
576 for(
auto item : selection->items()) {
577 auto text = cast<SPText>(
item);
581 auto parent = text->parent->getRepr();
582 auto sibling = text->getRepr();
584 auto const &layout = text->layout;
585 auto iter = layout.end();
586 while (iter != layout.begin()) {
590 if (!iter.prevCharacter()) {
594 if (layout.isWhitespace(iter))
597 auto str = Glib::ustring(1, layout.characterAt(iter));
598 auto point = layout.characterAnchorPoint(iter);
601 layout.getSourceOfCharacter(iter, &tspan);
610 for (
auto sp = tspan->
parent; sp && sp != text; sp = sp->parent) {
611 result_style->
merge(sp->style);
613 result_style->
merge(text->style);
615 Glib::ustring glyph_style = result_style->
writeIfDiff(text->parent->style);
622 new_node->
appendChild(xml_doc->createTextNode(str.c_str()));
625 parent->addChild(new_node, sibling);
626 auto new_text = cast<SPText>(doc->getObjectByRepr(new_node));
627 results.push_back(new_text);
630 to_delete.push_back(text);
634 for (
auto item : to_delete) {
638 if (results.empty()) {
640 _(
"Select <b>text(s)</b> to convert to glyphs."));
642 DocumentUndo::done(doc, _(
"Convert text to glyphs"), INKSCAPE_ICON(
"text-convert-to-regular"));
643 selection->setList(results);
656 _(
"Select <b>flowed text(s)</b> to convert."));
661 bool ignored =
false;
663 std::vector<Inkscape::XML::Node*> reprs;
664 std::vector<SPItem*>
items(selection->
items().begin(), selection->
items().end());
667 if (!is<SPFlowtext>(
item))
670 if (!cast_unsafe<SPFlowtext>(
item)->layout.outputExists()) {
691 reprs.push_back(repr);
697 }
else if (ignored) {
701 _(
"Flowed text(s) must be <b>visible</b> in order to be converted."));
706 _(
"<b>No flowed text(s)</b> to convert in the selection."));
713 std::vector<Glib::ustring> shapes_url = Glib::Regex::split_simple(
" ", prop);
715 for (
auto shape_url : shapes_url) {
716 if (shape_url.compare(0, 5,
"url(#") != 0 || shape_url.compare(shape_url.size() - 1, 1,
")") != 0) {
717 std::cerr <<
"text_relink_shapes_str: Invalid shape value: " << shape_url.raw() << std::endl;
719 auto old_id = shape_url.substr(5, shape_url.size() - 6);
720 auto find_it = old_to_new.find(old_id);
721 if (find_it != old_to_new.end()) {
722 res.append(
"url(#").append(find_it->second).append(
") ");
724 std::cerr <<
"Failed to replace reference " << old_id.raw() << std::endl;
730 assert(res.raw().back() ==
' ');
731 res.resize(res.size() - 1);
Coord descrim() const
Calculate the descriminant.
Axis-aligned rectangle that can be empty.
Two-dimensional point that doubles as a vector.
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.
SPItemRange items()
Returns a range of selected SPItems.
boost::enable_if< boost::is_base_of< SPObject, T >, void >::type setList(const std::vector< T * > &objs)
Selects exactly the specified objects.
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.
bool isEmpty()
Returns true if no items are selected.
static Preferences * get()
Access the singleton Preferences object.
The set of selected SPObjects for a given document and layer model.
void set(XML::Node *repr)
Set the selection to an XML node's SPObject.
Generates the layout for either wrapped or non-wrapped text and stores the result.
Alignment
For expressing paragraph alignment.
iterator end() const
Returns an iterator pointing just past the end of the last glyph, which is also just past the end of ...
Alignment paragraphAlignment(iterator const &it) const
Returns the actual alignment used for the paragraph containing the character pointed to by it.
iterator begin() const
Returns an iterator pointing at the first glyph of the flowed output.
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.
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 * duplicate(Document *doc) const =0
Create a duplicate of this node.
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.
To do: update description of desktop.
SPDocument * getDocument() const
Inkscape::MessageStack * messageStack() const
Inkscape::Selection * getSelection() const
Typed SVG document implementation.
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
Base class for visual SVG elements.
void doWriteTransform(Geom::Affine const &transform, Geom::Affine const *adv=nullptr, bool compensate=true)
Set a new transform on an object.
SPObject is an abstract base class of all of the document nodes at the SVG document level.
void setAttribute(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
void removeAttribute(char const *key)
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
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.
std::string getUrl() const
Get the id in a URL format.
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
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::WHITE_SPACE, SPIEnum< SPWhiteSpace > > white_space
white space (svg2)
T< SPAttr::TEXT_ANCHOR, SPIEnum< SPTextAnchor > > text_anchor
Anchor of the text (svg1.1 10.9.1)
T< SPAttr::SHAPE_INSIDE, SPIShapes > shape_inside
SVG2 Text Wrapping.
T< SPAttr::SHAPE_SUBTRACT, SPIShapes > shape_subtract
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.
Raw stack of active status messages.
static R & release(R &r)
Decrements the reference count of a anchored object.
Singleton class to access the preferences file in a convenient way.
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_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.
void sp_repr_css_unset_property(SPCSSAttr *css, gchar const *name)
Set a style property to "inkscape:unset".
C facade to Inkscape::XML::Node.
TODO: insert short description here.
TODO: insert short description here.
TODO: insert short description here.
Geom::Affine i2i_affine(SPObject const *src, SPObject const *dest)
TODO: insert short description here.
void sp_textpath_to_text(SPObject *tp)
bool SP_IS_TEXT_TEXTPATH(SPObject const *obj)
TODO: insert short description here.
Interface for XML documents.
virtual Node * createTextNode(char const *content)=0
virtual Node * createElement(char const *name)=0
SPStyle - a style object for SPItem objects.
void text_remove_from_path()
void text_flow_shape_subtract()
Glib::ustring text_relink_shapes_str(gchar const *prop, std::map< Glib::ustring, Glib::ustring > const &old_to_new)
void text_flow_into_shape()
static void text_remove_all_kerns_recursively(SPObject *o)
void text_remove_all_kerns()
static SPItem * text_or_flowtext_in_selection(Inkscape::Selection *selection)
static SPItem * shape_in_selection(Inkscape::Selection *selection)
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)