<commit_before>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://www.visualizationlibrary.com                                               */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  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.                                   */
/*                                                                                */
/*  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 COPYRIGHT HOLDER 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 <vl/Extrusion.hpp>
#include <vl/Tessellator.hpp>
#include <vl/GLSLmath.hpp>

using namespace vl;

ref<Geometry> Extrusion::extrude()
{
  if (silhouette().empty())
  {
    Log::error("Extrusion::extrude(): no silhouette defined.\n");
    return NULL;
  }
  if (positionPath().empty())
  {
    Log::error("Extrusion::extrude() needs at least a non empty positionPath().\n");
    return NULL;
  }
  if (!scalingPath().empty() && scalingPath().size() != positionPath().size()-2)
  {
    Log::error("Extrusion::extrude(): scalingPath() must have the same number of control points as positionPath().\n");
    return NULL;
  }
  if (!rotationPath().empty() && rotationPath().size() != positionPath().size()-2)
  {
    Log::error("Extrusion::extrude(): rotationPath() must have the same number of control points as positionPath().\n");
    return NULL;
  }
  if (!colorPath().empty() && colorPath().size() != positionPath().size()-2)
  {
    Log::error("Extrusion::extrude(): colorPath() must have the same number of control points as positionPath().\n");
    return NULL;
  }

  ref<Geometry> geom = new Geometry;

  int segments = positionPath().size()-2;

  std::vector<fvec3> verts;
  verts.resize( silhouette().size() * segments );

  vl::fmat4 m = fmat4::rotation(fvec3(0,1,0),positionPath()[1]-positionPath()[0]);

  // initialize silhouette on the x/z plane
  std::vector<vl::fvec3> projected_sil;
  projected_sil.resize(silhouette().size());
  for(unsigned i=0; i<silhouette().size(); ++i)
  {
    projected_sil[i] = m * vl::fvec3(silhouette()[i].x(),0,silhouette()[i].y()) + positionPath()[0];
  }

  // initialize plane normals from 1 to n-1 (end points are excluded)
  std::vector<fvec3> plane_normals;
  plane_normals.resize(positionPath().size());
  for(unsigned i=1; i<plane_normals.size()-1; ++i)
  {
    fvec3 p0 = positionPath()[i-1] - positionPath()[i];
    fvec3 p1 = positionPath()[i+1] - positionPath()[i];
    p0.normalize();
    p1.normalize();
    plane_normals[i] = (p1-p0).normalize();
  }

  for(unsigned i=1; i<positionPath().size()-1; ++i)
  {
    for(int j=0; j<(int)silhouette().size(); ++j)
    {
      fvec3 V = (positionPath()[i] - positionPath()[i-1]).normalize();
      const fvec3& P = projected_sil[j];
      const fvec3& orig = positionPath()[i];
      const fvec3& N = plane_normals [i];
      float d = dot(N,orig);
      float t = dot(V,N) ? (d-dot(P,N))/dot(V,N) : 0 /*error*/;
      // project current projected_sil on next plane along p0->p1 vector
      verts.at(j+silhouette().size()*(i-1)) = projected_sil[j] = P + V*t;
    }
  }

  // rotation
  if(!rotationPath().empty())
  {
    for(unsigned i=1; i<positionPath().size()-1; ++i)
    {
      fvec3 r = (positionPath()[i+1] - positionPath()[i]).normalize();
      fmat4 mat = vl::fmat4::rotation(rotationPath()[i-1],r);
      fvec3 c;
      for(int j=0; j<(int)silhouette().size(); ++j)
        c += verts.at(j+silhouette().size()*(i-1));
      c /= (float)silhouette().size();
      for(int j=0; j<(int)silhouette().size(); ++j)
        verts.at(j+silhouette().size()*(i-1)) = (mat*(verts.at(j+silhouette().size()*(i-1))-c))+c;
    }
  }

  // scaling
  if(!scalingPath().empty())
  {
    for(unsigned i=1; i<positionPath().size()-1; ++i)
    {
      float s = scalingPath()[i-1];
      fvec3 c;
      for(int j=0; j<(int)silhouette().size(); ++j)
        c += verts.at(j+silhouette().size()*(i-1));
      c /= (float)silhouette().size();
      for(int j=0; j<(int)silhouette().size(); ++j)
        verts.at(j+silhouette().size()*(i-1)) = (s*(verts.at(j+silhouette().size()*(i-1))-c))+c;
    }
  }

  int prof_count = silhouetteMode() == SilhouetteClosed ? (int)silhouette().size() : (int)silhouette().size()-1;
  ref<DrawElementsUInt> de = new DrawElementsUInt(PT_QUADS);
  geom->primitives()->push_back(de.get());
  de->indices()->resize(4 * prof_count * (segments-1));
  for(int iseg=0; iseg<segments-1; ++iseg)
  {
    for(int iquad=0; iquad<prof_count; ++iquad)
    {
      de->indices()->at(iquad*4+iseg*4*prof_count + 3) = (iseg + 0) * (GLuint)silhouette().size() + iquad;
      de->indices()->at(iquad*4+iseg*4*prof_count + 2) = (iseg + 0) * (GLuint)silhouette().size() + (iquad+1)%silhouette().size();
      de->indices()->at(iquad*4+iseg*4*prof_count + 1) = (iseg + 1) * (GLuint)silhouette().size() + (iquad+1)%silhouette().size();
      de->indices()->at(iquad*4+iseg*4*prof_count + 0) = (iseg + 1) * (GLuint)silhouette().size() + iquad;
    }
  }

  // bottom/top caps

  size_t tess_bottom_count = 0;
  size_t tess_top_count    = 0;

  if(fillBottom())
  {
    unsigned start = verts.size();
    Tessellator tessellator;
    tessellator.contours().push_back((int)silhouette().size());
    for(unsigned i=0; i<silhouette().size(); ++i)
      tessellator.contourVerts().push_back((dvec3)verts[i]);
    tessellator.setWindingRule(vl::TW_TESS_WINDING_NONZERO);
    tessellator.tessellate();
    for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
      verts.push_back(tessellator.tessellatedTris()[i]);
    if (tessellator.tessellatedTris().size())
      geom->primitives()->push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
    tess_bottom_count = tessellator.tessellatedTris().size();
  }
  if(fillTop())
  {
    unsigned start = verts.size();
    Tessellator tessellator;
    tessellator.contours().push_back(silhouette().size());
    for(unsigned i=0; i<silhouette().size(); ++i)
      tessellator.contourVerts().push_back((dvec3)verts[verts.size()-i-1-tess_bottom_count]);
    tessellator.setWindingRule(vl::TW_TESS_WINDING_NONZERO);
    tessellator.tessellate();
    for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
      verts.push_back(tessellator.tessellatedTris()[i]);
    if (tessellator.tessellatedTris().size())
      geom->primitives()->push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
    tess_top_count = tessellator.tessellatedTris().size();
  }

  ref<ArrayFVec3> vert_array = new ArrayFVec3;
  geom->setVertexArray( vert_array.get() );
  *vert_array = verts;

  if (!colorPath().empty())
  {
    ref<ArrayFVec4> col_array = new ArrayFVec4;
    geom->setColorArray(col_array.get());
    col_array->resize(geom->vertexArray()->size());
    int offs = 0;
    for(int iseg=0; iseg<segments; ++iseg)
    {
      for(unsigned j=0; j<silhouette().size(); ++j, ++offs)
        col_array->at(offs) = colorPath()[iseg];
    }
    if (fillBottom())
    {
      for(unsigned j=0; j<tess_bottom_count; ++j, ++offs)
        col_array->at(offs) = colorPath()[0];
    }
    if (fillTop())
    {
      for(unsigned j=0; j<tess_top_count; ++j, ++offs)
        col_array->at(offs) = colorPath().back();
    }
  }

  if (!smooth())
    geom->convertPrimitivesToDrawArrays();

  geom->computeNormals();

  return geom;
}
<commit_msg>compilation fix<commit_after>/**************************************************************************************/
/*                                                                                */
/*  Visualization Library                                                             */
/*  http://www.visualizationlibrary.com                                               */
/*                                                                                */
/*  Copyright (c) 2005-2010, Michele Bosi                                             */
/*  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.                                   */
/*                                                                                */
/*  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 COPYRIGHT HOLDER 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 <vl/Extrusion.hpp>
#include <vl/Tessellator.hpp>
#include <vl/GLSLmath.hpp>

using namespace vl;

ref<Geometry> Extrusion::extrude()
{
  if (silhouette().empty())
  {
    Log::error("Extrusion::extrude(): no silhouette defined.\n");
    return NULL;
  }
  if (positionPath().empty())
  {
    Log::error("Extrusion::extrude() needs at least a non empty positionPath().\n");
    return NULL;
  }
  if (!scalingPath().empty() && scalingPath().size() != positionPath().size()-2)
  {
    Log::error("Extrusion::extrude(): scalingPath() must have the same number of control points as positionPath().\n");
    return NULL;
  }
  if (!rotationPath().empty() && rotationPath().size() != positionPath().size()-2)
  {
    Log::error("Extrusion::extrude(): rotationPath() must have the same number of control points as positionPath().\n");
    return NULL;
  }
  if (!colorPath().empty() && colorPath().size() != positionPath().size()-2)
  {
    Log::error("Extrusion::extrude(): colorPath() must have the same number of control points as positionPath().\n");
    return NULL;
  }

  ref<Geometry> geom = new Geometry;

  int segments = positionPath().size()-2;

  std::vector<fvec3> verts;
  verts.resize( silhouette().size() * segments );

  vl::fmat4 m = fmat4::rotation(fvec3(0,1,0),positionPath()[1]-positionPath()[0]);

  // initialize silhouette on the x/z plane
  std::vector<vl::fvec3> projected_sil;
  projected_sil.resize(silhouette().size());
  for(unsigned i=0; i<silhouette().size(); ++i)
  {
    projected_sil[i] = m * vl::fvec3(silhouette()[i].x(),0,silhouette()[i].y()) + positionPath()[0];
  }

  // initialize plane normals from 1 to n-1 (end points are excluded)
  std::vector<fvec3> plane_normals;
  plane_normals.resize(positionPath().size());
  for(unsigned i=1; i<plane_normals.size()-1; ++i)
  {
    fvec3 p0 = positionPath()[i-1] - positionPath()[i];
    fvec3 p1 = positionPath()[i+1] - positionPath()[i];
    p0.normalize();
    p1.normalize();
    plane_normals[i] = (p1-p0).normalize();
  }

  for(unsigned i=1; i<positionPath().size()-1; ++i)
  {
    for(int j=0; j<(int)silhouette().size(); ++j)
    {
      fvec3 V = (positionPath()[i] - positionPath()[i-1]).normalize();
      const fvec3& P = projected_sil[j];
      const fvec3& orig = positionPath()[i];
      const fvec3& N = plane_normals [i];
      float d = dot(N,orig);
      float t = dot(V,N) ? (d-dot(P,N))/dot(V,N) : 0 /*error*/;
      // project current projected_sil on next plane along p0->p1 vector
      verts.at(j+silhouette().size()*(i-1)) = projected_sil[j] = P + V*t;
    }
  }

  // rotation
  if(!rotationPath().empty())
  {
    for(unsigned i=1; i<positionPath().size()-1; ++i)
    {
      fvec3 r = (positionPath()[i+1] - positionPath()[i]).normalize();
      fmat4 mat = vl::fmat4::rotation(rotationPath()[i-1],r);
      fvec3 c;
      for(int j=0; j<(int)silhouette().size(); ++j)
        c += verts.at(j+silhouette().size()*(i-1));
      c /= (float)silhouette().size();
      for(int j=0; j<(int)silhouette().size(); ++j)
        verts.at(j+silhouette().size()*(i-1)) = (mat*(verts.at(j+silhouette().size()*(i-1))-c))+c;
    }
  }

  // scaling
  if(!scalingPath().empty())
  {
    for(unsigned i=1; i<positionPath().size()-1; ++i)
    {
      float s = scalingPath()[i-1];
      fvec3 c;
      for(int j=0; j<(int)silhouette().size(); ++j)
        c += verts.at(j+silhouette().size()*(i-1));
      c /= (float)silhouette().size();
      for(int j=0; j<(int)silhouette().size(); ++j)
        verts.at(j+silhouette().size()*(i-1)) = (s*(verts.at(j+silhouette().size()*(i-1))-c))+c;
    }
  }

  int prof_count = silhouetteMode() == SilhouetteClosed ? (int)silhouette().size() : (int)silhouette().size()-1;
  ref<DrawElementsUInt> de = new DrawElementsUInt(PT_QUADS);
  geom->primitives()->push_back(de.get());
  de->indices()->resize(4 * prof_count * (segments-1));
  for(int iseg=0; iseg<segments-1; ++iseg)
  {
    for(int iquad=0; iquad<prof_count; ++iquad)
    {
      de->indices()->at(iquad*4+iseg*4*prof_count + 3) = (iseg + 0) * (GLuint)silhouette().size() + iquad;
      de->indices()->at(iquad*4+iseg*4*prof_count + 2) = (iseg + 0) * (GLuint)silhouette().size() + (iquad+1)%silhouette().size();
      de->indices()->at(iquad*4+iseg*4*prof_count + 1) = (iseg + 1) * (GLuint)silhouette().size() + (iquad+1)%silhouette().size();
      de->indices()->at(iquad*4+iseg*4*prof_count + 0) = (iseg + 1) * (GLuint)silhouette().size() + iquad;
    }
  }

  // bottom/top caps

  size_t tess_bottom_count = 0;
  size_t tess_top_count    = 0;

  if(fillBottom())
  {
    unsigned start = verts.size();
    Tessellator tessellator;
    tessellator.contours().push_back((int)silhouette().size());
    for(unsigned i=0; i<silhouette().size(); ++i)
      tessellator.contourVerts().push_back((dvec3)verts[i]);
    tessellator.setWindingRule(vl::TW_TESS_WINDING_NONZERO);
    tessellator.tessellate();
    for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
      verts.push_back(tessellator.tessellatedTris()[i]);
    if (tessellator.tessellatedTris().size())
      geom->primitives()->push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
    tess_bottom_count = tessellator.tessellatedTris().size();
  }
  if(fillTop())
  {
    unsigned start = verts.size();
    Tessellator tessellator;
    tessellator.contours().push_back(silhouette().size());
    for(unsigned i=0; i<silhouette().size(); ++i)
      tessellator.contourVerts().push_back((dvec3)verts[verts.size()-i-1-tess_bottom_count]);
    tessellator.setWindingRule(vl::TW_TESS_WINDING_NONZERO);
    tessellator.tessellate();
    for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
      verts.push_back(tessellator.tessellatedTris()[i]);
    if (tessellator.tessellatedTris().size())
      geom->primitives()->push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
    tess_top_count = tessellator.tessellatedTris().size();
  }

  ref<ArrayFVec3> vert_array = new ArrayFVec3;
  geom->setVertexArray( vert_array.get() );
  *vert_array = verts;

  if (!colorPath().empty())
  {
    ref<ArrayFVec4> col_array = new ArrayFVec4;
    geom->setColorArray(col_array.get());
    col_array->resize(geom->vertexArray()->size());
    int offs = 0;
    for(int iseg=0; iseg<segments; ++iseg)
    {
      for(unsigned j=0; j<silhouette().size(); ++j, ++offs)
        col_array->at(offs) = colorPath()[iseg];
    }
    if (fillBottom())
    {
      for(unsigned j=0; j<tess_bottom_count; ++j, ++offs)
        col_array->at(offs) = colorPath()[0];
    }
    if (fillTop())
    {
      for(unsigned j=0; j<tess_top_count; ++j, ++offs)
        col_array->at(offs) = colorPath().back();
    }
  }

  if (!smooth())
    geom->convertDrawElementsToDrawArrays();

  geom->computeNormals();

  return geom;
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkProgrammableFilter.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 "vtkProgrammableFilter.h"
#include "vtkPolyData.h"
#include "vtkStructuredGrid.h"
#include "vtkStructuredPoints.h"
#include "vtkUnstructuredGrid.h"
#include "vtkRectilinearGrid.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"

