Krita Source Code Documentation
Loading...
Searching...
No Matches
KoSvgTextShape Class Reference

#include <KoSvgTextShape.h>

+ Inheritance diagram for KoSvgTextShape:

Classes

struct  TextCursorChangeListener
 ShapeChangeListener so we can inform any text cursors that the cursor needs updating. More...
 

Public Types

enum class  DebugElement { CharBbox = 1 << 0 , LineBox = 1 << 1 }
 
enum  TextType { PrePositionedText = 0 , PreformattedText , InlineWrap , TextInShape }
 
- Public Types inherited from KoShape
enum  ChangeType {
  PositionChanged , RotationChanged , ScaleChanged , ShearChanged ,
  SizeChanged , GenericMatrixChange , KeepAspectRatioChange , ParentChanged ,
  Deleted , StrokeChanged , BackgroundChanged , ShadowChanged ,
  BorderChanged , ParameterChanged , ContentChanged , TextRunAroundChanged ,
  ChildChanged , ConnectionPointChanged , ClipPathChanged , ClipMaskChanged ,
  TransparencyChanged
}
 Used by shapeChanged() to select which change was made. More...
 
enum  ChildZOrderPolicy { ChildZDefault , ChildZParentChild = ChildZDefault , ChildZPassThrough }
 Used by compareShapeZIndex() to order shapes. More...
 
enum  PaintOrder { Fill , Stroke , Markers }
 
enum  RunThroughLevel { Background , Foreground }
 
enum  TextRunAroundContour { ContourBox , ContourFull , ContourOutside }
 The behavior text should do when intersecting this shape. More...
 
enum  TextRunAroundSide {
  BiggestRunAroundSide , LeftRunAroundSide , RightRunAroundSide , EnoughRunAroundSide ,
  BothRunAroundSide , NoRunAround , RunThrough
}
 The behavior text should do when intersecting this shape. More...
 

Public Member Functions

void applyTextLength (KisForest< KoSvgTextContentElement >::child_iterator currentTextElement, QVector< CharacterResult > &result, int &currentIndex, int &resolvedDescendentNodes, bool isHorizontal, const KoSvgTextProperties resolvedProps, const KoSvgText::ResolutionHandler &resHandler)
 
void applyWhiteSpace (KisForest< KoSvgTextContentElement > &tree, const bool convertToPreWrapped=false)
 applyWhiteSpace CSS Whitespace processes whitespaces so that duplicate white spaces and unnecessary hard breaks get removed from the text. Within the text layout we avoid removing the white spaces. However, when converting between text types it can be useful to remove these spaces. This function actually applies the white space rule to the active text.
 
void applyWhiteSpaceImpl (std::reverse_iterator< KisForest< KoSvgTextContentElement >::child_iterator > current, QVector< bool > &collapsed, QString &allText, const bool convertToPreWrapped)
 
QSharedPointer< KoShapeBackgroundbackground () const override
 
QRectF boundingRect () const override
 Get the bounding box of the shape.
 
void cleanUp ()
 Cleans up the internal text data. Used by undo commands.
 
void clearAssociatedOutlines ()
 
KoShapecloneShape () const override
 creates a deep copy of the shape or shape's subtree
 
KoShapecollectPaths (const KoShape *rootShape, QVector< CharacterResult > &result, int &currentIndex)
 
void computeTextDecorations (KisForest< KoSvgTextContentElement >::child_iterator currentTextElement, const QVector< CharacterResult > &result, const QMap< int, int > &logicalToVisual, const KoSvgText::ResolutionHandler resHandler, KoPathShape *textPath, qreal textPathoffset, bool side, int &currentIndex, bool isHorizontal, bool ltr, bool wrapping, const KoSvgTextProperties resolvedProps)
 
void convertCharTransformsToPreformatted (bool makeInlineSize=false)
 convertCharTransformsToPreformatted Converts the text to a preformatted SVG 2.0 text. This changes the textType();
 
std::unique_ptr< KoSvgTextShapecopyRange (int index, int length) const
 copyRange Copy the rich text for the given range.
 
QPainterPath cursorForPos (int pos, QLineF &caret, QColor &color, double bidiFlagSize=1.0)
 cursorForPos returns the QPainterPath associated with this cursorPosition.
 
void debugParsing ()
 Outputs debug with the current textData tree.
 
void enterNodeSubtree ()
 Set the current node to its first child, entering the subtree.
 
KoSvgTextNodeIndex findNodeIndexForPropertyId (KoSvgTextProperties::PropertyId propertyId)
 findNodeIndexForPropertyId
 
QPair< int, int > findRangeForNodeIndex (const KoSvgTextNodeIndex &node) const
 findRangeForNodeIndex Find the start and end cursor position for a given nodeIndex.
 
bool fontMatchingDisabled () const
 fontMatchingDisabled
 
QMap< KoSvgText::TextDecoration, QPainterPath > generateDecorationPaths (const int &start, const int &end, const KoSvgText::ResolutionHandler resHandler, const QVector< CharacterResult > &result, const bool isHorizontal, const KoSvgText::TextDecorations &decor, const KoSvgText::TextDecorationStyle style=KoSvgText::TextDecorationStyle::Solid, const bool textDecorationSkipInset=false, const KoPathShape *currentTextPath=nullptr, const qreal currentTextPathOffset=0.0, const bool textPathSide=false, const KoSvgText::TextDecorationUnderlinePosition underlinePosH=KoSvgText::TextDecorationUnderlinePosition::UnderlineAuto, const KoSvgText::TextDecorationUnderlinePosition underlinePosV=KoSvgText::TextDecorationUnderlinePosition::UnderlineAuto)
 
KoSvgTextShapeMementoSP getMemento ()
 Get a memento holding the current textdata and layout info.
 
int indexForPos (int pos) const
 indexForPos get the string index for a given cursor position.
 
QPointF initialTextPosition () const
 initialTextPosition Returns the initial text position as per SVG algorithm. The eventual result of this can include transforms or repositioning due to text shapes.
 
bool insertRichText (int pos, const KoSvgTextShape *richText)
 insertRichText Insert rich text at the given cursor pos. This will first split contents at the given pos before inserting the new rich text.
 
bool insertText (int pos, QString text)
 insertText Insert a text somewhere in the KoTextShape.
 
 KoSvgTextShape ()
 
 KoSvgTextShape (const KoSvgTextShape &rhs)
 
void leaveNodeSubtree ()
 Set the current node to its parent, leaving the subtree.
 
int lineEnd (int pos)
 lineEnd return the 'line end' for this pos. This uses anchored chunks, so each absolute x, y posititioning will be considered a line-start.
 
int lineStart (int pos)
 lineStart return the 'line start' for this pos. This uses anchored chunks, so each absolute x, y posititioning will be considered a line-start.
 
void mergePropertiesIntoRange (const int startPos, const int endPos, const KoSvgTextProperties properties, const QSet< KoSvgTextProperties::PropertyId > removeProperties=QSet< KoSvgTextProperties::PropertyId >())
 mergePropertiesIntoRange Merge given properties into the given range. This will first split the nodes at the two range ends, and then merge in the properties into each leaf node. Won't do anything when startPos == endPos
 
int nextIndex (int pos)
 nextIndex Return the first cursor position with a higher string index.
 
int nextLine (int pos)
 nextLine get a position on the next line for this position.
 
void notifyCursorPosChanged (int pos, int anchor)
 Notify that the cursor position has changed.
 
void notifyMarkupChanged ()
 Notify that the markup has changed.
 
QPainterPath outline () const override
 
QRectF outlineRect () const override
 
void paint (QPainter &painter) const override
 Paint the shape fill The class extending this one is responsible for painting itself. painter is expected to be preconfigured to work in "document" pixels.
 
void paintDebug (QPainter &painter, const QVector< CharacterResult > &result, int &currentIndex)
 
void paintDebug (QPainter &painter, DebugElements elements) const
 
QVector< PaintOrderpaintOrder () const override
 paintOrder
 
void paintPaths (QPainter &painter, const QPainterPath &outlineRect, const KoShape *rootShape, const QVector< CharacterResult > &result, const KoSvgText::TextRendering rendering, QPainterPath &chunk, int &currentIndex)
 
void paintStroke (QPainter &painter) const override
 paintStroke paints the shape's stroked outline
 
void paintTextDecoration (QPainter &painter, const QPainterPath &outlineRect, const KoShape *rootShape, const KoSvgText::TextDecoration type, const KoSvgText::TextRendering rendering)
 
QString plainText ()
 plainText plain text of all text inside this text shape, without the bidi controls or any transforms.
 
int posDown (int pos, bool visual=false)
 return position below.
 
int posForIndex (int index, bool firstIndex=false, bool skipSynthetic=false) const
 posForIndex Get the cursor position for a given index in a string.
 
int posForPoint (QPointF point, int start=-1, int end=-1, bool *overlaps=nullptr)
 posForPoint Finds the closest cursor position for the given point in shape coordinates.
 
int posForPointLineSensitive (QPointF point)
 posForPointLineSensitive When clicking on an empty space in a wrapped text, it is preferable to have the caret be at the end of the line visually associated with that empty space than the positions above or below that might be closer.
 
int posLeft (int pos, bool visual=false)
 
int posRight (int pos, bool visual=false)
 
int posUp (int pos, bool visual=false)
 return position above.
 
int previousIndex (int pos)
 previousIndex Return the first pos which has a lower string index.
 
int previousLine (int pos)
 previousLine get a position on the previous line for this position.
 
 Private ()=default
 
 Private (const Private &rhs)
 
KoSvgTextProperties propertiesForPos (const int pos, bool inherited=false) const
 Return the properties at a given position.
 
QList< KoSvgTextPropertiespropertiesForRange (const int startPos, const int endPos, bool inherited=false) const
 propertiesForRange get the properties for a range.
 
 Q_DECLARE_FLAGS (DebugElements, DebugElement)
 
void relayout ()
 
void relayout () const
 
bool relayoutIsBlocked () const
 relayoutIsBlocked
 
bool removeText (int &index, int &length)
 removeText Where insert text explicitly uses a cursorposition, remove text uses a string index. It will modify these values so that...
 
bool saveHtml (HtmlSavingContext &context)
 
bool saveSvg (SvgSavingContext &context) override
 Saves SVG data.
 
QPainterPath selectionBoxes (int pos, int anchor)
 selectionBoxes returns all selection boxes for a given range. Range will be normalized internally.
 
void setBackground (QSharedPointer< KoShapeBackground > background) override
 
void setCharacterTransformsFromLayout ()
 setCharacterTransformsFromLayout Converts the text to a prepositioned SVG 1.1 text. This changes the textType();
 
void setFontMatchingDisabled (const bool disable)
 setDisableFontMatching
 
void setMemento (const KoSvgTextShapeMementoSP memento)
 Set the text data and layout info, reset listening cursors to 0.
 
void setMemento (const KoSvgTextShapeMementoSP memento, int pos, int anchor)
 Set the text data, layout info and also adjust any listening cursors.
 
void setPaintOrder (PaintOrder first, PaintOrder second) override
 setPaintOrder set the paint order. As there's only three entries in any given paintorder, you only need to have the first and second entry to set it.
 
void setPropertiesAtPos (int pos, KoSvgTextProperties properties)
 setPropertiesAtPos will set the properties at pos.
 
void setRelayoutBlocked (const bool disable)
 
void setResolution (qreal xRes, qreal yRes) override
 
void setShapesInside (QList< KoShape * > shapesInside)
 setShapesInside
 
void setShapesSubtract (QList< KoShape * > shapesSubtract)
 setShapesSubtract
 
void setStroke (KoShapeStrokeModelSP stroke) override
 
void setTransformsFromLayout (KisForest< KoSvgTextContentElement > &tree, const QVector< CharacterResult > layout)
 
void setTransformsFromLayoutImpl (KisForest< KoSvgTextContentElement >::child_iterator current, const KoSvgTextProperties parentProps, const QVector< CharacterResult > layout, int &globalIndex, bool isHorizontal)
 
QList< KoShape * > shapesInside () const
 shapesInside
 
QList< KoShape * > shapesSubtract () const
 shapesSubtract
 
QMap< QString, QString > shapeTypeSpecificStyles (SvgSavingContext &context) const
 
KoShapeStrokeModelSP stroke () const override
 
KoShapetextOutline () const
 textOutline This turns the text object into non-text KoShape(s) to the best of its abilities.
 
KoSvgTextProperties textProperties () const
 
TextType textType () const
 textType This enum gives an indication of what kind of text this shape is. The different text types are a bit blurry as SVG allows a mixutre to provide fallback information. When such fallback is in place, this will only return the primary text type, that is, TextInShape before InlineWrap and InlineWrap before PrePositioned/Preformatted. This primarily exists to give UI feedback.
 
QPainterPath underlines (int pos, int anchor, KoSvgText::TextDecorations decor, KoSvgText::TextDecorationStyle style, qreal minimum, bool thick)
 
int wordEnd (int pos)
 wordEnd return the pos of the first wordbreak.
 
int wordLeft (int pos, bool visual=false)
 wordLeft return the cursorpos for the word left or the extreme of the line.
 
int wordRight (int pos, bool visual=false)
 wordRight return the cursorpos for the word right or the extreme of the line.
 
int wordStart (int pos)
 wordStart return the first pos before a wordbreak in the start direction.
 
KoSvgText::WritingMode writingMode () const
 writingMode There's a number of places we need to check the writing mode to provide proper controls.
 
 ~KoSvgTextShape () override
 
 ~Private ()
 
- Public Member Functions inherited from KoShape
QRectF absoluteOutlineRect () const
 
QPointF absolutePosition (KoFlake::AnchorPosition anchor=KoFlake::Center) const
 
QTransform absoluteTransformation () const
 
bool addDependee (KoShape *shape)
 
QString additionalAttribute (const QString &name) const
 
void addShapeChangeListener (ShapeChangeListener *listener)
 
KoShapeAnchoranchor () const
 
void applyAbsoluteTransformation (const QTransform &matrix)
 
void applyTransformation (const QTransform &matrix)
 
virtual ChildZOrderPolicy childZOrderPolicy ()
 
KoClipMaskclipMask () const
 Returns the currently set clip mask or 0 if there is no clip mask set.
 
KoClipPathclipPath () const
 Returns the currently set clip path or 0 if there is no clip path set.
 
KoShapecloneShapeAndBakeAbsoluteTransform () const
 creates a deep copy of the shape/shapes tree and bakes the absolute transform of this into the resulting shape.
 
void copySettings (const KoShape *shape)
 
QList< KoShape * > dependees () const
 Returns list of shapes depending on this shape.
 
QPointF documentToShape (const QPointF &point) const
 Transforms point from document coordinates to shape coordinates.
 
QRectF documentToShape (const QRectF &rect) const
 Transform rect from document coordinates to shape coordinates.
 
KoFilterEffectStackfilterEffectStack () const
 
bool hasAdditionalAttribute (const QString &name) const
 
bool hasCommonParent (const KoShape *shape) const
 
bool hasDependee (KoShape *shape) const
 Returns if the given shape is dependent on this shape.
 
virtual bool hasTransparency () const
 
virtual bool hitTest (const QPointF &position) const
 Check if the shape is hit on position.
 
QString hyperLink () const
 
bool inheritBackground () const
 inheritBackground shows if the shape inherits background from its parent
 
bool inheritPaintOrder () const
 inheritPaintOrder
 
bool inheritsTransformFromAny (const QList< KoShape * > ancestorsInQuestion) const
 inheritsTransformFromAny checks if the shape inherits transformation from any of the shapes listed in ancestorsInQuestion. The inheritance is checked in recursive way.
 
bool inheritStroke () const
 inheritStroke shows if the shape inherits the stroke from its parent
 
bool isContentProtected () const
 
bool isGeometryProtected () const
 
bool isPrintable () const
 
bool isSelectable () const
 
virtual bool isShapeEditable (bool recursive=true) const
 checks recursively if the shape or one of its parents is not visible or locked
 
bool isVisible (bool recursive=true) const
 
bool keepAspectRatio () const
 
 KoShape ()
 Constructor.
 
qreal minimumHeight () const
 
QString name () const
 
void notifyChanged ()
 
virtual void paintMarkers (QPainter &painter) const
 paintStroke paints the shape's markers
 
KoShapeContainerparent () const
 
QPointF position () const
 Get the position of the shape in pt.
 
void removeAdditionalAttribute (const QString &name)
 
void removeAdditionalStyleAttribute (const char *name)
 
void removeDependee (KoShape *shape)
 
void removeShapeChangeListener (ShapeChangeListener *listener)
 
void rotate (qreal angle)
 Rotate the shape (relative)
 
qreal rotation () const
 
int runThrough () const
 
void scale (qreal sx, qreal sy)
 Scale the shape using the zero-point which is the top-left corner.
 
void setAbsolutePosition (const QPointF &newPosition, KoFlake::AnchorPosition anchor=KoFlake::Center)
 
void setAdditionalAttribute (const QString &name, const QString &value)
 
void setAdditionalStyleAttribute (const char *name, const QString &value)
 
void setAnchor (KoShapeAnchor *anchor)
 
void setClipMask (KoClipMask *clipMask)
 Sets a new clip mask, removing the old one. The mask is owned by the shape.
 
void setClipPath (KoClipPath *clipPath)
 Sets a new clip path, removing the old one.
 
void setContentProtected (bool protect)
 
void setFilterEffectStack (KoFilterEffectStack *filterEffectStack)
 Sets the new filter effect stack, removing the old one.
 
void setGeometryProtected (bool on)
 
void setHyperLink (const QString &hyperLink)
 
void setInheritBackground (bool value)
 setInheritBackground marks a shape as inheriting the background from the parent shape. NOTE: The currently selected background is destroyed.
 
void setInheritPaintOrder (bool value)
 setInheritPaintOrder set inherit paint order.
 
void setInheritStroke (bool value)
 setInheritStroke marks a shape as inheriting the stroke from the parent shape. NOTE: The currently selected stroke is destroyed.
 
void setKeepAspectRatio (bool keepAspect)
 
void setMinimumHeight (qreal height)
 
void setName (const QString &name)
 
void setParent (KoShapeContainer *parent)
 
virtual void setPosition (const QPointF &position)
 Set the position of the shape in pt.
 
void setPrintable (bool on)
 
virtual void setRunThrough (short int runThrough)
 
void setSelectable (bool selectable)
 
void setShadow (KoShapeShadow *shadow)
 Sets the new shadow, removing the old one.
 
void setShapeId (const QString &id)
 
virtual void setSize (const QSizeF &size)
 Resize the shape.
 
void setTextRunAroundContour (TextRunAroundContour contour)
 
void setTextRunAroundDistanceBottom (qreal distance)
 
void setTextRunAroundDistanceLeft (qreal distance)
 
void setTextRunAroundDistanceRight (qreal distance)
 
void setTextRunAroundDistanceTop (qreal distance)
 
void setTextRunAroundSide (TextRunAroundSide side, RunThroughLevel runThrough=Background)
 
void setTextRunAroundThreshold (qreal threshold)
 
void setToolDelegates (const QSet< KoShape * > &delegates)
 
void setTransformation (const QTransform &matrix)
 
void setTransparency (qreal transparency)
 
void setUserData (KoShapeUserData *userData)
 
void setVisible (bool on)
 
void setZIndex (qint16 zIndex)
 
KoShapeShadowshadow () const
 Returns the currently set shadow or 0 if there is no shadow set.
 
virtual QPainterPath shadowOutline () const
 
QString shapeId () const
 
QPointF shapeToDocument (const QPointF &point) const
 Transforms point from shape coordinates to document coordinates.
 
QRectF shapeToDocument (const QRectF &rect) const
 Transforms rect from shape coordinates to document coordinates.
 
void shear (qreal sx, qreal sy)
 Shear the shape The shape will be sheared using the zero-point which is the top-left corner.
 
virtual QSizeF size () const
 Get the size of the shape in pt.
 
virtual KoSnapData snapData () const
 Returns additional snap data the shape wants to have snapping to.
 
KoInsets strokeInsets () const
 
TextRunAroundContour textRunAroundContour () const
 
qreal textRunAroundDistanceBottom () const
 
qreal textRunAroundDistanceLeft () const
 
qreal textRunAroundDistanceRight () const
 
qreal textRunAroundDistanceTop () const
 
TextRunAroundSide textRunAroundSide () const
 
qreal textRunAroundThreshold () const
 
QSet< KoShape * > toolDelegates () const
 
QTransform transformation () const
 Returns the shapes local transformation matrix.
 
qreal transparency (bool recursive=false) const
 
virtual void update () const
 
virtual void updateAbsolute (const QRectF &rect) const
 
KoShapeUserDatauserData () const
 
virtual void waitUntilReady (bool asynchronous=true) const
 
qint16 zIndex () const
 
virtual ~KoShape ()
 Destructor.
 
- Public Member Functions inherited from SvgShape
virtual bool loadSvg (const QDomElement &element, SvgLoadingContext &context)
 Loads data from specified svg element.
 
void saveMetadata (SvgSavingContext &context)
 
virtual ~SvgShape ()
 

Static Public Member Functions

static qreal anchoredChunkShift (const QVector< CharacterResult > &result, const bool isHorizontal, const int start, int &end)
 
static void applyAnchoring (QVector< CharacterResult > &result, bool isHorizontal, const KoSvgText::ResolutionHandler resHandler)
 
static void applyTextPath (KisForest< KoSvgTextContentElement >::child_iterator parent, QVector< CharacterResult > &result, bool isHorizontal, QPointF &startPos, const KoSvgTextProperties resolvedProps)
 
static qreal characterResultOnPath (CharacterResult &cr, qreal length, qreal offset, bool isHorizontal, bool isClosed)
 
static int childCount (KisForest< KoSvgTextContentElement >::child_iterator it)
 Get the child count of the current node. A node without children is a text node.
 
static void cleanUp (KisForest< KoSvgTextContentElement > &tree)
 cleanUp This cleans up the tree by...
 
static QVector< bool > collapsedWhiteSpacesForText (KisForest< KoSvgTextContentElement > &tree, QString &allText, const bool alsoCollapseLowSurrogate=false)
 collapsedWhiteSpacesForText This returns the collapsed spaces for a given piece of text, without transforms.
 
