text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    vtkLegendBoxActor.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 "vtkLegendBoxActor.h"
  
  #include "vtkActor.h"
  #include "vtkCellArray.h"
  #include "vtkDoubleArray.h"
  #include "vtkImageData.h"
  #include "vtkObjectFactory.h"
  #include "vtkPlaneSource.h"
  #include "vtkPolyData.h"
  #include "vtkPolyDataMapper.h"
  #include "vtkPolyDataMapper2D.h"
  #include "vtkProperty2D.h"
  #include "vtkProperty.h"
  #include "vtkTexturedActor2D.h"
  #include "vtkTextMapper.h"
  #include "vtkTextProperty.h"
  #include "vtkTexture.h"
  #include "vtkTransform.h"
  #include "vtkTransformPolyDataFilter.h"
  #include "vtkViewport.h"
  
  vtkStandardNewMacro(vtkLegendBoxActor);
  
  vtkCxxSetObjectMacro(vtkLegendBoxActor,EntryTextProperty,vtkTextProperty);
  
  //----------------------------------------------------------------------------
  vtkLegendBoxActor::vtkLegendBoxActor()
  {
    // Positioning information
    this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport();
    this->PositionCoordinate->SetValue(0.75, 0.75);
  
    this->Position2Coordinate->SetValue(0.2, 0.2);
  
    this->LockBorder = 0;
    this->ScalarVisibility = 1;
  
    // Control font properties
    this->EntryTextProperty = vtkTextProperty::New();
    this->EntryTextProperty->SetBold(0);
    this->EntryTextProperty->SetItalic(0);
    this->EntryTextProperty->SetShadow(0);
    this->EntryTextProperty->SetFontFamily(VTK_ARIAL);
    this->EntryTextProperty->SetJustification(VTK_TEXT_LEFT);
    this->EntryTextProperty->SetVerticalJustification(VTK_TEXT_CENTERED);
  
    this->Border = 1;
    this->Box = 0;
    this->Padding = 3;
  
    // Symbols and text strings
    this->NumberOfEntries = 0;
    this->Size = 0;
    this->Colors = nullptr;
    this->Symbol = nullptr;
    this->Transform = nullptr;
    this->SymbolTransform = nullptr;
    this->SymbolMapper = nullptr;
    this->SymbolActor = nullptr;
    this->TextMapper = nullptr;
    this->TextActor = nullptr;
  
    this->Icon = nullptr;
    this->IconActor = nullptr;
    this->IconMapper = nullptr;
    this->IconTransformFilter = nullptr;
    this->IconTransform = nullptr;
    this->IconImage = nullptr;
  
    // Construct the border
    this->BorderPolyData = vtkPolyData::New();
    vtkPoints *points = vtkPoints::New();
    points->SetNumberOfPoints(4);
    this->BorderPolyData->SetPoints(points);
    points->Delete();
    vtkCellArray *lines = vtkCellArray::New();
    lines->InsertNextCell(5); //points will be updated later
    lines->InsertCellPoint(0);
    lines->InsertCellPoint(1);
    lines->InsertCellPoint(2);
    lines->InsertCellPoint(3);
    lines->InsertCellPoint(0);
    this->BorderPolyData->SetLines(lines);
    lines->Delete();
  
    this->BorderMapper = vtkPolyDataMapper2D::New();
    this->BorderMapper->SetInputData(this->BorderPolyData);
  
    this->BorderActor = vtkActor2D::New();
    this->BorderActor->SetMapper(this->BorderMapper);
  
    // Construct the box
    this->BoxPolyData = vtkPolyData::New();
    this->BoxPolyData->SetPoints(this->BorderPolyData->GetPoints());
    vtkCellArray *polys = vtkCellArray::New();
    polys->InsertNextCell(4);
    polys->InsertCellPoint(0);
    polys->InsertCellPoint(1);
    polys->InsertCellPoint(2);
    polys->InsertCellPoint(3);
    this->BoxPolyData->SetPolys(polys);
    polys->Delete();
  
    this->BoxMapper = vtkPolyDataMapper2D::New();
    this->BoxMapper->SetInputData(this->BoxPolyData);
  
    this->BoxActor = vtkActor2D::New();
    this->BoxActor->SetMapper(this->BoxMapper);
  
    // Background.
    this->UseBackground = 0;
    this->BackgroundOpacity = 1.0;
    this->BackgroundColor[0] =  this->BackgroundColor[1] = this->BackgroundColor[2] = 0.3;
    this->Background = vtkPlaneSource::New();
    this->BackgroundActor = vtkTexturedActor2D::New();
    this->BackgroundMapper = vtkPolyDataMapper2D::New();
    this->BackgroundActor->SetMapper(this->BackgroundMapper);
  }
  
  //----------------------------------------------------------------------------
  vtkLegendBoxActor::~vtkLegendBoxActor()
  {
    this->InitializeEntries();
  
    if ( this->BorderActor )
    {
      this->BorderActor->Delete();
      this->BorderMapper->Delete();
      this->BorderPolyData->Delete();
    }
  
    if ( this->BoxActor )
    {
      this->BoxActor->Delete();
      this->BoxMapper->Delete();
      this->BoxPolyData->Delete();
    }
  
    if ( this->BackgroundActor )
    {
      this->BackgroundActor->Delete();
      this->BackgroundMapper->Delete();
      this->Background->Delete();
    }
  
    this->SetEntryTextProperty(nullptr);
  }
  
  //----------------------------------------------------------------------------
  void vtkLegendBoxActor::InitializeEntries()
  {
    int i;
  
    if ( this->Size > 0 )
    {
      this->Colors->Delete();
      for (i=0; i<this->Size; i++)
      {
        if ( this->Symbol[i] )
        {
          this->Symbol[i]->Delete();
        }
        this->Transform[i]->Delete();
        this->SymbolTransform[i]->Delete();
        this->SymbolMapper[i]->Delete();
        this->SymbolActor[i]->Delete();
        if ( this->TextMapper[i] )
        {
          this->TextMapper[i]->Delete();
          this->TextActor[i]->Delete();
        }
  
        if( this->IconImage[i] )
        {
          this->IconImage[i]->Delete();
        }
  
        this->Icon[i]->Delete();
        this->IconTransform[i]->Delete();
        this->IconTransformFilter[i]->Delete();
        this->IconMapper[i]->Delete();
        this->IconActor[i]->Delete();
      }//for all entries
      delete [] this->Symbol; this->Symbol = nullptr;
      delete [] this->Transform; this->Transform = nullptr;
      delete [] this->SymbolTransform; this->SymbolTransform = nullptr;
      delete [] this->SymbolMapper; this->SymbolMapper = nullptr;
      delete [] this->SymbolActor; this->SymbolActor = nullptr;
      delete [] this->TextMapper; this->TextMapper = nullptr;
      delete [] this->TextActor; this->TextActor = nullptr;
  
      delete [] this->IconImage; this->IconImage = nullptr;
      delete [] this->Icon; this->Icon = nullptr;
      delete [] this->IconActor; this->IconActor = nullptr;
      delete [] this->IconMapper; this->IconMapper = nullptr;
      delete [] this->IconTransform; this->IconTransform = nullptr;
      delete [] this->IconTransformFilter; this->IconTransformFilter = nullptr;
    }//if entries have been defined
  }
  
  //----------------------------------------------------------------------------
  void vtkLegendBoxActor::SetNumberOfEntries(int num)
  {
    if ( num == this->NumberOfEntries )
    {
      return;
    }
  
    else if ( num < this->Size )
    {
      this->NumberOfEntries = num;
    }
  
    else //allocate space
    {
      int i;
  
      //Create internal actors, etc.
      vtkDoubleArray *colors = vtkDoubleArray::New();
      colors->SetNumberOfComponents(3);
      colors->SetNumberOfTuples(num);
      vtkTextMapper **textMapper= new vtkTextMapper* [num];
      vtkActor2D **textActor = new vtkActor2D* [num];
  
      // Symbol
      vtkPolyData **symbol = new vtkPolyData* [num];
      vtkTransform **transform= new vtkTransform* [num];
      vtkTransformPolyDataFilter **symbolTransform =
                                   new vtkTransformPolyDataFilter* [num];
      vtkPolyDataMapper2D **symbolMapper = new vtkPolyDataMapper2D* [num];
      vtkActor2D **symbolActor = new vtkActor2D* [num];
  
      // Icon.
      vtkPlaneSource **icon = new vtkPlaneSource* [num];
      vtkTransform **iconTransform= new vtkTransform* [num];
      vtkTransformPolyDataFilter **iconTransformFilter =
                                   new vtkTransformPolyDataFilter* [num];
      vtkPolyDataMapper2D **iconMapper = new vtkPolyDataMapper2D* [num];
      vtkTexturedActor2D **iconActor = new vtkTexturedActor2D* [num];
      vtkImageData **iconImage = new vtkImageData* [num];
  
      //copy old values
      for (i=0; i<this->NumberOfEntries; i++)
      {
        colors->SetTuple(i,this->Colors->GetTuple(i));
        textMapper[i] = this->TextMapper[i];
        textMapper[i]->Register(this);
        textActor[i] = this->TextActor[i];
        textActor[i]->Register(this);
  
        // Symbol.
        symbol[i] = this->Symbol[i];
        if ( symbol[i] )
        {
          symbol[i]->Register(this);
        }
  
        transform[i] = this->Transform[i];
        transform[i]->Register(this);
  
        symbolTransform[i] = this->SymbolTransform[i];
        symbolTransform[i]->Register(this);
  
        symbolMapper[i] = this->SymbolMapper[i];
        symbolMapper[i]->Register(this);
  
        symbolActor[i] = this->SymbolActor[i];
        symbolActor[i]->Register(this);
  
        // Icon.
        icon[i] = this->Icon[i];
        icon[i]->Register(this);
  
        iconTransform[i] = this->IconTransform[i];
        iconTransform[i]->Register(this);
  
        iconTransformFilter[i] = this->IconTransformFilter[i];
        iconTransformFilter[i]->Register(this);
  
        iconMapper[i] = this->IconMapper[i];
        iconMapper[i]->Register(this);
  
        iconActor[i] = this->IconActor[i];
        iconActor[i]->Register(this);
  
        iconImage[i] = this->IconImage[i];
        if( iconImage[i] )
        {
          iconImage[i]->Register(this);
        }
      }
  
      //initialize data values
      static double color[3]={-1.0,-1.0,-1.0};
      for (i=this->NumberOfEntries; i<num; i++) //initialize
      {
        colors->SetTuple(i,color);
        textMapper[i] = vtkTextMapper::New();
        textActor[i] = vtkActor2D::New();
        textActor[i]->SetMapper(textMapper[i]);
  
        // Symbol.
        symbol[i] = nullptr;
        transform[i] = vtkTransform::New();
        symbolTransform[i] = vtkTransformPolyDataFilter::New();
        symbolTransform[i]->SetTransform(transform[i]);
        symbolMapper[i] = vtkPolyDataMapper2D::New();
        symbolMapper[i]->SetInputConnection(
          symbolTransform[i]->GetOutputPort());
        symbolActor[i] = vtkActor2D::New();
        symbolActor[i]->SetMapper(symbolMapper[i]);
  
        // Icon.
        iconImage[i] = nullptr;
  
        icon[i] = vtkPlaneSource::New();
        icon[i]->SetPoint1(1.0, 0.0, 0.0);
        icon[i]->SetPoint2(0, 1.0, 0.0);
        icon[i]->SetOrigin(0.0, 0.0, 0.0);
        icon[i]->SetResolution(1, 1);
  
        iconTransform[i] = vtkTransform::New();
  
        iconTransformFilter[i] = vtkTransformPolyDataFilter::New();
        iconTransformFilter[i]->SetTransform(iconTransform[i]);
  
        iconMapper[i] = vtkPolyDataMapper2D::New();
        iconMapper[i]->SetInputConnection(
          iconTransformFilter[i]->GetOutputPort());
  
        iconActor[i] = vtkTexturedActor2D::New();
        iconActor[i]->SetMapper(iconMapper[i]);
      }
  
      //Clear out the old stuff
      this->InitializeEntries();
  
      //Bring everything up to date
      this->NumberOfEntries = this->Size = num;
      this->Colors = colors;
      this->TextMapper = textMapper;
      this->TextActor = textActor;
  
      this->Symbol = symbol;
      this->Transform = transform;
      this->SymbolTransform = symbolTransform;
      this->SymbolMapper = symbolMapper;
      this->SymbolActor = symbolActor;
  
      this->Icon = icon;
      this->IconTransform = iconTransform;
      this->IconTransformFilter = iconTransformFilter;
      this->IconMapper = iconMapper;
      this->IconActor = iconActor;
      this->IconImage = iconImage;
    }
  
    this->Modified();
  }
  
  //----------------------------------------------------------------------------
  void vtkLegendBoxActor::SetEntry(int i, vtkPolyData *symbol, const char* string,
                                   double color[3])
  {
    if ( i >= 0 && i < this->NumberOfEntries )
    {
      this->SetEntrySymbol(i,symbol);
      this->SetEntryString(i,string);
      this->SetEntryColor(i,color);
    }
  }
  
  //----------------------------------------------------------------------------
  void vtkLegendBoxActor::SetEntry(int i, vtkImageData *icon, const char* string, double color[3])
  {
    if ( i >= 0 && i < this->NumberOfEntries )
    {
      this->SetEntryIcon(i,icon);
      this->SetEntryString(i,string);
      this->SetEntryColor(i,color);
    }
  }
  
  
  //----------------------------------------------------------------------------
  void vtkLegendBoxActor::SetEntry(int i, vtkPolyData *symbol, vtkImageData *icon,
                                   const char* string, double color[3])
  {
    if ( i >= 0 && i < this->NumberOfEntries )
    {
      this->SetEntry(i, symbol, string, color);
      this->SetEntryIcon(i, icon);
    }
  }
  
  //----------------------------------------------------------------------------
  void vtkLegendBoxActor::SetEntrySymbol(int i, vtkPolyData *symbol)
  {
    if ( i >= 0 && i < this->NumberOfEntries )
    {
      if ( this->Symbol[i] == symbol )
      {
        return;
      }
      if ( this->Symbol[i] )
      {
        this->Symbol[i]->Delete();
      }
      this->Symbol[i] = symbol;
      if ( this->Symbol[i] )
      {
        this->Symbol[i]->Register(this);
      }
      this->Modified();
    }
  }
  
  //----------------------------------------------------------------------------
  void vtkLegendBoxActor::SetEntryIcon(int i, vtkImageData *icon)
  {
    if ( i >= 0 && i < this->NumberOfEntries )
    {
      if ( this->IconImage[i] == icon )
      {
        return;
      }
      if ( this->IconImage[i] )
      {
        this->IconImage[i]->Delete();
      }
      this->IconImage[i] = icon;
      if ( this->IconImage[i] )
      {
        this->IconImage[i]->Register(this);
      }
      this->Modified();
    }
  }
  
  //----------------------------------------------------------------------------
  void vtkLegendBoxActor::SetEntryString(int i, const char* string)
  {
    if ( i >= 0 && i < this->NumberOfEntries )
    {
      if ( this->TextMapper[i]->GetInput() && string
           && (!strcmp(this->TextMapper[i]->GetInput(),string)))
      {
        return;
      }
      this->TextMapper[i]->SetInput(string);
      this->Modified();
    }
  }
  
  //----------------------------------------------------------------------------
  void vtkLegendBoxActor::SetEntryColor(int i, double color[3])
  {
    if ( i >= 0 && i < this->NumberOfEntries )
    {
      double oldColor[3];
      this->Colors->GetTuple(i, oldColor);
  
      if ( oldColor[0] != color[0] || oldColor[1] != color[1] ||
           oldColor[2] != color[2] )
      {
        this->Colors->SetTuple3(i,color[0],color[1],color[2]);
        this->Modified();
      }
    }
  }
  
  //----------------------------------------------------------------------------
  void vtkLegendBoxActor::SetEntryColor(int i, double r, double g, double b)
  {
    double rgb[3];
    rgb[0] = r; rgb[1] = g; rgb[2] = b;
    this->SetEntryColor(i,rgb);
  }
  
  //----------------------------------------------------------------------------
  vtkPolyData *vtkLegendBoxActor::GetEntrySymbol(int i)
  {
    if ( i < 0 || i >= this->NumberOfEntries )
    {
      return nullptr;
    }
    else
    {
      return this->Symbol[i];
    }
  }
  
  //----------------------------------------------------------------------------
  vtkImageData* vtkLegendBoxActor::GetEntryIcon(int i)
  {
    if ( i < 0 || i >= this->NumberOfEntries )
    {
      return nullptr;
    }
    else
    {
      return this->IconImage[i];
    }
  }
  
  //----------------------------------------------------------------------------
  const char* vtkLegendBoxActor::GetEntryString(int i)
  {
    if ( i < 0 || i >= this->NumberOfEntries )
    {
      return nullptr;
    }
    else
    {
      return this->TextMapper[i]->GetInput();
    }
  }
  
  //----------------------------------------------------------------------------
  double* vtkLegendBoxActor::GetEntryColor(int i)
  {
    if ( i < 0 || i >= this->NumberOfEntries )
    {
      return nullptr;
    }
    else
    {
      return vtkArrayDownCast<vtkDoubleArray>(this->Colors)->GetPointer(i*3);
    }
  }
  
  //----------------------------------------------------------------------------
  // 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 vtkLegendBoxActor::ReleaseGraphicsResources(vtkWindow *win)
  {
    if ( this->BackgroundActor )
    {
       this->BackgroundActor->ReleaseGraphicsResources(win);
    }
  
    if ( this->BorderActor )
    {
       this->BorderActor->ReleaseGraphicsResources(win);
    }
  
    if ( this->BoxActor )
    {
       this->BoxActor->ReleaseGraphicsResources(win);
    }
  
    for (int i=0; i < this->Size; i++)
    {
      this->TextActor[i]->ReleaseGraphicsResources(win);
      this->SymbolActor[i]->ReleaseGraphicsResources(win);
      this->IconActor[i]->ReleaseGraphicsResources(win);
    }
  }
  
  //----------------------------------------------------------------------------
  int vtkLegendBoxActor::RenderOverlay(vtkViewport *viewport)
  {
    if ( this->NumberOfEntries <= 0 )
    {
      return 0;
    }
  
    int renderedSomething = 0;
    if ( this->BackgroundActor && this->UseBackground )
    {
      this->BackgroundActor->RenderOverlay(viewport);
    }
  
    if ( this->Border )
    {
      renderedSomething += this->BorderActor->RenderOverlay(viewport);
    }
  
    if ( this->Box )
    {
      renderedSomething += this->BoxActor->RenderOverlay(viewport);
    }
  
    if ( this->LegendEntriesVisible )
    {
      for (int i=0; i<this->NumberOfEntries; i++)
      {
        if ( this->Symbol[i] )
        {
          renderedSomething += this->SymbolActor[i]->RenderOverlay(viewport);
        }
        if ( this->IconImage[i] )
        {
          renderedSomething += this->IconActor[i]->RenderOverlay(viewport);
        }
  
        renderedSomething += this->TextActor[i]->RenderOverlay(viewport);
      }
    }
  
    return renderedSomething;
  }
  
  //----------------------------------------------------------------------------
  int vtkLegendBoxActor::RenderOpaqueGeometry(vtkViewport *viewport)
  {
    int i;
    double symbolSize;
  
    if ( this->NumberOfEntries <= 0 )
    {
      return 0;
    }
  
    if (!this->EntryTextProperty)
    {
      vtkErrorMacro(<<"Need entry text property to render legend box actor");
      return 0;
    }
  
    // Check to see whether we have to rebuild everything
    int *vsize = viewport->GetSize();
    if (this->GetMTime() > this->BuildTime ||
        this->EntryTextProperty->GetMTime()  > this->BuildTime ||
        vsize[0] != this->CachedSize[0] || vsize[1] != this->CachedSize[1] )
    {
      vtkDebugMacro(<<"Rebuilding text");
      this->CachedSize[0] = vsize[0];
      this->CachedSize[1] = vsize[1];
  
      // If text prop has changed, recopy it to all mappers
      // We have to use shallow copy since the color of each text prop
      // can be overridden
  
      if (this->EntryTextProperty->GetMTime()  > this->BuildTime)
      {
        for (i = 0; i < this->NumberOfEntries; i++)
        {
          this->TextMapper[i]->GetTextProperty()->ShallowCopy(
            this->EntryTextProperty);
        }
      }
  
      //Get position information
      int *x1, *x2;
      double p1[3], p2[3];
      x1 = this->PositionCoordinate->GetComputedViewportValue(viewport);
      x2 = this->Position2Coordinate->GetComputedViewportValue(viewport);
      p1[0] = (double)x1[0]; p1[1] = (double)x1[1]; p1[2] = 0.0;
      p2[0] = (double)x2[0]; p2[1] = (double)x2[1]; p2[2] = 0.0;
  
      //Compute spacing...trying to keep things proportional
      //
      //Find the longest string and symbol width ratio
      int length, maxLength;
      int maxTextMapper = 0;
      int tempi[2], fontSize;
      double sf, twr, swr;
      const double *bounds;
      bool iconExists   (false);
      bool symbolExists (false);
  
      for (swr=0.0, maxLength=i=0; i<this->NumberOfEntries; i++)
      {
        this->TextMapper[i]->GetTextProperty()->SetFontSize(12);
        length = this->TextMapper[i]->GetWidth(viewport);
        if ( length > maxLength )
        {
          maxLength = length;
          maxTextMapper = i;
        }
  
        if ( this->Symbol[i] ) //if there is a symbol
        {
          symbolExists = true;
          //this->Symbol[i]->Update();
          bounds = this->Symbol[i]->GetBounds();
          if ( (bounds[3]-bounds[2]) == 0.0 )
          {
            sf = 1.0;
          }
          else
          {
            sf = (bounds[1]-bounds[0]) / (bounds[3]-bounds[2]);
          }
          if ( sf > swr )
          {
            swr = sf;
          }
        }//if symbol defined
  
          // We pick the one with highest ratio if both symbol and icon
          // exists.
          if(this->IconImage[i])
          {
            iconExists = true;
  
            bounds = this->IconImage[i]->GetBounds();
            if ( (bounds[3]-bounds[2]) == 0.0 )
            {
              sf = 1.0;
            }
            else
            {
              sf = (bounds[1]-bounds[0]) / (bounds[3]-bounds[2]);
            }
            if ( sf > swr )
            {
              swr = sf;
            }
          } // if icon defined.
      }
  
      //Compute the final proportion (symbol width to text width)
      fontSize = 12;
      this->TextMapper[maxTextMapper]->GetTextProperty()->SetFontSize(fontSize);
      this->TextMapper[maxTextMapper]->GetSize(viewport,tempi);
  
      if(maxLength>0) // make sure that tempi is not 0, to avoid a
        // divide-by-zero floating-point exception.
      {
        twr = (double)tempi[0]/tempi[1];
        symbolSize = swr / (swr + twr);
      }
      else
      {
        symbolSize=0;
      }
  
      if(iconExists && symbolExists)
      {
        symbolSize *= 2;
      }
  
      //Okay, now that the proportions are okay, let's size everything
      //First the text
      int size[2];
      size[0] = (int)((1.0-symbolSize)*(p2[0] - p1[0] - 2.0*this->Padding));
      size[1] = (int)((p2[1] - p1[1] - 2.0*this->Padding)/this->NumberOfEntries);
  
      fontSize = this->TextMapper[maxTextMapper]->SetConstrainedFontSize(
        viewport, size[0], size[1]);
      this->TextMapper[maxTextMapper]->GetSize(viewport,tempi);
  
      // don't draw anything if it's too small
      if ( size[1] > 0 && fontSize > 0)
      {
        this->LegendEntriesVisible = 1;
      }
      else
      {
        this->LegendEntriesVisible = 0;
      }
  
      //Border and box - may adjust spacing based on font size relationship
      //to the proportions relative to the border
      //
      if (this->Border || this->Box)
      {
        //adjust the border/box placement if too much whitespace
        if ( !this->LockBorder && tempi[0] < size[0] )
        {
          p2[0] = p1[0] + 2. * this->Padding
            + symbolSize * ( p2[0] - p1[0] - 2. * this->Padding ) + tempi[0];
        }
        vtkPoints *pts = this->BorderPolyData->GetPoints();
        pts->SetPoint( 0, p1 );
        pts->SetPoint(1, p2[0], p1[1], 0. );
        pts->SetPoint(2, p2[0], p2[1], 0. );
        pts->SetPoint(3, p1[0], p2[1], 0. );
        pts->Modified();
      }
  
      if ( this->UseBackground )
      {
        this->Background->SetOrigin( p1[0], p1[1], 0. );
        this->Background->SetPoint1( p2[0], p1[1], 0. );
        this->Background->SetPoint2( p1[0], p2[1], 0. );
  
        this->BackgroundMapper->SetInputConnection( this->Background->GetOutputPort() );
        this->BackgroundActor->GetProperty()->SetOpacity( this->BackgroundOpacity );
        this->BackgroundActor->GetProperty()->SetColor( this->BackgroundColor );
      }
  
      if ( this->Border )
      {
        this->BorderActor->SetProperty( this->GetProperty() );
      }
  
      //Place text strings
      double color[3];
      double posY;
      double posX = p1[0] + this->Padding +
                   symbolSize*(p2[0] - p1[0] - 2.0*this->Padding);
      for (i=0; i<this->NumberOfEntries; i++)
      {
        posY = p2[1] - this->Padding - (double)i*size[1] - 0.5*size[1];
        this->TextActor[i]->SetPosition(posX,posY);
        this->TextMapper[i]->GetTextProperty()->SetFontSize(fontSize);
        this->TextMapper[i]->GetTextProperty()->SetVerticalJustification(
              VTK_TEXT_CENTERED);
        this->TextMapper[i]->GetTextProperty()->SetJustification(VTK_TEXT_LEFT);
        this->Colors->GetTuple(i, color);
        if ( color[0] >= 0.0 && color[1] >= 0.0 && color[2] >= 0.0 )
        {
          this->TextMapper[i]->GetTextProperty()->SetColor(color[0],
                                                           color[1],
                                                           color[2]);
        }
      }
  
      double sizeFraction = 1.0;
  
      double symbolsPositionFraction = 0.5;
      double iconsPositionFraction   = 0.0;
  
      if(symbolExists && iconExists)
      {
        symbolsPositionFraction = 0.25;
        iconsPositionFraction   = 0.625;
  
        sizeFraction = 0.5;
      }
      else if(iconExists)
      {
        iconsPositionFraction = 0.5;
      }
      else
      {
        // Do nothing.
      }
  
      //Place symbols
      //
      //Find the x-y bounds of the symbols...we'll be scaling these as well
      size[0] = (int)(sizeFraction * symbolSize*(p2[0] - p1[0] - 2.0*this->Padding));
      posX = p1[0] + this->Padding +
                   symbolsPositionFraction * symbolSize*(p2[0] - p1[0] - 2.0*this->Padding);
      for (i=0; i<this->NumberOfEntries; i++)
      {
        if ( this->Symbol[i] )
        {
          this->SymbolTransform[i]->SetInputData(this->Symbol[i]);
          bounds = this->Symbol[i]->GetBounds();
  
          if ( (bounds[1]-bounds[0]) == 0.0 )
          {
            sf = VTK_DOUBLE_MAX;
          }
          else
          {
            sf = size[0]/(bounds[1]-bounds[0]);
          }
  
          if ( (bounds[3]-bounds[2]) == 0.0 )
          {
            if ( sf >= VTK_DOUBLE_MAX )
            {
              sf = 1.0;
            }
          }
          else if ( (size[1]/(bounds[3]-bounds[2])) < sf )
          {
            sf = size[1]/(bounds[3]-bounds[2]);
          }
  
          posY = p2[1] - this->Padding - (double)i*size[1] - 0.5*size[1] -
                         0.25*tempi[1];
          this->Transform[i]->Identity();
          this->Transform[i]->Translate(posX, posY, 0.0);
          this->Transform[i]->Scale(0.5*sf, 0.5*sf, 1);
          this->SymbolMapper[i]->SetScalarVisibility(this->ScalarVisibility);
          this->SymbolActor[i]->GetProperty()->DeepCopy(this->GetProperty());
          this->Colors->GetTuple(i, color);
          if ( color[0] >= 0.0 && color[1] >= 0.0 && color[2] >= 0.0 )
          {
            this->SymbolActor[i]->GetProperty()->SetColor(color[0],
                                                          color[1],
                                                          color[2]);
          }
        }//if symbol defined
        else
        {
          std::cout << "Symbol is not defined: " << std::endl;
        }
      }
  
        // Place icons.
        size[0] = (int)(sizeFraction * symbolSize*(p2[0] - p1[0] - 2.0*this->Padding));
        posX = p1[0] + this->Padding +
                     iconsPositionFraction * symbolSize*(p2[0] - p1[0] - 2.0*this->Padding);
        for (i=0; i<this->NumberOfEntries; i++)
        {
          if ( this->IconImage[i] )
          {
            vtkTexture *texture (vtkTexture::New());
            texture->SetInputData(this->IconImage[i]);
            this->IconActor[i]->SetTexture(texture);
            texture->Delete();
            this->Icon[i]->Update();
            this->IconTransformFilter[i]->SetInputConnection(
              this->Icon[i]->GetOutputPort());
            this->IconTransformFilter[i]->Update();
            bounds = this->Icon[i]->GetOutput(0)->GetBounds();
  
            if ( (bounds[1]-bounds[0]) == 0.0 )
            {
              sf = VTK_DOUBLE_MAX;
            }
            else
            {
              sf = size[0]/(bounds[1]-bounds[0]);
            }
  
            if ( (bounds[3]-bounds[2]) == 0.0 )
            {
              if ( sf >= VTK_DOUBLE_MAX )
              {
                sf = 1.0;
              }
            }
            else if ( (size[1]/(bounds[3]-bounds[2])) < sf )
            {
              sf = size[1]/(bounds[3]-bounds[2]);
            }
  
            posY = p2[1] - this->Padding - (double)i*size[1] - 0.5*size[1] -
                           0.25*tempi[1];
            this->IconTransform[i]->Identity();
            this->IconTransform[i]->Translate(posX, posY, 0.0);
            this->IconTransform[i]->Scale(0.5 * sf, 0.5 * sf, 1);
            this->IconMapper[i]->SetScalarVisibility(this->ScalarVisibility);
          }// If icon is defined.
        }
      this->BuildTime.Modified();
    }//rebuild legend box
  
    //Okay, now we're ready to render something
    //Border
    int renderedSomething = 0;
    if ( this->BackgroundActor && this->UseBackground )
    {
      this->BackgroundActor->RenderOpaqueGeometry(viewport);
    }
  
    if ( this->Border )
    {
      renderedSomething += this->BorderActor->RenderOpaqueGeometry(viewport);
    }
  
    if ( this->Box )
    {
      renderedSomething += this->BoxActor->RenderOpaqueGeometry(viewport);
    }
  
    if ( this->LegendEntriesVisible )
    {
      for (i=0; i<this->NumberOfEntries; i++)
      {
        if ( this->Symbol[i] )
        {
          renderedSomething += this->SymbolActor[i]->RenderOpaqueGeometry(viewport);
        }
        if( this->IconImage[i])
        {
          renderedSomething += this->IconActor[i]->RenderOpaqueGeometry(viewport);
        }
        renderedSomething += this->TextActor[i]->RenderOpaqueGeometry(viewport);
      }
    }
  
    return renderedSomething;
  }
  
  //-----------------------------------------------------------------------------
  // Description:
  // Does this prop have some translucent polygonal geometry?
  vtkTypeBool vtkLegendBoxActor::HasTranslucentPolygonalGeometry()
  {
    return 0;
  }
  
  //----------------------------------------------------------------------------
  void vtkLegendBoxActor::PrintSelf(ostream& os, vtkIndent indent)
  {
    this->Superclass::PrintSelf(os,indent);
  
    if (this->EntryTextProperty)
    {
      os << indent << "Entry Text Property:\n";
      this->EntryTextProperty->PrintSelf(os,indent.GetNextIndent());
    }
    else
    {
      os << indent << "Entry Text Property: (none)\n";
    }
  
    os << indent << "Number Of Entries: " << this->NumberOfEntries << "\n";
  
    os << indent << "Scalar Visibility: "
       << (this->ScalarVisibility ? "On\n" : "Off\n");
    os << indent << "Padding: " << this->Padding << "\n";
    os << indent << "Border: " << (this->Border ? "On\n" : "Off\n");
    os << indent << "Box: " << (this->Box ? "On\n" : "Off\n");
    os << indent << "LockBorder: " << (this->LockBorder ? "On\n" : "Off\n");
  
    os << indent << "UseBackgroud: " << (this->UseBackground ? "On\n" : "Off\n");
    os << indent << "BackgroundOpacity: " << this->BackgroundOpacity << "\n";
  
    os << indent << "BackgroundColor: (" << this->BackgroundColor[0] << ", "
      << this->BackgroundColor[1] << ", " << this->BackgroundColor[2] << ")\n";
  }
  
  //----------------------------------------------------------------------------
  void vtkLegendBoxActor::ShallowCopy(vtkProp *prop)
  {
    vtkLegendBoxActor *a = vtkLegendBoxActor::SafeDownCast(prop);
    if ( a != nullptr )
    {
      this->SetPosition2(a->GetPosition2());
      this->SetEntryTextProperty(a->GetEntryTextProperty());
      this->SetBorder(a->GetBorder());
      this->SetLockBorder(a->GetLockBorder());
      this->SetPadding(a->GetPadding());
      this->SetScalarVisibility(a->GetScalarVisibility());
      this->SetNumberOfEntries(a->GetNumberOfEntries());
      for (int i=0; i<this->NumberOfEntries; i++)
      {
        this->SetEntrySymbol(i,a->GetEntrySymbol(i));
        this->SetEntryString(i,a->GetEntryString(i));
        this->SetEntryColor(i,a->GetEntryColor(i));
      }
    }
  
    // Now do superclass
    this->vtkActor2D::ShallowCopy(prop);
  }
  