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

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

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "vtkWindow.h"

// Construct an instance of  vtkRenderWindow with its screen size
// set to 300x300, borders turned on, positioned at (0,0), double
// buffering turned on.
vtkWindow::vtkWindow()
{
  this->OffScreenRendering = 0;
  this->Size[0] = this->Size[1] = 0;
  this->Position[0] = this->Position[1] = 0;
  this->Mapped = 0;
  this->WindowName = new char[strlen("Visualization Toolkit")+1];
    strcpy( this->WindowName, "Visualization Toolkit" );
  this->Erase = 1;
  this->DoubleBuffer = 0;
  this->DPI = 120;
}

// Destructor for the vtkWindow object.
vtkWindow::~vtkWindow()
{
  if( this->WindowName )
    {
    delete [] this->WindowName;
	this->WindowName = NULL;
    }
}

void vtkWindow::SetWindowName( char * _arg )
{
  vtkDebugMacro("Debug: In " __FILE__ << ", line " << __LINE__ << "\n"
         << this->GetClassName() << " (" << this << "): setting "
         << this->WindowName  << " to " << _arg << "\n\n");

  if ( this->WindowName && _arg && (!strcmp(this->WindowName,_arg)))
    {
    return;
    }
  if (this->WindowName)
    {
    delete [] this->WindowName;
    }
  if( _arg )
    {
    this->WindowName = new char[strlen(_arg)+1];
    strcpy(this->WindowName,_arg);
    }
  else
    {
    this->WindowName = NULL;
    }
  this->Modified();
}

int *vtkWindow::GetSize()
{
  return this->Size;
}

void vtkWindow::SetSize(int a[2])
{
  this->SetSize(a[0],a[1]);
}

void vtkWindow::SetSize(int x, int y)
{
  if ((this->Size[0] != x)||(this->Size[1] != y))
    {
    this->Modified();
    this->Size[0] = x;
    this->Size[1] = y;
    }
}

int *vtkWindow::GetPosition()
{
  return this->Position;
}

void vtkWindow::SetPosition(int a[2])
{
  this->SetPosition(a[0],a[1]);
}
void vtkWindow::SetPosition(int x, int y)
{
  if ((this->Position[0] != x)||(this->Position[1] != y))
    {
    this->Modified();
    this->Position[0] = x;
    this->Position[1] = y;
    }
}

void vtkWindow::PrintSelf(ostream& os, vtkIndent indent)
{
  int *temp;

  vtkObject::PrintSelf(os,indent);

  os << indent << "Erase: " << (this->Erase ? "On\n" : "Off\n");
  if ( this->WindowName )
    {
    os << indent << "Window Name: " << this->WindowName << "\n";
    }
  else
    {
    os << indent << "Window Name: (none)\n";
    }

  temp = this->GetPosition();
  os << indent << "Position: (" << temp[0] << ", " << temp[1] << ")\n";
  temp = this->GetSize();
  os << indent << "Size: (" << temp[0] << ", " << temp[1] << ")\n";
  os << indent << "Mapped: " << this->Mapped << "\n";
  os << indent << "OffScreenRendering: " << this->OffScreenRendering << "\n";
  os << indent << "Double Buffered: " << this->DoubleBuffer << "\n";
  os << indent << "DPI: " << this->DPI << "\n";

}