vtkCxxRevisionMacro(vtkProgrammableFilter, "1.21");
vtkStandardNewMacro(vtkProgrammableFilter);

// Construct programmable filter with empty execute method.
vtkProgrammableFilter::vtkProgrammableFilter()
{
  this->ExecuteMethod = NULL;
  this->ExecuteMethodArg = NULL;
  this->ExecuteMethodArgDelete = NULL;
}

vtkProgrammableFilter::~vtkProgrammableFilter()
{
  // delete the current arg if there is one and a delete meth
  if ((this->ExecuteMethodArg)&&(this->ExecuteMethodArgDelete))
    {
    (*this->ExecuteMethodArgDelete)(this->ExecuteMethodArg);
    }
}

// Get the input as a concrete type. This method is typically used by the
// writer of the filter function to get the input as a particular type (i.e.,
// it essentially does type casting). It is the users responsibility to know
// the correct type of the input data.
vtkPolyData *vtkProgrammableFilter::GetPolyDataInput()
{
  return (vtkPolyData *)this->GetInput();
}

// Get the input as a concrete type.
vtkStructuredPoints *vtkProgrammableFilter::GetStructuredPointsInput()
{
  return (vtkStructuredPoints *)this->GetInput();
}

// Get the input as a concrete type.
vtkStructuredGrid *vtkProgrammableFilter::GetStructuredGridInput()
{
  return (vtkStructuredGrid *)this->GetInput();
}

// Get the input as a concrete type.
vtkUnstructuredGrid *vtkProgrammableFilter::GetUnstructuredGridInput()
{
  return (vtkUnstructuredGrid *)this->GetInput();
}

// Get the input as a concrete type.
vtkRectilinearGrid *vtkProgrammableFilter::GetRectilinearGridInput()
{
  return (vtkRectilinearGrid *)this->GetInput();
}

// Specify the function to use to operate on the point attribute data. Note
// that the function takes a single (void *) argument.
void vtkProgrammableFilter::SetExecuteMethod(void (*f)(void *), void *arg)
{
  if ( f != this->ExecuteMethod || arg != this->ExecuteMethodArg )
    {
    // delete the current arg if there is one and a delete meth
    if ((this->ExecuteMethodArg)&&(this->ExecuteMethodArgDelete))
      {
      (*this->ExecuteMethodArgDelete)(this->ExecuteMethodArg);
      }
    this->ExecuteMethod = f;
    this->ExecuteMethodArg = arg;
    this->Modified();
    }
}

// Set the arg delete method. This is used to free user memory.
void vtkProgrammableFilter::SetExecuteMethodArgDelete(void (*f)(void *))
{
  if ( f != this->ExecuteMethodArgDelete)
    {
    this->ExecuteMethodArgDelete = f;
    this->Modified();
    }
}

int vtkProgrammableFilter::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  // get the info objects
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  // get the input and ouptut
  vtkDataSet *input = vtkDataSet::SafeDownCast(
    inInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkDataSet *output = vtkDataSet::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  vtkDebugMacro(<<"Executing programmable filter");

  // First, copy the input to the output as a starting point
  output->CopyStructure( input );

  // Now invoke the procedure, if specified.
  if ( this->ExecuteMethod != NULL )
    {
    (*this->ExecuteMethod)(this->ExecuteMethodArg);
    }

  return 1;
}

<commit_msg>ENH: Add the python programmable filter<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkProgrammableFilter.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 "vtkProgrammableFilter.h"
#include "vtkPolyData.h"
#include "vtkStructuredGrid.h"
#include "vtkStructuredPoints.h"
#include "vtkUnstructuredGrid.h"
#include "vtkRectilinearGrid.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"

vtkCxxRevisionMacro(vtkProgrammableFilter, "1.22");
vtkStandardNewMacro(vtkProgrammableFilter);

// Construct programmable filter with empty execute method.
vtkProgrammableFilter::vtkProgrammableFilter()
{
  this->ExecuteMethod = NULL;
  this->ExecuteMethodArg = NULL;
  this->ExecuteMethodArgDelete = NULL;
}

vtkProgrammableFilter::~vtkProgrammableFilter()
{
  // delete the current arg if there is one and a delete meth
  if ((this->ExecuteMethodArg)&&(this->ExecuteMethodArgDelete))
    {
    (*this->ExecuteMethodArgDelete)(this->ExecuteMethodArg);
    }
}

// Get the input as a concrete type. This method is typically used by the
// writer of the filter function to get the input as a particular type (i.e.,
// it essentially does type casting). It is the users responsibility to know
// the correct type of the input data.
vtkPolyData *vtkProgrammableFilter::GetPolyDataInput()
{
  return (vtkPolyData *)this->GetInput();
}

// Get the input as a concrete type.
vtkStructuredPoints *vtkProgrammableFilter::GetStructuredPointsInput()
{
  return (vtkStructuredPoints *)this->GetInput();
}

// Get the input as a concrete type.
vtkStructuredGrid *vtkProgrammableFilter::GetStructuredGridInput()
{
  return (vtkStructuredGrid *)this->GetInput();
}

// Get the input as a concrete type.
vtkUnstructuredGrid *vtkProgrammableFilter::GetUnstructuredGridInput()
{
  return (vtkUnstructuredGrid *)this->GetInput();
}

// Get the input as a concrete type.
vtkRectilinearGrid *vtkProgrammableFilter::GetRectilinearGridInput()
{
  return (vtkRectilinearGrid *)this->GetInput();
}

// Specify the function to use to operate on the point attribute data. Note
// that the function takes a single (void *) argument.
void vtkProgrammableFilter::SetExecuteMethod(void (*f)(void *), void *arg)
{
  if ( f != this->ExecuteMethod || arg != this->ExecuteMethodArg )
    {
    // delete the current arg if there is one and a delete meth
    if ((this->ExecuteMethodArg)&&(this->ExecuteMethodArgDelete))
      {
      (*this->ExecuteMethodArgDelete)(this->ExecuteMethodArg);
      }
    this->ExecuteMethod = f;
    this->ExecuteMethodArg = arg;
    this->Modified();
    }
}

// Set the arg delete method. This is used to free user memory.
void vtkProgrammableFilter::SetExecuteMethodArgDelete(void (*f)(void *))
{
  if ( f != this->ExecuteMethodArgDelete)
    {
    this->ExecuteMethodArgDelete = f;
    this->Modified();
    }
}

int vtkProgrammableFilter::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  // get the info objects
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  // get the input and ouptut
  vtkDataSet *input = vtkDataSet::SafeDownCast(
    inInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkDataSet *output = vtkDataSet::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  vtkDebugMacro(<<"Executing programmable filter");

  // First, copy the input to the output as a starting point
  if (input->GetDataObjectType() == output->GetDataObjectType())
    {
    output->CopyStructure( input );
    }

  // Now invoke the procedure, if specified.
  if ( this->ExecuteMethod != NULL )
    {
    (*this->ExecuteMethod)(this->ExecuteMethodArg);
    }

  return 1;
}

<|endoftext|>


<commit_before>#include "mainwindow.h"

#include <QX11Info>
#include <stdlib.h>
#include <QtCore>
#include <QtGui>

#include <maliit/namespace.h>
#include <maliit/inputmethod.h>

namespace {
    const char * const TextPrompt = "Double-click this text area to invoke virtual keyboard ...";
    const char * const ImModuleEnv = "QT_IM_MODULE";
    const char * const ExpectedImModule = "MInputContext";
    const QString serverName("maliit-server"); //TODO: when maliit and example application is split out, look up in .pc file

    QString checkForErrors()
    {
        const char * const imModule = getenv(ImModuleEnv);
        QString errorMsg;

        if (not imModule
            || (0 != strcmp(getenv(ImModuleEnv), ExpectedImModule))) {
            errorMsg.append(QString("You will not be able to use the virtual keyboard. The " \
                                    "environment variable %1 must be set to %2.")
                            .arg(ImModuleEnv)
                            .arg(ExpectedImModule));
        }

        if (not QX11Info::isCompositingManagerRunning()) {
            if (not errorMsg.isEmpty()) {
                errorMsg.append("\n");
            }

            errorMsg.append(QString("No compositing window manager found. You might be able to run the " \
                            "Maliit server in self-compositing mode:\n" \
                            "$ %1 -use-self-composition -manual-redirection").arg(serverName));
        }

        return errorMsg;
    }

    bool enableFullScreenMode()
    {
        return (qApp->arguments().contains("-fullscreen"));
    }
}

