Krita Source Code Documentation
Loading...
Searching...
No Matches
SvgChangeTextPaddingMarginStrategy.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
7
8#include "SvgTextTool.h"
9#include <KoPathShape.h>
10#include <KoPathSegment.h>
12
13#include <KoSvgTextProperties.h>
15
17
18#include <kis_global.h>
19
22 , m_shape(shape)
23 , m_lastMousePos(clicked)
24{
27
30
31 const QPointF padding(shapePadding+2, shapePadding+2);
32 const QPointF margin(shapeMargin+2, shapeMargin+2);
33
34 qreal minDistance = std::numeric_limits<qreal>::max();
35 KoPathShape *candidate = nullptr;
36 bool isPadding = false;
37 Q_FOREACH(KoShape *shape, m_shape->shapesSubtract()) {
38 KoPathShape *path = dynamic_cast<KoPathShape*>(shape);
39 if (!path) continue;
40 const QPointF mp = shape->documentToShape(clicked);
41 const QRectF marginRect(mp - margin, mp + margin);
42
43 Q_FOREACH(KoPathSegment segment, path->segmentsAt(marginRect)) {
44 const qreal nearestT = segment.nearestPoint(mp);
45 const QPointF nearestP = segment.pointAt(nearestT);
46 const qreal distance = kisDistance(mp, nearestP) - shapeMargin;
47 if (distance < minDistance) {
48 candidate = path;
49 minDistance = distance;
50 }
51 }
52 }
53
54 Q_FOREACH(KoShape *shape, m_shape->shapesInside()) {
55 KoPathShape *path = dynamic_cast<KoPathShape*>(shape);
56 if (!path) continue;
57 const QPointF mp = shape->documentToShape(clicked);
58 const QRectF paddingRect(mp - padding, mp + padding);
59
60 qDebug() << "segments" << path->segmentsAt(paddingRect).size() << paddingRect;
61 Q_FOREACH(KoPathSegment segment, path->segmentsAt(paddingRect)) {
62 const qreal nearestT = segment.nearestPoint(mp);
63 const QPointF nearestP = segment.pointAt(nearestT);
64 const qreal distance = kisDistance(mp, nearestP) - shapePadding;
65 if (distance < minDistance) {
66 candidate = path;
67 minDistance = distance;
68 isPadding = true;
69 }
70 }
71 }
72
73 m_referenceShape = candidate;
74 m_isPadding = isPadding;
75}
76
81
82std::optional<QPointF> SvgChangeTextPaddingMarginStrategy::hitTest(KoSvgTextShape *shape, const QPointF &mousePos, const qreal grabSensitivityInPts)
83{
84 if (!shape) return std::nullopt;
85 const QList<QPainterPath> textAreas = shape->textWrappingAreas();
86 if (textAreas.isEmpty()) return std::nullopt;
87
88 const QPointF grab(grabSensitivityInPts, grabSensitivityInPts);
89 const QRectF grabRect(mousePos-grab, mousePos+grab);
90
91 Q_FOREACH(const QPainterPath area, shape->textWrappingAreas()) {
93 if (!s) continue;
95 KoPathSegment segment = s->segmentAtPoint(mousePos, grabRect);
96 if (segment.isValid()) {
97 qreal nearest = segment.nearestPoint(s->documentToShape(mousePos));
98 return std::make_optional(segment.angleVectorAtParam(nearest));
99 }
100 }
101
102 return std::nullopt;
103}
104
105QLineF getLine(QPointF mousePos, KoPathShape *referenceShape, bool isPadding) {
106 if (!referenceShape) return QLineF();
107 const bool hit = referenceShape->hitTest(mousePos);
108 if ((!hit && isPadding) || (hit && !isPadding)) return QLineF();
109
110 QPointF pos = referenceShape->documentToShape(mousePos);
111 QLineF l(pos, pos);
112
113 qreal minDistance = std::numeric_limits<qreal>::max();
114
115 Q_FOREACH(KoPathSegment segment, referenceShape->segmentsAt(referenceShape->outlineRect().adjusted(-2, -2, 2, 2))) {
116 const qreal nearestT = segment.nearestPoint(pos);
117 const QPointF nearestP = segment.pointAt(nearestT);
118 const qreal distance = kisDistance(pos, nearestP);
119 if (distance < minDistance) {
120 l.setP1(nearestP);
121 minDistance = distance;
122 }
123 }
124 if (l.length() < 0) {
125 l.setLength(0);
126 }
127 return l;
128}
129
133 length.value = line.length();
134 previous.setProperty(propId, QVariant::fromValue(length));
135 return previous;
136}
137
138void SvgChangeTextPaddingMarginStrategy::paint(QPainter &painter, const KoViewConverter &converter, const KoColorDisplayRendererInterface *displayRendererInterface)
139{
140 if (!(m_referenceShape && m_shape)) return;
141 painter.save();
142 KisHandlePainterHelper handlePainter =
145
146
147 const QLineF line = getLine(m_lastMousePos, m_referenceShape, m_isPadding);
148 const QTransform lineTf = m_referenceShape->absoluteTransformation() * m_shape->absoluteTransformation().inverted();
149 handlePainter.drawConnectionLine(lineTf.map(line));
150
153 Q_FOREACH(QPainterPath area, areas) {
154 handlePainter.drawPath(area);
155 }
156
157 painter.restore();
158}
159
160void SvgChangeTextPaddingMarginStrategy::handleMouseMove(const QPointF &mouseLocation, Qt::KeyboardModifiers modifiers)
161{
162 Q_UNUSED(modifiers);
163 m_lastMousePos = mouseLocation;
164}
165
173
174void SvgChangeTextPaddingMarginStrategy::finishInteraction(Qt::KeyboardModifiers modifiers)
175{
176 Q_UNUSED(modifiers);
177}
qreal length(const QPointF &vec)
Definition Ellipse.cc:82
float value(const T *src, size_t ch)
qreal distance(const QPointF &p1, const QPointF &p2)
QLineF getLine(QPointF mousePos, KoPathShape *referenceShape, bool isPadding)
KoSvgTextProperties getProperties(bool isPadding, QLineF line, KoSvgTextProperties previous=KoSvgTextProperties())
The KisHandlePainterHelper class is a special helper for painting handles around objects....
void drawPath(const QPainterPath &path)
void drawConnectionLine(const QLineF &line)
void setHandleStyle(const KisHandleStyle &style)
static KisHandleStyle & selectedPrimaryHandles(KisHandlePalette palette=KisHandlePalette())
virtual KisHandlePalette handlePaletteForDisplayColorSpace() const =0
handlePaletteForDisplayColorSpace
uint handleRadius() const
Convenience function to get the global handle radius.
A KoPathSegment consist of two neighboring KoPathPoints.
QPointF pointAt(qreal t) const
Returns point at given t.
QPointF angleVectorAtParam(qreal t)
angleVectorAtParam Calculates the angle vector at t.
qreal nearestPoint(const QPointF &point) const
bool isValid() const
Returns if segment is valid, e.g. has two valid points.
The position of a path point within a path shape.
Definition KoPathShape.h:63
KoPathSegment segmentAtPoint(const QPointF &point, const QRectF &grabRoi) const
bool hitTest(const QPointF &position) const override
reimplemented
QRectF outlineRect() const override
reimplemented
QList< KoPathSegment > segmentsAt(const QRectF &rect) const
Returns the list of path segments within the given rectangle.
static KoPathShape * createShapeFromPainterPath(const QPainterPath &path)
Creates path shape from given QPainterPath.
QPointF documentToShape(const QPointF &point) const
Transforms point from document coordinates to shape coordinates.
Definition KoShape.cpp:1011
QTransform absoluteTransformation() const
Definition KoShape.cpp:330
void setTransformation(const QTransform &matrix)
Definition KoShape.cpp:369
static KisHandlePainterHelper createHandlePainterHelperView(QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius=0.0, int decorationThickness=1)
Definition KoShape.cpp:977
static const KoSvgTextProperties & defaultProperties()
void inheritFrom(const KoSvgTextProperties &parentProperties, bool resolve=false, bool onlyFontAndLineHeight=false)
QVariant propertyOrDefault(PropertyId id) const
QList< QPainterPath > textWrappingAreas() const
textWrappingAreas The text wrapping areas are computed from shapesInside() and shapesSubtract(),...
QList< KoShape * > shapesInside
QList< KoShape * > shapesSubtract
static QList< QPainterPath > generateTextAreas(const QList< KoShape * > shapesInside, const QList< KoShape * > shapesSubtract, const KoSvgTextProperties &props)
generateTextAreas Generates text areas with the given shapes and properties. This is used to paint pr...
KoSvgTextProperties textProperties() const
void handleMouseMove(const QPointF &mouseLocation, Qt::KeyboardModifiers modifiers) override
static std::optional< QPointF > hitTest(KoSvgTextShape *shape, const QPointF &mousePos, const qreal grabSensitivityInPts)
hitTest Tests whether the current mouse position is over a text wrapping area, and if so,...
SvgChangeTextPaddingMarginStrategy(SvgTextTool *tool, KoSvgTextShape *shape, const QPointF &clicked)
void paint(QPainter &painter, const KoViewConverter &converter, const KoColorDisplayRendererInterface *displayRendererInterface) override
void finishInteraction(Qt::KeyboardModifiers modifiers) override
The SvgTextMergePropertiesRangeCommand class This sets properties on a specific range in a single tex...
qreal kisDistance(const QPointF &pt1, const QPointF &pt2)
Definition kis_global.h:190