summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2015-12-05 14:40:56 +0000
committertavmjong-free <tavmjong@free.fr>2015-12-05 14:40:56 +0000
commit78005ad417dde6dddab40efacb757b1d6b0c03d0 (patch)
treea827191465ff949ec952b55ffed30fe943cab019 /src
parentadded comment + simpler rounding (diff)
downloadinkscape-78005ad417dde6dddab40efacb757b1d6b0c03d0.tar.gz
inkscape-78005ad417dde6dddab40efacb757b1d6b0c03d0.zip
Handle units in the 'x', 'y', 'dx', and 'dy' text and tspan attributes.
Fixed bugs: - https://launchpad.net/bugs/1522478 - https://launchpad.net/bugs/262528 - https://launchpad.net/bugs/168845 (bzr r14505)
Diffstat (limited to 'src')
-rw-r--r--src/sp-rect.cpp12
-rw-r--r--src/sp-text.cpp88
-rw-r--r--src/sp-tref.cpp2
-rw-r--r--src/sp-tspan.cpp32
-rw-r--r--src/svg/svg-length.cpp2
-rw-r--r--src/svg/svg-length.h2
-rw-r--r--src/text-tag-attributes.h5
7 files changed, 107 insertions, 36 deletions
diff --git a/src/sp-rect.cpp b/src/sp-rect.cpp
index e17d7373c..2ba9a7023 100644
--- a/src/sp-rect.cpp
+++ b/src/sp-rect.cpp
@@ -61,13 +61,13 @@ void SPRect::set(unsigned key, gchar const *value) {
switch (key) {
case SP_ATTR_X:
this->x.readOrUnset(value);
- this->x.update( ex, em, w );
+ this->x.update( em, ex, w );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
case SP_ATTR_Y:
this->y.readOrUnset(value);
- this->y.update( ex, em, h );
+ this->y.update( em, ex, h );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -75,7 +75,7 @@ void SPRect::set(unsigned key, gchar const *value) {
if (!this->width.read(value) || this->width.value < 0.0) {
this->width.unset();
}
- this->width.update( ex, em, w );
+ this->width.update( em, ex, w );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -83,7 +83,7 @@ void SPRect::set(unsigned key, gchar const *value) {
if (!this->height.read(value) || this->height.value < 0.0) {
this->height.unset();
}
- this->height.update( ex, em, h );
+ this->height.update( em, ex, h );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -91,7 +91,7 @@ void SPRect::set(unsigned key, gchar const *value) {
if (!this->rx.read(value) || this->rx.value <= 0.0) {
this->rx.unset();
}
- this->rx.update( ex, em, w );
+ this->rx.update( em, ex, w );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -99,7 +99,7 @@ void SPRect::set(unsigned key, gchar const *value) {
if (!this->ry.read(value) || this->ry.value <= 0.0) {
this->ry.unset();
}
- this->ry.update( ex, em, h );
+ this->ry.update( em, ex, h );
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
diff --git a/src/sp-text.cpp b/src/sp-text.cpp
index d351e58e3..c7dfdd694 100644
--- a/src/sp-text.cpp
+++ b/src/sp-text.cpp
@@ -93,7 +93,7 @@ void SPText::release() {
void SPText::set(unsigned int key, const gchar* value) {
//std::cout << "SPText::set: " << sp_attribute_name( key ) << ": " << (value?value:"Null") << std::endl;
- if (this->attributes.readSingleAttribute(key, value)) {
+ if (this->attributes.readSingleAttribute(key, value, style, &viewport)) {
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
} else {
switch (key) {
@@ -181,6 +181,16 @@ void SPText::update(SPCtx *ctx, guint flags) {
SP_OBJECT_CHILD_MODIFIED_FLAG |
SP_TEXT_LAYOUT_MODIFIED_FLAG ) )
{
+
+ SPItemCtx const *ictx = reinterpret_cast<SPItemCtx const *>(ctx);
+
+ double const w = ictx->viewport.width();
+ double const h = ictx->viewport.height();
+ double const em = style->font_size.computed;
+ double const ex = 0.5 * em; // fixme: get x height from pango or libnrtype.
+
+ attributes.update( em, ex, w, h );
+
/* fixme: It is not nice to have it here, but otherwise children content changes does not work */
/* fixme: Even now it may not work, as we are delayed */
/* fixme: So check modification flag everywhere immediate state is used */
@@ -576,7 +586,7 @@ unsigned SPText::_buildLayoutInput(SPObject *root, Inkscape::Text::Layout::Optio
SPString *str = dynamic_cast<SPString *>(child);
if (str) {
Glib::ustring const &string = str->string;
- // std::cout << " Appending: " << string << std::endl;
+ // std::cout << " Appending: >" << string << "<" << std::endl;
layout.appendText(string, root->style, child, &optional_attrs, child_attrs_offset + length);
length += string.length();
} else if (!sp_repr_is_meta_element(child->getRepr())) {
@@ -671,25 +681,30 @@ void SPText::_clearFlow(Inkscape::DrawingGroup *in_arena)
* TextTagAttributes implementation
*/
-void TextTagAttributes::readFrom(Inkscape::XML::Node const *node)
-{
- readSingleAttribute(SP_ATTR_X, node->attribute("x"));
- readSingleAttribute(SP_ATTR_Y, node->attribute("y"));
- readSingleAttribute(SP_ATTR_DX, node->attribute("dx"));
- readSingleAttribute(SP_ATTR_DY, node->attribute("dy"));
- readSingleAttribute(SP_ATTR_ROTATE, node->attribute("rotate"));
- readSingleAttribute(SP_ATTR_TEXTLENGTH, node->attribute("textLength"));
- readSingleAttribute(SP_ATTR_LENGTHADJUST, node->attribute("lengthAdjust"));
-}
-
-bool TextTagAttributes::readSingleAttribute(unsigned key, gchar const *value)
+// Not used.
+// void TextTagAttributes::readFrom(Inkscape::XML::Node const *node)
+// {
+// readSingleAttribute(SP_ATTR_X, node->attribute("x"));
+// readSingleAttribute(SP_ATTR_Y, node->attribute("y"));
+// readSingleAttribute(SP_ATTR_DX, node->attribute("dx"));
+// readSingleAttribute(SP_ATTR_DY, node->attribute("dy"));
+// readSingleAttribute(SP_ATTR_ROTATE, node->attribute("rotate"));
+// readSingleAttribute(SP_ATTR_TEXTLENGTH, node->attribute("textLength"));
+// readSingleAttribute(SP_ATTR_LENGTHADJUST, node->attribute("lengthAdjust"));
+// }
+
+bool TextTagAttributes::readSingleAttribute(unsigned key, gchar const *value, SPStyle const *style, Geom::Rect const *viewport)
{
+ // std::cout << "TextTagAttributes::readSingleAttribute: key: " << key
+ // << " value: " << (value?value:"Null") << std::endl;
std::vector<SVGLength> *attr_vector;
+ bool update_x = false;
+ bool update_y = false;
switch (key) {
- case SP_ATTR_X: attr_vector = &attributes.x; break;
- case SP_ATTR_Y: attr_vector = &attributes.y; break;
- case SP_ATTR_DX: attr_vector = &attributes.dx; break;
- case SP_ATTR_DY: attr_vector = &attributes.dy; break;
+ case SP_ATTR_X: attr_vector = &attributes.x; update_x = true; break;
+ case SP_ATTR_Y: attr_vector = &attributes.y; update_y = true; break;
+ case SP_ATTR_DX: attr_vector = &attributes.dx; update_x = true; break;
+ case SP_ATTR_DY: attr_vector = &attributes.dy; update_y = true; break;
case SP_ATTR_ROTATE: attr_vector = &attributes.rotate; break;
case SP_ATTR_TEXTLENGTH:
attributes.textLength.readOrUnset(value);
@@ -706,6 +721,19 @@ bool TextTagAttributes::readSingleAttribute(unsigned key, gchar const *value)
// FIXME: sp_svg_length_list_read() amalgamates repeated separators. This prevents unset values.
*attr_vector = sp_svg_length_list_read(value);
+
+ if( (update_x || update_y) && style != NULL && viewport != NULL ) {
+ double const w = viewport->width();
+ double const h = viewport->height();
+ double const em = style->font_size.computed;
+ double const ex = em * 0.5;
+ for(std::vector<SVGLength>::iterator it = attr_vector->begin(); it != attr_vector->end(); ++it) {
+ if( update_x )
+ it->update( em, ex, w );
+ if( update_y )
+ it->update( em, ex, h );
+ }
+ }
return true;
}
@@ -728,12 +756,26 @@ void TextTagAttributes::writeTo(Inkscape::XML::Node *node) const
}
}
+void TextTagAttributes::update( double em, double ex, double w, double h )
+{
+ for(std::vector<SVGLength>::iterator it = attributes.x.begin(); it != attributes.x.end(); ++it) {
+ it->update( em, ex, w );
+ }
+ for(std::vector<SVGLength>::iterator it = attributes.y.begin(); it != attributes.y.end(); ++it) {
+ it->update( em, ex, h );
+ }
+ for(std::vector<SVGLength>::iterator it = attributes.dx.begin(); it != attributes.dx.end(); ++it) {
+ it->update( em, ex, w );
+ }
+ for(std::vector<SVGLength>::iterator it = attributes.dy.begin(); it != attributes.dy.end(); ++it) {
+ it->update( em, ex, h );
+ }
+}
+
void TextTagAttributes::writeSingleAttributeLength(Inkscape::XML::Node *node, gchar const *key, const SVGLength &length)
{
if (length._set) {
- gchar single_value_string[32];
- g_ascii_formatd(single_value_string, sizeof (single_value_string), "%.8g", length.computed);
- node->setAttribute(key, single_value_string);
+ node->setAttribute(key, length.write().c_str());
} else
node->setAttribute(key, NULL);
}
@@ -744,13 +786,11 @@ void TextTagAttributes::writeSingleAttributeVector(Inkscape::XML::Node *node, gc
node->setAttribute(key, NULL);
else {
Glib::ustring string;
- gchar single_value_string[32];
// FIXME: this has no concept of unset values because sp_svg_length_list_read() can't read them back in
for (std::vector<SVGLength>::const_iterator it = attr_vector.begin() ; it != attr_vector.end() ; ++it) {
- g_ascii_formatd(single_value_string, sizeof (single_value_string), "%.8g", it->computed);
if (!string.empty()) string += ' ';
- string += single_value_string;
+ string += it->write();
}
node->setAttribute(key, string.c_str());
}
diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp
index aef18462a..ba592058b 100644
--- a/src/sp-tref.cpp
+++ b/src/sp-tref.cpp
@@ -92,7 +92,7 @@ void SPTRef::set(unsigned int key, const gchar* value) {
debug("0x%p %s(%u): '%s'",this,
sp_attribute_name(key),key,value ? value : "<no value>");
- if (this->attributes.readSingleAttribute(key, value)) { // x, y, dx, dy, rotate
+ if (this->attributes.readSingleAttribute(key, value, style, &viewport)) { // x, y, dx, dy, rotate
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
} else if (key == SP_ATTR_XLINK_HREF) { // xlink:href
if ( !value ) {
diff --git a/src/sp-tspan.cpp b/src/sp-tspan.cpp
index 7582cb9e6..05f8430ba 100644
--- a/src/sp-tspan.cpp
+++ b/src/sp-tspan.cpp
@@ -70,7 +70,7 @@ void SPTSpan::release() {
}
void SPTSpan::set(unsigned int key, const gchar* value) {
- if (this->attributes.readSingleAttribute(key, value)) {
+ if (this->attributes.readSingleAttribute(key, value, style, &viewport)) {
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
} else {
switch (key) {
@@ -103,6 +103,20 @@ void SPTSpan::update(SPCtx *ctx, guint flags) {
}
SPItem::update(ctx, flags);
+
+ if (flags & ( SP_OBJECT_STYLE_MODIFIED_FLAG |
+ SP_OBJECT_CHILD_MODIFIED_FLAG |
+ SP_TEXT_LAYOUT_MODIFIED_FLAG ) )
+ {
+ SPItemCtx const *ictx = reinterpret_cast<SPItemCtx const *>(ctx);
+
+ double const w = ictx->viewport.width();
+ double const h = ictx->viewport.height();
+ double const em = style->font_size.computed;
+ double const ex = 0.5 * em; // fixme: get x height from pango or libnrtype.
+
+ attributes.update( em, ex, w, h );
+ }
}
void SPTSpan::modified(unsigned int flags) {
@@ -264,7 +278,7 @@ void SPTextPath::release() {
}
void SPTextPath::set(unsigned int key, const gchar* value) {
- if (this->attributes.readSingleAttribute(key, value)) {
+ if (this->attributes.readSingleAttribute(key, value, style, &viewport)) {
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
} else {
switch (key) {
@@ -304,6 +318,20 @@ void SPTextPath::update(SPCtx *ctx, guint flags) {
ochild->updateDisplay(ctx, flags);
}
}
+
+ if (flags & ( SP_OBJECT_STYLE_MODIFIED_FLAG |
+ SP_OBJECT_CHILD_MODIFIED_FLAG |
+ SP_TEXT_LAYOUT_MODIFIED_FLAG ) )
+ {
+ SPItemCtx const *ictx = reinterpret_cast<SPItemCtx const *>(ctx);
+
+ double const w = ictx->viewport.width();
+ double const h = ictx->viewport.height();
+ double const em = style->font_size.computed;
+ double const ex = 0.5 * em; // fixme: get x height from pango or libnrtype.
+
+ attributes.update( em, ex, w, h );
+ }
}
diff --git a/src/svg/svg-length.cpp b/src/svg/svg-length.cpp
index edbc59c36..cd995582d 100644
--- a/src/svg/svg-length.cpp
+++ b/src/svg/svg-length.cpp
@@ -463,7 +463,7 @@ unsigned int sp_svg_length_read_ldd(gchar const *str, SVGLength::Unit *unit, dou
return r;
}
-std::string const SVGLength::write()
+std::string SVGLength::write() const
{
return sp_svg_length_write_with_units(*this);
}
diff --git a/src/svg/svg-length.h b/src/svg/svg-length.h
index 84056dd5f..2aaf248b1 100644
--- a/src/svg/svg-length.h
+++ b/src/svg/svg-length.h
@@ -57,7 +57,7 @@ public:
bool read(char const *str);
void readOrUnset(char const *str, Unit u = NONE, float v = 0, float c = 0);
bool readAbsolute(char const *str);
- std::string const write();
+ std::string write() const;
// To set 'v' use '='
void set(Unit u, float v); // Sets computed value based on u and v.
void set(Unit u, float v, float c); // Sets all three values.
diff --git a/src/text-tag-attributes.h b/src/text-tag-attributes.h
index 7a389ed39..2cf7a8bde 100644
--- a/src/text-tag-attributes.h
+++ b/src/text-tag-attributes.h
@@ -31,11 +31,14 @@ public:
/** Process the parameters from the set() function of SPObject.
Returns true if \a key was a recognised attribute. */
- bool readSingleAttribute(unsigned key, gchar const *value);
+ bool readSingleAttribute(unsigned key, gchar const *value, SPStyle const *style, Geom::Rect const *viewport);
/// Write out all the contents of #attributes to the given node.
void writeTo(Inkscape::XML::Node *node) const;
+ /// Update relative values
+ void update( double em, double ex, double w, double h );
+
/** For tspan role=line elements we should not use the set x,y
coordinates since that would overrule the values calculated by the
text layout engine, however if there are more than one element in