class MyTextEdit
    : public QTextEdit
{
private:
    bool wasFocused;

public:
    MyTextEdit()
        : QTextEdit(TextPrompt)
        , wasFocused(false)
    {}

protected:
    void focusInEvent(QFocusEvent *e)
    {
        toPlainText();
        // On first text edit, clear pre-set TextPrompt:
        if (not wasFocused && toPlainText() == QString(TextPrompt)) {
            wasFocused = true;
            setText("");
        }

        QTextEdit::focusInEvent(e);
    }
};

MainWindow::MainWindow()
    : QMainWindow()
    , serverProcess(new QProcess(this))
    , orientationIndex(0)
    , startServerButton(new QPushButton)
    , rotateKeyboardButton(new QPushButton)
    , textEdit(new QTextEdit)
{
    serverProcess->setProcessChannelMode(QProcess::ForwardedChannels);
    connect(serverProcess, SIGNAL(error(QProcess::ProcessError)),
            this, SLOT(onServerError()));
    connect(serverProcess, SIGNAL(stateChanged(QProcess::ProcessState)),
            this, SLOT(onServerStateChanged()));

    connect(startServerButton, SIGNAL(clicked()),
            this, SLOT(onStartServerClicked()));
    connect(rotateKeyboardButton, SIGNAL(clicked()),
            this, SLOT(onRotateKeyboardClicked()));

    initUI();
    onServerStateChanged();
}

void MainWindow::initUI()
{
    setWindowTitle("Maliit test application");

    QVBoxLayout *vbox = new QVBoxLayout();

    rotateKeyboardButton->setText("Rotate keyboard");
    vbox->addWidget(startServerButton);
    vbox->addWidget(rotateKeyboardButton);

    // Clicking the button will steal focus from the text edit, thus hiding
    // the virtual keyboard:
    QPushButton *hideVkb = new QPushButton("Hide virtual keyboard");
    vbox->addWidget(hideVkb);
    vbox->addWidget(textEdit);

    // But don't want other buttons to steal focus:
    startServerButton->setFocusProxy(textEdit);
    rotateKeyboardButton->setFocusProxy(textEdit);

    QPushButton *closeApp = new QPushButton("Close application");
    vbox->addWidget(closeApp);
    connect(closeApp, SIGNAL(clicked()),
            this,     SLOT(close()));

    setCentralWidget(new QWidget);
    centralWidget()->setLayout(vbox);

    if (enableFullScreenMode()) {
        showFullScreen();
    } else {
        show();
    }
}

MainWindow::~MainWindow()
{
    serverProcess->terminate();
}

void MainWindow::onStartServerClicked()
{

    QStringList arguments;
    arguments << "-bypass-wm-hint";

    // Self-compositing is currently only supported in fullscreen mode:
    if (enableFullScreenMode()) {
        arguments << "-use-self-composition";
    }

    if (serverProcess->state() != QProcess::NotRunning) {
        serverProcess->terminate();
    } else {
        serverProcess->start(serverName, arguments);
    }
}

void MainWindow::onServerError()
{
    textEdit->setText(serverProcess->errorString());
}

void MainWindow::onServerStateChanged()
{
    switch (serverProcess->state()) {
    case QProcess::Running:
        startServerButton->setText("(running) Stop input method server");
        break;
    case QProcess::Starting:
        startServerButton->setText("(starting) Stop input method server");
        break;
    case QProcess::NotRunning:
        startServerButton->setText("(stopped) Start input method server");
    default:
        break;
    }
}

void MainWindow::onRotateKeyboardClicked()
{
    const Maliit::OrientationAngle orientations[] = {Maliit::Angle0,
                                                     Maliit::Angle90,
                                                     Maliit::Angle180,
                                                     Maliit::Angle270};
    orientationIndex++;
    if (orientationIndex >= 4) {
        orientationIndex = 0;
    }
    const Maliit::OrientationAngle angle = orientations[orientationIndex];

    //! [Get singleton InputMethod instance]
    Maliit::InputMethod::instance()->setOrientationAngle(angle);
    //! [Get singleton InputMethod instance]
}
<commit_msg>Only use QX11Info on X11 platform<commit_after>#include "mainwindow.h"

#include <stdlib.h>
#include <QtCore>
#include <QtGui>

#if defined(Q_WS_X11)
#include <QX11Info>
#endif

#include <maliit/namespace.h>
#include <maliit/inputmethod.h>

namespace {
    const char * const TextPrompt = "Double-click this text area to invoke virtual keyboard ...";
    const char * const ImModuleEnv = "QT_IM_MODULE";
    const char * const ExpectedImModule = "MInputContext";
    const QString serverName("maliit-server"); //TODO: when maliit and example application is split out, look up in .pc file

    QString checkForErrors()
    {
        const char * const imModule = getenv(ImModuleEnv);
        QString errorMsg;

        if (not imModule
            || (0 != strcmp(getenv(ImModuleEnv), ExpectedImModule))) {
            errorMsg.append(QString("You will not be able to use the virtual keyboard. The " \
                                    "environment variable %1 must be set to %2.")
                            .arg(ImModuleEnv)
                            .arg(ExpectedImModule));
        }

#if defined(Q_WS_X11)
        if (not QX11Info::isCompositingManagerRunning()) {
            if (not errorMsg.isEmpty()) {
                errorMsg.append("\n");
            }

            errorMsg.append(QString("No compositing window manager found. You might be able to run the " \
                            "Maliit server in self-compositing mode:\n" \
                            "$ %1 -use-self-composition -manual-redirection").arg(serverName));
        }
#endif

        return errorMsg;
    }

    bool enableFullScreenMode()
    {
        return (qApp->arguments().contains("-fullscreen"));
    }
}

class MyTextEdit
    : public QTextEdit
{
private:
    bool wasFocused;

public:
    MyTextEdit()
        : QTextEdit(TextPrompt)
        , wasFocused(false)
    {}

protected:
    void focusInEvent(QFocusEvent *e)
    {
        toPlainText();
        // On first text edit, clear pre-set TextPrompt:
        if (not wasFocused && toPlainText() == QString(TextPrompt)) {
            wasFocused = true;
            setText("");
        }

        QTextEdit::focusInEvent(e);
    }
};

MainWindow::MainWindow()
    : QMainWindow()
    , serverProcess(new QProcess(this))
    , orientationIndex(0)
    , startServerButton(new QPushButton)
    , rotateKeyboardButton(new QPushButton)
    , textEdit(new QTextEdit)
{
    serverProcess->setProcessChannelMode(QProcess::ForwardedChannels);
    connect(serverProcess, SIGNAL(error(QProcess::ProcessError)),
            this, SLOT(onServerError()));
    connect(serverProcess, SIGNAL(stateChanged(QProcess::ProcessState)),
            this, SLOT(onServerStateChanged()));

    connect(startServerButton, SIGNAL(clicked()),
            this, SLOT(onStartServerClicked()));
    connect(rotateKeyboardButton, SIGNAL(clicked()),
            this, SLOT(onRotateKeyboardClicked()));

    initUI();
    onServerStateChanged();
}

void MainWindow::initUI()
{
    setWindowTitle("Maliit test application");

    QVBoxLayout *vbox = new QVBoxLayout();

    rotateKeyboardButton->setText("Rotate keyboard");
    vbox->addWidget(startServerButton);
    vbox->addWidget(rotateKeyboardButton);

    // Clicking the button will steal focus from the text edit, thus hiding
    // the virtual keyboard:
    QPushButton *hideVkb = new QPushButton("Hide virtual keyboard");
    vbox->addWidget(hideVkb);
    vbox->addWidget(textEdit);

    // But don't want other buttons to steal focus:
    startServerButton->setFocusProxy(textEdit);
    rotateKeyboardButton->setFocusProxy(textEdit);

    QPushButton *closeApp = new QPushButton("Close application");
    vbox->addWidget(closeApp);
    connect(closeApp, SIGNAL(clicked()),
            this,     SLOT(close()));

    setCentralWidget(new QWidget);
    centralWidget()->setLayout(vbox);

    if (enableFullScreenMode()) {
        showFullScreen();
    } else {
        show();
    }
}

MainWindow::~MainWindow()
{
    serverProcess->terminate();
}

void MainWindow::onStartServerClicked()
{

    QStringList arguments;
    arguments << "-bypass-wm-hint";

    // Self-compositing is currently only supported in fullscreen mode:
    if (enableFullScreenMode()) {
        arguments << "-use-self-composition";
    }

    if (serverProcess->state() != QProcess::NotRunning) {
        serverProcess->terminate();
    } else {
        serverProcess->start(serverName, arguments);
    }
}

void MainWindow::onServerError()
{
    textEdit->setText(serverProcess->errorString());
}

void MainWindow::onServerStateChanged()
{
    switch (serverProcess->state()) {
    case QProcess::Running:
        startServerButton->setText("(running) Stop input method server");
        break;
    case QProcess::Starting:
        startServerButton->setText("(starting) Stop input method server");
        break;
    case QProcess::NotRunning:
        startServerButton->setText("(stopped) Start input method server");
    default:
        break;
    }
}

void MainWindow::onRotateKeyboardClicked()
{
    const Maliit::OrientationAngle orientations[] = {Maliit::Angle0,
                                                     Maliit::Angle90,
                                                     Maliit::Angle180,
                                                     Maliit::Angle270};
    orientationIndex++;
    if (orientationIndex >= 4) {
        orientationIndex = 0;
    }
    const Maliit::OrientationAngle angle = orientations[orientationIndex];

    //! [Get singleton InputMethod instance]
    Maliit::InputMethod::instance()->setOrientationAngle(angle);
    //! [Get singleton InputMethod instance]
}
<|endoftext|>


<commit_before>#include "ex14_16_StrBlob.h"

//==================================================================
//
//		operators
//
//==================================================================

bool operator==(const StrBlob &lhs, const StrBlob &rhs)
{
	return *lhs.data == *rhs.data;
}

bool operator!=(const StrBlob &lhs, const StrBlob &rhs)
{
	return !(lhs == rhs);
}

bool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
	return lhs.curr == rhs.curr;
}

bool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
	return !(lhs == rhs);
}

bool operator==(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
	return lhs.curr == rhs.curr;
}

bool operator!=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
	return !(lhs == rhs);
}

//==================================================================
//
//		copy assignment operator and move assignment operator.
//
//==================================================================

StrBlob& StrBlob::operator=(const StrBlob &lhs)
{
	data = make_shared<vector<string>>(*lhs.data);
	return *this;
}

StrBlob& StrBlob::operator=(StrBlob &&rhs) NOEXCEPT
{
	if (this != &rhs) {
		data = std::move(rhs.data);
		rhs.data = nullptr;
	}

	return *this;
}

//==================================================================
//
//		members
//
//==================================================================

StrBlobPtr StrBlob::begin()
{
	return StrBlobPtr(*this);
}

StrBlobPtr StrBlob::end()
{
	return StrBlobPtr(*this, data->size());
}

ConstStrBlobPtr StrBlob::cbegin() const
{
    return ConstStrBlobPtr(*this);
}

ConstStrBlobPtr StrBlob::cend() const
{
    return ConstStrBlobPtr(*this, data->size());
}
<commit_msg>Update ex14_16_StrBlob.cpp<commit_after>#include "ex14_16_StrBlob.h"

//==================================================================
//
//		operators
//
//==================================================================

bool operator==(const StrBlob &lhs, const StrBlob &rhs)
{
    return *lhs.data == *rhs.data;
}

bool operator!=(const StrBlob &lhs, const StrBlob &rhs)
{
    return !(lhs == rhs);
}

bool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
    return lhs.curr == rhs.curr;
}

bool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
    return !(lhs == rhs);
}

bool operator==(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
    return lhs.curr == rhs.curr;
}

bool operator!=(const ConstStrBlobPtr &lhs, const ConstStrBlobPtr &rhs)
{
    return !(lhs == rhs);
}

//==================================================================
//
//		copy assignment operator and move assignment operator.
//
//==================================================================

StrBlob& StrBlob::operator=(const StrBlob &lhs)
{
    data = make_shared<vector<string>>(*lhs.data);
    return *this;
}

StrBlob& StrBlob::operator=(StrBlob &&rhs) NOEXCEPT
{
    if (this != &rhs) {
        data = std::move(rhs.data);
        rhs.data = nullptr;
    }

    return *this;
}

//==================================================================
//
//		members
//
//==================================================================

StrBlobPtr StrBlob::begin()
{
    return StrBlobPtr(*this);
}

StrBlobPtr StrBlob::end()
{
    return StrBlobPtr(*this, data->size());
}

ConstStrBlobPtr StrBlob::cbegin() const
{
    return ConstStrBlobPtr(*this);
}

