Cropping paint devices
Adrian
adrian at pagenet.plus.com
Sat Mar 26 14:55:17 CET 2005
On Sat Mar 26 14:08 , Boudewijn Rempt <boud at valdyas.org> sent:
>On Saturday 26 March 2005 13:50, Casper Boemann wrote:
>
>> When you create the tileRect you must multiply width to col and height to
>
>> row.
I think there's a bit more to it because the tiles in each hash table entry are
stored in a linked list:
> void KisTiledDataManager::setExtent(Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h)
> {
> QRect newRect = QRect(x, y, w, h).normalize();
> QRect oldRect = QRect(m_extentMinX, m_extentMinY, m_extentMaxX - m_extentMinX
+ 1, m_extentMaxY - m_extentMinY + 1).normalize();
>
> // Do nothing if the desired size is bigger than we currently are: that is
handled by the autoextending automatically
> if (newRect.contains(oldRect)) return;
>
> // Loop through all tiles, if a tile is wholly outside the extent, add to the
memento, then delete it,
> // if the tile is partially outside the extent, clear the outside pixels to
black transparent (XXX: use the
> // default pixel for this when avaiable).
> for(int i = 0; i < 1024; i++)
> {
> KisTile *tile = m_hashTable[i];
>
In order to remove deleted tiles from the hash table list, you need to keep track
of the tile before the one to be deleted.
KisTile *prevTile = 0;
> while(tile)
> {
> QRect tileRect = QRect(tile -> getCol(), tile -> getRow(), KisTile::WIDTH,
KisTile::HEIGHT);
This wants to be:
QRect tileRect = QRect(tile -> getCol() * KisTile::WIDTH, tile -> getRow() *
KisTile::HEIGHT, KisTile::WIDTH, KisTile::HEIGHT);
>
>
> if (newRect.contains(tileRect)) {
> // Completely inside, do nothing
> tile->getNext();
This should be:
prevTile = tile;
tile = tile->getNext();
> }
> else {
> Q_UINT32 tileHash = calcTileHash(tileRect.x(), tileRect.y());
i is the tileHash for this tile so you can replace tileHash with i:
ensureTileMementoed(tile -> getCol(), tile -> getRow(), i, tile);
>
> if (newRect.intersects(tileRect)) {
> // Partially inside, clear the non-intersecting bits
>
> // Create the intersection of the tile and new rect
> QRect intersection = newRect.intersect(tileRect);
> intersection.setRect(intersection.x() - tileRect.x(), intersection.y() -
tileRect.y(), intersection.width(), intersection.height());
>
> // This can be done a lot more efficiently, no doubt, by clearing runs of
pixels to the left and the right of
> // the intersecting line.
> for (int y = 0; y < KisTile::HEIGHT; ++y) {
> for (int x = 0; x < KisTile::WIDTH; ++x) {
> if (!intersection.contains(x,y)) {
> Q_UINT8 * ptr = tile -> data(x, y);
> memset(ptr, 0, m_pixelSize);
> }
> }
> }
>
> tile->getNext();
This should be:
prevTile = tile;
tile = tile->getNext();
> }
> else {
> // Completely outside, delete this tile. It had already been mementoed
> KisTile *deltile = tile;
You need to remove the deleted tile from the hash table list before deleting it:
if (prevTile == 0) {
// This was the first tile in the hash table bucket
m_hashTable[i] = tile -> getNext();
} else {
prevTile -> setNext(tile -> getNext());
}
tile = tile->getNext();
delete deltile;
> }
> }
>
>
> }
> }
>
> // Set the extent correctly
> m_extentMinX = x;
> m_extentMinY = y;
> m_extentMaxX = x + w + 1;
> m_extentMaxY = y + h + 1;
These should both be - 1 rather than + 1.
Adrian
More information about the kimageshop
mailing list