static QVector< SubChunkcollectSubChunks (KisForest< KoSvgTextContentElement >::child_iterator it, KoSvgTextProperties parent, bool textInPath, bool &firstTextInPath)
 
static void computeFontMetrics (KisForest< KoSvgTextContentElement >::child_iterator parent, const KoSvgTextProperties &parentProps, const KoSvgText::FontMetrics &parentBaselineTable, const KoSvgText::Baseline parentBaseline, const QPointF superScript, const QPointF subScript, QVector< CharacterResult > &result, int &currentIndex, const KoSvgText::ResolutionHandler resHandler, const bool isHorizontal, const bool disableFontMatching)
 
static KoSvgTextNodeIndex createTextNodeIndex (KisForest< KoSvgTextContentElement >::child_iterator textElement)
 
static const QString & defaultPlaceholderText ()
 
static void finalizeDecoration (QPainterPath decorationPath, const QPointF offset, const QPainterPathStroker &stroker, const KoSvgText::TextDecoration type, QMap< KoSvgText::TextDecoration, QPainterPath > &decorationPaths, const KoPathShape *currentTextPath, const bool isHorizontal, const qreal currentTextPathOffset, const bool textPathSide)
 
static KisForest< KoSvgTextContentElement >::depth_first_tail_iterator findTextContentElementForIndex (KisForest< KoSvgTextContentElement > &tree, int &currentIndex, int sought, bool skipZeroWidth=false)
 findTextContentElementForIndex Finds the given leaf of the current tree-wide string index.
 
static void handleLineBoxAlignment (KisForest< KoSvgTextContentElement >::child_iterator parent, QVector< CharacterResult > &result, const QVector< LineBox > lineBoxes, int &currentIndex, const bool isHorizontal, const KoSvgTextProperties resolvedProps)
 
static void insertNewLinesAtAnchors (KisForest< KoSvgTextContentElement > &tree, bool shapesInside=false)
 insertNewLinesAtAnchors Resolves character transforms and then inserts new lines at each transform that creates a new chunk.
 
static void insertNewLinesAtAnchorsImpl (std::reverse_iterator< KisForest< KoSvgTextContentElement >::child_iterator > current, QVector< KoSvgText::CharTransformation > &resolvedTransforms, bool &inTextPath)
 
static void insertTransforms (KisForest< KoSvgTextContentElement > &tree, const int start, const int length, const bool allowSkipFirst)
 insertTransforms Inserts empty transforms into tree recursively.
 
static int insertTransformsImpl (KisForest< KoSvgTextContentElement >::child_iterator currentTextElement, const int globalIndex, const int start, const int length, const QVector< bool > collapsedCharacters, const bool allowSkipFirst)
 insertTransformsImpl Recursive function that handles inserting empty transforms into a given range. Used by insertTransforms.
 
static KisForest< KoSvgTextContentElement >::child_iterator iteratorForTreeIndex (const QVector< int > treeIndex, KisForest< KoSvgTextContentElement >::child_iterator parent)
 
static bool loadGlyph (const KoSvgText::ResolutionHandler &resHandler, const FT_Int32 faceLoadFlags, const bool isHorizontal, const char32_t firstCodepoint, const KoSvgText::TextRendering rendering, raqm_glyph_t &currentGlyph, CharacterResult &charResult, QPointF &totalAdvanceFTFontCoordinates)
 
static std::pair< QTransform, qreal > loadGlyphOnly (const QTransform &ftTF, FT_Int32 faceLoadFlags, bool isHorizontal, raqm_glyph_t &currentGlyph, CharacterResult &charResult, const KoSvgText::TextRendering rendering)
 
static int numChars (KisForest< KoSvgTextContentElement >::child_iterator parent, bool withControls=false, KoSvgTextProperties resolvedProps=KoSvgTextProperties::defaultProperties())
 Get the number of characters for the whole subtree of this node.
 
static void removeTransforms (KisForest< KoSvgTextContentElement > &tree, const int start, const int length)
 removeTransforms Remove all local SVG character transforms in a certain range. Local transforms are influenced by whitespace collapse and whether they are set to unicode codepoints, and they also accumulate from parent to child. This function removes all local transforms in a certain section.
 
static int removeTransformsImpl (KisForest< KoSvgTextContentElement >::child_iterator currentTextElement, const int globalIndex, const int start, const int length, const QVector< bool > collapsedCharacters)
 removeTransformsImpl recursive function that handles removing local transforms in a certain range. Used by removeTransform.
 
static void resolveTransforms (KisForest< KoSvgTextContentElement >::child_iterator currentTextElement, QString text, QVector< CharacterResult > &result, int &currentIndex, bool isHorizontal, bool wrapped, bool textInPath, QVector< KoSvgText::CharTransformation > &resolved, QVector< bool > collapsedChars, const KoSvgTextProperties resolvedProps, bool withControls=true)
 
static bool splitContentElement (KisForest< KoSvgTextContentElement > &tree, int index)
 splitContentElement split the contentElement in tree at index into two nodes.
 
static bool startIndexOfIterator (KisForest< KoSvgTextContentElement >::child_iterator parent, KisForest< KoSvgTextContentElement >::child_iterator target, int &currentIndex)
 
static QPainterPath stretchGlyphOnPath (const QPainterPath &glyph, const QPainterPath &path, bool isHorizontal, qreal offset, bool isClosed)
 
- Static Public Member Functions inherited from KoShape
static QRectF absoluteOutlineRect (const QList< KoShape * > &shapes)
 
static QRectF boundingRect (const QList< KoShape * > &shapes)
 
static bool compareShapeZIndex (KoShape *s1, KoShape *s2)
 
static KisHandlePainterHelper createHandlePainterHelperDocument (QPainter *painter, KoShape *shape, qreal handleRadius, int decorationThickness)
 
static KisHandlePainterHelper createHandlePainterHelperView (QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius=0.0, int decorationThickness=1)
 
static QVector< PaintOrderdefaultPaintOrder ()
 default paint order as per SVG specification
 
static QList< KoShape * > linearizeSubtree (const QList< KoShape * > &shapes)
 
static QList< KoShape * > linearizeSubtreeSorted (const QList< KoShape * > &shapes)
 

Public Attributes

QVector< CursorPoscursorPos
 
bool disableFontMatching = false
 Turn off font matching, which should speed up relayout slightly.
 
QPointF initialTextPosition = QPointF()
 
bool isBidi = false
 
bool isLoading = false
 Turned on when loading in text data, blocks updates to shape listeners.
 
QVector< LineBoxlineBoxes
 
QMap< int, int > logicalToVisualCursorPos
 
QString plainText
 
QVector< CharacterResultresult
 
QList< KoShape * > shapesInside
 
QList< KoShape * > shapesSubtract
 
KisForest< KoSvgTextContentElementtextData
 
int xRes = 72
 
int yRes = 72
 

Protected Member Functions

void shapeChanged (ChangeType type, KoShape *shape) override
 
- Protected Member Functions inherited from KoShape
 KoShape (const KoShape &rhs)
 
QList< ShapeChangeListener * > listeners () const
 
void setSizeImpl (const QSizeF &size) const
 
void shapeChangedPriv (KoShape::ChangeType type)
 
QTransform transform () const
 return the current matrix that contains the rotation/scale/position of this shape
 

Private Member Functions

QPainterPath defaultCursorShape ()
 defaultCursorShape This returns a default cursor shape for when there's no text inside the text shape.
 
int nextPos (int pos, bool visual)
 nextPos get the next position.
 
int previousPos (int pos, bool visual)
 previousPos get the previous position.
 
void setMementoImpl (const KoSvgTextShapeMementoSP memento)
 

Private Attributes

QScopedPointer< Privated
 
- Private Attributes inherited from KoShape::Private
QList< KoShape * > dependees
 list of shape dependent on this shape
 
QList< KoShape::ShapeChangeListener * > listeners
 
KoShapeContainerparent
 
QSet< KoShapeManager * > shapeManagers
 
QSet< KoShape * > toolDelegates
 

Friends

class KoSvgTextLoader
 
class TestSvgText
 

Additional Inherited Members

- Static Public Attributes inherited from KoShape
static const qint16 maxZIndex = std::numeric_limits<qint16>::max()
 
static const qint16 minZIndex = std::numeric_limits<qint16>::min()
 

Detailed Description

KoSvgTextShape is a root chunk of the <text> element subtree.

Definition at line 28 of file KoSvgTextShape.h.

Member Enumeration Documentation

◆ DebugElement

enum class KoSvgTextShape::DebugElement
strong
Enumerator
CharBbox 
LineBox 

Definition at line 46 of file KoSvgTextShape.h.

46 {
47 CharBbox = 1 << 0,
48 LineBox = 1 << 1,
49 };
The LineBox struct.

◆ TextType

Enumerator
PrePositionedText 

SVG 1.1 text, white spaces are collapsed or only spaces are preserved. Identical to PreformattedText otherwise.

PreformattedText 

Text-on-Path falls under this or PrePositionedText depending on collapse of lines.

No wrapping, but preserves spaces and linebreaks.

InlineWrap 

Uses inline size to wrap and preserves spaces.

TextInShape 

Uses shape-inside to wrap and preserves spaces.

Definition at line 69 of file KoSvgTextShape.h.

69 {
76 };
@ PreformattedText
Text-on-Path falls under this or PrePositionedText depending on collapse of lines.
@ TextInShape
Uses shape-inside to wrap and preserves spaces.
@ InlineWrap
Uses inline size to wrap and preserves spaces.

Constructor & Destructor Documentation

◆ KoSvgTextShape() [1/2]

KoSvgTextShape::KoSvgTextShape ( )

Definition at line 129 of file KoSvgTextShape.cpp.

130 : KoShape()
131 , d(new Private)
132{
134 d->textData.insert(d->textData.childBegin(), KoSvgTextContentElement());
135}
#define KoSvgTextShape_SHAPEID
KoShape()
Constructor.
Definition KoShape.cpp:163
void setShapeId(const QString &id)
Definition KoShape.cpp:1062
QScopedPointer< Private > d
The KoSvgTextContentElement struct.

References d, KoSvgTextShape_SHAPEID, and KoShape::setShapeId().

◆ KoSvgTextShape() [2/2]

KoSvgTextShape::KoSvgTextShape ( const KoSvgTextShape & rhs)

Definition at line 137 of file KoSvgTextShape.cpp.

138 : KoShape(rhs)
139 , d(new Private(*rhs.d))
140{
142}
Private()=default

References KoSvgTextShape_SHAPEID, and KoShape::setShapeId().

◆ ~KoSvgTextShape()

KoSvgTextShape::~KoSvgTextShape ( )
override

Definition at line 144 of file KoSvgTextShape.cpp.

145{
146}

◆ ~Private()

KoSvgTextShape::~Private ( )
inline

Definition at line 470 of file KoSvgTextShape_p.h.

470 {
471 qDeleteAll(shapesInside);
472 qDeleteAll(shapesSubtract);
473 }
QList< KoShape * > shapesInside
QList< KoShape * > shapesSubtract

Member Function Documentation

◆ anchoredChunkShift()

static qreal KoSvgTextShape::anchoredChunkShift ( const QVector< CharacterResult > & result,
const bool isHorizontal,
const int start,
int & end )
static

◆ applyAnchoring()

static void KoSvgTextShape::applyAnchoring ( QVector< CharacterResult > & result,
bool isHorizontal,
const KoSvgText::ResolutionHandler resHandler )
static

◆ applyTextLength()

void KoSvgTextShape::applyTextLength ( KisForest< KoSvgTextContentElement >::child_iterator currentTextElement,
QVector< CharacterResult > & result,
int & currentIndex,
int & resolvedDescendentNodes,
bool isHorizontal,
const KoSvgTextProperties resolvedProps,
const KoSvgText::ResolutionHandler & resHandler )

◆ applyTextPath()

static void KoSvgTextShape::applyTextPath ( KisForest< KoSvgTextContentElement >::child_iterator parent,
QVector< CharacterResult > & result,
bool isHorizontal,
QPointF & startPos,
const KoSvgTextProperties resolvedProps )
static

◆ applyWhiteSpace()

void KoSvgTextShape::applyWhiteSpace ( KisForest< KoSvgTextContentElement > & tree,
const bool convertToPreWrapped = false )
inline

applyWhiteSpace CSS Whitespace processes whitespaces so that duplicate white spaces and unnecessary hard breaks get removed from the text. Within the text layout we avoid removing the white spaces. However, when converting between text types it can be useful to remove these spaces. This function actually applies the white space rule to the active text.

Parameters
tree– tree to apply the whitespace rule onto.
convertToPreWrapped– switch all whitespace rules to pre-wrapped.

Definition at line 865 of file KoSvgTextShape_p.h.

865 {
866 QString allText;
867 QVector<bool> collapsed = collapsedWhiteSpacesForText(tree, allText, false);
868
869 auto end = std::make_reverse_iterator(tree.childBegin());
870 auto begin = std::make_reverse_iterator(tree.childEnd());
871
872 for (; begin != end; begin++) {
873 applyWhiteSpaceImpl(begin, collapsed, allText, convertToPreWrapped);
874 }
875 if (convertToPreWrapped) {
876 tree.childBegin()->properties.setProperty(KoSvgTextProperties::TextCollapseId, QVariant::fromValue(KoSvgText::Preserve));
877 tree.childBegin()->properties.setProperty(KoSvgTextProperties::TextWrapId, QVariant::fromValue(KoSvgText::Wrap));
878 }
879 }
child_iterator childEnd()
Definition KisForest.h:880
child_iterator childBegin()
Definition KisForest.h:876
@ TextCollapseId
KoSvgText::TextSpaceCollapse.
@ TextWrapId
KoSvgText::TextWrap.
void applyWhiteSpaceImpl(std::reverse_iterator< KisForest< KoSvgTextContentElement >::child_iterator > current, QVector< bool > &collapsed, QString &allText, const bool convertToPreWrapped)
static QVector< bool > collapsedWhiteSpacesForText(KisForest< KoSvgTextContentElement > &tree, QString &allText, const bool alsoCollapseLowSurrogate=false)
collapsedWhiteSpacesForText This returns the collapsed spaces for a given piece of text,...
@ Preserve
Do not collapse any space.
Definition KoSvgText.h:99

References KisForestDetail::Forest< T >::childBegin(), KisForestDetail::Forest< T >::childEnd(), KoSvgText::Preserve, KoSvgTextProperties::TextCollapseId, KoSvgTextProperties::TextWrapId, and KoSvgText::Wrap.

◆ applyWhiteSpaceImpl()

void KoSvgTextShape::applyWhiteSpaceImpl ( std::reverse_iterator< KisForest< KoSvgTextContentElement >::child_iterator > current,
QVector< bool > & collapsed,
QString & allText,
const bool convertToPreWrapped )
inline

Definition at line 881 of file KoSvgTextShape_p.h.

881 {
882 auto base = current.base();
883 // It seems that .base() refers to the next entry instead of the pointer,
884 // which is coherent with the template implementation of "operator*" here:
885 // https://en.cppreference.com/w/cpp/iterator/reverse_iterator.html
886 base--;
887 if(base != siblingEnd(base)) {
888 auto end = std::make_reverse_iterator(childBegin(base));
889 auto begin = std::make_reverse_iterator(childEnd(base));
890 for (; begin != end; begin++) {
891 applyWhiteSpaceImpl(begin, collapsed, allText, convertToPreWrapped);
892 }
893 }
894
895 if (!current->text.isEmpty()) {
896 const int total = current->text.size();
897 QString currentText = allText.right(total);
898
899 for (int i = 0; i < total; i++) {
900 const int j = total - (i+1);
901 const bool col = collapsed.takeLast();
902 if (col) {
903 currentText.remove(j, 1);
904 }
905
906 }
907 current->text = currentText;
908 allText.chop(total);
909 }
910 if (convertToPreWrapped) {
911 current->properties.removeProperty(KoSvgTextProperties::TextCollapseId);
912 current->properties.removeProperty(KoSvgTextProperties::TextWrapId);
913 }
914 }
ChildIterator< value_type, is_const > childBegin(const ChildIterator< value_type, is_const > &it)
Definition KisForest.h:290
ChildIterator< value_type, is_const > siblingEnd(const ChildIterator< value_type, is_const > &it)
Definition KisForest.h:255
ChildIterator< value_type, is_const > childEnd(const ChildIterator< value_type, is_const > &it)
Definition KisForest.h:300

References KoSvgTextProperties::TextCollapseId, and KoSvgTextProperties::TextWrapId.

◆ background()

QSharedPointer< KoShapeBackground > KoSvgTextShape::background ( ) const
overridevirtual

Return the brush used to paint the background of this shape with. A QBrush can have a plain color, be fully transparent or have a complex fill. setting such a brush will allow the shape to fill itself using that brush and will be able to tell if its transparent or not.

Returns
the background-brush

Reimplemented from KoShape.

Definition at line 1148 of file KoSvgTextShape.cpp.

1149{
1150 KoSvgTextProperties props = KisForestDetail::size(d->textData)? d->textData.childBegin()->properties: KoSvgTextProperties();
1153 }
1155}
A simple solid color shape background.
@ FillId
KoSvgText::BackgroundProperty.
QList< PropertyId > properties() const
QVariant property(PropertyId id, const QVariant &defaultValue=QVariant()) const
bool hasProperty(PropertyId id) const
int size(const Forest< T > &forest)
Definition KisForest.h:1232
BackgroundProperty is a special wrapper around KoShapeBackground for managing it in KoSvgTextProperti...
Definition KoSvgText.h:714

References d, KoSvgTextProperties::FillId, KoSvgTextProperties::hasProperty(), KoSvgTextProperties::properties(), KoSvgTextProperties::property(), and KisForestDetail::size().

◆ boundingRect()

QRectF KoSvgTextShape::boundingRect ( ) const
overridevirtual

Get the bounding box of the shape.

This includes the line width and the shadow of the shape

Returns
the bounding box of the shape

Reimplemented from KoShape.

Definition at line 1614 of file KoSvgTextShape.cpp.

1615{
1616 QRectF result;
1617 QList<KoShapeStrokeModelSP> parentStrokes;
1618 for (auto it = d->textData.compositionBegin(); it != d->textData.compositionEnd(); it++) {
1619 if (it.state() == KisForestDetail::Enter) {
1620 if (it->properties.hasProperty(KoSvgTextProperties::StrokeId)) {
1621 parentStrokes.append(it->properties.property(KoSvgTextProperties::StrokeId).value<KoSvgText::StrokeProperty>().property);
1622 }
1623 } else {
1624 KoShapeStrokeModelSP stroke = parentStrokes.size() > 0? parentStrokes.last(): nullptr;
1625 QRectF bb = it->associatedOutline.boundingRect();
1626 QMap<KoSvgText::TextDecoration, QPainterPath> decorations = it->textDecorations;
1627 for (int i = 0; i < decorations.values().size(); ++i) {
1628 bb |= decorations.values().at(i).boundingRect();
1629 }
1630 if (!bb.isEmpty()) {
1631 if (stroke) {
1632 KoInsets insets;
1633 stroke->strokeInsets(this, insets);
1634 result |= bb.adjusted(-insets.left, -insets.top, insets.right, insets.bottom);
1635 } else {
1636 result |= bb;
1637 }
1638 }
1639 if (it->properties.hasProperty(KoSvgTextProperties::StrokeId)) {
1640 // reset stroke to use parent stroke.
1641 parentStrokes.pop_back();
1642 }
1643 }
1644 }
1645 return this->absoluteTransformation().mapRect(result);
1646}
QTransform absoluteTransformation() const
Definition KoShape.cpp:382
@ StrokeId
KoSvgText::StrokeProperty.
KoShapeStrokeModelSP stroke() const override
QVector< CharacterResult > result
qreal bottom
Bottom inset.
Definition KoInsets.h:50
qreal right
Right inset.
Definition KoInsets.h:52
qreal top
Top inset.
Definition KoInsets.h:49
qreal left
Left inset.
Definition KoInsets.h:51
StrokeProperty is a special wrapper around KoShapeStrokeModel for managing it in KoSvgTextProperties.
Definition KoSvgText.h:733

References KoShape::absoluteTransformation(), KoInsets::bottom, d, KisForestDetail::Enter, KoInsets::left, result, KoInsets::right, stroke(), KoSvgTextProperties::StrokeId, and KoInsets::top.

◆ characterResultOnPath()

static qreal KoSvgTextShape::characterResultOnPath ( CharacterResult & cr,
qreal length,
qreal offset,
bool isHorizontal,
bool isClosed )
static

◆ childCount()

static int KoSvgTextShape::childCount ( KisForest< KoSvgTextContentElement >::child_iterator it)
inlinestatic

Get the child count of the current node. A node without children is a text node.

Definition at line 608 of file KoSvgTextShape_p.h.

608 {
609 return std::distance(KisForestDetail::childBegin(it), KisForestDetail::childEnd(it));
610 }

References KisForestDetail::childBegin(), and KisForestDetail::childEnd().

◆ cleanUp() [1/2]

void KoSvgTextShape::cleanUp ( )

Cleans up the internal text data. Used by undo commands.

Definition at line 1095 of file KoSvgTextShape.cpp.

1096{
1097 KoSvgTextShape::Private::cleanUp(d->textData);
1098 notifyChanged();
1100}
void shapeChangedPriv(KoShape::ChangeType type)
Definition KoShape.cpp:132
@ ContentChanged
the content of the shape changed e.g. a new image inside a pixmap/text change inside a textshape
Definition KoShape.h:110
void notifyChanged()
Definition KoShape.cpp:698

References KoShape::ContentChanged, d, KoShape::notifyChanged(), and KoShape::shapeChangedPriv().

◆ cleanUp() [2/2]

static void KoSvgTextShape::cleanUp ( KisForest< KoSvgTextContentElement > & tree)
inlinestatic

cleanUp This cleans up the tree by...

  • Removing empty text elements that are not the root or text paths.
  • Merging sibling elements with similar properties.
  • Merging single children with parent if possible.
    Parameters
    tree– tree to clean up

Definition at line 1069 of file KoSvgTextShape_p.h.

