1 // Created on: 2004-06-22
3 // Copyright (c) 2004-2012 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
21 #include <Aspect_ColorScale.ixx>
23 #include <Aspect_ColorMap.hxx>
24 #include <Aspect_ColorMapEntry.hxx>
25 #include <Aspect_SequenceOfColor.hxx>
26 #include <Aspect_TypeOfColorScaleData.hxx>
27 #include <Aspect_TypeOfColorScalePosition.hxx>
29 #include <TCollection_AsciiString.hxx>
30 #include <TCollection_ExtendedString.hxx>
31 #include <TColStd_SequenceOfExtendedString.hxx>
33 #include <Precision.hxx>
37 Aspect_ColorScale::Aspect_ColorScale()
48 myAtBorder( Standard_True ),
49 myReversed( Standard_False ),
50 myColorType( Aspect_TOCSD_AUTO ),
51 myLabelType( Aspect_TOCSD_AUTO ),
52 myLabelPos( Aspect_TOCSP_RIGHT ),
53 myTitlePos( Aspect_TOCSP_CENTER ),
58 Standard_Real Aspect_ColorScale::GetMin() const
63 Standard_Real Aspect_ColorScale::GetMax() const
68 void Aspect_ColorScale::GetRange( Standard_Real& aMin, Standard_Real& aMax ) const
74 Aspect_TypeOfColorScaleData Aspect_ColorScale::GetLabelType() const
79 Aspect_TypeOfColorScaleData Aspect_ColorScale::GetColorType() const
84 Standard_Integer Aspect_ColorScale::GetNumberOfIntervals() const
89 TCollection_ExtendedString Aspect_ColorScale::GetTitle() const
94 TCollection_AsciiString Aspect_ColorScale::GetFormat() const
99 TCollection_ExtendedString Aspect_ColorScale::GetLabel( const Standard_Integer anIndex ) const
101 TCollection_ExtendedString aLabel;
102 if ( anIndex >= 0 && anIndex < myLabels.Length() )
103 aLabel = myLabels.Value( anIndex + 1 );
107 Quantity_Color Aspect_ColorScale::GetColor( const Standard_Integer anIndex ) const
109 Quantity_Color aColor;
110 if ( anIndex >= 0 && anIndex < myColors.Length() )
111 aColor = myColors.Value( anIndex + 1 );
115 void Aspect_ColorScale::GetLabels( TColStd_SequenceOfExtendedString& aLabels ) const
118 for ( Standard_Integer i = 1; i <= myLabels.Length(); i++ )
119 aLabels.Append( myLabels.Value( i ) );
122 void Aspect_ColorScale::GetColors( Aspect_SequenceOfColor& aColors ) const
125 for ( Standard_Integer i = 1; i <= myColors.Length(); i++ )
126 aColors.Append( myColors.Value( i ) );
129 Aspect_TypeOfColorScalePosition Aspect_ColorScale::GetLabelPosition() const
134 Aspect_TypeOfColorScalePosition Aspect_ColorScale::GetTitlePosition() const
139 Standard_Boolean Aspect_ColorScale::IsReversed() const
144 Standard_Boolean Aspect_ColorScale::IsLabelAtBorder() const
149 void Aspect_ColorScale::SetMin( const Standard_Real aMin )
151 SetRange( aMin, GetMax() );
154 void Aspect_ColorScale::SetMax( const Standard_Real aMax )
156 SetRange( GetMin(), aMax );
159 void Aspect_ColorScale::SetRange( const Standard_Real aMin, const Standard_Real aMax )
161 if ( myMin == aMin && myMax == aMax )
164 myMin = Min( aMin, aMax );
165 myMax = Max( aMin, aMax );
167 if ( GetColorType() == Aspect_TOCSD_AUTO )
171 void Aspect_ColorScale::SetLabelType( const Aspect_TypeOfColorScaleData aType )
173 if ( myLabelType == aType )
180 void Aspect_ColorScale::SetColorType( const Aspect_TypeOfColorScaleData aType )
182 if ( myColorType == aType )
189 void Aspect_ColorScale::SetNumberOfIntervals( const Standard_Integer aNum )
191 if ( myInterval == aNum || aNum < 1 )
198 void Aspect_ColorScale::SetTitle( const TCollection_ExtendedString& aTitle )
200 if ( myTitle == aTitle )
207 void Aspect_ColorScale::SetFormat( const TCollection_AsciiString& aFormat )
209 if ( myFormat == aFormat )
213 if ( GetLabelType() == Aspect_TOCSD_AUTO )
217 void Aspect_ColorScale::SetLabel( const TCollection_ExtendedString& aLabel, const Standard_Integer anIndex )
219 Standard_Boolean changed = Standard_False;
220 Standard_Integer i = anIndex < 1 ? myLabels.Length() + 1 : anIndex;
221 if ( i <= myLabels.Length() ) {
222 changed = myLabels.Value( i ) != aLabel;
223 myLabels.SetValue( i, aLabel );
226 changed = Standard_True;
227 while ( i > myLabels.Length() )
228 myLabels.Append( TCollection_ExtendedString() );
229 myLabels.SetValue( i, aLabel );
235 void Aspect_ColorScale::SetColor(const Quantity_Color& aColor, const Standard_Integer anIndex )
237 Standard_Boolean changed = Standard_False;
238 Standard_Integer i = anIndex < 1 ? myLabels.Length() + 1 : anIndex;
239 if ( i <= myColors.Length() ) {
240 changed = myColors.Value( i ) != aColor;
241 myColors.SetValue( i, aColor );
244 changed = Standard_True;
245 while ( i > myColors.Length() )
246 myColors.Append( Quantity_Color() );
247 myColors.SetValue( i, aColor );
253 void Aspect_ColorScale::SetLabels( const TColStd_SequenceOfExtendedString& aSeq )
256 for ( Standard_Integer i = 1; i <= aSeq.Length(); i++ )
257 myLabels.Append( aSeq.Value( i ) );
260 void Aspect_ColorScale::SetColors( const Handle(Aspect_ColorMap)& aMap )
263 if ( !aMap.IsNull() )
264 for ( Standard_Integer i = 1; i <= aMap->Size(); i++ )
265 myColors.Append( aMap->Entry( i ).Color() );
268 void Aspect_ColorScale::SetColors( const Aspect_SequenceOfColor& aSeq )
271 for ( Standard_Integer i = 1; i <= aSeq.Length(); i++ )
272 myColors.Append( aSeq.Value( i ) );
275 void Aspect_ColorScale::SetLabelPosition( const Aspect_TypeOfColorScalePosition aPos )
277 if ( myLabelPos == aPos )
284 void Aspect_ColorScale::SetTitlePosition( const Aspect_TypeOfColorScalePosition aPos )
286 if ( myTitlePos == aPos )
293 void Aspect_ColorScale::SetReversed( const Standard_Boolean aReverse )
295 if ( myReversed == aReverse )
298 myReversed = aReverse;
302 void Aspect_ColorScale::SetLabelAtBorder( const Standard_Boolean anOn )
304 if ( myAtBorder == anOn )
311 void Aspect_ColorScale::GetPosition( Standard_Real& aX, Standard_Real& aY ) const
317 Standard_Real Aspect_ColorScale::GetXPosition() const
322 Standard_Real Aspect_ColorScale::GetYPosition() const
327 void Aspect_ColorScale::SetPosition( const Standard_Real aX, const Standard_Real aY )
329 if ( myXPos == aX && myYPos == aY )
338 void Aspect_ColorScale::SetXPosition( const Standard_Real aX )
340 SetPosition( aX, GetYPosition() );
343 void Aspect_ColorScale::SetYPosition( const Standard_Real aY )
345 SetPosition( GetXPosition(), aY );
348 void Aspect_ColorScale::GetSize( Standard_Real& aWidth, Standard_Real& aHeight ) const
354 Standard_Real Aspect_ColorScale::GetWidth() const
359 Standard_Real Aspect_ColorScale::GetHeight() const
364 void Aspect_ColorScale::SetSize( const Standard_Real aWidth, const Standard_Real aHeight )
366 if ( myWidth == aWidth && myHeight == aHeight )
375 void Aspect_ColorScale::SetWidth( const Standard_Real aWidth )
377 SetSize( aWidth, GetHeight() );
380 void Aspect_ColorScale::SetHeight( const Standard_Real aHeight )
382 SetSize( GetWidth(), aHeight );
385 void Aspect_ColorScale::SizeHint( Standard_Integer& aWidth, Standard_Integer& aHeight ) const
387 Standard_Integer num = GetNumberOfIntervals();
389 Standard_Integer spacer = 5;
390 Standard_Integer textWidth = 0;
391 Standard_Integer textHeight = TextHeight( "" );
392 Standard_Integer colorWidth = 20;
394 if ( GetLabelPosition() != Aspect_TOCSP_NONE )
395 for ( Standard_Integer idx = 0; idx < num; idx++ )
396 textWidth = Max( textWidth, TextWidth( GetCurrentLabel( idx + 1 ) ) );
398 Standard_Integer scaleWidth = 0;
399 Standard_Integer scaleHeight = 0;
401 Standard_Integer titleWidth = 0;
402 Standard_Integer titleHeight = 0;
404 if ( IsLabelAtBorder() ) {
406 if ( GetTitle().Length() )
410 scaleWidth = colorWidth + textWidth + ( textWidth ? 3 : 2 ) * spacer;
411 scaleHeight = (Standard_Integer)( 1.5 * ( num + 1 ) * textHeight );
413 if ( GetTitle().Length() ) {
414 titleHeight = TextHeight( GetTitle() ) + spacer;
415 titleWidth = TextWidth( GetTitle() ) + 10;
418 aWidth = Max( titleWidth, scaleWidth );
419 aHeight = scaleHeight + titleHeight;
422 void Aspect_ColorScale::DrawScale( const Quantity_Color& aBgColor,
423 const Standard_Integer X, const Standard_Integer Y,
424 const Standard_Integer W, const Standard_Integer H )
429 Standard_Integer num = GetNumberOfIntervals();
430 Aspect_TypeOfColorScalePosition labPos = GetLabelPosition();
432 Standard_Integer spacer = 5;
433 Standard_Integer textWidth = 0;
434 Standard_Integer textHeight = TextHeight( "" );
436 Standard_Boolean drawLabel = GetLabelPosition() != Aspect_TOCSP_NONE;
438 TCollection_ExtendedString aTitle = GetTitle();
440 Standard_Integer titleWidth = 0;
441 Standard_Integer titleHeight = 0;
443 Standard_Integer aGray = (Standard_Integer)(255 * ( aBgColor.Red() * 11 + aBgColor.Green() * 16 + aBgColor.Blue() * 5 ) / 32);
444 Quantity_Color aFgColor( aGray < 128 ? Quantity_NOC_WHITE : Quantity_NOC_BLACK );
447 if ( aTitle.Length() ) {
448 titleWidth = TextWidth( aTitle );
449 titleHeight = TextHeight( aTitle ) + 2 * spacer;
450 PaintText( aTitle, X + spacer, Y + spacer, aFgColor );
453 Standard_Boolean reverse = IsReversed();
455 Aspect_SequenceOfColor colors;
456 TColStd_SequenceOfExtendedString labels;
457 for ( int idx = 0; idx < num; idx++ ) {
459 colors.Append( GetCurrentColor( idx ) );
460 labels.Append( GetCurrentLabel( idx ) );
463 colors.Prepend( GetCurrentColor( idx ) );
464 labels.Prepend( GetCurrentLabel( idx ) );
468 if ( IsLabelAtBorder() ) {
470 labels.Append( GetCurrentLabel( num ) );
472 labels.Prepend( GetCurrentLabel( num ) );
476 for ( Standard_Integer i = 1; i <= labels.Length(); i++ )
477 textWidth = Max( textWidth, TextWidth( labels.Value( i ) ) );
479 Standard_Integer lab = labels.Length();
481 Standard_Real spc = ( H - ( ( Min( lab, 2 ) + Abs( lab - num - 1 ) ) * textHeight ) - titleHeight );
482 Standard_Real val = spc != 0 ? 1.0 * ( lab - Min( lab, 2 ) ) * textHeight / spc : 0;
484 Standard_Real fPart = modf( val, &iPart );
485 Standard_Integer filter = (Standard_Integer)iPart + ( fPart != 0 ? 1 : 0 );
487 Standard_Real step = 1.0 * ( H - ( lab - num + Abs( lab - num - 1 ) ) * textHeight - titleHeight ) / num;
489 Standard_Integer ascent = 0;
490 Standard_Integer colorWidth = Max( 5, Min( 20, W - textWidth - 3 * spacer ) );
491 if ( labPos == Aspect_TOCSP_CENTER || !drawLabel )
492 colorWidth = W - 2 * spacer;
495 Standard_Integer x = X + spacer;
496 if ( labPos == Aspect_TOCSP_LEFT )
497 x += textWidth + ( textWidth ? 1 : 0 ) * spacer;
499 Standard_Real offset = 1.0 * textHeight / 2 * ( lab - num + Abs( lab - num - 1 ) ) + titleHeight;
500 for ( Standard_Integer ci = 1; ci <= colors.Length() && step > 0; ci++ ) {
501 Standard_Integer y = (Standard_Integer)( Y + ( ci - 1 )* step + offset );
502 Standard_Integer h = (Standard_Integer)( Y + ( ci ) * step + offset ) - y;
503 PaintRect( x, y, colorWidth, h, colors.Value( ci ), Standard_True );
507 PaintRect( x - 1, (Standard_Integer)(Y + offset - 1), colorWidth + 2, (Standard_Integer)(colors.Length() * step + 2), aFgColor );
510 offset = 1.0 * Abs( lab - num - 1 ) * ( step - textHeight ) / 2 + 1.0 * Abs( lab - num - 1 ) * textHeight / 2;
511 offset += titleHeight;
512 if ( drawLabel && labels.Length() && filter > 0 ) {
513 Standard_Integer i1 = 0;
514 Standard_Integer i2 = lab - 1;
515 Standard_Integer last1( i1 ), last2( i2 );
518 case Aspect_TOCSP_CENTER:
519 x += ( colorWidth - textWidth ) / 2;
521 case Aspect_TOCSP_RIGHT:
522 x += colorWidth + spacer;
525 while ( i2 - i1 >= filter || ( i2 == 0 && i1 == 0 ) ) {
526 Standard_Integer pos1 = i1;
527 Standard_Integer pos2 = lab - 1 - i2;
528 if ( filter && !( pos1 % filter ) ) {
529 PaintText( labels.Value( i1 + 1 ), x, (Standard_Integer)( Y + i1 * step + ascent + offset ), aFgColor );
532 if ( filter && !( pos2 % filter ) ) {
533 PaintText( labels.Value( i2 + 1 ), x, (Standard_Integer)( Y + i2 * step + ascent + offset ), aFgColor );
539 Standard_Integer pos = i1;
540 Standard_Integer i0 = -1;
541 while ( pos <= i2 && i0 == -1 ) {
542 if ( filter && !( pos % filter ) && Abs( pos - last1 ) >= filter && Abs( pos - last2 ) >= filter )
548 PaintText( labels.Value( i0 + 1 ), x, (Standard_Integer)( Y + i0 * step + ascent + offset ), aFgColor );
554 Standard_Boolean Aspect_ColorScale::BeginPaint()
556 return Standard_True;
559 Standard_Boolean Aspect_ColorScale::EndPaint()
561 return Standard_True;
564 void Aspect_ColorScale::UpdateColorScale()
568 TCollection_AsciiString Aspect_ColorScale::Format() const
573 TCollection_ExtendedString Aspect_ColorScale::GetCurrentLabel( const Standard_Integer anIndex ) const
575 TCollection_ExtendedString aLabel;
576 if ( GetLabelType() == Aspect_TOCSD_USER )
577 aLabel = GetLabel( anIndex );
579 Standard_Real val = GetNumber( anIndex );
580 Standard_Character buf[1024];
581 TCollection_AsciiString aFormat = Format();
582 sprintf( buf, aFormat.ToCString(), val );
583 aLabel = TCollection_ExtendedString( buf );
589 Quantity_Color Aspect_ColorScale::GetCurrentColor( const Standard_Integer anIndex ) const
591 Quantity_Color aColor;
592 if ( GetColorType() == Aspect_TOCSD_USER )
593 aColor = GetColor( anIndex );
595 aColor = Quantity_Color( HueFromValue( anIndex, 0, GetNumberOfIntervals() - 1 ), 1.0, 1.0, Quantity_TOC_HLS );
599 Standard_Real Aspect_ColorScale::GetNumber( const Standard_Integer anIndex ) const
601 Standard_Real aNum = 0;
602 if ( GetNumberOfIntervals() > 0 )
603 aNum = GetMin() + anIndex * ( Abs( GetMax() - GetMin() ) / GetNumberOfIntervals() );
607 Standard_Integer Aspect_ColorScale::HueFromValue( const Standard_Integer aValue,
608 const Standard_Integer aMin, const Standard_Integer aMax )
610 Standard_Integer minLimit( 0 ), maxLimit( 230 );
612 Standard_Integer aHue = maxLimit;
614 aHue = (Standard_Integer)( maxLimit - ( maxLimit - minLimit ) * ( aValue - aMin ) / ( aMax - aMin ) );
616 aHue = Min( Max( minLimit, aHue ), maxLimit );
621 Standard_Integer Aspect_ColorScale::GetTextHeight() const {
625 void Aspect_ColorScale::SetTextHeight(const Standard_Integer aHeigh) {
626 myTextHeight = aHeigh;
631 Standard_Boolean Aspect_ColorScale::FindColor( const Standard_Real aValue,
632 Quantity_Color& aColor ) const
634 return FindColor( aValue, myMin, myMax, myInterval, aColor );
638 Standard_Boolean Aspect_ColorScale::FindColor( const Standard_Real aValue,
639 const Standard_Real aMin,
640 const Standard_Real aMax,
641 const Standard_Integer ColorsCount,
642 Quantity_Color& aColor )
644 if( aValue<aMin || aValue>aMax || aMax<aMin )
645 return Standard_False;
649 Standard_Real IntervNumber = 0;
652 else if( aValue>aMax )
653 IntervNumber = ColorsCount-1;
654 else if( Abs( aMax-aMin ) > Precision::Approximation() )
655 IntervNumber = Ceiling( Standard_Real( ColorsCount ) * ( aValue - aMin ) / ( aMax - aMin ) );
657 Standard_Integer Interv = Standard_Integer( IntervNumber );
659 aColor = Quantity_Color( HueFromValue( Interv, 0, ColorsCount - 1 ), 1.0, 1.0, Quantity_TOC_HLS );
661 return Standard_True;