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_brush.cc 40KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333
  1. /*
  2. * Copyright (c) 1999 Matthias Elter <me@kde.org>
  3. * Copyright (c) 2003 Patrick Julien <freak@codepimps.org>
  4. * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
  5. * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
  6. * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  21. */
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. #ifdef HAVE_SYS_TYPES_H
  26. #include <sys/types.h>
  27. #endif
  28. #include <netinet/in.h>
  29. #include <limits.h>
  30. #include <stdlib.h>
  31. #include <cfloat>
  32. #include <tqfile.h>
  33. #include <tqimage.h>
  34. #include <tqpoint.h>
  35. #include <tqvaluevector.h>
  36. #include <kdebug.h>
  37. #include <tdelocale.h>
  38. #include <kis_meta_registry.h>
  39. #include "kis_paint_device.h"
  40. #include "kis_global.h"
  41. #include "kis_brush.h"
  42. #include "kis_alpha_mask.h"
  43. #include "kis_colorspace_factory_registry.h"
  44. #include "kis_iterators_pixel.h"
  45. #include "kis_image.h"
  46. namespace {
  47. struct GimpBrushV1Header {
  48. TQ_UINT32 header_size; /* header_size = sizeof (BrushHeader) + brush name */
  49. TQ_UINT32 version; /* brush file version # */
  50. TQ_UINT32 width; /* width of brush */
  51. TQ_UINT32 height; /* height of brush */
  52. TQ_UINT32 bytes; /* depth of brush in bytes */
  53. };
  54. /// All fields are in MSB on disk!
  55. struct GimpBrushHeader {
  56. TQ_UINT32 header_size; /* header_size = sizeof (BrushHeader) + brush name */
  57. TQ_UINT32 version; /* brush file version # */
  58. TQ_UINT32 width; /* width of brush */
  59. TQ_UINT32 height; /* height of brush */
  60. TQ_UINT32 bytes; /* depth of brush in bytes */
  61. /* The following are only defined in version 2 */
  62. TQ_UINT32 magic_number; /* GIMP brush magic number */
  63. TQ_UINT32 spacing; /* brush spacing as % of width & height, 0 - 1000 */
  64. };
  65. // Needed, or the GIMP won't open it!
  66. TQ_UINT32 const GimpV2BrushMagic = ('G' << 24) + ('I' << 16) + ('M' << 8) + ('P' << 0);
  67. }
  68. #define DEFAULT_SPACING 0.25
  69. #define MAXIMUM_SCALE 2
  70. KisBrush::KisBrush(const TQString& filename) : super(filename)
  71. {
  72. m_brushType = INVALID;
  73. m_ownData = true;
  74. m_useColorAsMask = false;
  75. m_hasColor = false;
  76. m_spacing = DEFAULT_SPACING;
  77. m_boundary = 0;
  78. }
  79. KisBrush::KisBrush(const TQString& filename,
  80. const TQByteArray& data,
  81. TQ_UINT32 & dataPos) : super(filename)
  82. {
  83. m_brushType = INVALID;
  84. m_ownData = false;
  85. m_useColorAsMask = false;
  86. m_hasColor = false;
  87. m_spacing = DEFAULT_SPACING;
  88. m_boundary = 0;
  89. m_data.setRawData(data.data() + dataPos, data.size() - dataPos);
  90. init();
  91. m_data.resetRawData(data.data() + dataPos, data.size() - dataPos);
  92. dataPos += m_header_size + (width() * height() * m_bytes);
  93. }
  94. KisBrush::KisBrush(KisPaintDevice* image, int x, int y, int w, int h)
  95. : super(TQString(""))
  96. {
  97. m_brushType = INVALID;
  98. m_ownData = true;
  99. m_useColorAsMask = false;
  100. m_hasColor = true;
  101. m_spacing = DEFAULT_SPACING;
  102. m_boundary = 0;
  103. initFromPaintDev(image, x, y, w, h);
  104. }
  105. KisBrush::KisBrush(const TQImage& image, const TQString& name)
  106. : super(TQString(""))
  107. {
  108. m_ownData = false;
  109. m_useColorAsMask = false;
  110. m_hasColor = true;
  111. m_spacing = DEFAULT_SPACING;
  112. m_boundary = 0;
  113. setImage(image);
  114. setName(name);
  115. setBrushType(IMAGE);
  116. }
  117. KisBrush::~KisBrush()
  118. {
  119. m_scaledBrushes.clear();
  120. delete m_boundary;
  121. }
  122. bool KisBrush::load()
  123. {
  124. if (m_ownData) {
  125. TQFile file(filename());
  126. file.open(IO_ReadOnly);
  127. m_data = file.readAll();
  128. file.close();
  129. }
  130. return init();
  131. }
  132. bool KisBrush::init()
  133. {
  134. GimpBrushHeader bh;
  135. if (sizeof(GimpBrushHeader) > m_data.size()) {
  136. return false;
  137. }
  138. memcpy(&bh, &m_data[0], sizeof(GimpBrushHeader));
  139. bh.header_size = ntohl(bh.header_size);
  140. m_header_size = bh.header_size;
  141. bh.version = ntohl(bh.version);
  142. m_version = bh.version;
  143. bh.width = ntohl(bh.width);
  144. bh.height = ntohl(bh.height);
  145. bh.bytes = ntohl(bh.bytes);
  146. m_bytes = bh.bytes;
  147. bh.magic_number = ntohl(bh.magic_number);
  148. m_magic_number = bh.magic_number;
  149. if (bh.version == 1) {
  150. // No spacing in version 1 files so use Gimp default
  151. bh.spacing = static_cast<int>(DEFAULT_SPACING * 100);
  152. }
  153. else {
  154. bh.spacing = ntohl(bh.spacing);
  155. if (bh.spacing > 1000) {
  156. return false;
  157. }
  158. }
  159. setSpacing(bh.spacing / 100.0);
  160. if (bh.header_size > m_data.size() || bh.header_size == 0) {
  161. return false;
  162. }
  163. TQString name;
  164. if (bh.version == 1) {
  165. // Version 1 has no magic number or spacing, so the name
  166. // is at a different offset. Character encoding is undefined.
  167. const char *text = &m_data[sizeof(GimpBrushV1Header)];
  168. name = TQString::fromAscii(text, bh.header_size - sizeof(GimpBrushV1Header));
  169. } else {
  170. // ### Version = 3->cinepaint; may be float16 data!
  171. // Version >=2: UTF-8 encoding is used
  172. name = TQString::fromUtf8(&m_data[sizeof(GimpBrushHeader)],
  173. bh.header_size - sizeof(GimpBrushHeader));
  174. }
  175. setName(i18n(name.ascii())); // Ascii? And what with real UTF-8 chars?
  176. if (bh.width == 0 || bh.height == 0 || !m_img.create(bh.width, bh.height, 32)) {
  177. return false;
  178. }
  179. TQ_INT32 k = bh.header_size;
  180. if (bh.bytes == 1) {
  181. // Grayscale
  182. if (static_cast<TQ_UINT32>(k + bh.width * bh.height) > m_data.size()) {
  183. return false;
  184. }
  185. m_brushType = MASK;
  186. m_hasColor = false;
  187. for (TQ_UINT32 y = 0; y < bh.height; y++) {
  188. for (TQ_UINT32 x = 0; x < bh.width; x++, k++) {
  189. TQ_INT32 val = 255 - static_cast<uchar>(m_data[k]);
  190. m_img.setPixel(x, y, tqRgb(val, val, val));
  191. }
  192. }
  193. } else if (bh.bytes == 4) {
  194. // RGBA
  195. if (static_cast<TQ_UINT32>(k + (bh.width * bh.height * 4)) > m_data.size()) {
  196. return false;
  197. }
  198. m_brushType = IMAGE;
  199. m_img.setAlphaBuffer(true);
  200. m_hasColor = true;
  201. for (TQ_UINT32 y = 0; y < bh.height; y++) {
  202. for (TQ_UINT32 x = 0; x < bh.width; x++, k += 4) {
  203. m_img.setPixel(x, y, tqRgba(m_data[k],
  204. m_data[k+1],
  205. m_data[k+2],
  206. m_data[k+3]));
  207. }
  208. }
  209. } else {
  210. return false;
  211. }
  212. setWidth(m_img.width());
  213. setHeight(m_img.height());
  214. //createScaledBrushes();
  215. if (m_ownData) {
  216. m_data.resize(0); // Save some memory, we're using enough of it as it is.
  217. }
  218. if (m_img.width() == 0 || m_img.height() == 0)
  219. setValid(false);
  220. else
  221. setValid(true);
  222. return true;
  223. }
  224. bool KisBrush::initFromPaintDev(KisPaintDevice* image, int x, int y, int w, int h) {
  225. // Forcefully convert to RGBA8
  226. // XXX profile and exposure?
  227. setImage(image->convertToTQImage(0, x, y, w, h));
  228. setName(image->name());
  229. m_brushType = IMAGE;
  230. m_hasColor = true;
  231. return true;
  232. }
  233. bool KisBrush::save()
  234. {
  235. TQFile file(filename());
  236. file.open(IO_WriteOnly | IO_Truncate);
  237. bool ok = saveToDevice(TQT_TQIODEVICE(&file));
  238. file.close();
  239. return ok;
  240. }
  241. bool KisBrush::saveToDevice(TQIODevice* dev) const
  242. {
  243. GimpBrushHeader bh;
  244. TQCString utf8Name = name().utf8(); // Names in v2 brushes are in UTF-8
  245. char const* name = utf8Name.data();
  246. int nameLength = tqstrlen(name);
  247. int wrote;
  248. bh.header_size = htonl(sizeof(GimpBrushHeader) + nameLength);
  249. bh.version = htonl(2); // Only RGBA8 data needed atm, no cinepaint stuff
  250. bh.width = htonl(width());
  251. bh.height = htonl(height());
  252. // Hardcoded, 4 bytes RGBA or 1 byte GREY
  253. if (!hasColor())
  254. bh.bytes = htonl(1);
  255. else
  256. bh.bytes = htonl(4);
  257. bh.magic_number = htonl(GimpV2BrushMagic);
  258. bh.spacing = htonl(static_cast<TQ_UINT32>(spacing() * 100.0));
  259. // Write header: first bh, then the name
  260. TQByteArray bytes;
  261. bytes.setRawData(reinterpret_cast<char*>(&bh), sizeof(GimpBrushHeader));
  262. wrote = dev->writeBlock(bytes);
  263. bytes.resetRawData(reinterpret_cast<char*>(&bh), sizeof(GimpBrushHeader));
  264. if (wrote == -1)
  265. return false;
  266. wrote = dev->writeBlock(name, nameLength); // No +1 for the trailing NULL it seems...
  267. if (wrote == -1)
  268. return false;
  269. int k = 0;
  270. if (!hasColor()) {
  271. bytes.resize(width() * height());
  272. for (TQ_INT32 y = 0; y < height(); y++) {
  273. for (TQ_INT32 x = 0; x < width(); x++) {
  274. TQRgb c = m_img.pixel(x, y);
  275. bytes[k++] = static_cast<char>(255 - tqRed(c)); // red == blue == green
  276. }
  277. }
  278. } else {
  279. bytes.resize(width() * height() * 4);
  280. for (TQ_INT32 y = 0; y < height(); y++) {
  281. for (TQ_INT32 x = 0; x < width(); x++) {
  282. // order for gimp brushes, v2 is: RGBA
  283. TQRgb pixel = m_img.pixel(x,y);
  284. bytes[k++] = static_cast<char>(tqRed(pixel));
  285. bytes[k++] = static_cast<char>(tqGreen(pixel));
  286. bytes[k++] = static_cast<char>(tqBlue(pixel));
  287. bytes[k++] = static_cast<char>(tqAlpha(pixel));
  288. }
  289. }
  290. }
  291. wrote = dev->writeBlock(bytes);
  292. if (wrote == -1)
  293. return false;
  294. return true;
  295. }
  296. TQImage KisBrush::img()
  297. {
  298. TQImage image = m_img;
  299. if (hasColor() && useColorAsMask()) {
  300. image.detach();
  301. for (int x = 0; x < image.width(); x++) {
  302. for (int y = 0; y < image.height(); y++) {
  303. TQRgb c = image.pixel(x, y);
  304. int a = (tqGray(c) * tqAlpha(c)) / 255;
  305. image.setPixel(x, y, tqRgba(a, 0, a, a));
  306. }
  307. }
  308. }
  309. return image;
  310. }
  311. KisAlphaMaskSP KisBrush::mask(const KisPaintInformation& info, double subPixelX, double subPixelY) const
  312. {
  313. if (m_scaledBrushes.isEmpty()) {
  314. createScaledBrushes();
  315. }
  316. double scale = scaleForPressure(info.pressure);
  317. const ScaledBrush *aboveBrush = 0;
  318. const ScaledBrush *belowBrush = 0;
  319. findScaledBrushes(scale, &aboveBrush, &belowBrush);
  320. Q_ASSERT(aboveBrush != 0);
  321. KisAlphaMaskSP outputMask = 0;
  322. if (belowBrush != 0) {
  323. // We're in between two masks. Interpolate between them.
  324. KisAlphaMaskSP scaledAboveMask = scaleMask(aboveBrush, scale, subPixelX, subPixelY);
  325. KisAlphaMaskSP scaledBelowMask = scaleMask(belowBrush, scale, subPixelX, subPixelY);
  326. double t = (scale - belowBrush->scale()) / (aboveBrush->scale() - belowBrush->scale());
  327. outputMask = KisAlphaMask::interpolate(scaledBelowMask, scaledAboveMask, t);
  328. } else {
  329. if (fabs(scale - aboveBrush->scale()) < DBL_EPSILON) {
  330. // Exact match.
  331. outputMask = scaleMask(aboveBrush, scale, subPixelX, subPixelY);
  332. } else {
  333. // We are smaller than the smallest mask, which is always 1x1.
  334. double s = scale / aboveBrush->scale();
  335. outputMask = scaleSinglePixelMask(s, aboveBrush->mask()->alphaAt(0, 0), subPixelX, subPixelY);
  336. }
  337. }
  338. return outputMask;
  339. }
  340. KisPaintDeviceSP KisBrush::image(KisColorSpace * /*colorSpace*/, const KisPaintInformation& info, double subPixelX, double subPixelY) const
  341. {
  342. if (m_scaledBrushes.isEmpty()) {
  343. createScaledBrushes();
  344. }
  345. double scale = scaleForPressure(info.pressure);
  346. const ScaledBrush *aboveBrush = 0;
  347. const ScaledBrush *belowBrush = 0;
  348. findScaledBrushes(scale, &aboveBrush, &belowBrush);
  349. Q_ASSERT(aboveBrush != 0);
  350. TQImage outputImage;
  351. if (belowBrush != 0) {
  352. // We're in between two brushes. Interpolate between them.
  353. TQImage scaledAboveImage = scaleImage(aboveBrush, scale, subPixelX, subPixelY);
  354. TQImage scaledBelowImage = scaleImage(belowBrush, scale, subPixelX, subPixelY);
  355. double t = (scale - belowBrush->scale()) / (aboveBrush->scale() - belowBrush->scale());
  356. outputImage = interpolate(scaledBelowImage, scaledAboveImage, t);
  357. } else {
  358. if (fabs(scale - aboveBrush->scale()) < DBL_EPSILON) {
  359. // Exact match.
  360. outputImage = scaleImage(aboveBrush, scale, subPixelX, subPixelY);
  361. } else {
  362. // We are smaller than the smallest brush, which is always 1x1.
  363. double s = scale / aboveBrush->scale();
  364. outputImage = scaleSinglePixelImage(s, aboveBrush->image().pixel(0, 0), subPixelX, subPixelY);
  365. }
  366. }
  367. int outputWidth = outputImage.width();
  368. int outputHeight = outputImage.height();
  369. KisPaintDevice *layer = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getRGB8(), "brush");
  370. TQ_CHECK_PTR(layer);
  371. for (int y = 0; y < outputHeight; y++) {
  372. KisHLineIterator iter = layer->createHLineIterator( 0, y, outputWidth, true);
  373. for (int x = 0; x < outputWidth; x++) {
  374. TQ_UINT8 * p = iter.rawData();
  375. TQRgb pixel = outputImage.pixel(x, y);
  376. int red = tqRed(pixel);
  377. int green = tqGreen(pixel);
  378. int blue = tqBlue(pixel);
  379. int alpha = tqAlpha(pixel);
  380. // Scaled images are in pre-multiplied alpha form so
  381. // divide by alpha.
  382. // channel order is BGRA
  383. if (alpha != 0) {
  384. p[2] = (red * 255) / alpha;
  385. p[1] = (green * 255) / alpha;
  386. p[0] = (blue * 255) / alpha;
  387. p[3] = alpha;
  388. }
  389. ++iter;
  390. }
  391. }
  392. return layer;
  393. }
  394. void KisBrush::setHotSpot(KisPoint pt)
  395. {
  396. double x = pt.x();
  397. double y = pt.y();
  398. if (x < 0)
  399. x = 0;
  400. else if (x >= width())
  401. x = width() - 1;
  402. if (y < 0)
  403. y = 0;
  404. else if (y >= height())
  405. y = height() - 1;
  406. m_hotSpot = KisPoint(x, y);
  407. }
  408. KisPoint KisBrush::hotSpot(const KisPaintInformation& info) const
  409. {
  410. double scale = scaleForPressure(info.pressure);
  411. double w = width() * scale;
  412. double h = height() * scale;
  413. // The smallest brush we can produce is a single pixel.
  414. if (w < 1) {
  415. w = 1;
  416. }
  417. if (h < 1) {
  418. h = 1;
  419. }
  420. // XXX: This should take m_hotSpot into account, though it
  421. // isn't specified by gimp brushes so it would default to the centre
  422. // anyway.
  423. KisPoint p(w / 2, h / 2);
  424. return p;
  425. }
  426. enumBrushType KisBrush::brushType() const
  427. {
  428. if (m_brushType == IMAGE && useColorAsMask()) {
  429. return MASK;
  430. }
  431. else {
  432. return m_brushType;
  433. }
  434. }
  435. bool KisBrush::hasColor() const
  436. {
  437. return m_hasColor;
  438. }
  439. void KisBrush::createScaledBrushes() const
  440. {
  441. if (!m_scaledBrushes.isEmpty())
  442. m_scaledBrushes.clear();
  443. // Construct a series of brushes where each one's dimensions are
  444. // half the size of the previous one.
  445. int width = m_img.width() * MAXIMUM_SCALE;
  446. int height = m_img.height() * MAXIMUM_SCALE;
  447. TQImage scaledImage;
  448. while (true) {
  449. if (width >= m_img.width() && height >= m_img.height()) {
  450. scaledImage = scaleImage(m_img, width, height);
  451. }
  452. else {
  453. // Scale down the previous image once we're below 1:1.
  454. scaledImage = scaleImage(scaledImage, width, height);
  455. }
  456. KisAlphaMaskSP scaledMask = new KisAlphaMask(scaledImage, hasColor());
  457. TQ_CHECK_PTR(scaledMask);
  458. double xScale = static_cast<double>(width) / m_img.width();
  459. double yScale = static_cast<double>(height) / m_img.height();
  460. double scale = xScale;
  461. m_scaledBrushes.append(ScaledBrush(scaledMask, hasColor() ? scaledImage : TQImage(), scale, xScale, yScale));
  462. if (width == 1 && height == 1) {
  463. break;
  464. }
  465. // Round up so that we never have to scale an image by less than 1/2.
  466. width = (width + 1) / 2;
  467. height = (height + 1) / 2;
  468. }
  469. }
  470. double KisBrush::xSpacing(double pressure) const
  471. {
  472. return width() * scaleForPressure(pressure) * m_spacing;
  473. }
  474. double KisBrush::ySpacing(double pressure) const
  475. {
  476. return height() * scaleForPressure(pressure) * m_spacing;
  477. }
  478. double KisBrush::scaleForPressure(double pressure)
  479. {
  480. double scale = pressure / PRESSURE_DEFAULT;
  481. if (scale < 0) {
  482. scale = 0;
  483. }
  484. if (scale > MAXIMUM_SCALE) {
  485. scale = MAXIMUM_SCALE;
  486. }
  487. return scale;
  488. }
  489. TQ_INT32 KisBrush::maskWidth(const KisPaintInformation& info) const
  490. {
  491. // Add one for sub-pixel shift
  492. return static_cast<TQ_INT32>(ceil(width() * scaleForPressure(info.pressure)) + 1);
  493. }
  494. TQ_INT32 KisBrush::maskHeight(const KisPaintInformation& info) const
  495. {
  496. // Add one for sub-pixel shift
  497. return static_cast<TQ_INT32>(ceil(height() * scaleForPressure(info.pressure)) + 1);
  498. }
  499. KisAlphaMaskSP KisBrush::scaleMask(const ScaledBrush *srcBrush, double scale, double subPixelX, double subPixelY) const
  500. {
  501. // Add one pixel for sub-pixel shifting
  502. int dstWidth = static_cast<int>(ceil(scale * width())) + 1;
  503. int dstHeight = static_cast<int>(ceil(scale * height())) + 1;
  504. KisAlphaMaskSP dstMask = new KisAlphaMask(dstWidth, dstHeight);
  505. TQ_CHECK_PTR(dstMask);
  506. KisAlphaMaskSP srcMask = srcBrush->mask();
  507. // Compute scales to map the scaled brush onto the required scale.
  508. double xScale = srcBrush->xScale() / scale;
  509. double yScale = srcBrush->yScale() / scale;
  510. int srcWidth = srcMask->width();
  511. int srcHeight = srcMask->height();
  512. for (int dstY = 0; dstY < dstHeight; dstY++) {
  513. for (int dstX = 0; dstX < dstWidth; dstX++) {
  514. double srcX = (dstX - subPixelX + 0.5) * xScale;
  515. double srcY = (dstY - subPixelY + 0.5) * yScale;
  516. srcX -= 0.5;
  517. srcY -= 0.5;
  518. int leftX = static_cast<int>(srcX);
  519. if (srcX < 0) {
  520. leftX--;
  521. }
  522. double xInterp = srcX - leftX;
  523. int topY = static_cast<int>(srcY);
  524. if (srcY < 0) {
  525. topY--;
  526. }
  527. double yInterp = srcY - topY;
  528. TQ_UINT8 topLeft = (leftX >= 0 && leftX < srcWidth && topY >= 0 && topY < srcHeight) ? srcMask->alphaAt(leftX, topY) : OPACITY_TRANSPARENT;
  529. TQ_UINT8 bottomLeft = (leftX >= 0 && leftX < srcWidth && topY + 1 >= 0 && topY + 1 < srcHeight) ? srcMask->alphaAt(leftX, topY + 1) : OPACITY_TRANSPARENT;
  530. TQ_UINT8 topRight = (leftX + 1 >= 0 && leftX + 1 < srcWidth && topY >= 0 && topY < srcHeight) ? srcMask->alphaAt(leftX + 1, topY) : OPACITY_TRANSPARENT;
  531. TQ_UINT8 bottomRight = (leftX + 1 >= 0 && leftX + 1 < srcWidth && topY + 1 >= 0 && topY + 1 < srcHeight) ? srcMask->alphaAt(leftX + 1, topY + 1) : OPACITY_TRANSPARENT;
  532. double a = 1 - xInterp;
  533. double b = 1 - yInterp;
  534. // Bi-linear interpolation
  535. int d = static_cast<int>(a * b * topLeft
  536. + a * (1 - b) * bottomLeft
  537. + (1 - a) * b * topRight
  538. + (1 - a) * (1 - b) * bottomRight + 0.5);
  539. if (d < OPACITY_TRANSPARENT) {
  540. d = OPACITY_TRANSPARENT;
  541. }
  542. else
  543. if (d > OPACITY_OPAQUE) {
  544. d = OPACITY_OPAQUE;
  545. }
  546. dstMask->setAlphaAt(dstX, dstY, static_cast<TQ_UINT8>(d));
  547. }
  548. }
  549. return dstMask;
  550. }
  551. TQImage KisBrush::scaleImage(const ScaledBrush *srcBrush, double scale, double subPixelX, double subPixelY) const
  552. {
  553. // Add one pixel for sub-pixel shifting
  554. int dstWidth = static_cast<int>(ceil(scale * width())) + 1;
  555. int dstHeight = static_cast<int>(ceil(scale * height())) + 1;
  556. TQImage dstImage(dstWidth, dstHeight, 32);
  557. dstImage.setAlphaBuffer(true);
  558. const TQImage srcImage = srcBrush->image();
  559. // Compute scales to map the scaled brush onto the required scale.
  560. double xScale = srcBrush->xScale() / scale;
  561. double yScale = srcBrush->yScale() / scale;
  562. int srcWidth = srcImage.width();
  563. int srcHeight = srcImage.height();
  564. for (int dstY = 0; dstY < dstHeight; dstY++) {
  565. for (int dstX = 0; dstX < dstWidth; dstX++) {
  566. double srcX = (dstX - subPixelX + 0.5) * xScale;
  567. double srcY = (dstY - subPixelY + 0.5) * yScale;
  568. srcX -= 0.5;
  569. srcY -= 0.5;
  570. int leftX = static_cast<int>(srcX);
  571. if (srcX < 0) {
  572. leftX--;
  573. }
  574. double xInterp = srcX - leftX;
  575. int topY = static_cast<int>(srcY);
  576. if (srcY < 0) {
  577. topY--;
  578. }
  579. double yInterp = srcY - topY;
  580. TQRgb topLeft = (leftX >= 0 && leftX < srcWidth && topY >= 0 && topY < srcHeight) ? srcImage.pixel(leftX, topY) : tqRgba(0, 0, 0, 0);
  581. TQRgb bottomLeft = (leftX >= 0 && leftX < srcWidth && topY + 1 >= 0 && topY + 1 < srcHeight) ? srcImage.pixel(leftX, topY + 1) : tqRgba(0, 0, 0, 0);
  582. TQRgb topRight = (leftX + 1 >= 0 && leftX + 1 < srcWidth && topY >= 0 && topY < srcHeight) ? srcImage.pixel(leftX + 1, topY) : tqRgba(0, 0, 0, 0);
  583. TQRgb bottomRight = (leftX + 1 >= 0 && leftX + 1 < srcWidth && topY + 1 >= 0 && topY + 1 < srcHeight) ? srcImage.pixel(leftX + 1, topY + 1) : tqRgba(0, 0, 0, 0);
  584. double a = 1 - xInterp;
  585. double b = 1 - yInterp;
  586. // Bi-linear interpolation. Image is pre-multiplied by alpha.
  587. int red = static_cast<int>(a * b * tqRed(topLeft)
  588. + a * (1 - b) * tqRed(bottomLeft)
  589. + (1 - a) * b * tqRed(topRight)
  590. + (1 - a) * (1 - b) * tqRed(bottomRight) + 0.5);
  591. int green = static_cast<int>(a * b * tqGreen(topLeft)
  592. + a * (1 - b) * tqGreen(bottomLeft)
  593. + (1 - a) * b * tqGreen(topRight)
  594. + (1 - a) * (1 - b) * tqGreen(bottomRight) + 0.5);
  595. int blue = static_cast<int>(a * b * tqBlue(topLeft)
  596. + a * (1 - b) * tqBlue(bottomLeft)
  597. + (1 - a) * b * tqBlue(topRight)
  598. + (1 - a) * (1 - b) * tqBlue(bottomRight) + 0.5);
  599. int alpha = static_cast<int>(a * b * tqAlpha(topLeft)
  600. + a * (1 - b) * tqAlpha(bottomLeft)
  601. + (1 - a) * b * tqAlpha(topRight)
  602. + (1 - a) * (1 - b) * tqAlpha(bottomRight) + 0.5);
  603. if (red < 0) {
  604. red = 0;
  605. }
  606. else
  607. if (red > 255) {
  608. red = 255;
  609. }
  610. if (green < 0) {
  611. green = 0;
  612. }
  613. else
  614. if (green > 255) {
  615. green = 255;
  616. }
  617. if (blue < 0) {
  618. blue = 0;
  619. }
  620. else
  621. if (blue > 255) {
  622. blue = 255;
  623. }
  624. if (alpha < 0) {
  625. alpha = 0;
  626. }
  627. else
  628. if (alpha > 255) {
  629. alpha = 255;
  630. }
  631. dstImage.setPixel(dstX, dstY, tqRgba(red, green, blue, alpha));
  632. }
  633. }
  634. return dstImage;
  635. }
  636. TQImage KisBrush::scaleImage(const TQImage& srcImage, int width, int height)
  637. {
  638. TQImage scaledImage;
  639. //TQString filename;
  640. int srcWidth = srcImage.width();
  641. int srcHeight = srcImage.height();
  642. double xScale = static_cast<double>(srcWidth) / width;
  643. double yScale = static_cast<double>(srcHeight) / height;
  644. if (xScale > 2 + DBL_EPSILON || yScale > 2 + DBL_EPSILON || xScale < 1 - DBL_EPSILON || yScale < 1 - DBL_EPSILON) {
  645. // smoothScale gives better results when scaling an image up
  646. // or scaling it to less than half size.
  647. scaledImage = srcImage.smoothScale(width, height);
  648. //filename = TQString("smoothScale_%1x%2.png").arg(width).arg(height);
  649. }
  650. else {
  651. scaledImage.create(width, height, 32);
  652. scaledImage.setAlphaBuffer(srcImage.hasAlphaBuffer());
  653. for (int dstY = 0; dstY < height; dstY++) {
  654. for (int dstX = 0; dstX < width; dstX++) {
  655. double srcX = (dstX + 0.5) * xScale;
  656. double srcY = (dstY + 0.5) * yScale;
  657. srcX -= 0.5;
  658. srcY -= 0.5;
  659. int leftX = static_cast<int>(srcX);
  660. if (srcX < 0) {
  661. leftX--;
  662. }
  663. double xInterp = srcX - leftX;
  664. int topY = static_cast<int>(srcY);
  665. if (srcY < 0) {
  666. topY--;
  667. }
  668. double yInterp = srcY - topY;
  669. TQRgb topLeft = (leftX >= 0 && leftX < srcWidth && topY >= 0 && topY < srcHeight) ? srcImage.pixel(leftX, topY) : tqRgba(0, 0, 0, 0);
  670. TQRgb bottomLeft = (leftX >= 0 && leftX < srcWidth && topY + 1 >= 0 && topY + 1 < srcHeight) ? srcImage.pixel(leftX, topY + 1) : tqRgba(0, 0, 0, 0);
  671. TQRgb topRight = (leftX + 1 >= 0 && leftX + 1 < srcWidth && topY >= 0 && topY < srcHeight) ? srcImage.pixel(leftX + 1, topY) : tqRgba(0, 0, 0, 0);
  672. TQRgb bottomRight = (leftX + 1 >= 0 && leftX + 1 < srcWidth && topY + 1 >= 0 && topY + 1 < srcHeight) ? srcImage.pixel(leftX + 1, topY + 1) : tqRgba(0, 0, 0, 0);
  673. double a = 1 - xInterp;
  674. double b = 1 - yInterp;
  675. int red;
  676. int green;
  677. int blue;
  678. int alpha;
  679. if (srcImage.hasAlphaBuffer()) {
  680. red = static_cast<int>(a * b * tqRed(topLeft) * tqAlpha(topLeft)
  681. + a * (1 - b) * tqRed(bottomLeft) * tqAlpha(bottomLeft)
  682. + (1 - a) * b * tqRed(topRight) * tqAlpha(topRight)
  683. + (1 - a) * (1 - b) * tqRed(bottomRight) * tqAlpha(bottomRight) + 0.5);
  684. green = static_cast<int>(a * b * tqGreen(topLeft) * tqAlpha(topLeft)
  685. + a * (1 - b) * tqGreen(bottomLeft) * tqAlpha(bottomLeft)
  686. + (1 - a) * b * tqGreen(topRight) * tqAlpha(topRight)
  687. + (1 - a) * (1 - b) * tqGreen(bottomRight) * tqAlpha(bottomRight) + 0.5);
  688. blue = static_cast<int>(a * b * tqBlue(topLeft) * tqAlpha(topLeft)
  689. + a * (1 - b) * tqBlue(bottomLeft) * tqAlpha(bottomLeft)
  690. + (1 - a) * b * tqBlue(topRight) * tqAlpha(topRight)
  691. + (1 - a) * (1 - b) * tqBlue(bottomRight) * tqAlpha(bottomRight) + 0.5);
  692. alpha = static_cast<int>(a * b * tqAlpha(topLeft)
  693. + a * (1 - b) * tqAlpha(bottomLeft)
  694. + (1 - a) * b * tqAlpha(topRight)
  695. + (1 - a) * (1 - b) * tqAlpha(bottomRight) + 0.5);
  696. if (alpha != 0) {
  697. red /= alpha;
  698. green /= alpha;
  699. blue /= alpha;
  700. }
  701. }
  702. else {
  703. red = static_cast<int>(a * b * tqRed(topLeft)
  704. + a * (1 - b) * tqRed(bottomLeft)
  705. + (1 - a) * b * tqRed(topRight)
  706. + (1 - a) * (1 - b) * tqRed(bottomRight) + 0.5);
  707. green = static_cast<int>(a * b * tqGreen(topLeft)
  708. + a * (1 - b) * tqGreen(bottomLeft)
  709. + (1 - a) * b * tqGreen(topRight)
  710. + (1 - a) * (1 - b) * tqGreen(bottomRight) + 0.5);
  711. blue = static_cast<int>(a * b * tqBlue(topLeft)
  712. + a * (1 - b) * tqBlue(bottomLeft)
  713. + (1 - a) * b * tqBlue(topRight)
  714. + (1 - a) * (1 - b) * tqBlue(bottomRight) + 0.5);
  715. alpha = 255;
  716. }
  717. if (red < 0) {
  718. red = 0;
  719. }
  720. else
  721. if (red > 255) {
  722. red = 255;
  723. }
  724. if (green < 0) {
  725. green = 0;
  726. }
  727. else
  728. if (green > 255) {
  729. green = 255;
  730. }
  731. if (blue < 0) {
  732. blue = 0;
  733. }
  734. else
  735. if (blue > 255) {
  736. blue = 255;
  737. }
  738. if (alpha < 0) {
  739. alpha = 0;
  740. }
  741. else
  742. if (alpha > 255) {
  743. alpha = 255;
  744. }
  745. scaledImage.setPixel(dstX, dstY, tqRgba(red, green, blue, alpha));
  746. }
  747. }
  748. //filename = TQString("bilinear_%1x%2.png").arg(width).arg(height);
  749. }
  750. //scaledImage.save(filename, "PNG");
  751. return scaledImage;
  752. }
  753. void KisBrush::findScaledBrushes(double scale, const ScaledBrush **aboveBrush, const ScaledBrush **belowBrush) const
  754. {
  755. uint current = 0;
  756. while (true) {
  757. *aboveBrush = &(m_scaledBrushes[current]);
  758. if (fabs((*aboveBrush)->scale() - scale) < DBL_EPSILON) {
  759. // Scale matches exactly
  760. break;
  761. }
  762. if (current == m_scaledBrushes.count() - 1) {
  763. // This is the last one
  764. break;
  765. }
  766. if (scale > m_scaledBrushes[current + 1].scale() + DBL_EPSILON) {
  767. // We fit in between the two.
  768. *belowBrush = &(m_scaledBrushes[current + 1]);
  769. break;
  770. }
  771. current++;
  772. }
  773. }
  774. KisAlphaMaskSP KisBrush::scaleSinglePixelMask(double scale, TQ_UINT8 maskValue, double subPixelX, double subPixelY)
  775. {
  776. int srcWidth = 1;
  777. int srcHeight = 1;
  778. int dstWidth = 2;
  779. int dstHeight = 2;
  780. KisAlphaMaskSP outputMask = new KisAlphaMask(dstWidth, dstHeight);
  781. TQ_CHECK_PTR(outputMask);
  782. double a = subPixelX;
  783. double b = subPixelY;
  784. for (int y = 0; y < dstHeight; y++) {
  785. for (int x = 0; x < dstWidth; x++) {
  786. TQ_UINT8 topLeft = (x > 0 && y > 0) ? maskValue : OPACITY_TRANSPARENT;
  787. TQ_UINT8 bottomLeft = (x > 0 && y < srcHeight) ? maskValue : OPACITY_TRANSPARENT;
  788. TQ_UINT8 topRight = (x < srcWidth && y > 0) ? maskValue : OPACITY_TRANSPARENT;
  789. TQ_UINT8 bottomRight = (x < srcWidth && y < srcHeight) ? maskValue : OPACITY_TRANSPARENT;
  790. // Bi-linear interpolation
  791. int d = static_cast<int>(a * b * topLeft
  792. + a * (1 - b) * bottomLeft
  793. + (1 - a) * b * topRight
  794. + (1 - a) * (1 - b) * bottomRight + 0.5);
  795. // Multiply by the square of the scale because a 0.5x0.5 pixel
  796. // has 0.25 the value of the 1x1.
  797. d = static_cast<int>(d * scale * scale + 0.5);
  798. if (d < OPACITY_TRANSPARENT) {
  799. d = OPACITY_TRANSPARENT;
  800. }
  801. else
  802. if (d > OPACITY_OPAQUE) {
  803. d = OPACITY_OPAQUE;
  804. }
  805. outputMask->setAlphaAt(x, y, static_cast<TQ_UINT8>(d));
  806. }
  807. }
  808. return outputMask;
  809. }
  810. TQImage KisBrush::scaleSinglePixelImage(double scale, TQRgb pixel, double subPixelX, double subPixelY)
  811. {
  812. int srcWidth = 1;
  813. int srcHeight = 1;
  814. int dstWidth = 2;
  815. int dstHeight = 2;
  816. TQImage outputImage(dstWidth, dstHeight, 32);
  817. outputImage.setAlphaBuffer(true);
  818. double a = subPixelX;
  819. double b = subPixelY;
  820. for (int y = 0; y < dstHeight; y++) {
  821. for (int x = 0; x < dstWidth; x++) {
  822. TQRgb topLeft = (x > 0 && y > 0) ? pixel : tqRgba(0, 0, 0, 0);
  823. TQRgb bottomLeft = (x > 0 && y < srcHeight) ? pixel : tqRgba(0, 0, 0, 0);
  824. TQRgb topRight = (x < srcWidth && y > 0) ? pixel : tqRgba(0, 0, 0, 0);
  825. TQRgb bottomRight = (x < srcWidth && y < srcHeight) ? pixel : tqRgba(0, 0, 0, 0);
  826. // Bi-linear interpolation. Images are in pre-multiplied form.
  827. int red = static_cast<int>(a * b * tqRed(topLeft)
  828. + a * (1 - b) * tqRed(bottomLeft)
  829. + (1 - a) * b * tqRed(topRight)
  830. + (1 - a) * (1 - b) * tqRed(bottomRight) + 0.5);
  831. int green = static_cast<int>(a * b * tqGreen(topLeft)
  832. + a * (1 - b) * tqGreen(bottomLeft)
  833. + (1 - a) * b * tqGreen(topRight)
  834. + (1 - a) * (1 - b) * tqGreen(bottomRight) + 0.5);
  835. int blue = static_cast<int>(a * b * tqBlue(topLeft)
  836. + a * (1 - b) * tqBlue(bottomLeft)
  837. + (1 - a) * b * tqBlue(topRight)
  838. + (1 - a) * (1 - b) * tqBlue(bottomRight) + 0.5);
  839. int alpha = static_cast<int>(a * b * tqAlpha(topLeft)
  840. + a * (1 - b) * tqAlpha(bottomLeft)
  841. + (1 - a) * b * tqAlpha(topRight)
  842. + (1 - a) * (1 - b) * tqAlpha(bottomRight) + 0.5);
  843. // Multiply by the square of the scale because a 0.5x0.5 pixel
  844. // has 0.25 the value of the 1x1.
  845. alpha = static_cast<int>(alpha * scale * scale + 0.5);
  846. // Apply to the colour channels too since we are
  847. // storing pre-multiplied by alpha.
  848. red = static_cast<int>(red * scale * scale + 0.5);
  849. green = static_cast<int>(green * scale * scale + 0.5);
  850. blue = static_cast<int>(blue * scale * scale + 0.5);
  851. if (red < 0) {
  852. red = 0;
  853. }
  854. else
  855. if (red > 255) {
  856. red = 255;
  857. }
  858. if (green < 0) {
  859. green = 0;
  860. }
  861. else
  862. if (green > 255) {
  863. green = 255;
  864. }
  865. if (blue < 0) {
  866. blue = 0;
  867. }
  868. else
  869. if (blue > 255) {
  870. blue = 255;
  871. }
  872. if (alpha < 0) {
  873. alpha = 0;
  874. }
  875. else
  876. if (alpha > 255) {
  877. alpha = 255;
  878. }
  879. outputImage.setPixel(x, y, tqRgba(red, green, blue, alpha));
  880. }
  881. }
  882. return outputImage;
  883. }
  884. TQImage KisBrush::interpolate(const TQImage& image1, const TQImage& image2, double t)
  885. {
  886. Q_ASSERT((image1.width() == image2.width()) && (image1.height() == image2.height()));
  887. Q_ASSERT(t > -DBL_EPSILON && t < 1 + DBL_EPSILON);
  888. int width = image1.width();
  889. int height = image1.height();
  890. TQImage outputImage(width, height, 32);
  891. outputImage.setAlphaBuffer(true);
  892. for (int x = 0; x < width; x++) {
  893. for (int y = 0; y < height; y++) {
  894. TQRgb image1pixel = image1.pixel(x, y);
  895. TQRgb image2pixel = image2.pixel(x, y);
  896. // Images are in pre-multiplied alpha format.
  897. int red = static_cast<int>((1 - t) * tqRed(image1pixel) + t * tqRed(image2pixel) + 0.5);
  898. int green = static_cast<int>((1 - t) * tqGreen(image1pixel) + t * tqGreen(image2pixel) + 0.5);
  899. int blue = static_cast<int>((1 - t) * tqBlue(image1pixel) + t * tqBlue(image2pixel) + 0.5);
  900. int alpha = static_cast<int>((1 - t) * tqAlpha(image1pixel) + t * tqAlpha(image2pixel) + 0.5);
  901. if (red < 0) {
  902. red = 0;
  903. }
  904. else
  905. if (red > 255) {
  906. red = 255;
  907. }
  908. if (green < 0) {
  909. green = 0;
  910. }
  911. else
  912. if (green > 255) {
  913. green = 255;
  914. }
  915. if (blue < 0) {
  916. blue = 0;
  917. }
  918. else
  919. if (blue > 255) {
  920. blue = 255;
  921. }
  922. if (alpha < 0) {
  923. alpha = 0;
  924. }
  925. else
  926. if (alpha > 255) {
  927. alpha = 255;
  928. }
  929. outputImage.setPixel(x, y, tqRgba(red, green, blue, alpha));
  930. }
  931. }
  932. return outputImage;
  933. }
  934. KisBrush::ScaledBrush::ScaledBrush()
  935. {
  936. m_mask = 0;
  937. m_image = TQImage();
  938. m_scale = 1;
  939. m_xScale = 1;
  940. m_yScale = 1;
  941. }
  942. KisBrush::ScaledBrush::ScaledBrush(KisAlphaMaskSP scaledMask, const TQImage& scaledImage, double scale, double xScale, double yScale)
  943. {
  944. m_mask = scaledMask;
  945. m_image = scaledImage;
  946. m_scale = scale;
  947. m_xScale = xScale;
  948. m_yScale = yScale;
  949. if (!m_image.isNull()) {
  950. // Convert image to pre-multiplied by alpha.
  951. m_image.detach();
  952. for (int y = 0; y < m_image.height(); y++) {
  953. for (int x = 0; x < m_image.width(); x++) {
  954. TQRgb pixel = m_image.pixel(x, y);
  955. int red = tqRed(pixel);
  956. int green = tqGreen(pixel);
  957. int blue = tqBlue(pixel);
  958. int alpha = tqAlpha(pixel);
  959. red = (red * alpha) / 255;
  960. green = (green * alpha) / 255;
  961. blue = (blue * alpha) / 255;
  962. m_image.setPixel(x, y, tqRgba(red, green, blue, alpha));
  963. }
  964. }
  965. }
  966. }
  967. void KisBrush::setImage(const TQImage& img)
  968. {
  969. m_img = img;
  970. m_img.detach();
  971. setWidth(img.width());
  972. setHeight(img.height());
  973. m_scaledBrushes.clear();
  974. setValid(true);
  975. }
  976. TQ_INT32 KisBrush::width() const
  977. {
  978. return m_width;
  979. }
  980. void KisBrush::setWidth(TQ_INT32 w)
  981. {
  982. m_width = w;
  983. }
  984. TQ_INT32 KisBrush::height() const
  985. {
  986. return m_height;
  987. }
  988. void KisBrush::setHeight(TQ_INT32 h)
  989. {
  990. m_height = h;
  991. }
  992. /*TQImage KisBrush::outline(double pressure) {
  993. KisLayerSP layer = image(KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),""),
  994. KisPaintInformation(pressure));
  995. KisBoundary bounds(layer.data());
  996. int w = maskWidth(pressure);
  997. int h = maskHeight(pressure);
  998. bounds.generateBoundary(w, h);
  999. TQPixmap pix(bounds.pixmap(w, h));
  1000. TQImage result;
  1001. result = pix;
  1002. return result;
  1003. }*/
  1004. void KisBrush::generateBoundary() {
  1005. KisPaintDeviceSP dev;
  1006. int w = maskWidth(KisPaintInformation());
  1007. int h = maskHeight(KisPaintInformation());
  1008. if (brushType() == IMAGE || brushType() == PIPE_IMAGE) {
  1009. dev = image(KisMetaRegistry::instance()->csRegistry() ->getColorSpace(KisID("RGBA",""),""), KisPaintInformation());
  1010. } else {
  1011. KisAlphaMaskSP amask = mask(KisPaintInformation());
  1012. KisColorSpace* cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),"");
  1013. dev = new KisPaintDevice(cs, "tmp for generateBoundary");
  1014. for (int y = 0; y < h; y++) {
  1015. KisHLineIteratorPixel it = dev->createHLineIterator(0, y, w, true);
  1016. int x = 0;
  1017. while(!it.isDone()) {
  1018. cs->setAlpha(it.rawData(), amask->alphaAt(x++, y), 1);
  1019. ++it;
  1020. }
  1021. }
  1022. }
  1023. m_boundary = new KisBoundary(dev);
  1024. m_boundary->generateBoundary(w, h);
  1025. }
  1026. KisBoundary KisBrush::boundary() {
  1027. if (!m_boundary)
  1028. generateBoundary();
  1029. return *m_boundary;
  1030. }
  1031. void KisBrush::makeMaskImage() {
  1032. if (!hasColor())
  1033. return;
  1034. TQImage img;
  1035. img.create(width(), height(), 32);
  1036. if (m_img.width() == img.width() && m_img.height() == img.height()) {
  1037. for (int x = 0; x < width(); x++) {
  1038. for (int y = 0; y < height(); y++) {
  1039. TQRgb c = m_img.pixel(x, y);
  1040. int a = (tqGray(c) * tqAlpha(c)) / 255; // tqGray(black) = 0
  1041. img.setPixel(x, y, tqRgba(a, a, a, 255));
  1042. }
  1043. }
  1044. m_img = img;
  1045. }
  1046. m_brushType = MASK;
  1047. m_hasColor = false;
  1048. m_useColorAsMask = false;
  1049. delete m_boundary;
  1050. m_boundary = 0;
  1051. m_scaledBrushes.clear();
  1052. }
  1053. KisBrush* KisBrush::clone() const {
  1054. KisBrush* c = new KisBrush("");
  1055. c->m_spacing = m_spacing;
  1056. c->m_useColorAsMask = m_useColorAsMask;
  1057. c->m_hasColor = m_useColorAsMask;
  1058. c->m_img = m_img;
  1059. c->m_width = m_width;
  1060. c->m_height = m_height;
  1061. c->m_ownData = false;
  1062. c->m_hotSpot = m_hotSpot;
  1063. c->m_brushType = m_brushType;
  1064. c->setValid(true);
  1065. return c;
  1066. }
  1067. #include "kis_brush.moc"