1069 {
1070 for (auto it = tree.depthFirstTailBegin(); it != tree.depthFirstTailEnd(); it++) {
1071 const int children = childCount(siblingCurrent(it));
1072 if (children == 0) {
1073
1074 // Remove empty leafs that are not the root or text paths.
1075 const int length = it->numChars(false);
1076 if (length == 0 && siblingCurrent(it) != tree.childBegin() && !it->textPath) {
1077 tree.erase(siblingCurrent(it));
1078 } else {
1079 // check if siblings are similar.
1080 auto siblingPrev = siblingCurrent(it);
1082 QVariant(KoSvgText::BidiNormal)).toInt());
1083 siblingPrev--;
1084 if (!isEnd(siblingPrev)
1085 && siblingPrev != siblingCurrent(it)
1086 && (siblingPrev->localTransformations.isEmpty() && it->localTransformations.isEmpty())
1087 && (!siblingPrev->textPath && !it->textPath)
1088 && (siblingPrev->textLength.isAuto && it->textLength.isAuto)
1089 && (siblingPrev->properties == it->properties)
1091 // TODO: handle localtransforms better; annoyingly, this requires whitespace handling
1092 siblingPrev->text += it->text;
1093 tree.erase(siblingCurrent(it));
1094 }
1095 }
1096 } else if (children == 1) {
1097 // merge single children into parents if possible.
1098 auto child = childBegin(siblingCurrent(it));
1099 if ((child->localTransformations.isEmpty() && it->localTransformations.isEmpty())
1100 && (!child->textPath && !it->textPath)
1101 && (child->textLength.isAuto && it->textLength.isAuto)
1102 && (!child->properties.hasNonInheritableProperties() || !it->properties.hasNonInheritableProperties())) {
1103 if (it->properties.hasNonInheritableProperties()) {
1104 KoSvgTextProperties props = it->properties;
1105 props.setAllButNonInheritableProperties(child->properties);
1106 child->properties = props;
1107 } else {
1108 child->properties.inheritFrom(it->properties);
1109 }
1110 tree.move(child, siblingCurrent(it));
1111 tree.erase(siblingCurrent(it));
1112 }
1113 }
1114 }
1115 }
qreal length(const QPointF &vec)
Definition Ellipse.cc:82
depth_first_tail_iterator depthFirstTailEnd()
Definition KisForest.h:856
child_iterator move(child_iterator subtree, child_iterator newPos)
move a subtree to new position Moves subtree into a new position pointer by newPos....
Definition KisForest.h:994
depth_first_tail_iterator depthFirstTailBegin()
Definition KisForest.h:852
child_iterator erase(child_iterator pos)
Removes element at position pos. If pos is 'end', then result is undefined.
Definition KisForest.h:956
@ UnicodeBidiId
KoSvgText::UnicodeBidi.
void setAllButNonInheritableProperties(const KoSvgTextProperties &properties)
Used to merge child properties into parent properties.
static int childCount(KisForest< KoSvgTextContentElement >::child_iterator it)
Get the child count of the current node. A node without children is a text node.
int toInt(const QString &str, bool *ok=nullptr)
bool isEnd(const ChildIterator< T, is_const > &it)
Definition KisForest.h:341
ChildIterator< value_type, is_const > siblingCurrent(ChildIterator< value_type, is_const > it)
Definition KisForest.h:240
@ BidiNormal
No new bidi-level is started.
Definition KoSvgText.h:57
@ BidiIsolate
Content is ordered as if in a separate paragraph.
Definition KoSvgText.h:61
@ BidiIsolateOverride
Definition KoSvgText.h:62

References KoSvgText::BidiIsolate, KoSvgText::BidiIsolateOverride, KoSvgText::BidiNormal, KisForestDetail::Forest< T >::childBegin(), KisForestDetail::Forest< T >::depthFirstTailBegin(), KisForestDetail::Forest< T >::depthFirstTailEnd(), KisForestDetail::Forest< T >::erase(), length(), KisForestDetail::Forest< T >::move(), KoSvgTextProperties::properties(), KoSvgTextProperties::setAllButNonInheritableProperties(), and KoSvgTextProperties::UnicodeBidiId.

◆ clearAssociatedOutlines()

void KoSvgTextShape::clearAssociatedOutlines ( )

◆ cloneShape()

KoShape * KoSvgTextShape::cloneShape ( ) const
overridevirtual

creates a deep copy of the shape or shape's subtree

Returns
a cloned shape

Reimplemented from KoShape.

Definition at line 154 of file KoSvgTextShape.cpp.

155{
156 return new KoSvgTextShape(*this);
157}

References KoSvgTextShape().

◆ collapsedWhiteSpacesForText()

static QVector< bool > KoSvgTextShape::collapsedWhiteSpacesForText ( KisForest< KoSvgTextContentElement > & tree,
QString & allText,
const bool alsoCollapseLowSurrogate = false )
inlinestatic

collapsedWhiteSpacesForText This returns the collapsed spaces for a given piece of text, without transforms.

Parameters
tree– text data tree.
allText– some collapseMethods modify the text. This is a pointer that sets the modified text.
alsoCollapseLowSurrogate– whether to mark utf16 surrogates as collapsed too.
Returns
list of collapsed characters

Definition at line 703 of file KoSvgTextShape_p.h.

703 {
704 QMap<int, KoSvgText::TextSpaceCollapse> collapseModes;
705
707 for (auto it = tree.compositionBegin(); it != tree.compositionEnd(); it++) {
708 if (it.state() == KisForestDetail::Enter) {
709 KoSvgTextProperties ownProperties = it->properties;
710 ownProperties.inheritFrom(parentProps.last());
711 parentProps.append(ownProperties);
712
713 const int children = childCount(siblingCurrent(it));
714 if (children == 0) {
715 QString text = it->text;
716 KoSvgText::TextSpaceCollapse collapse = KoSvgText::TextSpaceCollapse(parentProps.last().propertyOrDefault(KoSvgTextProperties::TextCollapseId).toInt());
717 collapseModes.insert(allText.size(), collapse);
718 allText += text;
719 }
720 } else {
721 parentProps.pop_back();
722 }
723 }
724 QVector<bool> collapsed = KoCssTextUtils::collapseSpaces(&allText, collapseModes);
725
726 if (alsoCollapseLowSurrogate) {
727 for (int i = 0; i < allText.size(); i++) {
728 if (i > 0 && allText.at(i).isLowSurrogate() && allText.at(i-1).isHighSurrogate()) {
729 collapsed[i] = true;
730 }
731 }
732 }
733 return collapsed;
734 }
composition_iterator compositionBegin()
Definition KisForest.h:912
composition_iterator compositionEnd()
Definition KisForest.h:916
static QVector< bool > collapseSpaces(QString *text, QMap< int, KoSvgText::TextSpaceCollapse > collapseMethods)
collapseSpaces Some versions of CSS-Text 'white-space' or 'text-space-collapse' will collapse or tran...
static const KoSvgTextProperties & defaultProperties()
void inheritFrom(const KoSvgTextProperties &parentProperties, bool resolve=false)
TextSpaceCollapse
Definition KoSvgText.h:96

References KoCssTextUtils::collapseSpaces(), KisForestDetail::Forest< T >::compositionBegin(), KisForestDetail::Forest< T >::compositionEnd(), KoSvgTextProperties::defaultProperties(), KisForestDetail::Enter, KoSvgTextProperties::inheritFrom(), KoSvgTextProperties::properties(), and KoSvgTextProperties::TextCollapseId.

◆ collectPaths()

KoShape * KoSvgTextShape::collectPaths ( const KoShape * rootShape,
QVector< CharacterResult > & result,
int & currentIndex )

◆ collectSubChunks()

static QVector< SubChunk > KoSvgTextShape::collectSubChunks ( KisForest< KoSvgTextContentElement >::child_iterator it,
KoSvgTextProperties parent,
bool textInPath,
bool & firstTextInPath )
static

Return a linearized representation of a subtree of text "subchunks".

◆ computeFontMetrics()

static void KoSvgTextShape::computeFontMetrics ( KisForest< KoSvgTextContentElement >::child_iterator parent,
const KoSvgTextProperties & parentProps,
const KoSvgText::FontMetrics & parentBaselineTable,
const KoSvgText::Baseline parentBaseline,
const QPointF superScript,
const QPointF subScript,
QVector< CharacterResult > & result,
int & currentIndex,
const KoSvgText::ResolutionHandler resHandler,
const bool isHorizontal,
const bool disableFontMatching )
static

◆ computeTextDecorations()

void KoSvgTextShape::computeTextDecorations ( KisForest< KoSvgTextContentElement >::child_iterator currentTextElement,
const QVector< CharacterResult > & result,
const QMap< int, int > & logicalToVisual,
const KoSvgText::ResolutionHandler resHandler,
KoPathShape * textPath,
qreal textPathoffset,
bool side,
int & currentIndex,
bool isHorizontal,
bool ltr,
bool wrapping,
const KoSvgTextProperties resolvedProps )

◆ convertCharTransformsToPreformatted()

void KoSvgTextShape::convertCharTransformsToPreformatted ( bool makeInlineSize = false)

convertCharTransformsToPreformatted Converts the text to a preformatted SVG 2.0 text. This changes the textType();

Parameters
makeInlineSize– whether to have inline size applied.

Definition at line 1259 of file KoSvgTextShape.cpp.

1260{
1261 const int inlineSize = writingMode() == KoSvgText::HorizontalTB? outlineRect().width(): outlineRect().height();
1262 d->applyWhiteSpace(d->textData, true);
1263 d->insertNewLinesAtAnchors(d->textData, !d->shapesInside.isEmpty());
1264 d->cleanUp(d->textData);
1265
1266 KoSvgTextProperties props = this->propertiesForPos(-1);
1267 if (makeInlineSize) {
1269 // Using QCeil here because otherwise the text will layout too tight.
1270 val.customValue = qCeil(inlineSize);
1271 val.isAuto = false;
1273 props.setProperty(KoSvgTextProperties::InlineSizeId, QVariant::fromValue(val));
1274 }
1275 } else {
1277 }
1278 // NOTE: applyWhiteSpace and insertNewLines don't notify changes,
1279 // so setProperties is the only thing triggering relayout();
1280 setPropertiesAtPos(-1, props);
1281}
@ InlineSizeId
KoSvgText::AutoValue.
void removeProperty(PropertyId id)
void setProperty(PropertyId id, const QVariant &value)
KoSvgTextProperties propertiesForPos(const int pos, bool inherited=false) const
Return the properties at a given position.
void setPropertiesAtPos(int pos, KoSvgTextProperties properties)
setPropertiesAtPos will set the properties at pos.
KoSvgText::WritingMode writingMode() const
writingMode There's a number of places we need to check the writing mode to provide proper controls.
QRectF outlineRect() const override
@ HorizontalTB
Definition KoSvgText.h:38

References KoSvgText::AutoValue::customValue, d, KoSvgTextProperties::hasProperty(), KoSvgText::HorizontalTB, KoSvgTextProperties::InlineSizeId, KoSvgText::AutoValue::isAuto, outlineRect(), propertiesForPos(), KoSvgTextProperties::removeProperty(), setPropertiesAtPos(), KoSvgTextProperties::setProperty(), and writingMode().

◆ copyRange()

std::unique_ptr< KoSvgTextShape > KoSvgTextShape::copyRange ( int index,
int length ) const

copyRange Copy the rich text for the given range.

Parameters
index– start string index of the range.
length– length of the range.
Returns
a KoSvgTextShape with only the content elements inside the range.

Definition at line 1041 of file KoSvgTextShape.cpp.

1042{
1043 KoSvgTextShape *clone = new KoSvgTextShape(*this);
1044 int zero = 0;
1045 int endRange = index + length;
1046 int size = KoSvgTextShape::Private::numChars(clone->d->textData.childBegin(), false) - endRange;
1047 clone->removeText(endRange, size);
1048 clone->removeText(zero, index);
1049 KoSvgTextShape::Private::cleanUp(clone->d->textData);
1050 return std::unique_ptr<KoSvgTextShape>(clone);
1051}
virtual QSizeF size() const
Get the size of the shape in pt.
Definition KoShape.cpp:820
bool removeText(int &index, int &length)
removeText Where insert text explicitly uses a cursorposition, remove text uses a string index....

References d, KoSvgTextShape(), length(), removeText(), and KoShape::size().

◆ createTextNodeIndex()

static KoSvgTextNodeIndex KoSvgTextShape::createTextNodeIndex ( KisForest< KoSvgTextContentElement >::child_iterator textElement)
static

◆ cursorForPos()

QPainterPath KoSvgTextShape::cursorForPos ( int pos,
QLineF & caret,
QColor & color,
double bidiFlagSize = 1.0 )

cursorForPos returns the QPainterPath associated with this cursorPosition.

Parameters
posthe cursor Position
bidiFlagSize– size of the bidirectional indicator.
Returns
a path to draw a cursor with.

Definition at line 541 of file KoSvgTextShape.cpp.

542{
543 if (d->result.isEmpty() || d->cursorPos.isEmpty() || pos < 0 || pos >= d->cursorPos.size()) {
544 return defaultCursorShape();
545 }
546 QPainterPath p;
547
548 CursorPos cursorPos = d->cursorPos.at(pos);
549
550 CharacterResult res = d->result.at(cursorPos.cluster);
551
552 const QTransform tf = res.finalTransform();
553 color = res.cursorInfo.color;
554 caret = res.cursorInfo.caret;
555 caret.translate(res.cursorInfo.offsets.value(cursorPos.offset, QPointF()));
556
557 p.moveTo(tf.map(caret.p1()));
558 p.lineTo(tf.map(caret.p2()));
559 if (d->isBidi && bidiFlagSize > 0) {
560 int sign = res.cursorInfo.rtl ? -1 : 1;
561 double bidiFlagHalf = bidiFlagSize * 0.5;
562 QPointF point3;
563 QPointF point4;
565 qreal slope = bidiFlagHalf * (caret.dx()/ caret.dy());
566 point3 = QPointF(caret.p2().x() + slope + (sign * bidiFlagHalf), caret.p2().y() + bidiFlagHalf);
567 point4 = QPointF(point3.x() + slope - (sign * bidiFlagHalf),point3.y() + bidiFlagHalf);
568 } else {
569 qreal slope = bidiFlagHalf * (caret.dy()/ caret.dx());
570 point3 = QPointF(caret.p2().x() - bidiFlagHalf, caret.p2().y() - slope + (sign * bidiFlagHalf));
571 point4 = QPointF(point3.x() - bidiFlagHalf, point3.y() - slope - (sign * bidiFlagHalf));
572 }
573 p.lineTo(tf.map(point3));
574 p.lineTo(tf.map(point4));
575 }
576 caret = tf.map(caret);
577
578 return p;
579}
const Params2D p
QVector< CursorPos > cursorPos
QPainterPath defaultCursorShape()
defaultCursorShape This returns a default cursor shape for when there's no text inside the text shape...
QTransform finalTransform() const
QLineF caret
Caret for this characterResult.
bool rtl
Whether the current glyph is right-to-left, as opposed to the markup.
QColor color
Which color the current position has.
QVector< QPointF > offsets
The advance offsets for each grapheme index.

References CursorInfo::caret, CursorInfo::color, CharacterResult::cursorInfo, cursorPos, d, defaultCursorShape(), CharacterResult::finalTransform(), KoSvgText::HorizontalTB, CursorInfo::offsets, p, CursorInfo::rtl, sign(), and writingMode().

◆ debugParsing()

void KoSvgTextShape::debugParsing ( )

Outputs debug with the current textData tree.

Definition at line 1488 of file KoSvgTextShape.cpp.

1489{
1490 qDebug() << "Tree size:" << KisForestDetail::size(d->textData);
1491 QString spaces;
1492 for (auto it = compositionBegin(d->textData); it != compositionEnd(d->textData); it++) {
1493 if (it.state() == KisForestDetail::Enter) {
1494
1495 qDebug() << QString(spaces + "+") << it->text;
1496 qDebug() << QString(spaces + "|") << it->properties.convertToSvgTextAttributes();
1497 qDebug() << QString(spaces + "| PropertyType:") << it->properties.property(KoSvgTextProperties::KraTextStyleType).toString();
1498 qDebug() << QString(spaces + "| Fill set: ") << it->properties.hasProperty(KoSvgTextProperties::FillId);
1499 qDebug() << QString(spaces + "| Stroke set: ") << it->properties.hasProperty(KoSvgTextProperties::StrokeId);
1500 qDebug() << QString(spaces + "| Opacity: ") << it->properties.property(KoSvgTextProperties::Opacity);
1501 qDebug() << QString(spaces + "| PaintOrder: ") << it->properties.hasProperty(KoSvgTextProperties::PaintOrder);
1502 qDebug() << QString(spaces + "| Visibility set: ") << it->properties.hasProperty(KoSvgTextProperties::Visiblity);
1503 qDebug() << QString(spaces + "| TextPath set: ") << (!it->textPath.isNull());
1504 qDebug() << QString(spaces + "| Transforms set: ") << it->localTransformations;
1505 spaces.append(" ");
1506 }
1507
1508 if (it.state() == KisForestDetail::Leave) {
1509 spaces.chop(1);
1510 }
1511 }
1512}
@ Visiblity
Bool, CSS visibility.
@ PaintOrder
QVector<KoShape::PaintOrder>
@ Opacity
Double, SVG shape opacity.
@ KraTextStyleType
string, used to identify the style preset type (character or paragraph).
ResultIterator compositionEnd(Iterator it)
Definition KisForest.h:570
ResultIterator compositionBegin(Iterator it)
Definition KisForest.h:562

References d, KisForestDetail::Enter, KoSvgTextProperties::FillId, KoSvgTextProperties::KraTextStyleType, KisForestDetail::Leave, KoSvgTextProperties::Opacity, KoSvgTextProperties::PaintOrder, KisForestDetail::size(), KoSvgTextProperties::StrokeId, and KoSvgTextProperties::Visiblity.

◆ defaultCursorShape()

QPainterPath KoSvgTextShape::defaultCursorShape ( )
private

defaultCursorShape This returns a default cursor shape for when there's no text inside the text shape.

Returns
a QPainterPath for a cursor.

Definition at line 524 of file KoSvgTextShape.cpp.

525{
527 double fontSize = this->textProperties().fontSize().value;
528 QPainterPath p;
529 if (mode == KoSvgText::HorizontalTB) {
530 p.moveTo(0, fontSize*0.2);
531 p.lineTo(0, -fontSize);
532 } else {
533 p.moveTo(-fontSize * 0.5, 0);
534 p.lineTo(fontSize, 0);
535 }
536 p.translate(d->initialTextPosition);
537
538 return p;
539}
KoSvgText::CssLengthPercentage fontSize() const
KoSvgTextProperties textProperties() const

References d, KoSvgTextProperties::fontSize(), KoSvgText::HorizontalTB, p, textProperties(), KoSvgText::CssLengthPercentage::value, and writingMode().

◆ defaultPlaceholderText()

const QString & KoSvgTextShape::defaultPlaceholderText ( )
static

Definition at line 148 of file KoSvgTextShape.cpp.

149{
150 static const QString s_placeholderText = i18nc("Default text for the text shape", "Placeholder Text");
151 return s_placeholderText;
152}

◆ enterNodeSubtree()

void KoSvgTextShape::enterNodeSubtree ( )

Set the current node to its first child, entering the subtree.

Definition at line 1437 of file KoSvgTextShape.cpp.

1438{
1439
1440}

◆ finalizeDecoration()

static void KoSvgTextShape::finalizeDecoration ( QPainterPath decorationPath,
const QPointF offset,
const QPainterPathStroker & stroker,
const KoSvgText::TextDecoration type,
QMap< KoSvgText::TextDecoration, QPainterPath > & decorationPaths,
const KoPathShape * currentTextPath,
const bool isHorizontal,
const qreal currentTextPathOffset,
const bool textPathSide )
static

◆ findNodeIndexForPropertyId()

KoSvgTextNodeIndex KoSvgTextShape::findNodeIndexForPropertyId ( KoSvgTextProperties::PropertyId propertyId)

findNodeIndexForPropertyId

Returns
the nodeIndex of the first content element found with a given property id. @propertyId -- id to search for.

Definition at line 1116 of file KoSvgTextShape.cpp.

1117{
1118 for (auto it = d->textData.childBegin(); it != d->textData.childEnd(); it++) {
1119 if (it->properties.hasProperty(propertyId)) {
1120 return Private::createTextNodeIndex(it);
1122 auto found = findNodeIndexForPropertyIdImpl(it, propertyId);
1123 if (found != it) {
1124 return Private::createTextNodeIndex(found);
1125 }
1126 }
1127 }
1128 return Private::createTextNodeIndex(d->textData.childBegin());
1129}
KisForest< KoSvgTextContentElement >::child_iterator findNodeIndexForPropertyIdImpl(KisForest< KoSvgTextContentElement >::child_iterator parent, KoSvgTextProperties::PropertyId propertyId)

References KisForestDetail::childBegin(), KisForestDetail::childEnd(), d, and findNodeIndexForPropertyIdImpl().

◆ findRangeForNodeIndex()

QPair< int, int > KoSvgTextShape::findRangeForNodeIndex ( const KoSvgTextNodeIndex & node) const

findRangeForNodeIndex Find the start and end cursor position for a given nodeIndex.

Parameters
nodethe tree index to find the range for.
Returns
A QPair<int,int> describing cursor position range encompassed by the tree index and it's children. Will return {-1, -1} when the tree index is invalid.

Definition at line 1131 of file KoSvgTextShape.cpp.

1132{
1133 int startIndex = 0;
1134 int endIndex = 0;
1135 for (auto child = d->textData.childBegin(); child != d->textData.childEnd(); child++) {
1136 // count children
1137 d->startIndexOfIterator(child, node.d->textElement, startIndex);
1138 endIndex = d->numChars(node.d->textElement) + startIndex;
1139 }
1140 return qMakePair(posForIndex(startIndex), posForIndex(endIndex));
1141}
QScopedPointer< Private > d
int posForIndex(int index, bool firstIndex=false, bool skipSynthetic=false) const
posForIndex Get the cursor position for a given index in a string.

References d, KoSvgTextNodeIndex::d, and posForIndex().

◆ findTextContentElementForIndex()