<commit_msg>BUG: Fixed segfault when calling this->GetPosition before window creation in XWindows<commit_after>/*=========================================================================

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

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "vtkWindow.h"

// Construct an instance of  vtkRenderWindow with its screen size
// set to 300x300, borders turned on, positioned at (0,0), double
// buffering turned on.
vtkWindow::vtkWindow()
{
  this->OffScreenRendering = 0;
  this->Size[0] = this->Size[1] = 0;
  this->Position[0] = this->Position[1] = 0;
  this->Mapped = 0;
  this->WindowName = new char[strlen("Visualization Toolkit")+1];
    strcpy( this->WindowName, "Visualization Toolkit" );
  this->Erase = 1;
  this->DoubleBuffer = 0;
  this->DPI = 120;
}

// Destructor for the vtkWindow object.
vtkWindow::~vtkWindow()
{
  if( this->WindowName )
    {
    delete [] this->WindowName;
	this->WindowName = NULL;
    }
}

void vtkWindow::SetWindowName( char * _arg )
{
  vtkDebugMacro("Debug: In " __FILE__ << ", line " << __LINE__ << "\n"
         << this->GetClassName() << " (" << this << "): setting "
         << this->WindowName  << " to " << _arg << "\n\n");

  if ( this->WindowName && _arg && (!strcmp(this->WindowName,_arg)))
    {
    return;
    }
  if (this->WindowName)
    {
    delete [] this->WindowName;
    }
  if( _arg )
    {
    this->WindowName = new char[strlen(_arg)+1];
    strcpy(this->WindowName,_arg);
    }
  else
    {
    this->WindowName = NULL;
    }
  this->Modified();
}

int *vtkWindow::GetSize()
{
  return this->Size;
}

void vtkWindow::SetSize(int a[2])
{
  this->SetSize(a[0],a[1]);
}

void vtkWindow::SetSize(int x, int y)
{
  if ((this->Size[0] != x)||(this->Size[1] != y))
    {
    this->Modified();
    this->Size[0] = x;
    this->Size[1] = y;
    }
}

int *vtkWindow::GetPosition()
{
  return this->Position;
}

void vtkWindow::SetPosition(int a[2])
{
  this->SetPosition(a[0],a[1]);
}
void vtkWindow::SetPosition(int x, int y)
{
  if ((this->Position[0] != x)||(this->Position[1] != y))
    {
    this->Modified();
    this->Position[0] = x;
    this->Position[1] = y;
    }
}

void vtkWindow::PrintSelf(ostream& os, vtkIndent indent)
{
  int *temp;

  vtkObject::PrintSelf(os,indent);

  os << indent << "Erase: " << (this->Erase ? "On\n" : "Off\n");
  if ( this->WindowName )
    {
    os << indent << "Window Name: " << this->WindowName << "\n";
    }
  else
    {
    os << indent << "Window Name: (none)\n";
    }

	// Can only print out the ivars because the window may not have been
	// created yet.
	//  temp = this->GetPosition();
  os << indent << "Position: (" << Position[0] << ", " << Position[1] << ")\n";
	//  temp = this->GetSize();
  os << indent << "Size: (" << Size[0] << ", " << Size[1] << ")\n";
  os << indent << "Mapped: " << this->Mapped << "\n";
  os << indent << "OffScreenRendering: " << this->OffScreenRendering << "\n";
  os << indent << "Double Buffered: " << this->DoubleBuffer << "\n";
  os << indent << "DPI: " << this->DPI << "\n";

}

<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "CAVEView.h"
#include "ExternalRenderWindow.h"

#include "Renderer.h"
#include "OgreWorld.h"

#include <QDesktopWidget>
#include <QResizeEvent>
#include <QKeyEvent>
#include <QDebug>
#include <QApplication>

#include "Framework.h"
#include "UiAPI.h"
#include "UiMainWindow.h"

#include "MemoryLeakCheck.h"

namespace CAVEStereo
{
    CAVEView::CAVEView(const OgreRenderer::RendererPtr &renderer) :
        renderer_(renderer),
        camera_(0),
        render_window_(0)
    {
    }

    CAVEView::~CAVEView()
    {
        if (!renderer_.expired() && camera_)
        {
            Ogre::Root::getSingleton().detachRenderTarget(render_window_->getRenderWindow()->getName());
            renderer_.lock()->GetActiveOgreWorld()->GetSceneManager()->destroyCamera(camera_);
        }
        SAFE_DELETE(render_window_);
    }

    void CAVEView::Initialize(const QString& name,  Ogre::Vector3 &top_left, Ogre::Vector3 &bottom_left, Ogre::Vector3 &bottom_right, Ogre::Vector3 &eye_pos)
    {
        assert(!renderer_.expired());
        Initialize(name, renderer_.lock()->GetWindowWidth(), renderer_.lock()->GetWindowHeight(),top_left, bottom_left, bottom_right, eye_pos);
    }

    void CAVEView::InitializePanorama(const QString& name, Ogre::Vector3 &top_left, Ogre::Vector3 &bottom_left, Ogre::Vector3 &bottom_right, Ogre::Vector3 &eye_pos,int n)
    {
        assert(!renderer_.expired());
        InitializePanorama(name, renderer_.lock()->GetWindowWidth(), renderer_.lock()->GetWindowHeight(),top_left, bottom_left, bottom_right, eye_pos, n);
    }

    void CAVEView::GetProjectionParameters( Ogre::Vector3 &top_left, Ogre::Vector3 &bottom_left, Ogre::Vector3 &bottom_right, Ogre::Vector3 &eye_pos)
    {
        top_left = tl;
        bottom_left = lb;
        bottom_right = rb;
        eye_pos = ep;
    }

    void CAVEView::ReCalculateProjection(Ogre::Vector3 &top_left, Ogre::Vector3 &bottom_left, Ogre::Vector3 &bottom_right, Ogre::Vector3 &eye_pos)
    {
        lb = bottom_left;
        rb = bottom_right;
        tl = top_left;
        ep = eye_pos;

        assert(renderer_.lock());
        assert(camera_);
        assert(render_window_);
        bool openGL = false;
        if (renderer_.lock()->GetRoot()->getRenderSystem()->getName() == "OpenGL Rendering Subsystem")
            openGL = true;

        //Projection magic be happening here.
        double n = camera_->getNearClipDistance();
        double f = camera_->getFarClipDistance();
        double l, r, b, t;

        //screenspace axes
        Ogre::Vector3 sr, su, sn;
        //from eye to screenpoints
        Ogre::Vector3 ebl,etl,ebr;

        Ogre::Matrix4 proj_mat, transl, change_base;

        sr=bottom_right-bottom_left;
        sr.normalise();
        su=top_left-bottom_left;
        su.normalise();
        sn=su.crossProduct(sr);
        sn.normalise();

        ebl = bottom_left-eye_pos;
        etl = top_left-eye_pos;
        ebr = bottom_right-eye_pos;

        qreal distance_to_plane;
        if(openGL)
        {
            sn = -sn;
            distance_to_plane = -sn.dotProduct(ebl);
        }
        else
        {
            distance_to_plane = sn.dotProduct(ebl);
        }

        l = sr.dotProduct(ebl)*n/distance_to_plane;
        r = sr.dotProduct(ebr)*n/distance_to_plane;
        b = su.dotProduct(ebl)*n/distance_to_plane;
        t = su.dotProduct(etl)*n/distance_to_plane;

        renderer_.lock()->GetRoot()->getRenderSystem()->_makeProjectionMatrix(l,r,b,t,n,f,proj_mat);
        change_base=Ogre::Matrix4(sr.x,sr.y,sr.z,0,
                                  su.x,su.y,su.z,0,
                                  sn.x,sn.y,sn.z,0,
                                  0,0,0,1);

        transl.makeTrans(-eye_pos);
        proj_mat = proj_mat*change_base*transl;
        camera_->setCustomProjectionMatrix(true, proj_mat);
    }

    void CAVEView::Initialize(const QString& name, qreal window_width, qreal window_height, Ogre::Vector3 &top_left, Ogre::Vector3 &bottom_left, Ogre::Vector3 &bottom_right, Ogre::Vector3 &eye_pos)
    {
        assert(renderer_.lock().get());
        Ogre::Camera* original_cam = renderer_.lock()->GetActiveOgreCamera();
        std::string std_name = name.toStdString();
        render_window_ = new ExternalRenderWindow();
        render_window_->CreateRenderWindow(std_name, window_width, window_height,0,0,false);
        render_window_->setGeometry(20,20,window_width,window_height);
        camera_ = renderer_.lock()->GetActiveOgreWorld()->GetSceneManager()->createCamera(std_name + "_camera");
        render_window_->getRenderWindow()->addViewport(camera_);
        camera_->getViewport()->setOverlaysEnabled(false);
        camera_->getViewport()->setShadowsEnabled(true);

        //setup the camera
        camera_->setCustomProjectionMatrix(false);
        camera_->setNearClipDistance(original_cam->getNearClipDistance());
        camera_->setFarClipDistance(original_cam->getFarClipDistance());
        camera_->setVisibilityFlags(original_cam->getVisibilityFlags());

        Ogre::SceneNode* node = dynamic_cast<Ogre::SceneNode*>(original_cam->getParentNode());
        if(node)
            node->attachObject(camera_);

        ReCalculateProjection(top_left, bottom_left, bottom_right, eye_pos);
    }

    void CAVEView::InitializePanorama(const QString& name, qreal window_width, qreal window_height, Ogre::Vector3 &top_left, Ogre::Vector3 &bottom_left, Ogre::Vector3 &bottom_right, Ogre::Vector3 &eye_pos, int window_number)
    {
        assert(renderer_.lock().get());
        Ogre::Camera* original_cam = renderer_.lock()->GetActiveOgreCamera();
        std::string std_name = name.toStdString();
        render_window_ = new ExternalRenderWindow();
        QRect rect = QApplication::desktop()->screenGeometry();
        int new_render_width = rect.width();
        int new_render_height = rect.height();
        int new_render_x = ((new_render_width/2) - ((new_render_width*0.2)/2) );

        switch(window_number)
        {
            case 1:
                render_window_->CreateRenderWindow(std_name, new_render_width*0.2, new_render_height*0.2,0,0,false);
                render_window_->setGeometry(new_render_x + 2*(new_render_width*0.2),0.77*new_render_height,new_render_width*0.2, new_render_height*0.2);
                break;
            case 2:
                render_window_->CreateRenderWindow(std_name, new_render_width*0.2, new_render_height*0.2,0,0,false);
                render_window_->setGeometry(new_render_x + (new_render_width*0.2),0.77*new_render_height,new_render_width*0.2, new_render_height*0.2);
                break;
            case 3:
                render_window_->CreateRenderWindow(std_name, new_render_width*0.2, new_render_height*0.2,0,0,false);
                render_window_->setGeometry(new_render_x ,0.77*new_render_height,new_render_width*0.2, new_render_height*0.2);
                break;
            case 4:
                render_window_->CreateRenderWindow(std_name, new_render_width*0.2, new_render_height*0.2,0,0,false);
                render_window_->setGeometry(new_render_x - (new_render_width*0.2),0.77*new_render_height,new_render_width*0.2, new_render_height*0.2);
                break;
            case 5:
                render_window_->CreateRenderWindow(std_name, new_render_width*0.2, new_render_height*0.2,0,0,false);
                render_window_->setGeometry(new_render_x - 2*(new_render_width*0.2),0.77*new_render_height,new_render_width*0.2, new_render_height*0.2);
                break;
        }

        camera_ = renderer_.lock()->GetActiveOgreWorld()->GetSceneManager()->createCamera(std_name + "_camera");
        render_window_->getRenderWindow()->addViewport(camera_);
        camera_->getViewport()->setOverlaysEnabled(false);
        camera_->getViewport()->setShadowsEnabled(true);

        camera_->setCustomProjectionMatrix(false);
        camera_->setNearClipDistance(original_cam->getNearClipDistance());
        camera_->setFarClipDistance(original_cam->getFarClipDistance());
        camera_->setVisibilityFlags(original_cam->getVisibilityFlags());

        Ogre::SceneNode* node = dynamic_cast<Ogre::SceneNode*>(original_cam->getParentNode());
        if(node)
            node->attachObject(camera_);

        ReCalculateProjection(top_left, bottom_left, bottom_right, eye_pos);
    }
}
<commit_msg>CAVE & Stereo module build fix, after default/main cam renames in Renderer. Thanks to the friendly anonymous reporter on IRC :)<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "CAVEView.h"
#include "ExternalRenderWindow.h"

#include "Renderer.h"
#include "OgreWorld.h"

#include <QDesktopWidget>
#include <QResizeEvent>
#include <QKeyEvent>
#include <QDebug>
#include <QApplication>

#include "Framework.h"
#include "UiAPI.h"
#include "UiMainWindow.h"

#include "MemoryLeakCheck.h"

namespace CAVEStereo
{
    CAVEView::CAVEView(const OgreRenderer::RendererPtr &renderer) :
        renderer_(renderer),
        camera_(0),
        render_window_(0)
    {
    }

    CAVEView::~CAVEView()
    {
        if (!renderer_.expired() && camera_)
        {
            Ogre::Root::getSingleton().detachRenderTarget(render_window_->getRenderWindow()->getName());
            renderer_.lock()->GetActiveOgreWorld()->GetSceneManager()->destroyCamera(camera_);
        }
        SAFE_DELETE(render_window_);
    }

    void CAVEView::Initialize(const QString& name,  Ogre::Vector3 &top_left, Ogre::Vector3 &bottom_left, Ogre::Vector3 &bottom_right, Ogre::Vector3 &eye_pos)
    {
        assert(!renderer_.expired());
        Initialize(name, renderer_.lock()->GetWindowWidth(), renderer_.lock()->GetWindowHeight(),top_left, bottom_left, bottom_right, eye_pos);
    }

    void CAVEView::InitializePanorama(const QString& name, Ogre::Vector3 &top_left, Ogre::Vector3 &bottom_left, Ogre::Vector3 &bottom_right, Ogre::Vector3 &eye_pos,int n)
    {
        assert(!renderer_.expired());
        InitializePanorama(name, renderer_.lock()->GetWindowWidth(), renderer_.lock()->GetWindowHeight(),top_left, bottom_left, bottom_right, eye_pos, n);
    }

    void CAVEView::GetProjectionParameters( Ogre::Vector3 &top_left, Ogre::Vector3 &bottom_left, Ogre::Vector3 &bottom_right, Ogre::Vector3 &eye_pos)
    {
        top_left = tl;
        bottom_left = lb;
        bottom_right = rb;
        eye_pos = ep;
    }

    void CAVEView::ReCalculateProjection(Ogre::Vector3 &top_left, Ogre::Vector3 &bottom_left, Ogre::Vector3 &bottom_right, Ogre::Vector3 &eye_pos)
    {
        lb = bottom_left;
        rb = bottom_right;
        tl = top_left;
        ep = eye_pos;

        assert(renderer_.lock());
        assert(camera_);
        assert(render_window_);
        bool openGL = false;
        if (renderer_.lock()->GetRoot()->getRenderSystem()->getName() == "OpenGL Rendering Subsystem")
            openGL = true;

        //Projection magic be happening here.
        double n = camera_->getNearClipDistance();
        double f = camera_->getFarClipDistance();
        double l, r, b, t;

        //screenspace axes
        Ogre::Vector3 sr, su, sn;
        //from eye to screenpoints
        Ogre::Vector3 ebl,etl,ebr;

        Ogre::Matrix4 proj_mat, transl, change_base;

        sr=bottom_right-bottom_left;
        sr.normalise();
        su=top_left-bottom_left;
        su.normalise();
        sn=su.crossProduct(sr);
        sn.normalise();

        ebl = bottom_left-eye_pos;
        etl = top_left-eye_pos;
        ebr = bottom_right-eye_pos;

        qreal distance_to_plane;
        if(openGL)
        {
            sn = -sn;
            distance_to_plane = -sn.dotProduct(ebl);
        }
        else
        {
            distance_to_plane = sn.dotProduct(ebl);
        }

        l = sr.dotProduct(ebl)*n/distance_to_plane;
        r = sr.dotProduct(ebr)*n/distance_to_plane;
        b = su.dotProduct(ebl)*n/distance_to_plane;
        t = su.dotProduct(etl)*n/distance_to_plane;

        renderer_.lock()->GetRoot()->getRenderSystem()->_makeProjectionMatrix(l,r,b,t,n,f,proj_mat);
        change_base=Ogre::Matrix4(sr.x,sr.y,sr.z,0,
                                  su.x,su.y,su.z,0,
                                  sn.x,sn.y,sn.z,0,
                                  0,0,0,1);

        transl.makeTrans(-eye_pos);
        proj_mat = proj_mat*change_base*transl;
        camera_->setCustomProjectionMatrix(true, proj_mat);
    }

    void CAVEView::Initialize(const QString& name, qreal window_width, qreal window_height, Ogre::Vector3 &top_left, Ogre::Vector3 &bottom_left, Ogre::Vector3 &bottom_right, Ogre::Vector3 &eye_pos)
    {
        assert(renderer_.lock().get());
        Ogre::Camera* original_cam = renderer_.lock()->MainOgreCamera();
        std::string std_name = name.toStdString();
        render_window_ = new ExternalRenderWindow();
        render_window_->CreateRenderWindow(std_name, window_width, window_height,0,0,false);
        render_window_->setGeometry(20,20,window_width,window_height);
        camera_ = renderer_.lock()->GetActiveOgreWorld()->GetSceneManager()->createCamera(std_name + "_camera");
        render_window_->getRenderWindow()->addViewport(camera_);
        camera_->getViewport()->setOverlaysEnabled(false);
        camera_->getViewport()->setShadowsEnabled(true);

        //setup the camera
        camera_->setCustomProjectionMatrix(false);
        camera_->setNearClipDistance(original_cam->getNearClipDistance());
        camera_->setFarClipDistance(original_cam->getFarClipDistance());
        camera_->setVisibilityFlags(original_cam->getVisibilityFlags());

        Ogre::SceneNode* node = dynamic_cast<Ogre::SceneNode*>(original_cam->getParentNode());
        if(node)
            node->attachObject(camera_);

        ReCalculateProjection(top_left, bottom_left, bottom_right, eye_pos);
    }

    void CAVEView::InitializePanorama(const QString& name, qreal window_width, qreal window_height, Ogre::Vector3 &top_left, Ogre::Vector3 &bottom_left, Ogre::Vector3 &bottom_right, Ogre::Vector3 &eye_pos, int window_number)
    {
        assert(renderer_.lock().get());
        Ogre::Camera* original_cam = renderer_.lock()->MainOgreCamera();
        std::string std_name = name.toStdString();
        render_window_ = new ExternalRenderWindow();
        QRect rect = QApplication::desktop()->screenGeometry();
        int new_render_width = rect.width();
        int new_render_height = rect.height();
        int new_render_x = ((new_render_width/2) - ((new_render_width*0.2)/2) );

        switch(window_number)
        {
            case 1:
                render_window_->CreateRenderWindow(std_name, new_render_width*0.2, new_render_height*0.2,0,0,false);
                render_window_->setGeometry(new_render_x + 2*(new_render_width*0.2),0.77*new_render_height,new_render_width*0.2, new_render_height*0.2);
                break;
            case 2:
                render_window_->CreateRenderWindow(std_name, new_render_width*0.2, new_render_height*0.2,0,0,false);
                render_window_->setGeometry(new_render_x + (new_render_width*0.2),0.77*new_render_height,new_render_width*0.2, new_render_height*0.2);
                break;
            case 3:
                render_window_->CreateRenderWindow(std_name, new_render_width*0.2, new_render_height*0.2,0,0,false);
                render_window_->setGeometry(new_render_x ,0.77*new_render_height,new_render_width*0.2, new_render_height*0.2);
                break;
            case 4:
                render_window_->CreateRenderWindow(std_name, new_render_width*0.2, new_render_height*0.2,0,0,false);
                render_window_->setGeometry(new_render_x - (new_render_width*0.2),0.77*new_render_height,new_render_width*0.2, new_render_height*0.2);
                break;
            case 5:
                render_window_->CreateRenderWindow(std_name, new_render_width*0.2, new_render_height*0.2,0,0,false);
                render_window_->setGeometry(new_render_x - 2*(new_render_width*0.2),0.77*new_render_height,new_render_width*0.2, new_render_height*0.2);
                break;
        }

        camera_ = renderer_.lock()->GetActiveOgreWorld()->GetSceneManager()->createCamera(std_name + "_camera");
        render_window_->getRenderWindow()->addViewport(camera_);
        camera_->getViewport()->setOverlaysEnabled(false);
        camera_->getViewport()->setShadowsEnabled(true);

        camera_->setCustomProjectionMatrix(false);
        camera_->setNearClipDistance(original_cam->getNearClipDistance());
        camera_->setFarClipDistance(original_cam->getFarClipDistance());
        camera_->setVisibilityFlags(original_cam->getVisibilityFlags());

        Ogre::SceneNode* node = dynamic_cast<Ogre::SceneNode*>(original_cam->getParentNode());
        if(node)
            node->attachObject(camera_);

        ReCalculateProjection(top_left, bottom_left, bottom_right, eye_pos);
    }
}
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in LICENSE

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "MemoryLeakCheck.h"
#include "OggVorbisLoader.h"
#include "LoggingFunctions.h"

#include <sstream>

#ifndef TUNDRA_NO_AUDIO
#include <vorbis/vorbisfile.h>
#endif

#ifndef TUNDRA_NO_AUDIO
namespace
{

class OggMemDataSource
{
public:
    OggMemDataSource(const u8* data, size_t size) :
        data_(data),
        size_(size),
        position_(0)
    {
    }

    size_t Read(void* ptr, size_t size)
    {
        size_t max_read = size_ - position_;
        if (size > max_read)
            size = max_read;
        if (size)
        {
            memcpy(ptr, &data_[position_], size);
            position_ += size;
        }
        return size;
    }

    int Seek(ogg_int64_t offset, int whence)
    {
        ogg_int64_t new_pos = position_;
        switch (whence)
        {
        case SEEK_SET:
            new_pos = offset;
            break;

        case SEEK_CUR:
            new_pos += offset;
            break;

        case SEEK_END:
            new_pos = size_ + offset;
            break;
        }

        if ((new_pos < 0) || (new_pos > size_))
            return -1;
        position_ = (uint)new_pos;
        return 0;
    }

    long Tell() const
    {
        return (long)position_;
    }

private:
    const u8* data_;
    size_t size_;
    size_t position_;
};

size_t OggReadCallback(void* ptr, size_t size, size_t nmemb, void* datasource)
{
    OggMemDataSource* source = (OggMemDataSource*)datasource;
    return source->Read(ptr, size * nmemb);
}

int OggSeekCallback(void* datasource, ogg_int64_t offset, int whence)
{
    OggMemDataSource* source = (OggMemDataSource*)datasource;
    return source->Seek(offset, whence);
}

long OggTellCallback(void* datasource)
{
    OggMemDataSource* source = (OggMemDataSource*)datasource;
    return source->Tell();
}

} // ~unnamed namespace
#endif

namespace OggVorbisLoader
{

bool LoadOggVorbisFromFileInMemory(const u8 *fileData, size_t numBytes, std::vector<u8> &dst, bool *isStereo, bool *is16Bit, int *frequency)
{
    if (!fileData || numBytes == 0)
    {
        LogError("Null input data passed in");
        return false;
    }

    if (!isStereo || !is16Bit || !frequency)
    {
        LogError("Outputs not set");
        return false;
    }

#ifndef TUNDRA_NO_AUDIO
    OggVorbis_File vf;
    OggMemDataSource src(fileData, numBytes);

    ov_callbacks cb;
    cb.read_func = &OggReadCallback;
    cb.seek_func = &OggSeekCallback;
    cb.tell_func = &OggTellCallback;
    cb.close_func = 0;

    int ret = ov_open_callbacks(&src, &vf, 0, 0, cb);
    if (ret < 0)
    {
        LogError("Not ogg vorbis format");
        ov_clear(&vf);
        return false;
    }

    vorbis_info* vi = ov_info(&vf, -1);
    if (!vi)
    {
        LogError("No ogg vorbis stream info");
        ov_clear(&vf);
        return false;
    }

    std::ostringstream msg;
    msg << "Decoding ogg vorbis stream with " << vi->channels << " channels, frequency " << vi->rate;
//    LogDebug(msg.str());

    *frequency = vi->rate;
    *isStereo = (vi->channels > 1);
    if (vi->channels != 1 && vi->channels != 2)
        LogWarning("Warning: Loaded Ogg Vorbis data contains an unsupported number of channels: " + QString::number(vi->channels));

    uint decoded_bytes = 0;
    dst.clear();
    for(;;)
    {
        static const int MAX_DECODE_SIZE = 16384;
        dst.resize(decoded_bytes + MAX_DECODE_SIZE);
        int bitstream;
        long ret = ov_read(&vf, (char*)&dst[decoded_bytes], MAX_DECODE_SIZE, 0, 2, 1, &bitstream);
        if (ret <= 0)
            break;
        decoded_bytes += ret;
    }

    dst.resize(decoded_bytes);

    {
        std::ostringstream msg;
        msg << "Decoded " << decoded_bytes << " bytes of ogg vorbis sound data";
//        LogDebug(msg.str());
    }

    ov_clear(&vf);
    return true;
#else
    return false;
#endif
}

} // ~OggVorbisLoader
<commit_msg>Singed<->unsigned int conversion warning fix.<commit_after>// For conditions of distribution and use, see copyright notice in LICENSE

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "MemoryLeakCheck.h"
#include "OggVorbisLoader.h"
#include "LoggingFunctions.h"

#include <sstream>

#ifndef TUNDRA_NO_AUDIO
#include <vorbis/vorbisfile.h>
#endif

#ifndef TUNDRA_NO_AUDIO
namespace
{

class OggMemDataSource
{
public:
    OggMemDataSource(const u8* data, size_t size) :
        data_(data),
        size_(size),
        position_(0)
    {
    }

    size_t Read(void* ptr, size_t size)
    {
        size_t max_read = size_ - position_;
        if (size > max_read)
            size = max_read;
        if (size)
        {
            memcpy(ptr, &data_[position_], size);
            position_ += size;
        }
        return size;
    }

    int Seek(ogg_int64_t offset, int whence)
    {
        size_t new_pos = position_;
        switch (whence)
        {
        case SEEK_SET:
            new_pos = offset;
            break;
        case SEEK_CUR:
            new_pos += offset;
            break;
        case SEEK_END:
            new_pos = size_ + offset;
            break;
        }

        if (new_pos < 0 || new_pos > size_)
            return -1;
        position_ = new_pos;
        return 0;
    }

    long Tell() const
    {
        return (long)position_;
    }

private:
    const u8* data_;
    size_t size_;
    size_t position_;
};

size_t OggReadCallback(void* ptr, size_t size, size_t nmemb, void* datasource)
{
    OggMemDataSource* source = (OggMemDataSource*)datasource;
    return source->Read(ptr, size * nmemb);
}

int OggSeekCallback(void* datasource, ogg_int64_t offset, int whence)
{
    OggMemDataSource* source = (OggMemDataSource*)datasource;
    return source->Seek(offset, whence);
}

long OggTellCallback(void* datasource)
{
    OggMemDataSource* source = (OggMemDataSource*)datasource;
    return source->Tell();
}

} // ~unnamed namespace
#endif

namespace OggVorbisLoader
{

bool LoadOggVorbisFromFileInMemory(const u8 *fileData, size_t numBytes, std::vector<u8> &dst, bool *isStereo, bool *is16Bit, int *frequency)
{
    if (!fileData || numBytes == 0)
    {
        LogError("Null input data passed in");
        return false;
    }

    if (!isStereo || !is16Bit || !frequency)
    {
        LogError("Outputs not set");
        return false;
    }

#ifndef TUNDRA_NO_AUDIO
    OggVorbis_File vf;
    OggMemDataSource src(fileData, numBytes);

    ov_callbacks cb;
    cb.read_func = &OggReadCallback;
    cb.seek_func = &OggSeekCallback;
    cb.tell_func = &OggTellCallback;
    cb.close_func = 0;

    int ret = ov_open_callbacks(&src, &vf, 0, 0, cb);
    if (ret < 0)
    {
        LogError("Not ogg vorbis format");
        ov_clear(&vf);
        return false;
    }

    vorbis_info* vi = ov_info(&vf, -1);
    if (!vi)
    {
        LogError("No ogg vorbis stream info");
        ov_clear(&vf);
        return false;
    }

    std::ostringstream msg;
    msg << "Decoding ogg vorbis stream with " << vi->channels << " channels, frequency " << vi->rate;
//    LogDebug(msg.str());

    *frequency = vi->rate;
    *isStereo = (vi->channels > 1);
    if (vi->channels != 1 && vi->channels != 2)
        LogWarning("Warning: Loaded Ogg Vorbis data contains an unsupported number of channels: " + QString::number(vi->channels));

    uint decoded_bytes = 0;
    dst.clear();
    for(;;)
    {
        static const int MAX_DECODE_SIZE = 16384;
        dst.resize(decoded_bytes + MAX_DECODE_SIZE);
        int bitstream;
        long ret = ov_read(&vf, (char*)&dst[decoded_bytes], MAX_DECODE_SIZE, 0, 2, 1, &bitstream);
        if (ret <= 0)
            break;
        decoded_bytes += ret;
    }

    dst.resize(decoded_bytes);

    {
        std::ostringstream msg;
        msg << "Decoded " << decoded_bytes << " bytes of ogg vorbis sound data";
//        LogDebug(msg.str());
    }

    ov_clear(&vf);
    return true;
#else
    return false;
#endif
}

} // ~OggVorbisLoader
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2008, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  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 OWNER 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 "IECore/DPXImageWriter.h"
#include "IECore/MessageHandler.h"
#include "IECore/VectorTypedData.h"
#include "IECore/ByteOrder.h"
#include "IECore/ImagePrimitive.h"
#include "IECore/FileNameParameter.h"
#include "IECore/DataConvert.h"
#include "IECore/ScaledDataConversion.h"
#include "IECore/CompoundDataConversion.h"
#include "IECore/LinearToCineonDataConversion.h"
#include "IECore/DespatchTypedData.h"

#include "IECore/private/dpx.h"

#include "boost/format.hpp"

#include <fstream>
#include <time.h>

using namespace IECore;
using namespace std;
using namespace boost;
using namespace Imath;

const Writer::WriterDescription<DPXImageWriter> DPXImageWriter::m_writerDescription("dpx");

DPXImageWriter::DPXImageWriter() :
		ImageWriter("DPXImageWriter", "Serializes images to Digital Picture eXchange 10-bit log image format")
{
}

DPXImageWriter::DPXImageWriter( ObjectPtr image, const string &fileName ) :
		ImageWriter("DPXImageWriter", "Serializes images to Digital Picture eXchange 10-bit log image format")
{
	m_objectParameter->setValue( image );
	m_fileNameParameter->setTypedValue( fileName );
}

DPXImageWriter::~DPXImageWriter()
{
}

struct DPXImageWriter::ChannelConverter
{
	typedef void ReturnType;

	std::string m_channelName;
	Box2i m_displayWindow;
	Box2i m_dataWindow;
	unsigned int m_bitShift;
	std::vector<unsigned int> &m_imageBuffer;

	ChannelConverter( const std::string &channelName, const Box2i &displayWindow, const Box2i &dataWindow, unsigned int bitShift, std::vector<unsigned int> &imageBuffer  )
	: m_channelName( channelName ), m_displayWindow( displayWindow ), m_dataWindow( dataWindow ), m_bitShift( bitShift ), m_imageBuffer( imageBuffer )
	{
	}

	template<typename T>
	ReturnType operator()( typename T::Ptr dataContainer )
	{
		assert( dataContainer );

		const typename T::ValueType &data = dataContainer->readable();

		CompoundDataConversion<
			ScaledDataConversion<typename T::ValueType::value_type, float>,
			LinearToCineonDataConversion<float, unsigned int>
		> converter;

		int displayWidth = m_displayWindow.size().x + 1;
		int dataWidth = m_dataWindow.size().x + 1;

		int dataY = 0;

		for ( int y = m_dataWindow.min.y; y <= m_dataWindow.max.y; y++, dataY++ )
		{
			int dataOffset = dataY * dataWidth;
			assert( dataOffset >= 0 );

			for ( int x = m_dataWindow.min.x; x <= m_dataWindow.max.x; x++, dataOffset++ )
			{
				int pixelIdx = ( y - m_displayWindow.min.y ) * displayWidth + ( x - m_displayWindow.min.x );

				assert( pixelIdx >= 0 );
				assert( pixelIdx < (int)m_imageBuffer.size() );
				assert( dataOffset < (int)data.size() );

				/// Perform the conversion, and set the appropriate bits in the "cell"
				m_imageBuffer[ pixelIdx ] |= converter( data[dataOffset] ) << m_bitShift;
			}
		}
	};

	struct ErrorHandler
	{
		template<typename T, typename F>
		void operator()( typename T::ConstPtr data, const F& functor )
		{
			assert( data );

			throw InvalidArgumentException( ( boost::format( "DPXImageWriter: Invalid data type \"%s\" for channel \"%s\"." ) % Object::typeNameFromTypeId( data->typeId() ) % functor.m_channelName ).str() );
		}
	};
};

void DPXImageWriter::writeImage( const vector<string> &names, ConstImagePrimitivePtr image, const Box2i &dataWindow ) const
{
	// write the dpx in the standard 10bit log format
	ofstream out;
	out.open(fileName().c_str());
	if ( !out.is_open() )
	{
		throw IOException( "DPXImageWriter: Error writing to " + fileName() );
	}

	/// We'd like RGB to be at the front, in that order, because it seems that not all readers support the channel identifiers!
	vector<string> desiredChannelOrder;
	desiredChannelOrder.push_back( "R" );
	desiredChannelOrder.push_back( "G" );
	desiredChannelOrder.push_back( "B" );

	vector<string> namesCopy = names;
	vector<string> filteredNames;

	for ( vector<string>::const_iterator it = desiredChannelOrder.begin(); it != desiredChannelOrder.end(); ++it )
	{
		vector<string>::iterator res = find( namesCopy.begin(), namesCopy.end(), *it );
		if ( res != namesCopy.end() )
		{
			namesCopy.erase( res );
			filteredNames.push_back( *it );
		}
	}

	for ( vector<string>::const_iterator it = namesCopy.begin(); it != namesCopy.end(); ++it )
	{
		filteredNames.push_back( *it );
	}

	assert( names.size() == filteredNames.size() );

	Box2i displayWindow = image->getDisplayWindow();

	int displayWidth  = 1 + displayWindow.size().x;
	int displayHeight = 1 + displayWindow.size().y;

	// build the header
	DPXFileInformation fi;
	memset(&fi, 0, sizeof(fi));

	DPXImageInformation ii;
	memset(&ii, 0, sizeof(ii));

	DPXImageOrientation ioi;
	memset(&ioi, 0, sizeof(ioi));

	DPXMotionPictureFilm mpf;
	memset(&mpf, 0, sizeof(mpf));

	DPXTelevisionHeader th;
	memset(&th, 0, sizeof(th));

	fi.magic = asBigEndian<>( 0x53445058 );

	// compute data offsets
	fi.gen_hdr_size = sizeof(fi) + sizeof(ii) + sizeof(ioi);
	fi.gen_hdr_size = asBigEndian<>(fi.gen_hdr_size);

	fi.ind_hdr_size = sizeof(mpf) + sizeof(th);
	fi.ind_hdr_size = asBigEndian<>(fi.ind_hdr_size);

	int header_size = sizeof(fi) + sizeof(ii) + sizeof(ioi) + sizeof(mpf) + sizeof(th);
	fi.image_data_offset = header_size;
	fi.image_data_offset = asBigEndian<>(fi.image_data_offset);

	strcpy((char *) fi.vers, "V2.0");

	strncpy( (char *) fi.file_name, fileName().c_str(), sizeof( fi.file_name ) );

	// compute the current date and time
	time_t t;
	time(&t);
	struct tm gmt;
	localtime_r(&t, &gmt);
	snprintf((char *) fi.create_time,  sizeof( fi.create_time ), "%04d:%02d:%02d:%02d:%02d:%02d:%s",
	        1900 + gmt.tm_year, gmt.tm_mon, gmt.tm_mday,
	        gmt.tm_hour, gmt.tm_min, gmt.tm_sec, gmt.tm_zone );

	snprintf((char *) fi.creator, sizeof( fi.creator ), "cortex");
	snprintf((char *) fi.project, sizeof( fi.project ), "cortex");
	snprintf((char *) fi.copyright, sizeof( fi.copyright ), "Unknown");

	ii.orientation = 0;    // left-to-right, top-to-bottom
	ii.element_number = 1;
	ii.pixels_per_line = displayWidth;
	ii.lines_per_image_ele = displayHeight;

	ii.element_number      = asBigEndian<>(ii.element_number);
	ii.pixels_per_line     = asBigEndian<>(ii.pixels_per_line);
	ii.lines_per_image_ele = asBigEndian<>(ii.lines_per_image_ele);

	for (int c = 0; c < 8; ++c)
	{
		DPXImageInformation::_image_element &ie = ii.image_element[c];
		ie.data_sign = 0;

		/// \todo Dcoument these constants
		ie.ref_low_data = 0;
		ie.ref_low_quantity = 0.0;
		ie.ref_high_data = 1023;
		ie.ref_high_quantity = 2.046;

		ie.ref_low_data = asBigEndian<>(ie.ref_low_data);
		ie.ref_low_quantity = asBigEndian<>(ie.ref_low_quantity);
		ie.ref_high_data = asBigEndian<>(ie.ref_high_data);
		ie.ref_high_quantity = asBigEndian<>(ie.ref_high_quantity);

		/// \todo Dcoument these constants
		ie.transfer = 1;
		ie.packing = 256;
		ie.bit_size = 10;
		ie.descriptor = 50;

		ie.data_offset = fi.image_data_offset;
	}

	ioi.x_offset = 0;
	ioi.y_offset = 0;

	// Write the header
	int image_data_size = sizeof( unsigned int ) * displayWidth * displayHeight;
	fi.file_size = header_size + image_data_size;

	fi.file_size = asBigEndian<>(fi.file_size);

	out.write(reinterpret_cast<char *>(&fi),  sizeof(fi));
	if ( out.fail() )
	{
		throw IOException( "DPXImageWriter: Error writing to " + fileName() );
	}

	out.write(reinterpret_cast<char *>(&ii),  sizeof(ii));
	if ( out.fail() )
	{
		throw IOException( "DPXImageWriter: Error writing to " + fileName() );
	}

	out.write(reinterpret_cast<char *>(&ioi), sizeof(ioi));
	if ( out.fail() )
	{
		throw IOException( "DPXImageWriter: Error writing to " + fileName() );
	}

	out.write(reinterpret_cast<char *>(&mpf), sizeof(mpf));
	if ( out.fail() )
	{
		throw IOException( "DPXImageWriter: Error writing to " + fileName() );
	}

	out.write(reinterpret_cast<char *>(&th),  sizeof(th));
	if ( out.fail() )
	{
		throw IOException( "DPXImageWriter: Error writing to " + fileName() );
	}

	// write the data
	vector<unsigned int> imageBuffer( displayWidth*displayHeight, 0 );

	int offset = 0;
	vector<string>::const_iterator i = filteredNames.begin();
	while (i != filteredNames.end())
	{
		if (!(*i == "R" || *i == "G" || *i == "B"))
		{
			msg( Msg::Warning, "DPXImageWriter::write", format( "Channel \"%s\" was not encoded." ) % *i );
			++i;
			continue;
		}

		int bpp = 10;
		unsigned int shift = (32 - bpp) - (offset*bpp);

		assert( image->variables.find( *i ) != image->variables.end() );
		DataPtr dataContainer = image->variables.find( *i )->second.data;
		assert( dataContainer );

		ChannelConverter converter( *i, image->getDisplayWindow(), dataWindow, shift, imageBuffer );

		despatchTypedData<
			ChannelConverter,
			TypeTraits::IsNumericVectorTypedData,
			ChannelConverter::ErrorHandler
		>( dataContainer, converter );

		++i;
		++offset;
	}

	// write the buffer
	for (int i = 0; i < displayWidth * displayHeight; ++i)
	{
		imageBuffer[i] = asBigEndian<>(imageBuffer[i]);
		out.write( (const char *) (&imageBuffer[i]), sizeof(unsigned int) );
		if ( out.fail() )
		{
			throw IOException( "DPXImageWriter: Error writing to " + fileName() );
		}
	}
}
<commit_msg>Fixed constant to make consistent with DPXImageReader<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2008, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  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 OWNER 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 "IECore/DPXImageWriter.h"
#include "IECore/MessageHandler.h"
#include "IECore/VectorTypedData.h"
#include "IECore/ByteOrder.h"
#include "IECore/ImagePrimitive.h"
#include "IECore/FileNameParameter.h"
#include "IECore/DataConvert.h"
#include "IECore/ScaledDataConversion.h"
#include "IECore/CompoundDataConversion.h"
#include "IECore/LinearToCineonDataConversion.h"
#include "IECore/DespatchTypedData.h"

#include "IECore/private/dpx.h"

#include "boost/format.hpp"

#include <fstream>
#include <time.h>

using namespace IECore;
using namespace std;
using namespace boost;
using namespace Imath;

const Writer::WriterDescription<DPXImageWriter> DPXImageWriter::m_writerDescription("dpx");

DPXImageWriter::DPXImageWriter() :
		ImageWriter("DPXImageWriter", "Serializes images to Digital Picture eXchange 10-bit log image format")
{
}

DPXImageWriter::DPXImageWriter( ObjectPtr image, const string &fileName ) :
		ImageWriter("DPXImageWriter", "Serializes images to Digital Picture eXchange 10-bit log image format")
{
	m_objectParameter->setValue( image );
	m_fileNameParameter->setTypedValue( fileName );
}

DPXImageWriter::~DPXImageWriter()
{
}

struct DPXImageWriter::ChannelConverter
{
	typedef void ReturnType;

	std::string m_channelName;
	Box2i m_displayWindow;
	Box2i m_dataWindow;
	unsigned int m_bitShift;
	std::vector<unsigned int> &m_imageBuffer;

	ChannelConverter( const std::string &channelName, const Box2i &displayWindow, const Box2i &dataWindow, unsigned int bitShift, std::vector<unsigned int> &imageBuffer  )
	: m_channelName( channelName ), m_displayWindow( displayWindow ), m_dataWindow( dataWindow ), m_bitShift( bitShift ), m_imageBuffer( imageBuffer )
	{
	}

	template<typename T>
	ReturnType operator()( typename T::Ptr dataContainer )
	{
		assert( dataContainer );

		const typename T::ValueType &data = dataContainer->readable();

		CompoundDataConversion<
			ScaledDataConversion<typename T::ValueType::value_type, float>,
			LinearToCineonDataConversion<float, unsigned int>
		> converter;

		int displayWidth = m_displayWindow.size().x + 1;
		int dataWidth = m_dataWindow.size().x + 1;

		int dataY = 0;

		for ( int y = m_dataWindow.min.y; y <= m_dataWindow.max.y; y++, dataY++ )
		{
			int dataOffset = dataY * dataWidth;
			assert( dataOffset >= 0 );

			for ( int x = m_dataWindow.min.x; x <= m_dataWindow.max.x; x++, dataOffset++ )
			{
				int pixelIdx = ( y - m_displayWindow.min.y ) * displayWidth + ( x - m_displayWindow.min.x );

				assert( pixelIdx >= 0 );
				assert( pixelIdx < (int)m_imageBuffer.size() );
				assert( dataOffset < (int)data.size() );

				/// Perform the conversion, and set the appropriate bits in the "cell"
				m_imageBuffer[ pixelIdx ] |= converter( data[dataOffset] ) << m_bitShift;
			}
		}
	};

	struct ErrorHandler
	{
		template<typename T, typename F>
		void operator()( typename T::ConstPtr data, const F& functor )
		{
			assert( data );

			throw InvalidArgumentException( ( boost::format( "DPXImageWriter: Invalid data type \"%s\" for channel \"%s\"." ) % Object::typeNameFromTypeId( data->typeId() ) % functor.m_channelName ).str() );
		}
	};
};

void DPXImageWriter::writeImage( const vector<string> &names, ConstImagePrimitivePtr image, const Box2i &dataWindow ) const
{
	// write the dpx in the standard 10bit log format
	ofstream out;
	out.open(fileName().c_str());
	if ( !out.is_open() )
	{
		throw IOException( "DPXImageWriter: Error writing to " + fileName() );
	}

	/// We'd like RGB to be at the front, in that order, because it seems that not all readers support the channel identifiers!
	vector<string> desiredChannelOrder;
	desiredChannelOrder.push_back( "R" );
	desiredChannelOrder.push_back( "G" );
	desiredChannelOrder.push_back( "B" );

	vector<string> namesCopy = names;
	vector<string> filteredNames;

	for ( vector<string>::const_iterator it = desiredChannelOrder.begin(); it != desiredChannelOrder.end(); ++it )
	{
		vector<string>::iterator res = find( namesCopy.begin(), namesCopy.end(), *it );
		if ( res != namesCopy.end() )
		{
			namesCopy.erase( res );
			filteredNames.push_back( *it );
		}
	}

	for ( vector<string>::const_iterator it = namesCopy.begin(); it != namesCopy.end(); ++it )
	{
		filteredNames.push_back( *it );
	}

	assert( names.size() == filteredNames.size() );

	Box2i displayWindow = image->getDisplayWindow();

	int displayWidth  = 1 + displayWindow.size().x;
	int displayHeight = 1 + displayWindow.size().y;

	// build the header
	DPXFileInformation fi;
	memset(&fi, 0, sizeof(fi));

	DPXImageInformation ii;
	memset(&ii, 0, sizeof(ii));

	DPXImageOrientation ioi;
	memset(&ioi, 0, sizeof(ioi));

	DPXMotionPictureFilm mpf;
	memset(&mpf, 0, sizeof(mpf));

	DPXTelevisionHeader th;
	memset(&th, 0, sizeof(th));

	fi.magic = asBigEndian<>( 0x53445058 );

	// compute data offsets
	fi.gen_hdr_size = sizeof(fi) + sizeof(ii) + sizeof(ioi);
	fi.gen_hdr_size = asBigEndian<>(fi.gen_hdr_size);

	fi.ind_hdr_size = sizeof(mpf) + sizeof(th);
	fi.ind_hdr_size = asBigEndian<>(fi.ind_hdr_size);

	int header_size = sizeof(fi) + sizeof(ii) + sizeof(ioi) + sizeof(mpf) + sizeof(th);
	fi.image_data_offset = header_size;
	fi.image_data_offset = asBigEndian<>(fi.image_data_offset);

	strcpy((char *) fi.vers, "V2.0");

	strncpy( (char *) fi.file_name, fileName().c_str(), sizeof( fi.file_name ) );

	// compute the current date and time
	time_t t;
	time(&t);
	struct tm gmt;
	localtime_r(&t, &gmt);
	snprintf((char *) fi.create_time,  sizeof( fi.create_time ), "%04d:%02d:%02d:%02d:%02d:%02d:%s",
	        1900 + gmt.tm_year, gmt.tm_mon, gmt.tm_mday,
	        gmt.tm_hour, gmt.tm_min, gmt.tm_sec, gmt.tm_zone );

	snprintf((char *) fi.creator, sizeof( fi.creator ), "cortex");
	snprintf((char *) fi.project, sizeof( fi.project ), "cortex");
	snprintf((char *) fi.copyright, sizeof( fi.copyright ), "Unknown");

	ii.orientation = 0;    // left-to-right, top-to-bottom
	ii.element_number = 1;
	ii.pixels_per_line = displayWidth;
	ii.lines_per_image_ele = displayHeight;

	ii.element_number      = asBigEndian<>(ii.element_number);
	ii.pixels_per_line     = asBigEndian<>(ii.pixels_per_line);
	ii.lines_per_image_ele = asBigEndian<>(ii.lines_per_image_ele);

	for (int c = 0; c < 8; ++c)
	{
		DPXImageInformation::_image_element &ie = ii.image_element[c];
		ie.data_sign = 0;

		/// \todo Dcoument these constants
		ie.ref_low_data = 0;
		ie.ref_low_quantity = 0.0;
		ie.ref_high_data = 1023;
		ie.ref_high_quantity = 2.046;

		ie.ref_low_data = asBigEndian<>(ie.ref_low_data);
		ie.ref_low_quantity = asBigEndian<>(ie.ref_low_quantity);
		ie.ref_high_data = asBigEndian<>(ie.ref_high_data);
		ie.ref_high_quantity = asBigEndian<>(ie.ref_high_quantity);

		/// \todo Dcoument these constants
		ie.transfer = 1;
		ie.packing =  asBigEndian<short>( 1 );
		ie.bit_size = 10;
		ie.descriptor = 50;

		ie.data_offset = fi.image_data_offset;
	}

	ioi.x_offset = 0;
	ioi.y_offset = 0;

	// Write the header
	int image_data_size = sizeof( unsigned int ) * displayWidth * displayHeight;
	fi.file_size = header_size + image_data_size;

	fi.file_size = asBigEndian<>(fi.file_size);

	out.write(reinterpret_cast<char *>(&fi),  sizeof(fi));
	if ( out.fail() )
	{
		throw IOException( "DPXImageWriter: Error writing to " + fileName() );
	}

	out.write(reinterpret_cast<char *>(&ii),  sizeof(ii));
	if ( out.fail() )
	{
		throw IOException( "DPXImageWriter: Error writing to " + fileName() );
	}

	out.write(reinterpret_cast<char *>(&ioi), sizeof(ioi));
	if ( out.fail() )
	{
		throw IOException( "DPXImageWriter: Error writing to " + fileName() );
	}

	out.write(reinterpret_cast<char *>(&mpf), sizeof(mpf));
	if ( out.fail() )
	{
		throw IOException( "DPXImageWriter: Error writing to " + fileName() );
	}

	out.write(reinterpret_cast<char *>(&th),  sizeof(th));
	if ( out.fail() )
	{
		throw IOException( "DPXImageWriter: Error writing to " + fileName() );
	}

	// write the data
	vector<unsigned int> imageBuffer( displayWidth*displayHeight, 0 );

	int offset = 0;
	vector<string>::const_iterator i = filteredNames.begin();
	while (i != filteredNames.end())
	{
		if (!(*i == "R" || *i == "G" || *i == "B"))
		{
			msg( Msg::Warning, "DPXImageWriter::write", format( "Channel \"%s\" was not encoded." ) % *i );
			++i;
			continue;
		}

		int bpp = 10;
		unsigned int shift = (32 - bpp) - (offset*bpp);

		assert( image->variables.find( *i ) != image->variables.end() );
		DataPtr dataContainer = image->variables.find( *i )->second.data;
		assert( dataContainer );

		ChannelConverter converter( *i, image->getDisplayWindow(), dataWindow, shift, imageBuffer );

		despatchTypedData<
			ChannelConverter,
			TypeTraits::IsNumericVectorTypedData,
			ChannelConverter::ErrorHandler
		>( dataContainer, converter );

		++i;
		++offset;
	}

	// write the buffer
	for (int i = 0; i < displayWidth * displayHeight; ++i)
	{
		imageBuffer[i] = asBigEndian<>(imageBuffer[i]);
		out.write( (const char *) (&imageBuffer[i]), sizeof(unsigned int) );
		if ( out.fail() )
		{
			throw IOException( "DPXImageWriter: Error writing to " + fileName() );
		}
	}
}
<|endoftext|>


<commit_before>#include <list>
#include <map>
#include <stdexcept>
#include <string>
#include <utility>

#include <boost/tr1/unordered_map.hpp>

#include <boost/filesystem.hpp>

#include <AlpinoCorpus/CorpusReader.hh>
#include <AlpinoCorpus/CorpusReaderFactory.hh>
#include <AlpinoCorpus/Entry.hh>
#include <AlpinoCorpus/Error.hh>
#include <AlpinoCorpus/IterImpl.hh>
#include <AlpinoCorpus/RecursiveCorpusReader.hh>

#include "util/NameCompare.hh"

namespace bf = boost::filesystem;

namespace alpinocorpus {

struct ReaderIter
{
  ReaderIter(std::string newName, CorpusReader *newReader,
      CorpusReader::EntryIterator newIter) :
    name(newName), reader(newReader), iter(newIter) {}

  std::string name;
  CorpusReader *reader;
  CorpusReader::EntryIterator iter;
};

/*
bool operator==(ReaderIter const &left, ReaderIter const &right)
{
  return left.name == right.name && left.reader == right.reader &&
    left.iter == right.iter;
}
*/

