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>
11
12#include <KoSvgTextProperties.h>
14
16
17#include <kis_global.h>
18
21 , m_shape(shape)
22 , m_lastMousePos(clicked)
23{
26
29
30 const QPointF padding(shapePadding+2, shapePadding+2);
31 const QPointF margin(shapeMargin+2, shapeMargin+2);
32
33 qreal minDistance = std::numeric_limits<qreal>::max();
34 KoPathShape *candidate = nullptr;
35 bool isPadding = false;
36 Q_FOREACH(KoShape *shape, m_shape->shapesSubtract()) {
37 KoPathShape *path = dynamic_cast<KoPathShape*>(shape);
38 if (!path) continue;
39 const QPointF mp = shape->documentToShape(clicked);
40 const QRectF marginRect(mp - margin, mp + margin);
41
42 Q_FOREACH(KoPathSegment segment, path->segmentsAt(marginRect)) {
43 const qreal nearestT = segment.nearestPoint(mp);
44 const QPointF nearestP = segment.pointAt(nearestT);
45 const qreal distance = kisDistance(mp, nearestP) - shapeMargin;
46 if (distance < minDistance) {
47 candidate = path;
48 minDistance = distance;
49 }
50 }
51 }
52
53 Q_FOREACH(KoShape *shape, m_shape->shapesInside()) {
54 KoPathShape *path = dynamic_cast<KoPathShape*>(shape);
55 if (!path) continue;
56 const QPointF mp = shape->documentToShape(clicked);
57 const QRectF paddingRect(mp - padding, mp + padding);
58
59 qDebug() << "segments" << path->segmentsAt(paddingRect).size() << paddingRect;
60 Q_FOREACH(KoPathSegment segment, path->segmentsAt(paddingRect)) {
61 const qreal nearestT = segment.nearestPoint(mp);
62 const QPointF nearestP = segment.pointAt(nearestT);
63 const qreal distance = kisDistance(mp, nearestP) - shapePadding;
64 if (distance < minDistance) {
65 candidate = path;
66 minDistance = distance;
67 isPadding = true;
68 }
69 }
70 }
71
72 m_referenceShape = candidate;
73 m_isPadding = isPadding;
74}
75
80
81std::optional<QPointF> SvgChangeTextPaddingMarginStrategy::hitTest(KoSvgTextShape *shape, const QPointF &mousePos, const qreal grabSensitivityInPts)
82{
83 if (!shape) return std::nullopt;
84 const QList<QPainterPath> textAreas = shape->textWrappingAreas();
85 if (textAreas.isEmpty()) return std::nullopt;
86
87 const QPointF grab(grabSensitivityInPts, grabSensitivityInPts);
88 const QRectF grabRect(mousePos-grab, mousePos+grab);
89
90 Q_FOREACH(const QPainterPath area, shape->textWrappingAreas()) {
92 if (!s) continue;
94 KoPathSegment segment = s->segmentAtPoint(mousePos, grabRect);
95 if (segment.isValid()) {
96 qreal nearest = segment.nearestPoint(s->documentToShape(mousePos));
97 return std::make_optional(segment.angleVectorAtParam(nearest));
98 }
99 }
100
101 return std::nullopt;
102}
103
104QLineF getLine(QPointF mousePos, KoPathShape *referenceShape, bool isPadding) {
105 if (!referenceShape) return QLineF();
106 const bool hit = referenceShape->hitTest(mousePos);
107 if ((!hit && isPadding) || (hit && !isPadding)) return QLineF();
108
109 QPointF pos = referenceShape->documentToShape(mousePos);
110 QLineF l(pos, pos);
111
112 qreal minDistance = std::numeric_limits<qreal>::max();
113
114 Q_FOREACH(KoPathSegment segment, referenceShape->segmentsAt(referenceShape->outlineRect().adjusted(-2, -2, 2, 2))) {
115 const qreal nearestT = segment.nearestPoint(pos);
116 const QPointF nearestP = segment.pointAt(nearestT);
117 const qreal distance = kisDistance(pos, nearestP);
118 if (distance < minDistance) {
119 l.setP1(nearestP);
120 minDistance = distance;
121 }
122 }
123 if (l.length() < 0) {
124 l.setLength(0);
125 }
126 return l;
127}
128
132 length.value = line.length();
133 previous.setProperty(propId, QVariant::fromValue(length));
134 return previous;
135}
136
137void SvgChangeTextPaddingMarginStrategy::paint(QPainter &painter, const KoViewConverter &converter)
138{
139 if (!(m_referenceShape && m_shape)) return;
140 painter.save();
141 KisHandlePainterHelper handlePainter =
144
145 const QLineF line = getLine(m_lastMousePos, m_referenceShape, m_isPadding);
146 const QTransform lineTf = m_referenceShape->absoluteTransformation() * m_shape->absoluteTransformation().inverted();
147 handlePainter.drawConnectionLine(lineTf.map(line));
148
151 Q_FOREACH(QPainterPath area, areas) {
152 handlePainter.drawPath(area);
153 }
154
155 painter.restore();
156}
157
158void SvgChangeTextPaddingMarginStrategy::handleMouseMove(const QPointF &mouseLocation, Qt::KeyboardModifiers modifiers)
159{
160 Q_UNUSED(modifiers);
161 m_lastMousePos = mouseLocation;
162}
163
171
172void SvgChangeTextPaddingMarginStrategy::finishInteraction(Qt::KeyboardModifiers modifiers)
173{
174 Q_UNUSED(modifiers);
175}
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()
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:1016
QTransform absoluteTransformation() const
Definition KoShape.cpp:335
void setTransformation(const QTransform &matrix)
Definition KoShape.cpp:374
static KisHandlePainterHelper createHandlePainterHelperView(QPainter *painter, KoShape *shape, const KoViewConverter &converter, qreal handleRadius=0.0, int decorationThickness=1)
Definition KoShape.cpp:982
static const KoSvgTextProperties & defaultProperties()
QVariant propertyOrDefault(PropertyId id) const
void inheritFrom(const KoSvgTextProperties &parentProperties, bool resolve=false)
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 paint(QPainter &painter, const KoViewConverter &converter) override
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 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