static KisForest< KoSvgTextContentElement >::depth_first_tail_iterator KoSvgTextShape::findTextContentElementForIndex ( KisForest< KoSvgTextContentElement > & tree,
int & currentIndex,
int sought,
bool skipZeroWidth = false )
inlinestatic

findTextContentElementForIndex Finds the given leaf of the current tree-wide string index.

Parameters
tree– tree to search in.
currentIndex– currentIndex, will always be set to the start index of the found element.
sought– index sought.
skipZeroWidth– whether to explicitly skip zero-width chunks. Remove text may set this to true, while inserting text into empty chunks requires this to be false.
Returns
iterator – found iterator. Will default to tree end if nothing is found.

Definition at line 625 of file KoSvgTextShape_p.h.

629 {
630 auto it = tree.depthFirstTailBegin();
631 for (; it != tree.depthFirstTailEnd(); it++) {
632 if (childCount(siblingCurrent(it)) > 0) {
633 continue;
634 }
635 int length = it->numChars(false);
636 if (length == 0 && skipZeroWidth) {
637 continue;
638 }
639
640 if (sought == currentIndex || (sought > currentIndex && sought < currentIndex + length)) {
641 break;
642 } else {
643 currentIndex += length;
644 }
645 }
646 return it;
647 }

References KisForestDetail::Forest< T >::depthFirstTailBegin(), KisForestDetail::Forest< T >::depthFirstTailEnd(), and length().

◆ fontMatchingDisabled()

bool KoSvgTextShape::fontMatchingDisabled ( ) const

fontMatchingDisabled

Returns
whether font matching is disabled for this shape.

Definition at line 1529 of file KoSvgTextShape.cpp.

1530{
1531 return d->disableFontMatching;
1532}

References d.

◆ generateDecorationPaths()

QMap< KoSvgText::TextDecoration, QPainterPath > KoSvgTextShape::generateDecorationPaths ( const int & start,
const int & end,
const KoSvgText::ResolutionHandler resHandler,
const QVector< CharacterResult > & result,
const bool isHorizontal,
const KoSvgText::TextDecorations & decor,
const KoSvgText::TextDecorationStyle style = KoSvgText::TextDecorationStyle::Solid,
const bool textDecorationSkipInset = false,
const KoPathShape * currentTextPath = nullptr,
const qreal currentTextPathOffset = 0.0,
const bool textPathSide = false,
const KoSvgText::TextDecorationUnderlinePosition underlinePosH = KoSvgText::TextDecorationUnderlinePosition::UnderlineAuto,
const KoSvgText::TextDecorationUnderlinePosition underlinePosV = KoSvgText::TextDecorationUnderlinePosition::UnderlineAuto )

◆ getMemento()

KoSvgTextShapeMementoSP KoSvgTextShape::getMemento ( )

Get a memento holding the current textdata and layout info.

Definition at line 1447 of file KoSvgTextShape.cpp.

1448{
1450 d->result,
1451 d->lineBoxes,
1452 d->cursorPos,
1453 d->logicalToVisualCursorPos,
1454 d->plainText,
1455 d->isBidi,
1456 d->initialTextPosition));
1457}
QSharedPointer< KoSvgTextShapeMemento > KoSvgTextShapeMementoSP

References d.

◆ handleLineBoxAlignment()

static void KoSvgTextShape::handleLineBoxAlignment ( KisForest< KoSvgTextContentElement >::child_iterator parent,
QVector< CharacterResult > & result,
const QVector< LineBox > lineBoxes,
int & currentIndex,
const bool isHorizontal,
const KoSvgTextProperties resolvedProps )
static

◆ indexForPos()

int KoSvgTextShape::indexForPos ( int pos) const

indexForPos get the string index for a given cursor position.

Parameters
posthe cursor position.
Returns
the index in the string.

Definition at line 796 of file KoSvgTextShape.cpp.

797{
798 if (d->cursorPos.isEmpty() || pos < 0) {
799 return -1;
800 }
801
802 return d->cursorPos.at(qMin(d->cursorPos.size()-1, pos)).index;
803}

References d.

◆ initialTextPosition()

QPointF KoSvgTextShape::initialTextPosition ( ) const

initialTextPosition Returns the initial text position as per SVG algorithm. The eventual result of this can include transforms or repositioning due to text shapes.

Returns
the initial text position in shape coordinates.

◆ insertNewLinesAtAnchors()

static void KoSvgTextShape::insertNewLinesAtAnchors ( KisForest< KoSvgTextContentElement > & tree,
bool shapesInside = false )
inlinestatic

insertNewLinesAtAnchors Resolves character transforms and then inserts new lines at each transform that creates a new chunk.

Parameters
tree– tree to apply to.
shapesInside– whether we're wrapping in shape.

Definition at line 923 of file KoSvgTextShape_p.h.

923 {
924 QString all;
925 QVector<bool> collapsed = collapsedWhiteSpacesForText(tree, all, false);
927 int globalIndex = 0;
928 KoSvgTextProperties props = tree.childBegin()->properties;
932 bool isHorizontal = mode == KoSvgText::HorizontalTB;
933 bool isWrapped = (props.hasProperty(KoSvgTextProperties::InlineSizeId)
934 || shapesInside);
935 QVector<KoSvgText::CharTransformation> resolvedTransforms(all.size());
936 resolveTransforms(tree.childBegin(), all, result, globalIndex,
937 isHorizontal, isWrapped, false, resolvedTransforms,
939 false);
940
941 auto end = std::make_reverse_iterator(tree.childBegin());
942 auto begin = std::make_reverse_iterator(tree.childEnd());
943
944 bool inTextPath = false;
945 for (; begin != end; begin++) {
946 insertNewLinesAtAnchorsImpl(begin, resolvedTransforms, inTextPath);
947 }
948 }
@ WritingModeId
KoSvgText::WritingMode.
QVariant propertyOrDefault(PropertyId id) const
static void resolveTransforms(KisForest< KoSvgTextContentElement >::child_iterator currentTextElement, QString text, QVector< CharacterResult > &result, int &currentIndex, bool isHorizontal, bool wrapped, bool textInPath, QVector< KoSvgText::CharTransformation > &resolved, QVector< bool > collapsedChars, const KoSvgTextProperties resolvedProps, bool withControls=true)
static void insertNewLinesAtAnchorsImpl(std::reverse_iterator< KisForest< KoSvgTextContentElement >::child_iterator > current, QVector< KoSvgText::CharTransformation > &resolvedTransforms, bool &inTextPath)

References KisForestDetail::Forest< T >::childBegin(), KisForestDetail::Forest< T >::childEnd(), KoSvgTextProperties::defaultProperties(), KoSvgTextProperties::hasProperty(), KoSvgText::HorizontalTB, KoSvgTextProperties::inheritFrom(), KoSvgTextProperties::InlineSizeId, KoSvgTextProperties::propertyOrDefault(), and KoSvgTextProperties::WritingModeId.

◆ insertNewLinesAtAnchorsImpl()

static void KoSvgTextShape::insertNewLinesAtAnchorsImpl ( std::reverse_iterator< KisForest< KoSvgTextContentElement >::child_iterator > current,
QVector< KoSvgText::CharTransformation > & resolvedTransforms,
bool & inTextPath )
inlinestatic

Because sometimes we have to deal with multiple transforms on a span we only really want to insert newlines when at a content element start. In theory the other transforms can be tested, but this is hard, and semantically it doesn't make sense if a svg text does this.

Definition at line 950 of file KoSvgTextShape_p.h.

952 {
953
954 inTextPath = (!current->textPath.isNull());
955 auto base = current.base();
956 base--;
957 if(base != siblingEnd(base)) {
958 auto end = std::make_reverse_iterator(childBegin(base));
959 auto begin = std::make_reverse_iterator(childEnd(base));
960 for (; begin != end; begin++) {
962 resolvedTransforms,
963 inTextPath);
964 }
965 }
966
967 if (!current->text.isEmpty()) {
968 const int total = current->text.size();
969
970 for (int i = 0; i < total; i++) {
971 const int j = total - (i+1);
972 KoSvgText::CharTransformation transform = resolvedTransforms.takeLast();
979 bool startsNewChunk = transform.startsNewChunk() && j == 0;
980
981 if (inTextPath) {
982 // First transform in path is always absolute, so we don't insert a newline.
983 startsNewChunk = false;
984 inTextPath = false;
985 }
986 // When there's no new chunk, we're not at the start of the text and there isn't already a line feed, insert a line feed.
987 if (startsNewChunk && !resolvedTransforms.isEmpty() && current->text.at(j) != QChar::LineFeed) {
988 current->text.insert(j, "\n");
989 }
990 }
991 }
992 current->localTransformations.clear();
993 }
QTransform transform() const
return the current matrix that contains the rotation/scale/position of this shape
Definition KoShape.cpp:1145

◆ insertRichText()

bool KoSvgTextShape::insertRichText ( int pos,
const KoSvgTextShape * richText )

insertRichText Insert rich text at the given cursor pos. This will first split contents at the given pos before inserting the new rich text.

Parameters
pos– cursor pos to insert at.
richTextKoSvgTextShape with rich text data. TODO: make this const once KisForest constness issues have been fixed.
Returns
whether insertion happened successfully.

Definition at line 1053 of file KoSvgTextShape.cpp.

1054{
1055 bool success = false;
1056 int currentIndex = 0;
1057 int elementIndex = 0;
1058 int insertionIndex = 0;
1059
1060 if (isEnd(richText->d->textData.childBegin())) {
1061 // rich text is empty.
1062 return success;
1063 }
1064
1065 if (pos > -1 && !d->cursorPos.isEmpty()) {
1066 CursorPos cursorPos = d->cursorPos.at(qMin(d->cursorPos.size()-1, pos));
1067 CharacterResult res = d->result.at(cursorPos.cluster);
1068 elementIndex = res.plaintTextIndex;
1069 insertionIndex = cursorPos.index;
1070 elementIndex = qMin(elementIndex, d->result.size()-1);
1071 }
1072
1073 KoSvgTextShape::Private::splitContentElement(this->d->textData, insertionIndex);
1074
1075 auto it = d->findTextContentElementForIndex(d->textData, currentIndex, insertionIndex);
1076 if (it != d->textData.depthFirstTailEnd()) {
1077 d->textData.move(richText->d->textData.childBegin(), siblingCurrent(it));
1078 success = true;
1079 } else {
1080 currentIndex = 0;
1081 it = d->findTextContentElementForIndex(d->textData, currentIndex, elementIndex);
1082 if (it != d->textData.depthFirstTailEnd()) {
1083 d->textData.move(richText->d->textData.childBegin(), siblingEnd(siblingCurrent(it)));
1084 success = true;
1085 }
1086 }
1087
1088 if (success) {
1089 notifyChanged();
1091 }
1092 return success;
1093}

References KoShape::ContentChanged, cursorPos, d, KoShape::notifyChanged(), CharacterResult::plaintTextIndex, and KoShape::shapeChangedPriv().

◆ insertText()

bool KoSvgTextShape::insertText ( int pos,
QString text )

insertText Insert a text somewhere in the KoTextShape.

Parameters
posthe cursor position.
textthe text to insert.
Returns
whether it was successful in inserting text.

< Current position of the search.

The distinction between element and insertion index allows us to insert text at the start or end of a content element, without ambiguity on whether we're inserting into the next element.

Definition at line 810 of file KoSvgTextShape.cpp.

811{
812 bool success = false;
813 int currentIndex = 0;
814
818 int elementIndex = 0;
819 int insertionIndex = 0;
820 if (pos > -1 && !d->cursorPos.isEmpty()) {
821 CursorPos cursorPos = d->cursorPos.at(pos);
822 CharacterResult res = d->result.at(cursorPos.cluster);
823 elementIndex = res.plaintTextIndex;
824 insertionIndex = cursorPos.index;
825 elementIndex = qMin(elementIndex, d->result.size()-1);
826 }
827 auto it = d->findTextContentElementForIndex(d->textData, currentIndex, elementIndex);
828 if (it != d->textData.depthFirstTailEnd()) {
829 const int offset = insertionIndex - currentIndex;
830 it->insertText(offset, text);
831
832 d->insertTransforms(d->textData, insertionIndex, text.size(), (elementIndex == insertionIndex));
835 success = true;
836 }
837 return success;
838}

References KoShape::ContentChanged, cursorPos, d, KoShape::notifyChanged(), CharacterResult::plaintTextIndex, and KoShape::shapeChangedPriv().

◆ insertTransforms()

static void KoSvgTextShape::insertTransforms ( KisForest< KoSvgTextContentElement > & tree,
const int start,
const int length,
const bool allowSkipFirst )
inlinestatic

insertTransforms Inserts empty transforms into tree recursively.

Parameters
tree– tree to insert transforms on.
start– start index.
length– amount of transforms to insert.
allowSkipFirst– whether we're allowed to skip the first transform because it is at the start of a text element.

Definition at line 802 of file KoSvgTextShape_p.h.

802 {
803 QString all;
804 QVector<bool> collapsedCharacters = collapsedWhiteSpacesForText(tree, all, true);
805
806 auto root = tree.childBegin();
807 insertTransformsImpl(root, 0, start, length, collapsedCharacters, allowSkipFirst);
808 }
static int insertTransformsImpl(KisForest< KoSvgTextContentElement >::child_iterator currentTextElement, const int globalIndex, const int start, const int length, const QVector< bool > collapsedCharacters, const bool allowSkipFirst)
insertTransformsImpl Recursive function that handles inserting empty transforms into a given range....

References KisForestDetail::Forest< T >::childBegin(), and length().

◆ insertTransformsImpl()

static int KoSvgTextShape::insertTransformsImpl ( KisForest< KoSvgTextContentElement >::child_iterator currentTextElement,
const int globalIndex,
const int start,
const int length,
const QVector< bool > collapsedCharacters,
const bool allowSkipFirst )
inlinestatic

insertTransformsImpl Recursive function that handles inserting empty transforms into a given range. Used by insertTransforms.

Definition at line 814 of file KoSvgTextShape_p.h.

814 {
815 int currentLength = 0;
816 auto it = childBegin(currentTextElement);
817 if (it != childEnd(currentTextElement)) {
818 for (; it != childEnd(currentTextElement); it++) {
819 currentLength += insertTransformsImpl(it, globalIndex + currentLength, start, length, collapsedCharacters, allowSkipFirst);
820 }
821 } else {
822 currentLength = currentTextElement->text.size();
823 }
824
825 if (!currentTextElement->localTransformations.isEmpty()) {
826 int transformOffset = 0;
827 int transformOffsetEnd = 0;
828
829 for (int i = globalIndex; i < globalIndex + currentLength; i++) {
830 if (i < start) {
831 transformOffset += collapsedCharacters.at(i)? 0: 1;
832 }
833 if (i < start + length) {
834 transformOffsetEnd += collapsedCharacters.at(i)? 0: 1;
835 } else {
836 break;
837 }
838 }
839
840 // When at the start, skip the first transform.
841 if (transformOffset == 0 && allowSkipFirst && currentTextElement->localTransformations.at(0).startsNewChunk()) {
842 transformOffset += 1;
843 }
844
845 if (transformOffset < currentTextElement->localTransformations.size()) {
846 for (int i = transformOffset; i < transformOffsetEnd; i++) {
847 currentTextElement->localTransformations.insert(i, KoSvgText::CharTransformation());
848 }
849 }
850
851 }
852 return currentLength;
853 }

References length().

◆ iteratorForTreeIndex()

static KisForest< KoSvgTextContentElement >::child_iterator KoSvgTextShape::iteratorForTreeIndex ( const QVector< int > treeIndex,
KisForest< KoSvgTextContentElement >::child_iterator parent )
inlinestatic

Definition at line 1117 of file KoSvgTextShape_p.h.

1117 {
1118 if (treeIndex.isEmpty()) return parent;
1119 QVector<int> idx = treeIndex;
1120 int count = idx.takeFirst();
1121 for (auto child = KisForestDetail::childBegin(parent); child != KisForestDetail::childEnd(parent); child++) {
1122 if (count == 0) {
1124 return iteratorForTreeIndex(idx, child);
1125 } else {
1126 return child;
1127 }
1128 }
1129 count -= 1;
1130 }
1132 }
KoShapeContainer * parent
Definition KoShape_p.h:80
static KisForest< KoSvgTextContentElement >::child_iterator iteratorForTreeIndex(const QVector< int > treeIndex, KisForest< KoSvgTextContentElement >::child_iterator parent)

References KisForestDetail::childBegin(), and KisForestDetail::childEnd().

◆ leaveNodeSubtree()

void KoSvgTextShape::leaveNodeSubtree ( )

Set the current node to its parent, leaving the subtree.

Definition at line 1442 of file KoSvgTextShape.cpp.

1443{
1444
1445}

◆ lineEnd()

int KoSvgTextShape::lineEnd ( int pos)

lineEnd return the 'line end' for this pos. This uses anchored chunks, so each absolute x, y posititioning will be considered a line-start.

Parameters
pos– the cursor pos for which to find the line end.
Returns
the line end.

Definition at line 266 of file KoSvgTextShape.cpp.

267{
268 if (pos < 0 || d->cursorPos.isEmpty() || d->result.isEmpty()) {
269 return pos;
270 }
271 if (pos > d->cursorPos.size() - 1) {
272 return d->cursorPos.size() - 1;
273 }
274 int candidate = 0;
275 int posCluster = d->cursorPos.at(pos).cluster;
276 for (int i = pos; i < d->cursorPos.size(); i++) {
277 CursorPos p = d->cursorPos.at(i);
278 if (d->result.at(p.cluster).anchored_chunk && i > pos && posCluster != p.cluster) {
279 break;
280 }
281 candidate = i;
282 }
283 return candidate;
284}

References cursorPos, d, and p.

◆ lineStart()

int KoSvgTextShape::lineStart ( int pos)

lineStart return the 'line start' for this pos. This uses anchored chunks, so each absolute x, y posititioning will be considered a line-start.

Parameters
pos– the cursor pos for which to find the line start.
Returns
the line start.

Definition at line 247 of file KoSvgTextShape.cpp.

248{
249 if (pos < 0 || d->cursorPos.isEmpty() || d->result.isEmpty()) {
250 return pos;
251 }
252 CursorPos p = d->cursorPos.at(pos);
253 if (d->result.at(p.cluster).anchored_chunk && p.offset == 0) {
254 return pos;
255 }
256 int candidate = 0;
257 for (int i = 0; i < pos; i++) {
258 CursorPos p2 = d->cursorPos.at(i);
259 if (d->result.at(p2.cluster).anchored_chunk && p2.offset == 0) {
260 candidate = i;
261 }
262 }
263 return candidate;
264}
QPointF p2

References cursorPos, d, p, and p2.

◆ loadGlyph()

static bool KoSvgTextShape::loadGlyph ( const KoSvgText::ResolutionHandler & resHandler,
const FT_Int32 faceLoadFlags,
const bool isHorizontal,
const char32_t firstCodepoint,
const KoSvgText::TextRendering rendering,
raqm_glyph_t & currentGlyph,
CharacterResult & charResult,
QPointF & totalAdvanceFTFontCoordinates )
static

◆ loadGlyphOnly()

static std::pair< QTransform, qreal > KoSvgTextShape::loadGlyphOnly ( const QTransform & ftTF,
FT_Int32 faceLoadFlags,
bool isHorizontal,
raqm_glyph_t & currentGlyph,
CharacterResult & charResult,
const KoSvgText::TextRendering rendering )
static

◆ mergePropertiesIntoRange()

void KoSvgTextShape::mergePropertiesIntoRange ( const int startPos,
const int endPos,
const KoSvgTextProperties properties,
const QSet< KoSvgTextProperties::PropertyId > removeProperties = QSet<KoSvgTextProperties::PropertyId>() )

mergePropertiesIntoRange Merge given properties into the given range. This will first split the nodes at the two range ends, and then merge in the properties into each leaf node. Won't do anything when startPos == endPos

First, the properties in removeProperties list will be removed, then properties in properties will be applied. If the property is present in both lists, then the value from properties will be used.

Parameters
startPos– cursor pos start.
endPos– cursor pos end.
properties– properties to merge in.
removeProperties– optional list of properties to remove, these will always apply after merging.

Definition at line 974 of file KoSvgTextShape.cpp.

978{
979 if ((startPos < 0 && startPos == endPos) || d->cursorPos.isEmpty()) {
980 if (KisForestDetail::size(d->textData)) {
981 Q_FOREACH(KoSvgTextProperties::PropertyId p, properties.properties()) {
982 d->textData.childBegin()->properties.setProperty(p, properties.property(p));
983 }
984 Q_FOREACH(KoSvgTextProperties::PropertyId p, removeProperties) {
985 d->textData.childBegin()->properties.removeProperty(p);
986 }
987 }
990 return;
991 }
992 const int startIndex = d->cursorPos.at(startPos).index;
993 const int endIndex = d->cursorPos.at(endPos).index;
994 if (startIndex != endIndex) {
995 KoSvgTextShape::Private::splitContentElement(d->textData, startIndex);
996 KoSvgTextShape::Private::splitContentElement(d->textData, endIndex);
997 }
998 bool changed = false;
999 int currentIndex = 0;
1000 KoSvgText::AutoValue inlineSize = d->textData.childBegin()->properties.propertyOrDefault(KoSvgTextProperties::InlineSizeId).value<KoSvgText::AutoValue>();
1001 bool isWrapping = !d->shapesInside.isEmpty() || !inlineSize.isAuto;
1002 for (auto it = d->textData.depthFirstTailBegin(); it != d->textData.depthFirstTailEnd(); it++) {
1003 if (KoSvgTextShape::Private::childCount(siblingCurrent(it)) > 0) {
1004 continue;
1005 }
1006
1007 if (currentIndex >= startIndex && currentIndex < endIndex) {
1008 Q_FOREACH(KoSvgTextProperties::PropertyId p, removeProperties) {
1010 d->textData.childBegin()->properties.removeProperty(p);
1011 } else {
1012 it->properties.removeProperty(p);
1013 }
1014 }
1015 Q_FOREACH(KoSvgTextProperties::PropertyId p, properties.properties()) {
1017 d->textData.childBegin()->properties.setProperty(p, properties.property(p));
1018 } else {
1019 it->properties.setProperty(p, properties.property(p));
1020 }
1021 }
1022
1023 changed = true;
1024 }
1025 currentIndex += it->numChars(false);
1026 }
1027
1028 if (changed){
1029 KoSvgTextShape::Private::cleanUp(d->textData);
1030 notifyChanged();
1032 if (properties.hasProperty(KoSvgTextProperties::FillId)) {
1034 }
1037 }
1038 }
1039}
@ StrokeChanged
the shapes stroke has changed
Definition KoShape.h:105
@ BackgroundChanged
the shapes background has changed
Definition KoShape.h:106
@ TextAnchorId
KoSvgText::TextAnchor.
static bool propertyIsBlockOnly(KoSvgTextProperties::PropertyId id)