class RecursiveCorpusReaderPrivate : public CorpusReader
{
  typedef std::map<std::string, CorpusReader *, NameCompare> CorpusReaders;
  class RecursiveIter : public IterImpl
  {
  public:
    RecursiveIter(CorpusReaders const &readers);
    RecursiveIter(CorpusReaders const &readers,
      std::string const &query);
    ~RecursiveIter();
    IterImpl *copy() const;
    void nextIterator();
    bool hasNext();
    Entry next(CorpusReader const &rdr);
  private:

    std::list<ReaderIter> d_iters;
  };
public:
  RecursiveCorpusReaderPrivate(std::string const &directory);
  virtual ~RecursiveCorpusReaderPrivate();

  EntryIterator getEntries() const;
  std::string getName() const;
  size_t getSize() const;
  void push_back(std::string const &name, CorpusReader *reader);
  std::string readEntry(std::string const &) const;
  std::string readEntryMarkQueries(std::string const &entry, std::list<MarkerQuery> const &queries) const;
  EntryIterator runXPath(std::string const &query) const;
  bool validQuery(QueryDialect d, bool variables, std::string const &query) const;

private:
  CorpusReader const *corpusReaderFromPath(std::string const &path) const;
  std::string entryFromPath(std::string const &path) const;

  bf::path d_directory;
  std::list<CorpusReader *> d_corpusReaders;
  CorpusReaders d_corpusReaderMap;
};

