Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_paint_device_strategies.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2013 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#ifndef __KIS_PAINT_DEVICE_STRATEGIES_H
8#define __KIS_PAINT_DEVICE_STRATEGIES_H
9
10#include "kis_wrapped_rect.h"
14
15
17{
18public:
21 : m_device(device), m_d(d)
22 {
23 }
24
26 }
27
28 virtual void move(const QPoint& pt) {
29 m_d->setX(pt.x());
30 m_d->setY(pt.y());
31 m_d->cache()->invalidate();
32 }
33
34 virtual QRect extent() const {
35 QRect extent;
36
37 qint32 x, y, w, h;
38 m_d->dataManager()->extent(x, y, w, h);
39 x += m_d->x();
40 y += m_d->y();
41 extent = QRect(x, y, w, h);
42
43 quint8 defaultOpacity = m_device->defaultPixel().opacityU8();
44
45 if (defaultOpacity != OPACITY_TRANSPARENT_U8)
47
48 return extent;
49 }
50
51 virtual KisRegion region() const {
52 return m_d->cache()->region().translated(m_d->x(), m_d->y());
53 }
54
55 virtual void crop(const QRect &rect) {
56 m_d->dataManager()->setExtent(rect.translated(-m_d->x(), -m_d->y()));
57 m_d->cache()->invalidate();
58 }
59
60 virtual void clear(const QRect & rc) {
62
63 dm->clear(rc.x() - m_d->x(), rc.y() - m_d->y(),
64 rc.width(), rc.height(),
65 dm->defaultPixel());
66 m_d->cache()->invalidate();
67 }
68
69 virtual void fill(const QRect &rc, const quint8 *fillPixel) {
70 m_d->dataManager()->clear(rc.x() - m_d->x(),
71 rc.y() - m_d->y(),
72 rc.width(),
73 rc.height(),
74 fillPixel);
75 m_d->cache()->invalidate();
76 }
77
78
79 virtual KisHLineIteratorSP createHLineIteratorNG(KisDataManager *dataManager, qint32 x, qint32 y, qint32 w, qint32 offsetX, qint32 offsetY) {
80 return new KisHLineIterator2(dataManager, x, y, w, offsetX, offsetY, true, m_d->cacheInvalidator());
81 }
82
83 virtual KisHLineConstIteratorSP createHLineConstIteratorNG(KisDataManager *dataManager, qint32 x, qint32 y, qint32 w, qint32 offsetX, qint32 offsetY) const {
84 return new KisHLineIterator2(dataManager, x, y, w, offsetX, offsetY, false, m_d->cacheInvalidator());
85 }
86
87
88 virtual KisVLineIteratorSP createVLineIteratorNG(qint32 x, qint32 y, qint32 w) {
89 m_d->cache()->invalidate();
90 return new KisVLineIterator2(m_d->dataManager().data(), x, y, w, m_d->x(), m_d->y(), true, m_d->cacheInvalidator());
91 }
92
93 virtual KisVLineConstIteratorSP createVLineConstIteratorNG(qint32 x, qint32 y, qint32 w) const {
94 return new KisVLineIterator2(m_d->dataManager().data(), x, y, w, m_d->x(), m_d->y(), false, m_d->cacheInvalidator());
95 }
96
101
105
106 virtual void fastBitBlt(KisPaintDeviceSP src, const QRect &rect) {
107 Q_ASSERT(m_device->fastBitBltPossible(src));
108 fastBitBltImpl(src->dataManager(), rect);
109 }
110
111 virtual void fastBitBltOldData(KisPaintDeviceSP src, const QRect &rect) {
112 Q_ASSERT(m_device->fastBitBltPossible(src));
113
114 m_d->dataManager()->bitBltOldData(src->dataManager(), rect.translated(-m_d->x(), -m_d->y()));
115 m_d->cache()->invalidate();
116 }
117
118 virtual void fastBitBltRough(KisPaintDeviceSP src, const QRect &rect) {
119 Q_ASSERT(m_device->fastBitBltPossible(src));
120 fastBitBltRoughImpl(src->dataManager(), rect);
121 }
122
123 virtual void fastBitBltRough(KisDataManagerSP srcDataManager, const QRect &rect) {
124 fastBitBltRoughImpl(srcDataManager, rect);
125 }
126
127 virtual void fastBitBltRoughOldData(KisPaintDeviceSP src, const QRect &rect) {
128 Q_ASSERT(m_device->fastBitBltPossible(src));
129
130 m_d->dataManager()->bitBltRoughOldData(src->dataManager(), rect.translated(-m_d->x(), -m_d->y()));
131 m_d->cache()->invalidate();
132 }
133
134 virtual void readBytes(quint8 *data, const QRect &rect) const {
135 readBytesImpl(data, rect, -1);
136 }
137
138 virtual void writeBytes(const quint8 * data, const QRect &rect) {
139 writeBytesImpl(data, rect, -1);
140 }
141
142 virtual QVector<quint8*> readPlanarBytes(qint32 x, qint32 y, qint32 w, qint32 h) const {
143 return m_d->dataManager()->readPlanarBytes(m_device->channelSizes(), x, y, w, h);
144 }
145
146 virtual void writePlanarBytes(QVector<quint8*> planes, qint32 x, qint32 y, qint32 w, qint32 h) {
147 m_d->dataManager()->writePlanarBytes(planes, m_device->channelSizes(), x, y, w, h);
148 m_d->cache()->invalidate();
149 }
150protected:
151 virtual void readBytesImpl(quint8 *data, const QRect &rect, int dataRowStride) const {
152 m_d->dataManager()->readBytes(data,
153 rect.x() - m_d->x(),
154 rect.y() - m_d->y(),
155 rect.width(),
156 rect.height(),
157 dataRowStride);
158 }
159
160 virtual void writeBytesImpl(const quint8 * data, const QRect &rect, int dataRowStride) {
161 m_d->dataManager()->writeBytes(data,
162 rect.x() - m_d->x(),
163 rect.y() - m_d->y(),
164 rect.width(),
165 rect.height(),
166 dataRowStride);
167 m_d->cache()->invalidate();
168 }
169
170 virtual void fastBitBltImpl(KisDataManagerSP srcDataManager, const QRect &rect)
171 {
172 m_d->dataManager()->bitBlt(srcDataManager, rect.translated(-m_d->x(), -m_d->y()));
173 m_d->cache()->invalidate();
174 }
175
176 virtual void fastBitBltRoughImpl(KisDataManagerSP srcDataManager, const QRect &rect)
177 {
178 m_d->dataManager()->bitBltRough(srcDataManager, rect.translated(-m_d->x(), -m_d->y()));
179 m_d->cache()->invalidate();
180 }
181
182protected:
185};
186
187
189{
190public:
198
199 const QRect wrapRect() const {
200 return m_wrapRect;
201 }
202
203 void setWrapRect(const QRect &rc) {
204 m_wrapRect = rc;
205 }
206
207 void move(const QPoint& pt) override {
208 QPoint offset (pt.x() - m_device->x(), pt.y() - m_device->y());
209
210 QRect exactBoundsBeforeMove = m_device->exactBounds();
212
213 QRegion borderRegion(exactBoundsBeforeMove.translated(offset.x(), offset.y()));
214 borderRegion -= m_wrapRect;
215
216 const int pixelSize = m_device->pixelSize();
217
218 auto rectIter = borderRegion.begin();
219 while (rectIter != borderRegion.end()) {
220 QRect rc = *rectIter;
223
224 int rows = 1;
225 int columns = 1;
226
227 for (int y = rc.y(); y <= rc.bottom(); y += rows) {
228 int rows = qMin(srcIt->numContiguousRows(y), dstIt->numContiguousRows(y));
229 rows = qMin(rows, rc.bottom() - y + 1);
230
231 for (int x = rc.x(); x <= rc.right(); x += columns) {
232 int columns = qMin(srcIt->numContiguousColumns(x), dstIt->numContiguousColumns(x));
233 columns = qMin(columns, rc.right() - x + 1);
234
235 srcIt->moveTo(x, y);
236 dstIt->moveTo(x, y);
237
238 int srcRowStride = srcIt->rowStride(x, y);
239 int dstRowStride = dstIt->rowStride(x, y);
240 const quint8 *srcPtr = srcIt->rawDataConst();
241 quint8 *dstPtr = dstIt->rawData();
242
243 for (int i = 0; i < rows; i++) {
244 memcpy(dstPtr, srcPtr, pixelSize * columns);
245 srcPtr += srcRowStride;
246 dstPtr += dstRowStride;
247 }
248 }
249 }
250 rectIter++;
251 }
252 }
253
258
259 KisRegion region() const override {
261 if (wrapAxis != WRAPAROUND_BOTH) {
263 QVector<QRect> rects;
264 Q_FOREACH (const QRect &rc, region.rects()) {
265 const QRect clippedRect = KisWrappedRect::clipToWrapRect(rc, m_wrapRect, wrapAxis);
266 if (!clippedRect.isEmpty()) {
267 rects.append(clippedRect);
268 }
269 }
270 region = KisRegion(rects);
271 return region;
272 }
273 else {
275 }
276 }
277
278 void crop(const QRect &rect) override {
280 }
281
282 void clear(const QRect &rect) override {
284 Q_FOREACH (const QRect &rc, splitRect) {
286 }
287 }
288
289 void fill(const QRect &rect, const quint8 *fillPixel) override {
291 Q_FOREACH (const QRect &rc, splitRect) {
292 KisPaintDeviceStrategy::fill(rc, fillPixel);
293 }
294 }
295
296 KisHLineIteratorSP createHLineIteratorNG(KisDataManager *dataManager, qint32 x, qint32 y, qint32 w, qint32 offsetX, qint32 offsetY) override {
297 KisWrappedRect splitRect(QRect(x, y, w, m_wrapRect.height()), m_wrapRect, m_device->defaultBounds()->wrapAroundModeAxis());
298 if (!splitRect.isSplit()) {
299 return KisPaintDeviceStrategy::createHLineIteratorNG(dataManager, x, y, w, offsetX, offsetY);
300 }
301 return new KisWrappedHLineIterator(dataManager, splitRect, offsetX, offsetY, true, m_d->cacheInvalidator());
302 }
303
304 KisHLineConstIteratorSP createHLineConstIteratorNG(KisDataManager *dataManager, qint32 x, qint32 y, qint32 w, qint32 offsetX, qint32 offsetY) const override {
305 KisWrappedRect splitRect(QRect(x, y, w, m_wrapRect.height()), m_wrapRect, m_device->defaultBounds()->wrapAroundModeAxis());
306 if (!splitRect.isSplit()) {
308 }
309 return new KisWrappedHLineIterator(dataManager, splitRect, offsetX, offsetY, false, m_d->cacheInvalidator());
310 }
311
312 KisVLineIteratorSP createVLineIteratorNG(qint32 x, qint32 y, qint32 h) override {
313 m_d->cache()->invalidate();
314
315 KisWrappedRect splitRect(QRect(x, y, m_wrapRect.width(), h), m_wrapRect, m_device->defaultBounds()->wrapAroundModeAxis());
316 if (!splitRect.isSplit()) {
318 }
319 return new KisWrappedVLineIterator(m_d->dataManager().data(), splitRect, m_d->x(), m_d->y(), true, m_d->cacheInvalidator());
320 }
321
322 KisVLineConstIteratorSP createVLineConstIteratorNG(qint32 x, qint32 y, qint32 h) const override {
323 KisWrappedRect splitRect(QRect(x, y, m_wrapRect.width(), h), m_wrapRect, m_device->defaultBounds()->wrapAroundModeAxis());
324 if (!splitRect.isSplit()) {
326 }
327 return new KisWrappedVLineIterator(m_d->dataManager().data(), splitRect, m_d->x(), m_d->y(), false, m_d->cacheInvalidator());
328 }
329
336
342
343 void fastBitBltImpl(KisDataManagerSP srcDataManager, const QRect &rect) override {
345 Q_FOREACH (const QRect &rc, splitRect) {
346 KisPaintDeviceStrategy::fastBitBltImpl(srcDataManager, rc);
347 }
348 }
349
350 void fastBitBltOldData(KisPaintDeviceSP src, const QRect &rect) override {
352 Q_FOREACH (const QRect &rc, splitRect) {
354 }
355 }
356
357 void fastBitBltRoughImpl(KisDataManagerSP srcDataManager, const QRect &rect) override
358 {
359 // no rough version in wrapped mode
360 fastBitBltImpl(srcDataManager, rect);
361 }
362
363 void fastBitBltRoughOldData(KisPaintDeviceSP src, const QRect &rect) override {
364 // no rough version in wrapped mode
366 }
367
368 void readBytes(quint8 *data, const QRect &rect) const override {
370
371 if (!splitRect.isSplit()) {
373 } else {
374 const int pixelSize = m_device->pixelSize();
375
376 int leftWidth = splitRect[KisWrappedRect::TOPLEFT].width();
377 int rightWidth = splitRect[KisWrappedRect::TOPRIGHT].width();
378
379 int totalHeight = rect.height();
380 int totalWidth = rect.width();
381 int dataRowStride = totalWidth * pixelSize;
382
383 int bufOffset = 0;
384 int row = 0;
385 while (row < totalHeight) {
386 int leftIndex = KisWrappedRect::TOPLEFT + bufOffset;
387 int rightIndex = KisWrappedRect::TOPRIGHT + bufOffset;
388
389 QPoint leftRectOrigin = splitRect[leftIndex].topLeft();
390 QPoint rightRectOrigin = splitRect[rightIndex].topLeft();
391
392 int height = qMin(splitRect[leftIndex].height(), totalHeight - row);
393
394 int col = 0;
395 while (col < totalWidth) {
396 int width;
397 quint8 *dataPtr;
398
399 width = qMin(leftWidth, totalWidth - col);
400 dataPtr = data + pixelSize * (col + row * totalWidth);
401 readBytesImpl(dataPtr, QRect(leftRectOrigin, QSize(width, height)), dataRowStride);
402 col += width;
403
404 if (col >= totalWidth) break;
405
406 width = qMin(rightWidth, totalWidth - col);
407 dataPtr = data + pixelSize * (col + row * totalWidth);
408 readBytesImpl(dataPtr, QRect(rightRectOrigin, QSize(width, height)), dataRowStride);
409 col += width;
410 }
411
412 row += height;
413 bufOffset = (bufOffset + 2) % 4;
414 }
415 }
416 }
417
418 void writeBytes(const quint8 *data, const QRect &rect) override {
420
421 if (!splitRect.isSplit()) {
423 } else {
424 const int pixelSize = m_device->pixelSize();
425
426 int totalWidth = rect.width();
427 int dataRowStride = totalWidth * pixelSize;
428
429 QRect rc;
430 QPoint origin;
431 const quint8 *dataPtr;
432
433 origin.rx() = 0;
434 origin.ry() = 0;
435 rc = splitRect.topLeft();
436 dataPtr = data + pixelSize * (origin.x() + totalWidth * origin.y());
437 writeBytesImpl(dataPtr, rc, dataRowStride);
438
439 origin.rx() = splitRect.topLeft().width();
440 origin.ry() = 0;
441 rc = splitRect.topRight();
442 dataPtr = data + pixelSize * (origin.x() + totalWidth * origin.y());
443 writeBytesImpl(dataPtr, rc, dataRowStride);
444
445 origin.rx() = 0;
446 origin.ry() = splitRect.topLeft().height();
447 rc = splitRect.bottomLeft();
448 dataPtr = data + pixelSize * (origin.x() + totalWidth * origin.y());
449 writeBytesImpl(dataPtr, rc, dataRowStride);
450
451 origin.rx() = splitRect.topLeft().width();
452 origin.ry() = splitRect.topLeft().height();
453 rc = splitRect.bottomRight();
454 dataPtr = data + pixelSize * (origin.x() + totalWidth * origin.y());
455 writeBytesImpl(dataPtr, rc, dataRowStride);
456 }
457 }
458
459private:
461};
462
463
464
465#endif /* __KIS_PAINT_DEVICE_STRATEGIES_H */
WrapAroundAxis
@ WRAPAROUND_BOTH
const quint8 OPACITY_TRANSPARENT_U8
virtual quint8 * rawData()=0
virtual const quint8 * rawDataConst() const =0
void clear(qint32 x, qint32 y, qint32 w, qint32 h, quint8 def)
void readBytes(quint8 *data, qint32 x, qint32 y, qint32 w, qint32 h, qint32 dataRowStride=-1) const
void setExtent(qint32 x, qint32 y, qint32 w, qint32 h)
void writeBytes(const quint8 *data, qint32 x, qint32 y, qint32 w, qint32 h, qint32 dataRowStride=-1)
void bitBltRough(KisTiledDataManagerSP srcDM, const QRect &rect)
QVector< quint8 * > readPlanarBytes(QVector< qint32 > channelsizes, qint32 x, qint32 y, qint32 w, qint32 h) const
void bitBltOldData(KisTiledDataManagerSP srcDM, const QRect &rect)
void writePlanarBytes(QVector< quint8 * > planes, QVector< qint32 > channelsizes, qint32 x, qint32 y, qint32 w, qint32 h)
void extent(qint32 &x, qint32 &y, qint32 &w, qint32 &h) const
void bitBltRoughOldData(KisTiledDataManagerSP srcDM, const QRect &rect)
void bitBlt(KisTiledDataManagerSP srcDM, const QRect &rect)
const quint8 * defaultPixel() const
virtual WrapAroundAxis wrapAroundModeAxis() const =0
virtual QRect bounds() const =0
virtual KisRandomConstAccessorSP createRandomConstAccessorNG() const
virtual KisHLineConstIteratorSP createHLineConstIteratorNG(KisDataManager *dataManager, qint32 x, qint32 y, qint32 w, qint32 offsetX, qint32 offsetY) const
virtual KisVLineConstIteratorSP createVLineConstIteratorNG(qint32 x, qint32 y, qint32 w) const
virtual QVector< quint8 * > readPlanarBytes(qint32 x, qint32 y, qint32 w, qint32 h) const
virtual void writeBytes(const quint8 *data, const QRect &rect)
KisPaintDeviceStrategy(KisPaintDevice *device, KisPaintDevice::Private *d)
virtual void fastBitBltRoughOldData(KisPaintDeviceSP src, const QRect &rect)
virtual void writePlanarBytes(QVector< quint8 * > planes, qint32 x, qint32 y, qint32 w, qint32 h)
virtual void fastBitBlt(KisPaintDeviceSP src, const QRect &rect)
virtual void readBytesImpl(quint8 *data, const QRect &rect, int dataRowStride) const
virtual void fastBitBltImpl(KisDataManagerSP srcDataManager, const QRect &rect)
virtual void fastBitBltRoughImpl(KisDataManagerSP srcDataManager, const QRect &rect)
virtual void fill(const QRect &rc, const quint8 *fillPixel)
virtual void writeBytesImpl(const quint8 *data, const QRect &rect, int dataRowStride)
virtual void fastBitBltRough(KisPaintDeviceSP src, const QRect &rect)
virtual void readBytes(quint8 *data, const QRect &rect) const
virtual KisHLineIteratorSP createHLineIteratorNG(KisDataManager *dataManager, qint32 x, qint32 y, qint32 w, qint32 offsetX, qint32 offsetY)
virtual KisVLineIteratorSP createVLineIteratorNG(qint32 x, qint32 y, qint32 w)
virtual void fastBitBltRough(KisDataManagerSP srcDataManager, const QRect &rect)
virtual void fastBitBltOldData(KisPaintDeviceSP src, const QRect &rect)
KisVLineConstIteratorSP createVLineConstIteratorNG(qint32 x, qint32 y, qint32 h) const override
void fastBitBltImpl(KisDataManagerSP srcDataManager, const QRect &rect) override
void readBytes(quint8 *data, const QRect &rect) const override
KisHLineConstIteratorSP createHLineConstIteratorNG(KisDataManager *dataManager, qint32 x, qint32 y, qint32 w, qint32 offsetX, qint32 offsetY) const override
void fastBitBltRoughOldData(KisPaintDeviceSP src, const QRect &rect) override
KisRandomConstAccessorSP createRandomConstAccessorNG() const override
KisPaintDeviceWrappedStrategy(const QRect &wrapRect, KisPaintDevice *device, KisPaintDevice::Private *d)
KisHLineIteratorSP createHLineIteratorNG(KisDataManager *dataManager, qint32 x, qint32 y, qint32 w, qint32 offsetX, qint32 offsetY) override
KisVLineIteratorSP createVLineIteratorNG(qint32 x, qint32 y, qint32 h) override
void fill(const QRect &rect, const quint8 *fillPixel) override
void writeBytes(const quint8 *data, const QRect &rect) override
void fastBitBltOldData(KisPaintDeviceSP src, const QRect &rect) override
void fastBitBltRoughImpl(KisDataManagerSP srcDataManager, const QRect &rect) override
quint32 pixelSize() const
bool fastBitBltPossible(KisPaintDeviceSP src)
QRect exactBounds() const
QVector< qint32 > channelSizes() const
KoColor defaultPixel() const
KisDefaultBoundsBaseSP defaultBounds() const
QPoint offset() const
virtual qint32 rowStride(qint32 x, qint32 y) const =0
virtual qint32 numContiguousRows(qint32 y) const =0
virtual void moveTo(qint32 x, qint32 y)=0
virtual qint32 numContiguousColumns(qint32 x) const =0
KisRegion translated(int x, int y) const
QVector< QRect > rects() const
quint8 opacityU8() const
Definition KoColor.cpp:341
KisWrappedLineIteratorBase< WrappedHLineIteratorStrategy, KisHLineIteratorNG > KisWrappedHLineIterator
KisWrappedLineIteratorBase< WrappedVLineIteratorStrategy, KisVLineIteratorNG > KisWrappedVLineIterator
KisDefaultBoundsBaseSP defaultBounds
KisDataManagerSP dataManager() const
KisIteratorCompleteListener * cacheInvalidator()
KisPaintDeviceCache * cache()
bool isSplit() const
static QRect clipToWrapRect(QRect rc, const QRect &wrapRect, WrapAroundAxis wrapAxis)
QRect topLeft() const
QRect bottomLeft() const
QRect bottomRight() const
QRect topRight() const