diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2019-09-06 09:10:24 +0000 |
|---|---|---|
| committer | Tavmjong Bah <tavmjong@free.fr> | 2019-09-06 09:10:24 +0000 |
| commit | 8a2c433d2042c1389dbc235278d20e70e3b92c0d (patch) | |
| tree | 0acf40642441c89d2ea77bdc947a5a44cebf5c57 /src | |
| parent | Fix error in GTK launch script (diff) | |
| download | inkscape-8a2c433d2042c1389dbc235278d20e70e3b92c0d.tar.gz inkscape-8a2c433d2042c1389dbc235278d20e70e3b92c0d.zip | |
Add listeners for when shapes used by text are changed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/object/sp-text.cpp | 48 | ||||
| -rw-r--r-- | src/object/sp-text.h | 19 | ||||
| -rw-r--r-- | src/style-internal.cpp | 57 | ||||
| -rw-r--r-- | src/style-internal.h | 22 | ||||
| -rw-r--r-- | src/style.cpp | 2 | ||||
| -rw-r--r-- | src/style.h | 4 |
6 files changed, 121 insertions, 31 deletions
diff --git a/src/object/sp-text.cpp b/src/object/sp-text.cpp index da9c2cca9..ee020ab54 100644 --- a/src/object/sp-text.cpp +++ b/src/object/sp-text.cpp @@ -285,6 +285,21 @@ Inkscape::XML::Node *SPText::write(Inkscape::XML::Document *xml_doc, Inkscape::X return repr; } + +void +SPText::shape_changed (Inkscape::XML::Node *repr, char const *key, char const *oldval, + char const *newval, bool is_interactive, void* data) { + + SPText* text = static_cast<SPText*>(data); + if (text) { + text->updateRepr(); // Why is this necessary, it is definitely overkill! + // text->rebuildLayout(); + } else { + std::cerr << "SPText::shape_changed: no text object!" << std::endl; + } +} + + Geom::OptRect SPText::bbox(Geom::Affine const &transform, SPItem::BBoxType type) const { Geom::OptRect bbox = SP_TEXT(this)->layout.bounds(transform); @@ -473,17 +488,10 @@ void SPText::_buildLayoutInit() exclusion_shape = _buildExclusionShape(); } - // Extract out shapes (a comma separated list of urls) - Glib::ustring shapeInside_value = style->shape_inside.value; - std::vector<Glib::ustring> shapes_url = Glib::Regex::split_simple(" ", shapeInside_value); - for (auto shape_url : shapes_url) { - if ( shape_url.compare(0,5,"url(#") != 0 || shape_url.compare(shape_url.size()-1,1,")") != 0 ){ - std::cerr << "SPText::_buildLayoutInit(): Invalid shape-inside value: " << shape_url << std::endl; - } else { - shape_url.erase(0,5); - shape_url.erase(shape_url.size()-1,1); - // std::cout << "SPText::_buildLayoutInit(): shape-inside: " << shape_url << std::endl; - SPShape *shape = dynamic_cast<SPShape *>(document->getObjectById( shape_url )); + // Find inside shape curves + for (auto shape_id : style->shape_inside.shape_ids) { + + SPShape *shape = dynamic_cast<SPShape *>(document->getObjectById( shape_id )); if ( shape ) { // This code adapted from sp-flowregion.cpp: GetDest() @@ -535,9 +543,6 @@ void SPText::_buildLayoutInit() } else { std::cerr << "SPText::_buildLayoutInit(): Failed to get curve." << std::endl; } - } else { - std::cerr << "SPText::_buildLayoutInit(): Failed to find shape." << std::endl; - } } } @@ -726,19 +731,9 @@ Shape* SPText::_buildExclusionShape() const Shape *result = new Shape(); // Union of all exclusion shapes Shape *shape_temp = new Shape(); - Glib::ustring shapeSubtract_value = style->shape_subtract.value; + for(auto shape_id : style->shape_subtract.shape_ids) { - // Extract out shapes (a comma separated list of urls) - std::vector<Glib::ustring> shapes_url = Glib::Regex::split_simple(" ", shapeSubtract_value); - - for(auto shape_url : shapes_url) { - if ( shape_url.compare(0,5,"url(#") != 0 || shape_url.compare(shape_url.size()-1,1,")") != 0 ){ - std::cerr << "SPText::_buildExclusionShape(): Invalid shape-inside value: " << shape_url << std::endl; - } else { - shape_url.erase(0,5); - shape_url.erase(shape_url.size()-1,1); - // std::cout << "SPText::_buildExclusionShape(): shape-inside: " << shape_url << std::endl; - SPShape *shape = dynamic_cast<SPShape *>(document->getObjectById( shape_url )); + SPShape *shape = dynamic_cast<SPShape *>(document->getObjectById( shape_id )); if ( shape ) { // This code adapted from sp-flowregion.cpp: GetDest() if (!(shape->_curve)) { @@ -772,7 +767,6 @@ Shape* SPText::_buildExclusionShape() const } } } - } } return result; } diff --git a/src/object/sp-text.h b/src/object/sp-text.h index d6016b3b4..3b7880a88 100644 --- a/src/object/sp-text.h +++ b/src/object/sp-text.h @@ -17,12 +17,14 @@ #include <cstddef> #include <sigc++/sigc++.h> -#include "libnrtype/Layout-TNG.h" +#include "desktop.h" #include "sp-item.h" #include "sp-string.h" // Provides many other headers with SP_IS_STRING #include "text-tag-attributes.h" -#include "desktop.h" +#include "libnrtype/Layout-TNG.h" + +#include "xml/node-event-vector.h" #define SP_TEXT(obj) (dynamic_cast<SPText*>((SPObject*)obj)) #define SP_IS_TEXT(obj) (dynamic_cast<const SPText*>((SPObject*)obj) != NULL) @@ -95,6 +97,10 @@ public: void modified(unsigned int flags) override; Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, unsigned int flags) override; + /** Callback for when a shape changes and we must reflow text. */ + static void shape_changed (Inkscape::XML::Node *repr, char const *key, char const *oldval, + char const *newval, bool is_interactive, void* data); + Geom::OptRect bbox(Geom::Affine const &transform, SPItem::BBoxType type) const override; void print(SPPrintContext *ctx) override; const char* displayName() const override; @@ -112,6 +118,15 @@ public: std::vector<Glib::ustring> get_shapes() const; // Gets list of shapes in shape-inside. }; +// For listeners in shapes that hold wrapped text. +static const Inkscape::XML::NodeEventVector text_shape_events = { + nullptr, /* child added */ + nullptr, /* child removed */ + SPText::shape_changed, /* attribute changed */ + nullptr, /* content changed */ + nullptr, /* order changed */ +}; + SPItem *create_text_with_inline_size (SPDesktop *desktop, Geom::Point p0, Geom::Point p1); SPItem *create_text_with_rectangle (SPDesktop *desktop, Geom::Point p0, Geom::Point p1); diff --git a/src/style-internal.cpp b/src/style-internal.cpp index 15c080d62..6a8ff6f89 100644 --- a/src/style-internal.cpp +++ b/src/style-internal.cpp @@ -35,6 +35,8 @@ #include "streq.h" #include "strneq.h" +#include "object/sp-text.h" + #include "svg/svg.h" #include "svg/svg-color.h" #include "svg/css-ostringstream.h" @@ -1099,6 +1101,61 @@ SPIString::operator==(const SPIBase& rhs) { } +// SPIShapes ------------------------------------------------------------ + +// Used to add/remove listeners for text wrapped in shapes. +// Note: this is done differently than for patterns, etc. where presentation attributes can be used. +// 'shape-inside' and 'shape-subtract' are only properties. +void +SPIShapes::read( gchar const *str) { + + if (!style) { + std::cerr << "SPIShapes::read: no style!" << std::endl; + return; + } + + if( !str ) return; + + set = true; + inherit = false; + value = g_strdup(str); + + // The object/repr this property is connected to.. + SPObject* object = style->object; + SPDocument* document = object->document; + Inkscape::XML::Node *text_repr = object->getRepr(); + + // Clear previously set listeners + for (auto shape_id : shape_ids) { + SPObject* shape_object = document->getObjectById (shape_id); + if (shape_object) { + Inkscape::XML::Node *shape_node = shape_object->getRepr(); + shape_node->removeListenerByData(object); + } + } + shape_ids.clear(); + + // Add new listeners + std::vector<Glib::ustring> shapes_url = Glib::Regex::split_simple(" ", str); + for (auto shape_url : shapes_url) { + + if ( shape_url.compare(0,5,"url(#") != 0 || shape_url.compare(shape_url.size()-1,1,")") != 0 ){ + std::cerr << "SPIShapes::read: Invalid shape value: " << shape_url << std::endl; + } else { + shape_url.erase(0,5); + shape_url.erase(shape_url.size()-1,1); + + shape_ids.push_back(shape_url); + + SPObject* shape_object = document->getObjectById (shape_url); + if (shape_object) { + Inkscape::XML::Node *shape_node = shape_object->getRepr(); + shape_node->addListener(&text_shape_events, object); + } + } + } +} + // SPIColor ------------------------------------------------------------- diff --git a/src/style-internal.h b/src/style-internal.h index a28474870..8cdf29144 100644 --- a/src/style-internal.h +++ b/src/style-internal.h @@ -716,6 +716,28 @@ public: gchar *value_default; }; +/// Shapes type internal to SPStyle. +// Used for 'shape-inside', shape-subtract' +// Differs from SPIString by creating/deleting listeners on referenced shapes. +class SPIShapes : public SPIString +{ + +public: + SPIShapes() + : SPIString() + {} + + // TODO probably want to avoid gchar* and c-style strings. + SPIShapes( Glib::ustring const &name, gchar const* value_default_in = nullptr ) + : SPIString( name, value_default_in ) + {} + + void read( gchar const *str ) override; + +public: + std::vector<Glib::ustring> shape_ids; +}; + /// Color type internal to SPStyle, FIXME Add string value to store SVG named color. class SPIColor : public SPIBase { diff --git a/src/style.cpp b/src/style.cpp index 9af026bd1..b54d3feda 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -456,6 +456,8 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) : // SPIPaint, SPIFilter needs access to 'this' (SPStyle) // for setting up signals... 'fill', 'stroke' already done filter.setStylePointer( this ); + shape_inside.setStylePointer( this ); + shape_subtract.setStylePointer( this ); // Used to iterate over markers marker_ptrs[SP_MARKER_LOC] = ▮ diff --git a/src/style.h b/src/style.h index 9e46fa3ea..3179c781b 100644 --- a/src/style.h +++ b/src/style.h @@ -173,8 +173,8 @@ public: SPIEnum white_space; /** SVG2 Text Wrapping */ - SPIString shape_inside; - SPIString shape_subtract; + SPIShapes shape_inside; + SPIShapes shape_subtract; SPILength shape_padding; SPILength shape_margin; SPILength inline_size; |