// Implementation of the public interface.
RecursiveCorpusReader::RecursiveCorpusReader(std::string const &directory) :
  d_private(new RecursiveCorpusReaderPrivate(directory))
{
}

RecursiveCorpusReader::~RecursiveCorpusReader()
{
  delete d_private;
}

CorpusReader::EntryIterator RecursiveCorpusReader::getEntries() const
{
  return d_private->getEntries();
}

std::string RecursiveCorpusReader::getName() const
{
  return d_private->getName();
}

size_t RecursiveCorpusReader::getSize() const
{
  return d_private->getSize();
}

bool RecursiveCorpusReader::validQuery(QueryDialect d, bool variables, std::string const &query) const
{
  return d_private->isValidQuery(d, variables, query);
}

std::string RecursiveCorpusReader::readEntry(std::string const &entry) const
{
  return d_private->readEntry(entry);
}

std::string RecursiveCorpusReader::readEntryMarkQueries(std::string const &entry,
    std::list<MarkerQuery> const &queries) const
{
  return d_private->readEntryMarkQueries(entry, queries);
}

CorpusReader::EntryIterator RecursiveCorpusReader::runXPath(std::string const &query) const
{
  return d_private->query(XPATH, query);
}

// Implementation of the private interface

RecursiveCorpusReaderPrivate::RecursiveCorpusReaderPrivate(std::string const &directory)
{
  if (directory[directory.size() - 1] == '/')
    d_directory = bf::path(directory).parent_path();
  else
    d_directory = bf::path(directory);

  if (!bf::exists(d_directory) ||
    !bf::is_directory(d_directory))
    throw OpenError(directory, "non-existent or not a directory");

  for (bf::recursive_directory_iterator iter(d_directory, bf::symlink_option::recurse);
       iter != bf::recursive_directory_iterator();
       ++iter)
  {
    if (iter->path().extension() != ".dact" &&
        iter->path().extension() != ".index")
      continue;

    CorpusReader *reader(CorpusReaderFactory::open(iter->path().string()));

    bf::path namePath = iter->path();
    namePath.replace_extension("");
    std::string name = namePath.string();

    name.erase(0, d_directory.string().size() + 1);

    push_back(name, reader);
  }
}

