3 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
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
34 #include <qdatastream.h>
40 : m_rgbaIsValid (false),
41 m_colorCacheIsValid (false)
44 kDebug () << "kpColor::<ctor>()";
48 kpColor::kpColor (int red
, int green
, int blue
, bool isTransparent
)
49 : m_colorCacheIsValid (false)
52 kDebug () << "kpColor::<ctor>(r=" << red
<< ",g=" << green
<< ",b=" << blue
53 << ",isTrans=" << isTransparent
<< ")" << endl
;
55 if (red
< 0 || red
> 255 ||
56 green
< 0 || green
> 255 ||
57 blue
< 0 || blue
> 255)
59 kError () << "kpColor::<ctor>(r=" << red
62 << ",t=" << isTransparent
63 << ") passed out of range values" << endl
;
64 m_rgbaIsValid
= false;
68 m_rgba
= qRgba (red
, green
, blue
, isTransparent
? 0 : 255/*opaque*/);
72 kpColor::kpColor (const QRgb
&rgba
)
73 : m_colorCacheIsValid (false)
76 kDebug () << "kpColor::<ctor>(rgba=" << (int *) rgba
<< ")";
78 if (qAlpha (rgba
) > 0 && qAlpha (rgba
) < 255)
80 kError () << "kpColor::<ctor>(QRgb) passed translucent alpha "
82 << " - trying to recover"
85 // Forget the alpha channel - make it opaque
86 m_rgba
= qRgb (qRed (m_rgba
), qGreen (m_rgba
), qBlue (m_rgba
));
96 kpColor::kpColor (const kpColor
&rhs
)
97 : m_rgbaIsValid (rhs
.m_rgbaIsValid
),
99 m_colorCacheIsValid (rhs
.m_colorCacheIsValid
),
100 m_colorCache (rhs
.m_colorCache
)
103 kDebug () << "kpColor::<copy_ctor>()";
108 QDataStream
&operator<< (QDataStream
&stream
, const kpColor
&color
)
110 stream
<< int (color
.m_rgbaIsValid
) << int (color
.m_rgba
);
116 QDataStream
&operator>> (QDataStream
&stream
, kpColor
&color
)
120 color
.m_rgbaIsValid
= a
;
123 color
.m_colorCacheIsValid
= false;
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 :))
136 m_rgbaIsValid
= rhs
.m_rgbaIsValid
;
138 m_colorCacheIsValid
= rhs
.m_colorCacheIsValid
;
139 m_colorCache
= rhs
.m_colorCache
;
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
)
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
177 // Do we dither in terms of validity?
178 if (isValid () != rhs
.isValid ())
181 // Are both of us invalid?
185 // --- both are now valid ---
188 if (isTransparent () != rhs
.isTransparent ())
191 // Are both of us transparent?
192 if (isTransparent ())
195 // --- both are now valid and opaque ---
198 if (m_rgba
== rhs
.m_rgba
)
202 if (processedSimilarity
== kpColor::Exact
)
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
);
219 bool kpColor::isValid () const
221 return m_rgbaIsValid
;
226 int kpColor::red () const
230 kError () << "kpColor::red() called with invalid kpColor" << endl
;
234 if (isTransparent ())
236 kError () << "kpColor::red() called with transparent kpColor" << endl
;
240 return qRed (m_rgba
);
244 int kpColor::green () const
248 kError () << "kpColor::green() called with invalid kpColor" << endl
;
252 if (isTransparent ())
254 kError () << "kpColor::green() called with transparent kpColor" << endl
;
258 return qGreen (m_rgba
);
262 int kpColor::blue () const
266 kError () << "kpColor::blue() called with invalid kpColor" << endl
;
270 if (isTransparent ())
272 kError () << "kpColor::blue() called with transparent kpColor" << endl
;
276 return qBlue (m_rgba
);
280 int kpColor::alpha () const
284 kError () << "kpColor::alpha() called with invalid kpColor" << endl
;
288 const int alpha
= qAlpha (m_rgba
);
290 if (alpha
> 0 && alpha
< 255)
292 kError () << "kpColor::alpha() called with translucent kpColor alpha=" << alpha
<< endl
;
295 return alpha
? 255 : 0;
304 bool kpColor::isTransparent () const
306 return (alpha () == 0);
310 bool kpColor::isOpaque () const
312 return (alpha () == 255);
317 QRgb
kpColor::toQRgb () const
321 kError () << "kpColor::toQRgb() called with invalid kpColor" << endl
;
329 QColor
kpColor::toQColor () const
333 kError () << "kpColor::toQColor() called with invalid kpColor" << endl
;
337 if (m_colorCacheIsValid
)
340 if (qAlpha (m_rgba
) < 255)
342 kError () << "kpColor::toQColor() called with not fully opaque kpColor alpha="
348 m_colorCache
= QColor (m_rgba
);
349 if (!m_colorCache
.isValid ())
351 kError () << "kpColor::toQColor () internal error - could not return valid QColor"
356 m_colorCacheIsValid
= true;
362 QColor
kpColor::maskColor () const
364 return isTransparent () ? Qt::color0
: Qt::color1
;