File indexing completed on 2024-06-16 04:11:24

0001 /*
0002  *  SPDX-FileCopyrightText: 2017 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef KOSVGTEXTPROPERTIES_H
0008 #define KOSVGTEXTPROPERTIES_H
0009 
0010 #include "kritaflake_export.h"
0011 #include "KoFlakeTypes.h"
0012 
0013 #include <QScopedPointer>
0014 #include <QVariant>
0015 #include <QList>
0016 
0017 class SvgLoadingContext;
0018 class KoShapeBackground;
0019 
0020 /**
0021  * KoSvgTextProperties represents the text attributes defined in SVG DOM tree
0022  *
0023  * There is a limitation in flake: it doesn't support the inheritance of shape
0024  * properties: every shape stores all the properties that were defined at the
0025  * loading/creation stage. KoSvgTextProperties allows the user to compare
0026  * the properties of the two shapes and distinguish, which properties were
0027  * inherited by text shape, and which are its own. It is needed to generate a
0028  * correct and clean SVG/markup code that can be edited by the user easily.
0029  * Otherwise, every \<tspan\> block will contain the full list of 20+ attributes,
0030  * which are not interesting for the user, since they are inherited or default.
0031  *
0032  * To achieve the goal, KoSvgTextProperties wraps all the SVG attributes into a
0033  * map of QVariants. When the user need to find a set of unique properties
0034  * of the shape, it iterates through the map and compares values with standard
0035  * QVariant-based comparison operator. If the property value in a child and a
0036  * parent is not the same, then it is not inherited.
0037  */
0038 class KRITAFLAKE_EXPORT KoSvgTextProperties
0039 {
0040 public:
0041     /**
0042      * Defines a set of supported properties. See SVG 1.1 for details.
0043      */
0044     enum PropertyId {
0045         WritingModeId, ///< KoSvgText::WritingMode
0046         DirectionId, ///< KoSvgText::Direction
0047         UnicodeBidiId, ///< KoSvgText::UnicodeBidi
0048         TextAnchorId, ///< KoSvgText::TextAnchor
0049         DominantBaselineId, ///< KoSvgText::Baseline
0050         AlignmentBaselineId, ///< KoSvgText::Baseline
0051         BaselineShiftModeId, ///< KoSvgText::BaselineShiftMode
0052         BaselineShiftValueId, ///< Double
0053         KerningId, ///< KoSvgText::AutoValue
0054         TextOrientationId, ///< KoSvgText::TextOrientation
0055         LetterSpacingId, ///< KoSvgText::AutoValue
0056         WordSpacingId, ///< KoSvgText::AutoValue
0057 
0058         FontFamiliesId, ///< QStringList
0059         FontStyleId, ///< QFont::Style
0060         FontStretchId, ///< Int
0061         FontWeightId, ///< Int
0062         FontSizeId, ///< Double
0063         FontSizeAdjustId, ///< KoSvgText::AutoValue
0064 
0065         /// KoSvgText::FontVariantFeature
0066         FontVariantCommonLigId,
0067         FontVariantDiscretionaryLigId,
0068         FontVariantHistoricalLigId,
0069         FontVariantContextualAltId,
0070         FontVariantPositionId,
0071         FontVariantCapsId,
0072         FontVariantNumFigureId,
0073         FontVariantNumSpacingId,
0074         FontVariantNumFractId,
0075         FontVariantNumOrdinalId,
0076         FontVariantNumSlashedZeroId,
0077         FontVariantHistoricalFormsId,
0078         FontVariantEastAsianVarId,
0079         FontVariantEastAsianWidthId,
0080         FontVariantRubyId,
0081 
0082         FontFeatureSettingsId, ///< QStringList
0083         FontOpticalSizingId, ///< Bool
0084         FontVariationSettingsId, ///< QStringList
0085 
0086         TextDecorationLineId, ///< Flags, KoSvgText::TextDecorations
0087         TextDecorationStyleId, ///< KoSvgText::TextDecorationStyle
0088         TextDecorationColorId, ///< QColor
0089         TextDecorationPositionHorizontalId, ///< KoSvgText::TextDecorationUnderlinePosition
0090         TextDecorationPositionVerticalId, ///< KoSvgText::TextDecorationUnderlinePosition
0091         FillId, ///< KoSvgText::BackgroundProperty
0092         StrokeId, ///< KoSvgText::StrokeProperty
0093         Opacity, ///< Double, SVG shape opacity.
0094         PaintOrder, ///< QVector<KoShape::PaintOrder>
0095         Visiblity, ///< Bool, CSS visibility
0096 
0097         TextLanguage, ///< a language string.
0098 
0099         TextCollapseId, ///< KoSvgText::TextSpaceCollapse
0100         TextWrapId, ///< KoSvgText::TextWrap
0101         TextTrimId, ///< Flags, KoSvgText::TextSpaceTrims
0102         LineBreakId, ///< KoSvgText::LineBreak
0103         WordBreakId, ///< KoSvgText::WordBreak
0104         TextAlignAllId, ///< KoSvgText::TextAlign
0105         TextAlignLastId, ///< KoSvgText::TextAlign
0106         TextTransformId, ///< KoSvgText::TextTransformInfo Struct
0107         TextOverFlowId, ///< KoSvgText::WordBreak
0108         OverflowWrapId, ///<
0109         InlineSizeId, ///< KoSvgText::AutoValue
0110         LineHeightId, ///< KoSvgText::AutoValue
0111         TextIndentId, ///< KoSvgText::TextIndentInfo Struct.
0112         HangingPunctuationId, ///< Flags, KoSvgText::HangingPunctuations
0113         TabSizeId, ///< Int
0114 
0115         ShapePaddingId, ///< Double
0116         ShapeMarginId,  ///< Double
0117 
0118         KraTextVersionId ///< Int, used for handling incorrectly saved files.
0119     };
0120 
0121     KoSvgTextProperties();
0122     ~KoSvgTextProperties();
0123 
0124     KoSvgTextProperties(const KoSvgTextProperties &rhs);
0125     KoSvgTextProperties& operator=(const KoSvgTextProperties &rhs);
0126 
0127     /**
0128      * Set the property \p id to \p value
0129      */
0130     void setProperty(PropertyId id, const QVariant &value);
0131 
0132     /**
0133      * Check if property \p id is present in this properties set
0134      */
0135     bool hasProperty(PropertyId id) const;
0136 
0137     /**
0138      * Return the value of property \p id. If the property doesn't exist in
0139      * the shape, return \p defaultValue instead.
0140      */
0141     QVariant property(PropertyId id, const QVariant &defaultValue = QVariant()) const;
0142 
0143     /**
0144      * Remove property \p id from the set
0145      */
0146     void removeProperty(PropertyId id);
0147 
0148     /**
0149      * Return the value of property \p id. If the property doesn't exist in the
0150      * shape, return the default value define in SVG 1.1.
0151      */
0152     QVariant propertyOrDefault(PropertyId id) const;
0153 
0154     /**
0155      * Return a list of properties contained in this set
0156      */
0157     QList<PropertyId> properties() const;
0158 
0159     /**
0160      * Return true if the set contains no properties
0161      */
0162     bool isEmpty() const;
0163 
0164     /**
0165      * Reset all non-inheritable properties to default values. The set of
0166      * non-inheritable properties is define by SVG 1.1. Used by the loading
0167      * code for resetting state automata's properties on entering a \<tspan\>.
0168      */
0169     void resetNonInheritableToDefault();
0170 
0171 
0172     /**
0173      * Apply properties from the parent shape. The property is set **iff** the
0174      * property is inheritable according to SVG and this set does not define
0175      * it.
0176      */
0177     void inheritFrom(const KoSvgTextProperties &parentProperties);
0178 
0179     /**
0180      * Return true if the property \p id is inherited from \p parentProperties.
0181      * The property is considered "inherited" **iff* it is inheritable
0182      * according to SVG and the parent defined the same property with the same
0183      * value.
0184      */
0185     bool inheritsProperty(PropertyId id, const KoSvgTextProperties &parentProperties) const;
0186 
0187     /**
0188      * Return a set of properties that ar **not** inherited from \p
0189      * parentProperties. The property is considered "inherited" **iff* it is
0190      * inheritable according to SVG and the parent defined the same property
0191      * with the same value.
0192      * @param keepFontSize whether to keep the font size, use for root nodes
0193      * so that it won't be omitted and inheriting from the "default", which may
0194      * not be deterministic.
0195      */
0196     KoSvgTextProperties ownProperties(const KoSvgTextProperties &parentProperties, bool keepFontSize = false) const;
0197 
0198     /**
0199      * @brief parseSvgTextAttribute add a property according to an XML attribute value.
0200      * @param context shared loading context
0201      * @param command XML attribute name
0202      * @param value attribute value
0203      *
0204      * @see supportedXmlAttributes for a list of supported attributes
0205      */
0206     void parseSvgTextAttribute(const SvgLoadingContext &context, const QString &command, const QString &value);
0207 
0208     /**
0209      * Convert all the properties of the set into a map of XML attribute/value
0210      * pairs.
0211      */
0212     QMap<QString, QString> convertToSvgTextAttributes() const;
0213 
0214     /**
0215      * @brief convertParagraphProperties
0216      * some properties only apply to the root shape, so we write those separately.
0217      * @return
0218      */
0219     QMap<QString, QString> convertParagraphProperties() const;
0220 
0221     QFont generateFont() const;
0222 
0223     /**
0224      * @brief fontFeaturesForText
0225      * Returns a harfbuzz friendly list of opentype font-feature settings using
0226      * the various font-variant and font-feature-settings values.
0227      * @param start the start pos of the text.
0228      * @param length the length of the text.
0229      * @return a list of strings for font-features and their ranges that can be
0230      * understood by harfbuzz.
0231      */
0232     QStringList fontFeaturesForText(int start, int length) const;
0233 
0234     /**
0235      * @brief fontAxisSettings
0236      * This is used to configure variable fonts. It gets the appropriate values
0237      * from font width, stretch, style, size, if font-optical-sizing is not set
0238      * to 'none, and finally the font-variation-settings property.
0239      * @return a map of axis-tags and their values.
0240      */
0241     QMap<QString, qreal> fontAxisSettings() const;
0242 
0243     QSharedPointer<KoShapeBackground> background() const;
0244     KoShapeStrokeModelSP stroke() const;
0245 
0246     /**
0247      * Return a list of supported XML attribute names (defined in SVG)
0248      */
0249     static QStringList supportedXmlAttributes();
0250 
0251     /**
0252      * Return a static object that defines default values for all the supported
0253      * properties according to SVG
0254      */
0255     static const KoSvgTextProperties& defaultProperties();
0256 
0257 private:
0258     struct Private;
0259     const QScopedPointer<Private> m_d;
0260 };
0261 
0262 #endif // KOSVGTEXTPROPERTIES_H