RecursiveCorpusReaderPrivate::~RecursiveCorpusReaderPrivate()
{
  for (std::list<CorpusReader *>::iterator iter = d_corpusReaders.begin();
      iter != d_corpusReaders.end(); ++iter)
    delete *iter;
}

CorpusReader::EntryIterator RecursiveCorpusReaderPrivate::getEntries() const
{
  return EntryIterator(new RecursiveIter(d_corpusReaderMap));
}

std::string RecursiveCorpusReaderPrivate::getName() const
{
  return "<multi>";
}

size_t RecursiveCorpusReaderPrivate::getSize() const
{
  size_t size = 0;

  for (std::list<CorpusReader *>::const_iterator iter =
      d_corpusReaders.begin(); iter != d_corpusReaders.end(); ++iter)
    size += (*iter)->size();

  return size;
}

void RecursiveCorpusReaderPrivate::push_back(std::string const &name,
    CorpusReader *reader)
{
  // Ignore empty corpus readers, simplifies assumptions.
  if (reader->size() == 0) {
    delete reader;
    return;
  }

  d_corpusReaders.push_back(reader);
  d_corpusReaderMap[name] = reader; // XXX - exists check?
}

CorpusReader const *RecursiveCorpusReaderPrivate::corpusReaderFromPath(
    std::string const &path) const
{
  for (CorpusReaders::const_iterator iter =
      d_corpusReaderMap.begin(); iter != d_corpusReaderMap.end(); ++iter)
    if (path.find(iter->first) == 0)
      return iter->second;

  throw std::runtime_error(std::string("Unknown corpus: " + path));
}

