From cca66b9ec4e494c1d919bff0f71a820d8afab1fa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:24:48 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- src/text-tag-attributes.h | 193 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 src/text-tag-attributes.h (limited to 'src/text-tag-attributes.h') diff --git a/src/text-tag-attributes.h b/src/text-tag-attributes.h new file mode 100644 index 0000000..b026059 --- /dev/null +++ b/src/text-tag-attributes.h @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** @file + * \brief contains and manages the attributes common to all types of text tag + * + * The five attributes x, y, dx, dy and rotate (todo: textlength, lengthadjust) + * are permitted on all of text, tspan and textpath elements so we need a class + * to abstract the management of those attributes from the actual type of the + * element. + *//* + * Authors: see git history + * + * Copyright (C) 2018 Authors + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ +#ifndef INKSCAPE_TEXT_TAG_ATTRIBUTES_H +#define INKSCAPE_TEXT_TAG_ATTRIBUTES_H + +#include +#include +#include +#include "libnrtype/Layout-TNG.h" +#include "svg/svg-length.h" + +namespace Inkscape { +namespace XML { +class Node; +} +} +enum class SPAttr; + +class TextTagAttributes { +public: + TextTagAttributes() = default; + TextTagAttributes(Inkscape::Text::Layout::OptionalTextTagAttrs attrs) + : attributes(std::move(attrs)) {} + + /// Fill in all the fields of #attributes from the given node. + void readFrom(Inkscape::XML::Node const *node); + + /** Process the parameters from the set() function of SPObject. + Returns true if \a key was a recognised attribute. */ + bool readSingleAttribute(SPAttr 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 + the x or y vectors we can presume that the user set them and hence + they should be copied. This function detects that condition so the + \a use_xy parameter to mergeInto() can be set correctly. */ + bool singleXYCoordinates() const; + + /** Returns false if all of the vectors are zero length. */ + bool anyAttributesSet() const; + + /** Implements the rules for overlaying the contents of the class + (treated as the child object) on top of previously existing + attributes from \a parent_attrs using the rules described in + SVG 1.1 section 10.5. \a parent_attrs_offset can be used to require + that only fields from \a parent_attrs starting at that index will + be used. Basically, the algorithm is that if a child attribute + exists that will be used, otherwise the parent attribute will be used, + otherwise the vector will end. textLength is never merged with parent. */ + void mergeInto(Inkscape::Text::Layout::OptionalTextTagAttrs *output, Inkscape::Text::Layout::OptionalTextTagAttrs const &parent_attrs, unsigned parent_attrs_offset, bool copy_xy, bool copy_dxdyrotate) const; + + /** Deletes all the values from all the vectors beginning at + \a start_index and extending for \a n fields. This is what you want + to do when deleting characters from the corresponding text. */ + void erase(unsigned start_index, unsigned n); + + /** Inserts \a n new values in all the stored vectors at \a + start_index. This is what you want to do when inserting characters + in the corresponding text. If a vector is shorter than \a start_index + it will not be extended (the defaults are fine). dx, dy and rotate + will be extended with zero values, x and y will be extended with + linearly interpolated values. TODO: The inserted values should probably + be unset but sp_svg_length_list_read() can't cope with that. */ + void insert(unsigned start_index, unsigned n); + + /** Divides the stored attributes into two, at the given index. The + first section (0..index-1) stay in this object, the second section + (index..end) go in \a second. This function is generally used when + line breaking. */ + void split(unsigned index, TextTagAttributes *second); + + /** Overwrites all the attributes contained in this object with the + given parameters by putting \a first at the beginning, then the + contents of \a second after \a second_index. */ + void join(TextTagAttributes const &first, TextTagAttributes const &second, unsigned second_index); + + /** Applies the given transformation to the stored coordinates. Pairs + of x and y coordinates are multiplied by the matrix and the dx and dy + vectors are multiplied by the given parameters. rotate is not altered. + If \a extend_zero_length is true, then if the x or y vectors are empty + they will be made length 1 in order to store the newly calculated + position. */ + void transform(Geom::Affine const &matrix, double scale_x, double scale_y, bool extend_zero_length = false); + + /** Gets current value of dx vector at \a index. */ + double getDx(unsigned index); + + /** Gets current value of dy vector at \a index. */ + double getDy(unsigned index); + + /** Adds the given value to the dx vector at the given + \a index. The vector is extended if necessary. */ + void addToDx(unsigned index, double delta); + + /** Adds the given value to the dy vector at the given + \a index. The vector is extended if necessary. */ + void addToDy(unsigned index, double delta); + + /** Adds the given values to the dx and dy vectors at the given + \a index. The vectors are extended if necessary. */ + void addToDxDy(unsigned index, Geom::Point const &adjust); + + /** Gets current value of rotate vector at \a index. */ + double getRotate(unsigned index); + + /** Adds the given value to the rotate vector at the given \a index. The + vector is extended if necessary. Delta is measured in degrees, clockwise + positive. */ + void addToRotate(unsigned index, double delta); + + /** Sets rotate vector at the given \a index. The vector is extended if + necessary. Angle is measured in degrees, clockwise positive. */ + void setRotate(unsigned index, double angle); + + /** Returns the first coordinates in the x and y vectors. If either + is zero length, 0.0 is used for that coordinate. */ + Geom::Point firstXY() const; + + /** Sets the first coordinates in the x and y vectors. */ + void setFirstXY(Geom::Point &point); + + /** Gets first value in the x vector as an SVGLength. Not guaranteed to remain valid. */ + SVGLength* getFirstXLength(); + + /** Gets first value in the y vector as an SVGLength. Not guaranteed to remain valid. */ + SVGLength* getFirstYLength(); + + SVGLength *getTextLength() { return &(attributes.textLength); } + int getLengthAdjust() { return attributes.lengthAdjust; } + +private: + /// This holds the actual values. + Inkscape::Text::Layout::OptionalTextTagAttrs attributes; + + /** Does the reverse of readSingleAttribute(), converting a vector<> to + its SVG string representation and writing it in to \a node. Used by + writeTo(). */ + static void writeSingleAttributeVector(Inkscape::XML::Node *node, gchar const *key, std::vector const &attr_vector); + + /** Writes a single length value to \a node. Used by + writeTo(). */ + static void writeSingleAttributeLength(Inkscape::XML::Node *node, gchar const *key, const SVGLength &length); + + /** Does mergeInto() for one member of #attributes. If \a overlay_list + is NULL then it does a simple copy of parent elements, starting at + \a parent_offset. */ + static void mergeSingleAttribute(std::vector *output_list, std::vector const &parent_list, unsigned parent_offset, std::vector const *overlay_list = nullptr); + + /// Does the work for erase(). + static void eraseSingleAttribute(std::vector *attr_vector, unsigned start_index, unsigned n); + + /// Does the work for insert(). + static void insertSingleAttribute(std::vector *attr_vector, unsigned start_index, unsigned n, bool is_xy); + + /// Does the work for split(). + static void splitSingleAttribute(std::vector *first_vector, unsigned index, std::vector *second_vector, bool trimZeros); + + /// Does the work for join(). + static void joinSingleAttribute(std::vector *dest_vector, std::vector const &first_vector, std::vector const &second_vector, unsigned second_index); +}; + + +#endif /* !INKSCAPE_TEXT_TAG_ATTRIBUTES_H */ + +/* + 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 : -- cgit v1.2.3