make sure to attach to the document also when a resize event is received prior of...
[kdegraphics.git] / kolourpaint / imagelib / kpColor.cpp
blob1ca2f1366840d3a7abdee91ad2dc4785c3949dc7
2 /*
3 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
4 All rights reserved.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #define DEBUG_KP_COLOR 0
32 #include <kpColor.h>
34 #include <qdatastream.h>
36 #include <kdebug.h>
39 kpColor::kpColor ()
40 : m_rgbaIsValid (false),
41 m_colorCacheIsValid (false)
43 #if DEBUG_KP_COLOR
44 kDebug () << "kpColor::<ctor>()";
45 #endif
48 kpColor::kpColor (int red, int green, int blue, bool isTransparent)
49 : m_colorCacheIsValid (false)
51 #if DEBUG_KP_COLOR
52 kDebug () << "kpColor::<ctor>(r=" << red << ",g=" << green << ",b=" << blue
53 << ",isTrans=" << isTransparent << ")" << endl;
54 #endif
55 if (red < 0 || red > 255 ||
56 green < 0 || green > 255 ||
57 blue < 0 || blue > 255)
59 kError () << "kpColor::<ctor>(r=" << red
60 << ",g=" << green
61 << ",b=" << blue
62 << ",t=" << isTransparent
63 << ") passed out of range values" << endl;
64 m_rgbaIsValid = false;
65 return;
68 m_rgba = qRgba (red, green, blue, isTransparent ? 0 : 255/*opaque*/);
69 m_rgbaIsValid = true;
72 kpColor::kpColor (const QRgb &rgba)
73 : m_colorCacheIsValid (false)
75 #if DEBUG_KP_COLOR
76 kDebug () << "kpColor::<ctor>(rgba=" << (int *) rgba << ")";
77 #endif
78 if (qAlpha (rgba) > 0 && qAlpha (rgba) < 255)
80 kError () << "kpColor::<ctor>(QRgb) passed translucent alpha "
81 << qAlpha (rgba)
82 << " - trying to recover"
83 << endl;
85 // Forget the alpha channel - make it opaque
86 m_rgba = qRgb (qRed (m_rgba), qGreen (m_rgba), qBlue (m_rgba));
87 m_rgbaIsValid = true;
89 else
91 m_rgba = rgba;
92 m_rgbaIsValid = true;
96 kpColor::kpColor (const kpColor &rhs)
97 : m_rgbaIsValid (rhs.m_rgbaIsValid),
98 m_rgba (rhs.m_rgba),
99 m_colorCacheIsValid (rhs.m_colorCacheIsValid),
100 m_colorCache (rhs.m_colorCache)
102 #if DEBUG_KP_COLOR
103 kDebug () << "kpColor::<copy_ctor>()";
104 #endif
107 // friend
108 QDataStream &operator<< (QDataStream &stream, const kpColor &color)
110 stream << int (color.m_rgbaIsValid) << int (color.m_rgba);
112 return stream;
115 // friend
116 QDataStream &operator>> (QDataStream &stream, kpColor &color)
118 int a, b;
119 stream >> a >> b;
120 color.m_rgbaIsValid = a;
121 color.m_rgba = b;
123 color.m_colorCacheIsValid = false;
125 return stream;
128 kpColor &kpColor::operator= (const kpColor &rhs)
130 // (as soon as you add a ptr, you won't be complaining to me that this
131 // method was unnecessary :))
133 if (this == &rhs)
134 return *this;
136 m_rgbaIsValid = rhs.m_rgbaIsValid;
137 m_rgba = rhs.m_rgba;
138 m_colorCacheIsValid = rhs.m_colorCacheIsValid;
139 m_colorCache = rhs.m_colorCache;
141 return *this;
144 bool kpColor::operator== (const kpColor &rhs) const
146 return isSimilarTo (rhs, kpColor::Exact);
149 bool kpColor::operator!= (const kpColor &rhs) const
151 return !(*this == rhs);
155 template <class dtype>
156 inline dtype square (dtype val)
158 return val * val;
161 // public static
162 int kpColor::processSimilarity (double colorSimilarity)
164 // sqrt (dr ^ 2 + dg ^ 2 + db ^ 2) <= colorSimilarity * sqrt (255 ^ 2 * 3)
165 // dr ^ 2 + dg ^ 2 + db ^ 2 <= (colorSimilarity ^ 2) * (255 ^ 2 * 3)
167 return int (square (colorSimilarity) * (square (255) * 3));
170 bool kpColor::isSimilarTo (const kpColor &rhs, int processedSimilarity) const
172 // Are we the same?
173 if (this == &rhs)
174 return true;
177 // Do we dither in terms of validity?
178 if (isValid () != rhs.isValid ())
179 return false;
181 // Are both of us invalid?
182 if (!isValid ())
183 return true;
185 // --- both are now valid ---
188 if (isTransparent () != rhs.isTransparent ())
189 return false;
191 // Are both of us transparent?
192 if (isTransparent ())
193 return true;
195 // --- both are now valid and opaque ---
198 if (m_rgba == rhs.m_rgba)
199 return true;
202 if (processedSimilarity == kpColor::Exact)
203 return false;
204 else
206 return (square (qRed (m_rgba) - qRed (rhs.m_rgba)) +
207 square (qGreen (m_rgba) - qGreen (rhs.m_rgba)) +
208 square (qBlue (m_rgba) - qBlue (rhs.m_rgba))
209 <= processedSimilarity);
213 kpColor::~kpColor ()
218 // public
219 bool kpColor::isValid () const
221 return m_rgbaIsValid;
225 // public
226 int kpColor::red () const
228 if (!m_rgbaIsValid)
230 kError () << "kpColor::red() called with invalid kpColor" << endl;
231 return 0;
234 if (isTransparent ())
236 kError () << "kpColor::red() called with transparent kpColor" << endl;
237 return 0;
240 return qRed (m_rgba);
243 // public
244 int kpColor::green () const
246 if (!m_rgbaIsValid)
248 kError () << "kpColor::green() called with invalid kpColor" << endl;
249 return 0;
252 if (isTransparent ())
254 kError () << "kpColor::green() called with transparent kpColor" << endl;
255 return 0;
258 return qGreen (m_rgba);
261 // public
262 int kpColor::blue () const
264 if (!m_rgbaIsValid)
266 kError () << "kpColor::blue() called with invalid kpColor" << endl;
267 return 0;
270 if (isTransparent ())
272 kError () << "kpColor::blue() called with transparent kpColor" << endl;
273 return 0;
276 return qBlue (m_rgba);
279 // public
280 int kpColor::alpha () const
282 if (!m_rgbaIsValid)
284 kError () << "kpColor::alpha() called with invalid kpColor" << endl;
285 return 0;
288 const int alpha = qAlpha (m_rgba);
290 if (alpha > 0 && alpha < 255)
292 kError () << "kpColor::alpha() called with translucent kpColor alpha=" << alpha << endl;
294 // no translucency
295 return alpha ? 255 : 0;
297 else
299 return alpha;
303 // public
304 bool kpColor::isTransparent () const
306 return (alpha () == 0);
309 // public
310 bool kpColor::isOpaque () const
312 return (alpha () == 255);
316 // public
317 QRgb kpColor::toQRgb () const
319 if (!m_rgbaIsValid)
321 kError () << "kpColor::toQRgb() called with invalid kpColor" << endl;
322 return 0;
325 return m_rgba;
328 // public
329 QColor kpColor::toQColor () const
331 if (!m_rgbaIsValid)
333 kError () << "kpColor::toQColor() called with invalid kpColor" << endl;
334 return Qt::black;
337 if (m_colorCacheIsValid)
338 return m_colorCache;
340 if (qAlpha (m_rgba) < 255)
342 kError () << "kpColor::toQColor() called with not fully opaque kpColor alpha="
343 << qAlpha (m_rgba)
344 << endl;
345 return Qt::black;
348 m_colorCache = QColor (m_rgba);
349 if (!m_colorCache.isValid ())
351 kError () << "kpColor::toQColor () internal error - could not return valid QColor"
352 << endl;
353 return Qt::black;
356 m_colorCacheIsValid = true;
358 return m_colorCache;
361 // public
362 QColor kpColor::maskColor () const
364 return isTransparent () ? Qt::color0 : Qt::color1;