std::string RecursiveCorpusReaderPrivate::entryFromPath(
    std::string const &path) const
{
  for (CorpusReaders::const_iterator iter =
      d_corpusReaderMap.begin(); iter != d_corpusReaderMap.end(); ++iter)
    if (path.find(iter->first) == 0)
      return path.substr(iter->first.size() + 1);

  throw std::runtime_error(std::string("Could not find entry: " + path));
}

std::string RecursiveCorpusReaderPrivate::readEntry(std::string const &path) const
{
  CorpusReader const *reader = corpusReaderFromPath(path);
  return reader->read(entryFromPath(path));
}

std::string RecursiveCorpusReaderPrivate::readEntryMarkQueries(
    std::string const &path, std::list<MarkerQuery> const &queries) const
{
  CorpusReader const *reader = corpusReaderFromPath(path);
  return reader->read(entryFromPath(path), queries);
}

CorpusReader::EntryIterator RecursiveCorpusReaderPrivate::runXPath(
    std::string const &query) const
{
  return EntryIterator(new RecursiveIter(d_corpusReaderMap, query));
}

bool RecursiveCorpusReaderPrivate::validQuery(QueryDialect d, bool variables, std::string const &query) const
{
  if (d_corpusReaders.size() == 0)
    return false;

  for (std::list<CorpusReader *>::const_iterator iter = d_corpusReaders.begin();
      iter != d_corpusReaders.end(); ++iter)
    if (!(*iter)->isValidQuery(d, variables, query))
      return false;

  // Correct according to all corpus readers.
  return true;
}

