<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMapper.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkMapper.h"
#include "vtkLookupTable.h"

// Initialize static member that controls global immediate mode rendering
static int vtkMapperGlobalImmediateModeRendering = 0;

// Initialize static member that controls global coincidence resolution
static int vtkMapperGlobalResolveCoincidentTopology = VTK_RESOLVE_OFF;
static double vtkMapperGlobalResolveCoincidentTopologyZShift = 0.01;
static float vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = 1.0;
static float vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits = 1.0;

// Construct with initial range (0,1).
vtkMapper::vtkMapper()
{
  this->Colors = NULL;

  this->LookupTable = NULL;

  this->ScalarVisibility = 1;
  this->ScalarRange[0] = 0.0; this->ScalarRange[1] = 1.0;
  this->UseLookupTableScalarRange = 0;

  this->ImmediateModeRendering = 0;

  this->ColorMode = VTK_COLOR_MODE_DEFAULT;
  this->ScalarMode = VTK_SCALAR_MODE_DEFAULT;

  this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = -1.0;
  this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = 1.0;
  this->Center[0] = this->Center[1] = this->Center[2] = 0.0;

  this->RenderTime = 0.0;

  strcpy(this->ArrayName, "");
  this->ArrayId = -1;
  this->ArrayComponent = -1;
  this->ArrayAccessMode = -1;
}

vtkMapper::~vtkMapper()
{
  if (this->LookupTable)
    {
    this->LookupTable->UnRegister(this);
    }
  if ( this->Colors != NULL )
    {
    this->Colors->UnRegister(this);
    }
}

// Get the bounds for the input of this mapper as
// (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
float *vtkMapper::GetBounds()
{
  static float bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0};

  if ( ! this->GetInput() )
    {
    return bounds;
    }
  else
    {
    this->Update();
    this->GetInput()->GetBounds(this->Bounds);
    return this->Bounds;
    }
}

vtkDataSet *vtkMapper::GetInput()
{
  if (this->NumberOfInputs < 1)
    {
    return NULL;
    }

  return (vtkDataSet *)(this->Inputs[0]);
}

void vtkMapper::SetGlobalImmediateModeRendering(int val)
{
  if (val == vtkMapperGlobalImmediateModeRendering)
    {
    return;
    }
  vtkMapperGlobalImmediateModeRendering = val;
}

int vtkMapper::GetGlobalImmediateModeRendering()
{
  return vtkMapperGlobalImmediateModeRendering;
}

void vtkMapper::SetResolveCoincidentTopology(int val)
{
  if (val == vtkMapperGlobalResolveCoincidentTopology)
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopology = val;
}

int vtkMapper::GetResolveCoincidentTopology()
{
  return vtkMapperGlobalResolveCoincidentTopology;
}

void vtkMapper::SetResolveCoincidentTopologyToDefault()
{
  vtkMapperGlobalResolveCoincidentTopology = VTK_RESOLVE_OFF;
}

void vtkMapper::SetResolveCoincidentTopologyZShift(double val)
{
  if (val == vtkMapperGlobalResolveCoincidentTopologyZShift)
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopologyZShift = val;
}

double vtkMapper::GetResolveCoincidentTopologyZShift()
{
  return vtkMapperGlobalResolveCoincidentTopologyZShift;
}

void vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(
                                            float factor, float units)
{
  if (factor == vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor &&
      units == vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits )
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = factor;
  vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = units;
}

void vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(
                           float& factor, float& units)
{
  factor = vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor;
  units = vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits;
}

// Overload standard modified time function. If lookup table is modified,
// then this object is modified as well.
unsigned long vtkMapper::GetMTime()
{
  unsigned long mTime=this->MTime.GetMTime();
  unsigned long lutMTime;

  if ( this->LookupTable != NULL )
    {
    lutMTime = this->LookupTable->GetMTime();
    mTime = ( lutMTime > mTime ? lutMTime : mTime );
    }

  return mTime;
}

void vtkMapper::ShallowCopy(vtkMapper *m)
{
  this->SetLookupTable(m->GetLookupTable());
  this->SetClippingPlanes(m->GetClippingPlanes());
  this->SetScalarVisibility(m->GetScalarVisibility());
  this->SetScalarRange(m->GetScalarRange());
  this->SetColorMode(m->GetColorMode());
  this->SetScalarMode(m->GetScalarMode());
  this->SetImmediateModeRendering(m->GetImmediateModeRendering());
}

