Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_paint_device_data.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com>
3 * SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8#ifndef __KIS_PAINT_DEVICE_DATA_H
9#define __KIS_PAINT_DEVICE_DATA_H
10
11#include "KisInterstrokeData.h"
13#include "KoAlwaysInline.h"
14#include "kis_command_utils.h"
15#include "kundo2command.h"
16
19 : m_dataManager(dataManager),
20 m_completionListener(completionListener){}
21
22
24 const int xOffset = 0;
25 const int yOffset = 0;
26 return new KisHLineIterator2(m_dataManager, rect.x(), rect.y(), rect.width(), xOffset, yOffset, false, m_completionListener);
27 }
28
30 const int xOffset = 0;
31 const int yOffset = 0;
32 return new KisHLineIterator2(m_dataManager, rect.x(), rect.y(), rect.width(), xOffset, yOffset, true, m_completionListener);
33 }
34
35 int pixelSize() const {
36 return m_dataManager->pixelSize();
37 }
38
41};
42
44
46{
47public:
49 : m_cache(paintDevice),
50 m_x(0), m_y(0),
51 m_colorSpace(0),
54 {
55 }
56
57 KisPaintDeviceData(KisPaintDevice *paintDevice, const KisPaintDeviceData *rhs, bool cloneContent)
58 : m_dataManager(cloneContent ?
59 new KisDataManager(*rhs->m_dataManager) :
60 new KisDataManager(rhs->m_dataManager->pixelSize(), rhs->m_dataManager->defaultPixel())),
61 m_cache(paintDevice),
62 m_x(rhs->m_x),
63 m_y(rhs->m_y),
67 {
69 // WARNING: interstroke data is **not** copied while cloning, that is expected behavior!
70 }
71
77
79 public:
81 const KoColorSpace *oldCs, const KoColorSpace *newCs,
82 KUndo2Command *parent)
83 : KUndo2Command(parent),
84 m_data(data),
85 m_oldCs(oldCs),
86 m_newCs(newCs)
87 {
88 Q_UNUSED(m_firstRun);
89 }
90
91 void redo() override {
93
96 }
97
98 void undo() override {
101
103 }
104
105 protected:
107
108 private:
109 bool m_firstRun {true};
112 };
113
114
116 public:
119 const KoColorSpace *oldCs, const KoColorSpace *newCs,
120 KUndo2Command *parent)
121 : ChangeProfileCommand(data, oldCs, newCs, parent),
122 m_oldDm(oldDm),
123 m_newDm(newDm)
124 {
125 }
126
127 void redo() override {
130 }
131
132 void undo() override {
135 }
136
137 private:
140 };
141
142 void assignColorSpace(const KoColorSpace *dstColorSpace, KUndo2Command *parentCommand) {
143 if (*m_colorSpace->profile() == *dstColorSpace->profile()) return;
144
146
148 new ChangeProfileCommand(this,
149 m_colorSpace, dstColorSpace,
150 parentCommand);
151
152 // NOTE: first redo is skipped on a higher level,
153 // at DeviceChangeColorSpaceCommand
154 cmd->redo();
155
156 if (!parentCommand) {
157 delete cmd;
158 }
159 }
160
161 void convertDataColorSpace(const KoColorSpace *dstColorSpace,
163 KoColorConversionTransformation::ConversionFlags conversionFlags,
164 KUndo2Command *parentCommand,
165 KoUpdater *updater = nullptr)
166 {
167 using InternalSequentialConstIterator =
169 using InternalSequentialIterator =
171
172 if (m_colorSpace == dstColorSpace || *m_colorSpace == *dstColorSpace) {
173 return;
174 }
175
176 QRect rc = m_dataManager->region().boundingRect();
177
178 const int dstPixelSize = dstColorSpace->pixelSize();
179 QScopedArrayPointer<quint8> dstDefaultPixel(new quint8[dstPixelSize]);
180 memset(dstDefaultPixel.data(), 0, dstPixelSize);
181 m_colorSpace->convertPixelsTo(m_dataManager->defaultPixel(), dstDefaultPixel.data(), dstColorSpace, 1, renderingIntent, conversionFlags);
182
183 KisDataManagerSP dstDataManager = new KisDataManager(dstPixelSize, dstDefaultPixel.data());
184
185
186 if (!rc.isEmpty()) {
187 InternalSequentialConstIterator srcIt(DirectDataAccessPolicy(m_dataManager.data(), cacheInvalidator()), rc, updater);
188 InternalSequentialIterator dstIt(DirectDataAccessPolicy(dstDataManager.data(), cacheInvalidator()), rc, updater);
189
190 int nConseqPixels = srcIt.nConseqPixels();
191
192 // since we are accessing data managers directly, the columns are always aligned
193 KIS_SAFE_ASSERT_RECOVER_NOOP(srcIt.nConseqPixels() == dstIt.nConseqPixels());
194
195 while(srcIt.nextPixels(nConseqPixels) &&
196 dstIt.nextPixels(nConseqPixels)) {
197
198 nConseqPixels = srcIt.nConseqPixels();
199
200 const quint8 *srcData = srcIt.rawDataConst();
201 quint8 *dstData = dstIt.rawData();
202
203 m_colorSpace->convertPixelsTo(srcData, dstData,
204 dstColorSpace,
205 nConseqPixels,
206 renderingIntent, conversionFlags);
207 }
208 }
209
210 // becomes owned by the parent
213 m_dataManager, dstDataManager,
214 m_colorSpace, dstColorSpace,
215 parentCommand);
216
217 // NOTE: first redo is skipped on a higher level,
218 // at DeviceChangeColorSpaceCommand
219 cmd->redo();
220
221 if (!parentCommand) {
222 delete cmd;
223 }
224 }
225
226 void reincarnateWithDetachedHistory(bool copyContent, KUndo2Command *parentCommand) {
227 struct SwitchDataManager : public KUndo2Command
228 {
229 SwitchDataManager(KisPaintDeviceData *data,
231 KUndo2Command *parent = 0)
232 : KUndo2Command(parent),
233 m_data(data),
234 m_oldDm(oldDm),
235 m_newDm(newDm)
236 {
237 }
238
239 void redo() override {
240 m_data->m_dataManager = m_newDm;
241 m_data->cache()->invalidate();
242 }
243
244 void undo() override {
245 m_data->m_dataManager = m_oldDm;
246 m_data->cache()->invalidate();
247 }
248
249 private:
250 KisPaintDeviceData *m_data;
251 KisDataManagerSP m_oldDm;
252 KisDataManagerSP m_newDm;
253 };
254
255 new KisCommandUtils::LambdaCommand(parentCommand,
256 [this, copyContent] () {
257 KisDataManagerSP newDm =
258 copyContent ?
259 new KisDataManager(*this->dataManager()) :
260 new KisDataManager(this->dataManager()->pixelSize(), this->dataManager()->defaultPixel());
261 return new SwitchDataManager(this, this->dataManager(), newDm);
262 });
263 }
264
265 void prepareClone(const KisPaintDeviceData *srcData, bool copyContent = false) {
266 m_x = srcData->x();
267 m_y = srcData->y();
268
269 if (copyContent) {
270 m_dataManager = new KisDataManager(*srcData->dataManager());
271 } else if (m_dataManager->pixelSize() !=
272 srcData->dataManager()->pixelSize()) {
273 // NOTE: we don't check default pixel value! it is the task of
274 // the higher level!
275
276 m_dataManager = new KisDataManager(srcData->dataManager()->pixelSize(), srcData->dataManager()->defaultPixel());
278 } else {
280 const quint8 *srcDefPixel = srcData->dataManager()->defaultPixel();
281
282 const int cmp =
283 memcmp(srcDefPixel,
286
287 if (cmp != 0) {
288 m_dataManager->setDefaultPixel(srcDefPixel);
289 }
290 }
291
292 m_levelOfDetail = srcData->levelOfDetail();
293 m_colorSpace = srcData->colorSpace();
295 }
296
300
304
305 ALWAYS_INLINE qint32 x() const {
306 return m_x;
307 }
308 ALWAYS_INLINE void setX(qint32 value) {
309 m_x = value;
310 }
311
312 ALWAYS_INLINE qint32 y() const {
313 return m_y;
314 }
315 ALWAYS_INLINE void setY(qint32 value) {
316 m_y = value;
317 }
318
320 return m_colorSpace;
321 }
322
324 return m_levelOfDetail;
325 }
329
333
337
339 struct SwapInterstrokeDataCommand : public KUndo2Command
340 {
341 SwapInterstrokeDataCommand(KisPaintDeviceData *q, KisInterstrokeDataSP data)
342 : m_q(q),
343 m_data(data)
344 {
345 }
346
347 void redo() override {
348 std::swap(m_data, m_q->m_interstrokeData);
349 }
350
351 void undo() override {
352 std::swap(m_data, m_q->m_interstrokeData);
353 }
354
355 private:
358 };
359
360 return new SwapInterstrokeDataCommand(this, value);
361 }
362
363
364private:
374
375
376private:
377
380 qint32 m_x;
381 qint32 m_y;
386};
387
388#endif /* __KIS_PAINT_DEVICE_DATA_H */
float value(const T *src, size_t ch)
#define ALWAYS_INLINE
virtual void undo()
virtual void redo()
void clear(qint32 x, qint32 y, qint32 w, qint32 h, quint8 def)
void setDefaultPixel(const quint8 *defPixel)
KisRegion region() const
quint32 pixelSize() const
const quint8 * defaultPixel() const
ChangeColorSpaceCommand(KisPaintDeviceData *data, KisDataManagerSP oldDm, KisDataManagerSP newDm, const KoColorSpace *oldCs, const KoColorSpace *newCs, KUndo2Command *parent)
ChangeProfileCommand(KisPaintDeviceData *data, const KoColorSpace *oldCs, const KoColorSpace *newCs, KUndo2Command *parent)
KisInterstrokeDataSP m_interstrokeData
ALWAYS_INLINE KisInterstrokeDataSP interstrokeData() const
ALWAYS_INLINE qint32 levelOfDetail() const
ALWAYS_INLINE qint32 y() const
ALWAYS_INLINE KisDataManagerSP dataManager() const
KisDataManagerSP m_dataManager
void assignColorSpace(const KoColorSpace *dstColorSpace, KUndo2Command *parentCommand)
void convertDataColorSpace(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags, KUndo2Command *parentCommand, KoUpdater *updater=nullptr)
ALWAYS_INLINE KisIteratorCompleteListener * cacheInvalidator()
ALWAYS_INLINE qint32 x() const
ALWAYS_INLINE KisPaintDeviceCache * cache()
void prepareClone(const KisPaintDeviceData *srcData, bool copyContent=false)
KisPaintDeviceData(KisPaintDevice *paintDevice)
KisPaintDeviceData(KisPaintDevice *paintDevice, const KisPaintDeviceData *rhs, bool cloneContent)
ALWAYS_INLINE void setX(qint32 value)
ALWAYS_INLINE void setY(qint32 value)
void init(const KoColorSpace *cs, KisDataManagerSP dataManager)
CacheInvalidator m_cacheInvalidator
KisPaintDeviceCache m_cache
ALWAYS_INLINE const KoColorSpace * colorSpace() const
const KoColorSpace * m_colorSpace
void reincarnateWithDetachedHistory(bool copyContent, KUndo2Command *parentCommand)
ALWAYS_INLINE KUndo2Command * createChangeInterstrokeDataCommand(KisInterstrokeDataSP value)
ALWAYS_INLINE void setLevelOfDetail(qint32 value)
QRect boundingRect() const
virtual quint32 pixelSize() const =0
virtual bool convertPixelsTo(const quint8 *src, quint8 *dst, const KoColorSpace *dstColorSpace, quint32 numPixels, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
virtual const KoColorProfile * profile() const =0
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
KisIteratorCompleteListener * m_completionListener
KisHLineConstIteratorSP createConstIterator(const QRect &rect)
KisHLineIteratorSP createIterator(const QRect &rect)
DirectDataAccessPolicy(KisDataManager *dataManager, KisIteratorCompleteListener *completionListener)
The LambdaCommand struct is a shorthand for creation of AggregateCommand commands using C++ lambda fe...
The KisIteratorCompleteListener struct is a special interface for notifying the paint device that an ...