diff options
Diffstat (limited to 'src/object/sp-string.cpp')
-rw-r--r-- | src/object/sp-string.cpp | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/src/object/sp-string.cpp b/src/object/sp-string.cpp new file mode 100644 index 0000000..ee38bfd --- /dev/null +++ b/src/object/sp-string.cpp @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * SVG <text> and <tspan> implementation + * + * Author: + * Lauris Kaplinski <lauris@kaplinski.com> + * Jon A. Cruz <jon@joncruz.org> + * Abhishek Sharma + * + * Copyright (C) 1999-2002 Lauris Kaplinski + * Copyright (C) 2000-2001 Ximian, Inc. + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +/* + * fixme: + * + * These subcomponents should not be items, or alternately + * we have to invent set of flags to mark, whether standard + * attributes are applicable to given item (I even like this + * idea somewhat - Lauris) + * + */ + +#include "sp-string.h" +#include "style.h" + +/*##################################################### +# SPSTRING +#####################################################*/ + +SPString::SPString() : SPObject() { + + // This is dangerous but strings shouldn't have style. + // delete (style); + // style = nullptr; +} + +SPString::~SPString() = default; + +void SPString::build(SPDocument *doc, Inkscape::XML::Node *repr) { + + read_content(); + + SPObject::build(doc, repr); +} + +void SPString::release() { + SPObject::release(); +} + + +void SPString::read_content() { + + string.clear(); + + //XML Tree being used directly here while it shouldn't be. + gchar const *xml_string = getRepr()->content(); + + // 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 | Collapse | 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( parent && parent->style ) { + if( parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PRE || + parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PREWRAP || + parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PRELINE ) { + collapse_line = false; + } + if( parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PRE || + parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PREWRAP ) { + collapse_space = false; + } + if( parent->style->white_space.computed != SP_CSS_WHITE_SPACE_NORMAL ) { + is_css = true; // If white-space not normal, we assume white-space is set. + } + } + if( !is_css ) { + // SVG 2: Use 'xml:space' only if 'white-space' not 'normal'. + if (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; + 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 += c; // Preserve line feed + continue; + } + break; + case '\t': // Tab + if( collapse_space ) { + white_space = true; // Convert to space and collapse + } else { + string += c; // Preserve tab + continue; + } + break; + case ' ': // Space + if( collapse_space ) { + white_space = true; // Collapse white space + } else { + string += c; // Preserve space + continue; + } + break; + default: + if( white_space && (!string.empty() || (getPrev() != nullptr))) { + string += ' '; + } + string += c; + white_space = false; + + } // End switch + } // End loop + + // Insert white space at end if more text follows + if (white_space && getRepr()->next() != nullptr) { // can't use SPObject::getNext() when the SPObject tree is still being built + string += ' '; + } + + // std::cout << ">" << string << "<" << std::endl; + requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); +} + +void SPString::update(SPCtx * /*ctx*/, unsigned /*flags*/) { + + // if (flags & (SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_MODIFIED_FLAG)) { + // /* Parent style or we ourselves changed, so recalculate */ + // flags &= ~SP_OBJECT_USER_MODIFIED_FLAG_B; // won't be "just a transformation" anymore, we're going to recompute "x" and "y" attributes + // } +} + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |