summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2014-07-30 08:31:31 +0000
committertavmjong-free <tavmjong@free.fr>2014-07-30 08:31:31 +0000
commitb7ebc313abd7f6aa501370d58ba54e6169e4218e (patch)
tree779a7b4b4f1cce041cffd987d530e4222f930ebe /src
parentFix a bug pointed by su_v on fillet-chamfer open paths (diff)
downloadinkscape-b7ebc313abd7f6aa501370d58ba54e6169e4218e.tar.gz
inkscape-b7ebc313abd7f6aa501370d58ba54e6169e4218e.zip
Read CSS Text 3 'white-space' property, SVG 2 <text> 'width', 'height' attributes.
(bzr r13341.1.110)
Diffstat (limited to 'src')
-rw-r--r--src/attributes.cpp10
-rw-r--r--src/attributes.h31
-rw-r--r--src/sp-string.cpp119
-rw-r--r--src/sp-text.cpp30
-rw-r--r--src/sp-text.h6
-rw-r--r--src/style-enums.h17
-rw-r--r--src/style.cpp10
-rw-r--r--src/style.h40
8 files changed, 212 insertions, 51 deletions
diff --git a/src/attributes.cpp b/src/attributes.cpp
index da7b25f03..3cca90105 100644
--- a/src/attributes.cpp
+++ b/src/attributes.cpp
@@ -413,10 +413,6 @@ static SPStyleProp const props[] = {
/* Text */
{SP_PROP_TEXT_INDENT, "text-indent"},
{SP_PROP_TEXT_ALIGN, "text-align"},
- {SP_PROP_TEXT_DECORATION, "text-decoration"},
- {SP_PROP_TEXT_DECORATION_LINE, "text-decoration-line"},
- {SP_PROP_TEXT_DECORATION_STYLE,"text-decoration-style"},
- {SP_PROP_TEXT_DECORATION_COLOR,"text-decoration-color"},
{SP_PROP_LINE_HEIGHT, "line-height"},
{SP_PROP_LETTER_SPACING, "letter-spacing"},
{SP_PROP_WORD_SPACING, "word-spacing"},
@@ -433,6 +429,12 @@ static SPStyleProp const props[] = {
{SP_PROP_GLYPH_ORIENTATION_VERTICAL, "glyph-orientation-vertical"},
{SP_PROP_KERNING, "kerning"},
{SP_PROP_TEXT_ANCHOR, "text-anchor"},
+ {SP_PROP_WHITE_SPACE, "white-space"},
+ /* Text Decoration */
+ {SP_PROP_TEXT_DECORATION, "text-decoration"},
+ {SP_PROP_TEXT_DECORATION_LINE, "text-decoration-line"},
+ {SP_PROP_TEXT_DECORATION_STYLE,"text-decoration-style"},
+ {SP_PROP_TEXT_DECORATION_COLOR,"text-decoration-color"},
/* Misc */
{SP_PROP_CLIP, "clip"},
{SP_PROP_COLOR, "color"},
diff --git a/src/attributes.h b/src/attributes.h
index 82e7ca8a6..47199ac51 100644
--- a/src/attributes.h
+++ b/src/attributes.h
@@ -399,9 +399,11 @@ enum SPAttributeEnum {
SP_ATTR_TEXT_EXCLUDE,
SP_ATTR_LAYOUT_OPTIONS,
- /* CSS2 */
- /* Custom full font name because Font stuff below is inadequate */
+ /* CSS & SVG Properties */
+
+ /* Custom full font name because Font stuff below is inadequate REMOVE ME */
SP_PROP_INKSCAPE_FONT_SPEC,
+
/* Font */
SP_PROP_FONT,
SP_PROP_FONT_FAMILY,
@@ -411,18 +413,16 @@ enum SPAttributeEnum {
SP_PROP_FONT_STYLE,
SP_PROP_FONT_VARIANT,
SP_PROP_FONT_WEIGHT,
- /* Text */
+
+ /* Text Layout */
SP_PROP_TEXT_INDENT,
SP_PROP_TEXT_ALIGN,
- SP_PROP_TEXT_DECORATION, /* SVG 1 underline etc.( no color or style) OR SVG2 with _LINE, _STYLE, _COLOR values */
- SP_PROP_TEXT_DECORATION_LINE, /* SVG 2 underline etc. */
- SP_PROP_TEXT_DECORATION_STYLE, /* SVG 2 proposed solid [SVG 1], dotted, etc.)*/
- SP_PROP_TEXT_DECORATION_COLOR, /* SVG 2 proposed same as text [SVG 1], specified*/
+
SP_PROP_LINE_HEIGHT,
SP_PROP_LETTER_SPACING,
SP_PROP_WORD_SPACING,
SP_PROP_TEXT_TRANSFORM,
- /* text (css3) */
+
SP_PROP_DIRECTION,
SP_PROP_BLOCK_PROGRESSION,
SP_PROP_WRITING_MODE,
@@ -434,6 +434,14 @@ enum SPAttributeEnum {
SP_PROP_GLYPH_ORIENTATION_VERTICAL,
SP_PROP_KERNING,
SP_PROP_TEXT_ANCHOR,
+ SP_PROP_WHITE_SPACE,
+
+ /* Text Decoration */
+ SP_PROP_TEXT_DECORATION, /* SVG 1 underline etc.( no color or style) OR SVG2 with _LINE, _STYLE, _COLOR values */
+ SP_PROP_TEXT_DECORATION_LINE, /* SVG 2 underline etc. */
+ SP_PROP_TEXT_DECORATION_STYLE, /* SVG 2 proposed solid [SVG 1], dotted, etc.)*/
+ SP_PROP_TEXT_DECORATION_COLOR, /* SVG 2 proposed same as text [SVG 1], specified*/
+
/* Misc */
SP_PROP_CLIP,
SP_PROP_COLOR,
@@ -443,24 +451,29 @@ enum SPAttributeEnum {
SP_PROP_VISIBILITY,
SP_PROP_BLEND_MODE,
SP_PROP_ISOLATION,
+
/* SVG */
/* Clip/Mask */
SP_PROP_CLIP_PATH,
SP_PROP_CLIP_RULE,
SP_PROP_MASK,
SP_PROP_OPACITY,
+
/* Filter */
SP_PROP_ENABLE_BACKGROUND,
SP_PROP_FILTER,
SP_PROP_FLOOD_COLOR,
SP_PROP_FLOOD_OPACITY,
SP_PROP_LIGHTING_COLOR,
+
/* Gradient */
SP_PROP_STOP_COLOR,
SP_PROP_STOP_OPACITY,
SP_PROP_STOP_PATH,
+
/* Interactivity */
SP_PROP_POINTER_EVENTS,
+
/* Paint */
SP_PROP_COLOR_INTERPOLATION,
SP_PROP_COLOR_INTERPOLATION_FILTERS,
@@ -487,10 +500,12 @@ enum SPAttributeEnum {
SP_PROP_STROKE_OPACITY,
SP_PROP_STROKE_WIDTH,
SP_PROP_TEXT_RENDERING,
+
/* Conditional */
SP_PROP_SYSTEM_LANGUAGE,
SP_PROP_REQUIRED_FEATURES,
SP_PROP_REQUIRED_EXTENSIONS,
+
/* LivePathEffect */
SP_PROP_PATH_EFFECT,
};
diff --git a/src/sp-string.cpp b/src/sp-string.cpp
index e9dfc168b..b561187d0 100644
--- a/src/sp-string.cpp
+++ b/src/sp-string.cpp
@@ -30,10 +30,14 @@
#include "sp-string.h"
+#include "style.h"
+
#include "xml/repr.h"
#include "sp-factory.h"
+#include <iostream>
+
namespace {
SPObject* createString() {
return new SPString();
@@ -65,45 +69,110 @@ void SPString::release() {
void SPString::read_content() {
- SPString* object = this;
+ SPString* object = this;
SPString *string = SP_STRING(object);
string->string.clear();
//XML Tree being used directly here while it shouldn't be.
gchar const *xml_string = string->getRepr()->content();
- // see algorithms described in svg 1.1 section 10.15
- if (object->xml_space.value == SP_XML_SPACE_PRESERVE) {
- for ( ; *xml_string ; xml_string = g_utf8_next_char(xml_string) ) {
- gunichar c = g_utf8_get_char(xml_string);
- if ((c == 0xa) || (c == 0xd) || (c == '\t')) {
- c = ' ';
- }
- string->string += c;
+
+ // std::cout << ">" << (xml_string?xml_string:"Null") << "<" << std::endl;
+
+ // SVG2/CSS Text Level 3 'white-space' has five values.
+ // See: http://dev.w3.org/csswg/css-text/#white-space
+ // | New Lines | Spaces/Tabs | Text Wrapping
+ // ---------|------------|--------------|--------------
+ // normal | Collapes | Collapse | Wrap
+ // pre | Preserve | Preserve | No Wrap
+ // nowrap | Collapse | Collapse | No Wrap
+ // pre-wrap | Preserve | Preserve | Wrap
+ // pre-line | Preserve | Collapse | Wrap
+
+ // 'xml:space' has two values:
+ // 'default' which corresponds to 'normal' (without wrapping).
+ // 'preserve' which corresponds to 'pre' except new lines are converted to spaces.
+ // See algorithms described in svg 1.1 section 10.15
+
+ bool collapse_space = true;
+ bool collapse_line = true;
+ bool is_css = false;
+
+ // Strings don't have style, check parent for style
+ if( object->parent && object->parent->style ) {
+ if( object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PRE ||
+ object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PREWRAP ||
+ object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PRELINE ) {
+ collapse_line = false;
+ }
+ if( object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PRE ||
+ object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PREWRAP ) {
+ collapse_space = false;
+ }
+ if( object->parent->style->white_space.computed != SP_CSS_WHITE_SPACE_NORMAL ) {
+ is_css = true; // If white-space not normal, we assume white-space is set.
}
}
- else {
- bool whitespace = false;
- for ( ; *xml_string ; xml_string = g_utf8_next_char(xml_string) ) {
- gunichar c = g_utf8_get_char(xml_string);
- if ((c == 0xa) || (c == 0xd)) {
+ if( !is_css ) {
+ // SVG 2: Use 'xml:space' only if 'white-space' not 'normal'.
+ if (object->xml_space.value == SP_XML_SPACE_PRESERVE) {
+ collapse_space = false;
+ }
+ }
+
+ bool white_space = false;
+ for ( ; *xml_string ; xml_string = g_utf8_next_char(xml_string) ) {
+
+ gunichar c = g_utf8_get_char(xml_string);
+ switch (c) {
+ case 0xd: // Carriage return
+ // XML Parsers convert 0xa, 0xd, 0xD 0xA to 0xA. CSS also follows this rule so we
+ // should never see 0xd.
+ std::cerr << "SPString: Carriage Return found! Argh!" << std::endl;
continue;
- }
- if ((c == ' ') || (c == '\t')) {
- whitespace = true;
- } else {
- if (whitespace && (!string->string.empty() || (object->getPrev() != NULL))) {
+ break;
+ case 0xa: // Line feed
+ if( collapse_line ) {
+ if( !is_css && collapse_space ) continue; // xml:space == 'default' strips LFs.
+ white_space = true; // Convert to space and collapse
+ } else {
+ string->string += c; // Preserve line feed
+ continue;
+ }
+ break;
+ case '\t': // Tab
+ if( collapse_space ) {
+ white_space = true; // Convert to space and collapse
+ } else {
+ string->string += c; // Preserve tab
+ continue;
+ }
+ break;
+ case ' ': // Space
+ if( collapse_space ) {
+ white_space = true; // Collapse white space
+ } else {
+ string->string += c; // Preserve space
+ continue;
+ }
+ break;
+ default:
+ if( white_space && (!string->string.empty() || (object->getPrev() != NULL))) {
string->string += ' ';
}
string->string += c;
- whitespace = false;
- }
- }
- if (whitespace && object->getRepr()->next() != NULL) { // can't use SPObject::getNext() when the SPObject tree is still being built
- string->string += ' ';
- }
+ white_space = false;
+
+ } // End switch
+ } // End loop
+
+ // Insert white space at end if more text follows
+ if (white_space && object->getRepr()->next() != NULL) { // can't use SPObject::getNext() when the SPObject tree is still being built
+ string->string += ' ';
}
+
+ // std::cout << ">" << string->string << "<" << std::endl;
object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
diff --git a/src/sp-text.cpp b/src/sp-text.cpp
index ccc5adf59..3bb1e16d0 100644
--- a/src/sp-text.cpp
+++ b/src/sp-text.cpp
@@ -82,6 +82,10 @@ void SPText::build(SPDocument *doc, Inkscape::XML::Node *repr) {
this->readAttr( "dy" );
this->readAttr( "rotate" );
+ // SVG 2 Auto wrapped text
+ this->readAttr( "width" );
+ this->readAttr( "height" );
+
SPItem::build(doc, repr);
this->readAttr( "sodipodi:linespacing" ); // has to happen after the styles are read
@@ -92,6 +96,8 @@ 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)) {
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
} else {
@@ -109,6 +115,22 @@ void SPText::set(unsigned int key, const gchar* value) {
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_TEXT_LAYOUT_MODIFIED_FLAG);
break;
+ case SP_ATTR_WIDTH:
+ if (!this->width.read(value) || this->width.value < 0.0) {
+ this->width.unset();
+ }
+
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_HEIGHT:
+ if (!this->height.read(value) || this->height.value < 0.0) {
+ this->height.unset();
+ }
+
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
default:
SPItem::set(key, value);
break;
@@ -284,6 +306,14 @@ Inkscape::XML::Node *SPText::write(Inkscape::XML::Document *xml_doc, Inkscape::X
this->getRepr()->setAttribute("sodipodi:linespacing", NULL);
}
+ // SVG 2 Auto-wrapped text
+ if( this->width.computed > 0.0 ) {
+ sp_repr_set_svg_double(repr, "width", this->width.computed);
+ }
+ if( this->height.computed > 0.0 ) {
+ sp_repr_set_svg_double(repr, "height", this->height.computed);
+ }
+
SPItem::write(xml_doc, repr, flags);
return repr;
diff --git a/src/sp-text.h b/src/sp-text.h
index 5f0485083..b9ae745c9 100644
--- a/src/sp-text.h
+++ b/src/sp-text.h
@@ -45,7 +45,11 @@ public:
//semiprivate: (need to be accessed by the C-style functions still)
TextTagAttributes attributes;
Inkscape::Text::Layout layout;
-
+
+ // SVG 2 Auto-wrapped text
+ SVGLength width;
+ SVGLength height;
+
/** when the object is transformed it's nicer to change the font size
and coordinates when we can, rather than just applying a matrix
transform. is_root is used to indicate to the function that it should
diff --git a/src/style-enums.h b/src/style-enums.h
index 356029a40..024943458 100644
--- a/src/style-enums.h
+++ b/src/style-enums.h
@@ -113,6 +113,14 @@ enum SPTextAnchor {
SP_CSS_TEXT_ANCHOR_END
};
+enum SPWhiteSpace {
+ SP_CSS_WHITE_SPACE_NORMAL,
+ SP_CSS_WHITE_SPACE_PRE,
+ SP_CSS_WHITE_SPACE_NOWRAP,
+ SP_CSS_WHITE_SPACE_PREWRAP,
+ SP_CSS_WHITE_SPACE_PRELINE
+};
+
enum SPCSSBaselineShift {
SP_CSS_BASELINE_SHIFT_BASELINE,
SP_CSS_BASELINE_SHIFT_SUB,
@@ -326,6 +334,15 @@ static SPStyleEnum const enum_text_anchor[] = {
{NULL, -1}
};
+static SPStyleEnum const enum_white_space[] = {
+ {"normal", SP_CSS_WHITE_SPACE_NORMAL },
+ {"pre", SP_CSS_WHITE_SPACE_PRE },
+ {"nowrap", SP_CSS_WHITE_SPACE_NOWRAP },
+ {"pre-wrap", SP_CSS_WHITE_SPACE_PREWRAP},
+ {"pre-line", SP_CSS_WHITE_SPACE_PRELINE},
+ {NULL, -1}
+};
+
static SPStyleEnum const enum_direction[] = {
{"ltr", SP_CSS_DIRECTION_LTR},
{"rtl", SP_CSS_DIRECTION_RTL},
diff --git a/src/style.cpp b/src/style.cpp
index f0710e404..97aae016a 100644
--- a/src/style.cpp
+++ b/src/style.cpp
@@ -135,6 +135,7 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
writing_mode( "writing-mode", enum_writing_mode, SP_CSS_WRITING_MODE_LR_TB ),
baseline_shift(),
text_anchor( "text-anchor", enum_text_anchor, SP_CSS_TEXT_ANCHOR_START ),
+ white_space( "white-space", enum_white_space, SP_CSS_WHITE_SPACE_NORMAL ),
// General visual properties
clip_rule( "clip-rule", enum_clip_rule, SP_WIND_RULE_NONZERO ),
@@ -297,6 +298,7 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
_properties.push_back( &writing_mode );
_properties.push_back( &baseline_shift );
_properties.push_back( &text_anchor );
+ _properties.push_back( &white_space );
_properties.push_back( &clip_rule );
_properties.push_back( &display );
@@ -379,6 +381,7 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
// _propmap.insert( std::make_pair( writing_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::writing_mode ) ) );
// _propmap.insert( std::make_pair( baseline_shift.name, reinterpret_cast<SPIBasePtr>(&SPStyle::baseline_shift ) ) );
// _propmap.insert( std::make_pair( text_anchor.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_anchor ) ) );
+ // _propmap.insert( std::make_pair( white_space.name, reinterpret_cast<SPIBasePtr>(&SPStyle::white_space ) ) );
// _propmap.insert( std::make_pair( clip_rule.name, reinterpret_cast<SPIBasePtr>(&SPStyle::clip_rule ) ) );
// _propmap.insert( std::make_pair( display.name, reinterpret_cast<SPIBasePtr>(&SPStyle::display ) ) );
@@ -670,6 +673,9 @@ SPStyle::readIfUnset( gint id, gchar const *val ) {
case SP_PROP_TEXT_ANCHOR:
text_anchor.readIfUnset( val );
break;
+ case SP_PROP_WHITE_SPACE:
+ white_space.readIfUnset( val );
+ break;
case SP_PROP_BASELINE_SHIFT:
baseline_shift.readIfUnset( val );
break;
@@ -1623,6 +1629,9 @@ sp_style_unset_property_attrs(SPObject *o)
if (style->text_anchor.set) {
repr->setAttribute("text-anchor", NULL);
}
+ if (style->white_space.set) {
+ repr->setAttribute("white_space", NULL);
+ }
if (style->writing_mode.set) {
repr->setAttribute("writing_mode", NULL);
}
@@ -1712,6 +1721,7 @@ sp_css_attr_unset_text(SPCSSAttr *css)
sp_repr_css_set_property(css, "block-progression", NULL);
sp_repr_css_set_property(css, "writing-mode", NULL);
sp_repr_css_set_property(css, "text-anchor", NULL);
+ sp_repr_css_set_property(css, "white_space", NULL);
sp_repr_css_set_property(css, "kerning", NULL); // not implemented yet
sp_repr_css_set_property(css, "dominant-baseline", NULL); // not implemented yet
sp_repr_css_set_property(css, "alignment-baseline", NULL); // not implemented yet
diff --git a/src/style.h b/src/style.h
index eb8a3ed91..8d0befe0e 100644
--- a/src/style.h
+++ b/src/style.h
@@ -92,8 +92,10 @@ private:
public:
/* ----------------------- THE PROPERTIES ------------------------- */
+ /* Match order in style.cpp. */
+
+ /* Font ---------------------------- */
- /* Font */
/** Font style */
SPIEnum font_style;
/** Which substyle of the font */
@@ -113,23 +115,13 @@ public:
/** Full font name, as font_factory::ConstructFontSpecification would give, for internal use. */
SPIString font_specification;
+ /* Text ----------------------------- */
+
/** First line indent of paragraphs (css2 16.1) */
SPILength text_indent;
/** text alignment (css2 16.2) (not to be confused with text-anchor) */
SPIEnum text_align;
- /** text decoration (css2 16.3.1) */
- SPITextDecoration text_decoration;
- /** CSS 3 2.1, 2.2, 2.3 */
- /** Not done yet, test_decoration3 = css3 2.4*/
- SPITextDecorationLine text_decoration_line;
- SPITextDecorationStyle text_decoration_style; // SPIEnum? Only one can be set at time.
- SPIColor text_decoration_color;
- // used to implement text_decoration, not saved to or read from SVG file
- SPITextDecorationData text_decoration_data;
-
- // 16.3.2 is text-shadow. That's complicated.
-
/** letter spacing (css2 16.4) */
SPILengthOrNormal letter_spacing;
/** word spacing (also css2 16.4) */
@@ -151,6 +143,25 @@ public:
/** Anchor of the text (svg1.1 10.9.1) */
SPIEnum text_anchor;
+ /** white space (svg2) */
+ SPIEnum white_space;
+
+ /* Text Decoration ----------------------- */
+
+ /** text decoration (css2 16.3.1) */
+ SPITextDecoration text_decoration;
+ /** CSS 3 2.1, 2.2, 2.3 */
+ /** Not done yet, test_decoration3 = css3 2.4*/
+ SPITextDecorationLine text_decoration_line;
+ SPITextDecorationStyle text_decoration_style; // SPIEnum? Only one can be set at time.
+ SPIColor text_decoration_color;
+ // used to implement text_decoration, not saved to or read from SVG file
+ SPITextDecorationData text_decoration_data;
+
+ // 16.3.2 is text-shadow. That's complicated.
+
+ /* General visual properties ------------- */
+
/** clip-rule: 0 nonzero, 1 evenodd */
SPIEnum clip_rule;
@@ -216,6 +227,8 @@ public:
SPIString marker_end;
SPIString* marker_ptrs[SP_MARKER_LOC_QTY];
+ /* Filter effects ------------------------ */
+
/** Filter effect */
SPIFilter filter;
/** Filter blend mode */
@@ -226,6 +239,7 @@ public:
/** enable-background, used for defining where filter effects get their background image */
SPIEnum enable_background;
+ /* Rendering hints ----------------------- */
/** hints on how to render: e.g. speed vs. accuracy.
* As of April, 2013, only image_rendering used. */