Krita Source Code Documentation
Loading...
Searching...
No Matches
SvgCreateTextStrategy.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2023 Alvin Wong <alvin@alvinhc.com>
3 *
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
8#include "SvgTextTool.h"
9
10#include <KoFontRegistry.h>
11
13#include "KoCanvasBase.h"
14#include "KoProperties.h"
15#include "KoSelection.h"
16#include "KoShapeController.h"
17#include "KoShapeFactoryBase.h"
18#include "KoShapeRegistry.h"
19#include "KoToolBase.h"
20#include "KoViewConverter.h"
21#include "KoSnapGuide.h"
23#include "kis_global.h"
24#include "kundo2command.h"
25
28 , m_dragStart(clicked)
29 , m_dragEnd(clicked)
30{
31 KoSvgTextProperties properties = tool->propertiesForNewText();
33 const KoSvgText::FontMetrics fontMetrics = properties.metrics(true);
34 const qreal ftMultiplier = properties.fontSize().value / fontMetrics.fontSize;
35 const double lineHeight = (fontMetrics.lineGap+fontMetrics.ascender+fontMetrics.descender)*ftMultiplier;
36 m_minSizeInline = {lineHeight, lineHeight};
37}
38
39void SvgCreateTextStrategy::paint(QPainter &painter, const KoViewConverter &converter)
40{
41 const QTransform originalPainterTransform = painter.transform();
42 painter.setTransform(converter.documentToView(), true);
43 KisHandlePainterHelper handlePainter(&painter, originalPainterTransform, 0.0, decorationThickness());
44
45 const QPolygonF poly(QRectF(m_dragStart, m_dragEnd));
47 handlePainter.drawRubberLine(poly);
48}
49
50void SvgCreateTextStrategy::handleMouseMove(const QPointF &mouseLocation, Qt::KeyboardModifiers modifiers)
51{
52 m_dragEnd = this->tool()->canvas()->snapGuide()->snap(mouseLocation, modifiers);
53 m_modifiers = modifiers;
54 const QRectF updateRect = QRectF(m_dragStart, m_dragEnd).normalized();
55 tool()->canvas()->updateCanvas(kisGrowRect(updateRect, 100));
56}
57
59{
60 SvgTextTool *const tool = qobject_cast<SvgTextTool *>(this->tool());
61
62 QRectF rectangle = QRectF(m_dragStart, m_dragEnd).normalized();
63
64 KoSvgTextProperties properties = tool->propertiesForNewText();
65 KoSvgTextProperties resolvedProperties = properties;
66 resolvedProperties.inheritFrom(KoSvgTextProperties::defaultProperties(), true);
67
68 const KoSvgText::FontMetrics fontMetrics = properties.metrics(true);
69 const qreal ftMultiplier = resolvedProperties.fontSize().value / fontMetrics.fontSize;
70 double ascender = fontMetrics.ascender;
71 ascender += fontMetrics.lineGap/2;
72 ascender *= ftMultiplier;
73 const double lineHeight = m_minSizeInline.width();
75
76 bool unwrappedText = m_modifiers.testFlag(Qt::ControlModifier);
77 if (rectangle.width() < m_minSizeInline.width() && rectangle.height() < m_minSizeInline.height()) {
78 unwrappedText = true;
79 }
80 if (!unwrappedText) {
82 val.isAuto = false;
83 val.customValue = writingMode == KoSvgText::HorizontalTB? rectangle.width(): rectangle.height();
84 properties.setProperty(KoSvgTextProperties::InlineSizeId, QVariant::fromValue(val));
85 }
86 if (writingMode != KoSvgText::HorizontalTB) {
88 }
89 // Ensure white space is set to pre-wrap if unspecified.
92 }
95 }
96
97 KoShapeFactoryBase *factory = KoShapeRegistry::instance()->value("KoSvgTextShapeID");
98 KoProperties *params = new KoProperties();//Fill these with "svgText", "defs" and "shapeRect"
99 params->setProperty("defs", QVariant(tool->generateDefs(properties)));
100
101 QPointF origin = rectangle.topLeft();
102
103 {
106
107 if (writingMode == KoSvgText::HorizontalTB) {
108 origin.setY(rectangle.top() + ascender);
109 if (halign == KoSvgText::AnchorMiddle) {
110 origin.setX(rectangle.center().x());
111 } else if ((halign == KoSvgText::AnchorEnd && !isRtl) || (halign == KoSvgText::AnchorStart && isRtl)) {
112 origin.setX(rectangle.right());
113 }
114 } else {
115 if (writingMode == KoSvgText::VerticalRL) {
116 origin.setX(rectangle.right() - (lineHeight*0.5));
117 } else {
118 origin.setX(rectangle.left() + (lineHeight*0.5));
119 }
120
121 if (halign == KoSvgText::AnchorMiddle) {
122 origin.setY(rectangle.center().y());
123 } else if (halign == KoSvgText::AnchorEnd) {
124 origin.setY(rectangle.bottom());
125 }
126 }
127 }
128 if (!rectangle.contains(origin) && unwrappedText) {
129 origin = writingMode == KoSvgText::HorizontalTB? QPointF(origin.x(), rectangle.bottom()): QPointF(rectangle.center().x(), origin.y());
130 }
131 params->setProperty("shapeRect", QVariant(rectangle));
132 params->setProperty("origin", QVariant(origin));
133
134 KoShape *textShape = factory->createShape( params, tool->canvas()->shapeController()->resourceManager());
135
136 KUndo2Command *parentCommand = new KUndo2Command();
137
138 new KoKeepShapesSelectedCommand(tool->koSelection()->selectedShapes(), {}, tool->canvas()->selectedShapesProxy(), false, parentCommand);
139
140 KUndo2Command *cmd = tool->canvas()->shapeController()->addShape(textShape, 0, parentCommand);
141 parentCommand->setText(cmd->text());
142
143 new KoKeepShapesSelectedCommand({}, {textShape}, tool->canvas()->selectedShapesProxy(), true, parentCommand);
144 tool->canvas()->snapGuide()->reset();
145
146 return parentCommand;
147}
148
150{
151 tool()->canvas()->snapGuide()->reset();
152 const QRectF updateRect = QRectF(m_dragStart, m_dragEnd).normalized();
153 tool()->canvas()->updateCanvas(updateRect);
154}
155
156void SvgCreateTextStrategy::finishInteraction(Qt::KeyboardModifiers modifiers)
157{
158 m_modifiers = modifiers;
159}
160
162{
163 QRectF rectangle = QRectF(m_dragStart, m_dragEnd).normalized();
164 return (rectangle.width() >= m_minSizeInline.width() || rectangle.height() >= m_minSizeInline.height()) && !m_modifiers.testFlag(Qt::ControlModifier);
165}
void setText(const KUndo2MagicString &text)
KUndo2MagicString text() const
The KisHandlePainterHelper class is a special helper for painting handles around objects....
void setHandleStyle(const KisHandleStyle &style)
void drawRubberLine(const QPolygonF &poly)
static KisHandleStyle & primarySelection()
KoSnapGuide * snapGuide
QPointer< KoShapeController > shapeController
virtual void updateCanvas(const QRectF &rc)=0
virtual KoSelectedShapesProxy * selectedShapesProxy() const =0
selectedShapesProxy() is a special interface for keeping a persistent connections to selectionChanged...
const T value(const QString &id) const
void setProperty(const QString &name, const QVariant &value)
virtual KoShape * createShape(const KoProperties *params, KoDocumentResourceManager *documentResources=0) const
static KoShapeRegistry * instance()
void reset()
Resets the snap guide.
QPointF snap(const QPointF &mousePosition, Qt::KeyboardModifiers modifiers)
snaps the mouse position, returns if mouse was snapped
@ TextAnchorId
KoSvgText::TextAnchor.
@ InlineSizeId
KoSvgText::AutoValue.
@ TextOrientationId
KoSvgText::TextOrientation.
@ TextCollapseId
KoSvgText::TextSpaceCollapse.
@ WritingModeId
KoSvgText::WritingMode.
@ DirectionId
KoSvgText::Direction.
@ TextWrapId
KoSvgText::TextWrap.
static const KoSvgTextProperties & defaultProperties()
bool hasProperty(PropertyId id) const
void setProperty(PropertyId id, const QVariant &value)
KoSvgText::FontMetrics metrics(const bool withResolvedLineHeight=true) const
metrics Return the metrics of the first available font.
QVariant propertyOrDefault(PropertyId id) const
KoSvgText::CssLengthPercentage fontSize() const
void inheritFrom(const KoSvgTextProperties &parentProperties, bool resolve=false)
KoCanvasBase * canvas() const
Returns the canvas the tool is working on.
virtual QPointF documentToView(const QPointF &documentPoint) const
void handleMouseMove(const QPointF &mouseLocation, Qt::KeyboardModifiers modifiers) override
KUndo2Command * createCommand() override
Qt::KeyboardModifiers m_modifiers
void finishInteraction(Qt::KeyboardModifiers modifiers) override
SvgCreateTextStrategy(SvgTextTool *tool, const QPointF &clicked)
void paint(QPainter &painter, const KoViewConverter &converter) override
T kisGrowRect(const T &rect, U offset)
Definition kis_global.h:186
TextAnchor
Where the text is anchored for SVG 1.1 text and 'inline-size'.
Definition KoSvgText.h:79
@ AnchorEnd
Anchor right for LTR, left for RTL.
Definition KoSvgText.h:82
@ AnchorStart
Anchor left for LTR, right for RTL.
Definition KoSvgText.h:80
@ AnchorMiddle
Anchor to the middle.
Definition KoSvgText.h:81
Direction
Base direction used by Bidi algorithm.
Definition KoSvgText.h:48
@ DirectionRightToLeft
Definition KoSvgText.h:50
@ HorizontalTB
Definition KoSvgText.h:38
@ OrientationUpright
Set all characters upright.
Definition KoSvgText.h:73
@ Preserve
Do not collapse any space.
Definition KoSvgText.h:99
The FontMetrics class A class to keep track of a variety of font metrics. Note that values are in Fre...
Definition KoSvgText.h:327
qint32 lineGap
additional linegap between consecutive lines.
Definition KoSvgText.h:341
qint32 fontSize
Currently set size, CSS unit 'em'.
Definition KoSvgText.h:329
qint32 descender
distance for origin to bottom.
Definition KoSvgText.h:340
qint32 ascender
distance from origin to top.
Definition KoSvgText.h:339