/*=========================================================================

  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 "vtkCoordinate.h"
#include "vtkFloatArray.h"
#include "vtkPointData.h"
#include "vtkImageData.h"
#include "vtkMath.h"
#include "vtkObjectFactory.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper2D.h"
#include "vtkProperty2D.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.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 "vtkMathTextUtilities.h"

#include <vector>
#include <set>
#include <map>

#include <stdio.h> // for snprintf

#if defined(_WIN32) && !defined(__CYGWIN__)
#  define SNPRINTF _snprintf
#else
#  define SNPRINTF snprintf
#endif

#undef VTK_DBG_LAYOUT

vtkStandardNewMacro(vtkScalarBarActor);

vtkCxxSetObjectMacro(vtkScalarBarActor,LookupTable,vtkScalarsToColors);
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->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->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 = true;
  this->DrawTickLabels = true;
}

//----------------------------------------------------------------------------
// 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 (vtkScalarBarActorInternal::ActorVector::size_type 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->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->ScalarBar->Delete();
  this->ScalarBarMapper->Delete();
  this->ScalarBarActor->Delete();

  this->P->NanSwatch->Delete();
  this->P->NanSwatchMapper->Delete();
  this->P->NanSwatchActor->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->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)
{
  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->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 (vtkScalarBarActorInternal::ActorVector::size_type i = 0; i < this->P->AnnotationLabels.size(); ++ i )
        {
        renderedSomething +=
          this->P->AnnotationLabels[i]->RenderOverlay( viewport );
        }
      }
    }

  renderedSomething = (renderedSomething > 0)?(1):(0);
  return renderedSomething;
}

//----------------------------------------------------------------------------
int vtkScalarBarActor::RenderOpaqueGeometry(vtkViewport* viewport)
{
  int renderedSomething = 0;

  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;
    }

  // 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->LabelTextProperty->GetMTime() > this->BuildTime ||
      this->TitleTextProperty->GetMTime() > this->BuildTime ||
      this->BackgroundProperty->GetMTime() > this->BuildTime ||
      this->FrameProperty->GetMTime() > this->BuildTime)

    {
    this->RebuildLayout(viewport);
    }

  // 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);
    }

  // Draw the annotation leaders and labels
  if ( this->DrawAnnotations )
    {
    if (!this->P->AnnotationLabels.empty())
      {
      renderedSomething +=
        this->P->AnnotationLeadersActor->RenderOpaqueGeometry( viewport );
      for (vtkScalarBarActorInternal::ActorVector::size_type 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";
    }

  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 << "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->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->LayoutNanSwatch();
  this->PrepareTitleText();
  this->LayoutTitle();
  this->ComputeScalarBarLength();
  this->LayoutTicks();
  this->LayoutAnnotations();

  // 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();
#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::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->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.;
    }

  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::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))
    {
    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);

  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.
  this->P->ScalarBarBox.Size[1] = static_cast<int>(this->P->ScalarBarBox.Size[1] -
    (this->P->NanSwatchSize + 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->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;
        /* or equivalently: Posn[1] -=
          this->P->Frame.Size[0] -
          this->P->TitleBox.Size[0] - this->TextPad -
          this->P->ScalarBarBox.Size[0];
          */
        }
      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];
      }

    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]] = static_cast<int>(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->TickBox.Posn[1] += this->TextPad *
        (this->TextPosition == PrecedeScalarBar ? -1 : +1);
      this->P->TickBox.Size[1] -= this->TextPad;
      }
    }
  this->NumberOfLabelsBuilt = this->NumberOfLabels;
}

//----------------------------------------------------------------------------
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->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); ++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::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->LabelTextProperty );
    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->LabelTextProperty->GetColor());
    this->P->AnnotationLeadersActor->GetProperty()->SetOpacity(
      this->LabelTextProperty->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
  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. 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->InsertNextTupleValue(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->InsertNextTupleValue(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->InsertNextTupleValue(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;
}
