1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: colctrl.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
35 #include <vcl/salbtype.hxx>
36 #include <vcl/bmpacc.hxx>
38 #include <svtools/colctrl.hxx>
44 SvColorControl::SvColorControl( Window
* pParent
, WinBits nStyle
) :
45 Control ( pParent
, nStyle
),
47 mpReadAccess ( NULL
),
53 // -----------------------------------------------------------------------
54 SvColorControl::SvColorControl( Window
* pParent
, const ResId
& rResId
) :
55 Control ( pParent
, rResId
),
57 mpReadAccess ( NULL
),
64 // -----------------------------------------------------------------------
65 SvColorControl::~SvColorControl()
70 // -----------------------------------------------------------------------
71 void SvColorControl::Initialize()
73 SetLineColor( Color( COL_BLACK
) );
76 // -----------------------------------------------------------------------
77 void SvColorControl::CreateBitmap()
79 const Size
aSize( GetOutputSizePixel() );
81 if( mpBitmap
&& mpBitmap
->GetSizePixel() != aSize
)
82 delete mpBitmap
, mpBitmap
= NULL
;
85 mpBitmap
= new Bitmap( aSize
, 24 );
87 BitmapWriteAccess
* pWriteAccess
= mpBitmap
->AcquireWriteAccess();
91 USHORT nX
= (USHORT
) aSize
.Width();
92 USHORT nY
= (USHORT
) aSize
.Height();
95 ColorHSB
aColHSB( 0, 0, mnLuminance
);
97 for( USHORT i
= 0; i
< nY
; i
++ )
99 nSat
= (UINT16
) FRound( 100 - ( 100.0 * i
+ 0.5 ) / nY
);
101 for( USHORT j
= 0; j
< nX
; j
++ )
103 nHue
= (UINT16
) FRound( ( 360.0 * j
+ 0.5 ) / nX
);
105 aColHSB
.SetHue( nHue
);
106 aColHSB
.SetSat( nSat
);
108 // mpBitmap always has a bit count of 24 => use of SetPixel(...) is safe
109 pWriteAccess
->SetPixel( i
, j
, BitmapColor( aColHSB
.GetRGB() ) );
113 mpBitmap
->ReleaseAccess( pWriteAccess
);
119 // -----------------------------------------------------------------------
120 void SvColorControl::ShowPosition( const Point
& rPos
)
122 // Explizites Abfragen des Bereichs, da schon mal ein Wert < 0 vorhanden ist
129 else if( nX
>= mpBitmap
->GetSizePixel().Width() )
130 nX
= mpBitmap
->GetSizePixel().Width() - 1L;
134 else if( nY
>= mpBitmap
->GetSizePixel().Height() )
135 nY
= mpBitmap
->GetSizePixel().Height() - 1L;
137 Point aPos
= maPosition
;
138 maPosition
.X() = nX
- 2;
139 maPosition
.Y() = nY
- 2;
140 Invalidate( Rectangle( aPos
, Size( 5, 5) ) );
141 Invalidate( Rectangle( maPosition
, Size( 5, 5) ) );
143 if( ( mpReadAccess
= mpBitmap
->AcquireReadAccess() ) != NULL
)
145 // mpBitmap always has a bit count of 24 => use of GetPixel(...) is safe
146 maColor
= mpReadAccess
->GetPixel( nY
, nX
);
147 mpBitmap
->ReleaseAccess( mpReadAccess
);
152 // -----------------------------------------------------------------------
153 void SvColorControl::MouseMove( const MouseEvent
& rMEvt
)
157 ShowPosition( rMEvt
.GetPosPixel() );
162 // -----------------------------------------------------------------------
163 void SvColorControl::MouseButtonDown( const MouseEvent
& rMEvt
)
165 if( rMEvt
.IsLeft() && !rMEvt
.IsShift() )
167 //ShowPointer( FALSE );
169 ShowPosition( rMEvt
.GetPosPixel() );
174 // -----------------------------------------------------------------------
175 void SvColorControl::MouseButtonUp( const MouseEvent
& )
177 //ShowPointer( TRUE );
178 if( IsMouseCaptured() )
182 // -----------------------------------------------------------------------
183 void SvColorControl::Paint( const Rectangle
& rRect
)
188 Bitmap
aOutputBitmap( *mpBitmap
);
190 if( GetBitCount() <= 8 )
191 aOutputBitmap
.Dither();
193 DrawBitmap( rRect
.TopLeft(), rRect
.GetSize(), rRect
.TopLeft(), rRect
.GetSize(), aOutputBitmap
);
195 // Positions-Control (Fadenkreuz oder Aehnliches)
196 Point
aPos1( maPosition
);
197 Point
aPos2( maPosition
);
199 DrawLine( aPos1
, aPos2
);
202 DrawLine( aPos1
, aPos2
);
205 DrawLine( aPos1
, aPos2
);
208 DrawLine( aPos1
, aPos2
);
211 // -----------------------------------------------------------------------
212 void SvColorControl::Resize()
218 // -----------------------------------------------------------------------
219 void SvColorControl::Modify()
221 maModifyHdl
.Call( this );
224 // -----------------------------------------------------------------------
225 void SvColorControl::SetColor( const ColorHSB
& rCol
, BOOL bSetColor
)
228 maColor
= rCol
.GetRGB();
232 USHORT nX
= (USHORT
) mpBitmap
->GetSizePixel().Width();
233 USHORT nY
= (USHORT
) mpBitmap
->GetSizePixel().Height();
234 INT16 nZ
= rCol
.GetBri();
237 nX
= rCol
.GetHue() * nX
/ 360; // Farbe
238 nY
= nY
- rCol
.GetSat() * nY
/ 100; // Saettigung
239 ShowPosition( Point( nX
, nY
) );
243 // -----------------------------------------------------------------------
244 void SvColorControl::SetColor( const Color
& rCol
)
250 ColorHSB
aColHsb( rCol
);
251 SetColor( aColHsb
, FALSE
);
255 // -----------------------------------------------------------------------
256 void SvColorControl::SetLuminance( short nLum
)
258 if( nLum
!= mnLuminance
&& nLum
>= 0 && nLum
<= 100 )
262 if( mnLuminance
< 40 )
263 SetLineColor( Color( COL_WHITE
) );
265 SetLineColor( Color( COL_BLACK
) );
269 long nX
= maPosition
.X() + 2;
270 long nY
= maPosition
.Y() + 2;
272 if( mpBitmap
&& ( ( mpReadAccess
= mpBitmap
->AcquireReadAccess() ) != NULL
) )
274 // mpBitmap always has a bit count of 24 => use of GetPixel(...) is safe
275 maColor
= mpReadAccess
->GetPixel( nY
, nX
);
276 mpBitmap
->ReleaseAccess( mpReadAccess
);
285 // -----------------------
286 // - ColorPreviewControl -
287 // -----------------------
290 // -----------------------------------------------------------------------
291 ColorPreviewControl::ColorPreviewControl( Window
* pParent
, WinBits nStyle
) :
292 Control ( pParent
, nStyle
)
294 SetFillColor( maColor
);
295 SetLineColor( maColor
);
298 // -----------------------------------------------------------------------
299 ColorPreviewControl::ColorPreviewControl( Window
* pParent
, const ResId
& rResId
) :
300 Control ( pParent
, rResId
)
302 SetFillColor( maColor
);
303 SetLineColor( maColor
);
307 // -----------------------------------------------------------------------
308 ColorPreviewControl::~ColorPreviewControl()
312 // -----------------------------------------------------------------------
313 void ColorPreviewControl::Paint( const Rectangle
& rRect
)
318 // -----------------------------------------------------------------------
319 void ColorPreviewControl::SetColor( const Color
& rCol
)
321 if( rCol
!= maColor
)
324 SetFillColor( maColor
);
325 SetLineColor( maColor
);
331 // -----------------------
332 // - ColorMixingControl -
333 // -----------------------
336 // -----------------------------------------------------------------------
337 ColorMixingControl::ColorMixingControl( Window
* pParent
, WinBits nStyle
,
338 USHORT nRows
, USHORT nColumns
) :
339 ValueSet ( pParent
, nStyle
),
341 mnColumns ( nColumns
)
346 // -----------------------------------------------------------------------
347 ColorMixingControl::ColorMixingControl( Window
* pParent
, const ResId
& rResId
,
348 USHORT nRows
, USHORT nColumns
) :
349 ValueSet ( pParent
, rResId
),
351 mnColumns ( nColumns
)
357 // -----------------------------------------------------------------------
358 ColorMixingControl::~ColorMixingControl()
362 // -----------------------------------------------------------------------
363 void ColorMixingControl::Initialize()
365 SetColCount( mnColumns
);
369 for( USHORT i
= 1; i
<= mnRows
* mnColumns
; i
++ )
371 InsertItem( i
, aColor
, aStr
);
374 /*maColor[ 0 ] = Color( COL_LIGHTRED );
375 maColor[ 1 ] = Color( COL_LIGHTGREEN );
376 maColor[ 2 ] = Color( COL_YELLOW );
377 maColor[ 3 ] = Color( COL_LIGHTBLUE );*/
379 SetColor( CMC_TOPLEFT
, Color( COL_LIGHTRED
) );
380 SetColor( CMC_BOTTOMRIGHT
, Color( COL_LIGHTBLUE
) );
382 SetColor( CMC_TOPRIGHT
, Color( COL_LIGHTGREEN
) );
383 SetColor( CMC_BOTTOMLEFT
, Color( COL_YELLOW
) );
386 FillColumn( mnColumns - 1 );
387 for( i = 0; i < mnRows; i++ )
391 // -----------------------------------------------------------------------
392 Color
ColorMixingControl::CalcDifferenceColor( USHORT nCol1
, USHORT nCol2
,
395 // Die Berechnung ist noch etwas ungenau, daher sollte besser mit floats
396 // gearbeitet werden... (muss !!!)
397 Color
aColor( GetItemColor( nCol1
) );
398 Color
aColor2( GetItemColor( nCol2
) );
400 aColor
.SetRed( (UINT8
) ( ( aColor2
.GetRed() - aColor
.GetRed() ) / nSteps
) );
401 aColor
.SetGreen( (UINT8
) ( ( aColor2
.GetGreen() - aColor
.GetGreen() ) / nSteps
) );
402 aColor
.SetBlue( (UINT8
) ( ( aColor2
.GetBlue() - aColor
.GetBlue() ) / nSteps
) );
407 // -----------------------------------------------------------------------
408 void ColorMixingControl::FillRow( USHORT nRow
)
410 USHORT nCol1
= nRow
* mnColumns
+ 1;
411 USHORT nCol2
= ( nRow
+ 1 ) * mnColumns
;
412 Color
aColor( GetItemColor( nCol1
) );
413 Color
aDiffColor( CalcDifferenceColor( nCol1
, nCol2
, mnColumns
- 1 ) );
415 for( USHORT i
= nCol1
+ 1; i
< nCol2
; i
++ )
417 aColor
.SetRed( aColor
.GetRed() + aDiffColor
.GetRed() );
418 aColor
.SetGreen( aColor
.GetGreen() + aDiffColor
.GetGreen() );
419 aColor
.SetBlue( aColor
.GetBlue() + aDiffColor
.GetBlue() );
421 SetItemColor( i
, aColor
);
422 SetItemText( i
, GetRGBString( aColor
) );
426 // -----------------------------------------------------------------------
427 void ColorMixingControl::FillColumn( USHORT nColumn
)
429 USHORT nCol1
= nColumn
+ 1;
430 USHORT nCol2
= nColumn
+ ( mnRows
- 1 ) * mnColumns
+ 1;
431 Color
aColor( GetItemColor( nCol1
) );
432 Color
aDiffColor( CalcDifferenceColor( nCol1
, nCol2
, mnRows
- 1 ) );
434 for( USHORT i
= nCol1
+ mnColumns
; i
< nCol2
; i
= i
+ mnColumns
)
436 aColor
.SetRed( aColor
.GetRed() + aDiffColor
.GetRed() );
437 aColor
.SetGreen( aColor
.GetGreen() + aDiffColor
.GetGreen() );
438 aColor
.SetBlue( aColor
.GetBlue() + aDiffColor
.GetBlue() );
440 SetItemColor( i
, aColor
);
441 SetItemText( i
, GetRGBString( aColor
) );
445 // -----------------------------------------------------------------------
446 void ColorMixingControl::SetRows( USHORT nRows
)
451 // -----------------------------------------------------------------------
452 void ColorMixingControl::SetColumns( USHORT nColumns
)
454 mnColumns
= nColumns
;
457 // -----------------------------------------------------------------------
458 void ColorMixingControl::SetColor( CMCPosition ePos
, const Color
& rCol
)
460 if( rCol
!= maColor
[ ePos
] )
462 maColor
[ ePos
] = rCol
;
465 String
aStr( GetRGBString( rCol
) );
476 nColumn
= mnColumns
- 1;
480 nPos
= ( mnRows
- 1 ) * mnColumns
+ 1;
484 case CMC_BOTTOMRIGHT
:
485 nPos
= mnRows
* mnColumns
;
486 nColumn
= mnColumns
- 1;
489 break; // -Wall not handled.
491 SetItemColor( nPos
, rCol
);
492 SetItemText( nPos
, aStr
);
493 FillColumn( nColumn
);
495 for( USHORT i
= 0; i
< mnRows
; i
++ )
500 // -----------------------------------------------------------------------
501 String
ColorMixingControl::GetRGBString( const Color
& rColor
)
503 String
aStr( String::CreateFromInt32(rColor
.GetRed()) );
505 aStr
+= String::CreateFromInt32(rColor
.GetGreen());
507 aStr
+= String::CreateFromInt32(rColor
.GetBlue());
511 // -----------------------------------------------------------------------
512 CMCPosition
ColorMixingControl::GetCMCPosition() const
514 CMCPosition ePos
= CMC_OTHER
;
515 USHORT nPos
= GetSelectItemId();
519 else if( nPos
== mnColumns
)
521 else if( nPos
== ( mnRows
- 1 ) * mnColumns
+ 1 )
522 ePos
= CMC_BOTTOMLEFT
;
523 else if( nPos
== mnRows
* mnColumns
)
524 ePos
= CMC_BOTTOMRIGHT
;
534 // Erste Ansaetze gingen auf die Berechnung von Sven Hannover zurueck
535 // Der jetzige Algorithmus stammt im weitesten Sinne aus dem Foley/VanDam
538 /**************************************************************************
540 |* ColorHSB::ColorHSB()
542 |* Beschreibung RGB nach HSB
543 |* Ersterstellung SOH 02.10.97
545 **************************************************************************/
547 ColorHSB::ColorHSB( const Color
& rColor
)
552 c
[0] = rColor
.GetRed();
553 c
[1] = rColor
.GetGreen();
554 c
[2] = rColor
.GetBlue();
562 // Brightness = max(R, G, B);
563 mnBri
= cMax
* 100 / 255;
571 UINT8 cDelta
= cMax
- cMin
;
573 // Saturation = max - min / max
575 mnSat
= cDelta
* 100 / cMax
;
580 mnHue
= 0; // Default = undefined
587 dHue
= (double)( c
[1] - c
[2] ) / (double)cDelta
;
589 else if( c
[1] == cMax
)
591 dHue
= 2.0 + (double)( c
[2] - c
[0] ) / (double)cDelta
;
593 else if ( c
[2] == cMax
)
595 dHue
= 4.0 + (double)( c
[0] - c
[1] ) / (double)cDelta
;
597 // else dHue = ??? -Wall FIXME
603 mnHue
= (UINT16
) dHue
;
607 /**************************************************************************
609 |* ColorHSB::GetRGB()
611 |* Beschreibung HSB nach RGB
612 |* Ersterstellung SOH 02.10.97
614 **************************************************************************/
616 Color
ColorHSB::GetRGB() const
619 UINT8 nB
= (UINT8
) ( mnBri
* 255 / 100 );
639 // #107375# Doing the calculation completely in floating
640 // point, the former optimization gave sometimes negative
641 // results for c and was pointless anyway
642 UINT8 a
= static_cast<UINT8
>( nB
* ( 100.0 - mnSat
) / 100.0 );
643 UINT8 b
= static_cast<UINT8
>( nB
* ( 100.0 - mnSat
* f
) / 100.0 );
644 UINT8 c
= static_cast<UINT8
>( nB
* ( 100.0 - mnSat
* ( 1.0 - f
) ) / 100.0 );
648 case 0: cR
= nB
; cG
= c
; cB
= a
; break;
649 case 1: cR
= b
; cG
= nB
; cB
= a
; break;
650 case 2: cR
= a
; cG
= nB
; cB
= c
; break;
651 case 3: cR
= a
; cG
= b
; cB
= nB
; break;
652 case 4: cR
= c
; cG
= a
; cB
= nB
; break;
653 case 5: cR
= nB
; cG
= a
; cB
= b
; break;
654 default: cR
= 0; cG
= 0; cB
= 0; break; // -Wall ????
658 return( Color( cR
, cG
, cB
) );
666 // -----------------------------------------------------------------------
667 ColorCMYK::ColorCMYK( const Color
& rColor
)
669 mnCyan
= 255 - rColor
.GetRed();
670 mnMagenta
= 255 - rColor
.GetGreen();
671 mnYellow
= 255 - rColor
.GetBlue();
673 mnKey
= Min( Min( mnCyan
, mnMagenta
), mnYellow
);
675 mnCyan
= mnCyan
- mnKey
;
676 mnMagenta
= mnMagenta
- mnKey
;
677 mnYellow
= mnYellow
- mnKey
;
680 // -----------------------------------------------------------------------
681 Color
ColorCMYK::GetRGB() const
683 int nTmp
= Max( 0, 255 - ( mnCyan
+ mnKey
) );
684 UINT8 cR
= (UINT8
) nTmp
;
685 nTmp
= Max( 0, 255 - ( mnMagenta
+ mnKey
) );
686 UINT8 cG
= (UINT8
) nTmp
;
687 nTmp
= Max( 0, 255 - ( mnYellow
+ mnKey
) );
688 UINT8 cB
= (UINT8
) nTmp
;
690 return( Color( cR
, cG
, cB
) );