karbon

vcolor.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001, The Karbon Developers
00003    Copyright (C) 2002, The Karbon Developers
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 
00022 #include <qdom.h>
00023 
00024 #include "vcolor.h"
00025 #include "vglobal.h"
00026 
00027 
00028 VColor::VColor( VColorSpace colorSpace )
00029 {
00030     m_colorSpace = colorSpace;
00031     m_opacity = 1.0;
00032 
00033     m_value[0] = 0.0;
00034     m_value[1] = 0.0;
00035     m_value[2] = 0.0;
00036     m_value[3] = 0.0;
00037 }
00038 
00039 VColor::VColor( const VColor& color )
00040 {
00041     m_colorSpace = color.m_colorSpace;
00042     m_opacity = color.m_opacity;
00043 
00044     m_value[0] = color.m_value[0];
00045     m_value[1] = color.m_value[1];
00046     m_value[2] = color.m_value[2];
00047     m_value[3] = color.m_value[3];
00048 }
00049 
00050 VColor::VColor( const QColor& color )
00051 {
00052     m_colorSpace = rgb;
00053     m_opacity = 1.0;
00054 
00055     m_value[0] = color.red() / 255.0;
00056     m_value[1] = color.green() / 255.0;
00057     m_value[2] = color.blue() / 255.0;
00058 }
00059 
00060 VColor::operator QColor() const
00061 {
00062     VColor copy( *this );
00063     copy.convertToColorSpace( rgb );
00064 
00065     QColor color;
00066     color.setRgb( int( 255 * copy[0] ), int( 255 * copy[1] ), int( 255 * copy[2] ) );
00067 
00068     return color;
00069 }
00070 
00071 void
00072 VColor::setColorSpace( const VColorSpace colorSpace, bool convert )
00073 {
00074     if( convert )
00075         convertToColorSpace( colorSpace );
00076 
00077     m_colorSpace = colorSpace;
00078 }
00079 
00080 void
00081 VColor::convertToColorSpace( const VColorSpace colorSpace )
00082 {
00083     // TODO: numerical stability.
00084     // TODO: undercolor removal with cmyk.
00085 
00086     if( colorSpace == rgb )
00087     {
00088         if( m_colorSpace == rgb )
00089         {
00090             // Do nothing.
00091         }
00092         else if( m_colorSpace == cmyk )
00093         {
00094             m_value[0] = 1.0 - kMin( 1.0f, m_value[0] + m_value[3] );
00095             m_value[1] = 1.0 - kMin( 1.0f, m_value[1] + m_value[3] );
00096             m_value[2] = 1.0 - kMin( 1.0f, m_value[2] + m_value[3] );
00097         }
00098         else if( m_colorSpace == hsb )
00099         {
00100             // Achromatic case (saturation == 0.0).
00101             if( m_value[1] == 0.0 )
00102             {
00103                 // Set to brightness:
00104                 m_value[0] = m_value[2];
00105                 m_value[1] = m_value[2];
00106                 m_value[2] = m_value[2];    // For readability.
00107             }
00108             else
00109             {
00110                 float hue6 = 6.0 * m_value[0];
00111                 uint i = static_cast<uint>( hue6 );
00112                 float f = hue6 - i;
00113 
00114                 float m = m_value[2] * ( 1.0 - m_value[1] );
00115                 float n = m_value[2] * ( 1.0 - m_value[1] * f );
00116                 float k = m_value[2] * ( 1.0 - m_value[1] * ( 1.0 - f ) );
00117 
00118                 float r;
00119                 float g;
00120                 float b;
00121 
00122                 switch( i )
00123                 {
00124                     case 1:
00125                         r = n;
00126                         g = m_value[2];
00127                         b = m;
00128                     break;
00129                     case 2:
00130                         r = m;
00131                         g = m_value[2];
00132                         b = k;
00133                     break;
00134                     case 3:
00135                         r = m;
00136                         g = n;
00137                         b = m_value[2];
00138                     break;
00139                     case 4:
00140                         r = k;
00141                         g = m;
00142                         b = m_value[2];
00143                     break;
00144                     case 5:
00145                         r = m_value[2];
00146                         g = m;
00147                         b = n;
00148                     break;
00149                     default:
00150                         r = m_value[2];
00151                         g = k;
00152                         b = m;
00153                 }
00154 
00155                 m_value[0] = r;
00156                 m_value[1] = g;
00157                 m_value[2] = b;
00158             }
00159         }
00160         else if( m_colorSpace == gray )
00161         {
00162             m_value[0] = m_value[0];    // For readability.
00163             m_value[1] = m_value[0];
00164             m_value[2] = m_value[0];
00165         }
00166     }
00167     else if( colorSpace == cmyk )
00168     {
00169         if( m_colorSpace == rgb )
00170         {
00171             m_value[0] = 1.0 - m_value[0];
00172             m_value[1] = 1.0 - m_value[1];
00173             m_value[2] = 1.0 - m_value[2];
00174             m_value[3] = 0.0;
00175         }
00176         else if( m_colorSpace == cmyk )
00177         {
00178             // Do nothing.
00179         }
00180         else if( m_colorSpace == hsb )
00181         {
00182 // TODO
00183         }
00184         else if( m_colorSpace == gray )
00185         {
00186             m_value[1] = 0.0;
00187             m_value[2] = 0.0;
00188             m_value[3] = 1.0 - m_value[0];
00189             m_value[0] = 0.0;
00190         }
00191     }
00192     else if( colorSpace == hsb )
00193     {
00194         if( m_colorSpace == rgb )
00195         {
00196             if(
00197                 m_value[0] == m_value[1] &&
00198                 m_value[1] == m_value[2] )
00199             {
00200                 // Arbitrary:
00201                 m_value[3] = m_value[0];
00202                 m_value[1] = 0.0;
00203                 m_value[2] = 0.0;
00204             }
00205             else
00206             {
00207                 float max;
00208                 float min;
00209 
00210                 // Find maximum + minimum rgb component:
00211                 if( m_value[0] > m_value[1] )
00212                 {
00213                     max = m_value[0];
00214                     min = m_value[1];
00215                 }
00216                 else
00217                 {
00218                     max = m_value[1];
00219                     min = m_value[0];
00220                 }
00221 
00222                 if( m_value[2] > max )
00223                     max = m_value[2];
00224 
00225                 if( m_value[2] < min )
00226                     min = m_value[2];
00227 
00228 
00229                 float hue;
00230                 const float diff = max - min;
00231 
00232                 // Which rgb component is maximum?
00233                 if( max == m_value[0] )
00234                     // Red:
00235                     hue = ( m_value[1] - m_value[2] ) * VGlobal::one_6 / diff;
00236                 else if( max == m_value[1] )
00237                     // Green:
00238                     hue = ( m_value[2] - m_value[0] ) * VGlobal::one_6 / diff + VGlobal::one_3;
00239                 else
00240                     // Blue:
00241                     hue = ( m_value[0] - m_value[1] ) * VGlobal::one_6 / diff + VGlobal::two_3;
00242 
00243                 if( hue < 0.0 )
00244                     hue += 1.0;
00245 
00246 
00247                 m_value[0] = hue;
00248                 m_value[1] = diff / max;
00249                 m_value[2] = max;
00250             }
00251         }
00252         else if( m_colorSpace == cmyk )
00253         {
00254 // TODO
00255         }
00256         else if( m_colorSpace == hsb )
00257         {
00258             // Do nothing.
00259         }
00260         else if( m_colorSpace == gray )
00261         {
00262             m_value[1] = 0.0;
00263             m_value[2] = m_value[0];
00264             m_value[0] = 0.0;
00265         }
00266     }
00267     else if( colorSpace == gray )
00268     {
00269         if( m_colorSpace == rgb )
00270         {
00271             m_value[0] =
00272                 0.3  * m_value[0] +
00273                 0.59 * m_value[1] +
00274                 0.11 * m_value[2];
00275         }
00276         else if( m_colorSpace == cmyk )
00277         {
00278             m_value[0] =
00279                 1.0 - kMin( 1.0,
00280                     0.3  * m_value[0] +
00281                     0.59 * m_value[1] +
00282                     0.11 * m_value[2] +
00283                     m_value[3] );
00284         }
00285         else if( m_colorSpace == hsb )
00286         {
00287             m_value[0] = m_value[2];
00288         }
00289         else if( m_colorSpace == gray )
00290         {
00291             // Do nothing.
00292         }
00293     }
00294 }
00295 
00296 void
00297 VColor::save( QDomElement& element ) const
00298 {
00299     QDomElement me = element.ownerDocument().createElement( "COLOR" );
00300     element.appendChild( me );
00301 
00302     if( m_colorSpace != rgb )
00303         me.setAttribute( "colorSpace", m_colorSpace );
00304     if( m_opacity != 1.0 )
00305         me.setAttribute( "opacity", m_opacity );
00306 
00307     if( m_colorSpace == gray )
00308         me.setAttribute( "v", m_value[0] );
00309     else
00310     {
00311         me.setAttribute( "v1", m_value[0] );
00312         me.setAttribute( "v2", m_value[1] );
00313         me.setAttribute( "v3", m_value[2] );
00314 
00315         if( m_colorSpace == cmyk )
00316             me.setAttribute( "v4", m_value[3] );
00317     }
00318 }
00319 
00320 void
00321 VColor::load( const QDomElement& element )
00322 {
00323     switch( element.attribute( "colorSpace" ).toUShort() )
00324     {
00325         case 1:
00326             m_colorSpace = cmyk; break;
00327         case 2:
00328             m_colorSpace = hsb; break;
00329         case 3:
00330             m_colorSpace = gray; break;
00331         default:
00332             m_colorSpace = rgb;
00333     }
00334 
00335     m_opacity = element.attribute( "opacity", "1.0" ).toFloat();
00336 
00337     if( m_colorSpace == gray )
00338         m_value[0] = element.attribute( "v", "0.0" ).toFloat();
00339     else
00340     {
00341         m_value[0] = element.attribute( "v1", "0.0" ).toFloat();
00342         m_value[1] = element.attribute( "v2", "0.0" ).toFloat();
00343         m_value[2] = element.attribute( "v3", "0.0" ).toFloat();
00344 
00345         if( m_colorSpace == cmyk )
00346             m_value[3] = element.attribute( "v4", "0.0" ).toFloat();
00347     }
00348 
00349     if( m_value[0] < 0.0 || m_value[0] > 1.0 )
00350         m_value[0] = 0.0;
00351     if( m_value[1] < 0.0 || m_value[1] > 1.0 )
00352         m_value[1] = 0.0;
00353     if( m_value[2] < 0.0 || m_value[2] > 1.0 )
00354         m_value[2] = 0.0;
00355     if( m_value[3] < 0.0 || m_value[3] > 1.0 )
00356         m_value[3] = 0.0;
00357 }
00358 
KDE Home | KDE Accessibility Home | Description of Access Keys