/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: colctrl.cxx,v $ * $Revision: 1.10 $ * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svtools.hxx" #include #include #include // ---------------- // - ColorControl - // ---------------- SvColorControl::SvColorControl( Window* pParent, WinBits nStyle ) : Control ( pParent, nStyle ), mpBitmap ( NULL ), mpReadAccess ( NULL ), mnLuminance ( 50 ) { Initialize(); } // ----------------------------------------------------------------------- SvColorControl::SvColorControl( Window* pParent, const ResId& rResId ) : Control ( pParent, rResId ), mpBitmap ( NULL ), mpReadAccess ( NULL ), mnLuminance ( 50 ) { Initialize(); } // ----------------------------------------------------------------------- SvColorControl::~SvColorControl() { delete mpBitmap; } // ----------------------------------------------------------------------- void SvColorControl::Initialize() { SetLineColor( Color( COL_BLACK ) ); } // ----------------------------------------------------------------------- void SvColorControl::CreateBitmap() { const Size aSize( GetOutputSizePixel() ); if( mpBitmap && mpBitmap->GetSizePixel() != aSize ) delete mpBitmap, mpBitmap = NULL; if( !mpBitmap ) mpBitmap = new Bitmap( aSize, 24 ); BitmapWriteAccess* pWriteAccess = mpBitmap->AcquireWriteAccess(); if( pWriteAccess ) { USHORT nX = (USHORT) aSize.Width(); USHORT nY = (USHORT) aSize.Height(); UINT16 nHue, nSat; ColorHSB aColHSB( 0, 0, mnLuminance ); for( USHORT i = 0; i < nY; i++ ) { nSat = (UINT16) FRound( 100 - ( 100.0 * i + 0.5 ) / nY ); for( USHORT j = 0; j < nX; j++ ) { nHue = (UINT16) FRound( ( 360.0 * j + 0.5 ) / nX ); aColHSB.SetHue( nHue ); aColHSB.SetSat( nSat ); // mpBitmap always has a bit count of 24 => use of SetPixel(...) is safe pWriteAccess->SetPixel( i, j, BitmapColor( aColHSB.GetRGB() ) ); } } mpBitmap->ReleaseAccess( pWriteAccess ); } SetColor( maColor ); } // ----------------------------------------------------------------------- void SvColorControl::ShowPosition( const Point& rPos ) { // Explizites Abfragen des Bereichs, da schon mal ein Wert < 0 vorhanden ist if( mpBitmap ) { long nX = rPos.X(); long nY = rPos.Y(); if( nX < 0L ) nX = 0L; else if( nX >= mpBitmap->GetSizePixel().Width() ) nX = mpBitmap->GetSizePixel().Width() - 1L; if( nY < 0L ) nY= 0L; else if( nY >= mpBitmap->GetSizePixel().Height() ) nY = mpBitmap->GetSizePixel().Height() - 1L; Point aPos = maPosition; maPosition.X() = nX - 2; maPosition.Y() = nY - 2; Invalidate( Rectangle( aPos, Size( 5, 5) ) ); Invalidate( Rectangle( maPosition, Size( 5, 5) ) ); if( ( mpReadAccess = mpBitmap->AcquireReadAccess() ) != NULL ) { // mpBitmap always has a bit count of 24 => use of GetPixel(...) is safe maColor = mpReadAccess->GetPixel( nY, nX ); mpBitmap->ReleaseAccess( mpReadAccess ); mpReadAccess = NULL; } } } // ----------------------------------------------------------------------- void SvColorControl::MouseMove( const MouseEvent& rMEvt ) { if( rMEvt.IsLeft() ) { ShowPosition( rMEvt.GetPosPixel() ); Modify(); } } // ----------------------------------------------------------------------- void SvColorControl::MouseButtonDown( const MouseEvent& rMEvt ) { if( rMEvt.IsLeft() && !rMEvt.IsShift() ) { //ShowPointer( FALSE ); CaptureMouse(); ShowPosition( rMEvt.GetPosPixel() ); Modify(); } } // ----------------------------------------------------------------------- void SvColorControl::MouseButtonUp( const MouseEvent& ) { //ShowPointer( TRUE ); if( IsMouseCaptured() ) ReleaseMouse(); } // ----------------------------------------------------------------------- void SvColorControl::Paint( const Rectangle& rRect ) { if( !mpBitmap ) CreateBitmap(); Bitmap aOutputBitmap( *mpBitmap ); if( GetBitCount() <= 8 ) aOutputBitmap.Dither(); DrawBitmap( rRect.TopLeft(), rRect.GetSize(), rRect.TopLeft(), rRect.GetSize(), aOutputBitmap ); // Positions-Control (Fadenkreuz oder Aehnliches) Point aPos1( maPosition ); Point aPos2( maPosition ); aPos2.X() += 4; DrawLine( aPos1, aPos2 ); aPos2.X() -= 4; aPos2.Y() += 4; DrawLine( aPos1, aPos2 ); aPos1.Y() += 4; aPos2.X() += 4; DrawLine( aPos1, aPos2 ); aPos1.X() += 4; aPos2.Y() -= 4; DrawLine( aPos1, aPos2 ); } // ----------------------------------------------------------------------- void SvColorControl::Resize() { CreateBitmap(); Control::Resize(); } // ----------------------------------------------------------------------- void SvColorControl::Modify() { maModifyHdl.Call( this ); } // ----------------------------------------------------------------------- void SvColorControl::SetColor( const ColorHSB& rCol, BOOL bSetColor ) { if( bSetColor ) maColor = rCol.GetRGB(); if( mpBitmap ) { USHORT nX = (USHORT) mpBitmap->GetSizePixel().Width(); USHORT nY = (USHORT) mpBitmap->GetSizePixel().Height(); INT16 nZ = rCol.GetBri(); SetLuminance( nZ ); nX = rCol.GetHue() * nX / 360; // Farbe nY = nY - rCol.GetSat() * nY / 100; // Saettigung ShowPosition( Point( nX, nY ) ); } } // ----------------------------------------------------------------------- void SvColorControl::SetColor( const Color& rCol ) { maColor = rCol; if( mpBitmap ) { ColorHSB aColHsb( rCol ); SetColor( aColHsb, FALSE ); } } // ----------------------------------------------------------------------- void SvColorControl::SetLuminance( short nLum ) { if( nLum != mnLuminance && nLum >= 0 && nLum <= 100 ) { mnLuminance = nLum; if( mnLuminance < 40 ) SetLineColor( Color( COL_WHITE ) ); else SetLineColor( Color( COL_BLACK ) ); CreateBitmap(); long nX = maPosition.X() + 2; long nY = maPosition.Y() + 2; if( mpBitmap && ( ( mpReadAccess = mpBitmap->AcquireReadAccess() ) != NULL ) ) { // mpBitmap always has a bit count of 24 => use of GetPixel(...) is safe maColor = mpReadAccess->GetPixel( nY, nX ); mpBitmap->ReleaseAccess( mpReadAccess ); mpReadAccess = NULL; } Invalidate(); } } // ----------------------- // - ColorPreviewControl - // ----------------------- // ----------------------------------------------------------------------- ColorPreviewControl::ColorPreviewControl( Window* pParent, WinBits nStyle ) : Control ( pParent, nStyle ) { SetFillColor( maColor ); SetLineColor( maColor ); } // ----------------------------------------------------------------------- ColorPreviewControl::ColorPreviewControl( Window* pParent, const ResId& rResId ) : Control ( pParent, rResId ) { SetFillColor( maColor ); SetLineColor( maColor ); } // ----------------------------------------------------------------------- ColorPreviewControl::~ColorPreviewControl() { } // ----------------------------------------------------------------------- void ColorPreviewControl::Paint( const Rectangle& rRect ) { DrawRect( rRect ); } // ----------------------------------------------------------------------- void ColorPreviewControl::SetColor( const Color& rCol ) { if( rCol != maColor ) { maColor = rCol; SetFillColor( maColor ); SetLineColor( maColor ); Invalidate(); } } // ----------------------- // - ColorMixingControl - // ----------------------- // ----------------------------------------------------------------------- ColorMixingControl::ColorMixingControl( Window* pParent, WinBits nStyle, USHORT nRows, USHORT nColumns ) : ValueSet ( pParent, nStyle ), mnRows ( nRows ), mnColumns ( nColumns ) { Initialize(); } // ----------------------------------------------------------------------- ColorMixingControl::ColorMixingControl( Window* pParent, const ResId& rResId, USHORT nRows, USHORT nColumns ) : ValueSet ( pParent, rResId ), mnRows ( nRows ), mnColumns ( nColumns ) { Initialize(); } // ----------------------------------------------------------------------- ColorMixingControl::~ColorMixingControl() { } // ----------------------------------------------------------------------- void ColorMixingControl::Initialize() { SetColCount( mnColumns ); Color aColor; String aStr; for( USHORT i = 1; i <= mnRows * mnColumns; i++ ) { InsertItem( i, aColor, aStr ); } /*maColor[ 0 ] = Color( COL_LIGHTRED ); maColor[ 1 ] = Color( COL_LIGHTGREEN ); maColor[ 2 ] = Color( COL_YELLOW ); maColor[ 3 ] = Color( COL_LIGHTBLUE );*/ SetColor( CMC_TOPLEFT, Color( COL_LIGHTRED ) ); SetColor( CMC_BOTTOMRIGHT, Color( COL_LIGHTBLUE ) ); SetColor( CMC_TOPRIGHT, Color( COL_LIGHTGREEN ) ); SetColor( CMC_BOTTOMLEFT, Color( COL_YELLOW ) ); /*FillColumn( 0 ); FillColumn( mnColumns - 1 ); for( i = 0; i < mnRows; i++ ) FillRow( i );*/ } // ----------------------------------------------------------------------- Color ColorMixingControl::CalcDifferenceColor( USHORT nCol1, USHORT nCol2, USHORT nSteps ) { // Die Berechnung ist noch etwas ungenau, daher sollte besser mit floats // gearbeitet werden... (muss !!!) Color aColor( GetItemColor( nCol1 ) ); Color aColor2( GetItemColor( nCol2 ) ); aColor.SetRed( (UINT8) ( ( aColor2.GetRed() - aColor.GetRed() ) / nSteps ) ); aColor.SetGreen( (UINT8) ( ( aColor2.GetGreen() - aColor.GetGreen() ) / nSteps ) ); aColor.SetBlue( (UINT8) ( ( aColor2.GetBlue() - aColor.GetBlue() ) / nSteps ) ); return( aColor ); } // ----------------------------------------------------------------------- void ColorMixingControl::FillRow( USHORT nRow ) { USHORT nCol1 = nRow * mnColumns + 1; USHORT nCol2 = ( nRow + 1 ) * mnColumns; Color aColor( GetItemColor( nCol1 ) ); Color aDiffColor( CalcDifferenceColor( nCol1, nCol2, mnColumns - 1 ) ); for( USHORT i = nCol1 + 1; i < nCol2; i++ ) { aColor.SetRed( aColor.GetRed() + aDiffColor.GetRed() ); aColor.SetGreen( aColor.GetGreen() + aDiffColor.GetGreen() ); aColor.SetBlue( aColor.GetBlue() + aDiffColor.GetBlue() ); SetItemColor( i, aColor ); SetItemText( i, GetRGBString( aColor ) ); } } // ----------------------------------------------------------------------- void ColorMixingControl::FillColumn( USHORT nColumn ) { USHORT nCol1 = nColumn + 1; USHORT nCol2 = nColumn + ( mnRows - 1 ) * mnColumns + 1; Color aColor( GetItemColor( nCol1 ) ); Color aDiffColor( CalcDifferenceColor( nCol1, nCol2, mnRows - 1 ) ); for( USHORT i = nCol1 + mnColumns; i < nCol2; i = i + mnColumns ) { aColor.SetRed( aColor.GetRed() + aDiffColor.GetRed() ); aColor.SetGreen( aColor.GetGreen() + aDiffColor.GetGreen() ); aColor.SetBlue( aColor.GetBlue() + aDiffColor.GetBlue() ); SetItemColor( i, aColor ); SetItemText( i, GetRGBString( aColor ) ); } } // ----------------------------------------------------------------------- void ColorMixingControl::SetRows( USHORT nRows ) { mnRows = nRows; } // ----------------------------------------------------------------------- void ColorMixingControl::SetColumns( USHORT nColumns ) { mnColumns = nColumns; } // ----------------------------------------------------------------------- void ColorMixingControl::SetColor( CMCPosition ePos, const Color& rCol ) { if( rCol != maColor[ ePos ] ) { maColor[ ePos ] = rCol; USHORT nPos = 0; USHORT nColumn = 0; String aStr( GetRGBString( rCol ) ); switch( ePos ) { case CMC_TOPLEFT: nPos = 1; nColumn = 0; break; case CMC_TOPRIGHT: nPos = mnColumns; nColumn = mnColumns - 1; break; case CMC_BOTTOMLEFT: nPos = ( mnRows - 1 ) * mnColumns + 1; nColumn = 0; break; case CMC_BOTTOMRIGHT: nPos = mnRows * mnColumns; nColumn = mnColumns - 1; break; case CMC_OTHER: break; // -Wall not handled. } SetItemColor( nPos, rCol ); SetItemText( nPos, aStr ); FillColumn( nColumn ); for( USHORT i = 0; i < mnRows; i++ ) FillRow( i ); } } // ----------------------------------------------------------------------- String ColorMixingControl::GetRGBString( const Color& rColor ) { String aStr( String::CreateFromInt32(rColor.GetRed()) ); aStr += ' '; aStr += String::CreateFromInt32(rColor.GetGreen()); aStr += ' '; aStr += String::CreateFromInt32(rColor.GetBlue()); return aStr; } // ----------------------------------------------------------------------- CMCPosition ColorMixingControl::GetCMCPosition() const { CMCPosition ePos = CMC_OTHER; USHORT nPos = GetSelectItemId(); if( nPos == 1 ) ePos = CMC_TOPLEFT; else if( nPos == mnColumns ) ePos = CMC_TOPRIGHT; else if( nPos == ( mnRows - 1 ) * mnColumns + 1 ) ePos = CMC_BOTTOMLEFT; else if( nPos == mnRows * mnColumns ) ePos = CMC_BOTTOMRIGHT; return( ePos ); } // ------------ // - ColorHSB - // ------------ // Erste Ansaetze gingen auf die Berechnung von Sven Hannover zurueck // Der jetzige Algorithmus stammt im weitesten Sinne aus dem Foley/VanDam /************************************************************************** |* |* ColorHSB::ColorHSB() |* |* Beschreibung RGB nach HSB |* Ersterstellung SOH 02.10.97 |* **************************************************************************/ ColorHSB::ColorHSB( const Color& rColor ) { UINT8 c[3]; UINT8 cMax, cMin; c[0] = rColor.GetRed(); c[1] = rColor.GetGreen(); c[2] = rColor.GetBlue(); cMax = c[0]; if( c[1] > cMax ) cMax = c[1]; if( c[2] > cMax ) cMax = c[2]; // Brightness = max(R, G, B); mnBri = cMax * 100 / 255; cMin = c[0]; if( c[1] < cMin ) cMin = c[1]; if( c[2] < cMin ) cMin = c[2]; UINT8 cDelta = cMax - cMin; // Saturation = max - min / max if( mnBri > 0 ) mnSat = cDelta * 100 / cMax; else mnSat = 0; if( mnSat == 0 ) mnHue = 0; // Default = undefined else { double dHue = 0; if( c[0] == cMax ) { dHue = (double)( c[1] - c[2] ) / (double)cDelta; } else if( c[1] == cMax ) { dHue = 2.0 + (double)( c[2] - c[0] ) / (double)cDelta; } else if ( c[2] == cMax ) { dHue = 4.0 + (double)( c[0] - c[1] ) / (double)cDelta; } // else dHue = ??? -Wall FIXME dHue *= 60.0; if( dHue < 0.0 ) dHue += 360.0; mnHue = (UINT16) dHue; } } /************************************************************************** |* |* ColorHSB::GetRGB() |* |* Beschreibung HSB nach RGB |* Ersterstellung SOH 02.10.97 |* **************************************************************************/ Color ColorHSB::GetRGB() const { UINT8 cR,cG,cB; UINT8 nB = (UINT8) ( mnBri * 255 / 100 ); if( mnSat == 0 ) { cR = nB; cG = nB; cB = nB; } else { double dH = mnHue; double f; UINT16 n; if( dH == 360.0 ) dH = 0.0; dH /= 60.0; n = (UINT16) dH; f = dH - n; // #107375# Doing the calculation completely in floating // point, the former optimization gave sometimes negative // results for c and was pointless anyway UINT8 a = static_cast( nB * ( 100.0 - mnSat ) / 100.0 ); UINT8 b = static_cast( nB * ( 100.0 - mnSat * f ) / 100.0 ); UINT8 c = static_cast( nB * ( 100.0 - mnSat * ( 1.0 - f ) ) / 100.0 ); switch( n ) { case 0: cR = nB; cG = c; cB = a; break; case 1: cR = b; cG = nB; cB = a; break; case 2: cR = a; cG = nB; cB = c; break; case 3: cR = a; cG = b; cB = nB; break; case 4: cR = c; cG = a; cB = nB; break; case 5: cR = nB; cG = a; cB = b; break; default: cR = 0; cG = 0; cB = 0; break; // -Wall ???? } } return( Color( cR, cG, cB ) ); } // ------------ // - ColorCMYK - // ------------ // ----------------------------------------------------------------------- ColorCMYK::ColorCMYK( const Color& rColor ) { mnCyan = 255 - rColor.GetRed(); mnMagenta = 255 - rColor.GetGreen(); mnYellow = 255 - rColor.GetBlue(); mnKey = Min( Min( mnCyan, mnMagenta ), mnYellow ); mnCyan = mnCyan - mnKey; mnMagenta = mnMagenta - mnKey; mnYellow = mnYellow - mnKey; } // ----------------------------------------------------------------------- Color ColorCMYK::GetRGB() const { int nTmp = Max( 0, 255 - ( mnCyan + mnKey ) ); UINT8 cR = (UINT8) nTmp; nTmp = Max( 0, 255 - ( mnMagenta + mnKey ) ); UINT8 cG = (UINT8) nTmp; nTmp = Max( 0, 255 - ( mnYellow + mnKey ) ); UINT8 cB = (UINT8) nTmp; return( Color( cR, cG, cB ) ); }