8#ifndef KO_SVG_TEXT_SHAPE_P_H
9#define KO_SVG_TEXT_SHAPE_P_H
24#include <QPainterPath>
86using Variant = std::variant<std::monostate, Outline, Bitmap, ColorLayers>;
167 if (newOrigin == QPointF())
return;
169 outlineGlyph->path.translate(-newOrigin);
171 for (
int i = 0; i< bitmapGlyph->drawRects.size(); i++) {
172 bitmapGlyph->drawRects[i].translate(-newOrigin);
175 for (
int i = 0; i< colorGlyph->paths.size(); i++) {
176 colorGlyph->paths[i].translate(-newOrigin);
198 QTransform scale = QTransform::fromScale(xScale, yScale);
199 if (scale.isIdentity())
return;
200 const bool scaleToZero = !(xScale > 0 && yScale > 0);
203 if (!outlineGlyph->path.isEmpty()) {
205 outlineGlyph->path = QPainterPath();
207 outlineGlyph->path = scale.map(outlineGlyph->path);
212 bitmapGlyph->drawRects.clear();
213 bitmapGlyph->images.clear();
215 for (
int i = 0; i< bitmapGlyph->drawRects.size(); i++) {
216 bitmapGlyph->drawRects[i] = scale.mapRect(bitmapGlyph->drawRects[i]);
220 for (
int i = 0; i< colorGlyph->paths.size(); i++) {
222 colorGlyph->paths[i] = QPainterPath();
224 colorGlyph->paths[i] = scale.map(colorGlyph->paths[i]);
313 Q_FOREACH(QLineF line, lineWidths) {
320 Q_FOREACH(QLineF line, lineWidths) {
379 for (
int i=0; i<
chunks.size(); i++) {
384 if ((pos.x() < max) &&
392 if ((pos.y() < max) &&
402 if (
chunks.isEmpty())
return true;
403 for (
int i =0; i <
chunks.size(); i++) {
404 if (!
chunks.at(i).chunkIndices.isEmpty())
return false;
442 : textData(rhs.textData) {
443 Q_FOREACH (
KoShape *shape, rhs.shapesInside) {
447 shapesInside.append(clonedShape);
449 Q_FOREACH (
KoShape *shape, rhs.shapesSubtract) {
453 shapesSubtract.append(clonedShape);
458 lineBoxes = rhs.lineBoxes;
460 cursorPos = rhs.cursorPos;
461 logicalToVisualCursorPos = rhs.logicalToVisualCursorPos;
462 plainText = rhs.plainText;
464 initialTextPosition = rhs.initialTextPosition;
466 isLoading = rhs.isLoading;
467 disableFontMatching = rhs.disableFontMatching;
471 qDeleteAll(shapesInside);
472 qDeleteAll(shapesSubtract);
481 bool isLoading =
false;
483 bool disableFontMatching =
false;
493 QPointF initialTextPosition = QPointF();
498 const FT_Int32 faceLoadFlags,
499 const bool isHorizontal,
500 const char32_t firstCodepoint,
502 raqm_glyph_t ¤tGlyph,
504 QPointF &totalAdvanceFTFontCoordinates);
507 FT_Int32 faceLoadFlags,
509 raqm_glyph_t ¤tGlyph,
525 const QPainterPath &path,
532 const QPointF superScript,
533 const QPointF subScript,
537 const bool isHorizontal,
538 const bool disableFontMatching);
545 const QMap<int, int>& logicalToVisual,
548 qreal textPathoffset,
558 const bool isHorizontal,
559 const KoSvgText::TextDecorations &decor,
561 const bool textDecorationSkipInset =
false,
563 const qreal currentTextPathOffset = 0.0,
564 const bool textPathSide =
false,
568 QPainterPath decorationPath,
569 const QPointF offset,
570 const QPainterPathStroker &stroker,
572 QMap<KoSvgText::TextDecoration, QPainterPath> &decorationPaths,
574 const bool isHorizontal,
575 const qreal currentTextPathOffset,
576 const bool textPathSide
580 const QPainterPath &outlineRect,
585 const QPainterPath &outlineRect,
600 int count = parent->numChars(withControls, props);
602 count += numChars(it, withControls, props);
628 bool skipZeroWidth =
false)
632 if (childCount(siblingCurrent(it)) > 0) {
635 int length = it->numChars(
false);
636 if (
length == 0 && skipZeroWidth) {
640 if (sought == currentIndex || (sought > currentIndex && sought < currentIndex +
length)) {
656 int currentIndex = 0;
659 auto contentElement = depth(tree) == 1? tree.
depthFirstTailBegin(): findTextContentElementForIndex(tree, currentIndex, index,
true);
662 bool suitableStartIndex = siblingCurrent(contentElement) == tree.
childBegin()? index >= currentIndex: index > currentIndex;
663 bool suitableEndIndex = siblingCurrent(contentElement) == tree.
childBegin()?
true: index < currentIndex + contentElement->numChars(
false);
665 if (suitableStartIndex && suitableEndIndex) {
667 duplicate.
text = contentElement->text;
668 int start = index - currentIndex;
669 int length = contentElement->numChars(
false) - start;
675 if (siblingCurrent(contentElement) != tree.
childBegin()
676 && !contentElement->textPath
677 && contentElement->textLength.isAuto
678 && contentElement->localTransformations.isEmpty()) {
679 contentElement->removeText(zero, start);
681 tree.
insert(siblingCurrent(contentElement), duplicate);
684 duplicate2.
text = contentElement->text;
686 contentElement->text.clear();
687 tree.
insert(childBegin(contentElement), duplicate);
688 tree.
insert(childEnd(contentElement), duplicate2);
704 QMap<int, KoSvgText::TextSpaceCollapse> collapseModes;
711 parentProps.append(ownProperties);
713 const int children = childCount(siblingCurrent(it));
715 QString text = it->text;
717 collapseModes.insert(allText.size(), collapse);
721 parentProps.pop_back();
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()) {
749 QVector<bool> collapsedCharacters = collapsedWhiteSpacesForText(tree, all,
true);
752 removeTransformsImpl(root, 0, start,
length, collapsedCharacters);
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);
768 currentLength = currentTextElement->text.size();
771 if (!currentTextElement->localTransformations.isEmpty()) {
772 int transformOffset = 0;
773 int transformOffsetEnd = 0;
775 for (
int i = globalIndex; i < globalIndex + currentLength; i++) {
777 transformOffset += collapsedCharacters.at(i)? 0: 1;
780 transformOffsetEnd += collapsedCharacters.at(i)? 0: 1;
785 if (transformOffset < currentTextElement->localTransformations.size()) {
786 currentTextElement->localTransformations.remove(transformOffset, transformOffsetEnd-transformOffset);
790 return currentLength;
804 QVector<bool> collapsedCharacters = collapsedWhiteSpacesForText(tree, all,
true);
807 insertTransformsImpl(root, 0, start,
length, collapsedCharacters, allowSkipFirst);
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);
822 currentLength = currentTextElement->text.size();
825 if (!currentTextElement->localTransformations.isEmpty()) {
826 int transformOffset = 0;
827 int transformOffsetEnd = 0;
829 for (
int i = globalIndex; i < globalIndex + currentLength; i++) {
831 transformOffset += collapsedCharacters.at(i)? 0: 1;
834 transformOffsetEnd += collapsedCharacters.at(i)? 0: 1;
841 if (transformOffset == 0 && allowSkipFirst && currentTextElement->localTransformations.at(0).startsNewChunk()) {
842 transformOffset += 1;
845 if (transformOffset < currentTextElement->localTransformations.size()) {
846 for (
int i = transformOffset; i < transformOffsetEnd; i++) {
852 return currentLength;
867 QVector<bool> collapsed = collapsedWhiteSpacesForText(tree, allText,
false);
869 auto end = std::make_reverse_iterator(tree.
childBegin());
870 auto begin = std::make_reverse_iterator(tree.
childEnd());
872 for (; begin != end; begin++) {
873 applyWhiteSpaceImpl(begin, collapsed, allText, convertToPreWrapped);
875 if (convertToPreWrapped) {
882 auto base = current.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);
895 if (!current->text.isEmpty()) {
896 const int total = current->text.size();
897 QString currentText = allText.right(total);
899 for (
int i = 0; i < total; i++) {
900 const int j = total - (i+1);
901 const bool col = collapsed.takeLast();
903 currentText.remove(j, 1);
907 current->text = currentText;
910 if (convertToPreWrapped) {
925 QVector<bool> collapsed = collapsedWhiteSpacesForText(tree, all,
false);
936 resolveTransforms(tree.
childBegin(), all, result, globalIndex,
937 isHorizontal, isWrapped,
false, resolvedTransforms,
941 auto end = std::make_reverse_iterator(tree.
childBegin());
942 auto begin = std::make_reverse_iterator(tree.
childEnd());
944 bool inTextPath =
false;
945 for (; begin != end; begin++) {
946 insertNewLinesAtAnchorsImpl(begin, resolvedTransforms, inTextPath);
954 inTextPath = (!current->textPath.isNull());
955 auto base = current.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++) {
961 insertNewLinesAtAnchorsImpl(begin,
967 if (!current->text.isEmpty()) {
968 const int total = current->text.size();
970 for (
int i = 0; i < total; i++) {
971 const int j = total - (i+1);
979 bool startsNewChunk = transform.startsNewChunk() && j == 0;
983 startsNewChunk =
false;
987 if (startsNewChunk && !resolvedTransforms.isEmpty() && current->text.at(j) != QChar::LineFeed) {
988 current->text.insert(j,
"\n");
992 current->localTransformations.clear();
996 for (
int i = 0; i< layout.size(); i++) {
998 if (layout.at(i).anchored_chunk) {
999 int plainTextIndex = layout.at(i).plaintTextIndex;
1000 splitContentElement(tree, plainTextIndex);
1004 int globalIndex = 0;
1015 int &globalIndex,
bool isHorizontal) {
1018 if (current->textPath)
return;
1019 for (
auto it = childBegin(current); it!= childEnd(current); it++) {
1020 setTransformsFromLayoutImpl(it, props, layout, globalIndex, isHorizontal);
1023 if (current->text.isEmpty()) {
1024 current->localTransformations.clear();
1027 const int length = current->numChars(
true, props);
1029 for (
int i = globalIndex; i< globalIndex+
length; i++) {
1040 qreal shift = anchoredChunkShift(layout, isHorizontal, i, endIndex);
1041 QPointF offset = isHorizontal? QPointF(shift, 0): QPointF(0, shift);
1048 transform.
dxPos = offset.x();
1049 transform.
dyPos = offset.y();
1053 transforms.append(transform);
1055 current->localTransformations = transforms;
1056 current->text = current->text.split(
"\n").join(
" ");
1071 const int children = childCount(siblingCurrent(it));
1072 if (children == 0) {
1075 const int length = it->numChars(
false);
1076 if (
length == 0 && siblingCurrent(it) != tree.
childBegin() && !it->textPath) {
1077 tree.
erase(siblingCurrent(it));
1080 auto siblingPrev = siblingCurrent(it);
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)
1092 siblingPrev->text += it->text;
1093 tree.
erase(siblingCurrent(it));
1096 }
else if (children == 1) {
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()) {
1106 child->properties = props;
1108 child->
properties.inheritFrom(it->properties);
1110 tree.
move(child, siblingCurrent(it));
1111 tree.
erase(siblingCurrent(it));
1118 if (treeIndex.isEmpty())
return parent;
1120 int count = idx.takeFirst();
1124 return iteratorForTreeIndex(idx, child);
1139 if (startIndexOfIterator(child,
target, currentIndex)) {
1143 currentIndex += numChars(child);
qreal length(const QPointF &vec)
KisMagneticGraph::vertex_descriptor target(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
constexpr qreal SHAPE_PRECISION
Value that indicates the precision for testing coordinates for text-in-shape layout.
@ ConditionallyHang
Only hang if no space otherwise, only measured for justification if not hanging.
@ Collapse
Collapse if first or last in line.
@ ForceHang
Force hanging at the start or end of a line, never measured for justification.
@ NoChange
Do nothing special.
child_iterator childEnd()
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...
depth_first_tail_iterator depthFirstTailEnd()
child_iterator childBegin()
child_iterator move(child_iterator subtree, child_iterator newPos)
move a subtree to new position Moves subtree into a new position pointer by newPos....
composition_iterator compositionBegin()
composition_iterator compositionEnd()
depth_first_tail_iterator depthFirstTailBegin()
child_iterator erase(child_iterator pos)
Removes element at position pos. If pos is 'end', then result is undefined.
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...
The position of a path point within a path shape.
virtual KoShape * cloneShape() const
creates a deep copy of the shape or shape's subtree
The KoSvgTextNodeIndex class.
@ InlineSizeId
KoSvgText::AutoValue.
@ UnicodeBidiId
KoSvgText::UnicodeBidi.
@ TextCollapseId
KoSvgText::TextSpaceCollapse.
@ WritingModeId
KoSvgText::WritingMode.
@ TextWrapId
KoSvgText::TextWrap.
QList< PropertyId > properties() const
static const KoSvgTextProperties & defaultProperties()
bool hasProperty(PropertyId id) const
void setAllButNonInheritableProperties(const KoSvgTextProperties &properties)
Used to merge child properties into parent properties.
QVariant propertyOrDefault(PropertyId id) const
void inheritFrom(const KoSvgTextProperties &parentProperties, bool resolve=false)
void applyTextLength(KisForest< KoSvgTextContentElement >::child_iterator currentTextElement, QVector< CharacterResult > &result, int ¤tIndex, int &resolvedDescendentNodes, bool isHorizontal, const KoSvgTextProperties resolvedProps, const KoSvgText::ResolutionHandler &resHandler)
static qreal anchoredChunkShift(const QVector< CharacterResult > &result, const bool isHorizontal, const int start, int &end)
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....
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)
void paintDebug(QPainter &painter, const QVector< CharacterResult > &result, int ¤tIndex)
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 i...
static void resolveTransforms(KisForest< KoSvgTextContentElement >::child_iterator currentTextElement, QString text, QVector< CharacterResult > &result, int ¤tIndex, bool isHorizontal, bool wrapped, bool textInPath, QVector< KoSvgText::CharTransformation > &resolved, QVector< bool > collapsedChars, const KoSvgTextProperties resolvedProps, bool withControls=true)
KisForest< KoSvgTextContentElement > textData
static bool splitContentElement(KisForest< KoSvgTextContentElement > &tree, int index)
splitContentElement split the contentElement in tree at index into two nodes.
QVector< CursorPos > cursorPos
static qreal characterResultOnPath(CharacterResult &cr, qreal length, qreal offset, bool isHorizontal, bool isClosed)
void setTransformsFromLayoutImpl(KisForest< KoSvgTextContentElement >::child_iterator current, const KoSvgTextProperties parentProps, const QVector< CharacterResult > layout, int &globalIndex, bool isHorizontal)
QVector< CharacterResult > result
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)
void applyWhiteSpaceImpl(std::reverse_iterator< KisForest< KoSvgTextContentElement >::child_iterator > current, QVector< bool > &collapsed, QString &allText, const bool convertToPreWrapped)
static KisForest< KoSvgTextContentElement >::depth_first_tail_iterator findTextContentElementForIndex(KisForest< KoSvgTextContentElement > &tree, int ¤tIndex, int sought, bool skipZeroWidth=false)
findTextContentElementForIndex Finds the given leaf of the current tree-wide string index.
void paintPaths(QPainter &painter, const QPainterPath &outlineRect, const KoShape *rootShape, const QVector< CharacterResult > &result, const KoSvgText::TextRendering rendering, QPainterPath &chunk, int ¤tIndex)
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....
static KoSvgTextNodeIndex createTextNodeIndex(KisForest< KoSvgTextContentElement >::child_iterator textElement)
QList< KoShape * > shapesInside
static KisForest< KoSvgTextContentElement >::child_iterator iteratorForTreeIndex(const QVector< int > treeIndex, KisForest< KoSvgTextContentElement >::child_iterator parent)
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.
QMap< int, int > logicalToVisualCursorPos
static void cleanUp(KisForest< KoSvgTextContentElement > &tree)
cleanUp This cleans up the tree by...
static void applyAnchoring(QVector< CharacterResult > &result, bool isHorizontal, const KoSvgText::ResolutionHandler resHandler)
static void insertNewLinesAtAnchorsImpl(std::reverse_iterator< KisForest< KoSvgTextContentElement >::child_iterator > current, QVector< KoSvgText::CharTransformation > &resolvedTransforms, bool &inTextPath)
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 ¤tIndex, bool isHorizontal, bool ltr, bool wrapping, const KoSvgTextProperties resolvedProps)
void setTransformsFromLayout(KisForest< KoSvgTextContentElement > &tree, const QVector< CharacterResult > layout)
Private(const Private &rhs)
KoShape * collectPaths(const KoShape *rootShape, QVector< CharacterResult > &result, int ¤tIndex)
static int childCount(KisForest< KoSvgTextContentElement >::child_iterator it)
Get the child count of the current node. A node without children is a text node.
void paintTextDecoration(QPainter &painter, const QPainterPath &outlineRect, const KoShape *rootShape, const KoSvgText::TextDecoration type, const KoSvgText::TextRendering rendering)
static void applyTextPath(KisForest< KoSvgTextContentElement >::child_iterator parent, QVector< CharacterResult > &result, bool isHorizontal, QPointF &startPos, const KoSvgTextProperties resolvedProps)
static void insertNewLinesAtAnchors(KisForest< KoSvgTextContentElement > &tree, bool shapesInside=false)
insertNewLinesAtAnchors Resolves character transforms and then inserts new lines at each transform th...
static std::pair< QTransform, qreal > loadGlyphOnly(const QTransform &ftTF, FT_Int32 faceLoadFlags, bool isHorizontal, raqm_glyph_t ¤tGlyph, CharacterResult &charResult, const KoSvgText::TextRendering rendering)
static void insertTransforms(KisForest< KoSvgTextContentElement > &tree, const int start, const int length, const bool allowSkipFirst)
insertTransforms Inserts empty transforms into tree recursively.
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 ¤tGlyph, CharacterResult &charResult, QPointF &totalAdvanceFTFontCoordinates)
void clearAssociatedOutlines()
static QVector< SubChunk > collectSubChunks(KisForest< KoSvgTextContentElement >::child_iterator it, KoSvgTextProperties parent, bool textInPath, bool &firstTextInPath)
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,...
QList< KoShape * > shapesSubtract
QVector< LineBox > lineBoxes
static QPainterPath stretchGlyphOnPath(const QPainterPath &glyph, const QPainterPath &path, bool isHorizontal, qreal offset, bool isClosed)
static bool startIndexOfIterator(KisForest< KoSvgTextContentElement >::child_iterator parent, KisForest< KoSvgTextContentElement >::child_iterator target, int ¤tIndex)
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 ¤tIndex, const KoSvgText::ResolutionHandler resHandler, const bool isHorizontal, const bool disableFontMatching)
static void handleLineBoxAlignment(KisForest< KoSvgTextContentElement >::child_iterator parent, QVector< CharacterResult > &result, const QVector< LineBox > lineBoxes, int ¤tIndex, const bool isHorizontal, const KoSvgTextProperties resolvedProps)
void applyWhiteSpace(KisForest< KoSvgTextContentElement > &tree, const bool convertToPreWrapped=false)
applyWhiteSpace CSS Whitespace processes whitespaces so that duplicate white spaces and unnecessary h...
#define KIS_ASSERT_RECOVER(cond)
std::variant< std::monostate, Outline, Bitmap, ColorLayers > Variant
ChildIterator< value_type, is_const > childBegin(const ChildIterator< value_type, is_const > &it)
ChildIterator< value_type, is_const > childEnd(const ChildIterator< value_type, is_const > &it)
TextAnchor
Where the text is anchored for SVG 1.1 text and 'inline-size'.
@ AnchorStart
Anchor left for LTR, right for RTL.
TextDecorationStyle
Style of the text-decoration.
@ Solid
Draw a solid line.Ex: --—.
TextDecorationUnderlinePosition
Which location to choose for the underline.
@ UnderlineAuto
Use Font metrics.
TextDecoration
Flags for text-decoration, for underline, overline and strikethrough.
Direction
Base direction used by Bidi algorithm.
Baseline
Baseline values used by dominant-baseline and baseline-align.
@ BidiNormal
No new bidi-level is started.
@ BidiIsolate
Content is ordered as if in a separate paragraph.
@ Preserve
Do not collapse any space.
LineEdgeBehaviour lineStart
QPointF totalBaselineOffset() const
QRectF inkBoundingBox
The bounds of the drawn glyph. Different from the bounds the charresult takes up in the layout,...
KoSvgText::TextAnchor anchor
qreal scaledDescent
Descender, in pt.
QPointF finalPosition
the final position, taking into account both CSS and SVG positioning considerations.
KoSvgText::FontMetrics metrics
Fontmetrics for current font, in Freetype scanline coordinates.
bool justifyAfter
Justification Opportunity follows this character.
KoSvgText::Direction direction
bool justifyBefore
Justification Opportunity precedes this character.
std::optional< qreal > tabSize
If present, this is a tab and it should align to multiples of this tabSize value.
QRectF lineHeightBox() const
lineHeightBox
qreal extraFontScaling
Freetype doesn't allow us to scale below 1pt, so we need to do an extra transformation in these cases...
bool anchored_chunk
whether this is the start of a new chunk.
QPointF dominantBaselineOffset
LineEdgeBehaviour lineEnd
void scaleCharacterResult(qreal xScale, qreal yScale)
scaleCharacterResult convenience function to scale the whole character result.
qreal scaledAscent
Ascender, in pt.
void calculateAndApplyTabsize(QPointF currentPos, bool isHorizontal, const KoSvgText::ResolutionHandler &resHandler)
bool isHorizontal
Whether the current glyph lays out horizontal or vertical. Currently same as paragraph,...
QPointF cssPosition
the position in accordance with the CSS specs, as opossed to the SVG spec.
qreal scaledHalfLeading
Leading for both sides, can be either negative or positive, in pt.
qreal fontHalfLeading
Leading for both sides, can be either negative or positive.
QRectF layoutBox() const
layoutBox
void translateOrigin(QPointF newOrigin)
translateOrigin For dominant baseline, we want to move the glyph origin. This encompassed the glyph,...
QTransform finalTransform() const
QLineF caret
Caret for this characterResult.
bool rtl
Whether the current glyph is right-to-left, as opposed to the markup.
QVector< int > graphemeIndices
The text-string indices of graphemes starting here, starting grapheme is not present.
QColor color
Which color the current position has.
QVector< QPointF > offsets
The advance offsets for each grapheme index.
int cluster
Which character result this position belongs in.
bool synthetic
Whether this position was inserted to have a visual indicator.
int index
Which grapheme this position belongs with.
int offset
Which offset this position belongs with.
QVector< QRectF > drawRects
QVector< bool > replaceWithForeGroundColor
QVector< QPainterPath > paths
The KoSvgTextContentElement struct.
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.
boost::optional< qreal > yPos
boost::optional< qreal > dxPos
boost::optional< qreal > dyPos
boost::optional< qreal > rotate
boost::optional< qreal > xPos
The FontMetrics class A class to keep track of a variety of font metrics. Note that values are in Fre...
void scaleBaselines(const qreal multiplier)
The ResolutionHandler class.
QPointF adjustCeil(const QPointF point) const
Adjusts the point to ceiled pixel values.
QPointF adjustFloor(const QPointF point) const
Adjusts the point to floored pixel values.
QPointF adjust(const QPointF point) const
Adjusts the point to rounded pixel values, based on whether roundToPixelHorizontal or roundToPixelVer...
LineBox(QVector< QLineF > lineWidths, bool ltr, QPointF indent, const KoSvgText::ResolutionHandler &resHandler)
void setCurrentChunk(LineChunk chunk)
QPointF baselineTop
Used to identify the top of the line for baseline-alignment.
void setCurrentChunkForPos(QPointF pos, bool isHorizontal)
void clearAndAdjust(bool isHorizontal, QPointF current, QPointF indent)
qreal expectedLineTop
Because fonts can affect lineheight mid-line, and this affects wrapping, this estimates the line-heig...
QVector< LineChunk > chunks
QPointF baselineBottom
Used to identify the bottom of the line for baseline-alignment.
LineBox(QPointF start, QPointF end, const KoSvgText::ResolutionHandler &resHandler)
QPointF conditionalHangEnd
QVector< int > chunkIndices
charResult indices that belong to this chunk.
QLineF length
Used to measure how long the current line is allowed to be.
KisForest< KoSvgTextContentElement >::child_iterator associatedLeaf
SubChunk(KisForest< KoSvgTextContentElement >::child_iterator leaf)
QSharedPointer< KoShapeBackground > bg
KoSvgTextProperties inheritedProps
QVector< QPair< int, int > > newToOldPositions
For transformed strings, we need to know which.