References KoShape::BackgroundChanged, KoShape::ContentChanged, d, KoSvgTextProperties::FillId, KoSvgTextProperties::hasProperty(), KoSvgTextProperties::InlineSizeId, KoSvgText::AutoValue::isAuto, KoShape::notifyChanged(), p, KoSvgTextProperties::properties(), KoSvgTextProperties::property(), KoSvgTextProperties::propertyIsBlockOnly(), KoShape::shapeChangedPriv(), KisForestDetail::size(), KoShape::StrokeChanged, KoSvgTextProperties::StrokeId, and KoSvgTextProperties::TextAnchorId.

◆ nextIndex()

int KoSvgTextShape::nextIndex ( int pos)

nextIndex Return the first cursor position with a higher string index.

Parameters
posthe cursor position.
Returns
the first pos with a higher cluster or same cluster and higher offset.

Definition at line 313 of file KoSvgTextShape.cpp.

314{
315 if (d->cursorPos.isEmpty()) {
316 return pos;
317 }
318 int currentIndex = d->cursorPos.at(pos).index;
319
320 for (int i = pos; i < d->cursorPos.size(); i++) {
321 if (d->cursorPos.at(i).index > currentIndex) {
322 return i;
323 }
324 }
325 return pos;
326}

References d.

◆ nextLine()

int KoSvgTextShape::nextLine ( int pos)

nextLine get a position on the next line for this position.

Parameters
pos– cursor position.
Returns
the pos on the next line;

Definition at line 371 of file KoSvgTextShape.cpp.

372{
373 if (pos < 0 || pos > d->cursorPos.size()-1 || d->result.isEmpty() || d->cursorPos.isEmpty()) {
374 return pos;
375 }
376
377 int nextLineStart = lineEnd(pos)+1;
378 int nextLineEnd = lineEnd(nextLineStart);
379 CursorPos cursorPos = d->cursorPos.at(pos);
380 if (!this->shapesInside().isEmpty()) {
381 LineBox nextLineBox;
382 for (int i = 0; i < d->lineBoxes.size(); ++i) {
383 for (int j = 0; j < d->lineBoxes.at(i).chunks.size(); ++j) {
384 if (d->lineBoxes.at(i).chunks.at(j).chunkIndices.contains(cursorPos.cluster)) {
385 nextLineBox = d->lineBoxes.at(qMin(i + 1, d->lineBoxes.size()-1));
386 }
387 }
388 }
389 if (nextLineBox.chunks.size()>0) {
390 int first = -1;
391 int last = -1;
392 Q_FOREACH(LineChunk chunk, nextLineBox.chunks) {
393 Q_FOREACH (int i, chunk.chunkIndices) {
394 if (d->result.at(i).addressable) {
395 if (first < 0) {
396 first = d->result.at(i).cursorInfo.graphemeIndices.first();
397 }
398 last = d->result.at(i).cursorInfo.graphemeIndices.last();
399 }
400 }
401 }
402 if (first > -1 && last > -1) {
403 nextLineStart = posForIndex(first);
404 nextLineEnd = posForIndex(last);
405 }
406 }
407 }
408
409
410 if (nextLineStart > d->cursorPos.size()-1) {
411 return d->cursorPos.size()-1;
412 }
413
414 CharacterResult res = d->result.at(cursorPos.cluster);
415 QPointF currentPoint = res.finalPosition;
416 currentPoint += res.cursorInfo.offsets.value(cursorPos.offset, res.advance);
417 int candidate = posForPoint(currentPoint, nextLineStart, nextLineEnd+1);
418 if (candidate < 0) {
419 return pos;
420 }
421
422 return candidate;
423}
int posForPoint(QPointF point, int start=-1, int end=-1, bool *overlaps=nullptr)
posForPoint Finds the closest cursor position for the given point in shape coordinates.
int lineEnd(int pos)
lineEnd return the 'line end' for this pos. This uses anchored chunks, so each absolute x,...
QPointF finalPosition
the final position, taking into account both CSS and SVG positioning considerations.
QVector< LineChunk > chunks
QVector< int > chunkIndices
charResult indices that belong to this chunk.

References CharacterResult::advance, LineChunk::chunkIndices, LineBox::chunks, CharacterResult::cursorInfo, cursorPos, d, CharacterResult::finalPosition, lineEnd(), CursorInfo::offsets, posForIndex(), posForPoint(), and shapesInside.

◆ nextPos()

int KoSvgTextShape::nextPos ( int pos,
bool visual )
private

nextPos get the next position.

Parameters
pos– cursor position.
Returns
the next pos;

Definition at line 343 of file KoSvgTextShape.cpp.

344{
345 if (d->cursorPos.isEmpty()) {
346 return -1;
347 }
348
349 if(visual) {
350 int visualIndex = d->logicalToVisualCursorPos.value(pos);
351 return d->logicalToVisualCursorPos.key(qMin(visualIndex + 1, d->cursorPos.size() - 1), d->cursorPos.size() - 1);
352 }
353
354 return qMin(pos + 1, d->cursorPos.size() - 1);
355}

References d.

◆ notifyCursorPosChanged()

void KoSvgTextShape::notifyCursorPosChanged ( int pos,
int anchor )

Notify that the cursor position has changed.

Definition at line 1233 of file KoSvgTextShape.cpp.

1234{
1235 if (d->isLoading) {
1236 return;
1237 }
1238 Q_FOREACH (KoShape::ShapeChangeListener *listener, listeners()) {
1239 TextCursorChangeListener *cursorListener = dynamic_cast<TextCursorChangeListener*>(listener);
1240 if (cursorListener) {
1241 cursorListener->notifyCursorPosChanged(pos, anchor);
1242 }
1243 }
1244}
QList< KoShape::ShapeChangeListener * > listeners
Definition KoShape_p.h:84
KoShapeAnchor * anchor() const

References KoShape::anchor(), d, KoShape::Private::listeners, and KoSvgTextShape::TextCursorChangeListener::notifyCursorPosChanged().

◆ notifyMarkupChanged()

void KoSvgTextShape::notifyMarkupChanged ( )

Notify that the markup has changed.

Definition at line 1246 of file KoSvgTextShape.cpp.

1247{
1248 if (d->isLoading) {
1249 return;
1250 }
1251 Q_FOREACH (KoShape::ShapeChangeListener *listener, listeners()) {
1252 TextCursorChangeListener *cursorListener = dynamic_cast<TextCursorChangeListener*>(listener);
1253 if (cursorListener) {
1254 cursorListener->notifyMarkupChanged();
1255 }
1256 }
1257}

References d, KoShape::Private::listeners, and KoSvgTextShape::TextCursorChangeListener::notifyMarkupChanged().

◆ numChars()

static int KoSvgTextShape::numChars ( KisForest< KoSvgTextContentElement >::child_iterator parent,
bool withControls = false,
KoSvgTextProperties resolvedProps = KoSvgTextProperties::defaultProperties() )
inlinestatic

Get the number of characters for the whole subtree of this node.

Definition at line 597 of file KoSvgTextShape_p.h.

597 {
598 KoSvgTextProperties props = parent->properties;
599 props.inheritFrom(resolvedProps, true);
600 int count = parent->numChars(withControls, props);
602 count += numChars(it, withControls, props);
603 }
604 return count;
605 }
static int numChars(KisForest< KoSvgTextContentElement >::child_iterator parent, bool withControls=false, KoSvgTextProperties resolvedProps=KoSvgTextProperties::defaultProperties())
Get the number of characters for the whole subtree of this node.

References KisForestDetail::childBegin(), KisForestDetail::childEnd(), and KoSvgTextProperties::inheritFrom().

◆ outline()

QPainterPath KoSvgTextShape::outline ( ) const
overridevirtual

returns the outline of the shape in the form of a path. The outline returned will always be relative to the position() of the shape, so moving the shape will not alter the result. The outline is used to draw the stroke on, for example.

Returns
the outline of the shape in the form of a path.

Reimplemented from KoShape.

Definition at line 1598 of file KoSvgTextShape.cpp.

1598 {
1599 QPainterPath result;
1600 for (auto it = d->textData.depthFirstTailBegin(); it != d->textData.depthFirstTailEnd(); it++) {
1601 result.addPath(it->associatedOutline);
1602 for (int i = 0; i < it->textDecorations.values().size(); ++i) {
1603 result.addPath(it->textDecorations.values().at(i));
1604 }
1605
1606 }
1607 return result;
1608}

References d, and result.

◆ outlineRect()

QRectF KoSvgTextShape::outlineRect ( ) const
overridevirtual

returns the outline of the shape in the form of a rect. The outlineRect returned will always be relative to the position() of the shape, so moving the shape will not alter the result. The outline is used to calculate the boundingRect.

Returns
the outline of the shape in the form of a rect.

Reimplemented from KoShape.

Definition at line 1609 of file KoSvgTextShape.cpp.

1610{
1611 return outline().boundingRect();
1612}
QPainterPath outline() const override

References outline().

◆ paint()

void KoSvgTextShape::paint ( QPainter & painter) const
overridevirtual

Paint the shape fill The class extending this one is responsible for painting itself. painter is expected to be preconfigured to work in "document" pixels.

Parameters
painterused for painting the shape

Implements KoShape.

Definition at line 1534 of file KoSvgTextShape.cpp.

1535{
1536 painter.save();
1538 if (textRendering == KoSvgText::RenderingOptimizeSpeed || !painter.testRenderHint(QPainter::Antialiasing)) {
1539 // also apply antialiasing only if antialiasing is active on provided target QPainter
1540 painter.setRenderHint(QPainter::Antialiasing, false);
1541 painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
1542 } else {
1543 painter.setRenderHint(QPainter::Antialiasing, true);
1544 painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
1545 }
1546
1547 QPainterPath chunk;
1548 int currentIndex = 0;
1549 if (!d->result.isEmpty()) {
1550 QPainterPath rootBounds;
1551 rootBounds.addRect(this->outline().boundingRect());
1552 d->paintTextDecoration(painter, rootBounds, this, KoSvgText::DecorationUnderline, textRendering);
1553 d->paintTextDecoration(painter, rootBounds, this, KoSvgText::DecorationOverline, textRendering);
1554 d->paintPaths(painter, rootBounds, this, d->result, textRendering, chunk, currentIndex);
1555 d->paintTextDecoration(painter, rootBounds, this, KoSvgText::DecorationLineThrough, textRendering);
1556 }
1557#if 0 // Debug
1558 Q_FOREACH (KoShape *child, this->shapes()) {
1559 const KoSvgTextChunkShape *textPathChunk = dynamic_cast<const KoSvgTextChunkShape *>(child);
1560 if (textPathChunk) {
1561 painter.save();
1562 painter.setPen(Qt::magenta);
1563 painter.setOpacity(0.5);
1564 if (textPathChunk->layoutInterface()->textPath()) {
1565 QPainterPath p = textPathChunk->layoutInterface()->textPath()->outline();
1566 p = textPathChunk->layoutInterface()->textPath()->transformation().map(p);
1567 painter.strokePath(p, QPen(Qt::green));
1568 painter.drawPoint(p.pointAtPercent(0));
1569 painter.drawPoint(p.pointAtPercent(p.percentAtLength(p.length() * 0.5)));
1570 painter.drawPoint(p.pointAtPercent(1.0));
1571 }
1572 painter.restore();
1573 }
1574 }
1575#endif
1576#if 0 // Debug
1577 Q_FOREACH (KoShape *shapeInside, d->shapesInside) {
1578 QPainterPath p = shapeInside->outline();
1579 p = shapeInside->transformation().map(p);
1580 painter.strokePath(p, QPen(Qt::green));
1581 }
1582 Q_FOREACH (KoShape *shapeInside, d->shapesSubtract) {
1583 QPainterPath p = shapeInside->outline();
1584 p = shapeInside->transformation().map(p);
1585 painter.strokePath(p, QPen(Qt::red));
1586 }
1587#endif
1588
1589 painter.restore();
1590}
virtual QPainterPath outline() const
Definition KoShape.cpp:630
QTransform transformation() const
Returns the shapes local transformation matrix.
Definition KoShape.cpp:424
QRectF boundingRect() const override
Get the bounding box of the shape.
@ DecorationOverline
Definition KoSvgText.h:260
@ DecorationLineThrough
Definition KoSvgText.h:261
@ DecorationUnderline
Definition KoSvgText.h:259
@ RenderingOptimizeSpeed
Definition KoSvgText.h:316

References boundingRect(), d, KoSvgText::DecorationLineThrough, KoSvgText::DecorationOverline, KoSvgText::DecorationUnderline, KoShape::outline(), outline(), p, KoSvgText::RenderingOptimizeSpeed, textProperties(), KoSvgTextProperties::TextRenderingId, and KoShape::transformation().

◆ paintDebug() [1/2]

void KoSvgTextShape::paintDebug ( QPainter & painter,
const QVector< CharacterResult > & result,
int & currentIndex )

◆ paintDebug() [2/2]

void KoSvgTextShape::paintDebug ( QPainter & painter,
DebugElements elements ) const

Definition at line 1648 of file KoSvgTextShape.cpp.

1649{
1650 if (elements & DebugElement::CharBbox) {
1651 int currentIndex = 0;
1652 if (!d->result.isEmpty()) {
1653 QPainterPath rootBounds;
1654 rootBounds.addRect(this->outline().boundingRect());
1655 d->paintDebug(painter, d->result, currentIndex);
1656 }
1657 }
1658
1659 if (elements & DebugElement::LineBox) {
1660 Q_FOREACH (LineBox lineBox, d->lineBoxes) {
1661 Q_FOREACH (const LineChunk &chunk, lineBox.chunks) {
1662 QPen pen;
1663 pen.setCosmetic(true);
1664 pen.setWidth(2);
1665 painter.setBrush(QBrush(Qt::transparent));
1666 pen.setColor(QColor(0, 128, 255, 128));
1667 painter.setPen(pen);
1668 painter.drawLine(chunk.length);
1669 pen.setColor(QColor(255, 128, 0, 128));
1670 painter.setPen(pen);
1671 painter.drawRect(chunk.boundingBox);
1672
1673 pen.setColor(QColor(255, 0, 0, 128));
1674 pen.setStyle(Qt::DashDotDotLine);
1675 painter.setPen(pen);
1676 painter.drawLine(chunk.length.translated(lineBox.baselineTop));
1677 pen.setColor(QColor(0, 128, 0, 128));
1678 pen.setStyle(Qt::DashDotLine);
1679 painter.setPen(pen);
1680 painter.drawLine(chunk.length.translated(lineBox.baselineBottom));
1681 }
1682 }
1683 }
1684}
QPointF baselineTop
Used to identify the top of the line for baseline-alignment.
QPointF baselineBottom
Used to identify the bottom of the line for baseline-alignment.
QLineF length
Used to measure how long the current line is allowed to be.

References LineBox::baselineBottom, LineBox::baselineTop, LineChunk::boundingBox, boundingRect(), CharBbox, LineBox::chunks, d, LineChunk::length, LineBox, and outline().

◆ paintOrder()

QVector< KoShape::PaintOrder > KoSvgTextShape::paintOrder ( ) const
overridevirtual

paintOrder

Returns
vector of paint orders, will always be 3 big and contain a fill, stroke and marker entry.

Reimplemented from KoShape.

Definition at line 1186 of file KoSvgTextShape.cpp.

1187{
1188 KoSvgTextProperties props = KisForestDetail::size(d->textData)? d->textData.childBegin()->properties: KoSvgTextProperties();
1191 }
1192 return KoShape::paintOrder();
1193}
virtual QVector< PaintOrder > paintOrder() const
paintOrder
Definition KoShape.cpp:773

References d, KoSvgTextProperties::hasProperty(), KoShape::paintOrder(), KoSvgTextProperties::PaintOrder, KoSvgTextProperties::properties(), KoSvgTextProperties::property(), and KisForestDetail::size().

◆ paintPaths()

void KoSvgTextShape::paintPaths ( QPainter & painter,
const QPainterPath & outlineRect,
const KoShape * rootShape,
const QVector< CharacterResult > & result,
const KoSvgText::TextRendering rendering,
QPainterPath & chunk,
int & currentIndex )

◆ paintStroke()

void KoSvgTextShape::paintStroke ( QPainter & painter) const
overridevirtual

paintStroke paints the shape's stroked outline

Parameters
painterused for painting the shape
See also
applyConversion()

Reimplemented from KoShape.

Definition at line 1592 of file KoSvgTextShape.cpp.

1593{
1594 Q_UNUSED(painter);
1595 // do nothing! everything is painted in paint()
1596}

◆ paintTextDecoration()

void KoSvgTextShape::paintTextDecoration ( QPainter & painter,
const QPainterPath & outlineRect,
const KoShape * rootShape,
const KoSvgText::TextDecoration type,
const KoSvgText::TextRendering rendering )

◆ plainText()

QString KoSvgTextShape::plainText ( )

plainText plain text of all text inside this text shape, without the bidi controls or any transforms.

Returns
a string of plain text.

◆ posDown()

int KoSvgTextShape::posDown ( int pos,
bool visual = false )

return position below.

Definition at line 232 of file KoSvgTextShape.cpp.

233{
236 if (mode == KoSvgText::VerticalRL || mode == KoSvgText::VerticalLR) {
237 if (direction == KoSvgText::DirectionRightToLeft) {
238 return previousPos(pos, visual);
239 } else {
240 return nextPos(pos, visual);
241 }
242 } else {
243 return nextLine(pos);
244 }
245}
@ DirectionId
KoSvgText::Direction.
int nextLine(int pos)
nextLine get a position on the next line for this position.
int nextPos(int pos, bool visual)
nextPos get the next position.
int previousPos(int pos, bool visual)
previousPos get the previous position.
Direction
Base direction used by Bidi algorithm.
Definition KoSvgText.h:48
@ DirectionRightToLeft
Definition KoSvgText.h:50

References KoSvgTextProperties::DirectionId, KoSvgText::DirectionRightToLeft, nextLine(), nextPos(), previousPos(), textProperties(), KoSvgText::VerticalLR, KoSvgText::VerticalRL, and writingMode().

◆ posForIndex()

int KoSvgTextShape::posForIndex ( int index,
bool firstIndex = false,
bool skipSynthetic = false ) const

posForIndex Get the cursor position for a given index in a string.

Parameters
index– index in the string.
firstIndex– whether to return for the first instance of the index.
skipSynthetic– whether to skip over synthetic cursorPositions.
Returns
the cursor – position for an index.

Definition at line 773 of file KoSvgTextShape.cpp.

774{
775 int pos = -1;
776 if (d->cursorPos.isEmpty() || index < 0) {
777 return pos;
778 }
779 for (int i = 0; i< d->cursorPos.size(); i++) {
780 if (skipSynthetic && d->cursorPos.at(i).synthetic) {
781 continue;
782 }
783 if (d->cursorPos.at(i).index <= index) {
784 pos = i;
785 if (d->cursorPos.at(i).index == index && firstIndex) {
786 break;
787 }
788 } else if (d->cursorPos.at(i).index > index) {
789 break;
790 }
791 }
792
793 return pos;
794}

References d.

◆ posForPoint()

int KoSvgTextShape::posForPoint ( QPointF point,
int start = -1,
int end = -1,
bool * overlaps = nullptr )

posForPoint Finds the closest cursor position for the given point in shape coordinates.

Parameters
point
start– optional start position;
end– optional end position;
overlaps– optional bool that is set if the point overlaps any glyph box.
Returns
the closest cursor position.

Definition at line 702 of file KoSvgTextShape.cpp.

703{
704 int a = 0;
705 int b = d->cursorPos.size();
706 if (start >= 0 && end >= 0) {
707 a = qMax(start, a);
708 b = qMin(end, b);
709 }
710 double closest = std::numeric_limits<double>::max();
711 int candidate = 0;
712 for (int i = a; i < b; i++) {
713 CursorPos pos = d->cursorPos.at(i);
714 CharacterResult res = d->result.at(pos.cluster);
715 QPointF cursorStart = res.finalPosition;
716 cursorStart += res.cursorInfo.offsets.value(pos.offset, res.advance);
717 double distance = kisDistance(cursorStart, point);
718 if (distance < closest) {
719 candidate = i;
720 closest = distance;
721 if (overlaps) {
722 *overlaps = res.finalTransform().map(res.layoutBox()).containsPoint(point, Qt::WindingFill);
723 }
724 }
725 }
726 return candidate;
727}
qreal distance(const QPointF &p1, const QPointF &p2)
qreal kisDistance(const QPointF &pt1, const QPointF &pt2)
Definition kis_global.h:190
QRectF layoutBox() const
layoutBox
int cluster
Which character result this position belongs in.
int offset
Which offset this position belongs with.

References CharacterResult::advance, CursorPos::cluster, CharacterResult::cursorInfo, d, distance(), CharacterResult::finalPosition, CharacterResult::finalTransform(), kisDistance(), CharacterResult::layoutBox(), CursorPos::offset, and CursorInfo::offsets.

◆ posForPointLineSensitive()

int KoSvgTextShape::posForPointLineSensitive ( QPointF point)

posForPointLineSensitive When clicking on an empty space in a wrapped text, it is preferable to have the caret be at the end of the line visually associated with that empty space than the positions above or below that might be closer.

Because SVG has several situations where there's no real lines, we first test for the closest cursorpos and also whether there's an actual overlap with a glyph. If there's no such overlap, we test against whether there's an anchored chunk in the inline direction, and if so search the line resulting from that. If not, we return the closest pos.

Parameters
pointthe point in shape coordinates.
Returns
the closest pos, taking into account any line starts or ends.

Definition at line 729 of file KoSvgTextShape.cpp.