ConstStrBlobPtr StrBlob::cend() const
{
    return ConstStrBlobPtr(*this, data->size());
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Christian <c@ethdev.com>
 * @date 2014
 * Solidity compiler.
 */

#include <algorithm>
#include <libsolidity/AST.h>
#include <libsolidity/Compiler.h>
#include <libsolidity/ExpressionCompiler.h>

using namespace std;

namespace dev {
namespace solidity {

bytes Compiler::compile(ContractDefinition& _contract)
{
	Compiler compiler;
	compiler.compileContract(_contract);
	return compiler.m_context.getAssembledBytecode();
}

void Compiler::compileContract(ContractDefinition& _contract)
{
	m_context = CompilerContext(); // clear it just in case

	//@todo constructor
	//@todo register state variables

	for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions())
		m_context.addFunction(*function);

	appendFunctionSelector(_contract.getDefinedFunctions());
	for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions())
		function->accept(*this);

	packIntoContractCreator();
}

void Compiler::packIntoContractCreator()
{
	CompilerContext creatorContext;
	eth::AssemblyItem sub = creatorContext.addSubroutine(m_context.getAssembly());
	// stack contains sub size
	creatorContext << eth::Instruction::DUP1 << sub << u256(0) << eth::Instruction::CODECOPY;
	creatorContext << u256(0) << eth::Instruction::RETURN;
	swap(m_context, creatorContext);
}

void Compiler::appendFunctionSelector(vector<ASTPointer<FunctionDefinition>> const& _functions)
{
	// sort all public functions and store them together with a tag for their argument decoding section
	map<string, pair<FunctionDefinition const*, eth::AssemblyItem>> publicFunctions;
	for (ASTPointer<FunctionDefinition> const& f: _functions)
		if (f->isPublic())
			publicFunctions.insert(make_pair(f->getName(), make_pair(f.get(), m_context.newTag())));

	//@todo remove constructor

	if (publicFunctions.size() > 255)
		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("More than 255 public functions for contract."));

	//@todo check for calldatasize?
	// retrieve the first byte of the call data
	m_context << u256(0) << eth::Instruction::CALLDATALOAD << u256(0) << eth::Instruction::BYTE;
	// check that it is not too large
	m_context << eth::Instruction::DUP1 << u256(publicFunctions.size() - 1) << eth::Instruction::LT;
	eth::AssemblyItem returnTag = m_context.appendConditionalJump();

	// otherwise, jump inside jump table (each entry of the table has size 4)
	m_context << u256(4) << eth::Instruction::MUL;
	eth::AssemblyItem jumpTableStart = m_context.pushNewTag();
	m_context << eth::Instruction::ADD << eth::Instruction::JUMP;

	// jump table @todo it could be that the optimizer destroys this
	m_context << jumpTableStart;
	for (pair<string, pair<FunctionDefinition const*, eth::AssemblyItem>> const& f: publicFunctions)
		m_context.appendJumpTo(f.second.second) << eth::Instruction::JUMPDEST;

	m_context << returnTag << eth::Instruction::STOP;

	for (pair<string, pair<FunctionDefinition const*, eth::AssemblyItem>> const& f: publicFunctions)
	{
		FunctionDefinition const& function = *f.second.first;
		m_context << f.second.second;

		eth::AssemblyItem returnTag = m_context.pushNewTag();
		appendCalldataUnpacker(function);
		m_context.appendJumpTo(m_context.getFunctionEntryLabel(function));
		m_context << returnTag;

		appendReturnValuePacker(function);
	}
}

void Compiler::appendCalldataUnpacker(FunctionDefinition const& _function)
{
	// We do not check the calldata size, everything is zero-padded.
	unsigned dataOffset = 1;

	//@todo this can be done more efficiently, saving some CALLDATALOAD calls
	for (ASTPointer<VariableDeclaration> const& var: _function.getParameters())
	{
		unsigned const numBytes = var->getType()->getCalldataEncodedSize();
		if (numBytes == 0)
			BOOST_THROW_EXCEPTION(CompilerError()
								  << errinfo_sourceLocation(var->getLocation())
								  << errinfo_comment("Type not yet supported."));
		if (numBytes == 32)
			m_context << u256(dataOffset) << eth::Instruction::CALLDATALOAD;
		else
			m_context << (u256(1) << ((32 - numBytes) * 8)) << u256(dataOffset)
					  << eth::Instruction::CALLDATALOAD << eth::Instruction::DIV;
		dataOffset += numBytes;
	}
}

void Compiler::appendReturnValuePacker(FunctionDefinition const& _function)
{
	//@todo this can be also done more efficiently
	unsigned dataOffset = 0;
	vector<ASTPointer<VariableDeclaration>> const& parameters = _function.getReturnParameters();
	for (unsigned i = 0; i < parameters.size(); ++i)
	{
		unsigned numBytes = parameters[i]->getType()->getCalldataEncodedSize();
		if (numBytes == 0)
			BOOST_THROW_EXCEPTION(CompilerError()
								  << errinfo_sourceLocation(parameters[i]->getLocation())
								  << errinfo_comment("Type not yet supported."));
		m_context << eth::dupInstruction(parameters.size() - i);
		if (numBytes != 32)
			m_context << (u256(1) << ((32 - numBytes) * 8)) << eth::Instruction::MUL;
		m_context << u256(dataOffset) << eth::Instruction::MSTORE;
		dataOffset += numBytes;
	}
	// note that the stack is not cleaned up here
	m_context << u256(dataOffset) << u256(0) << eth::Instruction::RETURN;
}

bool Compiler::visit(FunctionDefinition& _function)
{
	//@todo to simplify this, the calling convention could by changed such that
	// caller puts: [retarg0] ... [retargm] [return address] [arg0] ... [argn]
	// although note that this reduces the size of the visible stack

	m_context.startNewFunction();
	m_returnTag = m_context.newTag();
	m_breakTags.clear();
	m_continueTags.clear();

	m_context << m_context.getFunctionEntryLabel(_function);

	// stack upon entry: [return address] [arg0] [arg1] ... [argn]
	// reserve additional slots: [retarg0] ... [retargm] [localvar0] ... [localvarp]

	unsigned const numArguments = _function.getParameters().size();
	unsigned const numReturnValues = _function.getReturnParameters().size();
	unsigned const numLocalVariables = _function.getLocalVariables().size();

	for (ASTPointer<VariableDeclaration> const& variable: _function.getParameters() + _function.getReturnParameters())
		m_context.addVariable(*variable);
	for (VariableDeclaration const* localVariable: _function.getLocalVariables())
		m_context.addVariable(*localVariable);
	m_context.initializeLocalVariables(numReturnValues + numLocalVariables);

	_function.getBody().accept(*this);

	m_context << m_returnTag;

	// Now we need to re-shuffle the stack. For this we keep a record of the stack layout
	// that shows the target positions of the elements, where "-1" denotes that this element needs
	// to be removed from the stack.
	// Note that the fact that the return arguments are of increasing index is vital for this
	// algorithm to work.

	vector<int> stackLayout;
	stackLayout.push_back(numReturnValues); // target of return address
	stackLayout += vector<int>(numArguments, -1); // discard all arguments
	for (unsigned i = 0; i < numReturnValues; ++i)
		stackLayout.push_back(i);
	stackLayout += vector<int>(numLocalVariables, -1);

	while (stackLayout.back() != int(stackLayout.size() - 1))
		if (stackLayout.back() < 0)
		{
			m_context << eth::Instruction::POP;
			stackLayout.pop_back();
		}
		else
		{
			m_context << eth::swapInstruction(stackLayout.size() - stackLayout.back() - 1);
			swap(stackLayout[stackLayout.back()], stackLayout.back());
		}
	//@todo assert that everything is in place now

	m_context << eth::Instruction::JUMP;

	return false;
}

bool Compiler::visit(IfStatement& _ifStatement)
{
	ExpressionCompiler::compileExpression(m_context, _ifStatement.getCondition());
	eth::AssemblyItem trueTag = m_context.appendConditionalJump();
	if (_ifStatement.getFalseStatement())
		_ifStatement.getFalseStatement()->accept(*this);
	eth::AssemblyItem endTag = m_context.appendJump();
	m_context << trueTag;
	_ifStatement.getTrueStatement().accept(*this);
	m_context << endTag;
	return false;
}

bool Compiler::visit(WhileStatement& _whileStatement)
{
	eth::AssemblyItem loopStart = m_context.newTag();
	eth::AssemblyItem loopEnd = m_context.newTag();
	m_continueTags.push_back(loopStart);
	m_breakTags.push_back(loopEnd);

	m_context << loopStart;
	ExpressionCompiler::compileExpression(m_context, _whileStatement.getCondition());
	m_context << eth::Instruction::ISZERO;
	m_context.appendConditionalJumpTo(loopEnd);

	_whileStatement.getBody().accept(*this);

	m_context.appendJumpTo(loopStart);
	m_context << loopEnd;

	m_continueTags.pop_back();
	m_breakTags.pop_back();
	return false;
}

bool Compiler::visit(Continue&)
{
	if (asserts(!m_continueTags.empty()))
		BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Jump tag not available for \"continue\"."));
	m_context.appendJumpTo(m_continueTags.back());
	return false;
}

bool Compiler::visit(Break&)
{
	if (asserts(!m_breakTags.empty()))
		BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Jump tag not available for \"break\"."));
	m_context.appendJumpTo(m_breakTags.back());
	return false;
}

bool Compiler::visit(Return& _return)
{
	//@todo modifications are needed to make this work with functions returning multiple values
	if (Expression* expression = _return.getExpression())
	{
		ExpressionCompiler::compileExpression(m_context, *expression);
		VariableDeclaration const& firstVariable = *_return.getFunctionReturnParameters().getParameters().front();
		ExpressionCompiler::cleanHigherOrderBitsIfNeeded(*expression->getType(), *firstVariable.getType());
		int stackPosition = m_context.getStackPositionOfVariable(firstVariable);
		m_context << eth::swapInstruction(stackPosition) << eth::Instruction::POP;
	}
	m_context.appendJumpTo(m_returnTag);
	return false;
}

bool Compiler::visit(VariableDefinition& _variableDefinition)
{
	if (Expression* expression = _variableDefinition.getExpression())
	{
		ExpressionCompiler::compileExpression(m_context, *expression);
		ExpressionCompiler::cleanHigherOrderBitsIfNeeded(*expression->getType(),
														 *_variableDefinition.getDeclaration().getType());
		int stackPosition = m_context.getStackPositionOfVariable(_variableDefinition.getDeclaration());
		m_context << eth::swapInstruction(stackPosition) << eth::Instruction::POP;
	}
	return false;
}

bool Compiler::visit(ExpressionStatement& _expressionStatement)
{
	Expression& expression = _expressionStatement.getExpression();
	ExpressionCompiler::compileExpression(m_context, expression);
	if (expression.getType()->getCategory() != Type::Category::VOID)
		m_context << eth::Instruction::POP;
	return false;
}

}
}
<commit_msg>Ignore break and continue outside of loops.<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Christian <c@ethdev.com>
 * @date 2014
 * Solidity compiler.
 */

#include <algorithm>
#include <libsolidity/AST.h>
#include <libsolidity/Compiler.h>
#include <libsolidity/ExpressionCompiler.h>

using namespace std;

namespace dev {
namespace solidity {

bytes Compiler::compile(ContractDefinition& _contract)
{
	Compiler compiler;
	compiler.compileContract(_contract);
	return compiler.m_context.getAssembledBytecode();
}

void Compiler::compileContract(ContractDefinition& _contract)
{
	m_context = CompilerContext(); // clear it just in case

	//@todo constructor
	//@todo register state variables

	for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions())
		m_context.addFunction(*function);

	appendFunctionSelector(_contract.getDefinedFunctions());
	for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions())
		function->accept(*this);

	packIntoContractCreator();
}

void Compiler::packIntoContractCreator()
{
	CompilerContext creatorContext;
	eth::AssemblyItem sub = creatorContext.addSubroutine(m_context.getAssembly());
	// stack contains sub size
	creatorContext << eth::Instruction::DUP1 << sub << u256(0) << eth::Instruction::CODECOPY;
	creatorContext << u256(0) << eth::Instruction::RETURN;
	swap(m_context, creatorContext);
}