// a side effect of this is that this->Colors is also set
// to the return value
vtkScalars *vtkMapper::GetColors()
{
  vtkScalars *scalars = NULL;
  vtkDataArray *dataArray=0;
  vtkPointData *pd;
  vtkCellData *cd;
  vtkIdType i, numScalars;

  // make sure we have an input
  if (!this->GetInput())
    {
    return NULL;
    }

  // get and scalar data according to scalar mode
  if ( this->ScalarMode == VTK_SCALAR_MODE_DEFAULT )
    {
    scalars = this->GetInput()->GetPointData()->GetScalars();
    if (!scalars)
      {
      scalars = this->GetInput()->GetCellData()->GetScalars();
      }
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA )
    {
    scalars = this->GetInput()->GetPointData()->GetScalars();
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA )
    {
    scalars = this->GetInput()->GetCellData()->GetScalars();
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA )
    {
    pd = this->GetInput()->GetPointData();
    if (pd)
      {
      if (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
	{
	dataArray = pd->GetArray(this->ArrayId);
	}
      else
	{
	dataArray = pd->GetArray(this->ArrayName);
	}
      }

    if (dataArray &&
        (this->ArrayComponent < dataArray->GetNumberOfComponents()))
      {
      scalars = vtkScalars::New();
      numScalars = dataArray->GetNumberOfTuples();
      scalars->SetNumberOfScalars(numScalars);
      if (dataArray->GetNumberOfComponents() == 1)
        {
        scalars->SetData(dataArray);
        }
      else
        { // I do not know how useful it is to color by a componenet.
        // This could probably be done with out a copy
        // by using active component.
        for (i = 0; i < numScalars; i++)
          {
          scalars->
            InsertScalar(i, dataArray->GetComponent(i, this->ArrayComponent));
          }
        }
      }
    else
      {
      vtkWarningMacro(<<"Data array (used for coloring) not found");
      }
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA )
    {
    cd = this->GetInput()->GetCellData();
    if (cd)
      {
      if (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
	{
	dataArray = cd->GetArray(this->ArrayId);
	}
      else
	{
	dataArray = cd->GetArray(this->ArrayName);
	}
      }

    if (dataArray &&
        (this->ArrayComponent < dataArray->GetNumberOfComponents()))
      {
      scalars = vtkScalars::New();
      numScalars = dataArray->GetNumberOfTuples();
      scalars->SetNumberOfScalars(numScalars);
      if (dataArray->GetNumberOfComponents() == 1)
        {
        scalars->SetData(dataArray);
        }
      else
        { // I do not know how useful it is to color by a componenet.
        // This could probably be done with out a copy
        // by using active component.
        for (i = 0; i < numScalars; i++)
          {
          scalars->
            InsertScalar(i, dataArray->GetComponent(i, this->ArrayComponent));
          }
        }
      }
    else
      {
      vtkWarningMacro(<<"Data array (used for coloring) not found");
      }
    }

  // do we have any scalars ?
  if (scalars && this->ScalarVisibility)
    {
    // if the scalars have a lookup table use it instead
    if (scalars->GetLookupTable())
      {
      this->SetLookupTable(scalars->GetLookupTable());
      }
    else
      {
      // make sure we have a lookup table
      if ( this->LookupTable == NULL )
	      {
	      this->CreateDefaultLookupTable();
	      }
      this->LookupTable->Build();
      }

    // Setup mapper/scalar object for color generation
    if (!this->UseLookupTableScalarRange)
      {
      this->LookupTable->SetRange(this->ScalarRange);
      }

    if (this->Colors)
      {
      this->Colors->UnRegister(this);
      }
    this->Colors = scalars;
    this->Colors->Register(this);
    this->Colors->InitColorTraversal(1.0, this->LookupTable, this->ColorMode);
    }

  else //scalars not visible
    {
    if ( this->Colors )
      {
      this->Colors->UnRegister(this);
      }
    this->Colors = NULL;
    }

  if (((this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA) ||
       (this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA)) &&
      scalars)
    {
    scalars->Delete();
    }

  return this->Colors;
}

void vtkMapper::ColorByArrayComponent(int arrayNum, int component)
{
  if (this->ArrayId == arrayNum && component == this->ArrayComponent &&
      this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
    {
    return;
    }
  this->Modified();

  this->ArrayId = arrayNum;
  this->ArrayComponent = component;
  this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID;
}

void vtkMapper::ColorByArrayComponent(char* arrayName, int component)
{
  if (strcmp(this->ArrayName, arrayName) == 0 &&
      component == this->ArrayComponent &&
      this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
    {
    return;
    }
  this->Modified();

  strcpy(this->ArrayName, arrayName);
  this->ArrayComponent = component;
  this->ArrayAccessMode = VTK_GET_ARRAY_BY_NAME;
}

// Specify a lookup table for the mapper to use.
void vtkMapper::SetLookupTable(vtkScalarsToColors *lut)
{
  if ( this->LookupTable != lut )
    {
    if ( this->LookupTable)
      {
      this->LookupTable->UnRegister(this);
      }
    this->LookupTable = lut;
    if (lut)
      {
      lut->Register(this);
      }
    this->Modified();
    }
}

vtkScalarsToColors *vtkMapper::GetLookupTable()
{
  if ( this->LookupTable == NULL )
    {
    this->CreateDefaultLookupTable();
    }
  return this->LookupTable;
}

void vtkMapper::CreateDefaultLookupTable()
{
  if ( this->LookupTable)
    {
    this->LookupTable->UnRegister(this);
    }
  this->LookupTable = vtkLookupTable::New();
}

// Update the network connected to this mapper.
void vtkMapper::Update()
{
  if ( this->GetInput() )
    {
    this->GetInput()->Update();
    }
}

// Return the method of coloring scalar data.
const char *vtkMapper::GetColorModeAsString(void)
{
  if ( this->ColorMode == VTK_COLOR_MODE_LUMINANCE )
    {
    return "Luminance";
    }
  else if ( this->ColorMode == VTK_COLOR_MODE_MAP_SCALARS )
    {
    return "MapScalars";
    }
  else
    {
    return "Default";
    }
}

// Return the method for obtaining scalar data.
const char *vtkMapper::GetScalarModeAsString(void)
{
  if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA )
    {
    return "UseCellData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA )
    {
    return "UsePointData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA )
    {
    return "UsePointFieldData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA )
    {
    return "UseCellFieldData";
    }
  else
    {
    return "Default";
    }
}

void vtkMapper::PrintSelf(ostream& os, vtkIndent indent)
{
  this->vtkAbstractMapper3D::PrintSelf(os,indent);

  if ( this->LookupTable )
    {
    os << indent << "Lookup Table:\n";
    this->LookupTable->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Lookup Table: (none)\n";
    }

  os << indent << "Immediate Mode Rendering: "
    << (this->ImmediateModeRendering ? "On\n" : "Off\n");
  os << indent << "Global Immediate Mode Rendering: " <<
    (vtkMapperGlobalImmediateModeRendering ? "On\n" : "Off\n");

  os << indent << "Scalar Visibility: "
    << (this->ScalarVisibility ? "On\n" : "Off\n");

  float *range = this->GetScalarRange();
  os << indent << "Scalar Range: (" << range[0] << ", " << range[1] << ")\n";

  os << indent << "UseLookupTableScalarRange: " << this->UseLookupTableScalarRange << "\n";

  os << indent << "Color Mode: " << this->GetColorModeAsString() << endl;

  os << indent << "Scalar Mode: " << this->GetScalarModeAsString() << endl;

  os << indent << "RenderTime: " << this->RenderTime << endl;

  os << indent << "Resolve Coincident Topology: ";
  if ( vtkMapperGlobalResolveCoincidentTopology == VTK_RESOLVE_OFF )
    {
    os << "Off" << endl;
    }
  else if ( vtkMapperGlobalResolveCoincidentTopology == VTK_RESOLVE_POLYGON_OFFSET )
    {
    os << "Polygon Offset" << endl;
    }
  else
    {
    os << "Shift Z-Buffer" << endl;
    }
}
<commit_msg>ENH:No need to check if point data and cell data exists; it is guaranteed to always exist<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMapper.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkMapper.h"
#include "vtkLookupTable.h"

// Initialize static member that controls global immediate mode rendering
static int vtkMapperGlobalImmediateModeRendering = 0;

// Initialize static member that controls global coincidence resolution
static int vtkMapperGlobalResolveCoincidentTopology = VTK_RESOLVE_OFF;
static double vtkMapperGlobalResolveCoincidentTopologyZShift = 0.01;
static float vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = 1.0;
static float vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits = 1.0;

// Construct with initial range (0,1).
vtkMapper::vtkMapper()
{
  this->Colors = NULL;

  this->LookupTable = NULL;

  this->ScalarVisibility = 1;
  this->ScalarRange[0] = 0.0; this->ScalarRange[1] = 1.0;
  this->UseLookupTableScalarRange = 0;

  this->ImmediateModeRendering = 0;

  this->ColorMode = VTK_COLOR_MODE_DEFAULT;
  this->ScalarMode = VTK_SCALAR_MODE_DEFAULT;

  this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = -1.0;
  this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = 1.0;
  this->Center[0] = this->Center[1] = this->Center[2] = 0.0;

  this->RenderTime = 0.0;

  strcpy(this->ArrayName, "");
  this->ArrayId = -1;
  this->ArrayComponent = -1;
  this->ArrayAccessMode = -1;
}

vtkMapper::~vtkMapper()
{
  if (this->LookupTable)
    {
    this->LookupTable->UnRegister(this);
    }
  if ( this->Colors != NULL )
    {
    this->Colors->UnRegister(this);
    }
}

// Get the bounds for the input of this mapper as
// (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
float *vtkMapper::GetBounds()
{
  static float bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0};

  if ( ! this->GetInput() )
    {
    return bounds;
    }
  else
    {
    this->Update();
    this->GetInput()->GetBounds(this->Bounds);
    return this->Bounds;
    }
}

vtkDataSet *vtkMapper::GetInput()
{
  if (this->NumberOfInputs < 1)
    {
    return NULL;
    }

  return (vtkDataSet *)(this->Inputs[0]);
}

void vtkMapper::SetGlobalImmediateModeRendering(int val)
{
  if (val == vtkMapperGlobalImmediateModeRendering)
    {
    return;
    }
  vtkMapperGlobalImmediateModeRendering = val;
}

int vtkMapper::GetGlobalImmediateModeRendering()
{
  return vtkMapperGlobalImmediateModeRendering;
}

void vtkMapper::SetResolveCoincidentTopology(int val)
{
  if (val == vtkMapperGlobalResolveCoincidentTopology)
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopology = val;
}

int vtkMapper::GetResolveCoincidentTopology()
{
  return vtkMapperGlobalResolveCoincidentTopology;
}

void vtkMapper::SetResolveCoincidentTopologyToDefault()
{
  vtkMapperGlobalResolveCoincidentTopology = VTK_RESOLVE_OFF;
}

void vtkMapper::SetResolveCoincidentTopologyZShift(double val)
{
  if (val == vtkMapperGlobalResolveCoincidentTopologyZShift)
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopologyZShift = val;
}

double vtkMapper::GetResolveCoincidentTopologyZShift()
{
  return vtkMapperGlobalResolveCoincidentTopologyZShift;
}

void vtkMapper::SetResolveCoincidentTopologyPolygonOffsetParameters(
                                            float factor, float units)
{
  if (factor == vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor &&
      units == vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits )
    {
    return;
    }
  vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = factor;
  vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor = units;
}

void vtkMapper::GetResolveCoincidentTopologyPolygonOffsetParameters(
                           float& factor, float& units)
{
  factor = vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetFactor;
  units = vtkMapperGlobalResolveCoincidentTopologyPolygonOffsetUnits;
}

// Overload standard modified time function. If lookup table is modified,
// then this object is modified as well.
unsigned long vtkMapper::GetMTime()
{
  unsigned long mTime=this->MTime.GetMTime();
  unsigned long lutMTime;

  if ( this->LookupTable != NULL )
    {
    lutMTime = this->LookupTable->GetMTime();
    mTime = ( lutMTime > mTime ? lutMTime : mTime );
    }

  return mTime;
}

void vtkMapper::ShallowCopy(vtkMapper *m)
{
  this->SetLookupTable(m->GetLookupTable());
  this->SetClippingPlanes(m->GetClippingPlanes());
  this->SetScalarVisibility(m->GetScalarVisibility());
  this->SetScalarRange(m->GetScalarRange());
  this->SetColorMode(m->GetColorMode());
  this->SetScalarMode(m->GetScalarMode());
  this->SetImmediateModeRendering(m->GetImmediateModeRendering());
}

// a side effect of this is that this->Colors is also set
// to the return value
vtkScalars *vtkMapper::GetColors()
{
  vtkScalars *scalars = NULL;
  vtkDataArray *dataArray=0;
  vtkPointData *pd;
  vtkCellData *cd;
  vtkIdType i, numScalars;

  // make sure we have an input
  if (!this->GetInput())
    {
    return NULL;
    }

  // get and scalar data according to scalar mode
  if ( this->ScalarMode == VTK_SCALAR_MODE_DEFAULT )
    {
    scalars = this->GetInput()->GetPointData()->GetScalars();
    if (!scalars)
      {
      scalars = this->GetInput()->GetCellData()->GetScalars();
      }
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA )
    {
    scalars = this->GetInput()->GetPointData()->GetScalars();
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA )
    {
    scalars = this->GetInput()->GetCellData()->GetScalars();
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA )
    {
    pd = this->GetInput()->GetPointData();
    if (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
      {
      dataArray = pd->GetArray(this->ArrayId);
      }
    else
      {
      dataArray = pd->GetArray(this->ArrayName);
      }

    if (dataArray &&
        (this->ArrayComponent < dataArray->GetNumberOfComponents()))
      {
      scalars = vtkScalars::New();
      numScalars = dataArray->GetNumberOfTuples();
      scalars->SetNumberOfScalars(numScalars);
      if (dataArray->GetNumberOfComponents() == 1)
        {
        scalars->SetData(dataArray);
        }
      else
        { // I do not know how useful it is to color by a componenet.
        // This could probably be done with out a copy
        // by using active component.
        for (i = 0; i < numScalars; i++)
          {
          scalars->
            InsertScalar(i, dataArray->GetComponent(i, this->ArrayComponent));
          }
        }
      }
    else
      {
      vtkWarningMacro(<<"Data array (used for coloring) not found");
      }
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA )
    {
    cd = this->GetInput()->GetCellData();
    if (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
      {
      dataArray = cd->GetArray(this->ArrayId);
      }
    else
      {
      dataArray = cd->GetArray(this->ArrayName);
      }

    if (dataArray &&
        (this->ArrayComponent < dataArray->GetNumberOfComponents()))
      {
      scalars = vtkScalars::New();
      numScalars = dataArray->GetNumberOfTuples();
      scalars->SetNumberOfScalars(numScalars);
      if (dataArray->GetNumberOfComponents() == 1)
        {
        scalars->SetData(dataArray);
        }
      else
        { // I do not know how useful it is to color by a componenet.
        // This could probably be done with out a copy
        // by using active component.
        for (i = 0; i < numScalars; i++)
          {
          scalars->
            InsertScalar(i, dataArray->GetComponent(i, this->ArrayComponent));
          }
        }
      }
    else
      {
      vtkWarningMacro(<<"Data array (used for coloring) not found");
      }
    }

  // do we have any scalars ?
  if (scalars && this->ScalarVisibility)
    {
    // if the scalars have a lookup table use it instead
    if (scalars->GetLookupTable())
      {
      this->SetLookupTable(scalars->GetLookupTable());
      }
    else
      {
      // make sure we have a lookup table
      if ( this->LookupTable == NULL )
	      {
	      this->CreateDefaultLookupTable();
	      }
      this->LookupTable->Build();
      }

    // Setup mapper/scalar object for color generation
    if (!this->UseLookupTableScalarRange)
      {
      this->LookupTable->SetRange(this->ScalarRange);
      }

    if (this->Colors)
      {
      this->Colors->UnRegister(this);
      }
    this->Colors = scalars;
    this->Colors->Register(this);
    this->Colors->InitColorTraversal(1.0, this->LookupTable, this->ColorMode);
    }

  else //scalars not visible
    {
    if ( this->Colors )
      {
      this->Colors->UnRegister(this);
      }
    this->Colors = NULL;
    }

  if (((this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA) ||
       (this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA)) &&
      scalars)
    {
    scalars->Delete();
    }

  return this->Colors;
}

void vtkMapper::ColorByArrayComponent(int arrayNum, int component)
{
  if (this->ArrayId == arrayNum && component == this->ArrayComponent &&
      this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
    {
    return;
    }
  this->Modified();

  this->ArrayId = arrayNum;
  this->ArrayComponent = component;
  this->ArrayAccessMode = VTK_GET_ARRAY_BY_ID;
}

void vtkMapper::ColorByArrayComponent(char* arrayName, int component)
{
  if (strcmp(this->ArrayName, arrayName) == 0 &&
      component == this->ArrayComponent &&
      this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID)
    {
    return;
    }
  this->Modified();

  strcpy(this->ArrayName, arrayName);
  this->ArrayComponent = component;
  this->ArrayAccessMode = VTK_GET_ARRAY_BY_NAME;
}

// Specify a lookup table for the mapper to use.
void vtkMapper::SetLookupTable(vtkScalarsToColors *lut)
{
  if ( this->LookupTable != lut )
    {
    if ( this->LookupTable)
      {
      this->LookupTable->UnRegister(this);
      }
    this->LookupTable = lut;
    if (lut)
      {
      lut->Register(this);
      }
    this->Modified();
    }
}

vtkScalarsToColors *vtkMapper::GetLookupTable()
{
  if ( this->LookupTable == NULL )
    {
    this->CreateDefaultLookupTable();
    }
  return this->LookupTable;
}

void vtkMapper::CreateDefaultLookupTable()
{
  if ( this->LookupTable)
    {
    this->LookupTable->UnRegister(this);
    }
  this->LookupTable = vtkLookupTable::New();
}

// Update the network connected to this mapper.
void vtkMapper::Update()
{
  if ( this->GetInput() )
    {
    this->GetInput()->Update();
    }
}

// Return the method of coloring scalar data.
const char *vtkMapper::GetColorModeAsString(void)
{
  if ( this->ColorMode == VTK_COLOR_MODE_LUMINANCE )
    {
    return "Luminance";
    }
  else if ( this->ColorMode == VTK_COLOR_MODE_MAP_SCALARS )
    {
    return "MapScalars";
    }
  else
    {
    return "Default";
    }
}

// Return the method for obtaining scalar data.
const char *vtkMapper::GetScalarModeAsString(void)
{
  if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA )
    {
    return "UseCellData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_DATA )
    {
    return "UsePointData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA )
    {
    return "UsePointFieldData";
    }
  else if ( this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA )
    {
    return "UseCellFieldData";
    }
  else
    {
    return "Default";
    }
}

void vtkMapper::PrintSelf(ostream& os, vtkIndent indent)
{
  this->vtkAbstractMapper3D::PrintSelf(os,indent);

  if ( this->LookupTable )
    {
    os << indent << "Lookup Table:\n";
    this->LookupTable->PrintSelf(os,indent.GetNextIndent());
    }
  else
    {
    os << indent << "Lookup Table: (none)\n";
    }

  os << indent << "Immediate Mode Rendering: "
    << (this->ImmediateModeRendering ? "On\n" : "Off\n");
  os << indent << "Global Immediate Mode Rendering: " <<
    (vtkMapperGlobalImmediateModeRendering ? "On\n" : "Off\n");

  os << indent << "Scalar Visibility: "
    << (this->ScalarVisibility ? "On\n" : "Off\n");

  float *range = this->GetScalarRange();
  os << indent << "Scalar Range: (" << range[0] << ", " << range[1] << ")\n";

  os << indent << "UseLookupTableScalarRange: " << this->UseLookupTableScalarRange << "\n";

  os << indent << "Color Mode: " << this->GetColorModeAsString() << endl;

  os << indent << "Scalar Mode: " << this->GetScalarModeAsString() << endl;

  os << indent << "RenderTime: " << this->RenderTime << endl;

  os << indent << "Resolve Coincident Topology: ";
  if ( vtkMapperGlobalResolveCoincidentTopology == VTK_RESOLVE_OFF )
    {
    os << "Off" << endl;
    }
  else if ( vtkMapperGlobalResolveCoincidentTopology == VTK_RESOLVE_POLYGON_OFFSET )
    {
    os << "Polygon Offset" << endl;
    }
  else
    {
    os << "Shift Z-Buffer" << endl;
    }
}
<|endoftext|>


<commit_before>#ifdef ENABLE_LLVM

#include "llvm/jit_block.hpp"
#include "llvm/jit_context.hpp"

#include "call_frame.hpp"
#include "stack_variables.hpp"

#include "instruments/profiler.hpp"

using namespace llvm;

namespace rubinius {
namespace jit {

  void BlockBuilder::setup() {
    Signature sig(ls_, "Object");
    sig << "VM";
    sig << "CallFrame";
    sig << "BlockEnvironment";
    sig << "Arguments";
    sig << "BlockInvocation";

    func = sig.function("");

    Function::arg_iterator ai = func->arg_begin();
    vm =   ai++; vm->setName("state");
    prev = ai++; prev->setName("previous");
    block_env = ai++; block_env->setName("env");
    args = ai++; args->setName("args");
    block_inv = ai++; block_inv->setName("invocation");

    BasicBlock* block = BasicBlock::Create(ls_->ctx(), "entry", func);
    b().SetInsertPoint(block);

    info_.set_function(func);
    info_.set_vm(vm);
    info_.set_args(args);
    info_.set_previous(prev);
    info_.set_entry(block);

    BasicBlock* body = BasicBlock::Create(ls_->ctx(), "block_body", func);

    pass_one(body);

    info_.set_counter(b().CreateAlloca(ls_->Int32Ty, 0, "counter_alloca"));

    // The 3 here is because we store {ip, sp, type} per unwind.
    info_.set_unwind_info(b().CreateAlloca(ls_->Int32Ty,
          ConstantInt::get(ls_->Int32Ty, rubinius::kMaxUnwindInfos * 3),
          "unwind_info"));

    valid_flag = b().CreateAlloca(ls_->Int1Ty, 0, "valid_flag");

    Value* cfstk = b().CreateAlloca(obj_type,
        ConstantInt::get(ls_->Int32Ty,
          (sizeof(CallFrame) / sizeof(Object*)) + vmm_->stack_size),
        "cfstk");

    call_frame = b().CreateBitCast(
        cfstk,
        llvm::PointerType::getUnqual(cf_type), "call_frame");

    info_.set_out_args(b().CreateAlloca(ls_->type("Arguments"), 0, "out_args"));

    if(ls_->include_profiling()) {
      method_entry_ = b().CreateAlloca(ls_->Int8Ty,
          ConstantInt::get(ls_->Int32Ty, sizeof(profiler::MethodEntry)),
          "method_entry");

      info_.set_profiling_entry(method_entry_);
    }

    info_.set_call_frame(call_frame);

    stk = b().CreateConstGEP1_32(cfstk, sizeof(CallFrame) / sizeof(Object*), "stack");

    info_.set_stack(stk);

    Value* var_mem = b().CreateAlloca(obj_type,
        ConstantInt::get(ls_->Int32Ty,
          (sizeof(StackVariables) / sizeof(Object*)) + vmm_->number_of_locals),
        "var_mem");

    vars = b().CreateBitCast(
        var_mem,
        llvm::PointerType::getUnqual(stack_vars_type), "vars");

    info_.set_variables(vars);

    initialize_frame(vmm_->stack_size);

    nil_stack(vmm_->stack_size, constant(Qnil, obj_type));

    setup_block_scope();

    if(ls_->include_profiling()) {
      Value* test = b().CreateLoad(ls_->profiling(), "profiling");

      BasicBlock* setup_profiling = BasicBlock::Create(ls_->ctx(), "setup_profiling", func);
      BasicBlock* cont = BasicBlock::Create(ls_->ctx(), "continue", func);

      b().CreateCondBr(test, setup_profiling, cont);

      b().SetInsertPoint(setup_profiling);

      Signature sig(ls_, ls_->VoidTy);
      sig << "VM";
      sig << llvm::PointerType::getUnqual(ls_->Int8Ty);
      sig << "BlockEnvironment";
      sig << "Module";
      sig << "CompiledMethod";

      Value* call_args[] = {
        vm,
        method_entry_,
        block_env,
        module_,
        method
      };

      sig.call("rbx_begin_profiling_block", call_args, 5, "", b());

      b().CreateBr(cont);

      b().SetInsertPoint(cont);
    }
    b().CreateBr(body);

    b().SetInsertPoint(body);
  }

  void BlockBuilder::setup_block_scope() {
    b().CreateStore(ConstantExpr::getNullValue(llvm::PointerType::getUnqual(vars_type)),
        get_field(vars, offset::vars_on_heap));
    Value* self = b().CreateLoad(
        get_field(block_inv, offset::blockinv_self),
        "invocation.self");

    b().CreateStore(self, get_field(vars, offset::vars_self));

    Value* inv_mod = b().CreateLoad(
        get_field(block_inv, offset::blockinv_module),
        "invocation.module");

    Value* creation_mod = b().CreateLoad(
        get_field(block_env, offset::blockenv_module),
        "env.module");

    Value* mod = b().CreateSelect(
        b().CreateICmpNE(inv_mod, ConstantExpr::getNullValue(inv_mod->getType())),
        inv_mod,
        creation_mod);

    module_ = mod;

    b().CreateStore(mod, get_field(vars, offset::vars_module));

    Value* blk = b().CreateLoad(get_field(top_scope, offset::varscope_block),
        "args.block");
    b().CreateStore(blk, get_field(vars, offset::vars_block));

    // We don't use top_scope here because of nested blocks. Parent MUST be
    // the scope the block was created in, not the top scope for depth
    // variables to work.
    Value* be_scope = b().CreateLoad(
        get_field(block_env, offset::blockenv_scope),
        "env.scope");

    b().CreateStore(be_scope, get_field(vars, offset::vars_parent));
    b().CreateStore(constant(Qnil, obj_type), get_field(vars, offset::vars_last_match));

    nil_locals();
  }

  void BlockBuilder::initialize_frame(int stack_size) {
    Value* cm_gep = get_field(call_frame, offset::cf_cm);

    method = b().CreateLoad(get_field(block_env, offset::blockenv_method),
                            "env.method");

    // previous
    b().CreateStore(prev, get_field(call_frame, offset::cf_previous));

    // static_scope
    Value* ss = b().CreateLoad(get_field(block_inv, offset::blockinv_static_scope),
                               "invocation.static_scope");

    b().CreateStore(ss, get_field(call_frame, offset::cf_static_scope));

    // arguments
    b().CreateStore(args, get_field(call_frame, offset::cf_arguments));

    // msg
    b().CreateStore(Constant::getNullValue(ls_->Int8PtrTy),
        get_field(call_frame, offset::cf_msg));

    // cm
    b().CreateStore(method, cm_gep);

    // flags
    Value* inv_flags = b().CreateLoad(get_field(block_inv, offset::blockinv_flags),
        "invocation.flags");

    int block_flags = CallFrame::cCustomStaticScope |
      CallFrame::cMultipleScopes |
      CallFrame::cBlock;

    if(!use_full_scope_) block_flags |= CallFrame::cClosedScope;

    Value* flags = b().CreateOr(inv_flags,
        ConstantInt::get(ls_->Int32Ty, block_flags), "flags");

    b().CreateStore(flags, get_field(call_frame, offset::cf_flags));

    // ip
    b().CreateStore(ConstantInt::get(ls_->Int32Ty, 0),
        get_field(call_frame, offset::cf_ip));

    // scope
    b().CreateStore(vars, get_field(call_frame, offset::cf_scope));

    // top_scope
    top_scope = b().CreateLoad(
        get_field(block_env, offset::blockenv_top_scope),
        "env.top_scope");

    b().CreateStore(top_scope, get_field(call_frame, offset::cf_top_scope));

    // jit_data
    b().CreateStore(
        constant(info_.context().runtime_data_holder(), ls_->Int8PtrTy),
        get_field(call_frame, offset::cf_jit_data));

  }
}
}

#endif
<commit_msg>Make sure a JITd block strongly references it's JITd code. Fixes #413.<commit_after>#ifdef ENABLE_LLVM

#include "llvm/jit_block.hpp"
#include "llvm/jit_context.hpp"

#include "call_frame.hpp"
#include "stack_variables.hpp"

#include "instruments/profiler.hpp"

using namespace llvm;

namespace rubinius {
namespace jit {

  void BlockBuilder::setup() {
    Signature sig(ls_, "Object");
    sig << "VM";
    sig << "CallFrame";
    sig << "BlockEnvironment";
    sig << "Arguments";
    sig << "BlockInvocation";

    func = sig.function("");

    Function::arg_iterator ai = func->arg_begin();
    vm =   ai++; vm->setName("state");
    prev = ai++; prev->setName("previous");
    block_env = ai++; block_env->setName("env");
    args = ai++; args->setName("args");
    block_inv = ai++; block_inv->setName("invocation");

    BasicBlock* block = BasicBlock::Create(ls_->ctx(), "entry", func);
    b().SetInsertPoint(block);

    info_.set_function(func);
    info_.set_vm(vm);
    info_.set_args(args);
    info_.set_previous(prev);
    info_.set_entry(block);

    BasicBlock* body = BasicBlock::Create(ls_->ctx(), "block_body", func);

    pass_one(body);

    info_.set_counter(b().CreateAlloca(ls_->Int32Ty, 0, "counter_alloca"));

    // The 3 here is because we store {ip, sp, type} per unwind.
    info_.set_unwind_info(b().CreateAlloca(ls_->Int32Ty,
          ConstantInt::get(ls_->Int32Ty, rubinius::kMaxUnwindInfos * 3),
          "unwind_info"));

    valid_flag = b().CreateAlloca(ls_->Int1Ty, 0, "valid_flag");

    Value* cfstk = b().CreateAlloca(obj_type,
        ConstantInt::get(ls_->Int32Ty,
          (sizeof(CallFrame) / sizeof(Object*)) + vmm_->stack_size),
        "cfstk");

    call_frame = b().CreateBitCast(
        cfstk,
        llvm::PointerType::getUnqual(cf_type), "call_frame");

    info_.set_out_args(b().CreateAlloca(ls_->type("Arguments"), 0, "out_args"));

    if(ls_->include_profiling()) {
      method_entry_ = b().CreateAlloca(ls_->Int8Ty,
          ConstantInt::get(ls_->Int32Ty, sizeof(profiler::MethodEntry)),
          "method_entry");

      info_.set_profiling_entry(method_entry_);
    }

    info_.set_call_frame(call_frame);

    stk = b().CreateConstGEP1_32(cfstk, sizeof(CallFrame) / sizeof(Object*), "stack");

    info_.set_stack(stk);

    Value* var_mem = b().CreateAlloca(obj_type,
        ConstantInt::get(ls_->Int32Ty,
          (sizeof(StackVariables) / sizeof(Object*)) + vmm_->number_of_locals),
        "var_mem");

    vars = b().CreateBitCast(
        var_mem,
        llvm::PointerType::getUnqual(stack_vars_type), "vars");

    info_.set_variables(vars);

    initialize_frame(vmm_->stack_size);

    nil_stack(vmm_->stack_size, constant(Qnil, obj_type));

    setup_block_scope();

    if(ls_->include_profiling()) {
      Value* test = b().CreateLoad(ls_->profiling(), "profiling");

      BasicBlock* setup_profiling = BasicBlock::Create(ls_->ctx(), "setup_profiling", func);
      BasicBlock* cont = BasicBlock::Create(ls_->ctx(), "continue", func);

      b().CreateCondBr(test, setup_profiling, cont);

      b().SetInsertPoint(setup_profiling);

      Signature sig(ls_, ls_->VoidTy);
      sig << "VM";
      sig << llvm::PointerType::getUnqual(ls_->Int8Ty);
      sig << "BlockEnvironment";
      sig << "Module";
      sig << "CompiledMethod";

      Value* call_args[] = {
        vm,
        method_entry_,
        block_env,
        module_,
        method
      };

      sig.call("rbx_begin_profiling_block", call_args, 5, "", b());

      b().CreateBr(cont);

      b().SetInsertPoint(cont);
    }
    b().CreateBr(body);

    b().SetInsertPoint(body);
  }

  void BlockBuilder::setup_block_scope() {
    b().CreateStore(ConstantExpr::getNullValue(llvm::PointerType::getUnqual(vars_type)),
        get_field(vars, offset::vars_on_heap));
    Value* self = b().CreateLoad(
        get_field(block_inv, offset::blockinv_self),
        "invocation.self");

    b().CreateStore(self, get_field(vars, offset::vars_self));

    Value* inv_mod = b().CreateLoad(
        get_field(block_inv, offset::blockinv_module),
        "invocation.module");

    Value* creation_mod = b().CreateLoad(
        get_field(block_env, offset::blockenv_module),
        "env.module");

    Value* mod = b().CreateSelect(
        b().CreateICmpNE(inv_mod, ConstantExpr::getNullValue(inv_mod->getType())),
        inv_mod,
        creation_mod);

    module_ = mod;

    b().CreateStore(mod, get_field(vars, offset::vars_module));

    Value* blk = b().CreateLoad(get_field(top_scope, offset::varscope_block),
        "args.block");
    b().CreateStore(blk, get_field(vars, offset::vars_block));

    // We don't use top_scope here because of nested blocks. Parent MUST be
    // the scope the block was created in, not the top scope for depth
    // variables to work.
    Value* be_scope = b().CreateLoad(
        get_field(block_env, offset::blockenv_scope),
        "env.scope");

    b().CreateStore(be_scope, get_field(vars, offset::vars_parent));
    b().CreateStore(constant(Qnil, obj_type), get_field(vars, offset::vars_last_match));

    nil_locals();
  }

  void BlockBuilder::initialize_frame(int stack_size) {
    Value* cm_gep = get_field(call_frame, offset::cf_cm);

    method = b().CreateLoad(get_field(block_env, offset::blockenv_method),
                            "env.method");

    // previous
    b().CreateStore(prev, get_field(call_frame, offset::cf_previous));

    // static_scope
    Value* ss = b().CreateLoad(get_field(block_inv, offset::blockinv_static_scope),
                               "invocation.static_scope");

    b().CreateStore(ss, get_field(call_frame, offset::cf_static_scope));

    // arguments
    b().CreateStore(args, get_field(call_frame, offset::cf_arguments));

    // msg
    b().CreateStore(Constant::getNullValue(ls_->Int8PtrTy),
        get_field(call_frame, offset::cf_msg));

    // cm
    b().CreateStore(method, cm_gep);

    // flags
    Value* inv_flags = b().CreateLoad(get_field(block_inv, offset::blockinv_flags),
        "invocation.flags");

    int block_flags = CallFrame::cCustomStaticScope |
      CallFrame::cMultipleScopes |
      CallFrame::cBlock |
      CallFrame::cJITed;

    if(!use_full_scope_) block_flags |= CallFrame::cClosedScope;

    Value* flags = b().CreateOr(inv_flags,
        ConstantInt::get(ls_->Int32Ty, block_flags), "flags");

    b().CreateStore(flags, get_field(call_frame, offset::cf_flags));

    // ip
    b().CreateStore(ConstantInt::get(ls_->Int32Ty, 0),
        get_field(call_frame, offset::cf_ip));

    // scope
    b().CreateStore(vars, get_field(call_frame, offset::cf_scope));

    // top_scope
    top_scope = b().CreateLoad(
        get_field(block_env, offset::blockenv_top_scope),
        "env.top_scope");

    b().CreateStore(top_scope, get_field(call_frame, offset::cf_top_scope));

    // jit_data
    b().CreateStore(
        constant(info_.context().runtime_data_holder(), ls_->Int8PtrTy),
        get_field(call_frame, offset::cf_jit_data));

  }
}
}

#endif
<|endoftext|>


<commit_before>#include "graphicstransition.h"

#include <math.h>

#include <QPen>
#include <QPainter>

const qreal PI = 3.14;

GraphicsTransition::GraphicsTransition(GraphicsStateItem *from, GraphicsStateItem *to, QGraphicsItem *parent)
    : QGraphicsLineItem(parent){

    mCurrentState = from;
    mNextState = to;
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    setPen(QPen(Qt::white, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));

}

QRectF GraphicsTransition::boundingRect(){
    qreal extra = (pen().width() + 20) / 2.0;

        return QRectF(line().p1(), QSizeF(line().p2().x() - line().p1().x(),
                                          line().p2().y() - line().p1().y()))
            .normalized()
                .adjusted(-extra, -extra, extra, extra);
}

QPainterPath GraphicsTransition::shape(){
    QPainterPath path = QGraphicsLineItem::shape();
    path.addPolygon(mArrowHead);
    return path;
}

void GraphicsTransition::setNextState(GraphicsStateItem *state){
    mNextState = state;

}

void GraphicsTransition::setCurrentState(GraphicsStateItem *state){
    mCurrentState = state;

}

void GraphicsTransition::updatePosition(){

    if(mCurrentState != nullptr && mNextState != nullptr){
        QLineF line(mapFromItem(mCurrentState, 20, 0), mapFromItem(mNextState, 0, 0));
        setLine(line);
    }
}

void GraphicsTransition::writeXml(QXmlStreamWriter &writer){

    writer.writeStartElement("transition");
    writer.writeAttribute("target", mNextState->getId());

    //TODO for Each condition
    writer.writeStartElement("conditions");
    mCondition->writeXml(writer);
    writer.writeEndElement();

    writer.writeEndElement();
}

void GraphicsTransition::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){

    if (mCurrentState->collidesWithItem(mNextState))
       return;

    QPen myPen = pen();
    myPen.setColor(Qt::white);
    qreal arrowSize = 20;
    painter->setPen(myPen);
    painter->setBrush(Qt::white);

    QLineF centerLine(mCurrentState->getCenterPoint(), mNextState->getCenterPoint());
    QPolygonF endPolygon = mNextState->boundingRect();
    QPointF p1 = endPolygon.first() + mNextState->getCenterPoint();
    QPointF p2;
    QPointF intersectPoint;
    QLineF polyLine;
    for (int i = 1; i < endPolygon.count(); ++i) {
    p2 = endPolygon.at(i) + mNextState->getCenterPoint();
    polyLine = QLineF(p1, p2);
    QLineF::IntersectType intersectType =
        polyLine.intersect(centerLine, &intersectPoint);
    if (intersectType == QLineF::BoundedIntersection)
        break;
        p1 = p2;
    }

    setLine(QLineF(intersectPoint, mCurrentState->getCenterPoint()));

    double angle = ::acos(line().dx() / line().length());
    if (line().dy() >= 0){
        angle = (PI * 2) - angle;

        QPointF arrowP1 = line().p1() + QPointF(sin(angle + PI / 3) * arrowSize,
                                        cos(angle + PI / 3) * arrowSize);
        QPointF arrowP2 = line().p1() + QPointF(sin(angle + PI - PI / 3) * arrowSize,
                                        cos(angle + PI - PI / 3) * arrowSize);

        mArrowHead.clear();
        mArrowHead << line().p1() << arrowP1 << arrowP2;

        painter->drawLine(line());
        painter->drawPolygon(mArrowHead);
        if (isSelected()) {
            painter->setPen(QPen(Qt::white, 1, Qt::DashLine));
        QLineF myLine = line();
        myLine.translate(0, 2.0);
        painter->drawLine(myLine);
        myLine.translate(0,-4.0);
        painter->drawLine(myLine);
        }
    }

    QGraphicsLineItem::paint(painter, option, widget);

}

<commit_msg>Arrow head good angle<commit_after>#include "graphicstransition.h"

#include <math.h>

#include <QPen>
#include <QPainter>

const qreal PI = 3.14;

GraphicsTransition::GraphicsTransition(GraphicsStateItem *from, GraphicsStateItem *to, QGraphicsItem *parent)
    : QGraphicsLineItem(parent){

    mCurrentState = from;
    mNextState = to;
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    setPen(QPen(Qt::white, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));

}

QRectF GraphicsTransition::boundingRect(){
    qreal extra = (pen().width() + 20) / 2.0;

        return QRectF(line().p1(), QSizeF(line().p2().x() - line().p1().x(),
                                          line().p2().y() - line().p1().y()))
            .normalized()
                .adjusted(-extra, -extra, extra, extra);
}

QPainterPath GraphicsTransition::shape(){
    QPainterPath path = QGraphicsLineItem::shape();
    path.addPolygon(mArrowHead);
    return path;
}

void GraphicsTransition::setNextState(GraphicsStateItem *state){
    mNextState = state;

}

void GraphicsTransition::setCurrentState(GraphicsStateItem *state){
    mCurrentState = state;

}

void GraphicsTransition::updatePosition(){

    if(mCurrentState != nullptr && mNextState != nullptr){
        QLineF line(mapFromItem(mCurrentState, 20, 0), mapFromItem(mNextState, 0, 0));
        setLine(line);
    }
}

void GraphicsTransition::writeXml(QXmlStreamWriter &writer){

    writer.writeStartElement("transition");
    writer.writeAttribute("target", mNextState->getId());

    //TODO for Each condition
    writer.writeStartElement("conditions");
    mCondition->writeXml(writer);
    writer.writeEndElement();

    writer.writeEndElement();
}

void GraphicsTransition::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){

    if (mCurrentState->collidesWithItem(mNextState))
       return;

    QPen myPen = pen();
    myPen.setColor(Qt::white);
    qreal arrowSize = 20;
    painter->setPen(myPen);
    painter->setBrush(Qt::white);

    QLineF centerLine(mCurrentState->getCenterPoint(), mNextState->getCenterPoint());
    QPolygonF endPolygon = mNextState->boundingRect();
    QPointF p1 = endPolygon.first() + mNextState->getCenterPoint();
    QPointF p2;
    QPointF intersectPoint;
    QLineF polyLine;
    for (int i = 1; i < endPolygon.count(); ++i) {
    p2 = endPolygon.at(i) + mNextState->getCenterPoint();
    polyLine = QLineF(p1, p2);
    QLineF::IntersectType intersectType =
        polyLine.intersect(centerLine, &intersectPoint);
    if (intersectType == QLineF::BoundedIntersection)
        break;
        p1 = p2;
    }

    setLine(QLineF(intersectPoint, mCurrentState->getCenterPoint()));

    double angle = ::acos(line().dx() / line().length());
    if (line().dy() >= 0)
        angle = (PI * 2) - angle;

    QPointF arrowP1 = line().p1() + QPointF(sin(angle + PI / 3) * arrowSize,
                                    cos(angle + PI / 3) * arrowSize);
    QPointF arrowP2 = line().p1() + QPointF(sin(angle + PI - PI / 3) * arrowSize,
                                    cos(angle + PI - PI / 3) * arrowSize);

    mArrowHead.clear();
    mArrowHead << line().p1() << arrowP1 << arrowP2;

    painter->drawLine(line());
    painter->drawPolygon(mArrowHead);
    if (isSelected()) {
        painter->setPen(QPen(Qt::white, 1, Qt::DashLine));
        QLineF myLine = line();
        myLine.translate(0, 2.0);
        painter->drawLine(myLine);
        myLine.translate(0,-4.0);
        painter->drawLine(myLine);
    }

    QGraphicsLineItem::paint(painter, option, widget);

}

<|endoftext|>


<commit_before>// -*- coding: us-ascii-unix -*-
// Copyright 2012 Lukas Kemmer
//
// Licensed under the Apache License, Version 2.0 (the "License"); you
// may not use this file except in compliance with the License. You
// may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
#include <iomanip>
#include <sstream>
#include <string>
#include "bitmap/color.hh"
#include "bitmap/paint.hh"
#include "geo/angle.hh"
#include "geo/axis.hh"
#include "geo/geo-func.hh"
#include "geo/int-size.hh"
#include "geo/line.hh"
#include "geo/measure.hh"
#include "geo/radii.hh"
#include "geo/range.hh"
#include "geo/scale.hh"
#include "text/char-constants.hh"
#include "text/formatting.hh"
#include "text/slice.hh"
#include "util/generator-adapter.hh"
#include "util/index.hh"
#include "util/iter.hh"
#include "util/pos-info-constants.hh" // For MouseButton

namespace faint{

utf8_string bracketed(const utf8_string& s){
  return "(" + s + ")";
}

utf8_string capitalized(const utf8_string& s){
  if (s.empty()){
    return s;
  }
  return toupper(s[0]) + slice_from(s, 1);
}

utf8_string decapitalized(const utf8_string& s){
  if (s.empty()){
    return s;
  }
  return tolower(s[0]) + slice_from(s, 1);
}

std::string replace_all(const std::string& s, const std::string& old, const std::string& replacement) {
  std::string s2 = s;
  size_t start_pos = 0;
  while((start_pos = s2.find(old, start_pos)) != std::string::npos) {
    s2.replace(start_pos, old.length(), replacement);
    start_pos += replacement.length();
  }
  return s2;
}

utf8_string quoted(const utf8_string& s){
  return "\"" + s + "\"";
}

static utf8_string str_two_ints(int i1, int i2){
  std::stringstream ss;
  ss << i1 << "," << i2;
  return utf8_string(ss.str());
}

utf8_string str_floor(const Point& p){
  return str(floored(p));
}

utf8_string str(const Size& sz, const Precision& precision){
  return comma_sep(str(sz.w, precision),
    str(sz.h, precision));
}

utf8_string str(const IntPoint& p){
  return str_two_ints(p.x, p.y);
}

utf8_string str(const IntSize& sz){
  return str_two_ints(sz.w, sz.h);
}

utf8_string str(coord v, const Precision& precision){
  std::stringstream ss;
  ss << std::fixed << std::setprecision(precision) << v;
  return utf8_string(ss.str());
}

utf8_string str_user(const Index& index){
  return str_int(index.Get() + 1);
}

utf8_string str_coder(const Index& index){
  return str_int(index.Get());
}

utf8_string str(const Paint& paint){
  return visit(paint,
    [](const Color& c){
      return comma_sep(bracketed(str_smart_rgba(c,
        rgb_prefix(true))), str_hex(c));},
    [](const Pattern&){
      return utf8_string("Pattern");},
    [](const Gradient&){
      return utf8_string("Gradient");});
}

utf8_string str(const Scale& scale){
  std::stringstream ss;
  int sc_x = rounded(scale.x * 100);
  int sc_y = rounded(scale.y * 100);
  ss << sc_x << "%";
  if (sc_x != sc_y){
    ss << ", " << sc_y << "%";
  }
  return utf8_string(ss.str());
}

utf8_string str_axis_adverb(Axis axis){
  return axis == Axis::HORIZONTAL ?
    utf8_string("Horizontally") :
    utf8_string("Vertically");
}

utf8_string str_int(int v){
  std::stringstream ss;
  ss << v;
  return utf8_string(ss.str());
}

utf8_string str_int(int v, left_pad w){
  std::stringstream ss;
  ss << std::setfill('0') << std::setw(w) << std::right;
  ss << v;
  return utf8_string(ss.str());
}

utf8_string str_uint(size_t v){
  std::stringstream ss;
  ss << v;
  return utf8_string(ss.str());
}

utf8_string str_interval(const Interval& interval){
  std::stringstream ss;
  ss << interval.Lower() << "->" << interval.Upper();
  return utf8_string(ss.str());
}

utf8_string str_range(const ClosedIntRange& range){
  std::stringstream ss;
  ss << range.Lower() << "->" << range.Upper();
  return utf8_string(ss.str());
}

utf8_string str(const ColRGB& c){
  std::stringstream ss;
  ss << (int)c.r << "," << (int)c.g << "," << int(c.b);
  return utf8_string(ss.str());
}

utf8_string str_rgb(const Color& c){
  std::stringstream ss;
  ss << (int)c.r << "," << (int)c.g << "," << (int)c.b;
  return utf8_string(ss.str());
}

utf8_string str_rgba(const Color& c){
  std::stringstream ss;
  ss << (int)c.r << "," << (int)c.g << "," << (int)c.b << "," << (int)c.a;
  return utf8_string(ss.str());
}

Optional<ColRGB> parse_hex_color(const utf8_string& u8str){
  if (!is_ascii(u8str)){
    return no_option();
  }

  const auto s = replace_all(u8str.str(), "#", "0x");
  if (s.size() == 0){
    return no_option();
  }

  const size_t n = 0;
  const char* start = s.c_str();
  char* end = const_cast<char*>(start);
  // Seems I don't have the C++11 strtoul for std::string with msvc
  const unsigned int x = std::strtoul(start, &end, 16);
  if (end < start + s.size()){
    // Garbage at end of string
    return no_option();
  }
  if (x < 0x000000 || 0xffffff < x){
    // Hex value out of range
    return no_option();
  }
  return option(rgb_from_hex(x));
}

utf8_string str_smart_rgba(const Color& c, const rgb_prefix& prefix){
  if (!prefix.Get()){
    return str_smart_rgba(c);
  }
  else{
    return opaque(c) ?
      "RGB: " + str_rgb(c) :
      "RGBA: " + str_rgba(c);
  }
}

utf8_string str_smart_rgba(const Color& c){
  return opaque(c) ? str_rgb(c) : str_rgba(c);
}

utf8_string str_hex(const Color& c){
  std::stringstream ss;
  ss << "#";
  ss.fill('0');
  ss << std::uppercase << std::hex <<
    std::setw(2) << (int)c.r <<
    std::setw(2) << (int)c.g <<
    std::setw(2) << (int)c.b;
  return utf8_string(ss.str());
}

utf8_string str_hex(const int value){
  std::stringstream ss;
  ss << std::hex << value;
  return utf8_string(ss.str());
}

utf8_string str_length(coord len){
  std::stringstream ss;
  ss << std::fixed << std::setprecision(1) << len;
  return utf8_string(ss.str());
}

utf8_string str_int_length(int len){
  return str_int(len);
}

utf8_string str_center_radius(const Point& c, const Radii& r){
  std::stringstream ss;
  ss << std::fixed << std::setprecision(1) <<
    "c: " << c.x << "," << c.y << " r: " << r.x << "," << r.y;
  return utf8_string(ss.str());
}

utf8_string str_center_radius(const Point& c, double r){
  std::stringstream ss;

  ss << std::fixed << std::setprecision(1) <<
    "c: " << c.x << "," << c.y << " r: " << r;
  return utf8_string(ss.str());
}

utf8_string str_from_to(const IntPoint& p1, const IntPoint& p2){
  std::stringstream ss;
  ss << p1.x << "," << p1.y << "->" << p2.x << "," << p2.y;
  return utf8_string(ss.str());
}

utf8_string str_from_to(const Point& p1, const Point& p2){
  return str_from_to(floored(p1), floored(p2));
}

utf8_string str_degrees(const Angle& angle){
  std::stringstream ss;
  ss << std::fixed << std::setprecision(1) << angle.Deg();
  return utf8_string(ss.str());
}

utf8_string str_degrees_symbol(const Angle& angle){
  std::stringstream ss;
  ss << std::fixed << std::setprecision(1) << angle.Deg() <<
    chars::degree_sign.str();
  return utf8_string(ss.str());
}

utf8_string str_degrees_int_symbol(int angle){
  std::stringstream ss;
  if (angle == 360){
    angle = 0;
  }
  ss << angle << chars::degree_sign.str();
  return utf8_string(ss.str());
}

utf8_string str_percentage(int numerator, int denominator){
  int scale(static_cast<int>((100 * numerator / (double) denominator) + 0.5));
  std::stringstream ss;
  ss << scale << "%";
  return utf8_string(ss.str());
}

utf8_string str_line_status_subpixel(const LineSegment& l){
  int angle = rounded(angle360_ccw(l).Deg());

  return comma_sep(str_from_to(l.p0, l.p1),
    lbl("length", str_length(length(l))),
    lbl("angle", str_degrees_int_symbol(angle)));
}

static utf8_string str_from_to(const IntLineSegment& l){
  return str_from_to(l.p0, l.p1);
}

utf8_string str_line_status(const IntLineSegment& line){
  int lineRadius = 1 + // For non-subpixel lines, p1==p2 means length 1
    truncated(length(line));

  return comma_sep(str_from_to(line),
    lbl("length",
      str_int_length(lineRadius)),

    lbl("angle",
      str_degrees_int_symbol(rounded(angle360_ccw(floated(line)).Deg()))));
}

utf8_string lbl(const utf8_string& label, const utf8_string& value){
  return label + ": " + value;
}

utf8_string lbl(const utf8_string& label, int value){
  std::stringstream ss;
  ss << ": " << value;
  return label + utf8_string(ss.str());
}

utf8_string lbl_u(const utf8_string& label, size_t value){
  std::stringstream ss;
  ss << ": " << value;
  return label + utf8_string(ss.str());
}

utf8_string pluralize_count(size_t amount, const utf8_string& type){
  return space_sep(str_uint(amount),
    amount == 1 ? type :
    type + "s");
}

utf8_string pluralize(const utf8_string& item){
  return item + "s";
}

utf8_string primary_modifier(const utf8_string& action){
  return "Ctrl=" + action;
}

utf8_string secondary_modifier(const utf8_string& action){
  return "Shift=" + action;
}

utf8_string both_modifiers(const utf8_string& action){
  return "Ctrl+Shift=" + action;
}

utf8_string both_modifiers(){
  return "Ctrl+Shift";
}

utf8_string str_yh(int y, int h){
  std::stringstream ss;
  ss << "y: " << y << " h: " << h;
  return utf8_string(ss.str());
}

StrBtn::StrBtn(MouseButton button){
  if (button == MouseButton::LEFT){
    m_btnThis = "left";
    m_btnThat = "right";
  }
  else if (button == MouseButton::RIGHT){
    m_btnThis = "right";
    m_btnThat = "left";
  }
}

const utf8_string StrBtn::This(bool capital) const {
  return capital ? capitalized(m_btnThis) : m_btnThis;
}

const utf8_string StrBtn::Other(bool capital) const {
  return capital ? capitalized(m_btnThat) : m_btnThat;
}

utf8_string join(const utf8_string& sep, const std::vector<utf8_string>& strings){
  if (strings.empty()){
    return "";
  }
  return accumulate(first(strings), but_first(strings),
    [&](const auto& left, const auto& right){
      return left + sep + right;
    });
}

utf8_string comma_sep(const std::vector<utf8_string>& strings){
  return join(", ", strings);
}

utf8_string endline_sep(const std::vector<utf8_string>& strings){
  return join("\n", strings);
}

utf8_string no_sep(const std::vector<utf8_string>& strings){
  return join("", strings);
}

} // namespace
<commit_msg>Compilation fix, gcc<commit_after>// -*- coding: us-ascii-unix -*-
// Copyright 2012 Lukas Kemmer
//
// Licensed under the Apache License, Version 2.0 (the "License"); you
// may not use this file except in compliance with the License. You
// may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
#include <iomanip>
#include <sstream>
#include <string>
#include "bitmap/color.hh"
#include "bitmap/paint.hh"
#include "geo/angle.hh"
#include "geo/axis.hh"
#include "geo/geo-func.hh"
#include "geo/int-size.hh"
#include "geo/line.hh"
#include "geo/measure.hh"
#include "geo/radii.hh"
#include "geo/range.hh"
#include "geo/scale.hh"
#include "text/char-constants.hh"
#include "text/formatting.hh"
#include "text/slice.hh"
#include "util/generator-adapter.hh"
#include "util/index.hh"
#include "util/iter.hh"
#include "util/pos-info-constants.hh" // For MouseButton

namespace faint{

utf8_string bracketed(const utf8_string& s){
  return "(" + s + ")";
}

utf8_string capitalized(const utf8_string& s){
  if (s.empty()){
    return s;
  }
  return toupper(s[0]) + slice_from(s, 1);
}

utf8_string decapitalized(const utf8_string& s){
  if (s.empty()){
    return s;
  }
  return tolower(s[0]) + slice_from(s, 1);
}

std::string replace_all(const std::string& s, const std::string& old, const std::string& replacement) {
  std::string s2 = s;
  size_t start_pos = 0;
  while((start_pos = s2.find(old, start_pos)) != std::string::npos) {
    s2.replace(start_pos, old.length(), replacement);
    start_pos += replacement.length();
  }
  return s2;
}

utf8_string quoted(const utf8_string& s){
  return "\"" + s + "\"";
}

static utf8_string str_two_ints(int i1, int i2){
  std::stringstream ss;
  ss << i1 << "," << i2;
  return utf8_string(ss.str());
}

utf8_string str_floor(const Point& p){
  return str(floored(p));
}

utf8_string str(const Size& sz, const Precision& precision){
  return comma_sep(str(sz.w, precision),
    str(sz.h, precision));
}

utf8_string str(const IntPoint& p){
  return str_two_ints(p.x, p.y);
}

utf8_string str(const IntSize& sz){
  return str_two_ints(sz.w, sz.h);
}

utf8_string str(coord v, const Precision& precision){
  std::stringstream ss;
  ss << std::fixed << std::setprecision(precision) << v;
  return utf8_string(ss.str());
}

utf8_string str_user(const Index& index){
  return str_int(index.Get() + 1);
}

utf8_string str_coder(const Index& index){
  return str_int(index.Get());
}

utf8_string str(const Paint& paint){
  return visit(paint,
    [](const Color& c){
      return comma_sep(bracketed(str_smart_rgba(c,
        rgb_prefix(true))), str_hex(c));},
    [](const Pattern&){
      return utf8_string("Pattern");},
    [](const Gradient&){
      return utf8_string("Gradient");});
}

utf8_string str(const Scale& scale){
  std::stringstream ss;
  int sc_x = rounded(scale.x * 100);
  int sc_y = rounded(scale.y * 100);
  ss << sc_x << "%";
  if (sc_x != sc_y){
    ss << ", " << sc_y << "%";
  }
  return utf8_string(ss.str());
}

utf8_string str_axis_adverb(Axis axis){
  return axis == Axis::HORIZONTAL ?
    utf8_string("Horizontally") :
    utf8_string("Vertically");
}

utf8_string str_int(int v){
  std::stringstream ss;
  ss << v;
  return utf8_string(ss.str());
}

utf8_string str_int(int v, left_pad w){
  std::stringstream ss;
  ss << std::setfill('0') << std::setw(w) << std::right;
  ss << v;
  return utf8_string(ss.str());
}

utf8_string str_uint(size_t v){
  std::stringstream ss;
  ss << v;
  return utf8_string(ss.str());
}

utf8_string str_interval(const Interval& interval){
  std::stringstream ss;
  ss << interval.Lower() << "->" << interval.Upper();
  return utf8_string(ss.str());
}

utf8_string str_range(const ClosedIntRange& range){
  std::stringstream ss;
  ss << range.Lower() << "->" << range.Upper();
  return utf8_string(ss.str());
}

utf8_string str(const ColRGB& c){
  std::stringstream ss;
  ss << (int)c.r << "," << (int)c.g << "," << int(c.b);
  return utf8_string(ss.str());
}

utf8_string str_rgb(const Color& c){
  std::stringstream ss;
  ss << (int)c.r << "," << (int)c.g << "," << (int)c.b;
  return utf8_string(ss.str());
}

utf8_string str_rgba(const Color& c){
  std::stringstream ss;
  ss << (int)c.r << "," << (int)c.g << "," << (int)c.b << "," << (int)c.a;
  return utf8_string(ss.str());
}

Optional<ColRGB> parse_hex_color(const utf8_string& u8str){
  if (!is_ascii(u8str)){
    return no_option();
  }

  const auto s = replace_all(u8str.str(), "#", "0x");
  if (s.size() == 0){
    return no_option();
  }

  const char* start = s.c_str();
  char* end = const_cast<char*>(start);
  // Seems I don't have the C++11 strtoul for std::string with msvc
  const unsigned int x = std::strtoul(start, &end, 16);
  if (end < start + s.size()){
    // Garbage at end of string
    return no_option();
  }
  if (0xffffff < x){
    // Hex value out of range
    return no_option();
  }
  return option(rgb_from_hex(x));
}

utf8_string str_smart_rgba(const Color& c, const rgb_prefix& prefix){
  if (!prefix.Get()){
    return str_smart_rgba(c);
  }
  else{
    return opaque(c) ?
      "RGB: " + str_rgb(c) :
      "RGBA: " + str_rgba(c);
  }
}

utf8_string str_smart_rgba(const Color& c){
  return opaque(c) ? str_rgb(c) : str_rgba(c);
}

utf8_string str_hex(const Color& c){
  std::stringstream ss;
  ss << "#";
  ss.fill('0');
  ss << std::uppercase << std::hex <<
    std::setw(2) << (int)c.r <<
    std::setw(2) << (int)c.g <<
    std::setw(2) << (int)c.b;
  return utf8_string(ss.str());
}

utf8_string str_hex(const int value){
  std::stringstream ss;
  ss << std::hex << value;
  return utf8_string(ss.str());
}

utf8_string str_length(coord len){
  std::stringstream ss;
  ss << std::fixed << std::setprecision(1) << len;
  return utf8_string(ss.str());
}

utf8_string str_int_length(int len){
  return str_int(len);
}

utf8_string str_center_radius(const Point& c, const Radii& r){
  std::stringstream ss;
  ss << std::fixed << std::setprecision(1) <<
    "c: " << c.x << "," << c.y << " r: " << r.x << "," << r.y;
  return utf8_string(ss.str());
}

utf8_string str_center_radius(const Point& c, double r){
  std::stringstream ss;

  ss << std::fixed << std::setprecision(1) <<
    "c: " << c.x << "," << c.y << " r: " << r;
  return utf8_string(ss.str());
}

utf8_string str_from_to(const IntPoint& p1, const IntPoint& p2){
  std::stringstream ss;
  ss << p1.x << "," << p1.y << "->" << p2.x << "," << p2.y;
  return utf8_string(ss.str());
}

utf8_string str_from_to(const Point& p1, const Point& p2){
  return str_from_to(floored(p1), floored(p2));
}

utf8_string str_degrees(const Angle& angle){
  std::stringstream ss;
  ss << std::fixed << std::setprecision(1) << angle.Deg();
  return utf8_string(ss.str());
}

utf8_string str_degrees_symbol(const Angle& angle){
  std::stringstream ss;
  ss << std::fixed << std::setprecision(1) << angle.Deg() <<
    chars::degree_sign.str();
  return utf8_string(ss.str());
}

utf8_string str_degrees_int_symbol(int angle){
  std::stringstream ss;
  if (angle == 360){
    angle = 0;
  }
  ss << angle << chars::degree_sign.str();
  return utf8_string(ss.str());
}

utf8_string str_percentage(int numerator, int denominator){
  int scale(static_cast<int>((100 * numerator / (double) denominator) + 0.5));
  std::stringstream ss;
  ss << scale << "%";
  return utf8_string(ss.str());
}

utf8_string str_line_status_subpixel(const LineSegment& l){
  int angle = rounded(angle360_ccw(l).Deg());

  return comma_sep(str_from_to(l.p0, l.p1),
    lbl("length", str_length(length(l))),
    lbl("angle", str_degrees_int_symbol(angle)));
}

static utf8_string str_from_to(const IntLineSegment& l){
  return str_from_to(l.p0, l.p1);
}

utf8_string str_line_status(const IntLineSegment& line){
  int lineRadius = 1 + // For non-subpixel lines, p1==p2 means length 1
    truncated(length(line));

  return comma_sep(str_from_to(line),
    lbl("length",
      str_int_length(lineRadius)),

    lbl("angle",
      str_degrees_int_symbol(rounded(angle360_ccw(floated(line)).Deg()))));
}

utf8_string lbl(const utf8_string& label, const utf8_string& value){
  return label + ": " + value;
}

utf8_string lbl(const utf8_string& label, int value){
  std::stringstream ss;
  ss << ": " << value;
  return label + utf8_string(ss.str());
}

utf8_string lbl_u(const utf8_string& label, size_t value){
  std::stringstream ss;
  ss << ": " << value;
  return label + utf8_string(ss.str());
}

utf8_string pluralize_count(size_t amount, const utf8_string& type){
  return space_sep(str_uint(amount),
    amount == 1 ? type :
    type + "s");
}

utf8_string pluralize(const utf8_string& item){
  return item + "s";
}

utf8_string primary_modifier(const utf8_string& action){
  return "Ctrl=" + action;
}

utf8_string secondary_modifier(const utf8_string& action){
  return "Shift=" + action;
}

utf8_string both_modifiers(const utf8_string& action){
  return "Ctrl+Shift=" + action;
}

utf8_string both_modifiers(){
  return "Ctrl+Shift";
}

utf8_string str_yh(int y, int h){
  std::stringstream ss;
  ss << "y: " << y << " h: " << h;
  return utf8_string(ss.str());
}

StrBtn::StrBtn(MouseButton button){
  if (button == MouseButton::LEFT){
    m_btnThis = "left";
    m_btnThat = "right";
  }
  else if (button == MouseButton::RIGHT){
    m_btnThis = "right";
    m_btnThat = "left";
  }
}

const utf8_string StrBtn::This(bool capital) const {
  return capital ? capitalized(m_btnThis) : m_btnThis;
}

const utf8_string StrBtn::Other(bool capital) const {
  return capital ? capitalized(m_btnThat) : m_btnThat;
}

utf8_string join(const utf8_string& sep, const std::vector<utf8_string>& strings){
  if (strings.empty()){
    return "";
  }
  return accumulate(first(strings), but_first(strings),
    [&](const auto& left, const auto& right){
      return left + sep + right;
    });
}

utf8_string comma_sep(const std::vector<utf8_string>& strings){
  return join(", ", strings);
}

utf8_string endline_sep(const std::vector<utf8_string>& strings){
  return join("\n", strings);
}

utf8_string no_sep(const std::vector<utf8_string>& strings){
  return join("", strings);
}

} // namespace
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vvasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "TransactionUnloader.h"

#include "IncrementalExecutor.h"
#include "DeclUnloader.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Transaction.h"

#include "clang/AST/Decl.h"
#include "clang/AST/DependentDiagnostic.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Sema.h"

using namespace clang;

namespace cling {
  bool TransactionUnloader::unloadDeclarations(Transaction* T,
                                               DeclUnloader& DeclU) {
    bool Successful = true;

    for (Transaction::const_reverse_iterator I = T->rdecls_begin(),
           E = T->rdecls_end(); I != E; ++I) {
      const Transaction::ConsumerCallInfo& Call = I->m_Call;
      const DeclGroupRef& DGR = (*I).m_DGR;

      if (Call == Transaction::kCCIHandleVTable)
        continue;
      // The non templated classes come through HandleTopLevelDecl and
      // HandleTagDeclDefinition, this is why we need to filter.
      if (Call == Transaction::kCCIHandleTagDeclDefinition)
      if (const CXXRecordDecl* D
        = dyn_cast<CXXRecordDecl>(DGR.getSingleDecl()))
      if (D->getTemplateSpecializationKind() == TSK_Undeclared)
        continue;

      if (Call == Transaction::kCCINone)
        m_Interp->unload(*(*T->rnested_begin()));

      for (DeclGroupRef::const_iterator
             Di = DGR.end() - 1, E = DGR.begin() - 1; Di != E; --Di) {
        // Get rid of the declaration. If the declaration has name we should
        // heal the lookup tables as well
        Successful = DeclU.UnloadDecl(*Di) && Successful;
#ifndef NDEBUG
        assert(Successful && "Cannot handle that yet!");
#endif
      }
    }
    assert(T->rnested_begin() == T->rnested_end()
           && "nested transactions mismatch");
    return Successful;
  }

  bool TransactionUnloader::unloadFromPreprocessor(Transaction* T,
                                                   DeclUnloader& DeclU) {
    bool Successful = true;
    for (Transaction::const_reverse_macros_iterator MI = T->rmacros_begin(),
           ME = T->rmacros_end(); MI != ME; ++MI) {
      // Get rid of the macro definition
      Successful = DeclU.UnloadMacro(*MI) && Successful;
#ifndef NDEBUG
      assert(Successful && "Cannot handle that yet!");
#endif
    }
    return Successful;
  }

  bool TransactionUnloader::unloadDeserializedDeclarations(Transaction* T,
                                                   DeclUnloader& DeclU) {
    //FIXME: Terrible hack, we *must* get rid of parseForModule by implementing
    // a header file generator in cling.
    bool Successful = true;
    for (Transaction::const_reverse_iterator I = T->deserialized_rdecls_begin(),
           E = T->deserialized_rdecls_end(); I != E; ++I) {
      const DeclGroupRef& DGR = (*I).m_DGR;
      for (DeclGroupRef::const_iterator
             Di = DGR.end() - 1, E = DGR.begin() - 1; Di != E; --Di) {
        // We only want to revert all that came through parseForModule, and
        // not the PCH.
        if (!(*Di)->isFromASTFile())
          Successful = DeclU.UnloadDecl(*Di) && Successful;
#ifndef NDEBUG
        assert(Successful && "Cannot handle that yet!");
#endif
      }
    }
    return Successful;
  }

  bool TransactionUnloader::RevertTransaction(Transaction* T) {

    bool Successful = true;
    if (getExecutor() && T->getModule()) {
      Successful = getExecutor()->unloadFromJIT(T->getModule(),
                                                T->getExeUnloadHandle())
        && Successful;

      // Cleanup the module from unused global values.
      // if (T->getModule()) {
      //   llvm::ModulePass* globalDCE = llvm::createGlobalDCEPass();
      //   globalDCE->runOnModule(*T->getModule());
      // }

      Successful = unloadModule(T->getModule()) && Successful;
    }

    // Clean up the pending instantiations
    m_Sema->PendingInstantiations.clear();
    m_Sema->PendingLocalImplicitInstantiations.clear();

    DeclUnloader DeclU(m_Sema, m_CodeGen, T);
    Successful = unloadDeclarations(T, DeclU) && Successful;
    Successful = unloadDeserializedDeclarations(T, DeclU) && Successful;
    Successful = unloadFromPreprocessor(T, DeclU) && Successful;

#ifndef NDEBUG
    //FIXME: Move the nested transaction marker out of the decl lists and
    // reenable this assertion.
    //size_t DeclSize = std::distance(T->decls_begin(), T->decls_end());
    //if (T->getCompilationOpts().CodeGenerationForModule)
    //  assert (!DeclSize && "No parsed decls must happen in parse for module");
#endif

    if (Successful)
      T->setState(Transaction::kRolledBack);
    else
      T->setState(Transaction::kRolledBackWithErrors);

    // Release the input_line_X file unless verifying diagnostics.
    if (!m_Interp->getCI()->getDiagnosticOpts().VerifyDiagnostics)
      m_Sema->getSourceManager().invalidateCache(T->getBufferFID());

    return Successful;
  }

  bool TransactionUnloader::UnloadDecl(Decl* D) {
    return cling::UnloadDecl(m_Sema, m_CodeGen, D);
  }

  bool TransactionUnloader::unloadModule(llvm::Module* M) {
    for (auto& Func: M->functions())
      m_CodeGen->forgetGlobal(&Func);
    for (auto& Glob: M->globals())
      m_CodeGen->forgetGlobal(&Glob);
    return true;
  }
} // end namespace cling
<commit_msg>Fix filtering of CXXRecordDecls in Transaction unloader. This is necessary to unload a lot of anonymous structs throughout OS X Cocoa headers, but seems to have been an incorrect API usage in for C++ as well.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vvasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "TransactionUnloader.h"

#include "IncrementalExecutor.h"
#include "DeclUnloader.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Transaction.h"

#include "clang/AST/Decl.h"
#include "clang/AST/DependentDiagnostic.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Sema/Sema.h"

using namespace clang;

namespace cling {
  bool TransactionUnloader::unloadDeclarations(Transaction* T,
                                               DeclUnloader& DeclU) {
    bool Successful = true;

    for (Transaction::const_reverse_iterator I = T->rdecls_begin(),
           E = T->rdecls_end(); I != E; ++I) {
      const Transaction::ConsumerCallInfo& Call = I->m_Call;
      const DeclGroupRef& DGR = (*I).m_DGR;

      if (Call == Transaction::kCCIHandleVTable)
        continue;

      // The non templated classes come through HandleTopLevelDecl and
      // HandleTagDeclDefinition, this is why we need to filter.
      if (Call == Transaction::kCCIHandleTagDeclDefinition) {
        if (const CXXRecordDecl* D =
                                 dyn_cast<CXXRecordDecl>(DGR.getSingleDecl())) {
          // Make sure it's actually a template with getDescribedClassTemplate
          // TSK_Undeclared can be returned for classes that aren't templates
          if (D->getDescribedClassTemplate() &&
              D->getTemplateSpecializationKind() == TSK_Undeclared)
            continue;
        }
      }

      if (Call == Transaction::kCCINone)
        m_Interp->unload(*(*T->rnested_begin()));

      for (DeclGroupRef::const_iterator
             Di = DGR.end() - 1, E = DGR.begin() - 1; Di != E; --Di) {
        // Get rid of the declaration. If the declaration has name we should
        // heal the lookup tables as well
        Successful = DeclU.UnloadDecl(*Di) && Successful;
#ifndef NDEBUG
        assert(Successful && "Cannot handle that yet!");
#endif
      }
    }
    assert(T->rnested_begin() == T->rnested_end()
           && "nested transactions mismatch");
    return Successful;
  }

  bool TransactionUnloader::unloadFromPreprocessor(Transaction* T,
                                                   DeclUnloader& DeclU) {
    bool Successful = true;
    for (Transaction::const_reverse_macros_iterator MI = T->rmacros_begin(),
           ME = T->rmacros_end(); MI != ME; ++MI) {
      // Get rid of the macro definition
      Successful = DeclU.UnloadMacro(*MI) && Successful;
#ifndef NDEBUG
      assert(Successful && "Cannot handle that yet!");
#endif
    }
    return Successful;
  }

  bool TransactionUnloader::unloadDeserializedDeclarations(Transaction* T,
                                                   DeclUnloader& DeclU) {
    //FIXME: Terrible hack, we *must* get rid of parseForModule by implementing
    // a header file generator in cling.
    bool Successful = true;
    for (Transaction::const_reverse_iterator I = T->deserialized_rdecls_begin(),
           E = T->deserialized_rdecls_end(); I != E; ++I) {
      const DeclGroupRef& DGR = (*I).m_DGR;
      for (DeclGroupRef::const_iterator
             Di = DGR.end() - 1, E = DGR.begin() - 1; Di != E; --Di) {
        // We only want to revert all that came through parseForModule, and
        // not the PCH.
        if (!(*Di)->isFromASTFile())
          Successful = DeclU.UnloadDecl(*Di) && Successful;
#ifndef NDEBUG
        assert(Successful && "Cannot handle that yet!");
#endif
      }
    }
    return Successful;
  }

  bool TransactionUnloader::RevertTransaction(Transaction* T) {

    bool Successful = true;
    if (getExecutor() && T->getModule()) {
      Successful = getExecutor()->unloadFromJIT(T->getModule(),
                                                T->getExeUnloadHandle())
        && Successful;

      // Cleanup the module from unused global values.
      // if (T->getModule()) {
      //   llvm::ModulePass* globalDCE = llvm::createGlobalDCEPass();
      //   globalDCE->runOnModule(*T->getModule());
      // }

      Successful = unloadModule(T->getModule()) && Successful;
    }

    // Clean up the pending instantiations
    m_Sema->PendingInstantiations.clear();
    m_Sema->PendingLocalImplicitInstantiations.clear();

    DeclUnloader DeclU(m_Sema, m_CodeGen, T);
    Successful = unloadDeclarations(T, DeclU) && Successful;
    Successful = unloadDeserializedDeclarations(T, DeclU) && Successful;
    Successful = unloadFromPreprocessor(T, DeclU) && Successful;

#ifndef NDEBUG
    //FIXME: Move the nested transaction marker out of the decl lists and
    // reenable this assertion.
    //size_t DeclSize = std::distance(T->decls_begin(), T->decls_end());
    //if (T->getCompilationOpts().CodeGenerationForModule)
    //  assert (!DeclSize && "No parsed decls must happen in parse for module");
#endif

    if (Successful)
      T->setState(Transaction::kRolledBack);
    else
      T->setState(Transaction::kRolledBackWithErrors);

    // Release the input_line_X file unless verifying diagnostics.
    if (!m_Interp->getCI()->getDiagnosticOpts().VerifyDiagnostics)
      m_Sema->getSourceManager().invalidateCache(T->getBufferFID());

    return Successful;
  }

  bool TransactionUnloader::UnloadDecl(Decl* D) {
    return cling::UnloadDecl(m_Sema, m_CodeGen, D);
  }

  bool TransactionUnloader::unloadModule(llvm::Module* M) {
    for (auto& Func: M->functions())
      m_CodeGen->forgetGlobal(&Func);
    for (auto& Glob: M->globals())
      m_CodeGen->forgetGlobal(&Glob);
    return true;
  }
} // end namespace cling
<|endoftext|>