730{
731 bool overlaps = false;
732 int initialPos = posForPoint(point, -1, -1, &overlaps);
733
734 if (overlaps) {
735 return initialPos;
736 }
737
739
740 int candidateLineStart = 0;
741 double closest = std::numeric_limits<double>::max();
742 for (int i = 0; i < d->cursorPos.size(); i++) {
743 CursorPos pos = d->cursorPos.at(i);
744 CharacterResult res = d->result.at(pos.cluster);
745 if (res.anchored_chunk) {
746 QLineF caret = res.cursorInfo.caret;
747 caret.translate(res.finalPosition);
748 QPointF cursorStart = res.finalPosition;
749 cursorStart += res.cursorInfo.offsets.value(pos.offset, res.advance);
750 double distance = kisDistance(cursorStart, point);
751 if (mode == KoSvgText::HorizontalTB) {
752 if (caret.p1().y() > point.y() && caret.p2().y() <= point.y() && closest > distance) {
753 candidateLineStart = i;
754 closest = distance;
755 }
756 } else {
757 if (caret.p2().x() > point.x() && caret.p1().x() <= point.x() && closest > distance) {
758 candidateLineStart = i;
759 closest = distance;
760 }
761 }
762 }
763 }
764
765 if (candidateLineStart > -1) {
766 int end = lineEnd(candidateLineStart);
767 initialPos = posForPoint(point, candidateLineStart, qMin(end + 1, d->cursorPos.size()));
768 }
769
770 return initialPos;
771}
bool anchored_chunk
whether this is the start of a new chunk.

References CharacterResult::advance, CharacterResult::anchored_chunk, CursorInfo::caret, CursorPos::cluster, CharacterResult::cursorInfo, d, distance(), CharacterResult::finalPosition, KoSvgText::HorizontalTB, kisDistance(), lineEnd(), CursorPos::offset, CursorInfo::offsets, posForPoint(), and writingMode().

◆ posLeft()

int KoSvgTextShape::posLeft ( int pos,
bool visual = false )

return position to the left; visual indicates whether to use logical ('previous') or visual left (depending on direction).

Definition at line 182 of file KoSvgTextShape.cpp.

183{
186 if (mode == KoSvgText::VerticalRL) {
187 return nextLine(pos);
188 } else if (mode == KoSvgText::VerticalLR) {
189 return previousLine(pos);
190 } else {
191 if (direction == KoSvgText::DirectionRightToLeft) {
192 return nextPos(pos, visual);
193 } else {
194 return previousPos(pos, visual);
195 }
196 }
197}
int previousLine(int pos)
previousLine get a position on the previous line for this position.

References KoSvgTextProperties::DirectionId, KoSvgText::DirectionRightToLeft, nextLine(), nextPos(), previousLine(), previousPos(), textProperties(), KoSvgText::VerticalLR, KoSvgText::VerticalRL, and writingMode().

◆ posRight()

int KoSvgTextShape::posRight ( int pos,
bool visual = false )

return position to the right; visual indicates whether to use logical ('next') or visual right (depending on direction).

Definition at line 199 of file KoSvgTextShape.cpp.

200{
203
204 if (mode == KoSvgText::VerticalRL) {
205 return previousLine(pos);
206 } else if (mode == KoSvgText::VerticalLR) {
207 return nextLine(pos);
208 } else {
209 if (direction == KoSvgText::DirectionRightToLeft) {
210 return previousPos(pos, visual);
211 } else {
212 return nextPos(pos, visual);
213 }
214 }
215}

References KoSvgTextProperties::DirectionId, KoSvgText::DirectionRightToLeft, nextLine(), nextPos(), previousLine(), previousPos(), textProperties(), KoSvgText::VerticalLR, KoSvgText::VerticalRL, and writingMode().

◆ posUp()

int KoSvgTextShape::posUp ( int pos,
bool visual = false )

return position above.

Definition at line 217 of file KoSvgTextShape.cpp.

218{
221 if (mode == KoSvgText::VerticalRL || mode == KoSvgText::VerticalLR) {
222 if (direction == KoSvgText::DirectionRightToLeft) {
223 return nextPos(pos, visual);
224 } else {
225 return previousPos(pos, visual);
226 }
227 } else {
228 return previousLine(pos);
229 }
230}

References KoSvgTextProperties::DirectionId, KoSvgText::DirectionRightToLeft, nextPos(), previousLine(), previousPos(), textProperties(), KoSvgText::VerticalLR, KoSvgText::VerticalRL, and writingMode().

◆ previousIndex()

int KoSvgTextShape::previousIndex ( int pos)

previousIndex Return the first pos which has a lower string index.

Parameters
posthe cursor position.
Returns
the first cursor position with a lower index.

Definition at line 328 of file KoSvgTextShape.cpp.

329{
330 if (d->cursorPos.isEmpty()) {
331 return pos;
332 }
333 int currentIndex = d->cursorPos.at(pos).index;
334
335 for (int i = pos; i >= 0; i--) {
336 if (d->cursorPos.at(i).index < currentIndex) {
337 return i;
338 }
339 }
340 return pos;
341}

References d.

◆ previousLine()

int KoSvgTextShape::previousLine ( int pos)

previousLine get a position on the previous line for this position.

Parameters
pos– cursor position.
Returns
the pos on the previous line;

Definition at line 425 of file KoSvgTextShape.cpp.

426{
427 if (pos < 0 || pos > d->cursorPos.size()-1 || d->result.isEmpty() || d->cursorPos.isEmpty()) {
428 return pos;
429 }
430 int currentLineStart = lineStart(pos);
431 if (currentLineStart - 1 < 0) {
432 return 0;
433 }
434 int previousLineStart = lineStart(currentLineStart-1);
435
436 CursorPos cursorPos = d->cursorPos.at(pos);
437 if (!this->shapesInside().isEmpty()) {
438 LineBox previousLineBox;
439 for (int i = 0; i < d->lineBoxes.size(); ++i) {
440 for (int j = 0; j < d->lineBoxes.at(i).chunks.size(); ++j) {
441 if (d->lineBoxes.at(i).chunks.at(j).chunkIndices.contains(cursorPos.cluster)) {
442 previousLineBox = d->lineBoxes.at(qMax(i - 1, 0));
443 }
444 }
445 }
446 if (previousLineBox.chunks.size()>0) {
447 int first = -1;
448 int last = -1;
449 Q_FOREACH(LineChunk chunk, previousLineBox.chunks) {
450 Q_FOREACH (int i, chunk.chunkIndices) {
451 if (d->result.at(i).addressable) {
452 if (first < 0) {
453 first = d->result.at(i).cursorInfo.graphemeIndices.first();
454 }
455 last = d->result.at(i).cursorInfo.graphemeIndices.last();
456 }
457 }
458 }
459 if (first > -1 && last > -1) {
460 previousLineStart = posForIndex(first);
461 currentLineStart = posForIndex(last);
462 }
463 }
464 }
465
466 CharacterResult res = d->result.at(cursorPos.cluster);
467 QPointF currentPoint = res.finalPosition;
468 currentPoint += res.cursorInfo.offsets.value(cursorPos.offset, res.advance);
469 int candidate = posForPoint(currentPoint, previousLineStart, currentLineStart);
470 if (candidate < 0) {
471 return pos;
472 }
473
474 return candidate;
475}
int lineStart(int pos)
lineStart return the 'line start' for this pos. This uses anchored chunks, so each absolute x,...

References CharacterResult::advance, LineChunk::chunkIndices, LineBox::chunks, CharacterResult::cursorInfo, cursorPos, d, CharacterResult::finalPosition, lineStart(), CursorInfo::offsets, posForIndex(), posForPoint(), and shapesInside.

◆ previousPos()

int KoSvgTextShape::previousPos ( int pos,
bool visual )
private

previousPos get the previous position.

Parameters
pos– cursor position.
Returns
the previous pos;

Definition at line 357 of file KoSvgTextShape.cpp.

358{
359 if (d->cursorPos.isEmpty()) {
360 return -1;
361 }
362
363 if(visual) {
364 int visualIndex = d->logicalToVisualCursorPos.value(pos);
365 return d->logicalToVisualCursorPos.key(qMax(visualIndex - 1, 0), 0);
366 }
367
368 return qMax(pos - 1, 0);
369}

References d.

◆ Private() [1/2]

◆ Private() [2/2]

KoSvgTextShape::Private ( const Private & rhs)
inline

Definition at line 441 of file KoSvgTextShape_p.h.

442 : textData(rhs.textData) {
443 Q_FOREACH (KoShape *shape, rhs.shapesInside) {
444 KoShape *clonedShape = shape->cloneShape();
445 KIS_ASSERT_RECOVER(clonedShape) { continue; }
446
447 shapesInside.append(clonedShape);
448 }
449 Q_FOREACH (KoShape *shape, rhs.shapesSubtract) {
450 KoShape *clonedShape = shape->cloneShape();
451 KIS_ASSERT_RECOVER(clonedShape) { continue; }
452
453 shapesSubtract.append(clonedShape);
454 }
455 yRes = rhs.yRes;
456 xRes = rhs.xRes;
457 result = rhs.result;
458 lineBoxes = rhs.lineBoxes;
459
460 cursorPos = rhs.cursorPos;
461 logicalToVisualCursorPos = rhs.logicalToVisualCursorPos;
462 plainText = rhs.plainText;
463 isBidi = rhs.isBidi;
464 initialTextPosition = rhs.initialTextPosition;
465
466 isLoading = rhs.isLoading;
467 disableFontMatching = rhs.disableFontMatching;
468 }
virtual KoShape * cloneShape() const
creates a deep copy of the shape or shape's subtree
Definition KoShape.cpp:200
KisForest< KoSvgTextContentElement > textData
QPointF initialTextPosition
QMap< int, int > logicalToVisualCursorPos
bool isLoading
Turned on when loading in text data, blocks updates to shape listeners.
QVector< LineBox > lineBoxes
bool disableFontMatching
Turn off font matching, which should speed up relayout slightly.
#define KIS_ASSERT_RECOVER(cond)
Definition kis_assert.h:55

References KoShape::cloneShape(), and KIS_ASSERT_RECOVER.

◆ propertiesForPos()

KoSvgTextProperties KoSvgTextShape::propertiesForPos ( const int pos,
bool inherited = false ) const

Return the properties at a given position.

Definition at line 879 of file KoSvgTextShape.cpp.

880{
881 return propertiesForRange(pos, pos, inherited).value(0, KoSvgTextProperties());
882}
QList< KoSvgTextProperties > propertiesForRange(const int startPos, const int endPos, bool inherited=false) const
propertiesForRange get the properties for a range.

References propertiesForRange().

◆ propertiesForRange()

QList< KoSvgTextProperties > KoSvgTextShape::propertiesForRange ( const int startPos,
const int endPos,
bool inherited = false ) const

propertiesForRange get the properties for a range.

Parameters
startPos– range start.
endPos– range end.
Returns
list of properties.

Sometimes this gets called when xml data is uploaded into the shape, at which point the tree is empty.

Definition at line 895 of file KoSvgTextShape.cpp.

896{
898
900 if (d->isLoading) return props;
901
902 if (((startPos < 0 || startPos >= d->cursorPos.size()) && startPos == endPos) || d->cursorPos.isEmpty()) {
903 props = {KisForestDetail::size(d->textData)? d->textData.childBegin()->properties: KoSvgTextProperties()};
904 return props;
905 }
906 const int finalPos = d->cursorPos.size() - 1;
907 const int startIndex = d->cursorPos.at(qBound(0, startPos, finalPos)).index;
908 const int endIndex = d->cursorPos.at(qBound(0, endPos, finalPos)).index;
909 int sought = startIndex;
910 if (startIndex == endIndex) {
911 int currentIndex = 0;
912 auto it = d->findTextContentElementForIndex(d->textData, currentIndex, sought);
913 if (it != d->textData.depthFirstTailEnd()) {
914 if (inherited) {
915 props.append(inheritProperties(it));
916 } else {
917 props.append(it->properties);
918 }
919 } else {
920 currentIndex = 0;
921 it = d->findTextContentElementForIndex(d->textData, currentIndex, sought - 1);
922 if (it != d->textData.depthFirstTailEnd()) {
923 if (inherited) {
924 props.append(inheritProperties(it));
925 } else {
926 props.append(it->properties);
927 }
928 }
929 }
930 } else {
931 while(sought < endIndex) {
932 int currentIndex = 0;
933 auto it = d->findTextContentElementForIndex(d->textData, currentIndex, sought);
934 if (KisForestDetail::siblingCurrent(it) == d->textData.childBegin()) {
935 // If there's a selection and the search algorithm only returns the root, return empty.
936 // The root text properties should be retrieved explicitly (either by using -1 as pos, or by calling textProperties()).
937 props = {KoSvgTextProperties()};
938 return props;
939 } else if (it != d->textData.depthFirstTailEnd()) {
940 if (inherited) {
941 props.append(inheritProperties(it));
942 } else {
943 props.append(it->properties);
944 }
945 }
946 sought = currentIndex + it->numChars(false);
947 }
948 }
949
950 return props;
951}
KoSvgTextProperties inheritProperties(KisForest< KoSvgTextContentElement >::depth_first_tail_iterator it)

References d, inheritProperties(), KisForestDetail::siblingCurrent(), and KisForestDetail::size().

◆ Q_DECLARE_FLAGS()

KoSvgTextShape::Q_DECLARE_FLAGS ( DebugElements ,
DebugElement  )

◆ relayout() [1/2]

void KoSvgTextShape::relayout ( )

◆ relayout() [2/2]

void KoSvgTextShape::relayout ( ) const

Create a new text layout for the current content of the text shape chunks tree. The user should always call relayout() after every change in the text shapes hierarchy.

Definition at line 1760 of file KoSvgTextShape.cpp.

1761{
1762 d->relayout();
1763}

References d.

◆ relayoutIsBlocked()

bool KoSvgTextShape::relayoutIsBlocked ( ) const

relayoutIsBlocked

Returns
whether automatic relayout is blocked, as are updates to shape listeners.

Definition at line 1519 of file KoSvgTextShape.cpp.

1520{
1521 return d->isLoading;
1522}

References d.

◆ removeText()

bool KoSvgTextShape::removeText ( int & index,
int & length )

removeText Where insert text explicitly uses a cursorposition, remove text uses a string index. It will modify these values so that...

  • Whole code points are deleted at any time, avoiding no dangling surrogates.
  • Graphemes don't end with Zero-width-joiners, as that can lead to the grapheme merging with the next.
  • Variation selectors are deleted along their base.
  • regional sequences are deleted in pairs.
    Parameters
    index- index (not cursorpos!) of the start position.
    length- total length of text to remove.
    Returns
    whether it was successful.

Definition at line 840 of file KoSvgTextShape.cpp.

841{
842 bool success = false;
843 if (index < -1) {
844 return success;
845 }
846 int currentLength = length;
847 int endLength = 0;
848 while (currentLength > 0) {
849 int currentIndex = 0;
850
851 auto it = d->findTextContentElementForIndex(d->textData, currentIndex, index, true);
852 if (it != d->textData.depthFirstTailEnd()) {
853 int offset = index > currentIndex? index - currentIndex: 0;
854 int size = it->numChars(false);
855 it->removeText(offset, currentLength);
856 int diff = size - it->numChars(false);
857 currentLength -= diff;
858 endLength += diff;
859
860 if (index >= currentIndex) {
861 index = currentIndex + offset;
862 }
863
864 d->removeTransforms(d->textData, index, endLength);
865
866 success = true;
867 } else {
868 currentLength = -1;
869 }
870 }
871 if (success) {
872 length = endLength;
875 }
876 return success;
877}

References KoShape::ContentChanged, d, length(), KoShape::notifyChanged(), KoShape::shapeChangedPriv(), and KoShape::size().

◆ removeTransforms()

static void KoSvgTextShape::removeTransforms ( KisForest< KoSvgTextContentElement > & tree,
const int start,
const int length )
inlinestatic

removeTransforms Remove all local SVG character transforms in a certain range. Local transforms are influenced by whitespace collapse and whether they are set to unicode codepoints, and they also accumulate from parent to child. This function removes all local transforms in a certain section.

Parameters
tree– tree to remove transforms from.
start– start at which to remove transforms.
length– end to remove from.

Definition at line 747 of file KoSvgTextShape_p.h.

747 {
748 QString all;
749 QVector<bool> collapsedCharacters = collapsedWhiteSpacesForText(tree, all, true);
750
751 auto root = tree.childBegin();
752 removeTransformsImpl(root, 0, start, length, collapsedCharacters);
753 }
static int removeTransformsImpl(KisForest< KoSvgTextContentElement >::child_iterator currentTextElement, const int globalIndex, const int start, const int length, const QVector< bool > collapsedCharacters)
removeTransformsImpl recursive function that handles removing local transforms in a certain range....

References KisForestDetail::Forest< T >::childBegin(), and length().

◆ removeTransformsImpl()

static int KoSvgTextShape::removeTransformsImpl ( KisForest< KoSvgTextContentElement >::child_iterator currentTextElement,
const int globalIndex,
const int start,
const int length,
const QVector< bool > collapsedCharacters )
inlinestatic

removeTransformsImpl recursive function that handles removing local transforms in a certain range. Used by removeTransform.

Definition at line 760 of file KoSvgTextShape_p.h.

760 {
761 int currentLength = 0;
762 auto it = childBegin(currentTextElement);
763 if (it != childEnd(currentTextElement)) {
764 for (; it != childEnd(currentTextElement); it++) {
765 currentLength += removeTransformsImpl(it, globalIndex + currentLength, start, length, collapsedCharacters);
766 }
767 } else {
768 currentLength = currentTextElement->text.size();
769 }
770
771 if (!currentTextElement->localTransformations.isEmpty()) {
772 int transformOffset = 0;
773 int transformOffsetEnd = 0;
774
775 for (int i = globalIndex; i < globalIndex + currentLength; i++) {
776 if (i < start) {
777 transformOffset += collapsedCharacters.at(i)? 0: 1;
778 }
779 if (i < start + length) {
780 transformOffsetEnd += collapsedCharacters.at(i)? 0: 1;
781 } else {
782 break;
783 }
784 }
785 if (transformOffset < currentTextElement->localTransformations.size()) {
786 currentTextElement->localTransformations.remove(transformOffset, transformOffsetEnd-transformOffset);
787 }
788
789 }
790 return currentLength;
791 }

References length().

◆ resolveTransforms()

static void KoSvgTextShape::resolveTransforms ( KisForest< KoSvgTextContentElement >::child_iterator currentTextElement,
QString text,
QVector< CharacterResult > & result,
int & currentIndex,
bool isHorizontal,
bool wrapped,
bool textInPath,
QVector< KoSvgText::CharTransformation > & resolved,
QVector< bool > collapsedChars,
const KoSvgTextProperties resolvedProps,
bool withControls = true )
static

◆ saveHtml()

bool KoSvgTextShape::saveHtml ( HtmlSavingContext & context)

Definition at line 1357 of file KoSvgTextShape.cpp.

1358{
1359 bool success = true;
1361 for (auto it = d->textData.compositionBegin(); it != d->textData.compositionEnd(); it++) {
1362 if (it.state() == KisForestDetail::Enter) {
1363 QMap<QString, QString> shapeSpecificStyles;
1364
1365 if (it == d->textData.compositionBegin()) {
1366 context.shapeWriter().startElement("p", false);
1367 } else {
1368 context.shapeWriter().startElement("span", false);
1369 }
1370 KoSvgTextProperties ownProperties = it->properties.ownProperties(parentProps.last(),
1371 it == d->textData.compositionBegin());
1372 parentProps.append(ownProperties);
1373 QMap<QString, QString> attributes = ownProperties.convertToSvgTextAttributes();
1374 if (it == d->textData.compositionBegin())
1375 attributes.insert(ownProperties.convertParagraphProperties());
1376 bool addedFill = false;
1377 if (attributes.size() > 0) {
1378 QString styleString;
1379 for (auto it = attributes.constBegin(); it != attributes.constEnd(); ++it) {
1380 if (QString(it.key().toLatin1().data()).contains("text-anchor")) {
1381 QString val = it.value();
1382 if (it.value()=="middle") {
1383 val = "center";
1384 } else if (it.value()=="end") {
1385 val = "right";
1386 } else {
1387 val = "left";
1388 }
1389 styleString.append("text-align")
1390 .append(": ")
1391 .append(val)
1392 .append(";" );
1393 } else if (QString(it.key().toLatin1().data()).contains("fill")) {
1394 styleString.append("color")
1395 .append(": ")
1396 .append(it.value())
1397 .append(";" );
1398 addedFill = true;
1399 } else if (QString(it.key().toLatin1().data()).contains("font-size")) {
1400 QString val = it.value();
1401 styleString.append(it.key().toLatin1().data())
1402 .append(": ")
1403 .append(val)
1404 .append(";" );
1405 } else {
1406 styleString.append(it.key().toLatin1().data())
1407 .append(": ")
1408 .append(it.value())
1409 .append(";" );
1410 }
1411 }
1412 if (ownProperties.hasProperty(KoSvgTextProperties::FillId) && !addedFill) {
1413 KoColorBackground *b = dynamic_cast<KoColorBackground *>(it->properties.background().data());
1414 if (b) {
1415 styleString.append("color")
1416 .append(": ")
1417 .append(b->color().name())
1418 .append(";" );
1419 }
1420 }
1421 context.shapeWriter().addAttribute("style", styleString);
1422
1423 if (d->childCount(siblingCurrent(it)) == 0) {
1424 debugFlake << "saveHTML" << this << it->text;
1425 // After adding all the styling to the <p> element, add the text
1426 context.shapeWriter().addTextNode(it->text);
1427 }
1428 }
1429 } else {
1430 parentProps.pop_back();
1431 context.shapeWriter().endElement();
1432 }
1433 }
1434 return success;
1435}
#define debugFlake
Definition FlakeDebug.h:15
KoXmlWriter & shapeWriter()
Provides access to the shape writer.
QMap< QString, QString > convertToSvgTextAttributes() const
QMap< QString, QString > convertParagraphProperties() const
convertParagraphProperties some properties only apply to the root shape, so we write those separately...
void startElement(const char *tagName, bool indentInside=true)
void addTextNode(const QString &str)
void endElement()
void addAttribute(const char *attrName, const QString &value)
Definition KoXmlWriter.h:61