// Iteration over RecursiveCorpusReaders

RecursiveCorpusReaderPrivate::RecursiveIter::RecursiveIter(
  CorpusReaders const &readers)
{
  for (CorpusReaders::const_iterator
      iter = readers.begin();
      iter != readers.end(); ++iter)
    d_iters.push_back(ReaderIter(iter->first, iter->second,
          (iter->second->entries())));

  // If we have a query for which none of the corpora has a matching result,
  // then the iterator is in fact an end-iterator. We just don't know it yet,
  // unless we attempt to move the iterator.
  nextIterator();
}

RecursiveCorpusReaderPrivate::RecursiveIter::RecursiveIter(
  CorpusReaders const &readers,
  std::string const &query)
{
  for (CorpusReaders::const_iterator
      iter = readers.begin();
      iter != readers.end(); ++iter)
    d_iters.push_back(ReaderIter(iter->first, iter->second,
          (iter->second->query(XPATH, query))));

  // If we have a query for which none of the corpora has a matching result,
  // then the iterator is in fact an end-iterator. We just don't know it yet,
  // unless we attempt to move the iterator.
  nextIterator();
}

RecursiveCorpusReaderPrivate::RecursiveIter::~RecursiveIter() {}

IterImpl *RecursiveCorpusReaderPrivate::RecursiveIter::copy() const
{
  // No pointer members, pointer member of ReaderIter is not managed by
  // ReaderIter.
  return new RecursiveIter(*this);
}

bool RecursiveCorpusReaderPrivate::RecursiveIter::hasNext()
{
    return d_iters.size() != 0;
}

Entry RecursiveCorpusReaderPrivate::RecursiveIter::next(CorpusReader const &rdr)
{
    if (d_iters.size() == 0)
        throw std::runtime_error("Called next() on a finished iterator!");

    Entry e = d_iters.front().iter.next(rdr);
    e.name = d_iters.front().name + "/" + e.name;

    nextIterator();

    return e;
}

void RecursiveCorpusReaderPrivate::RecursiveIter::nextIterator()
{
  while (d_iters.size() != 0 &&
    !d_iters.front().iter.hasNext())
    d_iters.pop_front();
}

}

<commit_msg>Make RecursiveCorpusReader lazy.<commit_after>#include <list>
#include <map>
#include <stdexcept>
#include <string>
#include <utility>

#include <boost/tr1/memory.hpp>
#include <boost/tr1/unordered_map.hpp>

#include <boost/filesystem.hpp>

#include <AlpinoCorpus/CorpusReader.hh>
#include <AlpinoCorpus/CorpusReaderFactory.hh>
#include <AlpinoCorpus/Entry.hh>
#include <AlpinoCorpus/Error.hh>
#include <AlpinoCorpus/IterImpl.hh>
#include <AlpinoCorpus/RecursiveCorpusReader.hh>

#include "util/NameCompare.hh"

namespace bf = boost::filesystem;

namespace alpinocorpus {

struct ReaderIter
{
  ReaderIter(std::string newName, std::string newFilename) :
    name(newName), filename(newFilename) {}

  std::string name;
  std::string filename;
};

/*
bool operator==(ReaderIter const &left, ReaderIter const &right)
{
  return left.name == right.name && left.reader == right.reader &&
    left.iter == right.iter;
}
*/

class RecursiveCorpusReaderPrivate : public CorpusReader
{
  typedef std::map<std::string, std::string, NameCompare> Corpora;
  class RecursiveIter : public IterImpl
  {
  public:
    RecursiveIter(Corpora const &readers);
    RecursiveIter(Corpora const &readers,
      std::string const &query);
    ~RecursiveIter();
    IterImpl *copy() const;
    void nextIterator();
    bool hasNext();
    Entry next(CorpusReader const &rdr);
  private:
      void openTip();

      std::list<ReaderIter> d_iters;
      std::tr1::shared_ptr<CorpusReader> d_currentReader;
      std::tr1::shared_ptr<CorpusReader::EntryIterator> d_currentIter;
      std::string d_currentName;
      bool d_hasQuery;
      std::string d_query;
  };
public:
  RecursiveCorpusReaderPrivate(std::string const &directory);
  virtual ~RecursiveCorpusReaderPrivate();

  EntryIterator getEntries() const;
  std::string getName() const;
  size_t getSize() const;
  void push_back(std::string const &name, std::string const &filename);
  std::string readEntry(std::string const &) const;
  std::string readEntryMarkQueries(std::string const &entry, std::list<MarkerQuery> const &queries) const;
  EntryIterator runXPath(std::string const &query) const;
  bool validQuery(QueryDialect d, bool variables, std::string const &query) const;

private:
  std::string corpusFromPath(std::string const &path) const;
  std::string entryFromPath(std::string const &path) const;