void Compiler::appendFunctionSelector(vector<ASTPointer<FunctionDefinition>> const& _functions)
{
	// sort all public functions and store them together with a tag for their argument decoding section
	map<string, pair<FunctionDefinition const*, eth::AssemblyItem>> publicFunctions;
	for (ASTPointer<FunctionDefinition> const& f: _functions)
		if (f->isPublic())
			publicFunctions.insert(make_pair(f->getName(), make_pair(f.get(), m_context.newTag())));

	//@todo remove constructor

	if (publicFunctions.size() > 255)
		BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("More than 255 public functions for contract."));

	//@todo check for calldatasize?
	// retrieve the first byte of the call data
	m_context << u256(0) << eth::Instruction::CALLDATALOAD << u256(0) << eth::Instruction::BYTE;
	// check that it is not too large
	m_context << eth::Instruction::DUP1 << u256(publicFunctions.size() - 1) << eth::Instruction::LT;
	eth::AssemblyItem returnTag = m_context.appendConditionalJump();

	// otherwise, jump inside jump table (each entry of the table has size 4)
	m_context << u256(4) << eth::Instruction::MUL;
	eth::AssemblyItem jumpTableStart = m_context.pushNewTag();
	m_context << eth::Instruction::ADD << eth::Instruction::JUMP;

	// jump table @todo it could be that the optimizer destroys this
	m_context << jumpTableStart;
	for (pair<string, pair<FunctionDefinition const*, eth::AssemblyItem>> const& f: publicFunctions)
		m_context.appendJumpTo(f.second.second) << eth::Instruction::JUMPDEST;

	m_context << returnTag << eth::Instruction::STOP;

	for (pair<string, pair<FunctionDefinition const*, eth::AssemblyItem>> const& f: publicFunctions)
	{
		FunctionDefinition const& function = *f.second.first;
		m_context << f.second.second;

		eth::AssemblyItem returnTag = m_context.pushNewTag();
		appendCalldataUnpacker(function);
		m_context.appendJumpTo(m_context.getFunctionEntryLabel(function));
		m_context << returnTag;

		appendReturnValuePacker(function);
	}
}

void Compiler::appendCalldataUnpacker(FunctionDefinition const& _function)
{
	// We do not check the calldata size, everything is zero-padded.
	unsigned dataOffset = 1;

	//@todo this can be done more efficiently, saving some CALLDATALOAD calls
	for (ASTPointer<VariableDeclaration> const& var: _function.getParameters())
	{
		unsigned const numBytes = var->getType()->getCalldataEncodedSize();
		if (numBytes == 0)
			BOOST_THROW_EXCEPTION(CompilerError()
								  << errinfo_sourceLocation(var->getLocation())
								  << errinfo_comment("Type not yet supported."));
		if (numBytes == 32)
			m_context << u256(dataOffset) << eth::Instruction::CALLDATALOAD;
		else
			m_context << (u256(1) << ((32 - numBytes) * 8)) << u256(dataOffset)
					  << eth::Instruction::CALLDATALOAD << eth::Instruction::DIV;
		dataOffset += numBytes;
	}
}

void Compiler::appendReturnValuePacker(FunctionDefinition const& _function)
{
	//@todo this can be also done more efficiently
	unsigned dataOffset = 0;
	vector<ASTPointer<VariableDeclaration>> const& parameters = _function.getReturnParameters();
	for (unsigned i = 0; i < parameters.size(); ++i)
	{
		unsigned numBytes = parameters[i]->getType()->getCalldataEncodedSize();
		if (numBytes == 0)
			BOOST_THROW_EXCEPTION(CompilerError()
								  << errinfo_sourceLocation(parameters[i]->getLocation())
								  << errinfo_comment("Type not yet supported."));
		m_context << eth::dupInstruction(parameters.size() - i);
		if (numBytes != 32)
			m_context << (u256(1) << ((32 - numBytes) * 8)) << eth::Instruction::MUL;
		m_context << u256(dataOffset) << eth::Instruction::MSTORE;
		dataOffset += numBytes;
	}
	// note that the stack is not cleaned up here
	m_context << u256(dataOffset) << u256(0) << eth::Instruction::RETURN;
}

bool Compiler::visit(FunctionDefinition& _function)
{
	//@todo to simplify this, the calling convention could by changed such that
	// caller puts: [retarg0] ... [retargm] [return address] [arg0] ... [argn]
	// although note that this reduces the size of the visible stack

	m_context.startNewFunction();
	m_returnTag = m_context.newTag();
	m_breakTags.clear();
	m_continueTags.clear();

	m_context << m_context.getFunctionEntryLabel(_function);

	// stack upon entry: [return address] [arg0] [arg1] ... [argn]
	// reserve additional slots: [retarg0] ... [retargm] [localvar0] ... [localvarp]

	unsigned const numArguments = _function.getParameters().size();
	unsigned const numReturnValues = _function.getReturnParameters().size();
	unsigned const numLocalVariables = _function.getLocalVariables().size();

	for (ASTPointer<VariableDeclaration> const& variable: _function.getParameters() + _function.getReturnParameters())
		m_context.addVariable(*variable);
	for (VariableDeclaration const* localVariable: _function.getLocalVariables())
		m_context.addVariable(*localVariable);
	m_context.initializeLocalVariables(numReturnValues + numLocalVariables);

	_function.getBody().accept(*this);

	m_context << m_returnTag;

	// Now we need to re-shuffle the stack. For this we keep a record of the stack layout
	// that shows the target positions of the elements, where "-1" denotes that this element needs
	// to be removed from the stack.
	// Note that the fact that the return arguments are of increasing index is vital for this
	// algorithm to work.

	vector<int> stackLayout;
	stackLayout.push_back(numReturnValues); // target of return address
	stackLayout += vector<int>(numArguments, -1); // discard all arguments
	for (unsigned i = 0; i < numReturnValues; ++i)
		stackLayout.push_back(i);
	stackLayout += vector<int>(numLocalVariables, -1);

	while (stackLayout.back() != int(stackLayout.size() - 1))
		if (stackLayout.back() < 0)
		{
			m_context << eth::Instruction::POP;
			stackLayout.pop_back();
		}
		else
		{
			m_context << eth::swapInstruction(stackLayout.size() - stackLayout.back() - 1);
			swap(stackLayout[stackLayout.back()], stackLayout.back());
		}
	//@todo assert that everything is in place now

	m_context << eth::Instruction::JUMP;

	return false;
}

bool Compiler::visit(IfStatement& _ifStatement)
{
	ExpressionCompiler::compileExpression(m_context, _ifStatement.getCondition());
	eth::AssemblyItem trueTag = m_context.appendConditionalJump();
	if (_ifStatement.getFalseStatement())
		_ifStatement.getFalseStatement()->accept(*this);
	eth::AssemblyItem endTag = m_context.appendJump();
	m_context << trueTag;
	_ifStatement.getTrueStatement().accept(*this);
	m_context << endTag;
	return false;
}

bool Compiler::visit(WhileStatement& _whileStatement)
{
	eth::AssemblyItem loopStart = m_context.newTag();
	eth::AssemblyItem loopEnd = m_context.newTag();
	m_continueTags.push_back(loopStart);
	m_breakTags.push_back(loopEnd);

	m_context << loopStart;
	ExpressionCompiler::compileExpression(m_context, _whileStatement.getCondition());
	m_context << eth::Instruction::ISZERO;
	m_context.appendConditionalJumpTo(loopEnd);

	_whileStatement.getBody().accept(*this);

	m_context.appendJumpTo(loopStart);
	m_context << loopEnd;

	m_continueTags.pop_back();
	m_breakTags.pop_back();
	return false;
}

bool Compiler::visit(Continue&)
{
	if (!m_continueTags.empty())
		m_context.appendJumpTo(m_continueTags.back());
	return false;
}

bool Compiler::visit(Break&)
{
	if (!m_breakTags.empty())
		m_context.appendJumpTo(m_breakTags.back());
	return false;
}

bool Compiler::visit(Return& _return)
{
	//@todo modifications are needed to make this work with functions returning multiple values
	if (Expression* expression = _return.getExpression())
	{
		ExpressionCompiler::compileExpression(m_context, *expression);
		VariableDeclaration const& firstVariable = *_return.getFunctionReturnParameters().getParameters().front();
		ExpressionCompiler::cleanHigherOrderBitsIfNeeded(*expression->getType(), *firstVariable.getType());
		int stackPosition = m_context.getStackPositionOfVariable(firstVariable);
		m_context << eth::swapInstruction(stackPosition) << eth::Instruction::POP;
	}
	m_context.appendJumpTo(m_returnTag);
	return false;
}

bool Compiler::visit(VariableDefinition& _variableDefinition)
{
	if (Expression* expression = _variableDefinition.getExpression())
	{
		ExpressionCompiler::compileExpression(m_context, *expression);
		ExpressionCompiler::cleanHigherOrderBitsIfNeeded(*expression->getType(),
														 *_variableDefinition.getDeclaration().getType());
		int stackPosition = m_context.getStackPositionOfVariable(_variableDefinition.getDeclaration());
		m_context << eth::swapInstruction(stackPosition) << eth::Instruction::POP;
	}
	return false;
}

bool Compiler::visit(ExpressionStatement& _expressionStatement)
{
	Expression& expression = _expressionStatement.getExpression();
	ExpressionCompiler::compileExpression(m_context, expression);
	if (expression.getType()->getCategory() != Type::Category::VOID)
		m_context << eth::Instruction::POP;
	return false;
}

}
}
<|endoftext|>


<commit_before>/*
 * Project: FullereneViewer
 * Version: 1.0
 * Copyright: (C) 2011-14 Dr.Sc.KAWAMOTO,Takuji (Ext)
 * Create: 2012/01/18 00:35:19 JST
 */

#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "Config.h"
#include "Fullerene.h"
#include "CarbonAllotrope.h"
#include "Representations.h"
#include "Automorphisms.h"
#include "FullereneCharacteristic.h"
#include "Generator.h"
#include "DistanceMatrix.h"
#include "Pattern.h"
#include "Utils.h"
#include "Debug.h"
#include "DebugMemory.h"

bool Fullerene::s_need_representations = false;
bool Fullerene::s_need_fullerene_characteristic = false;
bool Fullerene::s_need_distance_matrix = false;

Fullerene::Fullerene()
  : p_carbon_allotrope(0), p_n(0), p_m(0), p_h(0),
    p_representations(0), p_characteristic(0), p_distance_matrix(0)
{
  strcpy(p_generator_label, "");
}