References KoXmlWriter::addAttribute(), KoXmlWriter::addTextNode(), KoSvgTextProperties::convertParagraphProperties(), KoSvgTextProperties::convertToSvgTextAttributes(), d, debugFlake, KoSvgTextProperties::defaultProperties(), KoXmlWriter::endElement(), KisForestDetail::Enter, KoSvgTextProperties::FillId, KoSvgTextProperties::hasProperty(), KoSvgTextProperties::properties(), HtmlSavingContext::shapeWriter(), and KoXmlWriter::startElement().

◆ saveSvg()

bool KoSvgTextShape::saveSvg ( SvgSavingContext & context)
overridevirtual

Saves SVG data.

Reimplemented from SvgShape.

Definition at line 1298 of file KoSvgTextShape.cpp.

1299{
1300 bool success = false;
1301 for (auto it = d->textData.compositionBegin(); it != d->textData.compositionEnd(); it++) {
1302 if (it.state() == KisForestDetail::Enter) {
1303 bool isTextPath = false;
1304 QMap<QString, QString> shapeSpecificStyles;
1305 if (it->textPath) {
1306 isTextPath = true;
1307 }
1308 if (it == d->textData.compositionBegin()) {
1309 context.shapeWriter().startElement("text", false);
1310
1311 if (!context.strippedTextMode()) {
1312 context.shapeWriter().addAttribute("id", context.getID(this));
1313
1314 // save the version to distinguish from the buggy Krita version
1315 // 2: Wrong font-size.
1316 // 3: Wrong font-size-adjust.
1317 context.shapeWriter().addAttribute("krita:textVersion", 3);
1318
1320 SvgStyleWriter::saveSvgStyle(this, context);
1321 } else {
1322 SvgStyleWriter::saveSvgFill(this->background(), false, this->outlineRect(), this->size(), this->absoluteTransformation(), context);
1323 SvgStyleWriter::saveSvgStroke(this->stroke(), context);
1325 inheritPaintOrder(), context, true);
1326 }
1327 shapeSpecificStyles = this->shapeTypeSpecificStyles(context);
1328 } else {
1329 if (isTextPath) {
1330 context.shapeWriter().startElement("textPath", false);
1331 } else {
1332 context.shapeWriter().startElement("tspan", false);
1333 }
1334 SvgStyleWriter::saveSvgBasicStyle(it->properties.property(KoSvgTextProperties::Visiblity, true).toBool(),
1335 it->properties.property(KoSvgTextProperties::Opacity, 0).toReal(),
1336 it->properties.property(KoSvgTextProperties::PaintOrder,
1337 QVariant::fromValue(paintOrder())
1339 !it->properties.hasProperty(KoSvgTextProperties::PaintOrder), context, true);
1340
1341 }
1342
1343 success = it->saveSvg(context,
1344 it == d->textData.compositionBegin(),
1345 d->childCount(siblingCurrent(it)) == 0,
1346 shapeSpecificStyles);
1347 } else {
1348 if (it == d->textData.compositionBegin()) {
1349 SvgStyleWriter::saveMetadata(this, context);
1350 }
1351 context.shapeWriter().endElement();
1352 }
1353 }
1354 return success;
1355}
float value(const T *src, size_t ch)
bool inheritPaintOrder() const
inheritPaintOrder
Definition KoShape.cpp:795
QSharedPointer< KoShapeBackground > background() const override
QVector< PaintOrder > paintOrder() const override
paintOrder
QMap< QString, QString > shapeTypeSpecificStyles(SvgSavingContext &context) const
QScopedPointer< KoXmlWriter > shapeWriter
QString getID(const KoShape *obj)
Returns the unique id for the given shape.
static void saveSvgFill(QSharedPointer< KoShapeBackground > background, const bool fillRuleEvenOdd, const QRectF outlineRect, const QSizeF size, const QTransform absoluteTransform, SvgSavingContext &context)
Saves fill style of specified shape.
static void saveSvgBasicStyle(const bool isVisible, const qreal transparency, const QVector< KoShape::PaintOrder > paintOrder, bool inheritPaintorder, SvgSavingContext &context, bool textShape=false)
Saves only stroke, fill and transparency of the shape.
static void saveSvgStyle(KoShape *shape, SvgSavingContext &context)
Saves the style of the specified shape.
static void saveMetadata(const KoShape *shape, SvgSavingContext &context)
static void saveSvgStroke(KoShapeStrokeModelSP, SvgSavingContext &context)
Saves stroke style of specified shape.
static void writeTransformAttributeLazy(const QString &name, const QTransform &transform, KoXmlWriter &shapeWriter)
Writes a transform as an attribute name iff the transform is not empty.
Definition SvgUtil.cpp:124

References KoShape::absoluteTransformation(), background(), d, KisForestDetail::Enter, SvgSavingContext::getID(), KoShape::inheritPaintOrder(), KoSvgTextProperties::Opacity, outlineRect(), KoSvgTextProperties::PaintOrder, paintOrder(), SvgStyleWriter::saveMetadata(), SvgStyleWriter::saveSvgBasicStyle(), SvgStyleWriter::saveSvgFill(), SvgStyleWriter::saveSvgStroke(), SvgStyleWriter::saveSvgStyle(), shapeTypeSpecificStyles(), SvgSavingContext::shapeWriter, KoShape::size(), SvgSavingContext::strippedTextMode, stroke(), KoShape::transformation(), value(), KoSvgTextProperties::Visiblity, and SvgUtil::writeTransformAttributeLazy().

◆ selectionBoxes()

QPainterPath KoSvgTextShape::selectionBoxes ( int pos,
int anchor )

selectionBoxes returns all selection boxes for a given range. Range will be normalized internally.

Parameters
pos– the main cursor pos.
anchor– the anchor from which the selection is calculated.
Returns
a winding-fill style QPainterPath will all boxes added as subpaths.

Definition at line 581 of file KoSvgTextShape.cpp.

582{
583 int start = qMin(pos, anchor);
584 int end = qMax(pos, anchor);
585 end = qMin(d->cursorPos.size()-1, end);
586
587 if (start == end || start < 0) {
588 return QPainterPath();
589 }
590
591 QPainterPath p;
592 p.setFillRule(Qt::WindingFill);
593 for (int i = start+1; i <= end; i++) {
594 CursorPos cursorPos = d->cursorPos.at(i);
595 CharacterResult res = d->result.at(cursorPos.cluster);
596 const QTransform tf = res.finalTransform();
597 QLineF first = res.cursorInfo.caret;
598 QLineF last = first;
599 if (res.cursorInfo.rtl) {
600 last.translate(res.cursorInfo.offsets.value(cursorPos.offset-1, res.advance));
601 first.translate(res.cursorInfo.offsets.value(cursorPos.offset, QPointF()));
602 } else {
603 first.translate(res.cursorInfo.offsets.value(cursorPos.offset-1, QPointF()));
604 last.translate(res.cursorInfo.offsets.value(cursorPos.offset, res.advance));
605 }
606 QPolygonF poly;
607 poly << first.p1() << first.p2() << last.p2() << last.p1() << first.p1();
608 p.addPolygon(tf.map(poly));
609 }
610
611 return p;
612}

References CharacterResult::advance, KoShape::anchor(), CursorInfo::caret, CharacterResult::cursorInfo, cursorPos, d, CharacterResult::finalTransform(), CursorInfo::offsets, p, and CursorInfo::rtl.

◆ setBackground()

void KoSvgTextShape::setBackground ( QSharedPointer< KoShapeBackground > background)
overridevirtual

Set the background of the shape. A shape background can be a plain color, a gradient, a pattern, be fully transparent or have a complex fill. Setting such a background will allow the shape to be filled and will be able to tell if it is transparent or not.

If the shape inherited the background from its parent, its stops inheriting it, that is inheritBackground property resets to false.

Parameters
backgroundthe new shape background.

Reimplemented from KoShape.

Definition at line 1157 of file KoSvgTextShape.cpp.

1158{
1159 if (KisForestDetail::size(d->textData) == 0) {
1160 d->textData.insert(d->textData.childBegin(), KoSvgTextContentElement());
1161 }
1162 d->textData.childBegin()->properties.setProperty(KoSvgTextProperties::FillId,
1163 QVariant::fromValue(KoSvgText::BackgroundProperty(background)));
1164
1166 notifyChanged();
1167}

References background(), KoShape::BackgroundChanged, d, KoSvgTextProperties::FillId, KoShape::notifyChanged(), KoShape::shapeChangedPriv(), and KisForestDetail::size().

◆ setCharacterTransformsFromLayout()

void KoSvgTextShape::setCharacterTransformsFromLayout ( )

setCharacterTransformsFromLayout Converts the text to a prepositioned SVG 1.1 text. This changes the textType();

Definition at line 1283 of file KoSvgTextShape.cpp.

1284{
1285 if (d->result.isEmpty()) return;
1286 d->setTransformsFromLayout(d->textData, d->result);
1287 d->cleanUp(d->textData);
1288 //d->applyWhiteSpace(d->textData, true);
1289 KoSvgTextProperties props = this->propertiesForPos(-1);
1293
1294 setPropertiesAtPos(-1, props);
1295}

References d, KoSvgTextProperties::InlineSizeId, propertiesForPos(), KoSvgTextProperties::removeProperty(), setPropertiesAtPos(), KoSvgTextProperties::TextCollapseId, and KoSvgTextProperties::TextWrapId.

◆ setFontMatchingDisabled()

void KoSvgTextShape::setFontMatchingDisabled ( const bool disable)

setDisableFontMatching

Parameters
disablefont matching when retrieving fonts for text layout (if possible). This speeds up text layout, but should only be done if there's only one font necessary and it can be found with the KoFFWWSconverter.

Definition at line 1524 of file KoSvgTextShape.cpp.

1525{
1526 d->disableFontMatching = disable;
1527}

References d.

◆ setMemento() [1/2]

void KoSvgTextShape::setMemento ( const KoSvgTextShapeMementoSP memento)

Set the text data and layout info, reset listening cursors to 0.

Definition at line 1474 of file KoSvgTextShape.cpp.

1475{
1476 setMementoImpl(memento);
1479}
void notifyCursorPosChanged(int pos, int anchor)
Notify that the cursor position has changed.
void notifyMarkupChanged()
Notify that the markup has changed.
void setMementoImpl(const KoSvgTextShapeMementoSP memento)

References notifyCursorPosChanged(), notifyMarkupChanged(), and setMementoImpl().

◆ setMemento() [2/2]

void KoSvgTextShape::setMemento ( const KoSvgTextShapeMementoSP memento,
int pos,
int anchor )

Set the text data, layout info and also adjust any listening cursors.

Definition at line 1481 of file KoSvgTextShape.cpp.

1482{
1483 setMementoImpl(memento);
1486}

References KoShape::anchor(), notifyCursorPosChanged(), notifyMarkupChanged(), and setMementoImpl().

◆ setMementoImpl()

void KoSvgTextShape::setMementoImpl ( const KoSvgTextShapeMementoSP memento)
private

Definition at line 1459 of file KoSvgTextShape.cpp.

1460{
1461 KoSvgTextShapeMementoImpl *impl = dynamic_cast<KoSvgTextShapeMementoImpl*>(memento.data());
1462 if (impl) {
1463 d->textData = impl->textData;
1464 d->result = impl->result;
1465 d->lineBoxes = impl->lineBoxes;
1466 d->cursorPos = impl->cursorPos;
1467 d->logicalToVisualCursorPos = impl->logicalToVisualCursorPos;
1468 d->plainText = impl->plainText;
1469 d->isBidi = impl->isBidi;
1470 d->initialTextPosition = impl->initialTextPosition;
1471 }
1472}
QVector< LineBox > lineBoxes
QMap< int, int > logicalToVisualCursorPos
KisForest< KoSvgTextContentElement > textData
QVector< CharacterResult > result
QVector< CursorPos > cursorPos

References KoSvgTextShapeMementoImpl::cursorPos, d, KoSvgTextShapeMementoImpl::initialTextPosition, KoSvgTextShapeMementoImpl::isBidi, KoSvgTextShapeMementoImpl::lineBoxes, KoSvgTextShapeMementoImpl::logicalToVisualCursorPos, KoSvgTextShapeMementoImpl::plainText, KoSvgTextShapeMementoImpl::result, and KoSvgTextShapeMementoImpl::textData.

◆ setPaintOrder()

void KoSvgTextShape::setPaintOrder ( KoShape::PaintOrder first,
KoShape::PaintOrder second )
overridevirtual

setPaintOrder set the paint order. As there's only three entries in any given paintorder, you only need to have the first and second entry to set it.

Parameters
firstfirst thing to paint
secondsecond thing to paint.

Reimplemented from KoShape.

Definition at line 1195 of file KoSvgTextShape.cpp.

1196{
1197 if (KisForestDetail::size(d->textData) == 0) {
1198 d->textData.insert(d->textData.childBegin(), KoSvgTextContentElement());
1199 }
1200 KIS_SAFE_ASSERT_RECOVER_RETURN(first != second);
1202
1203 if (first != Fill) {
1204 if (order.at(1) == first) {
1205 order[1] = order[0];
1206 order[0] = first;
1207 } else if (order.at(2) == first) {
1208 order[2] = order[0];
1209 order[0] = first;
1210 }
1211 }
1212 if (second != first && second != Stroke) {
1213 if (order.at(2) == second) {
1214 order[2] = order[1];
1215 order[1] = second;
1216 }
1217 }
1218 d->textData.childBegin()->properties.setProperty(KoSvgTextProperties::PaintOrder,
1219 QVariant::fromValue(order));
1220 setInheritPaintOrder(false);
1221}
static QVector< PaintOrder > defaultPaintOrder()
default paint order as per SVG specification
Definition KoShape.cpp:784
void setInheritPaintOrder(bool value)
setInheritPaintOrder set inherit paint order.
Definition KoShape.cpp:790
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References d, KoShape::defaultPaintOrder(), KoShape::Fill, KIS_SAFE_ASSERT_RECOVER_RETURN, KoSvgTextProperties::PaintOrder, KoShape::setInheritPaintOrder(), and KisForestDetail::size().

◆ setPropertiesAtPos()

void KoSvgTextShape::setPropertiesAtPos ( int pos,
KoSvgTextProperties properties )

setPropertiesAtPos will set the properties at pos.

Parameters
pos
properties

Definition at line 953 of file KoSvgTextShape.cpp.

954{
955 if (pos < 0 || d->cursorPos.isEmpty()) {
956 if (KisForestDetail::size(d->textData)) {
957 d->textData.childBegin()->properties = properties;
958 }
961 return;
962 }
963 CursorPos cursorPos = d->cursorPos.at(pos);
964 CharacterResult res = d->result.at(cursorPos.cluster);
965 int currentIndex = 0;
966 auto it = d->findTextContentElementForIndex(d->textData, currentIndex, res.plaintTextIndex);
967 if (it != d->textData.depthFirstTailEnd()) {
968 it->properties = properties;
971 }
972}

References KoShape::ContentChanged, cursorPos, d, KoShape::notifyChanged(), CharacterResult::plaintTextIndex, KoShape::shapeChangedPriv(), and KisForestDetail::size().

◆ setRelayoutBlocked()

void KoSvgTextShape::setRelayoutBlocked ( const bool disable)

Definition at line 1514 of file KoSvgTextShape.cpp.

1515{
1516 d->isLoading = disable;
1517}

References d.

◆ setResolution()

void KoSvgTextShape::setResolution ( qreal xRes,
qreal yRes )
overridevirtual

Update the image resolution in pixels per inch. Shapes should override this if they need to know the image resolution.

Parameters
xRes
yRes

Reimplemented from KoShape.

Definition at line 171 of file KoSvgTextShape.cpp.

172{
173 int roundedX = qRound(xRes);
174 int roundedY = qRound(yRes);
175 if (roundedX != d->xRes || roundedY != d->yRes) {
176 d->xRes = roundedX;
177 d->yRes = roundedY;
178 relayout();
179 }
180}
void relayout() const

References d, relayout(), xRes, and yRes.

◆ setShapesInside()

void KoSvgTextShape::setShapesInside ( QList< KoShape * > shapesInside)

setShapesInside

Parameters
shapesInsidethe list of shapes to make up the content area.

Definition at line 1717 of file KoSvgTextShape.cpp.

1718{
1719 d->shapesInside = shapesInside;
1720}

References d, and shapesInside.

◆ setShapesSubtract()

void KoSvgTextShape::setShapesSubtract ( QList< KoShape * > shapesSubtract)

setShapesSubtract

Parameters
shapesSubtractthe list of shapes that subtract from the wrapping area.

Definition at line 1727 of file KoSvgTextShape.cpp.

1728{
1729 d->shapesSubtract = shapesSubtract;
1730}

References d, and shapesSubtract.

◆ setStroke()

void KoSvgTextShape::setStroke ( KoShapeStrokeModelSP stroke)
overridevirtual

Set a new stroke, removing the old one. The stroke inheritance becomes disabled.

Parameters
strokethe new stroke, or 0 if there should be no stroke.

Reimplemented from KoShape.

Definition at line 1175 of file KoSvgTextShape.cpp.

1176{
1177 if (KisForestDetail::size(d->textData) == 0) {
1178 d->textData.insert(d->textData.childBegin(), KoSvgTextContentElement());
1179 }
1180 d->textData.childBegin()->properties.setProperty(KoSvgTextProperties::StrokeId,
1181 QVariant::fromValue(KoSvgText::StrokeProperty(stroke)));
1183 notifyChanged();
1184}

References d, KoShape::notifyChanged(), KoShape::shapeChangedPriv(), KisForestDetail::size(), stroke(), KoShape::StrokeChanged, and KoSvgTextProperties::StrokeId.

◆ setTransformsFromLayout()

void KoSvgTextShape::setTransformsFromLayout ( KisForest< KoSvgTextContentElement > & tree,
const QVector< CharacterResult > layout )
inline

Definition at line 995 of file KoSvgTextShape_p.h.

995 {
996 for (int i = 0; i< layout.size(); i++) {
997 //split all anchored chunks, so we can set transforms on them.
998 if (layout.at(i).anchored_chunk) {
999 int plainTextIndex = layout.at(i).plaintTextIndex;
1000 splitContentElement(tree, plainTextIndex);
1001 }
1002 }
1003
1004 int globalIndex = 0;
1005 for (auto it = tree.childBegin(); it != tree.childEnd(); it++) {
1007 it->properties.propertyOrDefault(KoSvgTextProperties::WritingModeId).toInt());
1008 bool isHorizontal = mode == KoSvgText::HorizontalTB;
1009 setTransformsFromLayoutImpl(it, KoSvgTextProperties::defaultProperties(), layout, globalIndex, isHorizontal);
1010 }
1011 }
static bool splitContentElement(KisForest< KoSvgTextContentElement > &tree, int index)
splitContentElement split the contentElement in tree at index into two nodes.
void setTransformsFromLayoutImpl(KisForest< KoSvgTextContentElement >::child_iterator current, const KoSvgTextProperties parentProps, const QVector< CharacterResult > layout, int &globalIndex, bool isHorizontal)

References KisForestDetail::Forest< T >::childBegin(), KisForestDetail::Forest< T >::childEnd(), KoSvgTextProperties::defaultProperties(), KoSvgText::HorizontalTB, and KoSvgTextProperties::WritingModeId.

◆ setTransformsFromLayoutImpl()

void KoSvgTextShape::setTransformsFromLayoutImpl ( KisForest< KoSvgTextContentElement >::child_iterator current,
const KoSvgTextProperties parentProps,
const QVector< CharacterResult > layout,
int & globalIndex,
bool isHorizontal )
inline

Definition at line 1013 of file KoSvgTextShape_p.h.

1015 {
1016 KoSvgTextProperties props = current->properties;
1017 props.inheritFrom(parentProps);
1018 if (current->textPath) return; // When we're doing text-on-path, we're already in preformatted mode.
1019 for (auto it = childBegin(current); it!= childEnd(current); it++) {
1020 setTransformsFromLayoutImpl(it, props, layout, globalIndex, isHorizontal);
1021 }
1022
1023 if (current->text.isEmpty()) {
1024 current->localTransformations.clear();
1025 } else {
1027 const int length = current->numChars(true, props);
1028
1029 for (int i = globalIndex; i< globalIndex+length; i++) {
1030 CharacterResult result = layout.value(i);
1031
1032 if (!result.addressable) {
1033 continue;
1034 }
1036
1037 //TODO: Also split up content element if multiple anchored chunks.
1038 if (result.anchored_chunk) {
1039 int endIndex = 0;
1040 qreal shift = anchoredChunkShift(layout, isHorizontal, i, endIndex);
1041 QPointF offset = isHorizontal? QPointF(shift, 0): QPointF(0, shift);
1042 transform.xPos = result.finalPosition.x() - offset.x();
1043 transform.yPos = result.finalPosition.y() - offset.y();
1044 } else if (i > 0) {
1045 CharacterResult resultPrev = layout.value(i-1);
1046 QPointF offset = (result.finalPosition - result.cssPosition) - (resultPrev.finalPosition - resultPrev.cssPosition);
1047
1048 transform.dxPos = offset.x();
1049 transform.dyPos = offset.y();
1050 }
1051 transform.rotate = result.rotate;
1052
1053 transforms.append(transform);
1054 }
1055 current->localTransformations = transforms;
1056 current->text = current->text.split("\n").join(" ");
1057 globalIndex += length;
1058 }
1059 }
static qreal anchoredChunkShift(const QVector< CharacterResult > &result, const bool isHorizontal, const int start, int &end)
QPointF cssPosition
the position in accordance with the CSS specs, as opossed to the SVG spec.

References CharacterResult::addressable, CharacterResult::anchored_chunk, CharacterResult::cssPosition, KoSvgText::CharTransformation::dxPos, KoSvgText::CharTransformation::dyPos, CharacterResult::finalPosition, KoSvgTextProperties::inheritFrom(), length(), KoSvgText::CharTransformation::rotate, CharacterResult::rotate, KoSvgText::CharTransformation::xPos, and KoSvgText::CharTransformation::yPos.

◆ shapeChanged()

