summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2019-09-06 09:10:24 +0000
committerTavmjong Bah <tavmjong@free.fr>2019-09-06 09:10:24 +0000
commit8a2c433d2042c1389dbc235278d20e70e3b92c0d (patch)
tree0acf40642441c89d2ea77bdc947a5a44cebf5c57 /src
parentFix error in GTK launch script (diff)
downloadinkscape-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.cpp48
-rw-r--r--src/object/sp-text.h19
-rw-r--r--src/style-internal.cpp57
-rw-r--r--src/style-internal.h22
-rw-r--r--src/style.cpp2
-rw-r--r--src/style.h4
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] = &marker;
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;