Fullerene::Fullerene(const char* generator_label)
  : p_carbon_allotrope(0), p_n(0), p_m(0), p_h(0),
    p_representations(0), p_characteristic(0), p_distance_matrix(0)
{
  strcpy(p_generator_label, generator_label);
  CarbonAllotrope* ca = new CarbonAllotrope();
  if (strcmp(p_generator_label, "T-Y") == 0)
    {
      ca->make_equator_by_chiral_characteristic(6, 6, 5);
      ca->close_normally_once();
      int result_number;
      int array[100];
      array[0] = 7;
      array[1] = 6;
      array[2] = 7;
      array[3] = 6;
      array[4] = 6;
      array[5] = 6;
      array[6] = 7;
      array[7] = 6;
      array[8] = 7;
      array[9] = 6;
      ca->enlarge_cylinder_by_n_polygons(new Pattern(10, array), result_number);
      ca->append_n_polygon_at_carbon(6, 131 + 48);
      ca->append_n_polygon_at_carbon(6, 117 + 48);
      ca->append_n_polygon_at_carbon(6, 132 + 48);
      ca->append_n_polygon_at_carbon(6, 136 + 48);
      ca->append_n_polygon_at_carbon(6, 118 + 48);
      ca->append_n_polygon_at_carbon(6, 123 + 48);
      ca->append_n_polygon_at_carbon(6, 138 + 48);
      ca->append_n_polygon_at_carbon(6, 140 + 48);
      array[0] = 156 + 48;
      array[1] = 155 + 48;
      array[2] = 0;
      array[3] = 0;
      array[4] = 0;
      array[5] = 0;
      array[6] = 0;
      ca->append_n_polygon_at_carbons(7, array);
      array[0] = 154 + 48;
      array[1] = 153 + 48;
      ca->append_n_polygon_at_carbons(7, array);
      array[0] = 160 + 48;
      array[1] = 159 + 48;
      array[2] = 164 + 48;
      array[3] = 163 + 48;
      array[4] = 0;
      array[5] = 0;
      ca->append_n_polygon_at_carbons(6, array);
      ca->append_n_polygon_at_carbon(6, 164 + 48);

      ca->append_n_polygon_at_carbon(6, 121 + 48);
      ca->append_n_polygon_at_carbon(6, 124 + 48);
      ca->append_n_polygon_at_carbon(6, 126 + 48);
      ca->append_n_polygon_at_carbon(6, 129 + 48);
      ca->append_n_polygon_at_carbon(6, 154 + 48);
      ca->append_n_polygon_at_carbon(6, 165 + 48);
      ca->append_n_polygon_at_carbon(6, 158 + 48);
      ca->append_n_polygon_at_carbon(6, 155 + 48);

      ca->append_n_polygon_at_carbon(6, 112 + 48);
      ca->append_n_polygon_at_carbon(6, 115 + 48);
      ca->append_n_polygon_at_carbon(6, 156 + 48);
      ca->append_n_polygon_at_carbon(6, 160 + 48);
      ca->append_n_polygon_at_carbon(6, 163 + 48);
      ca->append_n_polygon_at_carbon(6, 153 + 48);
      ca->append_n_polygon_at_carbon(6, 111 + 48);
      ca->append_n_polygon_at_carbon(6, 109 + 48);

      ca->append_n_polygon_at_carbon(6, 143 + 48);
      ca->append_n_polygon_at_carbon(6, 151 + 48);

      ca->append_n_polygon_at_carbon(6, 149 + 48);
      ca->append_n_polygon_at_carbon(6, 145 + 48);

      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->close_normally_once();

      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->close_normally_once();
    }
  else if (p_generator_label[0] == 'T')
    {
      p_n = 10;
      p_m = 0;
      p_h = 4;
      sscanf(p_generator_label, "T%d,%d,%d", &p_n, &p_m, &p_h);
      sprintf(p_generator_label, "T%d,%d,%d", p_n, p_m, p_h);
      ca->make_equator_by_chiral_characteristic(p_n, p_m, p_h);
      // TODO ca->close_force();
#ifdef DEBUG_CARBON_ALLOTROPE_CONSTRUCTION
      ca->print_detail();
#endif
    }
  else
    {
      Generator gen = Generator(generator_label, 6);
      bool symmetric = gen.symmetric();
      ca->make_symmetric_scrap(gen.scrap_no());
#ifdef DEBUG_CARBON_ALLOTROPE_CONSTRUCTION
      ca->print_detail();
#endif
      while (1)
        {
          int No = gen.glow();
          int num;
          ErrorCode result;
          if (symmetric)
            result =
              ca->fill_n_polygons_around_carbons_closed_to_center_and_pentagons(No, num);
          else
            result = ca->fill_n_polygon_around_oldest_carbon(No);
          assert(result == ERROR_CODE_OK);
#ifdef DEBUG_CARBON_ALLOTROPE_CONSTRUCTION
          ca->print_detail();
#endif
          List<Carbon> boundary;
          ca->list_boundary_carbons(boundary);
          int number_of_carbons_in_boundary = boundary.length();
          if (number_of_carbons_in_boundary == 0)
            break;
        }
    }
  set_carbon_allotrope(ca);
}

Fullerene::~Fullerene()
{
  if (p_carbon_allotrope)
    delete p_carbon_allotrope;
  if (p_representations)
    delete p_representations;
  if (p_characteristic)
    delete p_characteristic;
  if (p_distance_matrix)
    delete p_distance_matrix;
}

bool Fullerene::operator == (const Fullerene& that) const
{
  return ((*p_representations) == (*that.p_representations));
}

void Fullerene::set_carbon_allotrope(CarbonAllotrope* carbon_allotrope)
{
  int len;
  p_carbon_allotrope = carbon_allotrope;
#if defined(CONFIG_DRAW_MAJOR_AXES_SYMMETRY_IN_GURUGURU_MODE)
  s_need_representations = true;
#endif
  if (p_carbon_allotrope &&
      (s_need_fullerene_characteristic || s_need_distance_matrix ||
       s_need_representations))
    {
#ifdef DEBUG_FULLERENE_CONSTRUCTION
      printf("* representations ******************************\n");
#endif
      p_representations = new Representations();
      p_carbon_allotrope->all_representations(p_representations);
#ifdef DEBUG_FULLERENE_CONSTRUCTION
      len = p_representations->length();
      for (int i = 0; i < len; ++i)
        {
          Representation* rep = p_representations->get_representation(i);
          rep->print();
        }
      printf("************************************************\n");
#endif
      Automorphisms ams = Automorphisms(this);
      len = ams.number_of_automorphisms();
      for (int i = 0; i < len; ++i)
        {
          Automorphism* am = ams.get_automorphism(i);
          int order = am->order();
          if (order == 1)
            continue;
          int seq0, seq1, seq2, seq3, seq4, seq5;
          int fixed_carbons = am->fixed_carbons(seq0, seq1);
          int fixed_bonds = am->fixed_bonds(seq2, seq3);
          int fixed_rings = am->fixed_rings(seq4, seq5);
          AxisType type;
          if (fixed_carbons == 2)
            type = AXIS_TYPE_CENTER_OF_CARBON;
          else if (fixed_bonds == 2)
            {
              type = AXIS_TYPE_CENTER_OF_BOND;
              seq0 = seq2;
              seq1 = seq3;
            }
          else if (fixed_rings == 2)
            {
              type = AXIS_TYPE_CENTER_OF_RING;
              seq0 = seq4;
              seq1 = seq5;
            }
          else if ((fixed_rings == 1) && (fixed_bonds == 1))
            {
              type = AXIS_TYPE_CENTER_OF_RING_AND_BOND;
              seq0 = seq4;
              seq1 = seq2;
            }
          else if ((fixed_rings == 1) && (fixed_carbons == 1))
            {
              type = AXIS_TYPE_CENTER_OF_RING_AND_CARBON;
              seq1 = seq0;
              seq0 = seq4;
            }
          else
            assert(0);
          p_carbon_allotrope->register_axis(new SymmetryAxis(type, order,
                                                             seq0, seq1, am));
        }
      if (s_need_fullerene_characteristic)
        p_characteristic = new FullereneCharacteristic(p_carbon_allotrope);
      if (s_need_distance_matrix)
        p_distance_matrix = new DistanceMatrix(p_carbon_allotrope);
    }
}

void Fullerene::set_fullerene_name(const char* fullerene_name)
{
  assert(strlen(fullerene_name) <= NAME_MAX_SIZE);
  strcpy(p_fullerene_name, fullerene_name);
}

void Fullerene::set_generator_label(const char* generator_label)
{
  assert(strlen(generator_label) <= NAME_MAX_SIZE);
  strcpy(p_generator_label, generator_label);
}

/* Local Variables:	*/
/* mode: c++		*/
/* End:			*/
<commit_msg>忘れもの。with #16<commit_after>/*
 * Project: FullereneViewer
 * Version: 1.0
 * Copyright: (C) 2011-14 Dr.Sc.KAWAMOTO,Takuji (Ext)
 * Create: 2012/01/18 00:35:19 JST
 */

#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "Config.h"
#include "Fullerene.h"
#include "CarbonAllotrope.h"
#include "Representations.h"
#include "Automorphisms.h"
#include "FullereneCharacteristic.h"
#include "Generator.h"
#include "DistanceMatrix.h"
#include "Pattern.h"
#include "Utils.h"
#include "Debug.h"
#include "DebugMemory.h"

bool Fullerene::s_need_representations = false;
bool Fullerene::s_need_fullerene_characteristic = false;
bool Fullerene::s_need_distance_matrix = false;

Fullerene::Fullerene()
  : p_carbon_allotrope(0), p_n(0), p_m(0), p_h(0),
    p_representations(0), p_characteristic(0), p_distance_matrix(0)
{
  strcpy(p_generator_label, "");
}

Fullerene::Fullerene(const char* generator_label)
  : p_carbon_allotrope(0), p_n(0), p_m(0), p_h(0),
    p_representations(0), p_characteristic(0), p_distance_matrix(0)
{
  strcpy(p_generator_label, generator_label);
  CarbonAllotrope* ca = new CarbonAllotrope();
  if (strcmp(p_generator_label, "T-Y") == 0)
    {
      ca->make_equator_by_chiral_characteristic(6, 6, 5);
      ca->close_normally_once();
      int result_number;
      int array[100];
      array[0] = 7;
      array[1] = 6;
      array[2] = 7;
      array[3] = 6;
      array[4] = 6;
      array[5] = 6;
      array[6] = 7;
      array[7] = 6;
      array[8] = 7;
      array[9] = 6;
      ca->enlarge_cylinder_by_n_polygons(new Pattern(10, array), result_number);
      ca->append_n_polygon_at_carbon(6, 131 + 48);
      ca->append_n_polygon_at_carbon(6, 117 + 48);
      ca->append_n_polygon_at_carbon(6, 132 + 48);
      ca->append_n_polygon_at_carbon(6, 136 + 48);
      ca->append_n_polygon_at_carbon(6, 118 + 48);
      ca->append_n_polygon_at_carbon(6, 123 + 48);
      ca->append_n_polygon_at_carbon(6, 138 + 48);
      ca->append_n_polygon_at_carbon(6, 140 + 48);
      array[0] = 156 + 48;
      array[1] = 155 + 48;
      array[2] = 0;
      array[3] = 0;
      array[4] = 0;
      array[5] = 0;
      array[6] = 0;
      ca->append_n_polygon_at_carbons(7, array);
      array[0] = 154 + 48;
      array[1] = 153 + 48;
      ca->append_n_polygon_at_carbons(7, array);
      array[0] = 160 + 48;
      array[1] = 159 + 48;
      array[2] = 164 + 48;
      array[3] = 163 + 48;
      array[4] = 0;
      array[5] = 0;
      ca->append_n_polygon_at_carbons(6, array);
      ca->append_n_polygon_at_carbon(6, 164 + 48);

      ca->append_n_polygon_at_carbon(6, 121 + 48);
      ca->append_n_polygon_at_carbon(6, 124 + 48);
      ca->append_n_polygon_at_carbon(6, 126 + 48);
      ca->append_n_polygon_at_carbon(6, 129 + 48);
      ca->append_n_polygon_at_carbon(6, 154 + 48);
      ca->append_n_polygon_at_carbon(6, 165 + 48);
      ca->append_n_polygon_at_carbon(6, 158 + 48);
      ca->append_n_polygon_at_carbon(6, 155 + 48);

      ca->append_n_polygon_at_carbon(6, 112 + 48);
      ca->append_n_polygon_at_carbon(6, 115 + 48);
      ca->append_n_polygon_at_carbon(6, 156 + 48);
      ca->append_n_polygon_at_carbon(6, 160 + 48);
      ca->append_n_polygon_at_carbon(6, 163 + 48);
      ca->append_n_polygon_at_carbon(6, 153 + 48);
      ca->append_n_polygon_at_carbon(6, 111 + 48);
      ca->append_n_polygon_at_carbon(6, 109 + 48);

      ca->append_n_polygon_at_carbon(6, 143 + 48);
      ca->append_n_polygon_at_carbon(6, 151 + 48);

      ca->append_n_polygon_at_carbon(6, 149 + 48);
      ca->append_n_polygon_at_carbon(6, 145 + 48);

      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->close_normally_once();

      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->enlarge_cylinder_by_n_polygons(new Pattern(6), result_number);
      ca->close_normally_once();
    }
  else if (p_generator_label[0] == 'T')
    {
      p_n = 10;
      p_m = 0;
      p_h = 4;
      sscanf(p_generator_label, "T%d,%d,%d", &p_n, &p_m, &p_h);
      sprintf(p_generator_label, "T%d,%d,%d", p_n, p_m, p_h);
      ca->make_equator_by_chiral_characteristic(p_n, p_m, p_h);
      // TODO ca->close_force();
#ifdef DEBUG_CARBON_ALLOTROPE_CONSTRUCTION
      ca->print_detail();
#endif
    }
  else
    {
      Generator gen = Generator(generator_label, 6);
      bool symmetric = gen.symmetric();
      ca->make_symmetric_scrap(gen.scrap_no());
#ifdef DEBUG_CARBON_ALLOTROPE_CONSTRUCTION
      ca->print_detail();
#endif
      while (1)
        {
          int No = gen.glow();
          int num;
          ErrorCode result;
          if (symmetric)
            result =
              ca->fill_n_polygons_around_carbons_closed_to_center_and_pentagons(No, num);
          else
            result = ca->fill_n_polygon_around_oldest_carbon(No);
          assert(result == ERROR_CODE_OK);
#ifdef DEBUG_CARBON_ALLOTROPE_CONSTRUCTION
          ca->print_detail();
#endif
          List<Carbon> boundary;
          ca->list_boundary_carbons(boundary);
          int number_of_carbons_in_boundary = boundary.length();
          if (number_of_carbons_in_boundary == 0)
            break;
        }
    }
  set_carbon_allotrope(ca);
}

Fullerene::~Fullerene()
{
  if (p_carbon_allotrope)
    delete p_carbon_allotrope;
  if (p_representations)
    delete p_representations;
  if (p_characteristic)
    delete p_characteristic;
  if (p_distance_matrix)
    delete p_distance_matrix;
}

bool Fullerene::operator == (const Fullerene& that) const
{
  return ((*p_representations) == (*that.p_representations));
}

void Fullerene::set_carbon_allotrope(CarbonAllotrope* carbon_allotrope)
{
  int len;
  p_carbon_allotrope = carbon_allotrope;
#if defined(CONFIG_DRAW_MAJOR_AXES_SYMMETRY_IN_GURUGURU_MODE) || defined(CONFIG_DRAW_ALL_AXES_SYMMETRY_IN_GURUGURU_MODE)
  s_need_representations = true;
#endif
  if (p_carbon_allotrope &&
      (s_need_fullerene_characteristic || s_need_distance_matrix ||
       s_need_representations))
    {
#ifdef DEBUG_FULLERENE_CONSTRUCTION
      printf("* representations ******************************\n");
#endif
      p_representations = new Representations();
      p_carbon_allotrope->all_representations(p_representations);
#ifdef DEBUG_FULLERENE_CONSTRUCTION
      len = p_representations->length();
      for (int i = 0; i < len; ++i)
        {
          Representation* rep = p_representations->get_representation(i);
          rep->print();
        }
      printf("************************************************\n");
#endif
      Automorphisms ams = Automorphisms(this);
      len = ams.number_of_automorphisms();
      for (int i = 0; i < len; ++i)
        {
          Automorphism* am = ams.get_automorphism(i);
          int order = am->order();
          if (order == 1)
            continue;
          int seq0, seq1, seq2, seq3, seq4, seq5;
          int fixed_carbons = am->fixed_carbons(seq0, seq1);
          int fixed_bonds = am->fixed_bonds(seq2, seq3);
          int fixed_rings = am->fixed_rings(seq4, seq5);
          AxisType type;
          if (fixed_carbons == 2)
            type = AXIS_TYPE_CENTER_OF_CARBON;
          else if (fixed_bonds == 2)
            {
              type = AXIS_TYPE_CENTER_OF_BOND;
              seq0 = seq2;
              seq1 = seq3;
            }
          else if (fixed_rings == 2)
            {
              type = AXIS_TYPE_CENTER_OF_RING;
              seq0 = seq4;
              seq1 = seq5;
            }
          else if ((fixed_rings == 1) && (fixed_bonds == 1))
            {
              type = AXIS_TYPE_CENTER_OF_RING_AND_BOND;
              seq0 = seq4;
              seq1 = seq2;
            }
          else if ((fixed_rings == 1) && (fixed_carbons == 1))
            {
              type = AXIS_TYPE_CENTER_OF_RING_AND_CARBON;
              seq1 = seq0;
              seq0 = seq4;
            }
          else
            assert(0);
          p_carbon_allotrope->register_axis(new SymmetryAxis(type, order,
                                                             seq0, seq1, am));
        }
      if (s_need_fullerene_characteristic)
        p_characteristic = new FullereneCharacteristic(p_carbon_allotrope);
      if (s_need_distance_matrix)
        p_distance_matrix = new DistanceMatrix(p_carbon_allotrope);
    }
}

void Fullerene::set_fullerene_name(const char* fullerene_name)
{
  assert(strlen(fullerene_name) <= NAME_MAX_SIZE);
  strcpy(p_fullerene_name, fullerene_name);
}

void Fullerene::set_generator_label(const char* generator_label)
{
  assert(strlen(generator_label) <= NAME_MAX_SIZE);
  strcpy(p_generator_label, generator_label);
}

/* Local Variables:	*/
/* mode: c++		*/
/* End:			*/
<|endoftext|>


<commit_before><commit_msg>* prevent duplicate setting added.<commit_after><|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//  SouloudTedSid.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "Core/Main.h"
#include "IO/IO.h"
#include "HTTP/HTTPFileSystem.h"
#include "Gfx/Gfx.h"
#include "Input/Input.h"
#include "IMUI/IMUI.h"
#include "soloud.h"
#include "soloud_tedsid.h"
#include "soloud_biquadresonantfilter.h"
#include "soloud_echofilter.h"
#include "soloud_dcremovalfilter.h"
#include "soloud_bassboostfilter.h"

using namespace Oryol;

class SoloudTedSidApp : public App {
public:
    /// on init frame method
    virtual AppState::Code OnInit();
    /// on running frame method
    virtual AppState::Code OnRunning();
    /// on cleanup frame method
    virtual AppState::Code OnCleanup();

private:
    SoLoud::Soloud soloud;
    SoLoud::TedSid music1, music2;
    SoLoud::BiquadResonantFilter biquad;
    SoLoud::EchoFilter echo;
    SoLoud::DCRemovalFilter dcRemoval;
    SoLoud::BassboostFilter bassBoost;
    int musicHandle1 = 0;
    int musicHandle2 = 0;
    float filterParam0[4];
    float filterParam1[4];
    float filterParam2[4];
    float song1Volume = 1.0f;
    float song2Volume = 0.0f;
};
OryolMain(SoloudTedSidApp);

//------------------------------------------------------------------------------
AppState::Code
SoloudTedSidApp::OnRunning() {

    this->soloud.setFilterParameter(0, 0, 0, this->filterParam0[0]);
    this->soloud.setFilterParameter(0, 0, 2, this->filterParam1[0]);
    this->soloud.setFilterParameter(0, 0, 3, this->filterParam2[0]);
    this->soloud.setFilterParameter(0, 1, 0, this->filterParam0[1]);
    this->soloud.setFilterParameter(0, 1, 1, this->filterParam1[1]);
    this->soloud.setFilterParameter(0, 2, 0, this->filterParam0[2]);
    this->soloud.setFilterParameter(0, 3, 0, this->filterParam0[3]);

    float* buf = this->soloud.getWave();
    float* fft = this->soloud.calcFFT();

    Gfx::ApplyDefaultRenderTarget(ClearState::ClearColor(glm::vec4(0.2f, 0.4f, 0.8f, 1.0f)));
    IMUI::NewFrame();
    ImGui::SetNextWindowPos(ImVec2(500, 20), ImGuiSetCond_Once);
    ImGui::Begin("Output");
    ImGui::PlotLines("##Wave", buf, 256, 0, "Wave", -1, 1, ImVec2(264, 80));
    ImGui::PlotHistogram("##FFT", fft, 256/2, 0, "FFT", 0, 10, ImVec2(264, 80), 8);
    float sidregs[32 + 5];
    for (int i = 0; i < 32; i++) {
        sidregs[i] = this->soloud.getInfo(this->musicHandle1, i);
    }
    ImGui::PlotHistogram("##SID", sidregs, 32 + 5, 0, "          SID               TED", 0, 0xff, ImVec2(264, 80), 4);
    ImGui::Text("SID: %02X %02X %02X %02X %02X %02X %02X %02X",
        (int)this->soloud.getInfo(this->musicHandle1, 0),
        (int)this->soloud.getInfo(this->musicHandle1, 1),
        (int)this->soloud.getInfo(this->musicHandle1, 2),
        (int)this->soloud.getInfo(this->musicHandle1, 3),
        (int)this->soloud.getInfo(this->musicHandle1, 4),
        (int)this->soloud.getInfo(this->musicHandle1, 5),
        (int)this->soloud.getInfo(this->musicHandle1, 6),
        (int)this->soloud.getInfo(this->musicHandle1, 7));
    ImGui::Text("     %02X %02X %02X %02X %02X %02X %02X %02X",
        (int)this->soloud.getInfo(this->musicHandle1, 8),
        (int)this->soloud.getInfo(this->musicHandle1, 9),
        (int)this->soloud.getInfo(this->musicHandle1, 10),
        (int)this->soloud.getInfo(this->musicHandle1, 11),
        (int)this->soloud.getInfo(this->musicHandle1, 12),
        (int)this->soloud.getInfo(this->musicHandle1, 13),
        (int)this->soloud.getInfo(this->musicHandle1, 14),
        (int)this->soloud.getInfo(this->musicHandle1, 15));
    ImGui::Text("     %02X %02X %02X %02X %02X %02X %02X %02X",
        (int)this->soloud.getInfo(this->musicHandle1, 16),
        (int)this->soloud.getInfo(this->musicHandle1, 17),
        (int)this->soloud.getInfo(this->musicHandle1, 18),
        (int)this->soloud.getInfo(this->musicHandle1, 19),
        (int)this->soloud.getInfo(this->musicHandle1, 20),
        (int)this->soloud.getInfo(this->musicHandle1, 21),
        (int)this->soloud.getInfo(this->musicHandle1, 22),
        (int)this->soloud.getInfo(this->musicHandle1, 23));
    ImGui::Text("     %02X %02X %02X %02X %02X %02X %02X %02X",
        (int)this->soloud.getInfo(this->musicHandle1, 24),
        (int)this->soloud.getInfo(this->musicHandle1, 25),
        (int)this->soloud.getInfo(this->musicHandle1, 26),
        (int)this->soloud.getInfo(this->musicHandle1, 27),
        (int)this->soloud.getInfo(this->musicHandle1, 28),
        (int)this->soloud.getInfo(this->musicHandle1, 29),
        (int)this->soloud.getInfo(this->musicHandle1, 30),
        (int)this->soloud.getInfo(this->musicHandle1, 31));
    ImGui::Text("TED: %02X %02X %02X %02X %02X",
        (int)this->soloud.getInfo(this->musicHandle2, 64),
        (int)this->soloud.getInfo(this->musicHandle2, 65),
        (int)this->soloud.getInfo(this->musicHandle2, 66),
        (int)this->soloud.getInfo(this->musicHandle2, 67),
        (int)this->soloud.getInfo(this->musicHandle2, 68));
    ImGui::End();

    ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiSetCond_Once);
    ImGui::Begin("Control", nullptr, ImVec2(300, -1));
    ImGui::Text("Song volumes");
    if (ImGui::SliderFloat("Song1 vol", &this->song1Volume, 0, 1)) {
        this->soloud.setVolume(this->musicHandle1, this->song1Volume);
    }
    if (ImGui::SliderFloat("Song2 vol", &this->song2Volume, 0, 1)) {
        this->soloud.setVolume(this->musicHandle2, this->song2Volume);
    }
    ImGui::Separator();
    ImGui::Text("Biquad filter (lowpass)");
    ImGui::SliderFloat("Wet##4", &this->filterParam0[0], 0, 1);
    ImGui::SliderFloat("Frequency##4", &this->filterParam1[0], 0, 8000);
    ImGui::SliderFloat("Resonance##4", &this->filterParam2[0], 1, 20);
    ImGui::Separator();
    ImGui::Text("Bassboost filter");
    ImGui::SliderFloat("Wet##2", &this->filterParam0[1], 0, 1);
    ImGui::SliderFloat("Boost##2", &this->filterParam1[1], 0, 11);
    ImGui::Separator();
    ImGui::Text("Echo filter");
    ImGui::SliderFloat("Wet##3", &this->filterParam0[2], 0, 1);
    ImGui::Separator();
    ImGui::Text("DC removal filter");
    ImGui::SliderFloat("Wet##1", &this->filterParam0[3], 0, 1);
    ImGui::End();

    ImGui::Render();
    Gfx::CommitFrame();
    return Gfx::QuitRequested() ? AppState::Cleanup : AppState::Running;
}

