text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    vtkScalarBarActor.cxx
  
    Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
    All rights reserved.
    See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  
       This software is distributed WITHOUT ANY WARRANTY; without even
       the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
       PURPOSE.  See the above copyright notice for more information.
  
  =========================================================================*/
  #include "vtkScalarBarActor.h"
  #include "vtkScalarBarActorInternal.h"
  
  #include "vtkCellArray.h"
  #include "vtkCellData.h"
  #include "vtkColor.h"
  #include "vtkColorTransferFunction.h"
  #include "vtkCoordinate.h"
  #include "vtkFloatArray.h"
  #include "vtkImageData.h"
  #include "vtkLookupTable.h"
  #include "vtkMath.h"
  #include "vtkMathTextUtilities.h"
  #include "vtkNew.h"
  #include "vtkObjectFactory.h"
  #include "vtkPointData.h"
  #include "vtkPolyData.h"
  #include "vtkPolyDataMapper2D.h"
  #include "vtkProperty2D.h"
  #include "vtkRenderWindow.h"
  #include "vtkRenderer.h"
  #include "vtkScalarsToColors.h"
  #include "vtkSmartPointer.h"
  #include "vtkTextActor.h"
  #include "vtkTextProperty.h"
  #include "vtkTexture.h"
  #include "vtkTexturedActor2D.h"
  #include "vtkViewport.h"
  #include "vtkWindow.h"
  
  #include <vector>
  #include <set>
  #include <map>
  
  #include <cstdio> // for snprintf
  
  #undef VTK_DBG_LAYOUT
  
  vtkStandardNewMacro(vtkScalarBarActor);
  
  vtkCxxSetObjectMacro(vtkScalarBarActor, LookupTable, vtkScalarsToColors);
  vtkCxxSetObjectMacro(vtkScalarBarActor, AnnotationTextProperty, vtkTextProperty);
  vtkCxxSetObjectMacro(vtkScalarBarActor, LabelTextProperty, vtkTextProperty);
  vtkCxxSetObjectMacro(vtkScalarBarActor, TitleTextProperty, vtkTextProperty);
  vtkCxxSetObjectMacro(vtkScalarBarActor, BackgroundProperty, vtkProperty2D);
  vtkCxxSetObjectMacro(vtkScalarBarActor, FrameProperty, vtkProperty2D);
  
  //----------------------------------------------------------------------------
  // Instantiate object with 64 maximum colors; 5 labels; %%-#6.3g label
  // format, no title, and vertical orientation. The initial scalar bar
  // size is (0.05 x 0.8) of the viewport size.
  vtkScalarBarActor::vtkScalarBarActor()
  {
    this->P = new vtkScalarBarActorInternal;
    this->LookupTable = NULL;
    this->Position2Coordinate->SetValue(0.17, 0.8);
  
    this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport();
    this->PositionCoordinate->SetValue(0.82, 0.1);
  
    this->TextPad = 1;
    this->TitleRatio = 0.5;
    this->BarRatio = 0.375;
    this->MaximumNumberOfColors = 64;
    this->NumberOfLabels = 5;
    this->NumberOfLabelsBuilt = 0;
    this->Orientation = VTK_ORIENT_VERTICAL;
    this->Title = NULL;
    this->ComponentTitle = NULL;
    this->VerticalTitleSeparation = 0;
  
    this->LabelTextProperty = vtkTextProperty::New();
    this->LabelTextProperty->SetFontSize(12);
    this->LabelTextProperty->SetBold(1);
    this->LabelTextProperty->SetItalic(1);
    this->LabelTextProperty->SetShadow(1);
    this->LabelTextProperty->SetFontFamilyToArial();
  
    this->AnnotationTextProperty = vtkTextProperty::New();
    this->AnnotationTextProperty->SetFontSize(12);
    this->AnnotationTextProperty->SetBold(1);
    this->AnnotationTextProperty->SetItalic(1);
    this->AnnotationTextProperty->SetShadow(1);
    this->AnnotationTextProperty->SetFontFamilyToArial();
  
    this->TitleTextProperty = vtkTextProperty::New();
    this->TitleTextProperty->ShallowCopy(this->LabelTextProperty);
  
    this->LabelFormat = new char[8];
    sprintf(this->LabelFormat, "%s", "%-#6.3g");
  
    this->TitleActor = vtkTextActor::New();
    this->TitleActor->GetPositionCoordinate()->
      SetReferenceCoordinate(this->PositionCoordinate);
  
    this->ScalarBar = vtkPolyData::New();
    this->ScalarBarMapper = vtkPolyDataMapper2D::New();
    this->ScalarBarMapper->SetInputData(this->ScalarBar);
    this->ScalarBarActor = vtkActor2D::New();
    this->ScalarBarActor->SetMapper(this->ScalarBarMapper);
    this->ScalarBarActor->GetPositionCoordinate()->
      SetReferenceCoordinate(this->PositionCoordinate);
    this->LastOrigin[0] = 0;
    this->LastOrigin[1] = 0;
    this->LastSize[0] = 0;
    this->LastSize[1] = 0;
  
    this->DrawAnnotations = 1;
    this->DrawNanAnnotation = 0;
    this->AnnotationTextScaling = 0;
    this->FixedAnnotationLeaderLineColor = 0;
    this->NanAnnotation = 0;
    this->SetNanAnnotation("NaN");
    this->P->NanSwatch = vtkPolyData::New();
    this->P->NanSwatchMapper = vtkPolyDataMapper2D::New();
    this->P->NanSwatchActor = vtkActor2D::New();
    this->P->NanSwatchMapper->SetInputData(this->P->NanSwatch);
    this->P->NanSwatchActor->SetMapper(this->P->NanSwatchMapper);
    this->P->NanSwatchActor->GetPositionCoordinate()->
      SetReferenceCoordinate(this->PositionCoordinate);
  
    this->DrawBelowRangeSwatch = false;
    this->BelowRangeAnnotation = 0;
    this->SetBelowRangeAnnotation("Below");
    this->P->BelowRangeSwatch = vtkPolyData::New();
    this->P->BelowRangeSwatchMapper = vtkPolyDataMapper2D::New();
    this->P->BelowRangeSwatchActor = vtkActor2D::New();
    this->P->BelowRangeSwatchMapper->SetInputData(this->P->BelowRangeSwatch);
    this->P->BelowRangeSwatchActor->SetMapper(this->P->BelowRangeSwatchMapper);
    this->P->BelowRangeSwatchActor->GetPositionCoordinate()->
      SetReferenceCoordinate(this->PositionCoordinate);
  
    this->DrawAboveRangeSwatch = false;
    this->AboveRangeAnnotation = 0;
    this->SetAboveRangeAnnotation("Above");
    this->P->AboveRangeSwatch = vtkPolyData::New();
    this->P->AboveRangeSwatchMapper = vtkPolyDataMapper2D::New();
    this->P->AboveRangeSwatchActor = vtkActor2D::New();
    this->P->AboveRangeSwatchMapper->SetInputData(this->P->AboveRangeSwatch);
    this->P->AboveRangeSwatchActor->SetMapper(this->P->AboveRangeSwatchMapper);
    this->P->AboveRangeSwatchActor->GetPositionCoordinate()->
      SetReferenceCoordinate(this->PositionCoordinate);
  
    this->AnnotationLeaderPadding = 8.;
    this->P->AnnotationBoxes = vtkPolyData::New();
    this->P->AnnotationBoxesMapper = vtkPolyDataMapper2D::New();
    this->P->AnnotationBoxesActor = vtkActor2D::New();
    this->P->AnnotationBoxesMapper->SetInputData(this->P->AnnotationBoxes);
    this->P->AnnotationBoxesActor->SetMapper(this->P->AnnotationBoxesMapper);
    this->P->AnnotationBoxesActor->GetPositionCoordinate()->
      SetReferenceCoordinate(this->PositionCoordinate);
    this->P->AnnotationLeaders = vtkPolyData::New();
    this->P->AnnotationLeadersMapper = vtkPolyDataMapper2D::New();
    this->P->AnnotationLeadersActor = vtkActor2D::New();
    this->P->AnnotationLeadersMapper->SetInputData(this->P->AnnotationLeaders);
    this->P->AnnotationLeadersActor->SetMapper(this->P->AnnotationLeadersMapper);
    this->P->AnnotationLeadersActor->GetPositionCoordinate()->
      SetReferenceCoordinate(this->PositionCoordinate);
  
    this->P->TitleBox.Posn[0] = 0;
    this->P->TitleBox.Posn[1] = 0;
    this->P->TitleBox.Size[0] = 0;
    this->P->TitleBox.Size[1] = 0;
  
    // If opacity is on, a jail like texture is displayed behind it..
  
    this->UseOpacity       = 0;
    this->TextureGridWidth = 10.0;
  
    this->TexturePolyData = vtkPolyData::New();
    vtkPolyDataMapper2D* textureMapper = vtkPolyDataMapper2D::New();
    textureMapper->SetInputData(this->TexturePolyData);
    this->TextureActor = vtkTexturedActor2D::New();
    this->TextureActor->SetMapper(textureMapper);
    textureMapper->Delete();
    this->TextureActor->GetPositionCoordinate()->
      SetReferenceCoordinate(this->PositionCoordinate);
    vtkFloatArray* tc = vtkFloatArray::New();
    tc->SetNumberOfComponents(2);
    tc->SetNumberOfTuples(4);
    tc->InsertComponent(0, 0, 0.0);
    tc->InsertComponent(0, 1, 0.0);
    tc->InsertComponent(1, 1, 0.0);
    tc->InsertComponent(3, 0, 0.0);
    this->TexturePolyData->GetPointData()->SetTCoords(tc);
    tc->Delete();
  
    vtkCellArray* polys2 = vtkCellArray::New();
    polys2->InsertNextCell(4);
    polys2->InsertCellPoint(0);
    polys2->InsertCellPoint(1);
    polys2->InsertCellPoint(2);
    polys2->InsertCellPoint(3);
    polys2->Delete();
  
    vtkProperty2D* imageProperty = vtkProperty2D::New();
    imageProperty->SetOpacity(0.08);
    this->TextureActor->SetProperty(imageProperty);
    imageProperty->Delete();
  
    // Create the default texture. Just a "Jail" like grid
  
    const unsigned int dim = 128;
    vtkImageData* image = vtkImageData::New();
    image->SetDimensions(dim, dim, 1);
    image->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
  
    for (unsigned int y = 0; y < dim; y++)
      {
      unsigned char* ptr =
        static_cast<unsigned char*>(image->GetScalarPointer(0, y, 0));
      for (unsigned int x = 0; x < dim; x++)
        {
        *ptr = ((x == y) || (x == (dim - y - 1))) ? 255 : 0;
        ++ptr;
        }
      }
  
    this->Texture = vtkTexture::New();
    this->Texture->SetInputData(image);
    this->Texture->RepeatOn();
    this->TextureActor->SetTexture(this->Texture);
    image->Delete();
  
    // Default text position : Above scalar bar if orientation is horizontal
    //                         Right of scalar bar if orientation is vertical
    this->TextPosition = SucceedScalarBar;
  
    this->MaximumWidthInPixels = VTK_INT_MAX;
    this->MaximumHeightInPixels = VTK_INT_MAX;
  
    this->BackgroundProperty = vtkProperty2D::New();
    this->FrameProperty = vtkProperty2D::New();
  
    this->DrawBackground = 0;
    this->Background = vtkPolyData::New();
    this->BackgroundMapper = vtkPolyDataMapper2D::New();
    this->BackgroundMapper->SetInputData(this->Background);
    this->BackgroundActor = vtkActor2D::New();
    this->BackgroundActor->SetMapper(this->BackgroundMapper);
    this->BackgroundActor->GetPositionCoordinate()
      ->SetReferenceCoordinate(this->PositionCoordinate);
  
  #ifdef VTK_DBG_LAYOUT
    this->DrawFrame = 1;
  #else // VTK_DBG_LAYOUT
    this->DrawFrame = 0;
  #endif // VTK_DBG_LAYOUT
    this->Frame = vtkPolyData::New();
    this->FrameMapper = vtkPolyDataMapper2D::New();
    this->FrameMapper->SetInputData(this->Frame);
    this->FrameActor = vtkActor2D::New();
    this->FrameActor->SetMapper(this->FrameMapper);
    this->FrameActor->GetPositionCoordinate()
      ->SetReferenceCoordinate(this->PositionCoordinate);
  
    this->DrawColorBar = 1;
    this->DrawTickLabels = 1;
    this->UnconstrainedFontSize = false;
  }
  
  //----------------------------------------------------------------------------
  // Release any graphics resources that are being consumed by this actor.
  // The parameter window could be used to determine which graphic
  // resources to release.
  void vtkScalarBarActor::ReleaseGraphicsResources(vtkWindow* win)
  {
    this->TitleActor->ReleaseGraphicsResources(win);
    if (!this->P->TextActors.empty())
      {
      vtkScalarBarActorInternal::ActorVector::iterator it;
      for (
           it = this->P->TextActors.begin();
           it != this->P->TextActors.end();
           ++it)
        {
        (*it)->ReleaseGraphicsResources(win);
        }
      }
    for (size_t i = 0; i < this->P->AnnotationLabels.size(); ++i)
      {
      this->P->AnnotationLabels[i]->ReleaseGraphicsResources(win);
      }
    this->ScalarBarActor->ReleaseGraphicsResources(win);
    this->P->NanSwatchActor->ReleaseGraphicsResources(win);
    this->P->AboveRangeSwatchActor->ReleaseGraphicsResources(win);
    this->P->BelowRangeSwatchActor->ReleaseGraphicsResources(win);
    this->P->AnnotationBoxesActor->ReleaseGraphicsResources(win);
    this->P->AnnotationLeadersActor->ReleaseGraphicsResources(win);
    this->BackgroundActor->ReleaseGraphicsResources(win);
    this->FrameActor->ReleaseGraphicsResources(win);
    this->Texture->ReleaseGraphicsResources(win);
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::GetScalarBarRect(int rect[4], vtkViewport* viewport)
  {
    vtkCoordinate *origin = this->ScalarBarActor->GetPositionCoordinate();
    int * vpPos = origin->GetComputedViewportValue(viewport);
    rect[0] = vpPos[0];
    rect[1] = vpPos[1];
  
    double *bounds = this->ScalarBar->GetBounds();
    rect[0] += static_cast<int>(bounds[0] + 0.5);
    rect[1] += static_cast<int>(bounds[2] + 0.5);
    rect[2] = static_cast<int>(bounds[1] - bounds[0] + 0.5);
    rect[3] = static_cast<int>(bounds[3] - bounds[2] + 0.5);
  }
  
  //----------------------------------------------------------------------------
  vtkScalarBarActor::~vtkScalarBarActor()
  {
    delete [] this->LabelFormat;
    this->LabelFormat = NULL;
  
    this->TitleActor->Delete();
    this->SetNanAnnotation(NULL);
    this->SetBelowRangeAnnotation(NULL);
    this->SetAboveRangeAnnotation(NULL);
  
    this->ScalarBar->Delete();
    this->ScalarBarMapper->Delete();
    this->ScalarBarActor->Delete();
  
    this->P->NanSwatch->Delete();
    this->P->BelowRangeSwatch->Delete();
    this->P->AboveRangeSwatch->Delete();
    this->P->NanSwatchMapper->Delete();
    this->P->AboveRangeSwatchMapper->Delete();
    this->P->BelowRangeSwatchMapper->Delete();
    this->P->NanSwatchActor->Delete();
    this->P->AboveRangeSwatchActor->Delete();
    this->P->BelowRangeSwatchActor->Delete();
  
    this->P->AnnotationBoxes->Delete();
    this->P->AnnotationBoxesMapper->Delete();
    this->P->AnnotationBoxesActor->Delete();
  
    this->P->AnnotationLeaders->Delete();
    this->P->AnnotationLeadersMapper->Delete();
    this->P->AnnotationLeadersActor->Delete();
  
    delete [] this->Title;
    this->Title = NULL;
  
    delete [] this->ComponentTitle;
    this->ComponentTitle = NULL;
  
    this->SetLookupTable(NULL);
    this->SetAnnotationTextProperty(NULL);
    this->SetLabelTextProperty(NULL);
    this->SetTitleTextProperty(NULL);
    this->Texture->Delete();
    this->TextureActor->Delete();
    this->TexturePolyData->Delete();
    this->Background->Delete();
    this->BackgroundMapper->Delete();
    this->BackgroundActor->Delete();
    this->Frame->Delete();
    this->FrameMapper->Delete();
    this->FrameActor->Delete();
    this->SetBackgroundProperty(NULL);
    this->SetFrameProperty(NULL);
    delete this->P;
  }
  
  //----------------------------------------------------------------------------
  int vtkScalarBarActor::RenderOverlay(vtkViewport* viewport)
  {
    if (!this->RebuildLayoutIfNeeded(viewport))
      {
      return 0;
      }
  
    int renderedSomething = 0;
  
    // Is the viewport's RenderWindow capturing GL2PS-special props? We'll need
    // to handle this specially to get the texture to show up right.
    if (vtkRenderer *renderer = vtkRenderer::SafeDownCast(viewport))
      {
      if (vtkRenderWindow *renderWindow = renderer->GetRenderWindow())
        {
        if (renderWindow->GetCapturingGL2PSSpecialProps())
          {
          renderer->CaptureGL2PSSpecialProp(this);
          }
        }
      }
  
    // Everything is built, just have to render
    if (this->DrawBackground)
      {
      renderedSomething += this->BackgroundActor->RenderOverlay(viewport);
      }
  
    if (this->UseOpacity && this->DrawColorBar)
      {
      renderedSomething += this->TextureActor->RenderOverlay(viewport);
      }
  
    // Draw either the scalar bar (non-indexed mode) or
    // the annotated value boxes (indexed mode).
    if (!this->LookupTable->GetIndexedLookup())
      {
      if (this->DrawColorBar)
        {
        renderedSomething += this->ScalarBarActor->RenderOverlay(viewport);
        }
  
      if (this->DrawTickLabels)
        {
        vtkScalarBarActorInternal::ActorVector::iterator it;
        for (
             it = this->P->TextActors.begin();
             it != this->P->TextActors.end();
             ++it)
          {
          renderedSomething += (*it)->RenderOverlay(viewport);
          }
        }
      }
    else if (this->DrawColorBar)
      {
      renderedSomething +=
        this->P->AnnotationBoxesActor->RenderOverlay(viewport);
      }
  
    if (this->DrawNanAnnotation)
      {
      renderedSomething +=
        this->P->NanSwatchActor->RenderOverlay(viewport);
      }
  
    if (this->DrawBelowRangeSwatch)
      {
      renderedSomething +=
        this->P->BelowRangeSwatchActor->RenderOverlay(viewport);
      }
  
    if (this->DrawAboveRangeSwatch)
      {
      renderedSomething +=
        this->P->AboveRangeSwatchActor->RenderOverlay(viewport);
      }
  
    if (this->DrawFrame)
      {
      renderedSomething += this->FrameActor->RenderOverlay(viewport);
      }
  
    if (this->Title != NULL)
      {
      renderedSomething += this->TitleActor->RenderOverlay(viewport);
      }
  
    if (this->DrawAnnotations)
      {
      if (!this->P->AnnotationLabels.empty())
        {
        renderedSomething +=
          this->P->AnnotationLeadersActor->RenderOverlay(viewport);
        for (size_t i = 0; i < this->P->AnnotationLabels.size(); ++i)
          {
          renderedSomething +=
            this->P->AnnotationLabels[i]->RenderOverlay(viewport);
          }
        }
      }
  
    renderedSomething = (renderedSomething > 0)?(1):(0);
    return renderedSomething;
  }
  
  int vtkScalarBarActor::RebuildLayoutIfNeeded(vtkViewport* viewport)
  {
    if (!this->LookupTable)
      {
      vtkWarningMacro(<< "Need a mapper to render a scalar bar");
      return 0;
      }
  
    if (!this->TitleTextProperty)
      {
      vtkErrorMacro(<< "Need title text property to render a scalar bar");
      return 0;
      }
  
    if (!this->LabelTextProperty)
      {
      vtkErrorMacro(<< "Need label text property to render a scalar bar");
      return 0;
      }
  
    if (!this->AnnotationTextProperty)
      {
      vtkErrorMacro(<< "Need annotation text property to render a scalar bar");
      return 0;
      }
  
    // Check to see whether we have to rebuild everything
    int positionsHaveChanged = 0;
    if (viewport->GetMTime() > this->BuildTime ||
        (viewport->GetVTKWindow() &&
          viewport->GetVTKWindow()->GetMTime() > this->BuildTime))
      {
      // if the viewport has changed we may - or may not need
      // to rebuild, it depends on if the projected coords chage
      int size[2];
      int* barOrigin;
      barOrigin = this->PositionCoordinate->GetComputedViewportValue(viewport);
      size[0] =
        this->Position2Coordinate->GetComputedViewportValue(viewport)[0] -
        barOrigin[0];
      size[1] =
        this->Position2Coordinate->GetComputedViewportValue(viewport)[1] -
        barOrigin[1];
  
      // Check if we have bounds on the maximum size
      size[0] = size[0] > this->MaximumWidthInPixels
        ? this->MaximumWidthInPixels : size[0];
      size[1] = size[1] > this->MaximumHeightInPixels
        ? this->MaximumHeightInPixels : size[1];
  
      if (this->LastSize[0] != size[0] ||
          this->LastSize[1] != size[1] ||
          this->LastOrigin[0] != barOrigin[0] ||
          this->LastOrigin[1] != barOrigin[1])
        {
        positionsHaveChanged = 1;
        }
      }
  
    // Check to see whether we have to rebuild everything
    if (positionsHaveChanged ||
        this->GetMTime() > this->BuildTime ||
        this->LookupTable->GetMTime() > this->BuildTime ||
        this->AnnotationTextProperty->GetMTime() > this->BuildTime ||
        this->LabelTextProperty->GetMTime() > this->BuildTime ||
        this->TitleTextProperty->GetMTime() > this->BuildTime ||
        this->BackgroundProperty->GetMTime() > this->BuildTime ||
        this->FrameProperty->GetMTime() > this->BuildTime)
  
      {
      this->RebuildLayout(viewport);
      }
    return 1;
  }
  
  //----------------------------------------------------------------------------
  int vtkScalarBarActor::RenderOpaqueGeometry(vtkViewport* viewport)
  {
    if (!this->RebuildLayoutIfNeeded(viewport))
      {
      return 0;
      }
  
    int renderedSomething = 0;
  
    // Everything is built, just have to render
    if (this->Title != NULL)
      {
      renderedSomething +=
        this->TitleActor->RenderOpaqueGeometry(viewport);
      }
    // Draw either the scalar bar (non-indexed mode) or
    // the annotated value boxes (indexed mode).
    if (!this->LookupTable->GetIndexedLookup())
      {
      if (this->DrawColorBar)
        {
        renderedSomething +=
          this->ScalarBarActor->RenderOpaqueGeometry(viewport);
        }
      vtkScalarBarActorInternal::ActorVector::iterator ait;
      for (
           ait = this->P->TextActors.begin();
           ait != this->P->TextActors.end();
           ++ait)
        {
        renderedSomething += (*ait)->RenderOpaqueGeometry(viewport);
        }
      }
    else
      {
      if (this->DrawColorBar)
        {
        renderedSomething +=
          this->P->AnnotationBoxesActor->RenderOpaqueGeometry(viewport);
        }
      }
  
    if (this->DrawNanAnnotation)
      {
      renderedSomething +=
        this->P->NanSwatchActor->RenderOpaqueGeometry(viewport);
      }
  
    if (this->DrawBelowRangeSwatch)
      {
      renderedSomething +=
        this->P->BelowRangeSwatchActor->RenderOpaqueGeometry(viewport);
      }
  
    if (this->DrawAboveRangeSwatch)
      {
      renderedSomething +=
        this->P->AboveRangeSwatchActor->RenderOpaqueGeometry(viewport);
      }
  
    // Draw the annotation leaders and labels
    if (this->DrawAnnotations)
      {
      if (!this->P->AnnotationLabels.empty())
        {
        renderedSomething +=
          this->P->AnnotationLeadersActor->RenderOpaqueGeometry(viewport);
        for (size_t i = 0; i < this->P->AnnotationLabels.size(); ++i)
          {
          renderedSomething +=
            this->P->AnnotationLabels[i]->RenderOpaqueGeometry(viewport);
          }
        }
      }
  
    renderedSomething = (renderedSomething > 0)?(1):(0);
  
    return renderedSomething;
  }
  
  //-----------------------------------------------------------------------------
  // Description:
  // Does this prop have some translucent polygonal geometry?
  int vtkScalarBarActor::HasTranslucentPolygonalGeometry()
  { // TODO: Handle case when IndexedLookup is true and any colors in the palette
    // have an alpha value, as the color swatches drawn by
    // this->P->AnnotationBoxesActor have 1 translucent triangle for each
    // alpha-swatch.
    return 0;
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::PrintSelf(ostream& os, vtkIndent indent)
  {
    this->Superclass::PrintSelf(os, indent);
  
    if (this->LookupTable)
      {
      os << indent << "Lookup Table:\n";
      this->LookupTable->PrintSelf(os, indent.GetNextIndent());
      }
    else
      {
      os << indent << "Lookup Table: (none)\n";
      }
  
    if (this->TitleTextProperty)
      {
      os << indent << "Title Text Property:\n";
      this->TitleTextProperty->PrintSelf(os, indent.GetNextIndent());
      }
    else
      {
      os << indent << "Title Text Property: (none)\n";
      }
  
    if (this->LabelTextProperty)
      {
      os << indent << "Label Text Property:\n";
      this->LabelTextProperty->PrintSelf(os, indent.GetNextIndent());
      }
    else
      {
      os << indent << "Label Text Property: (none)\n";
      }
  
    if (this->AnnotationTextProperty)
      {
      os << indent << "Annotation Text Property:\n";
      this->AnnotationTextProperty->PrintSelf(os, indent.GetNextIndent());
      }
    else
      {
      os << indent << "Annotation Text Property: (none)\n";
      }
  
    os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n";
    os << indent << "ComponentTitle: "
      << (this->ComponentTitle ? this->ComponentTitle : "(none)") << "\n";
    os << indent << "Maximum Number Of Colors: "
      << this->MaximumNumberOfColors << "\n";
    os << indent << "Number Of Labels: " << this->NumberOfLabels << "\n";
    os << indent << "Number Of Labels Built: " << this->NumberOfLabelsBuilt << "\n";
  
    os << indent << "Orientation: ";
    if (this->Orientation == VTK_ORIENT_HORIZONTAL)
      {
      os << "Horizontal\n";
      }
    else
      {
      os << "Vertical\n";
      }
  
    os << indent << "Label Format: " << this->LabelFormat << "\n";
    os << indent << "UseOpacity: " << this->UseOpacity << "\n";
    if (this->UseOpacity)
      {
      os << indent << "TextureGridWidth: " << this->TextureGridWidth << "\n";
      os << indent << "TextureActor:\n";
      this->TextureActor->PrintSelf(os, indent.GetNextIndent());
      }
    if (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
      {
      os << indent << "TextPosition: PrecedeScalarBar\n";
      }
    else
      {
      os << indent << "TextPosition: SucceedScalarBar\n";
      }
  
    os << indent << "MaximumWidthInPixels: "
      << this->MaximumWidthInPixels << endl;
    os << indent << "MaximumHeightInPixels: "
      << this->MaximumHeightInPixels << endl;
  
    os << indent << "DrawAnnotations: "
      << this->DrawAnnotations << endl;
    os << indent << "DrawNanAnnotation: "
      << this->DrawNanAnnotation << endl;
    os << indent << "NanAnnotation: "
      << (this->NanAnnotation ? this->NanAnnotation : "(none)") << endl;
    os << indent << "AnnotationLeaderPadding: "
      << this->AnnotationLeaderPadding << endl;
    os << indent << "AnnotationTextScaling: "
      << this->AnnotationTextScaling << endl;
    os << indent << "VerticalTitleSeparation: "
      << VerticalTitleSeparation << endl;
  
    os << indent << "DrawBelowRangeSwatch: "
      << this->DrawBelowRangeSwatch << endl;
    os << indent << "BelowRangeAnnotation: "
      << (this->BelowRangeAnnotation ? this->BelowRangeAnnotation : "(none)") << endl;
  
    os << indent << "DrawAboveRangeSwatch: "
      << this->DrawAboveRangeSwatch << endl;
    os << indent << "AboveRangeAnnotation: "
      << (this->AboveRangeAnnotation ? this->AboveRangeAnnotation : "(none)") << endl;
  
    os << indent << "DrawBackground: " << this->DrawBackground << "\n";
    os << indent << "Background Property:\n";
    this->BackgroundProperty->PrintSelf(os, indent.GetNextIndent());
    os << indent << "DrawFrame: " << this->DrawFrame << "\n";
    os << indent << "Frame Property:\n";
    this->FrameProperty->PrintSelf(os, indent.GetNextIndent());
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::ShallowCopy(vtkProp* prop)
  {
    vtkScalarBarActor* a = vtkScalarBarActor::SafeDownCast(prop);
    if (a != NULL)
      {
      this->SetPosition2(a->GetPosition2());
      this->SetLookupTable(a->GetLookupTable());
      this->SetMaximumNumberOfColors(a->GetMaximumNumberOfColors());
      this->SetOrientation(a->GetOrientation());
      this->SetAnnotationTextProperty(a->GetAnnotationTextProperty());
      this->SetLabelTextProperty(a->GetLabelTextProperty());
      this->SetTitleTextProperty(a->GetTitleTextProperty());
      this->SetLabelFormat(a->GetLabelFormat());
      this->SetTitle(a->GetTitle());
      this->GetPositionCoordinate()->SetCoordinateSystem(
        a->GetPositionCoordinate()->GetCoordinateSystem());
      this->GetPositionCoordinate()->SetValue(
        a->GetPositionCoordinate()->GetValue());
      this->GetPosition2Coordinate()->SetCoordinateSystem(
        a->GetPosition2Coordinate()->GetCoordinateSystem());
      this->GetPosition2Coordinate()->SetValue(
        a->GetPosition2Coordinate()->GetValue());
      this->SetDrawBackground(a->GetDrawBackground());
      this->SetBackgroundProperty(a->GetBackgroundProperty());
      this->SetDrawFrame(a->GetDrawFrame());
      this->SetFrameProperty(a->GetFrameProperty());
      }
  
    // Now do superclass
    this->vtkActor2D::ShallowCopy(prop);
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::RebuildLayout(vtkViewport* viewport)
  {
    vtkDebugMacro(<< "Rebuilding subobjects");
  
    this->P->Viewport = viewport;
    this->FreeLayoutStorage();
  
    // Permute indices used to measure width and height
    // so that thickness and length according to the orientation
    // of the scalar bar instead.
    if (this->Orientation == VTK_ORIENT_VERTICAL)
      {
      this->P->TL[0] = 0;
      this->P->TL[1] = 1;
      }
    else
      {
      this->P->TL[0] = 1;
      this->P->TL[1] = 0;
      }
    this->P->NumNotes = this->LookupTable->GetNumberOfAnnotatedValues();
  
    // Warning: The order of these calls is extremely important
    // as each updates members of this->P used by later methods!
    this->ComputeFrame();
    this->ComputeScalarBarThickness();
    this->ComputeSwatchPad();
    this->LayoutNanSwatch();
    this->LayoutBelowRangeSwatch();
    this->LayoutAboveRangeSwatch();
  
    this->PrepareTitleText();
    this->LayoutTitle();
    this->ComputeScalarBarLength();
  
    this->LayoutAboveRangeSwatchPosn();
  
    this->LayoutTicks();
  
    this->LayoutAnnotations();
  
    if (this->UnconstrainedFontSize)
      {
      this->LayoutForUnconstrainedFont();
      }
  
    // Now generate/configure the VTK datasets and actors that
    // illustrate the scalar bar when rendered using the
    // layout computed above.
    this->ConfigureAnnotations();
    this->ConfigureFrame();
    this->ConfigureScalarBar();
    this->ConfigureTitle();
    this->ConfigureTicks();
    this->ConfigureNanSwatch();
    this->ConfigureAboveBelowRangeSwatch(false);
    this->ConfigureAboveBelowRangeSwatch(true);
  #ifdef VTK_DBG_LAYOUT
    this->DrawBoxes();
  #endif // VTK_DBG_LAYOUT
    this->BuildTime.Modified();
  }
  
  namespace
  {
  void AddBox(vtkPoints* pts, vtkCellArray* lines, vtkScalarBarBox& box, int tl[2])
    {
    vtkIdType pid[5];
    pid[0] = pts->InsertNextPoint(box.Posn[0], box.Posn[1], 0.);
    pid[1] = pts->InsertNextPoint(box.Posn[0] + box.Size[tl[0]], box.Posn[1], 0.);
    pid[2] = pts->InsertNextPoint(box.Posn[0] + box.Size[tl[0]], box.Posn[1] +
      box.Size[tl[1]], 0.);
    pid[3] = pts->InsertNextPoint(box.Posn[0], box.Posn[1] + box.Size[tl[1]], 0.);
  
    pid[4] = pid[0];
    for (int i = 0; i < 4; ++i)
      {
      lines->InsertNextCell(2, pid + i);
      }
    }
  }
  
  void vtkScalarBarActor::DrawBoxes()
  {
    vtkPoints* pts = this->Frame->GetPoints();
    vtkCellArray* lines = this->Frame->GetLines();
  
    AddBox(pts, lines, this->P->ScalarBarBox, this->P->TL);
    AddBox(pts, lines, this->P->NanBox, this->P->TL);
    AddBox(pts, lines, this->P->TitleBox, this->P->TL);
    if (this->NumberOfLabels > 0)
      {
      AddBox(pts, lines, this->P->TickBox, this->P->TL);
      }
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::ComputeFrame()
  {
    // get the viewport size in display coordinates
    int* p0;
    int* p1;
    int size[2];
    p0 = this->PositionCoordinate->GetComputedViewportValue(this->P->Viewport);
    p1 = this->Position2Coordinate->GetComputedViewportValue(this->P->Viewport);
    for (int i = 0; i < 2; ++i)
      {
      //this->P->Frame.Posn[i] = p0[i];
      this->P->Frame.Posn[i] = 0; // Translate the frame's coordinate system to p0
      size[i] = p1[i] - p0[i];
      }
  
    // Check if we have bounds on the maximum size
    size[0] = size[0] > this->MaximumWidthInPixels
      ? this->MaximumWidthInPixels : size[0];
    size[1] = size[1] > this->MaximumHeightInPixels
      ? this->MaximumHeightInPixels : size[1];
  
    for (int i = 0; i < 2; ++i)
      {
      this->P->Frame.Size[i] = size[this->P->TL[i]];
      }
  
    this->LastOrigin[0] = p0[0];
    this->LastOrigin[1] = p0[1];
    this->LastSize[0] = size[0];
    this->LastSize[1] = size[1];
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::ComputeScalarBarThickness()
  {
    // We do not set Size[1] (length), since the title bounds may encroach
    // on it in the vertical orientation.
    this->P->ScalarBarBox.Size[0] =
      static_cast<int>(ceil(this->P->Frame.Size[0] * this->BarRatio));
  
    // The lower-left corner of the scalar bar may be estimated here
    // as identical to the Frame position in one or both coordinates,
    // depending on whether tick marks should precede the scalar bar or
    // not and on the orientation.
    //
    // It will be altered later in this->LayoutTicks to account
    // for the half-height/width of tick labels.
    this->P->ScalarBarBox.Posn = this->P->Frame.Posn;
    if (this->TextPosition == PrecedeScalarBar)
      {
      this->P->ScalarBarBox.Posn[this->P->TL[0]] +=
        this->P->Frame.Size[0] - this->P->ScalarBarBox.Size[0];
      }
  
    // Now knock the thickness down and nudge the bar so the bar doesn't hug the frame.
    double nudge = this->P->ScalarBarBox.Size[0] / 8.;
    if (nudge > this->TextPad)
      {
      nudge = this->TextPad;
      }
    this->P->ScalarBarBox.Size[0] =
      static_cast<int>(this->P->ScalarBarBox.Size[0] - nudge);
    this->P->ScalarBarBox.Posn[this->P->TL[0]] =
      static_cast<int>(this->P->ScalarBarBox.Posn[this->P->TL[0]] +
        (nudge * (this->TextPosition == PrecedeScalarBar ? -1 : 1)));
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::ComputeSwatchPad()
  {
    if (this->P->NumNotes)
      {
      this->P->SwatchPad = this->P->Frame.Size[1] / this->P->NumNotes > 16. ?
        4. : (this->P->Frame.Size[1] / this->P->NumNotes / 4.);
      }
    else
      {
      this->P->SwatchPad = 4.;
      }
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::LayoutNanSwatch()
  {
    // We don't have ScalarBarBox.Size[1] set yet; use the frame width instead.
    this->P->NanSwatchSize = static_cast<double>(
      this->P->ScalarBarBox.Size[0] > this->P->Frame.Size[1] / 4 ?
      this->P->Frame.Size[1] / 4 : this->P->ScalarBarBox.Size[0]);
    if (this->P->NanSwatchSize < 4 && this->P->Frame.Size[1] > 16)
      {
      this->P->NanSwatchSize = 4;
      }
    if (!this->DrawNanAnnotation)
      {
      this->P->NanSwatchSize = 0;
      }
  
    if (this->Orientation == VTK_ORIENT_VERTICAL)
      {
      this->P->NanBox.Posn[0] = this->P->ScalarBarBox.Posn[0];
      this->P->NanBox.Posn[1] = this->P->Frame.Posn[1] + this->TextPad;
      this->P->ScalarBarBox.Posn[1] = static_cast<int>(this->P->ScalarBarBox.Posn[1] +
        (this->P->NanSwatchSize + this->P->SwatchPad));
      }
    else // HORIZONTAL
      {
      this->P->NanBox.Posn = this->P->ScalarBarBox.Posn;
      this->P->NanBox.Posn[this->P->TL[1]] =
        static_cast<int>(this->P->NanBox.Posn[this->P->TL[1]] +
          (this->P->Frame.Size[1] - this->P->NanSwatchSize));
      }
    this->P->NanBox.Size[0] = this->P->ScalarBarBox.Size[0];
    this->P->NanBox.Size[1] = static_cast<int>(this->P->NanSwatchSize);
    if (this->P->NanBox.Size[1] > 2 * this->TextPad)
      {
      this->P->NanBox.Size[1] -= this->TextPad;
      }
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::LayoutBelowRangeSwatch()
  {
    // We don't have ScalarBarBox.Size[1] set yet; use the frame width instead.
    this->P->BelowRangeSwatchSize = static_cast<double>(
      this->P->ScalarBarBox.Size[0] > this->P->Frame.Size[1] / 4 ?
      this->P->Frame.Size[1] / 4 : this->P->ScalarBarBox.Size[0]);
    if (this->P->BelowRangeSwatchSize < 4 && this->P->Frame.Size[1] > 16)
      {
      this->P->BelowRangeSwatchSize = 4;
      }
    if (!this->DrawBelowRangeSwatch)
      {
      this->P->BelowRangeSwatchSize = 0;
      }
  
    if (this->Orientation == VTK_ORIENT_VERTICAL)
      {
      this->P->BelowRangeSwatchBox.Posn[0] = this->P->ScalarBarBox.Posn[0];
      this->P->BelowRangeSwatchBox.Posn[1] = this->P->Frame.Posn[1] + this->TextPad;
  
      // move away because of nan annotation
      if (this->DrawNanAnnotation)
        {
        this->P->BelowRangeSwatchBox.Posn[1] =
          static_cast<int>(this->P->BelowRangeSwatchBox.Posn[1] +
            (this->P->NanBox.Size[1] + this->P->SwatchPad));
        }
      this->P->ScalarBarBox.Posn[1] = static_cast<int>(this->P->ScalarBarBox.Posn[1] +
        this->P->BelowRangeSwatchSize);
      }
    else // HORIZONTAL
      {
      this->P->BelowRangeSwatchBox.Posn = this->P->ScalarBarBox.Posn;
      }
  
    this->P->BelowRangeSwatchBox.Size[0] = this->P->ScalarBarBox.Size[0];
    this->P->BelowRangeSwatchBox.Size[1] =
      static_cast<int>(this->P->BelowRangeSwatchSize);
    if (this->P->BelowRangeSwatchBox.Size[1] > 2 * this->TextPad)
      {
      this->P->BelowRangeSwatchBox.Size[1] -= this->TextPad;
      }
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::LayoutAboveRangeSwatch()
  {
    // We don't have ScalarBarBox.Size[1] set yet; use the frame width instead.
    this->P->AboveRangeSwatchSize = static_cast<double>(
      this->P->ScalarBarBox.Size[0] > this->P->Frame.Size[1] / 4 ?
      this->P->Frame.Size[1] / 4 : this->P->ScalarBarBox.Size[0]);
    if (this->P->AboveRangeSwatchSize < 4 && this->P->Frame.Size[1] > 16)
      {
      this->P->AboveRangeSwatchSize = 4;
      }
    if (!this->DrawAboveRangeSwatch)
      {
      this->P->AboveRangeSwatchSize = 0;
      }
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::LayoutAboveRangeSwatchPosn()
  {
    if (this->Orientation == VTK_ORIENT_VERTICAL)
      {
      this->P->AboveRangeSwatchBox.Posn[0] = this->P->ScalarBarBox.Posn[0];
      this->P->AboveRangeSwatchBox.Posn[1] =
        this->P->Frame.Posn[1] + this->TextPad + this->P->ScalarBarBox.Size[1] +
        this->P->SwatchPad;
  
      if (this->DrawNanAnnotation)
        {
        this->P->AboveRangeSwatchBox.Posn[1] =
          static_cast<int>(this->P->AboveRangeSwatchBox.Posn[1] +
                           this->P->SwatchPad +
                           this->P->NanBox.Size[1]);
        }
  
      if (this->DrawBelowRangeSwatch)
        {
        this->P->AboveRangeSwatchBox.Posn[1] =
          static_cast<int>(this->P->AboveRangeSwatchBox.Posn[1] +
                           this->P->SwatchPad +
                           this->P->BelowRangeSwatchBox.Size[1]);
        }
      }
    else // HORIZONTAL
      {
      this->P->AboveRangeSwatchBox.Posn = this->P->ScalarBarBox.Posn;
      this->P->AboveRangeSwatchBox.Posn[this->P->TL[1]] =
        static_cast<int>(this->P->AboveRangeSwatchBox.Posn[this->P->TL[1]] +
          (this->P->Frame.Size[1] - this->P->AboveRangeSwatchSize));
  
      if (this->DrawNanAnnotation)
        {
        this->P->AboveRangeSwatchBox.Posn[this->P->TL[1]] =
          static_cast<int>(this->P->AboveRangeSwatchBox.Posn[this->P->TL[1]] -
            (this->P->NanBox.Size[this->P->TL[1]] + this->P->SwatchPad));
        }
      }
    this->P->AboveRangeSwatchBox.Size[0] = this->P->ScalarBarBox.Size[0];
    this->P->AboveRangeSwatchBox.Size[1] =
      static_cast<int>(this->P->AboveRangeSwatchSize);
    if (this->P->AboveRangeSwatchBox.Size[1] > 2 * this->TextPad)
      {
      this->P->AboveRangeSwatchBox.Size[1] -= this->TextPad;
      }
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::PrepareTitleText()
  {
    // Update actor with the latest title/subtitle
    if (this->ComponentTitle && strlen(this->ComponentTitle) > 0)
      {
      //need to account for a space between title & component and null term
      char* combinedTitle =
        new char[strlen(this->Title) + strlen(this->ComponentTitle) + 2];
      strcpy(combinedTitle, this->Title);
      strcat(combinedTitle, " ");
      strcat(combinedTitle, this->ComponentTitle);
      this->TitleActor->SetInput(combinedTitle);
      delete [] combinedTitle;
      }
    else
      {
      this->TitleActor->SetInput(this->Title);
      }
  
    if (this->TitleTextProperty->GetMTime() > this->BuildTime)
      {
      // Shallow copy here so that the size of the title prop is not affected
      // by the automatic adjustment of its text mapper's size (i.e. its
      // mapper's text property is identical except for the font size
      // which will be modified later). This allows text actors to
      // share the same text property, and in that case specifically allows
      // the title and label text prop to be the same.
      this->TitleActor->GetTextProperty()->ShallowCopy(this->TitleTextProperty);
      this->TitleActor->GetTextProperty()->SetJustificationToCentered();
      this->TitleActor->GetTextProperty()->SetVerticalJustification(
        this->TextPosition == PrecedeScalarBar ? VTK_TEXT_BOTTOM : VTK_TEXT_TOP);
      }
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::LayoutTitle()
  {
    if (this->Title == NULL || !strlen(this->Title))
      {
      this->P->TitleBox.Posn = vtkTuple<int, 2>(0.);
      this->P->TitleBox.Size = vtkTuple<int, 2>(0.);
      return;
      }
  
    int targetWidth, targetHeight;
    // Title spans entire width of frame at top, regardless of orientation.
    targetWidth = static_cast<int>(this->P->Frame.Size[this->P->TL[0]]) - 2 *
      this->TextPad;
    // Height is either: at most half the frame height or
    // a fixed portion of the frame remaining after subtracting the
    // scalar bar's thickness.
    //
    // When laid out horizontally, ticks share vertical space with title.
    // We want the title to be larger (18pt vs 14pt).
    targetHeight = static_cast<int>((
      this->Orientation == VTK_ORIENT_VERTICAL ||
      this->LookupTable->GetIndexedLookup()) ?
        ceil(this->P->Frame.Size[this->P->TL[1]] / 2. - this->TextPad) :
        (this->P->Frame.Size[0] - this->P->ScalarBarBox.Size[0] -
         (this->TextPosition == SucceedScalarBar ?
           this->P->ScalarBarBox.Posn[this->P->TL[0]] : 0) - this->TextPad) *
        this->TitleRatio);
  
    if (this->UnconstrainedFontSize)
      {
      this->TitleActor->GetTextProperty()->SetFontSize(
        this->TitleTextProperty->GetFontSize());
      }
    else
      {
      this->TitleActor->SetConstrainedFontSize(
        this->P->Viewport, targetWidth, targetHeight);
      }
  
    // Now fetch the actual size from the actor and use it to
    // update the box size and position.
    double titleSize[2] = {0, 0};
    this->TitleActor->GetSize(this->P->Viewport, titleSize);
    this->TitleActor->GetTextProperty()->SetVerticalJustificationToTop();
    for (int i = 0; i < 2; ++i)
      {
      this->P->TitleBox.Size[this->P->TL[i]] =
        static_cast<int>(ceil(titleSize[i]));
      }
  
    this->P->TitleBox.Posn[0] =
      this->P->Frame.Posn[0] +
      (this->P->Frame.Size[this->P->TL[0]] - titleSize[0]) / 2;
    this->P->TitleBox.Posn[1] =
      static_cast<int>(this->P->Frame.Posn[1] + this->P->Frame.Size[this->P->TL[1]]);
    if (
        this->Orientation == VTK_ORIENT_VERTICAL ||
        this->TextPosition == vtkScalarBarActor::SucceedScalarBar)
      {
      this->P->TitleBox.Posn[1] -= this->P->TitleBox.Size[this->P->TL[1]] +
        this->TextPad + static_cast<int>(this->FrameProperty->GetLineWidth());
      }
    else
      {
      this->P->TitleBox.Posn[1] = this->P->Frame.Posn[1] + this->TextPad -
        static_cast<int>(this->FrameProperty->GetLineWidth());
      }
  }
  
  //-----------------------------------------------------------------------------
  void vtkScalarBarActor::ComputeScalarBarLength()
  {
    this->P->ScalarBarBox.Size[1] =
      this->Orientation == VTK_ORIENT_VERTICAL ?
      this->P->Frame.Size[1] - this->P->TitleBox.Size[1] -
      this->VerticalTitleSeparation :
      this->P->Frame.Size[1];
  
    // The scalar bar does not include the Nan Swatch, the Below Range Swatch and
    // the Above Range Swatch.
    this->P->ScalarBarBox.Size[1] = static_cast<int>(this->P->ScalarBarBox.Size[1] -
      (this->P->NanSwatchSize + this->P->SwatchPad));
  
    // Correct Swatch behevior while keeping compat with images from tests
    if (this->P->BelowRangeSwatchSize > 0)
      {
      this->P->ScalarBarBox.Size[1] -=
        this->P->BelowRangeSwatchSize + this->P->SwatchPad;
      }
  
    if (this->P->AboveRangeSwatchSize > 0)
      {
      this->P->ScalarBarBox.Size[1] -= this->P->AboveRangeSwatchSize;
      if (this->P->NanSwatchSize > 0)
        {
        this->P->ScalarBarBox.Size[1] -= this->P->SwatchPad;
        }
      }
  }
  
  //-----------------------------------------------------------------------------
  void vtkScalarBarActor::LayoutTicks()
  {
    if (this->LookupTable->GetIndexedLookup())
      { // no tick marks in indexed lookup mode.
      this->NumberOfLabelsBuilt = 0;
      return;
      }
  
    // find the best size for the ticks
    const double* range = this->LookupTable->GetRange();
    char string[512];
    double val;
    int i;
  
    // TODO: this should be optimized, maybe by keeping a list of
    // allocated mappers, in order to avoid creation/destruction of
    // their underlying text properties (i.e. each time a mapper is
    // created, text properties are created and shallow-assigned a font size
    // which value might be "far" from the target font size).
    this->P->TextActors.resize(this->NumberOfLabels);
  
    // Does this map have its scale set to log?
    int isLogTable = this->LookupTable->UsingLogScale();
  
    for (i = 0; i < this->NumberOfLabels; i++)
      {
      this->P->TextActors[i].TakeReference(vtkTextActor::New());
  
      if (isLogTable)
        {
        double lval;
        if (this->NumberOfLabels > 1)
          {
          lval = log10(range[0]) +
            static_cast<double>(i) / (this->NumberOfLabels - 1) *
            (log10(range[1]) - log10(range[0]));
          }
        else
          {
          lval = log10(range[0]) + 0.5 * (log10(range[1]) - log10(range[0]));
          }
        val = pow(10.0, lval);
        }
      else
        {
        if (this->NumberOfLabels > 1)
          {
          val = range[0] +
            static_cast<double>(i) / (this->NumberOfLabels - 1)
            * (range[1] - range[0]);
          }
        else
          {
          val = range[0] + 0.5 * (range[1] - range[0]);
          }
        }
  
      snprintf(string, 511, this->LabelFormat, val);
      this->P->TextActors[i]->SetInput(string);
  
      // Shallow copy here so that the size of the label prop is not affected
      // by the automatic adjustment of its text mapper's size (i.e. its
      // mapper's text property is identical except for the font size
      // which will be modified later). This allows text actors to
      // share the same text property, and in that case specifically allows
      // the title and label text prop to be the same.
      this->P->TextActors[i]->GetTextProperty()->ShallowCopy(
        this->LabelTextProperty);
  
      this->P->TextActors[i]->SetProperty(this->GetProperty());
      this->P->TextActors[i]->GetPositionCoordinate()->
        SetReferenceCoordinate(this->PositionCoordinate);
      }
  
    if (this->NumberOfLabels)
      {
      int labelSize[2];
      labelSize[0] = labelSize[1] = 0;
      int targetWidth, targetHeight;
  
      this->P->TickBox.Posn = this->P->ScalarBarBox.Posn;
      if (this->Orientation == VTK_ORIENT_VERTICAL)
        { // NB. Size[0] = width, Size[1] = height
        // Ticks share the width with the scalar bar
        this->P->TickBox.Size[0] =
          this->P->Frame.Size[0] - this->P->ScalarBarBox.Size[0] -
          this->TextPad * 3;
        // Tick height could be adjusted if title text is
        // lowered by box constraints, but we won't bother:
        this->P->TickBox.Size[1] = this->P->Frame.Size[1] -
          this->P->TitleBox.Size[1] - 3 * this->TextPad -
          this->VerticalTitleSeparation;
        // Tick box height also reduced by NaN swatch size, if present:
        if (this->DrawNanAnnotation)
          {
          this->P->TickBox.Size[1] = static_cast<int>(this->P->TickBox.Size[1] -
            (this->P->NanBox.Size[1] + this->P->SwatchPad));
          }
        if (this->DrawBelowRangeSwatch)
          {
          this->P->TickBox.Size[1] = static_cast<int>(this->P->TickBox.Size[1] -
            (this->P->BelowRangeSwatchBox.Size[1] + this->P->SwatchPad));
          }
        if (this->DrawAboveRangeSwatch)
          {
          this->P->TickBox.Size[1] = static_cast<int>(this->P->TickBox.Size[1] -
            (this->P->AboveRangeSwatchBox.Size[1] + this->P->SwatchPad));
          }
  
        if (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
          {
          this->P->TickBox.Posn[0] = this->TextPad;
          }
        else
          {
          this->P->TickBox.Posn[0] += this->P->ScalarBarBox.Size[0] + 2 *
            this->TextPad;
          }
  
        targetWidth = this->P->TickBox.Size[0];
        targetHeight = static_cast<int>((this->P->TickBox.Size[1] -
          this->TextPad * (this->NumberOfLabels - 1)) /
                                        this->NumberOfLabels);
        }
      else
        { // NB. Size[1] = width, Size[0] = height
        // Ticks span the entire width of the frame
        this->P->TickBox.Size[1] = this->P->ScalarBarBox.Size[1];
        // Ticks share vertical space with title and scalar bar.
        this->P->TickBox.Size[0] =
          this->P->Frame.Size[0] - this->P->ScalarBarBox.Size[0] -
          4 * this->TextPad - this->P->TitleBox.Size[0];
  
        if (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
          {
          this->P->TickBox.Posn[1] =
            this->P->TitleBox.Size[0] + 2 * this->TextPad + this->P->TitleBox.Posn[1];
          }
        else
          {
          this->P->TickBox.Posn[1] += this->P->ScalarBarBox.Size[0];
          }
        targetWidth = static_cast<int>((this->P->TickBox.Size[1] -
          this->TextPad * (this->NumberOfLabels - 1)) /
            this->NumberOfLabels);
        targetHeight = this->P->TickBox.Size[0];
        }
  
      if (!this->UnconstrainedFontSize)
        {
        vtkTextActor::SetMultipleConstrainedFontSize(
          this->P->Viewport, targetWidth, targetHeight,
          this->P->TextActors.PointerArray(), this->NumberOfLabels,
          labelSize);
        }
  
      // Now adjust scalar bar size by the half-size of the first and last ticks
      this->P->ScalarBarBox.Posn[this->P->TL[1]]
        += labelSize[this->P->TL[1]] / 2.;
      this->P->ScalarBarBox.Size[1] -= labelSize[this->P->TL[1]];
      this->P->TickBox.Posn[this->P->TL[1]] =
        static_cast<int>(this->P->TickBox.Posn[this->P->TL[1]] +
                         (labelSize[this->P->TL[1]] / 2.));
      this->P->TickBox.Size[1] -= labelSize[this->P->TL[1]];
  
      if (this->Orientation == VTK_ORIENT_HORIZONTAL)
        {
        this->P->ScalarBarBox.Posn[0] += this->P->BelowRangeSwatchSize;
  
        this->P->TickBox.Posn[0] += this->P->BelowRangeSwatchSize;
  
        this->P->TickBox.Posn[1] += this->TextPad *
          (this->TextPosition == PrecedeScalarBar ? -1 : 1);
        this->P->TickBox.Size[1] -= this->TextPad;
        }
      }
    this->NumberOfLabelsBuilt = this->NumberOfLabels;
  }
  
  //-----------------------------------------------------------------------------
  void vtkScalarBarActor::LayoutForUnconstrainedFont()
  {
    if (this->UnconstrainedFontSize)
      {
      // recompute tickbox layout max sizes
      int labelWidth = 0;
      int labelHeight = 0;
      double fontSize[2] = {0, 0};
      for (size_t i = 0; i < this->P->TextActors.size(); ++i)
        {
        this->P->TextActors.at(i)->GetSize(this->P->Viewport, fontSize);
        if (fontSize[0] > labelWidth)
          {
          labelWidth = fontSize[0];
          }
  
        if (fontSize[1] > labelHeight)
          {
          labelHeight = fontSize[1];
          }
        }
  
      if (this->Orientation == VTK_ORIENT_VERTICAL)
        {
        this->P->TitleBox.Posn[1] += labelHeight * 0.75;
        this->P->TickBox.Size[0] = labelWidth;
        if (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
          {
          this->P->TickBox.Posn[0] =
            -labelWidth + this->P->Frame.Size[0] - this->P->ScalarBarBox.Size[0] -
            (labelWidth * 0.05);
          }
        }
      else
        {
        if (this->TextPosition == vtkScalarBarActor::PrecedeScalarBar)
          {
          this->P->TitleBox.Posn[1] =
            this->P->Frame.Posn[1] + this->P->ScalarBarBox.Posn[1] -
            this->P->TitleBox.Size[this->P->TL[1]] - labelHeight;
          }
        else
          {
          this->P->TitleBox.Posn[1] =
            this->P->Frame.Posn[1] +
            this->P->ScalarBarBox.Size[this->P->TL[1]] + labelHeight;
          }
        }
      }
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::LayoutAnnotations()
  {
    if (this->DrawAnnotations)
      {
      const double* range = this->LookupTable->GetRange();
  
      this->MapAnnotationLabels(
        this->LookupTable, this->P->ScalarBarBox.Posn[this->P->TL[1]],
        this->P->ScalarBarBox.Size[1], range);
      }
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::ConfigureFrame()
  {
    // set frame structure
    vtkPoints* frPts = vtkPoints::New();
    frPts->SetNumberOfPoints(5);
    vtkCellArray* frLines = vtkCellArray::New();
    frLines->Allocate(frLines->EstimateSize(1, 5));
  
    this->FrameActor->SetProperty(this->FrameProperty);
    this->Frame->Initialize();
    this->Frame->SetPoints(frPts);
    this->Frame->SetLines(frLines);
    frPts->Delete();
    frLines->Delete();
  
    // set background structure
    vtkPoints* bgPts = vtkPoints::New();
    bgPts->SetNumberOfPoints(4);
    vtkCellArray* bgPolys = vtkCellArray::New();
    bgPolys->Allocate(bgPolys->EstimateSize(1, 4));
  
    this->BackgroundActor->SetProperty(this->BackgroundProperty);
    this->Background->Initialize();
    this->Background->SetPoints(bgPts);
    this->Background->SetPolys(bgPolys);
    bgPts->Delete();
    bgPolys->Delete();
  
    double x[3];
    x[2] = 0.;
  
    // generate background and frame points and cell
    x[0] = 0;
    x[1] = 0;
    bgPts->SetPoint(0, x);
    frPts->SetPoint(0, x);
    frPts->SetPoint(4, x);
  
    x[0] = 0;
    x[1] = this->P->Frame.Size[this->P->TL[1]] - 0.5;
    bgPts->SetPoint(1, x);
    frPts->SetPoint(1, x);
  
    x[0] = this->P->Frame.Size[this->P->TL[0]] - 0.5;
    x[1] = this->P->Frame.Size[this->P->TL[1]] - 0.5;
    bgPts->SetPoint(2, x);
    frPts->SetPoint(2, x);
  
    x[0] = this->P->Frame.Size[this->P->TL[0]] - 0.5;
    x[1] = 0;
    bgPts->SetPoint(3, x);
    frPts->SetPoint(3, x);
  
    vtkIdType bgIds[5] = {0, 1, 2, 3, 4};
    bgPolys->InsertNextCell(4, bgIds);
    frLines->InsertNextCell(5, bgIds);
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::ConfigureScalarBar()
  {
    vtkScalarsToColors* lut = this->LookupTable;
    const double* range = lut->GetRange();
    this->P->NumColors = lut->GetIndexedLookup() ?
      lut->GetNumberOfAnnotatedValues() : this->MaximumNumberOfColors;
    this->P->NumSwatches = this->P->NumColors + (this->DrawNanAnnotation ? 1 : 0);
    int numPts = 2 * (this->P->NumColors + 1) + (this->DrawNanAnnotation ? 4 : 0);
  
    this->P->NumSwatches = this->P->NumColors + (this->DrawBelowRangeSwatch ? 1 : 0);
    numPts += (this->DrawBelowRangeSwatch ? 4 : 0);
  
    this->P->SwatchPts = vtkPoints::New();
    this->P->SwatchPts->SetNumberOfPoints(numPts);
    this->P->Polys = vtkCellArray::New();
    this->P->Polys->Allocate(
      this->P->Polys->EstimateSize(this->P->NumSwatches, 4));
    this->P->SwatchColors = vtkUnsignedCharArray::New();
  
    unsigned int nComponents = ((this->UseOpacity) ? 4 : 3);
    this->P->SwatchColors->SetNumberOfComponents(nComponents);
    this->P->SwatchColors->SetNumberOfTuples(this->P->NumSwatches);
  
    this->ScalarBarActor->SetProperty(this->GetProperty());
    this->ScalarBar->Initialize();
    this->ScalarBar->SetPoints(this->P->SwatchPts);
    this->ScalarBar->SetPolys(this->P->Polys);
    this->ScalarBar->GetCellData()->SetScalars(this->P->SwatchColors);
    this->P->SwatchPts->Delete();
    this->P->Polys->Delete();
    this->P->SwatchColors->Delete();
  
    double delta =
      static_cast<double>(this->P->ScalarBarBox.Size[1]) / this->P->NumColors;
    double x[3];
    x[2] = 0.;
    for (int i = 0; i < numPts / 2 - (this->DrawNanAnnotation ? 2 : 0) -
         (this->DrawBelowRangeSwatch ? 2 : 0) ; ++i)
      {
      x[this->P->TL[0]] = this->P->ScalarBarBox.Posn[this->P->TL[0]];
      x[this->P->TL[1]] = this->P->ScalarBarBox.Posn[this->P->TL[1]] + i * delta;
      this->P->SwatchPts->SetPoint(2 * i, x);
  
      x[this->P->TL[0]] = this->P->ScalarBarBox.Posn[this->P->TL[0]] +
        this->P->ScalarBarBox.Size[0];
      this->P->SwatchPts->SetPoint(2 * i + 1, x);
      }
  
    //polygons & cell colors
    unsigned char* rgb;
    double rgba[4];
    vtkIdType ptIds[4];
    for (int i = 0; i < this->P->NumColors; ++i)
      {
      ptIds[0] = 2 * i;
      ptIds[1] = ptIds[0] + 1;
      ptIds[2] = ptIds[1] + 2;
      ptIds[3] = ptIds[0] + 2;
      this->P->Polys->InsertNextCell(4, ptIds);
      double rgbval;
      if (this->LookupTable->UsingLogScale())
        {
        rgbval = log10(range[0]) +
          i * (log10(range[1]) - log10(range[0])) / this->P->NumColors;
        rgbval = pow(10.0, rgbval);
        }
      else
        {
        rgbval = range[0] + (range[1] - range[0]) *
          (i / static_cast<double>(this->P->NumColors));
        }
      lut->GetColor(rgbval, rgba);
      rgba[3] = lut->GetOpacity(rgbval);
      //write into array directly
      rgb = this->P->SwatchColors->GetPointer(nComponents * i);
      rgb[0] = static_cast<unsigned char>(rgba[0] * 255.);
      rgb[1] = static_cast<unsigned char>(rgba[1] * 255.);
      rgb[2] = static_cast<unsigned char>(rgba[2] * 255.);
      if (this->P->SwatchColors->GetNumberOfComponents() > 3)
        {
        rgb[3] = static_cast<unsigned char>(this->UseOpacity ? rgba[3] * 255. : 255.);
        }
      }
  
    // Set up a texture actor as an alternative to the 1-quad-per-color
    // scalar bar polydata.
    vtkPoints* texturePoints = vtkPoints::New();
    texturePoints->SetNumberOfPoints(4);
    this->TexturePolyData->SetPoints(texturePoints);
    texturePoints->SetPoint(0, 0.0, 0.0, 0.0);
  
    double p1[2], p2[2];
    p1[0] = this->P->ScalarBarBox.Posn[0];
    p1[1] = this->P->ScalarBarBox.Posn[1];
    p2[0] = p1[0] + this->P->ScalarBarBox.Size[this->P->TL[0]];
    p2[1] = p1[1] + this->P->ScalarBarBox.Size[this->P->TL[1]];
  
    texturePoints->SetPoint(0, p1[0], p1[1], 0.0);
    texturePoints->SetPoint(1, p2[0], p1[1], 0.0);
    texturePoints->SetPoint(2, p2[0], p2[1], 0.0);
    texturePoints->SetPoint(3, p1[0], p2[1], 0.0);
    texturePoints->Delete();
  
    double barWidth = this->P->ScalarBarBox.Size[this->P->TL[0]];
    double barHeight = this->P->ScalarBarBox.Size[this->P->TL[1]];
    vtkDataArray* tc = this->TexturePolyData->GetPointData()->GetTCoords();
    tc->SetTuple2(1, barWidth / this->TextureGridWidth, 0.0);
    tc->SetTuple2(2, barWidth / this->TextureGridWidth,
                  barHeight / this->TextureGridWidth);
    tc->SetTuple2(3, 0.0, barHeight / this->TextureGridWidth);
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::ConfigureTitle()
  {
    this->TitleActor->SetPosition(
      this->P->TitleBox.Posn[0] + this->P->TitleBox.Size[this->P->TL[0]] / 2,
      this->TitleActor->GetTextProperty()->GetVerticalJustification() ==
      VTK_TEXT_BOTTOM ?
      this->P->TitleBox.Posn[1]:
      this->P->TitleBox.Posn[1] + this->P->TitleBox.Size[this->P->TL[1]]);
  }
  
  //-----------------------------------------------------------------------------
  void vtkScalarBarActor::ConfigureTicks()
  {
    double val;
    double sizeTextData[2];
    for (int i = 0; i < this->NumberOfLabelsBuilt; ++i)
      {
      val = (this->NumberOfLabelsBuilt > 1 ?
        static_cast<double>(i) / (this->NumberOfLabelsBuilt - 1) : 0.5) *
        this->P->TickBox.Size[1] + this->P->TickBox.Posn[this->P->TL[1]];
      this->P->TextActors[i]->GetSize(this->P->Viewport, sizeTextData);
      if (this->Orientation == VTK_ORIENT_VERTICAL)
        { // VERTICAL
        this->P->TextActors[i]->GetTextProperty()->SetJustification(
          this->TextPosition == PrecedeScalarBar ? VTK_TEXT_RIGHT : VTK_TEXT_LEFT);
        this->P->TextActors[i]->GetTextProperty()
          ->SetVerticalJustificationToBottom();
        this->P->TextActors[i]->SetPosition(
          this->TextPosition == vtkScalarBarActor::PrecedeScalarBar ?
          this->P->TickBox.Posn[0] + this->P->TickBox.Size[0] :
          this->P->TickBox.Posn[0],
          //this->P->TickBox.Posn[0],
          val - 0.5 * sizeTextData[1]);
        }
      else
        { // HORIZONTAL
        this->P->TextActors[i]->GetTextProperty()->SetJustificationToCentered();
        this->P->TextActors[i]->GetTextProperty()->SetVerticalJustification(
          this->TextPosition == PrecedeScalarBar ? VTK_TEXT_TOP : VTK_TEXT_BOTTOM);
        this->P->TextActors[i]->SetPosition(val,
          this->TextPosition == PrecedeScalarBar ?
          this->P->TickBox.Posn[1] + this->P->TickBox.Size[0] :
          this->P->TickBox.Posn[1]);
        }
      }
  }
  
  //-----------------------------------------------------------------------------
  void vtkScalarBarActor::ConfigureNanSwatch()
  {
    if (!this->DrawNanAnnotation)
      {
      return;
      }
  
    int numPts = 4;
    vtkPoints* pts = vtkPoints::New();
    pts->SetNumberOfPoints(numPts);
    vtkCellArray* polys = vtkCellArray::New();
    polys->Allocate(polys->EstimateSize(1, 4));
    vtkUnsignedCharArray* colors = vtkUnsignedCharArray::New();
    colors->SetNumberOfComponents(4); // RGBA
    colors->SetNumberOfTuples(1);
  
    this->P->NanSwatch->Initialize();
    this->P->NanSwatch->SetPoints(pts);
    this->P->NanSwatch->SetPolys(polys);
    this->P->NanSwatch->GetCellData()->SetScalars(colors);
    pts->Delete();
    polys->Delete();
    colors->Delete();
  
    double x[3];
    x[2] = 0.;
  
    for (int j = 0; j < 2; ++j)
      {
      x[j] = this->P->NanBox.Posn[j];
      }
    int i = 0;
    pts->SetPoint(i++, x);
    x[0] += this->P->NanBox.Size[this->P->TL[0]];
    pts->SetPoint(i++, x);
    x[1] += this->P->NanBox.Size[this->P->TL[1]];
    pts->SetPoint(i++, x);
    x[0] -= this->P->NanBox.Size[this->P->TL[0]];
    pts->SetPoint(i++, x);
  
    // Add the swatch to the polydata and color it:
    unsigned char* rgb;
    double rgba[4];
    vtkIdType ptIds[4];
    ptIds[0] = 0;
    ptIds[1] = 1;
    ptIds[2] = 2;
    ptIds[3] = 3;
    polys->InsertNextCell(4, ptIds);
    this->LookupTable->GetIndexedColor(-1, rgba);
    rgb = colors->GetPointer(0); //write into array directly
    rgb[0] = static_cast<unsigned char>(rgba[0] * 255.);
    rgb[1] = static_cast<unsigned char>(rgba[1] * 255.);
    rgb[2] = static_cast<unsigned char>(rgba[2] * 255.);
    rgb[3] = static_cast<unsigned char>(this->UseOpacity ? rgba[3] * 255. : 255.);
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::ConfigureAboveBelowRangeSwatch(bool above)
  {
    // Check above/below
    vtkPolyData* swatch;
    vtkScalarBarBox* box;
    if (above)
      {
      if (!this->DrawAboveRangeSwatch)
        {
        return;
        }
      swatch = this->P->AboveRangeSwatch;
      box = &this->P->AboveRangeSwatchBox;
      }
    else
      {
      if (!this->DrawBelowRangeSwatch)
        {
        return;
        }
      swatch = this->P->BelowRangeSwatch;
      box = &this->P->BelowRangeSwatchBox;
      }
  
    int numPts = 4;
    vtkNew<vtkPoints> pts;
    pts->SetNumberOfPoints(numPts);
    vtkNew<vtkCellArray> polys;
    polys->Allocate(polys->EstimateSize(1, 4));
    vtkNew<vtkUnsignedCharArray> colors;
    colors->SetNumberOfComponents(4); // RGBA
    colors->SetNumberOfTuples(1);
  
    swatch->Initialize();
    swatch->SetPoints(pts.Get());
    swatch->SetPolys(polys.Get());
    swatch->GetCellData()->SetScalars(colors.Get());
    double x[3];
    x[2] = 0.;
  
    for (int j = 0; j < 2; ++j)
      {
      x[j] = box->Posn[j];
      }
    int i = 0;
    pts->SetPoint(i++, x);
    x[0] += box->Size[this->P->TL[0]];
    pts->SetPoint(i++, x);
    x[1] += box->Size[this->P->TL[1]];
    pts->SetPoint(i++, x);
    x[0] -= box->Size[this->P->TL[0]];
    pts->SetPoint(i++, x);
  
    // Add the swatch to the polydata and color it:
    double rgba[4] = { 1.0, 1.0, 1.0, 1.0 };
    vtkIdType ptIds[4] = { 0, 1, 2, 3};
    polys->InsertNextCell(4, ptIds);
    this->LookupTable->GetIndexedColor(-1, rgba);
  
    vtkLookupTable* lt = vtkLookupTable::SafeDownCast(this->LookupTable);
    vtkColorTransferFunction* ctf =
      vtkColorTransferFunction::SafeDownCast(this->LookupTable);
  
    if (lt)
      {
      if (above)
        {
        lt->GetAboveRangeColor(rgba);
        }
      else
        {
        lt->GetBelowRangeColor(rgba);
        }
      }
    else if (ctf)
      {
      if (above)
        {
        ctf->GetAboveRangeColor(rgba);
        }
      else
        {
        ctf->GetBelowRangeColor(rgba);
        }
      }
  
    unsigned char* rgb = colors->GetPointer(0); //write into array directly
    rgb[0] = static_cast<unsigned char>(rgba[0] * 255.);
    rgb[1] = static_cast<unsigned char>(rgba[1] * 255.);
    rgb[2] = static_cast<unsigned char>(rgba[2] * 255.);
    rgb[3] = static_cast<unsigned char>(this->UseOpacity ? rgba[3] * 255. : 255.);
  
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::ConfigureAnnotations()
  {
    // I. Create an actor for each valid label.
    int numNotes = static_cast<int>(this->P->Labels.size());
    if (!numNotes)
      {
      return;
      }
  
    this->P->AnnotationLabels.resize(numNotes);
    this->P->AnnotationAnchors.resize(numNotes);
    this->P->AnnotationColors.resize(numNotes);
    int i = 0;
    std::map<double, vtkStdString>::iterator it;
    for (it = this->P->Labels.begin(); it != this->P->Labels.end(); ++it, ++i)
      {
      this->P->AnnotationAnchors[i] = it->first;
      this->P->AnnotationColors[i] = this->P->LabelColors[it->first];
      this->P->AnnotationLabels[i] = vtkSmartPointer<vtkTextActor>::New();
      if (this->P->Viewport && this->AnnotationTextScaling)
        {
        this->P->AnnotationLabels[i]->SetTextScaleModeToViewport();
        this->P->AnnotationLabels[i]->ComputeScaledFont(this->P->Viewport);
        }
      this->P->AnnotationLabels[i]->GetTextProperty()->ShallowCopy(
        this->AnnotationTextProperty);
  
      this->P->AnnotationLabels[i]->SetProperty(this->GetProperty());
      // NB: If passed an empty string, pass a single space to the renderer;
      // empty strings get rendered as blobs which is Highly Undesirable.
      // Also render an empty string if the annotation can't be placed on the bar.
      this->P->AnnotationLabels[i]->SetInput(it->second.c_str());
      this->P->AnnotationLabels[i]->GetPositionCoordinate()->
        SetReferenceCoordinate(this->PositionCoordinate);
      }
  
    // Position each label and, in indexed mode, create the color swatches.
    if (this->LookupTable->GetIndexedLookup())
      {
      int indexedDenom = this->P->NumNotes;
      // Must reset the color on the leader lines since vtkTextProperty
      // doesn't inherit vtkProperty.
      // FIXME: Only set leader color when CellData scalars aren't used.
      this->P->AnnotationLeadersActor->GetProperty()->SetColor(
        this->AnnotationTextProperty->GetColor());
      this->P->AnnotationLeadersActor->GetProperty()->SetOpacity(
        this->AnnotationTextProperty->GetOpacity());
      // this->ScalarBar will not be drawn; instead, draw padded boxes
      // and leaders to labels for each annotated value.
      // Since labels are user-provided, we render with vtkTextActor
      // to allow fancy-ness.
      // 2 triangles per annotation: half-opaque, half-translucent:
      int numPts = 4 * indexedDenom;
      vtkPoints* pts = vtkPoints::New();
      pts->SetNumberOfPoints(numPts);
      vtkCellArray* polys = vtkCellArray::New();
      polys->Allocate(polys->EstimateSize(2 * indexedDenom, 3));
      vtkUnsignedCharArray* colors = vtkUnsignedCharArray::New();
      colors->SetNumberOfComponents(4); // RGBA
      colors->SetNumberOfTuples(2 * indexedDenom);
  
      this->P->AnnotationBoxes->Initialize();
      this->P->AnnotationBoxes->SetPoints(pts);
      this->P->AnnotationBoxes->SetPolys(polys);
      this->P->AnnotationBoxes->GetCellData()->SetScalars(colors);
      //this->P->AnnotationBoxes->SetProperty( this->GetProperty() );
      pts->Delete();
      polys->Delete();
      colors->Delete();
  
      // Use the nicely-provided scalar bar position to place
      // the annotated value swatches.
      double swatchC0, swatchC1; // fixed swatch coordinates
      double delta =
        static_cast<double>(this->P->ScalarBarBox.Size[1]) / indexedDenom;
      double x[3];
      x[2] = 0.;
      unsigned char* rgb;
      vtkIdType ptIds[4];
      swatchC0 = this->P->ScalarBarBox.Posn[this->P->TL[0]];
      swatchC1 = swatchC0 + this->P->ScalarBarBox.Size[0];
      if (this->Orientation == VTK_ORIENT_VERTICAL)
        {
        this->PlaceAnnotationsVertically(
          this->TextPosition == vtkScalarBarActor::SucceedScalarBar ?
          swatchC0 : swatchC1,
          this->P->ScalarBarBox.Posn[1],
          this->P->ScalarBarBox.Size[this->P->TL[0]],
          this->P->ScalarBarBox.Size[this->P->TL[1]],
          delta, this->P->SwatchPad);
        double top =
          this->P->ScalarBarBox.Posn[1] +
          this->P->ScalarBarBox.Size[this->P->TL[1]];
        for (i = 0; i < indexedDenom; ++i)
          {
          x[0] = swatchC0;
          x[1] = top - i * delta - this->P->SwatchPad;
          pts->SetPoint(4 * i, x);
          x[0] = swatchC1;
          pts->SetPoint(4 * i + 1, x);
          x[1] -= delta - this->P->SwatchPad * 2;
          pts->SetPoint(4 * i + 2, x);
          x[0] = swatchC0;
          pts->SetPoint(4 * i + 3, x);
          }
        }
      else
        {
        this->PlaceAnnotationsHorizontally(
          this->P->ScalarBarBox.Posn[0], swatchC1,
          this->P->ScalarBarBox.Size[1],
          this->P->ScalarBarBox.Size[0], delta, this->P->SwatchPad);
        for (i = 0; i < indexedDenom; ++i)
          {
          x[0] = this->P->ScalarBarBox.Posn[0] + i * delta + this->P->SwatchPad;
          x[1] = swatchC0;
          pts->SetPoint(4 * i, x);
          x[0] += delta - this->P->SwatchPad * 2;
          pts->SetPoint(4 * i + 1, x);
          x[1] = swatchC1;
          pts->SetPoint(4 * i + 2, x);
          x[0] -= delta - this->P->SwatchPad * 2;
          pts->SetPoint(4 * i + 3, x);
          }
        }
      for (i = 0; i < indexedDenom; ++i)
        {
        ptIds[0] = 4 * i;
        ptIds[1] = ptIds[0] + 1;
        ptIds[2] = ptIds[0] + 2;
        polys->InsertNextCell(3, ptIds);
  
        ptIds[1] = ptIds[2];
        ptIds[2] = ptIds[0] + 3;
        polys->InsertNextCell(3, ptIds);
  
        double rgbaF[4];
        this->LookupTable->GetIndexedColor(
          i == this->P->NumNotes ?
          -1 :
          i % this->LookupTable->GetNumberOfAvailableColors(),
          rgbaF);
        rgb = colors->GetPointer(
          /* numComponents */ 4 *
          /* numCells/swatch */ 2 *
          /* swatch */ i); //write into array directly
        rgb[0] = static_cast<unsigned char>(rgbaF[0] * 255.);
        rgb[1] = static_cast<unsigned char>(rgbaF[1] * 255.);
        rgb[2] = static_cast<unsigned char>(rgbaF[2] * 255.);
        rgb[3] = static_cast<unsigned char>(rgbaF[3] * 255.);
        rgb[4] = static_cast<unsigned char>(rgbaF[0] * 255.);
        rgb[5] = static_cast<unsigned char>(rgbaF[1] * 255.);
        rgb[6] = static_cast<unsigned char>(rgbaF[2] * 255.);
        rgb[7] = 255; // second triangle is always opaque
        }
      }
    else
      {
      if (this->Orientation == VTK_ORIENT_VERTICAL)
        {
        this->PlaceAnnotationsVertically(
          this->TextPosition == vtkScalarBarActor::SucceedScalarBar ?
          this->P->ScalarBarBox.Posn[this->P->TL[0]] :
          this->P->ScalarBarBox.Posn[this->P->TL[0]]
          + this->P->ScalarBarBox.Size[0],
          this->P->ScalarBarBox.Posn[1],
          this->P->ScalarBarBox.Size[0],
          this->P->ScalarBarBox.Size[1],
          0., this->P->SwatchPad);
        }
      else // HORIZONTAL
        {
        this->PlaceAnnotationsHorizontally(
          this->P->ScalarBarBox.Posn[0],
          this->P->ScalarBarBox.Posn[1] + this->P->ScalarBarBox.Size[0],
          this->P->ScalarBarBox.Size[1],
          this->P->ScalarBarBox.Size[0],
          0., this->P->SwatchPad);
        }
      }
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::FreeLayoutStorage()
  {
    // Delete previously constructed objects
    if (this->P->Viewport && this->P->Viewport->GetVTKWindow())
      {
      vtkWindow *win = this->P->Viewport->GetVTKWindow();
      if (!this->P->TextActors.empty())
        {
        vtkScalarBarActorInternal::ActorVector::iterator it;
        for (
             it = this->P->TextActors.begin();
             it != this->P->TextActors.end();
             ++it)
          {
          (*it)->ReleaseGraphicsResources(win);
          }
        }
      for (size_t i = 0; i < this->P->AnnotationLabels.size(); ++i)
        {
        this->P->AnnotationLabels[i]->ReleaseGraphicsResources(win);
        }
      }
  
    this->P->TextActors.clear();
    this->P->AnnotationLabels.clear();
    this->P->AnnotationAnchors.clear();
    this->P->AnnotationColors.clear();
  }
  
  //----------------------------------------------------------------------------
  void vtkScalarBarActor::SizeTitle(double* titleSize,
                                    int* size,
                                    vtkViewport* viewport)
  {
    titleSize[0] = titleSize[1] = 0;
  
    if (this->Title == NULL || !strlen(this->Title))
      {
      return;
      }
  
    int targetWidth, targetHeight;
    if (this->Orientation == VTK_ORIENT_VERTICAL)
      {
      targetWidth = static_cast<int>(0.9 * size[0]);
      targetHeight = static_cast<int>(0.1 * size[1]);
      }
    else
      {
      targetWidth = size[0];
      /*
         targetHeight = static_cast<int>(
         (this->LookupTable->GetIndexedLookup() ? 0.5 : 0.25) * size[1]);
       */
      if (this->LookupTable->GetIndexedLookup())
        {
        targetHeight = static_cast<int>(0.5 * size[1]);
        }
      else
        {
        double sizeTextData[2] = {0, 0};
        if (!this->P->TextActors.empty())
          { // Don't overlap tick-mark labels:
          this->P->TextActors[0]->GetSize(viewport, sizeTextData);
          }
        // The scalar bar takes half the height.
        // Subtract tick-label height and padding
        targetHeight =
          static_cast<int>((0.5 - 2 * 0.05) * size[1] - sizeTextData[1]);
        }
      }
  
    this->TitleActor->SetConstrainedFontSize(
      viewport, targetWidth, targetHeight);
  
    this->TitleActor->GetSize(viewport, titleSize);
  }
  
  //----------------------------------------------------------------------------
  int vtkScalarBarActor::MapAnnotationLabels(
    vtkScalarsToColors* lkup, double start, double delta, const double* range)
  {
    int numNotes = lkup->GetNumberOfAnnotatedValues();
    bool indexed = lkup->GetIndexedLookup() ? true : false;
    bool vertical = (this->Orientation == VTK_ORIENT_VERTICAL);
    vtkColor4d fltCol;
    double drange = range[1] - range[0];
    // I. If we are not in indexed mode, we must sort the labels that we can
    //    position by their order of appearance (since placement gives
    //    precedence to the median label). Hence, we use a map to accumulate
    //    labels.
    this->P->Labels.clear();
    this->P->LabelColors.clear();
    if (numNotes > 0)
      {
      for (int i = 0; i < numNotes; ++i)
        {
        vtkStdString label = lkup->GetAnnotation(i);
        lkup->GetAnnotationColor(lkup->GetAnnotatedValue(i), fltCol.GetData());
        double x;
        bool canPositionLabel = !label.empty();
        if (canPositionLabel)
          {
          if (indexed)
            {
            // Vertical orientation in indexed lookup mode is a special case:
            // The first swatch is placed at the top (highest y coordinate).
            // All other cases (all horizontal, interval-mode vertical) order
            // labels from lowest coordinate to highest.
            x = vertical ?
              start + (numNotes - i - 0.5) * delta / numNotes :
              start + (i + 0.5) * delta / numNotes;
            }
          else
            {
            vtkVariant pos = lkup->GetAnnotatedValue(i);
            x = pos.ToDouble(&canPositionLabel);
            if (canPositionLabel)
              { // Also do not draw if label is outside the scalar bar range.
              canPositionLabel = (x >= range[0] && x <= range[1]);
              }
            x = canPositionLabel ?
              (start + (x - range[0]) * delta / drange) :
              vtkMath::Nan();
            }
          }
        if (canPositionLabel)
          {
          this->P->Labels[x] = label;
          // Obtain a color for leader lines
          vtkColor3ub intCol;
          for (int j = 0; j < 3; ++j)
            {
            intCol.GetData()[j] =
              static_cast<unsigned char>(fltCol.GetData()[j] * 255.);
            }
          this->P->LabelColors[x] = intCol;
          }
        }
      }
  
    // II. Optionally add a NaN label.
    if (
        this->DrawNanAnnotation &&
        this->NanAnnotation &&
        this->NanAnnotation[0] != '\0')
      {
      // Get the NaN color
      lkup->GetIndexedColor(-1, fltCol.GetData());
      vtkColor3ub intCol;
      for (int j = 0; j < 3; ++j)
        {
        intCol.GetData()[j] =
          static_cast<unsigned char>(fltCol.GetData()[j] * 255.);
        }
      double x =
        this->P->NanBox.Posn[this->P->TL[1]] + this->P->NanBox.Size[1] / 2.;
      this->P->Labels[x] = this->NanAnnotation;
      this->P->LabelColors[x] = intCol;
      }
  
    // III. Optionally add a below range label.
    if (
        this->DrawBelowRangeSwatch &&
        this->BelowRangeAnnotation &&
        this->BelowRangeAnnotation[0] != '\0')
      {
      // Get the below range color
      lkup->GetIndexedColor(-1, fltCol.GetData());
      vtkColor3ub intCol;
      for (int j = 0; j < 3; ++j)
        {
        intCol.GetData()[j] =
          static_cast<unsigned char>(fltCol.GetData()[j] * 255.);
        }
      double x =
        this->P->BelowRangeSwatchBox.Posn[this->P->TL[1]] +
        this->P->BelowRangeSwatchBox.Size[1] / 2.;
      this->P->Labels[x] = this->BelowRangeAnnotation;
      this->P->LabelColors[x] = intCol;
      }
  
    // IV. Optionally add an above range label.
    if (
        this->DrawAboveRangeSwatch &&
        this->AboveRangeAnnotation &&
        this->AboveRangeAnnotation[0] != '\0')
      {
      // Get the above range color
      lkup->GetIndexedColor(-1, fltCol.GetData());
      vtkColor3ub intCol;
      for (int j = 0; j < 3; ++j)
        {
        intCol.GetData()[j] =
          static_cast<unsigned char>(fltCol.GetData()[j] * 255.);
        }
      double x =
        this->P->AboveRangeSwatchBox.Posn[this->P->TL[1]] +
        this->P->AboveRangeSwatchBox.Size[1] / 2.;
      this->P->Labels[x] = this->AboveRangeAnnotation;
      this->P->LabelColors[x] = intCol;
      }
  
    // V. Give subclasses a chance to edit the label map.
    this->EditAnnotations();
    return static_cast<int>(this->P->Labels.size());
  }
  
  //----------------------------------------------------------------------------
  int vtkScalarBarActor::PlaceAnnotationsVertically(
    double barX, double barY,
    double vtkNotUsed(barWidth), double barHeight,
    double vtkNotUsed(delta), double pad)
  {
    if (!this->LookupTable)
      {
      return 0;
      }
  
  #define VTK_ANN_VLAYOUT(j, dir, delt) \
    ctr = this->P->AnnotationAnchors[j]; \
    ll[0] = lpts->InsertNextPoint(xl0, ctr, 0.); \
    this->P->AnnotationLabels[j]->GetSize(this->P->Viewport, tsz); \
    hh = (tsz[1] + pad) / 2.; /* label half-height, incl. padding */ \
    if (((dir) < 0 && ctr + hh > dnCum) || ((dir) > 0 && ctr - hh < upCum)) \
    ctr = (delt) + (dir) * hh; \
    this->P->AnnotationLabels[j]->GetTextProperty()->SetJustification(\
      this->TextPosition == PrecedeScalarBar ? VTK_TEXT_LEFT : VTK_TEXT_RIGHT);\
    this->P->AnnotationLabels[j]->GetTextProperty()\
    ->SetVerticalJustificationToCentered(); \
    this->P->AnnotationLabels[j]->SetPosition(\
      barX + (this->TextPosition == PrecedeScalarBar ? 1 : -1) * \
        (pad + this->AnnotationLeaderPadding), \
                                              ctr); \
    ll[1] = lpts->InsertNextPoint(xl1, ctr, 0.); \
    llines->InsertNextCell(2, ll); \
    llcolors->InsertNextTypedTuple(this->P->AnnotationColors[j].GetData()); \
    if (upCum < ctr + hh) upCum = ctr + hh; \
    if (dnCum > ctr - hh) dnCum = ctr - hh;
  
    int numNotes = static_cast<int>(this->P->AnnotationLabels.size());
    vtkPoints* lpts = vtkPoints::New();
    vtkCellArray* llines = vtkCellArray::New();
    vtkUnsignedCharArray* llcolors = vtkUnsignedCharArray::New();
    llcolors->SetName("Leader Line Colors");
    llcolors->SetNumberOfComponents(3);
    llcolors->Allocate(numNotes);
    lpts->Allocate(2 * numNotes);
    llines->Allocate(llines->EstimateSize(numNotes, 2));
    this->P->AnnotationLeaders->Initialize();
    this->P->AnnotationLeaders->SetPoints(lpts);
    this->P->AnnotationLeaders->SetLines(llines);
    if (this->FixedAnnotationLeaderLineColor)
      {
      this->P->AnnotationLeaders->GetCellData()->SetScalars(NULL);
      }
    else
      {
      this->P->AnnotationLeaders->GetCellData()->SetScalars(llcolors);
      }
  
    // Start at the center and move outward (both up and down),
    // accumulating label heights as we go.
    int ic = numNotes / 2;
    int dn, up;
    double dnCum, upCum, ctr, hh;
    double tsz[2];
    // leader-line endpoint x-coordinates:
    double xl0 =
      barX + (this->TextPosition == PrecedeScalarBar ? 1 : -1) * pad / 2.;
    double xl1 = barX +
      (this->TextPosition == PrecedeScalarBar ? 1 : -1) *
      (pad / 2. + this->AnnotationLeaderPadding);
    vtkIdType ll[2]; // leader-line endpoint IDs
    if (2 * ic == numNotes)
      {
      dn = ic - 1;
      up = ic;
      dnCum = barY + barHeight;
      upCum = barY;
      }
    else
      {
      dn = ic - 1;
      up = ic + 1;
      dnCum = barY + barHeight;
      upCum = barY;
      VTK_ANN_VLAYOUT(ic, 0, dnCum);
      /*
         cout
         << "ic: " << ic << " ctr: " << ctr << " hh: " << hh
         << " uc: " << upCum << " dc: " << dnCum
         << " t:" << this->P->AnnotationLabels[ic]->GetInput() << endl;
       */
      }
    for (; dn >= 0; --dn, ++up)
      {
      VTK_ANN_VLAYOUT(dn, -1, dnCum);
      /*
         cout
         << "dn: " << dn << " ctr: " << ctr << " hh: " << hh
         << " uc: " << upCum << " dc: " << dnCum
         << " t:" << this->P->AnnotationLabels[dn]->GetInput() << endl;
       */
      VTK_ANN_VLAYOUT(up, 1, upCum);
      /*
         cout
         << "up: " << up << " ctr: " << ctr << " hh: " << hh
         << " uc: " << upCum << " dc: " << dnCum
         << " t:" << this->P->AnnotationLabels[up]->GetInput() << endl;
       */
      }
  
    lpts->Delete();
    llines->Delete();
    llcolors->Delete();
    return numNotes;
  }
  
  //-----------------------------------------------------------------------------
  struct vtkScalarBarHLabelInfo
  {
    double X[2]; // padded left-right label bounds
    double Y[2]; // padded top-bottom label bounds
    int Justification;
    double Anchor[2]; // x-y coordinates of anchor point
  };
  
  //-----------------------------------------------------------------------------
  // A non-overlapping label placer for a horizontal array of annotated swatches.
  // When space is tight, It displaces labels vertically and uses broken leader
  // lines to relate labels back to swatches.
  struct vtkScalarBarHLabelPlacer
  {
    std::vector<vtkScalarBarHLabelInfo> Places;
    unsigned Ctr;
    double Y0;
    double XBounds[2];
    int NumPlaced;
    double Pad;
    double LeaderPad;
    double Dir; // displacement direction (either +1 or -1)
    bool HaveCtr; // Is a label at the dead center? (i.e., is Places.size() odd?)
  
    vtkScalarBarHLabelPlacer(
      unsigned n, double y0, double dir, double xmin, double xmax,
      double pad, double leaderPad)
      : Places(n), Ctr(n % 2 ? n / 2 : n / 2 - 1), Y0(y0), NumPlaced(0),
      Pad(pad), LeaderPad(leaderPad),
      Dir(dir < 0 ? -1. : 1.), HaveCtr(n % 2 ? true : false)
        {
        this->XBounds[0] = xmin;
        this->XBounds[1] = xmax;
        }
  
    void Place(unsigned i, double xBest, double wd, double ht)
      {
      vtkScalarBarHLabelInfo& placement(this->Places[i]);
      unsigned farLo, farHi;
      int medNeighbor;
      int posRelToCenter =
        (i == this->Ctr && this->HaveCtr) ? 0 : (i > this->Ctr ? 1 : -1);
  
      if (posRelToCenter == 0 || this->NumPlaced == 0)
        { // center label
        placement.Y[0] = this->Y0 + this->Dir * (this->LeaderPad + this->Pad);
        // Note Y[1] has un-padded bounds on distal y axis! Required below.
        placement.Y[1] = placement.Y[0] + this->Dir * ht;
        placement.X[0] = xBest - wd / 2. - this->Pad;
        placement.X[1] = xBest + wd / 2. + this->Pad;
        placement.Justification = VTK_TEXT_CENTERED;
        placement.Anchor[0] = xBest;
        // Vertical justification changes, but Y[0] is always anchor:
        placement.Anchor[1] = placement.Y[0];
        }
      else // placing *a lateral* (as opposed to *the medial*) label.
        {
        // First: Horizontal placement.
        // Check immediate medial neighbor to see if placement can occur
        // without more displacement.
        bool needToDisplace = false;
        if (posRelToCenter == 1)
          {
          // label is right-justified;
          // placement.X[1] bounded from above by XBounds[1]
  
          // Furthest label we have placed so far.
          farLo = 2 * this->Ctr + (this->HaveCtr ? 0 : 1) - i;
          farHi = this->Ctr; // The closest label we might overlap is dead center.
          medNeighbor = i - 1;
          placement.Justification = VTK_TEXT_RIGHT;
          placement.X[1] = xBest;
          placement.X[0] = placement.X[1] - wd - 2 * this->Pad;
          placement.Anchor[0] = placement.X[1]; // - this->Pad;
          if (xBest - wd < this->Places[medNeighbor].X[1])
            { // We must displace
            needToDisplace = true;
            }
          }
        else // posRelToCenter == -1
          {
          // label is left-justified;
          // placement.X[0] bounded from below by XBounds[0] or left neighbor
  
          // The center label is the closest label we might overlap:
          farLo = this->Ctr + (this->HaveCtr ? 0 : 1);
          // The furthest label to the right we have placed so far.
          farHi = 2 * this->Ctr - i - (this->HaveCtr ? 1 : 0);
          medNeighbor = i + 1;
          if (!this->HaveCtr && medNeighbor >= static_cast<int>(farHi))
            {
            medNeighbor = -1;
            }
          placement.Justification = VTK_TEXT_LEFT;
          placement.X[0] = xBest;
          placement.X[1] = placement.X[0] + wd + 2 * this->Pad;
          placement.Anchor[0] = placement.X[0];
          if (medNeighbor >= 0 && xBest + wd > this->Places[medNeighbor].X[0])
            {
            // we must displace; put the label where it makes sense:
            // bounded on left by swatch edge.
            needToDisplace = true;
            }
          }
        // Second: Vertical placement. Displace label to avoid overlap if need be.
        if (!needToDisplace)
          {
          placement.Y[0] = (medNeighbor >= 0 ?
                            this->Places[medNeighbor].Y[0] :
                            this->Y0 + this->Dir * (this->LeaderPad + this->Pad));
          placement.Y[1] = placement.Y[0] + this->Dir * ht;
          //placement.X[1] = placement.X[0] + wd;
          placement.Anchor[1] = placement.Y[0];
          }
        else
          { // must displace... find out by how much
          // I. At least as much as immediate medial neighbor
          placement.Y[0] = this->Places[medNeighbor].Y[1] + this->Dir * this->Pad;
          for (unsigned j = farLo; j <= farHi; ++j)
            {
            // II. Check whether label has any y overlap && any x overlap.
            // There are 2 cases: one for labels above swatches, the other
            // for labels below swatches.
            if (
                (this->Dir < 0 && placement.Y[0] > this->Places[j].Y[1] &&
                 (i > j ?
                  placement.X[0] <= this->Places[j].X[1] :
                  placement.X[1] >= this->Places[j].X[0])) ||
                (this->Dir > 0 && placement.Y[0] < this->Places[j].Y[1] &&
                 (i > j ?
                  placement.X[0] <= this->Places[j].X[1] :
                  placement.X[1] >= this->Places[j].X[0])))
              {
              placement.Y[0] = this->Places[j].Y[1] + this->Dir * this->Pad;
              }
            }
          placement.Y[1] = placement.Y[0] + this->Dir * ht;
          // Vertical justification changes, but Y[0] is always anchor
          placement.Anchor[1] = placement.Y[0];
          }
        }
      ++this->NumPlaced;
      }
  
    void BreakLeader(
      vtkScalarBarHLabelInfo& label, double& curY, int j,
      vtkPoints* pts, vtkCellArray* lines, vtkUnsignedCharArray* colors,
      const vtkColor3ub& color
      )
      {
      vtkScalarBarHLabelInfo& other(this->Places[j]);
      vtkIdType pt;
      if (
          label.Anchor[0] > other.X[0] && label.Anchor[0] < other.X[1] &&
          ((this->Dir > 0 && label.Anchor[1] >= other.Y[0]) ||
           (this->Dir < 0 && label.Anchor[1] <= other.Y[0])
          )
         )
        {
        pt = pts->InsertNextPoint(label.Anchor[0], other.Y[0], 0.);
        lines->InsertCellPoint(pt);
        lines->InsertNextCell(2);
        colors->InsertNextTypedTuple(color.GetData());
        curY = other.Y[1];
        pt = pts->InsertNextPoint(label.Anchor[0], curY, 0.);
        lines->InsertCellPoint(pt);
        }
      }
  
    // Only called after all labels are placed
    void AddBrokenLeader(
      int lidx, vtkPoints* pts, vtkCellArray* lines,
      vtkUnsignedCharArray* colors, const vtkColor3ub& color)
      {
      vtkIdType pt;
      vtkScalarBarHLabelInfo& label(this->Places[lidx]);
  
      // I. Insert first vertex near swatch:
      lines->InsertNextCell(2);
      colors->InsertNextTypedTuple(color.GetData());
      double curY = this->Y0 + this->Dir * this->Pad / 2.;
      pt = pts->InsertNextPoint(label.Anchor[0], curY, 0.);
      lines->InsertCellPoint(pt);
  
      // II. Loop over all labels checking for interference.
      // Where found, close current line and start new one on the other side.
      int ic = static_cast<int>(this->Places.size()) / 2;
      int lf, rt;
      bool done = false;
      if (!this->HaveCtr)
        {
        lf = ic - 1;
        rt = ic;
        }
      else
        {
        lf = ic - 1;
        rt = ic + 1;
        if (lidx == ic)
          {
          done = true;
          }
        else
          {
          //cout << "Break " << lidx << " with " << ic << "\n";
          this->BreakLeader(label, curY, ic, pts, lines, colors, color);
          }
        }
      if (!done)
        {
        for (; lf >= 0; --lf, ++rt)
          {
          if (lf == lidx) break;
          //cout << "Break " << lidx << " with " << lf << "\n";
          this->BreakLeader(label, curY, lf, pts, lines, colors, color);
          if (rt == lidx) break;
          //cout << "Break " << lidx << " with " << rt << "\n";
          this->BreakLeader(label, curY, rt, pts, lines, colors, color);
          }
        }
  
      // III. Finally, close the open line segment with the label anchor point.
      pt = pts->InsertNextPoint(
        label.Anchor[0], label.Anchor[1] - this->Dir * this->Pad / 2., 0.);
      lines->InsertCellPoint(pt);
      }
  };
  
  //----------------------------------------------------------------------------
  /**\brief Non-overlapping label placer for a horizontal array of swatches.
   *
   * A set of rules are enforced during layout:
   * <ul>
   * <li> Any label may be wider than the entire legend.
   * <li> The center label should be centered on the center swatch
   * <li> No other label should extend beyond the legend's matching lateral
   *   extent (i.e., a label to the left of center
   *   should never extend beyond the left bounds of its swatch).
   * <li> To enforce this, labels may be displaced vertically (distally) away
   *   from the legend.
   * <li> Broken leaders should be drawn connecting each displaced label to
   *   its swatch, with breaks where long labels from the centerline or beyond
   *   obstruct it.
   * </ul>
   *
   * The algorithm for performing the layout enforces these rules as follows:
   * Labels are placed starting with the central (medial) label
   * and moving outwards;
   * this provides a consistent placement as the actor is resized.
   * First the horizontal label position is determined by examining the
   * width of the label and the extents of its medial neighbor (which will
   * have been placed already).
   * The vertical displacement is then computed by either copying the medial
   * neighbor's displacement (if no interference with the neighbor was required)
   * or incrementing the displacement beyond its immediate
   * neighbor and checking all other relevant labels for intereference.
   */
  int vtkScalarBarActor::PlaceAnnotationsHorizontally(
    double barX, double barY,
    double barWidth, double barHeight,
    double vtkNotUsed(delta), double pad)
  {
    if (!this->LookupTable)
      {
      return 0;
      }
  
  #define VTK_ANN_HLAYOUT(j, placer) \
    this->P->AnnotationLabels[j]->GetTextProperty()\
    ->SetJustification(placer.Places[j].Justification); \
    this->P->AnnotationLabels[j]->GetTextProperty()\
    ->SetVerticalJustification(placer.Dir > 0 ? \
      VTK_TEXT_BOTTOM : VTK_TEXT_TOP); \
    this->P->AnnotationLabels[j]->SetPosition(placer.Places[j].Anchor); \
    placer.AddBrokenLeader(j, lpts, llines, llcolors, \
                           this->P->AnnotationColors[j]);
  
    int numNotes = static_cast<int>(this->P->AnnotationLabels.size());
    bool precede = this->TextPosition == vtkScalarBarActor::PrecedeScalarBar;
    vtkScalarBarHLabelPlacer placer(
      numNotes, precede ? barY : barY - barHeight, precede ? 1 : -1,
      barX, barX + barWidth, pad, this->AnnotationLeaderPadding);
  
    vtkPoints* lpts = vtkPoints::New();
    vtkCellArray* llines = vtkCellArray::New();
    vtkUnsignedCharArray* llcolors = vtkUnsignedCharArray::New();
    llcolors->SetName("Leader Line Color");
    llcolors->SetNumberOfComponents(3);
    llcolors->Allocate(numNotes * numNotes);
    // TODO: Improve estimates, but we don't know how many breaks there will be:
    lpts->Allocate(numNotes * numNotes);
    llines->Allocate(llines->EstimateSize(numNotes * numNotes, 2));
    this->P->AnnotationLeaders->Initialize();
    this->P->AnnotationLeaders->SetPoints(lpts);
    this->P->AnnotationLeaders->SetLines(llines);
    if (this->FixedAnnotationLeaderLineColor)
      {
      this->P->AnnotationLeaders->GetCellData()->SetScalars(NULL);
      }
    else
      {
      this->P->AnnotationLeaders->GetCellData()->SetScalars(llcolors);
      }
  
    // Start at the center and move outward (both up and down),
    // accumulating label displacement as we go.
    int ic = numNotes / 2;
    int lf, rt;
    double tsz[2];
    vtkColor3ub leaderColor;
    if (2 * ic == numNotes)
      {
      lf = ic - 1;
      rt = ic;
      }
    else
      {
      lf = ic - 1;
      rt = ic + 1;
      this->P->AnnotationLabels[ic]->GetSize(this->P->Viewport, tsz);
      placer.Place(
        ic, this->P->AnnotationAnchors[ic], tsz[0], tsz[1]);
      VTK_ANN_HLAYOUT(ic, placer);
      }
    for (; lf >= 0; --lf, ++rt)
      {
      this->P->AnnotationLabels[lf]->GetSize(this->P->Viewport, tsz);
      placer.Place(
        lf, this->P->AnnotationAnchors[lf], tsz[0], tsz[1]);
      VTK_ANN_HLAYOUT(lf, placer);
      this->P->AnnotationLabels[rt]->GetSize(this->P->Viewport, tsz);
      placer.Place(
        rt, this->P->AnnotationAnchors[rt], tsz[0], tsz[1]);
      VTK_ANN_HLAYOUT(rt, placer);
      }
  
    lpts->Delete();
    llines->Delete();
    llcolors->Delete();
    return numNotes;
  }
  