void KoSvgTextShape::shapeChanged ( ChangeType type,
KoShape * shape )
overrideprotectedvirtual

A hook that allows inheriting classes to do something after a KoShape property changed This is called whenever the shape, position rotation or scale properties were altered.

Parameters
typean indicator which type was changed.
shapethe shape.

Reimplemented from KoShape.

Definition at line 159 of file KoSvgTextShape.cpp.

160{
161 if (d->isLoading) {
162 return;
163 }
164 KoShape::shapeChanged(type, shape);
165
166 if (type == ContentChanged) {
167 relayout();
168 }
169}
virtual void shapeChanged(ChangeType type, KoShape *shape=0)
Definition KoShape.cpp:1253

References KoShape::ContentChanged, d, relayout(), and KoShape::shapeChanged().

◆ shapesInside()

QList< KoShape * > KoSvgTextShape::shapesInside ( ) const

shapesInside

Returns
the list of shapes that make up the content area.

◆ shapesSubtract()

QList< KoShape * > KoSvgTextShape::shapesSubtract ( ) const

shapesSubtract

Returns
list of subtract shapes.

◆ shapeTypeSpecificStyles()

QMap< QString, QString > KoSvgTextShape::shapeTypeSpecificStyles ( SvgSavingContext & context) const

Definition at line 1737 of file KoSvgTextShape.cpp.

1738{
1739 QMap<QString, QString> map = this->textProperties().convertParagraphProperties();
1740 if (!d->shapesInside.isEmpty()) {
1741 QStringList shapesInsideList;
1742 Q_FOREACH(KoShape* shape, d->shapesInside) {
1743 QString id = SvgStyleWriter::embedShape(shape, context);
1744 shapesInsideList.append(QString("url(#%1)").arg(id));
1745 }
1746 map.insert("shape-inside", shapesInsideList.join(" "));
1747 }
1748 if (!d->shapesSubtract.isEmpty()) {
1749 QStringList shapesInsideList;
1750 Q_FOREACH(KoShape* shape, d->shapesSubtract) {
1751 QString id = SvgStyleWriter::embedShape(shape, context);
1752 shapesInsideList.append(QString("url(#%1)").arg(id));
1753 }
1754 map.insert("shape-subtract", shapesInsideList.join(" "));
1755 }
1756
1757 return map;
1758}
static QString embedShape(const KoShape *shape, SvgSavingContext &context)

References KoSvgTextProperties::convertParagraphProperties(), d, SvgStyleWriter::embedShape(), and textProperties().

◆ splitContentElement()

static bool KoSvgTextShape::splitContentElement ( KisForest< KoSvgTextContentElement > & tree,
int index )
inlinestatic

splitContentElement split the contentElement in tree at index into two nodes.

Parameters
tree– tree to work on.
index– index
Returns
whether it was successful.

Definition at line 655 of file KoSvgTextShape_p.h.

655 {
656 int currentIndex = 0;
657
658 // If there's only a single root element, don't bother searching.
659 auto contentElement = depth(tree) == 1? tree.depthFirstTailBegin(): findTextContentElementForIndex(tree, currentIndex, index, true);
660 if (contentElement == tree.depthFirstTailEnd()) return false;
661
662 bool suitableStartIndex = siblingCurrent(contentElement) == tree.childBegin()? index >= currentIndex: index > currentIndex;
663 bool suitableEndIndex = siblingCurrent(contentElement) == tree.childBegin()? true: index < currentIndex + contentElement->numChars(false);
664
665 if (suitableStartIndex && suitableEndIndex) {
667 duplicate.text = contentElement->text;
668 int start = index - currentIndex;
669 int length = contentElement->numChars(false) - start;
670 int zero = 0;
671 duplicate.removeText(start, length);
672
673 // TODO: handle localtransforms better; annoyingly, this requires whitespace handling
674
675 if (siblingCurrent(contentElement) != tree.childBegin()
676 && !contentElement->textPath
677 && contentElement->textLength.isAuto
678 && contentElement->localTransformations.isEmpty()) {
679 contentElement->removeText(zero, start);
680 duplicate.properties = contentElement->properties;
681 tree.insert(siblingCurrent(contentElement), duplicate);
682 } else {
684 duplicate2.text = contentElement->text;
685 duplicate2.removeText(zero, start);
686 contentElement->text.clear();
687 tree.insert(childBegin(contentElement), duplicate);
688 tree.insert(childEnd(contentElement), duplicate2);
689 }
690 return true;
691 }
692 return false;
693 }
child_iterator insert(child_iterator pos, X &&value)
Inserts element value into position pos. value becomes the child of the same parent as pos and is pla...
Definition KisForest.h:943
static KisForest< KoSvgTextContentElement >::depth_first_tail_iterator findTextContentElementForIndex(KisForest< KoSvgTextContentElement > &tree, int &currentIndex, int sought, bool skipZeroWidth=false)
findTextContentElementForIndex Finds the given leaf of the current tree-wide string index.
int depth(typename Forest< T >::const_child_iterator beginIt, typename Forest< T >::const_child_iterator endIt)
Definition KisForest.h:1213
void removeText(int &start, int length)
removeText removes text,
KoSvgTextProperties properties
The textProperties. This includes.
QString text
Plain text of the current node. Use insertText and removeText to manipulate it.

References KisForestDetail::Forest< T >::childBegin(), KisForestDetail::Forest< T >::depthFirstTailBegin(), KisForestDetail::Forest< T >::depthFirstTailEnd(), KisForestDetail::Forest< T >::insert(), length(), KoSvgTextContentElement::properties, KoSvgTextProperties::properties(), KoSvgTextContentElement::removeText(), and KoSvgTextContentElement::text.

◆ startIndexOfIterator()

static bool KoSvgTextShape::startIndexOfIterator ( KisForest< KoSvgTextContentElement >::child_iterator parent,
KisForest< KoSvgTextContentElement >::child_iterator target,
int & currentIndex )
inlinestatic

Definition at line 1134 of file KoSvgTextShape_p.h.

1134 {
1135 for (auto child = KisForestDetail::childBegin(parent); child != KisForestDetail::childEnd(parent); child++) {
1136 if (child == target) {
1137 return true;
1138 } else if ((KisForestDetail::childBegin(child) != KisForestDetail::childEnd(child))) {
1139 if (startIndexOfIterator(child, target, currentIndex)) {
1140 return true;
1141 }
1142 } else {
1143 currentIndex += numChars(child);
1144 }
1145 }
1146 return false;
1147 }
KisMagneticGraph::vertex_descriptor target(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
static bool startIndexOfIterator(KisForest< KoSvgTextContentElement >::child_iterator parent, KisForest< KoSvgTextContentElement >::child_iterator target, int &currentIndex)

References KisForestDetail::childBegin(), KisForestDetail::childEnd(), and target().

◆ stretchGlyphOnPath()

static QPainterPath KoSvgTextShape::stretchGlyphOnPath ( const QPainterPath & glyph,
const QPainterPath & path,
bool isHorizontal,
qreal offset,
bool isClosed )
static

◆ stroke()

KoShapeStrokeModelSP KoSvgTextShape::stroke ( ) const
overridevirtual

Returns the currently set stroke, or 0 if there is no stroke.

Returns
the currently set stroke, or 0 if there is no stroke.

Reimplemented from KoShape.

Definition at line 1169 of file KoSvgTextShape.cpp.

1170{
1171 KoSvgTextProperties props = KisForestDetail::size(d->textData)? d->textData.childBegin()->properties: KoSvgTextProperties();
1173}

References d, KoSvgTextProperties::properties(), KoSvgTextProperties::property(), KisForestDetail::size(), and KoSvgTextProperties::StrokeId.

◆ textOutline()

KoShape * KoSvgTextShape::textOutline ( ) const

textOutline This turns the text object into non-text KoShape(s) to the best of its abilities.

Returns
a single KoPathShape if only a single path is necessary, or multiple KoShapes (Paths, Images, and Rectangles with Masks are all possible) inside a KoShapeGroup.

Definition at line 1686 of file KoSvgTextShape.cpp.

1687{
1688 KoShape *shape;
1689 int currentIndex = 0;
1690 if (!d->result.empty()) {
1691 shape = d->collectPaths(this, d->result, currentIndex);
1692 }
1693
1694 return shape;
1695}

References d.

◆ textProperties()

KoSvgTextProperties KoSvgTextShape::textProperties ( ) const

Definition at line 1143 of file KoSvgTextShape.cpp.

1144{
1145 return KisForestDetail::size(d->textData)? d->textData.childBegin()->properties: KoSvgTextProperties();
1146}

References d, KoSvgTextProperties::properties(), and KisForestDetail::size().

◆ textType()

KoSvgTextShape::TextType KoSvgTextShape::textType ( ) const

textType This enum gives an indication of what kind of text this shape is. The different text types are a bit blurry as SVG allows a mixutre to provide fallback information. When such fallback is in place, this will only return the primary text type, that is, TextInShape before InlineWrap and InlineWrap before PrePositioned/Preformatted. This primarily exists to give UI feedback.

Returns
estimated TextType

Definition at line 1697 of file KoSvgTextShape.cpp.

1698{
1699 KoSvgText::AutoValue inlineSize = d->textData.childBegin()->properties.propertyOrDefault(KoSvgTextProperties::InlineSizeId).value<KoSvgText::AutoValue>();
1700 if (!d->shapesInside.isEmpty()) {
1701 return TextType::TextInShape;
1702 } else if (!inlineSize.isAuto) {
1703 return TextType::InlineWrap;
1704 } else {
1705 bool textSpaceCollapse = false;
1706 for (auto it = d->textData.depthFirstTailBegin(); it != d->textData.depthFirstTailEnd(); it++) {
1707 KoSvgText::TextSpaceCollapse collapse = KoSvgText::TextSpaceCollapse(it->properties.propertyOrDefault(KoSvgTextProperties::TextCollapseId).toInt());
1708 if (collapse == KoSvgText::Collapse || collapse == KoSvgText::PreserveSpaces) {
1709 textSpaceCollapse = true;
1710 break;
1711 }
1712 }
1714 }
1715}
@ Collapse
Collapse white space sequences into a single character.
Definition KoSvgText.h:97
@ PreserveSpaces
required for 'xml:space="preserve"' emulation.
Definition KoSvgText.h:102

References KoSvgText::Collapse, d, KoSvgTextProperties::InlineSizeId, InlineWrap, KoSvgText::AutoValue::isAuto, PreformattedText, PrePositionedText, KoSvgText::PreserveSpaces, KoSvgTextProperties::TextCollapseId, and TextInShape.

◆ underlines()

QPainterPath KoSvgTextShape::underlines ( int pos,
int anchor,
KoSvgText::TextDecorations decor,
KoSvgText::TextDecorationStyle style,
qreal minimum,
bool thick )

Definition at line 614 of file KoSvgTextShape.cpp.

615{
616 int start = qMin(pos, anchor);
617 int end = qMax(pos, anchor);
618
619 if (start == end || start < 0 || end >= d->cursorPos.size()) {
620 return QPainterPath();
621 }
622 QPainterPathStroker stroker;
623
625 stroker.setCapStyle(Qt::FlatCap);
626 if (style == KoSvgText::Solid) {
627 stroker.setDashPattern(Qt::SolidLine);
628 } else if (style == KoSvgText::Dashed) {
629 stroker.setDashPattern(Qt::DashLine);
630 } else if (style == KoSvgText::Dotted) {
631 stroker.setDashPattern(Qt::DotLine);
632 } else {
633 stroker.setDashPattern(Qt::SolidLine);
634 }
635
636 QPainterPath underPath;
637 QPainterPath overPath;
638 QPainterPath middlePath;
639 qint32 strokeWidth = 0;
640 QPointF inset = mode == KoSvgText::HorizontalTB? QPointF(minimum*0.5, 0): QPointF(0, minimum*0.5);
641 for (int i = start+1; i <= end; i++) {
642 CursorPos pos = d->cursorPos.at(i);
643 CharacterResult res = d->result.at(pos.cluster);
644 strokeWidth += res.metrics.underlineThickness;
645 const QTransform tf = res.finalTransform();
646 QPointF first = res.cursorInfo.caret.p1();
647 QPointF last = first;
648 if (res.cursorInfo.rtl) {
649 last += res.cursorInfo.offsets.value(pos.offset-1, res.advance);
650 first += res.cursorInfo.offsets.value(pos.offset, QPointF());
651 if (i == start+1) {
652 first -= inset;
653 }
654 if (i == end) {
655 last += inset;
656 }
657 } else {
658 first += res.cursorInfo.offsets.value(pos.offset-1, QPointF());
659 last += res.cursorInfo.offsets.value(pos.offset, res.advance);
660 if (i == start+1) {
661 first += inset;
662 }
663 if (i == end) {
664 last -= inset;
665 }
666 }
667
668 if (decor.testFlag(KoSvgText::DecorationUnderline)){
669 underPath.moveTo(tf.map(first));
670 underPath.lineTo(tf.map(last));
671 }
672 QPointF diff = res.cursorInfo.caret.p2() - res.cursorInfo.caret.p1();
673 if (decor.testFlag(KoSvgText::DecorationOverline)){
674 overPath.moveTo(tf.map(first+diff));
675 overPath.lineTo(tf.map(last+diff));
676 }
677 if (decor.testFlag(KoSvgText::DecorationLineThrough)){
678 middlePath.moveTo(tf.map(first+(diff*0.5)));
679 middlePath.lineTo(tf.map(last+(diff*0.5)));
680 }
681 }
682
683 const qreal freetypePixelsToPt = (1.0 / 64.0) * (72. / qMin(d->xRes, d->yRes));
684 const qreal width = strokeWidth > 0 ? qMax(qreal(strokeWidth/qMax(1, end-(start+1)))*freetypePixelsToPt, minimum): minimum;
685
686 stroker.setWidth(thick? width*2: width);
687
688 QPainterPath final;
689 if (decor.testFlag(KoSvgText::DecorationUnderline)){
690 final.addPath(stroker.createStroke(underPath));
691 }
692 if (decor.testFlag(KoSvgText::DecorationOverline)){
693 final.addPath(stroker.createStroke(overPath));
694 }
695 if (decor.testFlag(KoSvgText::DecorationLineThrough)){
696 final.addPath(stroker.createStroke(middlePath));
697 }
698
699 return final;
700}
@ Solid
Draw a solid line.Ex: --—.
Definition KoSvgText.h:266
@ Dashed
Draw a dashed line. Ex: - - - - -.
Definition KoSvgText.h:269
@ Dotted
Draw a dotted line. Ex: .....
Definition KoSvgText.h:268
KoSvgText::FontMetrics metrics
Fontmetrics for current font, in Freetype scanline coordinates.
qint32 underlineThickness
underline thickness from font.
Definition KoSvgText.h:357

References CharacterResult::advance, KoShape::anchor(), CursorInfo::caret, CursorPos::cluster, CharacterResult::cursorInfo, d, KoSvgText::Dashed, KoSvgText::DecorationLineThrough, KoSvgText::DecorationOverline, KoSvgText::DecorationUnderline, KoSvgText::Dotted, CharacterResult::finalTransform(), KoSvgText::HorizontalTB, CharacterResult::metrics, CursorPos::offset, CursorInfo::offsets, CursorInfo::rtl, KoSvgText::Solid, textProperties(), KoSvgText::FontMetrics::underlineThickness, and KoSvgTextProperties::WritingModeId.

◆ wordEnd()

int KoSvgTextShape::wordEnd ( int pos)

wordEnd return the pos of the first wordbreak.

Parameters
pos– cursor position.
Returns
the first wordbreak or line end.

Definition at line 477 of file KoSvgTextShape.cpp.

478{
479 if (pos < 0 || pos > d->cursorPos.size()-1 || d->result.isEmpty() || d->cursorPos.isEmpty()) {
480 return pos;
481 }
482 int currentLineEnd = lineEnd(pos);
483 if (pos == lineStart(pos) || pos == currentLineEnd) {
484 return pos;
485 }
486
487 int wordEnd = pos;
488 for (int i = pos; i<= currentLineEnd; i++) {
489 wordEnd = i;
490 CursorPos cursorPos = d->cursorPos.at(i);
491 if (d->result.at(cursorPos.cluster).cursorInfo.isWordBoundary && cursorPos.offset == 0) {
492 break;
493 }
494
495 }
496
497 return wordEnd;
498}
int wordEnd(int pos)
wordEnd return the pos of the first wordbreak.

References cursorPos, d, lineEnd(), lineStart(), and wordEnd().

◆ wordLeft()

int KoSvgTextShape::wordLeft ( int pos,
bool visual = false )

wordLeft return the cursorpos for the word left or the extreme of the line.

Parameters
posthe position.
visualwhether to flip for rtl.
Returns
the first pos before a wordbreak at the left.

Definition at line 286 of file KoSvgTextShape.cpp.

287{
288 //TODO: figure out preferred behaviour for wordLeft in RTL && visual.
289 Q_UNUSED(visual)
290 if (pos < 0 || pos > d->cursorPos.size()-1 || d->result.isEmpty() || d->cursorPos.isEmpty()) {
291 return pos;
292 }
294 if (direction == KoSvgText::DirectionRightToLeft) {
295 return wordEnd(pos);
296 }
297 return wordStart(pos);
298}
int wordStart(int pos)
wordStart return the first pos before a wordbreak in the start direction.

References d, KoSvgTextProperties::DirectionId, KoSvgText::DirectionRightToLeft, textProperties(), wordEnd(), and wordStart().

◆ wordRight()

int KoSvgTextShape::wordRight ( int pos,
bool visual = false )

wordRight return the cursorpos for the word right or the extreme of the line.

Parameters
posthe position.
visualwhether to flip for rtl.
Returns
the first word break at the right.

Definition at line 300 of file KoSvgTextShape.cpp.

301{
302 Q_UNUSED(visual)
303 if (pos < 0 || pos > d->cursorPos.size()-1 || d->result.isEmpty() || d->cursorPos.isEmpty()) {
304 return pos;
305 }
307 if (direction == KoSvgText::DirectionRightToLeft) {
308 return wordStart(pos);
309 }
310 return wordEnd(pos);
311}

References d, KoSvgTextProperties::DirectionId, KoSvgText::DirectionRightToLeft, textProperties(), wordEnd(), and wordStart().

◆ wordStart()

int KoSvgTextShape::wordStart ( int pos)

wordStart return the first pos before a wordbreak in the start direction.

Parameters
pos– cursor position
Returns
the first position before a wordbreak or the line start.

Definition at line 500 of file KoSvgTextShape.cpp.

501{
502 if (pos < 0 || pos > d->cursorPos.size()-1 || d->result.isEmpty() || d->cursorPos.isEmpty()) {
503 return pos;
504 }
505 int currentLineStart = lineStart(pos);
506 if (pos == currentLineStart || pos == lineEnd(pos)) {
507 return pos;
508 }
509
510 int wordStart = pos;
511 bool breakNext = false;
512 for (int i = pos; i >= currentLineStart; i--) {
513 if (breakNext) break;
514 CursorPos cursorPos = d->cursorPos.at(i);
515 if (d->result.at(cursorPos.cluster).cursorInfo.isWordBoundary && cursorPos.offset == 0) {
516 breakNext = true;
517 }
518 wordStart = i;
519 }
520
521 return wordStart;
522}

References cursorPos, d, lineEnd(), lineStart(), and wordStart().

◆ writingMode()

KoSvgText::WritingMode KoSvgTextShape::writingMode ( ) const

writingMode There's a number of places we need to check the writing mode to provide proper controls.

Returns
the writing mode of this text.

Definition at line 1228 of file KoSvgTextShape.cpp.

1229{
1231}

References textProperties(), and KoSvgTextProperties::WritingModeId.

Friends And Related Symbol Documentation

◆ KoSvgTextLoader

friend class KoSvgTextLoader
friend

Definition at line 518 of file KoSvgTextShape.h.

◆ TestSvgText

friend class TestSvgText
friend

Definition at line 517 of file KoSvgTextShape.h.

Member Data Documentation

◆ cursorPos

QVector<CursorPos> KoSvgTextShape::cursorPos

Definition at line 488 of file KoSvgTextShape_p.h.

◆ d

QScopedPointer<Private> KoSvgTextShape::d
private

Definition at line 545 of file KoSvgTextShape.h.

◆ disableFontMatching

bool KoSvgTextShape::disableFontMatching = false

Turn off font matching, which should speed up relayout slightly.

Definition at line 483 of file KoSvgTextShape_p.h.

◆ initialTextPosition

QPointF KoSvgTextShape::initialTextPosition = QPointF()

Definition at line 493 of file KoSvgTextShape_p.h.

◆ isBidi

bool KoSvgTextShape::isBidi = false

Definition at line 492 of file KoSvgTextShape_p.h.

◆ isLoading

bool KoSvgTextShape::isLoading = false

Turned on when loading in text data, blocks updates to shape listeners.

Definition at line 481 of file KoSvgTextShape_p.h.

◆ lineBoxes

QVector<LineBox> KoSvgTextShape::lineBoxes

Definition at line 486 of file KoSvgTextShape_p.h.

◆ logicalToVisualCursorPos

QMap<int, int> KoSvgTextShape::logicalToVisualCursorPos

Definition at line 489 of file KoSvgTextShape_p.h.

◆ plainText

QString KoSvgTextShape::plainText

Definition at line 491 of file KoSvgTextShape_p.h.

◆ result

QVector<CharacterResult> KoSvgTextShape::result

Definition at line 485 of file KoSvgTextShape_p.h.

◆ shapesInside

QList< KoShape * > KoSvgTextShape::shapesInside

Definition at line 477 of file KoSvgTextShape_p.h.

◆ shapesSubtract

QList< KoShape * > KoSvgTextShape::shapesSubtract

Definition at line 478 of file KoSvgTextShape_p.h.

◆ textData

KisForest<KoSvgTextContentElement> KoSvgTextShape::textData

Definition at line 480 of file KoSvgTextShape_p.h.

◆ xRes

int KoSvgTextShape::xRes = 72

Definition at line 475 of file KoSvgTextShape_p.h.

◆ yRes

int KoSvgTextShape::yRes = 72

Definition at line 476 of file KoSvgTextShape_p.h.


The documentation for this class was generated from the following files: