34 const quint8 *defaultPixel)
55 defaultTileData->
deref();
87 QWriteLocker locker(&
m_lock);
102 QReadLocker locker(&
m_lock);
109 retval = store.
write(str, strlen(str));
122 while ((tile = iter.
tile())) {
123 retval = compressor->writeTile(tile, store);
137 QWriteLocker locker(&
m_lock);
145 const qint32 maxLineLength = 79;
146 QByteArray line = stream->readLine(maxLineLength);
147 line = line.trimmed();
152 if (line[0] ==
'V') {
155 QString keyword = lineItems.takeFirst();
156 Q_ASSERT(keyword ==
"VERSION");
158 tilesVersion = lineItems.takeFirst().toInt();
164 numTiles = line.toUInt();
170 bool readSuccess =
true;
171 for (quint32 i = 0; i < numTiles; i++) {
172 if (!compressor->readTile(stream,
this)) {
185 buffer = QString(
"VERSION %1\n"
196 return store.
write(buffer.toLatin1());
199#define takeOneLine(stream, maxLine, keyword, value) \
201 QByteArray line = stream->readLine(maxLine); \
202 line = line.trimmed(); \
203 QList<QByteArray> lineItems = line.split(' '); \
204 keyword = lineItems.takeFirst(); \
205 value = lineItems.takeFirst().toInt(); \
217 const qint32 maxLineLength = 25;
218 const qint32 totalNumTests = 4;
219 bool foundDataMark =
false;
220 qint32 testsPassed = 0;
225 while(!foundDataMark && stream->canReadLine()) {
228 if (keyword ==
"TILEWIDTH") {
232 else if (keyword ==
"TILEHEIGHT") {
236 else if (keyword ==
"PIXELSIZE") {
240 else if (keyword ==
"DATA") {
242 foundDataMark =
true;
251 if(testsPassed != totalNumTests) {
252 warnTiles <<
"Not enough fields of tiles header present"
253 << testsPassed <<
"of" << totalNumTests;
256 return testsPassed == totalNumTests;
270 const quint8 *defaultData = tileData->
data();
275 while ((tile = iter.
tile())) {
276 if (tile->
extent().intersects(area)) {
278 if(memcmp(defaultData, tile->
data(), tileDataSize) == 0) {
279 tilesToDelete.push_back(tile);
289 Q_FOREACH (
KisTileSP tile, tilesToDelete) {
300 quint8 *dstBuf =
new quint8[num *
pixelSize];
301 quint8 *dstIt = dstBuf;
302 for (qint32 i = 0; i < num; i++) {
314 if (clearRect.isEmpty())
321 bool pixelBytesAreTheSame =
true;
323 if (clearPixel[i] != clearPixel[0]) {
324 pixelBytesAreTheSame =
false;
329 if (pixelBytesAreDefault) {
333 qint32 firstColumn =
xToCol(clearRect.left());
334 qint32 lastColumn =
xToCol(clearRect.right());
336 qint32 firstRow =
yToRow(clearRect.top());
337 qint32 lastRow =
yToRow(clearRect.bottom());
342 quint8 *clearPixelData = 0;
347 if (!pixelBytesAreDefault &&
355 for (qint32 row = firstRow; row <= lastRow; ++row) {
356 for (qint32 column = firstColumn; column <= lastColumn; ++column) {
360 QRect clearTileRect = clearRect & tileRect;
362 if (clearTileRect == tileRect) {
364 const bool wasDeleted =
372 if (!pixelBytesAreDefault) {
378 const qint32 lineSize = clearTileRect.width() *
pixelSize;
379 qint32 rowsRemaining = clearTileRect.height();
382 clearTileRect.left(),
385 quint8* tileIt = tw.
data();
387 if (pixelBytesAreTheSame) {
388 while (rowsRemaining > 0) {
389 memset(tileIt, *clearPixelData, lineSize);
394 while (rowsRemaining > 0) {
395 memcpy(tileIt, clearPixelData, lineSize);
405 delete[] clearPixelData;
412 clear(clearRect, buf);
418 clear(QRect(x, y, w, h), clearPixel);
422 clear(QRect(x, y, w, h), clearValue);
432template<
bool useOldSrcData>
435 if (
rect.isEmpty())
return;
438 const bool defaultPixelsCoincide =
449 for (qint32 row = firstRow; row <= lastRow; ++row) {
450 for (qint32 column = firstColumn; column <= lastColumn; ++column) {
452 bool srcTileExists =
false;
456 srcDM->
getOldTile(column, row, srcTileExists) :
461 QRect cloneTileRect =
rect & tileRect;
463 if (cloneTileRect == tileRect) {
465 const bool wasDeleted =
468 if (srcTileExists || !defaultPixelsCoincide) {
479 }
else if (wasDeleted) {
484 const qint32 lineSize = cloneTileRect.width() *
pixelSize;
485 qint32 rowsRemaining = cloneTileRect.height();
488 cloneTileRect.left(),
493 const quint8* srcTileIt = srcTile->
data() + tw.
offset();
494 quint8* dstTileIt = tw.
data();
496 while (rowsRemaining > 0) {
497 memcpy(dstTileIt, srcTileIt, lineSize);
509template<
bool useOldSrcData>
512 if (
rect.isEmpty())
return;
515 const bool defaultPixelsCoincide =
524 for (qint32 row = firstRow; row <= lastRow; ++row) {
525 for (qint32 column = firstColumn; column <= lastColumn; ++column) {
532 bool srcTileExists =
false;
536 srcDM->
getOldTile(column, row, srcTileExists) :
539 const bool wasDeleted =
542 if (srcTileExists || !defaultPixelsCoincide) {
553 }
else if (wasDeleted) {
562 bitBltImpl<false>(srcDM,
rect);
567 bitBltImpl<true>(srcDM,
rect);
572 bitBltRoughImpl<false>(srcDM,
rect);
577 bitBltRoughImpl<true>(srcDM,
rect);
588 newRect = newRect.normalized();
592 if (newRect.contains(oldRect))
return;
602 tileRect = tile->
extent();
603 if (newRect.contains(tileRect)) {
606 }
else if (newRect.intersects(tileRect)) {
607 QRect intersection = newRect & tileRect;
608 intersection.translate(- tileRect.topLeft());
613 quint8* data = tile->
data();
619 if (!intersection.contains(x, y)) {
643 while ((tile = iter.
tile())) {
644 indexes << QPoint(tile->
col(), tile->
row());
655 rect.getRect(&x, &y, &w, &h);
670 while ((tile = iter.
tile())) {
686 qint32 width, qint32 height,
687 qint32 dataRowStride)
689 QWriteLocker locker(&
m_lock);
696 qint32 width, qint32 height,
697 qint32 dataRowStride)
const
699 QReadLocker locker(&
m_lock);
707 qint32 width, qint32 height)
const
709 QReadLocker locker(&
m_lock);
718 qint32 width, qint32 height)
720 QWriteLocker locker(&
m_lock);
723 bool allChannelsPresent =
true;
725 Q_FOREACH (
const quint8* plane, planes) {
727 allChannelsPresent =
false;
732 if (allChannelsPresent) {
733 writePlanarBytesBody<true>(planes, channelSizes, x, y, width, height);
735 writePlanarBytesBody<false>(planes, channelSizes, x, y, width, height);
float value(const T *src, size_t ch)
KisMementoSP getMemento()
void setDefaultTileData(KisTileData *defaultTileData)
virtual bool write(const QByteArray &data)=0
static KisAbstractTileCompressorSP create(qint32 version)
KisTileData * createDefaultTileData(qint32 pixelSize, const quint8 *defPixel)
static KisTileDataStore * instance()
static void releaseInternalPools()
static const qint32 HEIGHT
static const qint32 WIDTH
std::enable_if< std::is_same< Helper, QWriteLocker >::value, void >::type deleteCurrent()
KisTileData * refAndFetchDefaultTileData() const
void addTile(TileTypeSP tile)
bool deleteTile(TileTypeSP tile)
void setDefaultTileData(KisTileData *defaultTileData)
KisTileData * tileData() const
void unlockForRead() const
void writePlanarBytes(QVector< quint8 * > planes, QVector< qint32 > channelsizes, qint32 x, qint32 y, qint32 w, qint32 h)
void readBytesBody(quint8 *data, qint32 x, qint32 y, qint32 width, qint32 height, qint32 dataRowStride=-1) const
QVector< quint8 * > readPlanarBytesBody(QVector< qint32 > channelsizes, qint32 x, qint32 y, qint32 w, qint32 h) const
void bitBltImpl(KisTiledDataManager *srcDM, const QRect &rect)
qint32 rowStride(qint32 x, qint32 y) const
QVector< quint8 * > readPlanarBytes(QVector< qint32 > channelsizes, qint32 x, qint32 y, qint32 w, qint32 h) const
void readBytes(quint8 *bytes, qint32 x, qint32 y, qint32 w, qint32 h, qint32 dataRowStride=-1) const
KisMementoManager * m_mementoManager
quint32 pixelSize() const
void bitBltRoughImpl(KisTiledDataManager *srcDM, const QRect &rect)
KisTiledExtentManager m_extentManager
qint32 yToRow(qint32 y) const
static const qint32 LEGACY_VERSION
bool writeTilesHeader(KisPaintDeviceWriter &store, quint32 numTiles)
const quint8 * defaultPixel() const
void writeBytes(const quint8 *bytes, qint32 x, qint32 y, qint32 w, qint32 h, qint32 dataRowStride=-1)
void bitBltOldData(KisTiledDataManager *srcDM, const QRect &rect)
qint32 numContiguousRows(qint32 y, qint32 minX, qint32 maxX) const
void setPixel(qint32 x, qint32 y, const quint8 *data)
void setDefaultPixel(const quint8 *defPixel)
bool processTilesHeader(QIODevice *stream, quint32 &numTiles)
qint32 numContiguousColumns(qint32 x, qint32 minY, qint32 maxY) const
static const qint32 CURRENT_VERSION
void writeBytesBody(const quint8 *data, qint32 x, qint32 y, qint32 width, qint32 height, qint32 dataRowStride=-1)
KisTiledDataManager(quint32 pixelSize, const quint8 *defPixel)
bool read(QIODevice *stream)
qint32 xToCol(qint32 x) const
quint8 * duplicatePixel(qint32 num, const quint8 *pixel)
void bitBltRoughOldData(KisTiledDataManager *srcDM, const QRect &rect)
KisTileSP getOldTile(qint32 col, qint32 row, bool &existingTile)
void bitBlt(KisTiledDataManager *srcDM, const QRect &rect)
KisTileHashTable * m_hashTable
static void releaseInternalPools()
void setDefaultPixelImpl(const quint8 *defPixel)
virtual ~KisTiledDataManager()
bool write(KisPaintDeviceWriter &store)
void bitBltRough(KisTiledDataManager *srcDM, const QRect &rect)
KisTileSP getReadOnlyTileLazy(qint32 col, qint32 row, bool &existingTile)
void setExtent(qint32 x, qint32 y, qint32 w, qint32 h)
void purge(const QRect &area)
void notifyTileAdded(qint32 col, qint32 row)
void replaceTileStats(const QVector< QPoint > &indexes)
void notifyTileRemoved(qint32 col, qint32 row)
KisSharedPtr< KisTile > KisTileSP
KisTileHashTableTraits< KisTile > KisTileHashTable
#define takeOneLine(stream, maxLine, keyword, value)