//------------------------------------------------------------------------------
AppState::Code
SoloudTedSidApp::OnInit() {

    IOSetup ioSetup;
    ioSetup.FileSystems.Add("http", HTTPFileSystem::Creator());
    ioSetup.Assigns.Add("snd:", ORYOL_SAMPLE_URL);
    IO::Setup(ioSetup);

    Gfx::Setup(GfxSetup::Window(800, 460, "SoLoud TED/SID Demo"));
    Input::Setup();
    IMUI::Setup();

    // need to compile in VS2013, can't use new initializers
    Memory::Clear(this->filterParam0, sizeof(this->filterParam0));
    Memory::Clear(this->filterParam1, sizeof(this->filterParam1));
    Memory::Clear(this->filterParam2, sizeof(this->filterParam2));
    this->filterParam1[0] = 1000;
    this->filterParam1[1] = 2;
    this->filterParam2[0] = 2;
    this->music1.setLooping(true);
    this->music2.setLooping(true);
    this->echo.setParams(0.2f, 0.5f, 0.05f);
    this->biquad.setParams(SoLoud::BiquadResonantFilter::LOWPASS, 44100, 4000, 2);
    this->soloud.setGlobalFilter(0, &this->biquad);
    this->soloud.setGlobalFilter(1, &this->bassBoost);
    this->soloud.setGlobalFilter(2, &this->echo);
    this->soloud.setGlobalFilter(3, &this->dcRemoval);
    this->soloud.init(SoLoud::Soloud::CLIP_ROUNDOFF|SoLoud::Soloud::ENABLE_VISUALIZATION);

    IO::Load("snd:modulation.sid.dump", [this](IO::LoadResult res) {
        this->music1.loadMem(res.Data.Data(), res.Data.Size(), true, true);
        this->musicHandle1 = this->soloud.play(this->music1);
        this->soloud.setVolume(this->musicHandle1, this->song1Volume);
    });
    IO::Load("snd:ted_storm.prg.dump", [this](IO::LoadResult res) {
        this->music2.loadMem(res.Data.Data(), res.Data.Size(), true, true);
        this->musicHandle2 = this->soloud.play(this->music2);
        this->soloud.setVolume(this->musicHandle2, this->song2Volume);
    });
    return App::OnInit();
}

//------------------------------------------------------------------------------
AppState::Code
SoloudTedSidApp::OnCleanup() {
    soloud.deinit();
    IMUI::Discard();
    Input::Discard();
    Gfx::Discard();
    return App::OnCleanup();
}
<commit_msg>minor code cleanup in SoLoud demo<commit_after>//------------------------------------------------------------------------------
//  SouloudTedSid.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "Core/Main.h"
#include "IO/IO.h"
#include "HTTP/HTTPFileSystem.h"
#include "Gfx/Gfx.h"
#include "Input/Input.h"
#include "IMUI/IMUI.h"
#include "soloud.h"
#include "soloud_tedsid.h"
#include "soloud_biquadresonantfilter.h"
#include "soloud_echofilter.h"
#include "soloud_dcremovalfilter.h"
#include "soloud_bassboostfilter.h"

using namespace Oryol;

class SoloudTedSidApp : public App {
public:
    /// on init frame method
    virtual AppState::Code OnInit();
    /// on running frame method
    virtual AppState::Code OnRunning();
    /// on cleanup frame method
    virtual AppState::Code OnCleanup();

private:
    SoLoud::Soloud soloud;
    SoLoud::TedSid music1, music2;
    SoLoud::BiquadResonantFilter biquad;
    SoLoud::EchoFilter echo;
    SoLoud::DCRemovalFilter dcRemoval;
    SoLoud::BassboostFilter bassBoost;
    int musicHandle1 = 0;
    int musicHandle2 = 0;
    float filterParam0[4];
    float filterParam1[4];
    float filterParam2[4];
    float music1Volume = 1.0f;
    float music2Volume = 0.0f;
    Buffer music1Data, music2Data;
};
OryolMain(SoloudTedSidApp);

//------------------------------------------------------------------------------
AppState::Code
SoloudTedSidApp::OnRunning() {

    this->soloud.setFilterParameter(0, 0, 0, this->filterParam0[0]);
    this->soloud.setFilterParameter(0, 0, 2, this->filterParam1[0]);
    this->soloud.setFilterParameter(0, 0, 3, this->filterParam2[0]);
    this->soloud.setFilterParameter(0, 1, 0, this->filterParam0[1]);
    this->soloud.setFilterParameter(0, 1, 1, this->filterParam1[1]);
    this->soloud.setFilterParameter(0, 2, 0, this->filterParam0[2]);
    this->soloud.setFilterParameter(0, 3, 0, this->filterParam0[3]);

    float* buf = this->soloud.getWave();
    float* fft = this->soloud.calcFFT();

    Gfx::ApplyDefaultRenderTarget(ClearState::ClearColor(glm::vec4(0.2f, 0.4f, 0.8f, 1.0f)));
    IMUI::NewFrame();
    ImGui::SetNextWindowPos(ImVec2(500, 20), ImGuiSetCond_Once);
    ImGui::Begin("Output");
    ImGui::PlotLines("##Wave", buf, 256, 0, "Wave", -1, 1, ImVec2(264, 80));
    ImGui::PlotHistogram("##FFT", fft, 256/2, 0, "FFT", 0, 10, ImVec2(264, 80), 8);
    float sidregs[32 + 5];
    for (int i = 0; i < 32; i++) {
        sidregs[i] = this->soloud.getInfo(this->musicHandle1, i);
    }
    ImGui::PlotHistogram("##SID", sidregs, 32 + 5, 0, "          SID               TED", 0, 0xff, ImVec2(264, 80), 4);
    ImGui::Text("SID: %02X %02X %02X %02X %02X %02X %02X %02X",
        (int)this->soloud.getInfo(this->musicHandle1, 0),
        (int)this->soloud.getInfo(this->musicHandle1, 1),
        (int)this->soloud.getInfo(this->musicHandle1, 2),
        (int)this->soloud.getInfo(this->musicHandle1, 3),
        (int)this->soloud.getInfo(this->musicHandle1, 4),
        (int)this->soloud.getInfo(this->musicHandle1, 5),
        (int)this->soloud.getInfo(this->musicHandle1, 6),
        (int)this->soloud.getInfo(this->musicHandle1, 7));
    ImGui::Text("     %02X %02X %02X %02X %02X %02X %02X %02X",
        (int)this->soloud.getInfo(this->musicHandle1, 8),
        (int)this->soloud.getInfo(this->musicHandle1, 9),
        (int)this->soloud.getInfo(this->musicHandle1, 10),
        (int)this->soloud.getInfo(this->musicHandle1, 11),
        (int)this->soloud.getInfo(this->musicHandle1, 12),
        (int)this->soloud.getInfo(this->musicHandle1, 13),
        (int)this->soloud.getInfo(this->musicHandle1, 14),
        (int)this->soloud.getInfo(this->musicHandle1, 15));
    ImGui::Text("     %02X %02X %02X %02X %02X %02X %02X %02X",
        (int)this->soloud.getInfo(this->musicHandle1, 16),
        (int)this->soloud.getInfo(this->musicHandle1, 17),
        (int)this->soloud.getInfo(this->musicHandle1, 18),
        (int)this->soloud.getInfo(this->musicHandle1, 19),
        (int)this->soloud.getInfo(this->musicHandle1, 20),
        (int)this->soloud.getInfo(this->musicHandle1, 21),
        (int)this->soloud.getInfo(this->musicHandle1, 22),
        (int)this->soloud.getInfo(this->musicHandle1, 23));
    ImGui::Text("     %02X %02X %02X %02X %02X %02X %02X %02X",
        (int)this->soloud.getInfo(this->musicHandle1, 24),
        (int)this->soloud.getInfo(this->musicHandle1, 25),
        (int)this->soloud.getInfo(this->musicHandle1, 26),
        (int)this->soloud.getInfo(this->musicHandle1, 27),
        (int)this->soloud.getInfo(this->musicHandle1, 28),
        (int)this->soloud.getInfo(this->musicHandle1, 29),
        (int)this->soloud.getInfo(this->musicHandle1, 30),
        (int)this->soloud.getInfo(this->musicHandle1, 31));
    ImGui::Text("TED: %02X %02X %02X %02X %02X",
        (int)this->soloud.getInfo(this->musicHandle2, 64),
        (int)this->soloud.getInfo(this->musicHandle2, 65),
        (int)this->soloud.getInfo(this->musicHandle2, 66),
        (int)this->soloud.getInfo(this->musicHandle2, 67),
        (int)this->soloud.getInfo(this->musicHandle2, 68));
    ImGui::End();

    ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiSetCond_Once);
    ImGui::Begin("Control", nullptr, ImVec2(300, -1));
    ImGui::Text("Song volumes");
    if (ImGui::SliderFloat("Song1 vol", &this->music1Volume, 0, 1)) {
        this->soloud.setVolume(this->musicHandle1, this->music1Volume);
    }
    if (ImGui::SliderFloat("Song2 vol", &this->music2Volume, 0, 1)) {
        this->soloud.setVolume(this->musicHandle2, this->music2Volume);
    }
    ImGui::Separator();
    ImGui::Text("Biquad filter (lowpass)");
    ImGui::SliderFloat("Wet##4", &this->filterParam0[0], 0, 1);
    ImGui::SliderFloat("Frequency##4", &this->filterParam1[0], 0, 8000);
    ImGui::SliderFloat("Resonance##4", &this->filterParam2[0], 1, 20);
    ImGui::Separator();
    ImGui::Text("Bassboost filter");
    ImGui::SliderFloat("Wet##2", &this->filterParam0[1], 0, 1);
    ImGui::SliderFloat("Boost##2", &this->filterParam1[1], 0, 11);
    ImGui::Separator();
    ImGui::Text("Echo filter");
    ImGui::SliderFloat("Wet##3", &this->filterParam0[2], 0, 1);
    ImGui::Separator();
    ImGui::Text("DC removal filter");
    ImGui::SliderFloat("Wet##1", &this->filterParam0[3], 0, 1);
    ImGui::End();

    ImGui::Render();
    Gfx::CommitFrame();
    return Gfx::QuitRequested() ? AppState::Cleanup : AppState::Running;
}

//------------------------------------------------------------------------------
AppState::Code
SoloudTedSidApp::OnInit() {

    IOSetup ioSetup;
    ioSetup.FileSystems.Add("http", HTTPFileSystem::Creator());
    #if ORYOL_DEBUG
    ioSetup.Assigns.Add("snd:", "http://localhost:8000/");
    #else
    ioSetup.Assigns.Add("snd:", ORYOL_SAMPLE_URL);
    #endif
    IO::Setup(ioSetup);

    Gfx::Setup(GfxSetup::Window(800, 460, "SoLoud TED/SID Demo"));
    Input::Setup();
    IMUI::Setup();

    // need to compile in VS2013, can't use new initializers
    Memory::Clear(this->filterParam0, sizeof(this->filterParam0));
    Memory::Clear(this->filterParam1, sizeof(this->filterParam1));
    Memory::Clear(this->filterParam2, sizeof(this->filterParam2));
    this->filterParam1[0] = 1000;
    this->filterParam1[1] = 2;
    this->filterParam2[0] = 2;
    this->music1.setLooping(true);
    this->music2.setLooping(true);
    this->echo.setParams(0.2f, 0.5f, 0.05f);
    this->biquad.setParams(SoLoud::BiquadResonantFilter::LOWPASS, 44100, 4000, 2);
    this->soloud.setGlobalFilter(0, &this->biquad);
    this->soloud.setGlobalFilter(1, &this->bassBoost);
    this->soloud.setGlobalFilter(2, &this->echo);
    this->soloud.setGlobalFilter(3, &this->dcRemoval);
    this->soloud.init(SoLoud::Soloud::CLIP_ROUNDOFF|SoLoud::Soloud::ENABLE_VISUALIZATION);

    IO::Load("snd:modulation.sid.dump", [this](IO::LoadResult res) {
        this->music1Data = std::move(res.Data);
        this->music1.loadMem(this->music1Data.Data(), this->music1Data.Size(), false, false);
        this->musicHandle1 = this->soloud.play(this->music1, this->music1Volume);
    });
    IO::Load("snd:ted_storm.prg.dump", [this](IO::LoadResult res) {
        this->music2Data = std::move(res.Data);
        this->music2.loadMem(this->music2Data.Data(), this->music2Data.Size(), false, false);
        this->musicHandle2 = this->soloud.play(this->music2, this->music2Volume);
    });
    return App::OnInit();
}

//------------------------------------------------------------------------------
AppState::Code
SoloudTedSidApp::OnCleanup() {
    soloud.deinit();
    IMUI::Discard();
    Input::Discard();
    Gfx::Discard();
    return App::OnCleanup();
}
<|endoftext|>