Krita Source Code Documentation
Loading...
Searching...
No Matches
KisPredefinedBrushModel.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2022 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
7
10#include <lager/lenses/tuple.hpp>
11#include <KisZug.h>
12#include <KisLager.h>
13
14namespace {
15
16auto brushSizeLens = lager::lenses::getset(
17 [](const std::tuple<QSize, qreal> &x) -> qreal { return std::get<0>(x).width() * std::get<1>(x); },
18 [](std::tuple<QSize, qreal> x, qreal brushSize) -> std::tuple<QSize, qreal> {
19 return std::make_tuple(std::get<0>(x), brushSize / std::get<0>(x).width());
20 });
21
22ComboBoxState calcApplicationSwitchState(enumBrushType brushType, bool supportsHSLBrushTips, enumBrushApplication application)
23{
24 QStringList values;
25 QStringList toolTips;
26 values << i18n("Alpha mask");
27 toolTips << i18nc("@info:tooltip", "Luminosity of the brush tip image is used as alpha channel for the stroke");
28 if (brushType == IMAGE || brushType == PIPE_IMAGE) {
29 values << i18n("Color image");
30 toolTips << i18nc("@info:tooltip", "The brush tip image is painted as it is");
31 if (supportsHSLBrushTips) {
32 values << i18n("Lightness map");
33 toolTips << i18nc("@info:tooltip", "Luminosity of the brush tip image is used as lightness correction for the painting color. Alpha channel of the brush tip image is used as alpha for the final stroke");
34 values << i18n("Gradient map");
35 toolTips << i18nc("@info:tooltip", "The brush tip maps its value to the currently selected gradient. Alpha channel of the brush tip image is used as alpha for the final stroke");
36 }
37 }
38
39
40 int currentValue = std::clamp((int)application, 0, (int)values.size() - 1);
41 return ComboBoxState{values, currentValue, values.size() > 1, toolTips};
42}
43
44QString calcBrushDetails(PredefinedBrushData data)
45{
46 QString brushTypeString = "";
47
48 QString animatedBrushTipSelectionMode;
49
50 if (data.brushType == INVALID) {
51 brushTypeString = i18n("Invalid");
52 } else if (data.brushType == MASK) {
53 brushTypeString = i18n("Mask");
54 } else if (data.brushType == IMAGE) {
55 brushTypeString = i18n("Image");
56 } else if (data.brushType == PIPE_MASK ) {
57 brushTypeString = i18n("Animated mask"); // GIH brush
58 animatedBrushTipSelectionMode = data.parasiteSelection;
59 } else if (data.brushType == PIPE_IMAGE ) {
60 brushTypeString = i18n("Animated image");
61 }
62
63 const QString brushDetailsText = QString("%1 (%2 × %3) %4")
64 .arg(brushTypeString)
65 .arg(data.baseSize.width())
66 .arg(data.baseSize.height())
67 .arg(animatedBrushTipSelectionMode);
68
69 return brushDetailsText;
70}
71
72auto effectiveResourceData = lager::lenses::getset(
73 [](const PredefinedBrushData &predefinedDataArg) {
74 if (predefinedDataArg.resourceSignature != KoResourceSignature()) {
75 return predefinedDataArg;
76 }
77
78 CommonData commonData;
79
82 PredefinedBrushData predefinedData = predefinedDataArg;
83
85
86 KisBrushSP fallbackResource = source.fallbackResource();
87 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(fallbackResource, predefinedData);
88
89 KisPredefinedBrushFactory::loadFromBrushResource(commonData, predefinedData, fallbackResource);
90
96
97 return predefinedData;
98 },
99 [](const PredefinedBrushData&,
100 const PredefinedBrushData &y) {
101
102 return y;
103 });
104
105} // namespace
106
107
108KisPredefinedBrushModel::KisPredefinedBrushModel(lager::cursor<CommonData> commonData,
109 lager::cursor<PredefinedBrushData> predefinedBrushData,
110 lager::cursor<qreal> commonBrushSizeData,
111 bool supportsHSLBrushTips)
112 : m_commonData(commonData),
113 m_predefinedBrushData(predefinedBrushData),
114 m_supportsHSLBrushTips(supportsHSLBrushTips),
115 m_commonBrushSizeData(commonBrushSizeData),
116 m_effectivePredefinedData(m_predefinedBrushData.zoom(effectiveResourceData)),
118 LAGER_QT(baseSize) {m_effectivePredefinedData[&PredefinedBrushData::baseSize]},
119 LAGER_QT(brushSize) {m_commonBrushSizeData},
120 LAGER_QT(application) {m_effectivePredefinedData[&PredefinedBrushData::application]
121 .zoom(kislager::lenses::do_static_cast<enumBrushApplication, int>)},
122 LAGER_QT(hasColorAndTransparency) {m_effectivePredefinedData[&PredefinedBrushData::hasColorAndTransparency]},
123 LAGER_QT(autoAdjustMidPoint) {m_effectivePredefinedData[&PredefinedBrushData::autoAdjustMidPoint]},
124 LAGER_QT(adjustmentMidPoint) {m_effectivePredefinedData[&PredefinedBrushData::adjustmentMidPoint]
125 .zoom(kislager::lenses::do_static_cast<quint8, int>)},
126 LAGER_QT(brightnessAdjustment) {m_effectivePredefinedData[&PredefinedBrushData::brightnessAdjustment]
127 .xform(kiszug::map_multiply<qreal>(100.0) | kiszug::map_round,
128 kiszug::map_static_cast<qreal> | kiszug::map_multiply<qreal>(0.01))},
129 LAGER_QT(contrastAdjustment) {m_effectivePredefinedData[&PredefinedBrushData::contrastAdjustment]
130 .xform(kiszug::map_multiply<qreal>(100.0) | kiszug::map_round,
131 kiszug::map_static_cast<qreal> | kiszug::map_multiply<qreal>(0.01))},
132 LAGER_QT(angle) {m_commonData[&CommonData::angle]
133 .zoom(kislager::lenses::scale<qreal>(180.0 / M_PI))},
134 LAGER_QT(spacing) {m_commonData[&CommonData::spacing]},
135 LAGER_QT(useAutoSpacing) {m_commonData[&CommonData::useAutoSpacing]},
136 LAGER_QT(autoSpacingCoeff) {m_commonData[&CommonData::autoSpacingCoeff]},
137 LAGER_QT(aggregatedSpacing) {lager::with(LAGER_QT(spacing),
138 LAGER_QT(useAutoSpacing),
139 LAGER_QT(autoSpacingCoeff))
140 .xform(zug::map(ToSpacingState{}),
141 zug::map(FromSpacingState{}))},
142 LAGER_QT(applicationSwitchState){lager::with(
143 m_effectivePredefinedData[&PredefinedBrushData::brushType],
144 m_supportsHSLBrushTips,
145 m_effectivePredefinedData[&PredefinedBrushData::application])
146 .xform(zug::map(&calcApplicationSwitchState))},
147 LAGER_QT(adjustmentsEnabled){LAGER_QT(applicationSwitchState)[&ComboBoxState::currentIndex]
148 .xform(kiszug::map_greater<int>(1))},
149 LAGER_QT(brushName) {LAGER_QT(resourceSignature)[&KoResourceSignature::name]},
150 LAGER_QT(brushDetails) {m_effectivePredefinedData.map(&calcBrushDetails)},
151 LAGER_QT(lightnessModeEnabled)
152 {LAGER_QT(applicationSwitchState)
154 xform(kiszug::map_equal<int>(LIGHTNESSMAP))}
155{
156}
157
158
160{
162 data.application =
163 static_cast<enumBrushApplication>(
164 LAGER_QT(applicationSwitchState)->currentIndex);
165 data.scale = m_commonBrushSizeData.get() / data.baseSize.width();
166
167 return data;
168
169}
170
172{
173 return static_cast<enumBrushApplication>(calcApplicationSwitchState(predefinedData.brushType, supportsHSLBrushTips, predefinedData.application).currentIndex);
174}
175
177{
178 return lager::view(brushSizeLens, std::make_tuple(predefinedData.baseSize, predefinedData.scale));
179}
180
182{
183 std::tie(predefinedData.baseSize, predefinedData.scale) =
184 lager::set(brushSizeLens, std::make_tuple(predefinedData.baseSize, predefinedData.scale), value);
185}
LAGER_QT(value)
float value(const T *src, size_t ch)
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
LAGER_QT(baseSize)
static KisResourcesInterfaceSP instance()
static void loadFromBrushResource(KisBrushModel::CommonData &commonData, KisBrushModel::PredefinedBrushData &predefinedBrushData, KisBrushSP brushResource)
static qreal effectiveBrushSize(PredefinedBrushData predefinedData)
lager::cursor< qreal > m_commonBrushSizeData
PredefinedBrushData bakedOptionData() const
KisPredefinedBrushModel(lager::cursor< CommonData > commonData, lager::cursor< PredefinedBrushData > predefinedBrushData, lager::cursor< qreal > commonBrushSizeData, bool supportsHSLBrushTips)
static enumBrushApplication effectiveBrushApplication(PredefinedBrushData predefinedData, bool supportsHSLBrushTips)
static void setEffectiveBrushSize(PredefinedBrushData &predefinedData, qreal value)
lager::cursor< PredefinedBrushData > m_effectivePredefinedData
A simple wrapper object for the main information about the resource.
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
enumBrushType
Definition kis_brush.h:30
@ IMAGE
Definition kis_brush.h:33
@ PIPE_IMAGE
Definition kis_brush.h:35
@ PIPE_MASK
Definition kis_brush.h:34
@ MASK
Definition kis_brush.h:32
@ INVALID
Definition kis_brush.h:31
enumBrushApplication
Definition kis_brush.h:38
@ LIGHTNESSMAP
Definition kis_brush.h:41
#define M_PI
Definition kis_global.h:111
const QString Brushes
constexpr auto map_round
Definition KisZug.h:64
KoResourceSignature resourceSignature