  bf::path d_directory;
  std::list<std::string> d_corpora;
  Corpora d_corporaMap;
};

// Implementation of the public interface.
RecursiveCorpusReader::RecursiveCorpusReader(std::string const &directory) :
  d_private(new RecursiveCorpusReaderPrivate(directory))
{
}

RecursiveCorpusReader::~RecursiveCorpusReader()
{
  delete d_private;
}

CorpusReader::EntryIterator RecursiveCorpusReader::getEntries() const
{
  return d_private->getEntries();
}

std::string RecursiveCorpusReader::getName() const
{
  return d_private->getName();
}

size_t RecursiveCorpusReader::getSize() const
{
  return d_private->getSize();
}

bool RecursiveCorpusReader::validQuery(QueryDialect d, bool variables, std::string const &query) const
{
  return d_private->isValidQuery(d, variables, query);
}

std::string RecursiveCorpusReader::readEntry(std::string const &entry) const
{
  return d_private->readEntry(entry);
}

std::string RecursiveCorpusReader::readEntryMarkQueries(std::string const &entry,
    std::list<MarkerQuery> const &queries) const
{
  return d_private->readEntryMarkQueries(entry, queries);
}

CorpusReader::EntryIterator RecursiveCorpusReader::runXPath(std::string const &query) const
{
  return d_private->query(XPATH, query);
}

// Implementation of the private interface

RecursiveCorpusReaderPrivate::RecursiveCorpusReaderPrivate(std::string const &directory)
{
  if (directory[directory.size() - 1] == '/')
    d_directory = bf::path(directory).parent_path();
  else
    d_directory = bf::path(directory);

  if (!bf::exists(d_directory) ||
    !bf::is_directory(d_directory))
    throw OpenError(directory, "non-existent or not a directory");

  for (bf::recursive_directory_iterator iter(d_directory, bf::symlink_option::recurse);
       iter != bf::recursive_directory_iterator();
       ++iter)
  {
    if (iter->path().extension() != ".dact" &&
        iter->path().extension() != ".index")
      continue;

    bf::path namePath = iter->path();
    namePath.replace_extension("");
    std::string name = namePath.string();

    name.erase(0, d_directory.string().size() + 1);

    push_back(name, iter->path().string());
  }
}

RecursiveCorpusReaderPrivate::~RecursiveCorpusReaderPrivate()
{
}

CorpusReader::EntryIterator RecursiveCorpusReaderPrivate::getEntries() const
{
  return EntryIterator(new RecursiveIter(d_corporaMap));
}

std::string RecursiveCorpusReaderPrivate::getName() const
{
  return "<multi>";
}

size_t RecursiveCorpusReaderPrivate::getSize() const
{
  size_t size = 0;

  for (std::list<std::string>::const_iterator iter =
      d_corpora.begin(); iter != d_corpora.end(); ++iter)
  {
      CorpusReader *reader;
      try {
          reader = CorpusReaderFactory::open(*iter);
      } catch (OpenError const &)
      {
        // XXX - Print a warning?
        continue;
      }
      size += reader->size();
      delete reader;
  }

  return size;
}

void RecursiveCorpusReaderPrivate::push_back(std::string const &name,
    std::string const &filename)
{
  // Ignore empty corpus readers, simplifies assumptions.
  /*if (reader->size() == 0) {
    delete reader;
    return;
  }
  */

  d_corpora.push_back(filename);
  d_corporaMap[name] = filename; // XXX - exists check?
}

std::string RecursiveCorpusReaderPrivate::corpusFromPath(
    std::string const &path) const
{
  for (Corpora::const_iterator iter =
      d_corporaMap.begin(); iter != d_corporaMap.end(); ++iter)
    if (path.find(iter->first) == 0)
      return iter->second;

  throw std::runtime_error(std::string("Unknown corpus: " + path));
}

std::string RecursiveCorpusReaderPrivate::entryFromPath(
    std::string const &path) const
{
  for (Corpora::const_iterator iter =
      d_corporaMap.begin(); iter != d_corporaMap.end(); ++iter)
    if (path.find(iter->first) == 0)
      return path.substr(iter->first.size() + 1);

  throw std::runtime_error(std::string("Could not find entry: " + path));
}

std::string RecursiveCorpusReaderPrivate::readEntry(std::string const &path) const
{
  std::string fn = corpusFromPath(path);
  CorpusReader *reader = CorpusReaderFactory::open(fn);
  std::string data = reader->read(entryFromPath(path));
  delete reader;
  return data;
}

std::string RecursiveCorpusReaderPrivate::readEntryMarkQueries(
    std::string const &path, std::list<MarkerQuery> const &queries) const
{
  std::string fn = corpusFromPath(path);
  CorpusReader *reader = CorpusReaderFactory::open(fn);
  std::string data = reader->read(entryFromPath(path), queries);
  delete reader;
  return data;
}

CorpusReader::EntryIterator RecursiveCorpusReaderPrivate::runXPath(
    std::string const &query) const
{
  return EntryIterator(new RecursiveIter(d_corporaMap, query));
}

bool RecursiveCorpusReaderPrivate::validQuery(QueryDialect d, bool variables, std::string const &query) const
{
  if (d_corpora.size() == 0)
    return false;

  // Only check using the first reader, otherwise, this is too expensive.
  std::string fn = d_corpora.front();
  CorpusReader *reader = CorpusReaderFactory::open(fn);
  bool valid = reader->isValidQuery(d, variables, query);
  delete reader;

  return valid;
}

// Iteration over RecursiveCorpusReaders

RecursiveCorpusReaderPrivate::RecursiveIter::RecursiveIter(
  Corpora const &corpora) : d_hasQuery(false)
{
  for (Corpora::const_iterator
      iter = corpora.begin();
      iter != corpora.end(); ++iter)
    d_iters.push_back(ReaderIter(iter->first, iter->second));
}

RecursiveCorpusReaderPrivate::RecursiveIter::RecursiveIter(
  Corpora const &readers,
  std::string const &query) : d_hasQuery(true)
{
  for (Corpora::const_iterator
      iter = readers.begin();
      iter != readers.end(); ++iter)
    d_iters.push_back(ReaderIter(iter->first, iter->second));

    d_query = query;
}

RecursiveCorpusReaderPrivate::RecursiveIter::~RecursiveIter() {}

IterImpl *RecursiveCorpusReaderPrivate::RecursiveIter::copy() const
{
  // No pointer members, pointer member of ReaderIter is not managed by
  // ReaderIter.
  return new RecursiveIter(*this);
}

bool RecursiveCorpusReaderPrivate::RecursiveIter::hasNext()
{
    nextIterator();
    return d_currentIter && d_currentIter->hasNext();
}

Entry RecursiveCorpusReaderPrivate::RecursiveIter::next(CorpusReader const &rdr)
{
    Entry e = d_currentIter->next(rdr);
    e.name = d_currentName + "/" + e.name;

    return e;
}

void RecursiveCorpusReaderPrivate::RecursiveIter::nextIterator()
{
  while (d_iters.size() != 0 &&
    (!d_currentIter || !d_currentIter->hasNext()))
  {
    d_currentIter.reset();
    d_currentReader.reset();
    openTip();
    d_iters.pop_front();
  }
}

void RecursiveCorpusReaderPrivate::RecursiveIter::openTip()
{
    CorpusReader *reader;
    try {
        reader = CorpusReaderFactory::open(d_iters.front().filename);
    } catch (OpenError const &e)
    {
        // XXX - print warning?
        return;
    }

    try {
      if (d_hasQuery)
        d_currentIter.reset(new EntryIterator(reader->query(CorpusReader::XPATH, d_query)));
      else
        d_currentIter.reset(new EntryIterator(reader->entries()));
    } catch (std::runtime_error &e)
    {
      delete reader;
      return;
    }

    d_currentReader.reset(reader);
    d_currentName = d_iters.front().name;
}

}

<|endoftext|>


<commit_before>#include "util/funcs.h"
#include "util/bitmap.h"
#include "fog_atmosphere.h"
#include <math.h>

static int screenX(){
	return 320;
}

static int screenY(){
	return 240;
}

FogAtmosphere::FogAtmosphere():
Atmosphere(){
	fog = new Bitmap( 50, 50 );
	fog->fill( Bitmap::MaskColor );
	fog->circleFill( 25, 25, 20, Bitmap::makeColor( 0xbb, 0xbb, 0xcc ) );

	for ( int i = 0; i < screenX(); i += 20 ){
		for ( int q = 0; q < 3; q++ ){
			fogs.push_back( new Fog( i + Util::rnd( 9 ) - 4, screenY() - Util::rnd( 30 ) - 40, Util::rnd( 360 ) ) );
		}
	}
}

FogAtmosphere::~FogAtmosphere(){
	delete fog;
}

void FogAtmosphere::draw( Bitmap * work ){
	Bitmap::transBlender( 0, 0, 0, 64 );
	for ( vector< Fog * >::iterator it = fogs.begin(); it != fogs.end(); it++ ){
		Fog * f = *it;
		int y = (int)(f->y + sin( f->ang * 3.14159 / 180.0 ) * 4);
		fog->drawTrans( f->x, y, *work );
	}
	/*
	screenX();
	for ( int i = -10; i < screenX() + 10; i += 15 ){
		fog->drawTrans( i, screenY() - 50, *work );
	}
	*/
}

void FogAtmosphere::act(){
	for ( vector< Fog * >::iterator it = fogs.begin(); it != fogs.end(); it++ ){
		Fog * f = *it;
		f->ang += 1;
	}
}
<commit_msg>delete fog<commit_after>#include "util/funcs.h"
#include "util/bitmap.h"
#include "fog_atmosphere.h"
#include <math.h>

static int screenX(){
	return 320;
}

static int screenY(){
	return 240;
}

FogAtmosphere::FogAtmosphere():
Atmosphere(){
	fog = new Bitmap( 50, 50 );
	fog->fill( Bitmap::MaskColor );
	fog->circleFill( 25, 25, 20, Bitmap::makeColor( 0xbb, 0xbb, 0xcc ) );

	for ( int i = 0; i < screenX(); i += 20 ){
		for ( int q = 0; q < 3; q++ ){
			fogs.push_back( new Fog( i + Util::rnd( 9 ) - 4, screenY() - Util::rnd( 30 ) - 40, Util::rnd( 360 ) ) );
		}
	}
}

FogAtmosphere::~FogAtmosphere(){
	delete fog;
	for ( vector< Fog * >::iterator it = fogs.begin(); it != fogs.end(); it++ ){
		delete *it;
	}
}

void FogAtmosphere::draw( Bitmap * work ){
	Bitmap::transBlender( 0, 0, 0, 64 );
	for ( vector< Fog * >::iterator it = fogs.begin(); it != fogs.end(); it++ ){
		Fog * f = *it;
		int y = (int)(f->y + sin( f->ang * 3.14159 / 180.0 ) * 4);
		fog->drawTrans( f->x, y, *work );
	}
	/*
	screenX();
	for ( int i = -10; i < screenX() + 10; i += 15 ){
		fog->drawTrans( i, screenY() - 50, *work );
	}
	*/
}

void FogAtmosphere::act(){
	for ( vector< Fog * >::iterator it = fogs.begin(); it != fogs.end(); it++ ){
		Fog * f = *it;
		f->ang += 1;
	}
}
<|endoftext|>