Krita Source Code Documentation
Loading...
Searching...
No Matches
SvgTextShortCuts.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-2.0-or-later
5 */
6#include "SvgTextShortCuts.h"
7#include <QAction>
9
11
16struct SvgTextShortcutInfo : public boost::equality_comparable<SvgTextShortcutInfo> {
17
21 Increase, //< Will increase by value 1.
22 Decrease //< Will decrease by value 1.
23 };
25
27 QVariant _value1, QVariant _value2, QVariant _testValue) {
29 info.propertyId = _propertyId;
30 info.type = Toggle;
31 info.value1 = _value1;
32 info.value2 = _value2;
33 info.testValue = _testValue;
34 return info;
35 }
36
37 static SvgTextShortcutInfo propertyChange(KoSvgTextProperties::PropertyId _propertyId, QVariant _value1, bool _increase) {
39 info.propertyId = _propertyId;
40 info.type = _increase? Increase: Decrease;
41 info.value1 = _value1;
42 return info;
43 }
44
45 static SvgTextShortcutInfo propertySet(KoSvgTextProperties::PropertyId _propertyId, QVariant _value1) {
47 info.propertyId = _propertyId;
48 info.type = Set;
49 info.value1 = _value1;
50 return info;
51 }
52
55 QVariant value1;
56 QVariant value2;
57 QVariant testValue;
58
59
60
61 bool operator==(const SvgTextShortcutInfo & other) const {
62 return (propertyId == other.propertyId
63 && type == other.type
64 && value1 == other.value1
65 && value2 == other.value2
66 && testValue == other.testValue);
67 }
68};
69
71
73 qRegisterMetaType<SvgTextShortcutInfo>("SvgTextShortcutInfo");
74#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
75 QMetaType::registerEqualsComparator<SvgTextShortcutInfo>();
76#endif
77}
78
79const QMap<QString, SvgTextShortcutInfo> textShortCuts = {
80 {
81 "svg_weight_bold",
83 QVariant(400), QVariant(700), QVariant(500))
84 },
85
86 {
87 "svg_weight_normal",
89 QVariant(400))
90 },
91 {
92 "svg_weight_demi",
94 QVariant(600))
95 },
96 {
97 "svg_weight_black",
99 QVariant(900))
100 },
101 {
102 "svg_weight_light",
104 QVariant(300))
105 },
106
107 {
108 "svg_format_italic",
110 QVariant::fromValue(KoSvgText::CssFontStyleData(QFont::StyleNormal)),
111 QVariant::fromValue(KoSvgText::CssFontStyleData(QFont::StyleItalic)),
112 QVariant::fromValue(KoSvgText::CssFontStyleData(QFont::StyleNormal)))
113 },
114
115 {
116 "svg_increase_font_size",
118 QVariant::fromValue(1), true)
119 },
120
121 {
122 "svg_decrease_font_size",
124 QVariant::fromValue(1), false)
125 },
126
127 {
128 "svg_format_underline",
130 QVariant(true), QVariant(false), QVariant(KoSvgText::DecorationUnderline))
131 },
132 {
133 "svg_format_strike_through",
135 QVariant(true), QVariant(false), QVariant(KoSvgText::DecorationLineThrough))
136 },
137 {
138 "svg_font_kerning",
140 QVariant(true), QVariant(false), QVariant(true))
141 },
142 {
143 "svg_align_right",
145 QVariant(KoSvgText::AlignStart))
146 },
147 {
148 "svg_align_left",
150 QVariant(KoSvgText::AlignEnd))
151 },
152 {
153 "svg_align_center",
155 QVariant(KoSvgText::AlignCenter))
156 },
157 {
158 "svg_align_justified",
160 QVariant(KoSvgText::AlignJustify))
161 },
162 {
163 "svg_format_subscript",
165 QVariant(KoSvgText::ShiftSub))
166 },
167 {
168 "svg_format_superscript",
170 QVariant(KoSvgText::ShiftSuper))
171 }
172};
173
178
179bool SvgTextShortCuts::configureAction(QAction *action, const QString &name)
180{
181 if (!textShortCuts.contains(name)) return false;
182 if (!action) return false;
183 SvgTextShortcutInfo info = textShortCuts.value(name);
184 action->setData(QVariant::fromValue(info));
185 return true;
186}
187
188bool SvgTextShortCuts::actionEnabled(QAction *action, const QList<KoSvgTextProperties> currentProperties) {
189 if (!action || !action->isCheckable() || !action->data().canConvert<SvgTextShortcutInfo>()) return false;
190 SvgTextShortcutInfo info = action->data().value<SvgTextShortcutInfo>();
191
193 return false;
194 }
195 const QVariant testValue = info.type == SvgTextShortcutInfo::Toggle? info.testValue: info.value1;
196
197 for (auto properties = currentProperties.begin(); properties != currentProperties.end(); properties++) {
198 const QVariant oldValue = properties->propertyOrDefault(info.propertyId);
199
200
201 if (oldValue.canConvert<KoSvgText::TextDecorations>() && info.propertyId == KoSvgTextProperties::TextDecorationLineId) {
202
203 const KoSvgText::TextDecorations oldDecor = oldValue.value<KoSvgText::TextDecorations>();
204 return oldDecor.testFlag(KoSvgText::TextDecoration(testValue.toInt()));
205
206 } else if (oldValue.canConvert<KoSvgText::CssFontStyleData>()) {
207 const KoSvgText::CssFontStyleData testVal = testValue.value<KoSvgText::CssFontStyleData>();
208 const KoSvgText::CssFontStyleData currentVal = oldValue.value<KoSvgText::CssFontStyleData>();
209 return (testVal.style == currentVal.style);
210 } else if (oldValue.canConvert<KoSvgText::AutoValue>()) {
211 const KoSvgText::AutoValue currentVal = oldValue.value<KoSvgText::AutoValue>();
212 if (testValue.canConvert<KoSvgText::AutoValue>()) {
213 return (testValue == oldValue);
214 } else if (testValue.canConvert<double>()) {
215 return currentVal.customValue == testValue.toDouble();
216 } else {
217 return currentVal.isAuto == testValue.toBool();
218 }
219 } else if (oldValue.canConvert<KoSvgText::CssLengthPercentage>()) {
220 const KoSvgText::CssLengthPercentage currentVal = oldValue.value<KoSvgText::CssLengthPercentage>();
221 if (testValue.canConvert<KoSvgText::CssLengthPercentage>()) {
222 return (testValue == oldValue);
223 } else {
224 return currentVal.value == testValue.toDouble();
225 }
226 } else if (oldValue.canConvert<KoSvgText::AutoLengthPercentage>()) {
227 const KoSvgText::AutoLengthPercentage currentVal = oldValue.value<KoSvgText::CssLengthPercentage>();
228 if (testValue.canConvert<KoSvgText::AutoLengthPercentage>()) {
229 return (testValue == oldValue);
230 } else if (testValue.canConvert<KoSvgText::CssLengthPercentage>()) {
231 return (testValue == QVariant::fromValue(currentVal.length));
232 } else {
233 return currentVal.length.value == testValue.toDouble();
234 }
235 } else if (oldValue.canConvert<KoSvgText::LineHeightInfo>()) {
236 const KoSvgText::LineHeightInfo currentVal = oldValue.value<KoSvgText::LineHeightInfo>();
237 if (testValue.canConvert<KoSvgText::LineHeightInfo>()) {
238 return (testValue == oldValue);
239 } else if (testValue.canConvert<KoSvgText::CssLengthPercentage>()) {
240 return (testValue == QVariant::fromValue(currentVal.length));
241 } else {
242 return currentVal.length.value == testValue.toDouble();
243 }
244 }
245 return (testValue == oldValue);
246 }
247 return false;
248}
249
256 QVariant newVal;
257 for(auto properties = currentProperties.begin(); properties != currentProperties.end(); properties++) {
258 QVariant oldValue = properties->propertyOrDefault(info.propertyId);
259
260 if (oldValue.canConvert<KoSvgText::TextDecorations>() && info.propertyId == KoSvgTextProperties::TextDecorationLineId) {
262 KoSvgText::TextDecorations oldDecor = oldValue.value<KoSvgText::TextDecorations>();
263 KoSvgText::TextDecorations newDecor;
264 newDecor.setFlag(decor, !oldDecor.testFlag(decor));
265 newVal = QVariant::fromValue(newDecor);
266 if (oldDecor.testFlag(decor)) {
267 break;
268 }
269 } else if (oldValue.canConvert<KoSvgText::CssFontStyleData>() && info.propertyId == KoSvgTextProperties::FontStyleId) {
271 KoSvgText::CssFontStyleData currentVal = oldValue.value<KoSvgText::CssFontStyleData>();
272 if (currentVal.style == testVal.style) {
273 newVal = info.value2;
274 break;
275 } else {
276 newVal = info.value1;
277 }
278 } else if (oldValue.canConvert<KoSvgText::AutoValue>() && info.propertyId == KoSvgTextProperties::KerningId) {
279 bool testVal = info.testValue.toBool();
280 KoSvgText::AutoValue currentVal = oldValue.value<KoSvgText::AutoValue>();
281 if (currentVal.isAuto == testVal) {
282 currentVal.customValue = 0.0;
283 currentVal.isAuto = info.value2.toBool();
284 newVal = QVariant::fromValue(currentVal);
285 break;
286 } else {
287 currentVal.isAuto = info.value1.toBool();
288 newVal = QVariant::fromValue(currentVal);
289 }
290 } else if (oldValue.canConvert<double>()) {
291 if (oldValue.toDouble() > info.testValue.toDouble()) {
292 newVal = info.value1;
293 break;
294 } else {
295 newVal = info.value2;
296 }
297 } else if (oldValue.canConvert<int>()) {
298 if (oldValue.toInt() > info.testValue.toInt()) {
299 newVal = info.value1;
300 break;
301 } else {
302 newVal = info.value2;
303 }
304 }
305 }
306 return newVal;
307}
308
316QVariant adjustValue(SvgTextShortcutInfo info, QVariant oldValue) {
317 QVariant newVal;
318
319 if (oldValue.canConvert<KoSvgText::CssLengthPercentage>()) {
322 length.value += info.value1.toDouble();
323 } else {
324 length.value -= info.value1.toDouble();
325 }
326 newVal = QVariant::fromValue(length);
327 } else if (oldValue.canConvert<KoSvgText::AutoLengthPercentage>()) {
329 length.isAuto = false;
331 length.length.value += info.value1.toDouble();
332 } else {
333 length.length.value -= info.value1.toDouble();
334 }
335 newVal = QVariant::fromValue(length);
336 } else if (oldValue.canConvert<KoSvgText::AutoValue>()) {
338 value.isAuto = false;
340 value.customValue += info.value1.toDouble();
341 } else {
342 value.customValue -= info.value1.toDouble();
343 }
344 newVal = QVariant::fromValue(value);
345 } else if (oldValue.canConvert<double>()) {
346 double value = oldValue.toDouble();
348 value += info.value1.toDouble();
349 } else {
350 value -= info.value1.toDouble();
351 }
352 newVal = QVariant::fromValue(value);
353 } else if (oldValue.canConvert<int>()) {
354 int value = oldValue.toInt();
356 value += info.value1.toInt();
357 } else {
358 value -= info.value1.toInt();
359 }
360 newVal = QVariant::fromValue(value);
361 }
362
363 return newVal;
364}
365
367{
368 if (!action || !action->data().canConvert<SvgTextShortcutInfo>() || currentProperties.isEmpty()) return KoSvgTextProperties();
369 SvgTextShortcutInfo info = action->data().value<SvgTextShortcutInfo>();
370
371 QVariant newVal;
372 if (info.type == SvgTextShortcutInfo::Toggle) {
373 newVal = toggleProperty(info, currentProperties);
374 } else if (info.type == SvgTextShortcutInfo::Set) {
375 KoSvgTextProperties properties = currentProperties.first();
376 QVariant oldValue = properties.propertyOrDefault(info.propertyId);
377
378 if (oldValue.canConvert<int>()) {
379 newVal = info.value1;
380 }
381 } else {
382 KoSvgTextProperties properties = currentProperties.first();
383 QVariant oldValue = properties.propertyOrDefault(info.propertyId);
384
385 newVal = adjustValue(info, oldValue);
386 }
387 KoSvgTextProperties newProperties;
388 newProperties.setProperty(info.propertyId, newVal);
389 return newProperties;
390}
qreal length(const QPointF &vec)
Definition Ellipse.cc:82
float value(const T *src, size_t ch)
QVariant toggleProperty(SvgTextShortcutInfo info, QList< KoSvgTextProperties > currentProperties)
toggleProperty Handles toggling properties for getModifiedProperties split out to make code easier to...
const QMap< QString, SvgTextShortcutInfo > textShortCuts
QVariant adjustValue(SvgTextShortcutInfo info, QVariant oldValue)
adjustValue Handles increase/decrease value for getModifiedProperties, split out to make code easier ...
KIS_DECLARE_STATIC_INITIALIZER
@ TextAlignAllId
KoSvgText::TextAlign.
@ FontStyleId
KoSvgText::CssSlantData.
@ BaselineShiftModeId
KoSvgText::BaselineShiftMode.
@ TextDecorationLineId
Flags, KoSvgText::TextDecorations.
@ KerningId
KoSvgText::AutoValue.
void setProperty(PropertyId id, const QVariant &value)
QVariant propertyOrDefault(PropertyId id) const
static bool actionEnabled(QAction *action, const QList< KoSvgTextProperties > currentProperties)
static QStringList possibleActions()
static KoSvgTextProperties getModifiedProperties(const QAction *action, QList< KoSvgTextProperties > currentProperties)
static bool configureAction(QAction *action, const QString &name)
Q_DECLARE_METATYPE(KisPaintopLodLimitations)
@ AlignCenter
Center text in line.
Definition KoSvgText.h:173
@ ShiftSuper
Use parent font metric for 'superscript'.
Definition KoSvgText.h:243
@ ShiftSub
Use parent font metric for 'subscript'.
Definition KoSvgText.h:242
TextDecoration
Flags for text-decoration, for underline, overline and strikethrough.
Definition KoSvgText.h:257
@ DecorationLineThrough
Definition KoSvgText.h:261
@ DecorationUnderline
Definition KoSvgText.h:259
CssLengthPercentage length
Definition KoSvgText.h:466
When style is oblique, a custom slant value can be specified for variable fonts.
Definition KoSvgText.h:475
CssLengthPercentage length
Definition KoSvgText.h:693
The SvgTextShortcutInfo class This.
static SvgTextShortcutInfo propertySet(KoSvgTextProperties::PropertyId _propertyId, QVariant _value1)
KoSvgTextProperties::PropertyId propertyId
static SvgTextShortcutInfo propertyChange(KoSvgTextProperties::PropertyId _propertyId, QVariant _value1, bool _increase)
@ Set
Will set value1, cannot be toggled.
@ Toggle
Toggle will test "testValue", and toggle between value1 and value 2;.
bool operator==(const SvgTextShortcutInfo &other) const
static SvgTextShortcutInfo propertyToggle(KoSvgTextProperties::PropertyId _propertyId, QVariant _value1, QVariant _value2, QVariant _testValue)