krita

kis_selection.cc

00001 /*
00002  *  Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
00003  *
00004  *  this program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the gnu general public license as published by
00006  *  the free software foundation; either version 2 of the license, or
00007  *  (at your option) any later version.
00008  *
00009  *  this program is distributed in the hope that it will be useful,
00010  *  but without any warranty; without even the implied warranty of
00011  *  merchantability or fitness for a particular purpose.  see the
00012  *  gnu general public license for more details.
00013  *
00014  *  you should have received a copy of the gnu general public license
00015  *  along with this program; if not, write to the free software
00016  *  foundation, inc., 675 mass ave, cambridge, ma 02139, usa.
00017  */
00018 
00019 #include <qimage.h>
00020 
00021 #include <kdebug.h>
00022 #include <klocale.h>
00023 #include <qcolor.h>
00024 
00025 #include "kis_layer.h"
00026 #include "kis_debug_areas.h"
00027 #include "kis_types.h"
00028 #include "kis_colorspace_factory_registry.h"
00029 #include "kis_fill_painter.h"
00030 #include "kis_iterators_pixel.h"
00031 #include "kis_integer_maths.h"
00032 #include "kis_image.h"
00033 #include "kis_datamanager.h"
00034 #include "kis_fill_painter.h"
00035 #include "kis_selection.h"
00036 
00037 KisSelection::KisSelection(KisPaintDeviceSP dev)
00038     : super(dev->parentLayer()
00039             , KisMetaRegistry::instance()->csRegistry()->getAlpha8()
00040             , (QString("selection for ") + dev->name()).latin1())
00041     , m_parentPaintDevice(dev)
00042     , m_doCacheExactRect(false)
00043     , m_dirty(false)
00044 {
00045     Q_ASSERT(dev);
00046 }
00047 
00048 KisSelection::KisSelection()
00049     : super(KisMetaRegistry::instance()->csRegistry()->getAlpha8(), "anonymous selection")
00050     , m_parentPaintDevice(0), m_dirty(false)
00051 {
00052 }
00053 
00054 KisSelection::KisSelection(const KisSelection& rhs)
00055     : super(rhs), m_parentPaintDevice(rhs.m_parentPaintDevice), m_doCacheExactRect(rhs.m_doCacheExactRect),
00056     m_cachedExactRect(rhs.m_cachedExactRect), m_dirty(rhs.m_dirty)
00057 {
00058 }
00059 
00060 KisSelection::~KisSelection()
00061 {
00062 }
00063 
00064 Q_UINT8 KisSelection::selected(Q_INT32 x, Q_INT32 y)
00065 {
00066     KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, false);
00067 
00068     Q_UINT8 *pix = iter.rawData();
00069 
00070     return *pix;
00071 }
00072 
00073 void KisSelection::setSelected(Q_INT32 x, Q_INT32 y, Q_UINT8 s)
00074 {
00075     KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, true);
00076 
00077     Q_UINT8 *pix = iter.rawData();
00078 
00079     *pix = s;
00080 }
00081 
00082 QImage KisSelection::maskImage()
00083 {
00084     // If part of a KisAdjustmentLayer, there may be no parent device.
00085     QImage img;
00086     QRect bounds;
00087     if (m_parentPaintDevice) {
00088 
00089         bounds = m_parentPaintDevice->exactBounds();
00090         bounds = bounds.intersect( m_parentPaintDevice->image()->bounds() );
00091         img = QImage(bounds.width(), bounds.height(), 32);
00092     }
00093     else {
00094         bounds = QRect( 0, 0, image()->width(), image()->height());
00095         img = QImage(bounds.width(), bounds.height(), 32);
00096     }
00097 
00098     KisHLineIteratorPixel it = createHLineIterator(bounds.x(), bounds.y(), bounds.width(), false);
00099     for (int y2 = bounds.y(); y2 < bounds.height() - bounds.y(); ++y2) {
00100             int x2 = 0;
00101             while (!it.isDone()) {
00102                     Q_UINT8 s = MAX_SELECTED - *(it.rawData());
00103                     Q_INT32 c = qRgb(s, s, s);
00104                     img.setPixel(x2, y2, c);
00105                     ++x2;
00106                     ++it;
00107             }
00108             it.nextRow();
00109     }
00110     return img;
00111 }
00112 void KisSelection::select(QRect r)
00113 {
00114     KisFillPainter painter(this);
00115     KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getRGB8();
00116     painter.fillRect(r, KisColor(Qt::white, cs), MAX_SELECTED);
00117     Q_INT32 x, y, w, h;
00118     extent(x, y, w, h);
00119 }
00120 
00121 void KisSelection::clear(QRect r)
00122 {
00123     KisFillPainter painter(this);
00124     KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getRGB8();
00125     painter.fillRect(r, KisColor(Qt::white, cs), MIN_SELECTED);
00126 }
00127 
00128 void KisSelection::clear()
00129 {
00130     Q_UINT8 defPixel = MIN_SELECTED;
00131     m_datamanager->setDefaultPixel(&defPixel);
00132     m_datamanager->clear();
00133 }
00134 
00135 void KisSelection::invert()
00136 {
00137     Q_INT32 x,y,w,h;
00138 
00139     extent(x, y, w, h);
00140     KisRectIterator it = createRectIterator(x, y, w, h, true);
00141     while ( ! it.isDone() )
00142     {
00143         // CBR this is wrong only first byte is inverted
00144         // BSAR: But we have always only one byte in this color model :-).
00145         *(it.rawData()) = MAX_SELECTED - *(it.rawData());
00146         ++it;
00147     }
00148     Q_UINT8 defPixel = MAX_SELECTED - *(m_datamanager->defaultPixel());
00149     m_datamanager->setDefaultPixel(&defPixel);
00150 }
00151 
00152 bool KisSelection::isTotallyUnselected(QRect r)
00153 {
00154     if(*(m_datamanager->defaultPixel()) != MIN_SELECTED)
00155         return false;
00156     QRect sr = selectedExactRect();
00157     return ! r.intersects(sr);
00158 }
00159 
00160 bool KisSelection::isProbablyTotallyUnselected(QRect r)
00161 {
00162     if(*(m_datamanager->defaultPixel()) != MIN_SELECTED)
00163         return false;
00164     QRect sr = selectedRect();
00165     return ! r.intersects(sr);
00166 }
00167 
00168 
00169 QRect KisSelection::selectedRect() const
00170 {
00171     if(*(m_datamanager->defaultPixel()) == MIN_SELECTED || !m_parentPaintDevice)
00172         return extent();
00173     else
00174         return extent().unite(m_parentPaintDevice->extent());
00175 }
00176 
00177 QRect KisSelection::selectedExactRect() const
00178 {
00179     if(m_doCacheExactRect)
00180         return m_cachedExactRect;
00181     else if(*(m_datamanager->defaultPixel()) == MIN_SELECTED || !m_parentPaintDevice)
00182         return exactBounds();
00183     else
00184         return exactBounds().unite(m_parentPaintDevice->exactBounds());
00185 }
00186 
00187 void KisSelection::stopCachingExactRect()
00188 {
00189     kdDebug() << "stop caching the exact rect" << endl;
00190     m_doCacheExactRect = false;
00191 }
00192 
00193 
00194 void KisSelection::startCachingExactRect()
00195 {
00196     kdDebug() << "start caching the exact rect" << endl;
00197     if(*(m_datamanager->defaultPixel()) == MIN_SELECTED || !m_parentPaintDevice)
00198         m_cachedExactRect = exactBounds();
00199     else
00200         m_cachedExactRect = exactBounds().unite(m_parentPaintDevice->exactBounds());
00201     m_doCacheExactRect = true;
00202 }
00203 
00204 void KisSelection::paintUniformSelectionRegion(QImage img, const QRect& imageRect, const QRegion& uniformRegion)
00205 {
00206     Q_ASSERT(img.size() == imageRect.size());
00207     Q_ASSERT(imageRect.contains(uniformRegion.boundingRect()));
00208 
00209     if (img.isNull() || img.size() != imageRect.size() || !imageRect.contains(uniformRegion.boundingRect())) {
00210         return;
00211     }
00212 
00213     if (*m_datamanager->defaultPixel() == MIN_SELECTED) {
00214 
00215         QRegion region = uniformRegion & QRegion(imageRect);
00216 
00217         if (!region.isEmpty()) {
00218             QMemArray<QRect> rects = region.rects();
00219 
00220             for (unsigned int i = 0; i < rects.count(); i++) {
00221                 QRect r = rects[i];
00222 
00223                 for (Q_INT32 y = 0; y < r.height(); ++y) {
00224 
00225                     QRgb *imagePixel = reinterpret_cast<QRgb *>(img.scanLine(r.y() - imageRect.y() + y));
00226                     imagePixel += r.x() - imageRect.x();
00227 
00228                     Q_INT32 numPixels = r.width();
00229 
00230                     while (numPixels > 0) {
00231 
00232                         QRgb srcPixel = *imagePixel;
00233                         Q_UINT8 srcGrey = (qRed(srcPixel) + qGreen(srcPixel) + qBlue(srcPixel)) / 9;
00234                         Q_UINT8 srcAlpha = qAlpha(srcPixel);
00235 
00236                         srcGrey = UINT8_MULT(srcGrey, srcAlpha);
00237                         Q_UINT8 dstAlpha = QMAX(srcAlpha, 192);
00238 
00239                         QRgb dstPixel = qRgba(128 + srcGrey, 128 + srcGrey, 165 + srcGrey, dstAlpha);
00240                         *imagePixel = dstPixel;
00241 
00242                         ++imagePixel;
00243                         --numPixels;
00244                     }
00245                 }
00246             }
00247         }
00248     }
00249 }
00250 
00251 void KisSelection::paintSelection(QImage img, Q_INT32 imageRectX, Q_INT32 imageRectY, Q_INT32 imageRectWidth, Q_INT32 imageRectHeight)
00252 {
00253     Q_ASSERT(img.size() == QSize(imageRectWidth, imageRectHeight));
00254 
00255     if (img.isNull() || img.size() != QSize(imageRectWidth, imageRectHeight)) {
00256         return;
00257     }
00258 
00259     QRect imageRect(imageRectX, imageRectY, imageRectWidth, imageRectHeight);
00260     QRect selectionExtent = extent();
00261 
00262     selectionExtent.setLeft(selectionExtent.left() - 1);
00263     selectionExtent.setTop(selectionExtent.top() - 1);
00264     selectionExtent.setWidth(selectionExtent.width() + 2);
00265     selectionExtent.setHeight(selectionExtent.height() + 2);
00266 
00267     QRegion uniformRegion = QRegion(imageRect);
00268     uniformRegion -= QRegion(selectionExtent);
00269 
00270     if (!uniformRegion.isEmpty()) {
00271         paintUniformSelectionRegion(img, imageRect, uniformRegion);
00272     }
00273 
00274     QRect nonuniformRect = imageRect & selectionExtent;
00275 
00276     if (!nonuniformRect.isEmpty()) {
00277 
00278         const Q_INT32 imageRectOffsetX = nonuniformRect.x() - imageRectX;
00279         const Q_INT32 imageRectOffsetY = nonuniformRect.y() - imageRectY;
00280 
00281         imageRectX = nonuniformRect.x();
00282         imageRectY = nonuniformRect.y();
00283         imageRectWidth = nonuniformRect.width();
00284         imageRectHeight = nonuniformRect.height();
00285 
00286         const Q_INT32 NUM_SELECTION_ROWS = 3;
00287 
00288         Q_UINT8 *selectionRow[NUM_SELECTION_ROWS];
00289 
00290         Q_INT32 aboveRowIndex = 0;
00291         Q_INT32 centreRowIndex = 1;
00292         Q_INT32 belowRowIndex = 2;
00293 
00294         selectionRow[aboveRowIndex] = new Q_UINT8[imageRectWidth + 2];
00295         selectionRow[centreRowIndex] = new Q_UINT8[imageRectWidth + 2];
00296         selectionRow[belowRowIndex] = new Q_UINT8[imageRectWidth + 2];
00297 
00298         readBytes(selectionRow[centreRowIndex], imageRectX - 1, imageRectY - 1, imageRectWidth + 2, 1);
00299         readBytes(selectionRow[belowRowIndex], imageRectX - 1, imageRectY, imageRectWidth + 2, 1);
00300 
00301         for (Q_INT32 y = 0; y < imageRectHeight; ++y) {
00302 
00303             Q_INT32 oldAboveRowIndex = aboveRowIndex;
00304             aboveRowIndex = centreRowIndex;
00305             centreRowIndex = belowRowIndex;
00306             belowRowIndex = oldAboveRowIndex;
00307 
00308             readBytes(selectionRow[belowRowIndex], imageRectX - 1, imageRectY + y + 1, imageRectWidth + 2, 1);
00309 
00310             const Q_UINT8 *aboveRow = selectionRow[aboveRowIndex] + 1;
00311             const Q_UINT8 *centreRow = selectionRow[centreRowIndex] + 1;
00312             const Q_UINT8 *belowRow = selectionRow[belowRowIndex] + 1;
00313 
00314             QRgb *imagePixel = reinterpret_cast<QRgb *>(img.scanLine(imageRectOffsetY + y));
00315             imagePixel += imageRectOffsetX;
00316 
00317             for (Q_INT32 x = 0; x < imageRectWidth; ++x) {
00318 
00319                 Q_UINT8 centre = *centreRow;
00320 
00321                 if (centre != MAX_SELECTED) {
00322 
00323                     // this is where we come if the pixels should be blue or bluish
00324 
00325                     QRgb srcPixel = *imagePixel;
00326                     Q_UINT8 srcGrey = (qRed(srcPixel) + qGreen(srcPixel) + qBlue(srcPixel)) / 9;
00327                     Q_UINT8 srcAlpha = qAlpha(srcPixel);
00328 
00329                     // Colour influence is proportional to alphaPixel.
00330                     srcGrey = UINT8_MULT(srcGrey, srcAlpha);
00331 
00332                     QRgb dstPixel;
00333 
00334                     if (centre == MIN_SELECTED) {
00335                         //this is where we come if the pixels should be blue (or red outline)
00336 
00337                         Q_UINT8 left = *(centreRow - 1);
00338                         Q_UINT8 right = *(centreRow + 1);
00339                         Q_UINT8 above = *aboveRow;
00340                         Q_UINT8 below = *belowRow;
00341 
00342                         // Stop unselected transparent areas from appearing the same
00343                         // as selected transparent areas.
00344                         Q_UINT8 dstAlpha = QMAX(srcAlpha, 192);
00345 
00346                         // now for a simple outline based on 4-connectivity
00347                         if (left != MIN_SELECTED || right != MIN_SELECTED || above != MIN_SELECTED || below != MIN_SELECTED) {
00348                             dstPixel = qRgba(255, 0, 0, dstAlpha);
00349                         } else {
00350                             dstPixel = qRgba(128 + srcGrey, 128 + srcGrey, 165 + srcGrey, dstAlpha);
00351                         }
00352                     } else {
00353                         dstPixel = qRgba(UINT8_BLEND(qRed(srcPixel), srcGrey + 128, centre),
00354                                          UINT8_BLEND(qGreen(srcPixel), srcGrey + 128, centre),
00355                                          UINT8_BLEND(qBlue(srcPixel), srcGrey + 165, centre),
00356                                          srcAlpha);
00357                     }
00358 
00359                     *imagePixel = dstPixel;
00360                 }
00361 
00362                 aboveRow++;
00363                 centreRow++;
00364                 belowRow++;
00365                 imagePixel++;
00366             }
00367         }
00368 
00369         delete [] selectionRow[aboveRowIndex];
00370         delete [] selectionRow[centreRowIndex];
00371         delete [] selectionRow[belowRowIndex];
00372     }
00373 }
00374 
00375 void KisSelection::paintSelection(QImage img, const QRect& scaledImageRect, const QSize& scaledImageSize, const QSize& imageSize)
00376 {
00377     if (img.isNull() || scaledImageRect.isEmpty() || scaledImageSize.isEmpty() || imageSize.isEmpty()) {
00378         return;
00379     }
00380 
00381     Q_ASSERT(img.size() == scaledImageRect.size());
00382 
00383     if (img.size() != scaledImageRect.size()) {
00384         return;
00385     }
00386 
00387     Q_INT32 imageWidth = imageSize.width();
00388     Q_INT32 imageHeight = imageSize.height();
00389 
00390     QRect selectionExtent = extent();
00391 
00392     selectionExtent.setLeft(selectionExtent.left() - 1);
00393     selectionExtent.setTop(selectionExtent.top() - 1);
00394     selectionExtent.setWidth(selectionExtent.width() + 2);
00395     selectionExtent.setHeight(selectionExtent.height() + 2);
00396 
00397     double xScale = static_cast<double>(scaledImageSize.width()) / imageWidth;
00398     double yScale = static_cast<double>(scaledImageSize.height()) / imageHeight;
00399 
00400     QRect scaledSelectionExtent;
00401 
00402     scaledSelectionExtent.setLeft(static_cast<int>(selectionExtent.left() * xScale));
00403     scaledSelectionExtent.setRight(static_cast<int>(ceil((selectionExtent.right() + 1) * xScale)) - 1);
00404     scaledSelectionExtent.setTop(static_cast<int>(selectionExtent.top() * yScale));
00405     scaledSelectionExtent.setBottom(static_cast<int>(ceil((selectionExtent.bottom() + 1) * yScale)) - 1);
00406 
00407     QRegion uniformRegion = QRegion(scaledImageRect);
00408     uniformRegion -= QRegion(scaledSelectionExtent);
00409 
00410     if (!uniformRegion.isEmpty()) {
00411         paintUniformSelectionRegion(img, scaledImageRect, uniformRegion);
00412     }
00413 
00414     QRect nonuniformRect = scaledImageRect & scaledSelectionExtent;
00415 
00416     if (!nonuniformRect.isEmpty()) {
00417 
00418         const Q_INT32 scaledImageRectXOffset = nonuniformRect.x() - scaledImageRect.x();
00419         const Q_INT32 scaledImageRectYOffset = nonuniformRect.y() - scaledImageRect.y();
00420 
00421         const Q_INT32 scaledImageRectX = nonuniformRect.x();
00422         const Q_INT32 scaledImageRectY = nonuniformRect.y();
00423         const Q_INT32 scaledImageRectWidth = nonuniformRect.width();
00424         const Q_INT32 scaledImageRectHeight = nonuniformRect.height();
00425 
00426         const Q_INT32 imageRowLeft = static_cast<Q_INT32>(scaledImageRectX / xScale);
00427         const Q_INT32 imageRowRight = static_cast<Q_INT32>((ceil((scaledImageRectX + scaledImageRectWidth - 1 + 1) / xScale)) - 1);
00428 
00429         const Q_INT32 imageRowWidth = imageRowRight - imageRowLeft + 1;
00430         const Q_INT32 imageRowStride = imageRowWidth + 2;
00431 
00432         const Q_INT32 NUM_SELECTION_ROWS = 3;
00433 
00434         Q_INT32 aboveRowIndex = 0;
00435         Q_INT32 centreRowIndex = 1;
00436         Q_INT32 belowRowIndex = 2;
00437 
00438         Q_INT32 aboveRowSrcY = -3;
00439         Q_INT32 centreRowSrcY = -3;
00440         Q_INT32 belowRowSrcY = -3;
00441 
00442         Q_UINT8 *selectionRows = new Q_UINT8[imageRowStride * NUM_SELECTION_ROWS];
00443         Q_UINT8 *selectionRow[NUM_SELECTION_ROWS];
00444 
00445         selectionRow[0] = selectionRows + 1;
00446         selectionRow[1] = selectionRow[0] + imageRowStride;
00447         selectionRow[2] = selectionRow[0] + (2 * imageRowStride);
00448 
00449         for (Q_INT32 y = 0; y < scaledImageRectHeight; ++y) {
00450 
00451             Q_INT32 scaledY = scaledImageRectY + y;
00452             Q_INT32 srcY = (scaledY * imageHeight) / scaledImageSize.height();
00453 
00454             Q_UINT8 *aboveRow;
00455             Q_UINT8 *centreRow;
00456             Q_UINT8 *belowRow;
00457 
00458             if (srcY - 1 == aboveRowSrcY) {
00459                 aboveRow = selectionRow[aboveRowIndex];
00460                 centreRow = selectionRow[centreRowIndex];
00461                 belowRow = selectionRow[belowRowIndex];
00462             } else if (srcY - 1 == centreRowSrcY) {
00463 
00464                 Q_INT32 oldAboveRowIndex = aboveRowIndex;
00465 
00466                 aboveRowIndex = centreRowIndex;
00467                 centreRowIndex = belowRowIndex;
00468                 belowRowIndex = oldAboveRowIndex;
00469 
00470                 aboveRow = selectionRow[aboveRowIndex];
00471                 centreRow = selectionRow[centreRowIndex];
00472                 belowRow = selectionRow[belowRowIndex];
00473 
00474                 readBytes(belowRow - 1, imageRowLeft - 1, srcY + 1, imageRowStride, 1);
00475 
00476             } else if (srcY - 1 == belowRowSrcY) {
00477 
00478                 Q_INT32 oldAboveRowIndex = aboveRowIndex;
00479                 Q_INT32 oldCentreRowIndex = centreRowIndex;
00480 
00481                 aboveRowIndex = belowRowIndex;
00482                 centreRowIndex = oldAboveRowIndex;
00483                 belowRowIndex = oldCentreRowIndex;
00484 
00485                 aboveRow = selectionRow[aboveRowIndex];
00486                 centreRow = selectionRow[centreRowIndex];
00487                 belowRow = selectionRow[belowRowIndex];
00488 
00489                 if (belowRowIndex == centreRowIndex + 1) {
00490                     readBytes(centreRow - 1, imageRowLeft - 1, srcY, imageRowStride, 2);
00491                 } else {
00492                     readBytes(centreRow - 1, imageRowLeft - 1, srcY, imageRowStride, 1);
00493                     readBytes(belowRow - 1, imageRowLeft - 1, srcY + 1, imageRowStride, 1);
00494                 }
00495 
00496             } else {
00497 
00498                 aboveRowIndex = 0;
00499                 centreRowIndex = 1;
00500                 belowRowIndex = 2;
00501 
00502                 aboveRow = selectionRow[aboveRowIndex];
00503                 centreRow = selectionRow[centreRowIndex];
00504                 belowRow = selectionRow[belowRowIndex];
00505 
00506                 readBytes(selectionRows, imageRowLeft - 1, srcY - 1, imageRowStride, NUM_SELECTION_ROWS);
00507             }
00508 
00509             aboveRowSrcY = srcY - 1;
00510             centreRowSrcY = aboveRowSrcY + 1;
00511             belowRowSrcY = centreRowSrcY + 1;
00512 
00513             QRgb *imagePixel = reinterpret_cast<QRgb *>(img.scanLine(scaledImageRectYOffset + y));
00514             imagePixel += scaledImageRectXOffset;
00515 
00516             for (Q_INT32 x = 0; x < scaledImageRectWidth; ++x) {
00517 
00518                 Q_INT32 scaledX = scaledImageRectX + x;
00519                 Q_INT32 srcX = (scaledX * imageWidth) / scaledImageSize.width();
00520 
00521                 Q_UINT8 centre = *(centreRow + srcX - imageRowLeft);
00522 
00523                 if (centre != MAX_SELECTED) {
00524 
00525                     // this is where we come if the pixels should be blue or bluish
00526 
00527                     QRgb srcPixel = *imagePixel;
00528                     Q_UINT8 srcGrey = (qRed(srcPixel) + qGreen(srcPixel) + qBlue(srcPixel)) / 9;
00529                     Q_UINT8 srcAlpha = qAlpha(srcPixel);
00530 
00531                     // Colour influence is proportional to alphaPixel.
00532                     srcGrey = UINT8_MULT(srcGrey, srcAlpha);
00533 
00534                     QRgb dstPixel;
00535 
00536                     if (centre == MIN_SELECTED) {
00537                         //this is where we come if the pixels should be blue (or red outline)
00538 
00539                         Q_UINT8 left = *(centreRow + (srcX - imageRowLeft) - 1);
00540                         Q_UINT8 right = *(centreRow + (srcX - imageRowLeft) + 1);
00541                         Q_UINT8 above = *(aboveRow + (srcX - imageRowLeft));
00542                         Q_UINT8 below = *(belowRow + (srcX - imageRowLeft));
00543 
00544                         // Stop unselected transparent areas from appearing the same
00545                         // as selected transparent areas.
00546                         Q_UINT8 dstAlpha = QMAX(srcAlpha, 192);
00547 
00548                         // now for a simple outline based on 4-connectivity
00549                         if (left != MIN_SELECTED || right != MIN_SELECTED || above != MIN_SELECTED || below != MIN_SELECTED) {
00550                             dstPixel = qRgba(255, 0, 0, dstAlpha);
00551                         } else {
00552                             dstPixel = qRgba(128 + srcGrey, 128 + srcGrey, 165 + srcGrey, dstAlpha);
00553                         }
00554                     } else {
00555                         dstPixel = qRgba(UINT8_BLEND(qRed(srcPixel), srcGrey + 128, centre),
00556                                          UINT8_BLEND(qGreen(srcPixel), srcGrey + 128, centre),
00557                                          UINT8_BLEND(qBlue(srcPixel), srcGrey + 165, centre),
00558                                          srcAlpha);
00559                     }
00560 
00561                     *imagePixel = dstPixel;
00562                 }
00563 
00564                 imagePixel++;
00565             }
00566         }
00567 
00568         delete [] selectionRows;
00569     }
00570 }
00571 
00572 void KisSelection::setDirty(const QRect& rc)
00573 {
00574     if (m_dirty)
00575         super::setDirty(rc);
00576 }
00577 
00578 void KisSelection::setDirty()
00579 {
00580     if (m_dirty)
00581         super::setDirty();
00582 }
KDE Home | KDE Accessibility Home | Description of Access Keys