KOffice – TDE office suite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

kis_selection.cc 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. /*
  2. * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
  3. *
  4. * this program is free software; you can redistribute it and/or modify
  5. * it under the terms of the gnu general public license as published by
  6. * the free software foundation; either version 2 of the license, or
  7. * (at your option) any later version.
  8. *
  9. * this program is distributed in the hope that it will be useful,
  10. * but without any warranty; without even the implied warranty of
  11. * merchantability or fitness for a particular purpose. see the
  12. * gnu general public license for more details.
  13. *
  14. * you should have received a copy of the gnu general public license
  15. * along with this program; if not, write to the free software
  16. * foundation, inc., 675 mass ave, cambridge, ma 02139, usa.
  17. */
  18. #include <tqimage.h>
  19. #include <kdebug.h>
  20. #include <tdelocale.h>
  21. #include <tqcolor.h>
  22. #include "kis_layer.h"
  23. #include "kis_debug_areas.h"
  24. #include "kis_types.h"
  25. #include "kis_colorspace_factory_registry.h"
  26. #include "kis_fill_painter.h"
  27. #include "kis_iterators_pixel.h"
  28. #include "kis_integer_maths.h"
  29. #include "kis_image.h"
  30. #include "kis_datamanager.h"
  31. #include "kis_fill_painter.h"
  32. #include "kis_selection.h"
  33. KisSelection::KisSelection(KisPaintDeviceSP dev)
  34. : super(dev->parentLayer()
  35. , KisMetaRegistry::instance()->csRegistry()->getAlpha8()
  36. , (TQString("selection for ") + dev->name()).latin1())
  37. , m_parentPaintDevice(dev)
  38. , m_doCacheExactRect(false)
  39. , m_dirty(false)
  40. {
  41. Q_ASSERT(dev);
  42. }
  43. KisSelection::KisSelection()
  44. : super(KisMetaRegistry::instance()->csRegistry()->getAlpha8(), "anonymous selection")
  45. , m_parentPaintDevice(0), m_dirty(false)
  46. {
  47. }
  48. KisSelection::KisSelection(const KisSelection& rhs)
  49. : super(rhs), m_parentPaintDevice(rhs.m_parentPaintDevice), m_doCacheExactRect(rhs.m_doCacheExactRect),
  50. m_cachedExactRect(rhs.m_cachedExactRect), m_dirty(rhs.m_dirty)
  51. {
  52. }
  53. KisSelection::~KisSelection()
  54. {
  55. }
  56. TQ_UINT8 KisSelection::selected(TQ_INT32 x, TQ_INT32 y)
  57. {
  58. KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, false);
  59. TQ_UINT8 *pix = iter.rawData();
  60. return *pix;
  61. }
  62. void KisSelection::setSelected(TQ_INT32 x, TQ_INT32 y, TQ_UINT8 s)
  63. {
  64. KisHLineIteratorPixel iter = createHLineIterator(x, y, 1, true);
  65. TQ_UINT8 *pix = iter.rawData();
  66. *pix = s;
  67. }
  68. TQImage KisSelection::maskImage()
  69. {
  70. // If part of a KisAdjustmentLayer, there may be no parent device.
  71. TQImage img;
  72. TQRect bounds;
  73. if (m_parentPaintDevice) {
  74. bounds = m_parentPaintDevice->exactBounds();
  75. bounds = bounds.intersect( m_parentPaintDevice->image()->bounds() );
  76. img = TQImage(bounds.width(), bounds.height(), 32);
  77. }
  78. else {
  79. bounds = TQRect( 0, 0, image()->width(), image()->height());
  80. img = TQImage(bounds.width(), bounds.height(), 32);
  81. }
  82. KisHLineIteratorPixel it = createHLineIterator(bounds.x(), bounds.y(), bounds.width(), false);
  83. for (int y2 = bounds.y(); y2 < bounds.height() - bounds.y(); ++y2) {
  84. int x2 = 0;
  85. while (!it.isDone()) {
  86. TQ_UINT8 s = MAX_SELECTED - *(it.rawData());
  87. TQ_INT32 c = tqRgb(s, s, s);
  88. img.setPixel(x2, y2, c);
  89. ++x2;
  90. ++it;
  91. }
  92. it.nextRow();
  93. }
  94. return img;
  95. }
  96. void KisSelection::select(TQRect r)
  97. {
  98. KisFillPainter painter(this);
  99. KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getRGB8();
  100. painter.fillRect(r, KisColor(TQt::white, cs), MAX_SELECTED);
  101. TQ_INT32 x, y, w, h;
  102. extent(x, y, w, h);
  103. }
  104. void KisSelection::clear(TQRect r)
  105. {
  106. KisFillPainter painter(this);
  107. KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getRGB8();
  108. painter.fillRect(r, KisColor(TQt::white, cs), MIN_SELECTED);
  109. }
  110. void KisSelection::clear()
  111. {
  112. TQ_UINT8 defPixel = MIN_SELECTED;
  113. m_datamanager->setDefaultPixel(&defPixel);
  114. m_datamanager->clear();
  115. }
  116. void KisSelection::invert()
  117. {
  118. TQ_INT32 x,y,w,h;
  119. extent(x, y, w, h);
  120. KisRectIterator it = createRectIterator(x, y, w, h, true);
  121. while ( ! it.isDone() )
  122. {
  123. // CBR this is wrong only first byte is inverted
  124. // BSAR: But we have always only one byte in this color model :-).
  125. *(it.rawData()) = MAX_SELECTED - *(it.rawData());
  126. ++it;
  127. }
  128. TQ_UINT8 defPixel = MAX_SELECTED - *(m_datamanager->defaultPixel());
  129. m_datamanager->setDefaultPixel(&defPixel);
  130. }
  131. bool KisSelection::isTotallyUnselected(TQRect r)
  132. {
  133. if(*(m_datamanager->defaultPixel()) != MIN_SELECTED)
  134. return false;
  135. TQRect sr = selectedExactRect();
  136. return ! r.intersects(sr);
  137. }
  138. bool KisSelection::isProbablyTotallyUnselected(TQRect r)
  139. {
  140. if(*(m_datamanager->defaultPixel()) != MIN_SELECTED)
  141. return false;
  142. TQRect sr = selectedRect();
  143. return ! r.intersects(sr);
  144. }
  145. TQRect KisSelection::selectedRect() const
  146. {
  147. if(*(m_datamanager->defaultPixel()) == MIN_SELECTED || !m_parentPaintDevice)
  148. return extent();
  149. else
  150. return extent().unite(m_parentPaintDevice->extent());
  151. }
  152. TQRect KisSelection::selectedExactRect() const
  153. {
  154. if(m_doCacheExactRect)
  155. return m_cachedExactRect;
  156. else if(*(m_datamanager->defaultPixel()) == MIN_SELECTED || !m_parentPaintDevice)
  157. return exactBounds();
  158. else
  159. return exactBounds().unite(m_parentPaintDevice->exactBounds());
  160. }
  161. void KisSelection::stopCachingExactRect()
  162. {
  163. kdDebug() << "stop caching the exact rect" << endl;
  164. m_doCacheExactRect = false;
  165. }
  166. void KisSelection::startCachingExactRect()
  167. {
  168. kdDebug() << "start caching the exact rect" << endl;
  169. if(*(m_datamanager->defaultPixel()) == MIN_SELECTED || !m_parentPaintDevice)
  170. m_cachedExactRect = exactBounds();
  171. else
  172. m_cachedExactRect = exactBounds().unite(m_parentPaintDevice->exactBounds());
  173. m_doCacheExactRect = true;
  174. }
  175. void KisSelection::paintUniformSelectionRegion(TQImage img, const TQRect& imageRect, const TQRegion& uniformRegion)
  176. {
  177. Q_ASSERT(img.size() == imageRect.size());
  178. Q_ASSERT(imageRect.contains(uniformRegion.boundingRect()));
  179. if (img.isNull() || img.size() != imageRect.size() || !imageRect.contains(uniformRegion.boundingRect())) {
  180. return;
  181. }
  182. if (*m_datamanager->defaultPixel() == MIN_SELECTED) {
  183. TQRegion region = uniformRegion & TQRegion(imageRect);
  184. if (!region.isEmpty()) {
  185. TQMemArray<TQRect> rects = region.rects();
  186. for (unsigned int i = 0; i < rects.count(); i++) {
  187. TQRect r = rects[i];
  188. for (TQ_INT32 y = 0; y < r.height(); ++y) {
  189. TQRgb *imagePixel = reinterpret_cast<TQRgb *>(img.scanLine(r.y() - imageRect.y() + y));
  190. imagePixel += r.x() - imageRect.x();
  191. TQ_INT32 numPixels = r.width();
  192. while (numPixels > 0) {
  193. TQRgb srcPixel = *imagePixel;
  194. TQ_UINT8 srcGrey = (tqRed(srcPixel) + tqGreen(srcPixel) + tqBlue(srcPixel)) / 9;
  195. TQ_UINT8 srcAlpha = tqAlpha(srcPixel);
  196. srcGrey = UINT8_MULT(srcGrey, srcAlpha);
  197. TQ_UINT8 dstAlpha = TQMAX(srcAlpha, 192);
  198. TQRgb dstPixel = tqRgba(128 + srcGrey, 128 + srcGrey, 165 + srcGrey, dstAlpha);
  199. *imagePixel = dstPixel;
  200. ++imagePixel;
  201. --numPixels;
  202. }
  203. }
  204. }
  205. }
  206. }
  207. }
  208. void KisSelection::paintSelection(TQImage img, TQ_INT32 imageRectX, TQ_INT32 imageRectY, TQ_INT32 imageRectWidth, TQ_INT32 imageRectHeight)
  209. {
  210. Q_ASSERT(img.size() == TQSize(imageRectWidth, imageRectHeight));
  211. if (img.isNull() || img.size() != TQSize(imageRectWidth, imageRectHeight)) {
  212. return;
  213. }
  214. TQRect imageRect(imageRectX, imageRectY, imageRectWidth, imageRectHeight);
  215. TQRect selectionExtent = extent();
  216. selectionExtent.setLeft(selectionExtent.left() - 1);
  217. selectionExtent.setTop(selectionExtent.top() - 1);
  218. selectionExtent.setWidth(selectionExtent.width() + 2);
  219. selectionExtent.setHeight(selectionExtent.height() + 2);
  220. TQRegion uniformRegion = TQRegion(imageRect);
  221. uniformRegion -= TQRegion(selectionExtent);
  222. if (!uniformRegion.isEmpty()) {
  223. paintUniformSelectionRegion(img, imageRect, uniformRegion);
  224. }
  225. TQRect nonuniformRect = imageRect & selectionExtent;
  226. if (!nonuniformRect.isEmpty()) {
  227. const TQ_INT32 imageRectOffsetX = nonuniformRect.x() - imageRectX;
  228. const TQ_INT32 imageRectOffsetY = nonuniformRect.y() - imageRectY;
  229. imageRectX = nonuniformRect.x();
  230. imageRectY = nonuniformRect.y();
  231. imageRectWidth = nonuniformRect.width();
  232. imageRectHeight = nonuniformRect.height();
  233. const TQ_INT32 NUM_SELECTION_ROWS = 3;
  234. TQ_UINT8 *selectionRow[NUM_SELECTION_ROWS];
  235. TQ_INT32 aboveRowIndex = 0;
  236. TQ_INT32 centreRowIndex = 1;
  237. TQ_INT32 belowRowIndex = 2;
  238. selectionRow[aboveRowIndex] = new TQ_UINT8[imageRectWidth + 2];
  239. selectionRow[centreRowIndex] = new TQ_UINT8[imageRectWidth + 2];
  240. selectionRow[belowRowIndex] = new TQ_UINT8[imageRectWidth + 2];
  241. readBytes(selectionRow[centreRowIndex], imageRectX - 1, imageRectY - 1, imageRectWidth + 2, 1);
  242. readBytes(selectionRow[belowRowIndex], imageRectX - 1, imageRectY, imageRectWidth + 2, 1);
  243. for (TQ_INT32 y = 0; y < imageRectHeight; ++y) {
  244. TQ_INT32 oldAboveRowIndex = aboveRowIndex;
  245. aboveRowIndex = centreRowIndex;
  246. centreRowIndex = belowRowIndex;
  247. belowRowIndex = oldAboveRowIndex;
  248. readBytes(selectionRow[belowRowIndex], imageRectX - 1, imageRectY + y + 1, imageRectWidth + 2, 1);
  249. const TQ_UINT8 *aboveRow = selectionRow[aboveRowIndex] + 1;
  250. const TQ_UINT8 *centreRow = selectionRow[centreRowIndex] + 1;
  251. const TQ_UINT8 *belowRow = selectionRow[belowRowIndex] + 1;
  252. TQRgb *imagePixel = reinterpret_cast<TQRgb *>(img.scanLine(imageRectOffsetY + y));
  253. imagePixel += imageRectOffsetX;
  254. for (TQ_INT32 x = 0; x < imageRectWidth; ++x) {
  255. TQ_UINT8 centre = *centreRow;
  256. if (centre != MAX_SELECTED) {
  257. // this is where we come if the pixels should be blue or bluish
  258. TQRgb srcPixel = *imagePixel;
  259. TQ_UINT8 srcGrey = (tqRed(srcPixel) + tqGreen(srcPixel) + tqBlue(srcPixel)) / 9;
  260. TQ_UINT8 srcAlpha = tqAlpha(srcPixel);
  261. // Colour influence is proportional to alphaPixel.
  262. srcGrey = UINT8_MULT(srcGrey, srcAlpha);
  263. TQRgb dstPixel;
  264. if (centre == MIN_SELECTED) {
  265. //this is where we come if the pixels should be blue (or red outline)
  266. TQ_UINT8 left = *(centreRow - 1);
  267. TQ_UINT8 right = *(centreRow + 1);
  268. TQ_UINT8 above = *aboveRow;
  269. TQ_UINT8 below = *belowRow;
  270. // Stop unselected transparent areas from appearing the same
  271. // as selected transparent areas.
  272. TQ_UINT8 dstAlpha = TQMAX(srcAlpha, 192);
  273. // now for a simple outline based on 4-connectivity
  274. if (left != MIN_SELECTED || right != MIN_SELECTED || above != MIN_SELECTED || below != MIN_SELECTED) {
  275. dstPixel = tqRgba(255, 0, 0, dstAlpha);
  276. } else {
  277. dstPixel = tqRgba(128 + srcGrey, 128 + srcGrey, 165 + srcGrey, dstAlpha);
  278. }
  279. } else {
  280. dstPixel = tqRgba(UINT8_BLEND(tqRed(srcPixel), srcGrey + 128, centre),
  281. UINT8_BLEND(tqGreen(srcPixel), srcGrey + 128, centre),
  282. UINT8_BLEND(tqBlue(srcPixel), srcGrey + 165, centre),
  283. srcAlpha);
  284. }
  285. *imagePixel = dstPixel;
  286. }
  287. aboveRow++;
  288. centreRow++;
  289. belowRow++;
  290. imagePixel++;
  291. }
  292. }
  293. delete [] selectionRow[aboveRowIndex];
  294. delete [] selectionRow[centreRowIndex];
  295. delete [] selectionRow[belowRowIndex];
  296. }
  297. }
  298. void KisSelection::paintSelection(TQImage img, const TQRect& scaledImageRect, const TQSize& scaledImageSize, const TQSize& imageSize)
  299. {
  300. if (img.isNull() || scaledImageRect.isEmpty() || scaledImageSize.isEmpty() || imageSize.isEmpty()) {
  301. return;
  302. }
  303. Q_ASSERT(img.size() == scaledImageRect.size());
  304. if (img.size() != scaledImageRect.size()) {
  305. return;
  306. }
  307. TQ_INT32 imageWidth = imageSize.width();
  308. TQ_INT32 imageHeight = imageSize.height();
  309. TQRect selectionExtent = extent();
  310. selectionExtent.setLeft(selectionExtent.left() - 1);
  311. selectionExtent.setTop(selectionExtent.top() - 1);
  312. selectionExtent.setWidth(selectionExtent.width() + 2);
  313. selectionExtent.setHeight(selectionExtent.height() + 2);
  314. double xScale = static_cast<double>(scaledImageSize.width()) / imageWidth;
  315. double yScale = static_cast<double>(scaledImageSize.height()) / imageHeight;
  316. TQRect scaledSelectionExtent;
  317. scaledSelectionExtent.setLeft(static_cast<int>(selectionExtent.left() * xScale));
  318. scaledSelectionExtent.setRight(static_cast<int>(ceil((selectionExtent.right() + 1) * xScale)) - 1);
  319. scaledSelectionExtent.setTop(static_cast<int>(selectionExtent.top() * yScale));
  320. scaledSelectionExtent.setBottom(static_cast<int>(ceil((selectionExtent.bottom() + 1) * yScale)) - 1);
  321. TQRegion uniformRegion = TQRegion(scaledImageRect);
  322. uniformRegion -= TQRegion(scaledSelectionExtent);
  323. if (!uniformRegion.isEmpty()) {
  324. paintUniformSelectionRegion(img, scaledImageRect, uniformRegion);
  325. }
  326. TQRect nonuniformRect = scaledImageRect & scaledSelectionExtent;
  327. if (!nonuniformRect.isEmpty()) {
  328. const TQ_INT32 scaledImageRectXOffset = nonuniformRect.x() - scaledImageRect.x();
  329. const TQ_INT32 scaledImageRectYOffset = nonuniformRect.y() - scaledImageRect.y();
  330. const TQ_INT32 scaledImageRectX = nonuniformRect.x();
  331. const TQ_INT32 scaledImageRectY = nonuniformRect.y();
  332. const TQ_INT32 scaledImageRectWidth = nonuniformRect.width();
  333. const TQ_INT32 scaledImageRectHeight = nonuniformRect.height();
  334. const TQ_INT32 imageRowLeft = static_cast<TQ_INT32>(scaledImageRectX / xScale);
  335. const TQ_INT32 imageRowRight = static_cast<TQ_INT32>((ceil((scaledImageRectX + scaledImageRectWidth - 1 + 1) / xScale)) - 1);
  336. const TQ_INT32 imageRowWidth = imageRowRight - imageRowLeft + 1;
  337. const TQ_INT32 imageRowStride = imageRowWidth + 2;
  338. const TQ_INT32 NUM_SELECTION_ROWS = 3;
  339. TQ_INT32 aboveRowIndex = 0;
  340. TQ_INT32 centreRowIndex = 1;
  341. TQ_INT32 belowRowIndex = 2;
  342. TQ_INT32 aboveRowSrcY = -3;
  343. TQ_INT32 centreRowSrcY = -3;
  344. TQ_INT32 belowRowSrcY = -3;
  345. TQ_UINT8 *selectionRows = new TQ_UINT8[imageRowStride * NUM_SELECTION_ROWS];
  346. TQ_UINT8 *selectionRow[NUM_SELECTION_ROWS];
  347. selectionRow[0] = selectionRows + 1;
  348. selectionRow[1] = selectionRow[0] + imageRowStride;
  349. selectionRow[2] = selectionRow[0] + (2 * imageRowStride);
  350. for (TQ_INT32 y = 0; y < scaledImageRectHeight; ++y) {
  351. TQ_INT32 scaledY = scaledImageRectY + y;
  352. TQ_INT32 srcY = (scaledY * imageHeight) / scaledImageSize.height();
  353. TQ_UINT8 *aboveRow;
  354. TQ_UINT8 *centreRow;
  355. TQ_UINT8 *belowRow;
  356. if (srcY - 1 == aboveRowSrcY) {
  357. aboveRow = selectionRow[aboveRowIndex];
  358. centreRow = selectionRow[centreRowIndex];
  359. belowRow = selectionRow[belowRowIndex];
  360. } else if (srcY - 1 == centreRowSrcY) {
  361. TQ_INT32 oldAboveRowIndex = aboveRowIndex;
  362. aboveRowIndex = centreRowIndex;
  363. centreRowIndex = belowRowIndex;
  364. belowRowIndex = oldAboveRowIndex;
  365. aboveRow = selectionRow[aboveRowIndex];
  366. centreRow = selectionRow[centreRowIndex];
  367. belowRow = selectionRow[belowRowIndex];
  368. readBytes(belowRow - 1, imageRowLeft - 1, srcY + 1, imageRowStride, 1);
  369. } else if (srcY - 1 == belowRowSrcY) {
  370. TQ_INT32 oldAboveRowIndex = aboveRowIndex;
  371. TQ_INT32 oldCentreRowIndex = centreRowIndex;
  372. aboveRowIndex = belowRowIndex;
  373. centreRowIndex = oldAboveRowIndex;
  374. belowRowIndex = oldCentreRowIndex;
  375. aboveRow = selectionRow[aboveRowIndex];
  376. centreRow = selectionRow[centreRowIndex];
  377. belowRow = selectionRow[belowRowIndex];
  378. if (belowRowIndex == centreRowIndex + 1) {
  379. readBytes(centreRow - 1, imageRowLeft - 1, srcY, imageRowStride, 2);
  380. } else {
  381. readBytes(centreRow - 1, imageRowLeft - 1, srcY, imageRowStride, 1);
  382. readBytes(belowRow - 1, imageRowLeft - 1, srcY + 1, imageRowStride, 1);
  383. }
  384. } else {
  385. aboveRowIndex = 0;
  386. centreRowIndex = 1;
  387. belowRowIndex = 2;
  388. aboveRow = selectionRow[aboveRowIndex];
  389. centreRow = selectionRow[centreRowIndex];
  390. belowRow = selectionRow[belowRowIndex];
  391. readBytes(selectionRows, imageRowLeft - 1, srcY - 1, imageRowStride, NUM_SELECTION_ROWS);
  392. }
  393. aboveRowSrcY = srcY - 1;
  394. centreRowSrcY = aboveRowSrcY + 1;
  395. belowRowSrcY = centreRowSrcY + 1;
  396. TQRgb *imagePixel = reinterpret_cast<TQRgb *>(img.scanLine(scaledImageRectYOffset + y));
  397. imagePixel += scaledImageRectXOffset;
  398. for (TQ_INT32 x = 0; x < scaledImageRectWidth; ++x) {
  399. TQ_INT32 scaledX = scaledImageRectX + x;
  400. TQ_INT32 srcX = (scaledX * imageWidth) / scaledImageSize.width();
  401. TQ_UINT8 centre = *(centreRow + srcX - imageRowLeft);
  402. if (centre != MAX_SELECTED) {
  403. // this is where we come if the pixels should be blue or bluish
  404. TQRgb srcPixel = *imagePixel;
  405. TQ_UINT8 srcGrey = (tqRed(srcPixel) + tqGreen(srcPixel) + tqBlue(srcPixel)) / 9;
  406. TQ_UINT8 srcAlpha = tqAlpha(srcPixel);
  407. // Colour influence is proportional to alphaPixel.
  408. srcGrey = UINT8_MULT(srcGrey, srcAlpha);
  409. TQRgb dstPixel;
  410. if (centre == MIN_SELECTED) {
  411. //this is where we come if the pixels should be blue (or red outline)
  412. TQ_UINT8 left = *(centreRow + (srcX - imageRowLeft) - 1);
  413. TQ_UINT8 right = *(centreRow + (srcX - imageRowLeft) + 1);
  414. TQ_UINT8 above = *(aboveRow + (srcX - imageRowLeft));
  415. TQ_UINT8 below = *(belowRow + (srcX - imageRowLeft));
  416. // Stop unselected transparent areas from appearing the same
  417. // as selected transparent areas.
  418. TQ_UINT8 dstAlpha = TQMAX(srcAlpha, 192);
  419. // now for a simple outline based on 4-connectivity
  420. if (left != MIN_SELECTED || right != MIN_SELECTED || above != MIN_SELECTED || below != MIN_SELECTED) {
  421. dstPixel = tqRgba(255, 0, 0, dstAlpha);
  422. } else {
  423. dstPixel = tqRgba(128 + srcGrey, 128 + srcGrey, 165 + srcGrey, dstAlpha);
  424. }
  425. } else {
  426. dstPixel = tqRgba(UINT8_BLEND(tqRed(srcPixel), srcGrey + 128, centre),
  427. UINT8_BLEND(tqGreen(srcPixel), srcGrey + 128, centre),
  428. UINT8_BLEND(tqBlue(srcPixel), srcGrey + 165, centre),
  429. srcAlpha);
  430. }
  431. *imagePixel = dstPixel;
  432. }
  433. imagePixel++;
  434. }
  435. }
  436. delete [] selectionRows;
  437. }
  438. }
  439. void KisSelection::setDirty(const TQRect& rc)
  440. {
  441. if (m_dirty)
  442. super::setDirty(rc);
  443. }
  444. void KisSelection::setDirty()
  445. {
  446. if (m_dirty)
  447. super::setDirty();
  448. }