<commit_before>/*
    This file is part of Akregator.

    Copyright (C) 2007 Frank Osterfeld <frank.osterfeld@kdemail.net>

    This program 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 2 of the License, or
    (at your option) any later version.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/
#include "articlemodel.h"

#include "article.h"
#include "articlematcher.h"
#include "akregatorconfig.h"
#include "treenode.h"
#include "feed.h"

#include <QString>

#include <KGlobal>
#include <KLocale>

#include <cassert>
#include <cmath>

using namespace Akregator;

class ArticleModel::Private {
private:
    ArticleModel* const q;
public:
    Private( TreeNode* node_, ArticleModel* qq );
    Akregator::TreeNode* node;
    QList<Akregator::Article> articles;
    void nodeDestroyed();
    void articlesAdded( TreeNode*, const QList<Article>& );
    void articlesRemoved( TreeNode*, const QList<Article>& );
    void articlesUpdated( TreeNode*, const QList<Article>& );

};

ArticleModel::Private::Private( TreeNode* node_, ArticleModel* qq )
 : q( qq ), node( node_ )
{
    Q_ASSERT( node );
}

Akregator::ArticleModel::ArticleModel(TreeNode* node, QObject* parent) : QAbstractTableModel( parent ), d( new Private( node, this ) )
{
    d->articles = node->articles();
    connect( node, SIGNAL(destroyed()), this, SLOT(nodeDestroyed()) );
    connect( node, SIGNAL(signalArticlesAdded(Akregator::TreeNode*, QList<Akregator::Article>)), SLOT( articlesAdded(Akregator::TreeNode*, QList<Akregator::Article>) ) );
    connect( node, SIGNAL(signalArticlesRemoved(Akregator::TreeNode*, QList<Akregator::Article>)), SLOT(articlesRemoved(Akregator::TreeNode*, QList<Akregator::Article>)) );
    connect( node, SIGNAL(signalArticlesUpdated(Akregator::TreeNode*, QList<Akregator::Article>)), SLOT(articlesUpdated(Akregator::TreeNode*, QList<Akregator::Article>)) );
}

Akregator::ArticleModel::~ArticleModel()
{
    delete d;
}

int Akregator::ArticleModel::columnCount( const QModelIndex& parent ) const
{
    return parent.isValid() ? 0 : ColumnCount;
}

int Akregator::ArticleModel::rowCount( const QModelIndex& parent ) const
{
    return parent.isValid() ? 0 : d->articles.count();
}

QVariant Akregator::ArticleModel::data( const QModelIndex& index, int role ) const
{
    if ( !index.isValid() || index.row() < 0 || index.row() >= d->articles.count() )
        return QVariant();
    const Akregator::Article article = d->articles[ index.row() ];

    if ( article.isNull() )
        return QVariant();

    switch ( role )
    {
        case Qt::DisplayRole:
        {
            switch ( index.column() )
            {
                case FeedTitleColumn:
                    return article.feed() ? article.feed()->title() : QVariant();
                case DateColumn:
                    return article.pubDate();
                case ItemTitleColumn:
                    return article.title();
                case AuthorColumn:
                    return article.author();
                case DescriptionColumn:
                case ContentColumn:
                    return article.description();
            }
        }
        case LinkRole:
        {
            return article.link();
        }
        case ItemIdRole:
        case GuidRole:
        {
            return article.guid();
        }
        case FeedIdRole:
        {
            return article.feed() ? article.feed()->xmlUrl() : QVariant();
        }
        case StatusRole:
        {
            return article.status();
        }
        case IsImportantRole:
        {
            return article.keep();
        }
    }

    return QVariant();
}

void Akregator::ArticleModel::Private::nodeDestroyed()
{
    node = 0;
    articles.clear();
    q->reset();
}

void ArticleModel::Private::articlesAdded( TreeNode* node, const QList<Article>& list )
{
    const int first = static_cast<int>( articles.count() );
    q->beginInsertRows( QModelIndex(), first, first + list.size() - 1 );
    articles << list;
    q->endInsertRows();
}

void ArticleModel::Private::articlesRemoved( TreeNode* node, const QList<Article>& list )
{
    //might want to avoid indexOf() in case of performance problems
    Q_FOREACH ( const Article& i, list )
    {
        const int row = articles.indexOf( i );
        assert( row != -1 );
        q->beginRemoveRows( QModelIndex(), row, row );
        q->endRemoveRows();
    }
}

void ArticleModel::Private::articlesUpdated( TreeNode* node, const QList<Article>& list )
{
    int rmin = articles.count() - 1;
    int rmax = 0;

    //might want to avoid indexOf() in case of performance problems
    Q_FOREACH ( const Article& i, list )
    {
        const int row = articles.indexOf( i );
        assert( row != -1 );
        rmin = std::min( row, rmin );
        rmax = std::max( row, rmax );
    }
    emit q->dataChanged( q->index( rmin, 0 ), q->index( rmax, ColumnCount-1 ) );
}

bool ArticleModel::rowMatches( int row, const boost::shared_ptr<const Akregator::Filters::AbstractMatcher>& matcher ) const
{
    assert( matcher );
    if ( row < 0 || row >= d->articles.count() )
        return false;
    return matcher->matches( d->articles[row] );
}

#include "articlemodel.moc"
<commit_msg>the append code only works correctly if list is non-empty<commit_after>/*
    This file is part of Akregator.

    Copyright (C) 2007 Frank Osterfeld <frank.osterfeld@kdemail.net>

    This program 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 2 of the License, or
    (at your option) any later version.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/
#include "articlemodel.h"

#include "article.h"
#include "articlematcher.h"
#include "akregatorconfig.h"
#include "treenode.h"
#include "feed.h"

#include <QString>

#include <KGlobal>
#include <KLocale>

#include <cassert>
#include <cmath>

using namespace Akregator;

class ArticleModel::Private {
private:
    ArticleModel* const q;
public:
    Private( TreeNode* node_, ArticleModel* qq );
    Akregator::TreeNode* node;
    QList<Akregator::Article> articles;
    void nodeDestroyed();
    void articlesAdded( TreeNode*, const QList<Article>& );
    void articlesRemoved( TreeNode*, const QList<Article>& );
    void articlesUpdated( TreeNode*, const QList<Article>& );

};

ArticleModel::Private::Private( TreeNode* node_, ArticleModel* qq )
 : q( qq ), node( node_ )
{
    Q_ASSERT( node );
}

Akregator::ArticleModel::ArticleModel(TreeNode* node, QObject* parent) : QAbstractTableModel( parent ), d( new Private( node, this ) )
{
    d->articles = node->articles();
    connect( node, SIGNAL(destroyed()), this, SLOT(nodeDestroyed()) );
    connect( node, SIGNAL(signalArticlesAdded(Akregator::TreeNode*, QList<Akregator::Article>)), SLOT( articlesAdded(Akregator::TreeNode*, QList<Akregator::Article>) ) );
    connect( node, SIGNAL(signalArticlesRemoved(Akregator::TreeNode*, QList<Akregator::Article>)), SLOT(articlesRemoved(Akregator::TreeNode*, QList<Akregator::Article>)) );
    connect( node, SIGNAL(signalArticlesUpdated(Akregator::TreeNode*, QList<Akregator::Article>)), SLOT(articlesUpdated(Akregator::TreeNode*, QList<Akregator::Article>)) );
}

Akregator::ArticleModel::~ArticleModel()
{
    delete d;
}

int Akregator::ArticleModel::columnCount( const QModelIndex& parent ) const
{
    return parent.isValid() ? 0 : ColumnCount;
}

int Akregator::ArticleModel::rowCount( const QModelIndex& parent ) const
{
    return parent.isValid() ? 0 : d->articles.count();
}

QVariant Akregator::ArticleModel::data( const QModelIndex& index, int role ) const
{
    if ( !index.isValid() || index.row() < 0 || index.row() >= d->articles.count() )
        return QVariant();
    const Akregator::Article article = d->articles[ index.row() ];

    if ( article.isNull() )
        return QVariant();

    switch ( role )
    {
        case Qt::DisplayRole:
        {
            switch ( index.column() )
            {
                case FeedTitleColumn:
                    return article.feed() ? article.feed()->title() : QVariant();
                case DateColumn:
                    return article.pubDate();
                case ItemTitleColumn:
                    return article.title();
                case AuthorColumn:
                    return article.author();
                case DescriptionColumn:
                case ContentColumn:
                    return article.description();
            }
        }
        case LinkRole:
        {
            return article.link();
        }
        case ItemIdRole:
        case GuidRole:
        {
            return article.guid();
        }
        case FeedIdRole:
        {
            return article.feed() ? article.feed()->xmlUrl() : QVariant();
        }
        case StatusRole:
        {
            return article.status();
        }
        case IsImportantRole:
        {
            return article.keep();
        }
    }

    return QVariant();
}

void Akregator::ArticleModel::Private::nodeDestroyed()
{
    node = 0;
    articles.clear();
    q->reset();
}

void ArticleModel::Private::articlesAdded( TreeNode* node, const QList<Article>& list )
{
    if ( list.isEmpty() ) //assert?
        return;
    const int first = static_cast<int>( articles.count() );
    q->beginInsertRows( QModelIndex(), first, first + list.size() - 1 );
    articles << list;
    q->endInsertRows();
}

void ArticleModel::Private::articlesRemoved( TreeNode* node, const QList<Article>& list )
{
    //might want to avoid indexOf() in case of performance problems
    Q_FOREACH ( const Article& i, list )
    {
        const int row = articles.indexOf( i );
        assert( row != -1 );
        q->beginRemoveRows( QModelIndex(), row, row );
        q->endRemoveRows();
    }
}

void ArticleModel::Private::articlesUpdated( TreeNode* node, const QList<Article>& list )
{
    int rmin = articles.count() - 1;
    int rmax = 0;

    //might want to avoid indexOf() in case of performance problems
    Q_FOREACH ( const Article& i, list )
    {
        const int row = articles.indexOf( i );
        assert( row != -1 );
        rmin = std::min( row, rmin );
        rmax = std::max( row, rmax );
    }
    emit q->dataChanged( q->index( rmin, 0 ), q->index( rmax, ColumnCount-1 ) );
}

bool ArticleModel::rowMatches( int row, const boost::shared_ptr<const Akregator::Filters::AbstractMatcher>& matcher ) const
{
    assert( matcher );
    if ( row < 0 || row >= d->articles.count() )
        return false;
    return matcher->matches( d->articles[row] );
}

#include "articlemodel.moc"
<|endoftext|>


<commit_before>/*
    This file is part of Akregator.

    Copyright (C) 2005 Frank Osterfeld <frank.osterfeld@kdemail.net>

    This program 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 2 of the License, or
    (at your option) any later version.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <qstringlist.h>

#include <kcombobox.h>
#include <klocale.h>

#include "configdialog.h"

#include "akregatorconfig.h"
#include "settings_advanced.h"
#include "settings_appearance.h"
#include "settings_archive.h"
#include "settings_browser.h"
#include "settings_general.h"
#include <qslider.h>
#include <qlabel.h>

namespace Akregator
{

ConfigDialog::ConfigDialog(QWidget* parent, const char* name, KConfigSkeleton* config, DialogType dialogType, int dialogButtons, ButtonCode defaultButton, bool modal) : KConfigDialog(parent, name, config, dialogType, dialogButtons, defaultButton, modal)
{
    addPage(new SettingsGeneral(this, "General"), i18n("General"), "package_settings");
    addPage(new SettingsArchive(this, "Archive"), i18n("Archive"), "package_settings");
    m_settingsAppearance = new SettingsAppearance(this, "Appearance");
    addPage(m_settingsAppearance, i18n("Appearance"), "fonts");
    addPage(new SettingsBrowser(this, "Browser"), i18n("Browser"), "package_network");
    m_settingsAdvanced = new SettingsAdvanced(this, "Advanced");
    addPage(m_settingsAdvanced, i18n("Advanced"), "package_network");
    m_settingsAdvanced->selectFactory(Settings::archiveBackend());
    m_config = config;
}

void ConfigDialog::updateSettings()
{
    Settings::setArchiveBackend(m_settingsAdvanced->selectedFactory());
    KConfigDialog::updateSettings();
}

void ConfigDialog::updateWidgets()
{
    m_settingsAdvanced->selectFactory(Settings::archiveBackend());
    m_settingsAppearance->slider_minimumFontSize->setDisabled(m_config->isImmutable("MinimumFontSize"));
    m_settingsAppearance->slider_mediumFontSize->setDisabled(m_config->isImmutable("MediumFontSize"));
    m_settingsAppearance->lbl_MinimumFontSize->setDisabled(m_config->isImmutable("MinimumFontSize"));
    m_settingsAppearance->lbl_MediumFontSize->setDisabled(m_config->isImmutable("MediumFontSize"));
    KConfigDialog::updateSettings();
}

ConfigDialog::~ConfigDialog() {}

} // namespace Akregator

#include "configdialog.moc"
<commit_msg>fix wrong call. doesn't fix any known bugs, but anyway<commit_after>/*
    This file is part of Akregator.

    Copyright (C) 2005 Frank Osterfeld <frank.osterfeld@kdemail.net>

    This program 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 2 of the License, or
    (at your option) any later version.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <qstringlist.h>

#include <kcombobox.h>
#include <klocale.h>

#include "configdialog.h"

#include "akregatorconfig.h"
#include "settings_advanced.h"
#include "settings_appearance.h"
#include "settings_archive.h"
#include "settings_browser.h"
#include "settings_general.h"
#include <qslider.h>
#include <qlabel.h>

namespace Akregator
{

ConfigDialog::ConfigDialog(QWidget* parent, const char* name, KConfigSkeleton* config, DialogType dialogType, int dialogButtons, ButtonCode defaultButton, bool modal) : KConfigDialog(parent, name, config, dialogType, dialogButtons, defaultButton, modal)
{
    addPage(new SettingsGeneral(this, "General"), i18n("General"), "package_settings");
    addPage(new SettingsArchive(this, "Archive"), i18n("Archive"), "package_settings");
    m_settingsAppearance = new SettingsAppearance(this, "Appearance");
    addPage(m_settingsAppearance, i18n("Appearance"), "fonts");
    addPage(new SettingsBrowser(this, "Browser"), i18n("Browser"), "package_network");
    m_settingsAdvanced = new SettingsAdvanced(this, "Advanced");
    addPage(m_settingsAdvanced, i18n("Advanced"), "package_network");
    m_settingsAdvanced->selectFactory(Settings::archiveBackend());
    m_config = config;
}

void ConfigDialog::updateSettings()
{
    Settings::setArchiveBackend(m_settingsAdvanced->selectedFactory());
    KConfigDialog::updateSettings();
}

void ConfigDialog::updateWidgets()
{
    m_settingsAdvanced->selectFactory(Settings::archiveBackend());
    m_settingsAppearance->slider_minimumFontSize->setDisabled(m_config->isImmutable("MinimumFontSize"));
    m_settingsAppearance->slider_mediumFontSize->setDisabled(m_config->isImmutable("MediumFontSize"));
    m_settingsAppearance->lbl_MinimumFontSize->setDisabled(m_config->isImmutable("MinimumFontSize"));
    m_settingsAppearance->lbl_MediumFontSize->setDisabled(m_config->isImmutable("MediumFontSize"));
    KConfigDialog::updateWidgets();
}

ConfigDialog::~ConfigDialog() {}

} // namespace Akregator

#include "configdialog.moc"
<|endoftext|>


<commit_before>
#ifndef __gl_h_
#include <glad/glad.h>
#endif

#include <iostream>
#include <cmath>
#include <memory>

// Include GLM
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/matrix_inverse.hpp"
#include "glm/gtx/string_cast.hpp"
#include <glm/gtx/transform.hpp>

#include "Camera.h"
#include "GLSpins.h"
#include "ISpinRenderer.h"
#include "ArrowSpinRenderer.h"
#include "SurfaceSpinRenderer.h"
#include "SphereSpinRenderer.h"
#include "BoundingBoxRenderer.h"
#include "CombinedSpinRenderer.h"
#include "CoordinateSystemRenderer.h"
#include "utilities.h"

#ifndef M_PI
	#define M_PI 3.14159265358979323846
#endif // !M_PI

GLSpins::GLSpins(std::vector<int> n_cells, bool threeD) {
  if (!gladLoadGL()) {
    std::cerr << "Failed to initialize glad" << std::endl;
  }

  // Reset any error potentially caused by glad
  glGetError();

  CHECK_GL_ERROR;
  setCameraToDefault();

  glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LESS);

  Options<GLSpins> options;
  options.set<ISpinRenderer::Option::COLORMAP_IMPLEMENTATION>(getColormapImplementation("hsv"));

  if (threeD)
  {
    //ToDo
  }
  else
  {
    options.set<SurfaceSpinRendererOptions::SURFACE_INDICES>(SurfaceSpinRenderer::generateCartesianSurfaceIndices(n_cells[0], n_cells[1]));
  }
  updateOptions(options);

  updateRenderers();
  CHECK_GL_ERROR;
}

GLSpins::~GLSpins() {
}

void GLSpins::updateSpins(const std::vector<glm::vec3>& positions, const std::vector<glm::vec3>& directions) {
  CHECK_GL_ERROR;
	for (auto it : _renderers) {
    auto renderer = it.first;
    renderer->updateSpins(positions, directions);
  }
  CHECK_GL_ERROR;
}

void GLSpins::updateSystemGeometry(glm::vec3 bounds_min, glm::vec3 center, glm::vec3 bounds_max) {
  Options<GLSpins> options;
  options.set<GLSpins::Option::BOUNDING_BOX_MIN>(bounds_min);
  options.set<GLSpins::Option::BOUNDING_BOX_MAX>(bounds_max);
  options.set<GLSpins::Option::SYSTEM_CENTER>(center);
  updateOptions(options);
}

void GLSpins::draw() {
  CHECK_GL_ERROR;
  // Clear the screen and the depth buffer
  auto background_color = _options.get<ISpinRenderer::Option::BACKGROUND_COLOR>();
  glClearColor(background_color.x, background_color.y, background_color.z, 1.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  Options<GLSpins> options;
  options.set<ISpinRenderer::Option::CAMERA_POSITION>(_camera.cameraPosition());
  options.set<ISpinRenderer::Option::CENTER_POSITION>(_camera.centerPosition());
  options.set<ISpinRenderer::Option::UP_VECTOR>(_camera.upVector());
  auto bounds_min = _options.get<GLSpins::Option::BOUNDING_BOX_MIN>();
  auto bounds_max = _options.get<GLSpins::Option::BOUNDING_BOX_MAX>();
  auto center = _options.get<GLSpins::Option::SYSTEM_CENTER>();
  options.set<CoordinateSystemRendererOptions::ORIGIN>(center);
  options.set<CoordinateSystemRendererOptions::AXIS_LENGTH>({
    fmax(fabs(bounds_max[0]-center[0]), 1.0),
    fmax(fabs(bounds_max[1]-center[1]), 1.0),
    fmax(fabs(bounds_max[2]-center[2]), 1.0)
  });
  updateOptions(options);

  glClear(GL_COLOR_BUFFER_BIT);
  for (auto it : _renderers) {
    auto renderer = it.first;
    auto viewport = it.second;
    glViewport((GLint)(viewport[0] * _width), (GLint)(viewport[1] * _height), (GLsizei)(viewport[2] * _width), (GLsizei)(viewport[3] * _height));
    glClear(GL_DEPTH_BUFFER_BIT);
    renderer->draw(viewport[2]/viewport[3] * _camera.aspectRatio());
  }
  _fps_counter.tick();
  CHECK_GL_ERROR;
}

float GLSpins::getFramerate() const {
  return _fps_counter.getFramerate();
}

void GLSpins::mouseMove(const glm::vec2& position_before, const glm::vec2& position_after, GLSpins::CameraMovementModes mode) {
  if (position_before == position_after) {
    return;
  }
  auto delta = position_after-position_before;
  auto length = glm::length(delta);
  auto forward = glm::normalize(_camera.centerPosition() - _camera.cameraPosition());
  auto camera_distance = glm::length(_camera.centerPosition() - _camera.cameraPosition());
  auto up = glm::normalize(_camera.upVector());
  auto right = glm::normalize(glm::cross(forward, up));
  up = glm::normalize(glm::cross(right, forward));
  delta = glm::normalize(delta);
  switch (mode) {
    case GLSpins::CameraMovementModes::ROTATE: {
      auto axis = glm::normalize(delta.x * up + delta.y * right);
      float angle = -length * 0.1f / 180 * 3.14f;
      auto rotation_matrix = glm::rotate(angle, axis);
      up = glm::mat3(rotation_matrix) * up;
      forward = glm::mat3(rotation_matrix) * forward;
      _camera.lookAt(_camera.centerPosition() - forward * camera_distance,
                     _camera.centerPosition(),
                     up);
    }
      break;
    case GLSpins::CameraMovementModes::TRANSLATE: {
      float factor = 0.001f * camera_distance * length;
      auto translation = factor * (delta.y * up - delta.x * right);
      _camera.lookAt(_camera.cameraPosition() + translation,
                     _camera.centerPosition() + translation,
                     up);
    }
      break;
    default:
      break;
  }
}

void GLSpins::mouseScroll(const float& wheel_delta) {
  auto forward = _camera.centerPosition() - _camera.cameraPosition();
  float camera_distance = glm::length(forward);
  float new_camera_distance = (float)(1+0.02*wheel_delta)*camera_distance;
  if (new_camera_distance < 2) {
    new_camera_distance = 2;
  }

  auto camera_position = _camera.centerPosition() - new_camera_distance/camera_distance * forward;
  _camera.lookAt(camera_position,
                 _camera.centerPosition(),
                 _camera.upVector());
}

void GLSpins::setFramebufferSize(float width, float height) {
  _width = width;
  _height = height;
  _camera.setAspectRatio(width / height);
}

void GLSpins::setCameraToDefault() {
  auto center = _options.get<GLSpins::Option::SYSTEM_CENTER>();
  _camera.lookAt(glm::vec3(center.x, center.y, center.z+30.0),
                 center,
                 glm::vec3(0.0f, 1.0f, 0.0f));
}

void GLSpins::setCameraToX() {
  auto center = _options.get<GLSpins::Option::SYSTEM_CENTER>();
  float camera_distance = glm::length(_camera.centerPosition() - _camera.cameraPosition());
  _camera.lookAt(glm::vec3(center.x+camera_distance, center.y, center.z),
                 center,
                 glm::vec3(0.0, 0.0, 1.0));
}

void GLSpins::setCameraToY() {
  auto center = _options.get<GLSpins::Option::SYSTEM_CENTER>();
  float camera_distance = glm::length(_camera.centerPosition() - _camera.cameraPosition());
  _camera.lookAt(glm::vec3(center.x, center.y+camera_distance, center.z),
                 center,
                 glm::vec3(1.0, 0.0, 0.0));
}

void GLSpins::setCameraToZ() {
  auto center = _options.get<GLSpins::Option::SYSTEM_CENTER>();
  float camera_distance = glm::length(_camera.centerPosition() - _camera.cameraPosition());
  _camera.lookAt(glm::vec3(center.x, center.y, center.z+camera_distance),
                 center,
                 glm::vec3(0.0, 1.0, 0.0));
}

static std::array<float, 4> locationToViewport(GLSpins::WidgetLocation location) {
  switch(location) {
    case GLSpins::WidgetLocation::BOTTOM_LEFT:
      return {0.0f, 0.0f, 0.2f, 0.2f};
    case GLSpins::WidgetLocation::BOTTOM_RIGHT:
      return {0.8f, 0.0f, 0.2f, 0.2f};
    case GLSpins::WidgetLocation::TOP_LEFT:
      return {0.0f, 0.8f, 0.2f, 0.2f};
    case GLSpins::WidgetLocation::TOP_RIGHT:
      return {0.8f, 0.8f, 0.2f, 0.2f};
  }
  return {0, 0, 1, 1};
}

void GLSpins::updateRenderers() {
  CHECK_GL_ERROR;
  bool show_bounding_box = options().get<GLSpins::Option::SHOW_BOUNDING_BOX>();
  bool show_coordinate_system = options().get<GLSpins::Option::SHOW_COORDINATE_SYSTEM>();
  bool show_miniview = options().get<GLSpins::Option::SHOW_MINIVIEW>();
  GLSpins::VisualizationMode mode = options().get<GLSpins::Option::VISUALIZATION_MODE>();
  GLSpins::WidgetLocation coordinate_system_location = options().get<GLSpins::Option::COORDINATE_SYSTEM_LOCATION>();
  GLSpins::WidgetLocation miniview_location = options().get<GLSpins::Option::MINIVIEW_LOCATION>();
  _renderers.clear();
  std::shared_ptr<ISpinRenderer> main_renderer;
  switch (mode) {
    case VisualizationMode::ARROWS:
      main_renderer = std::make_shared<ArrowSpinRenderer>();
      break;
    case VisualizationMode::SURFACE:
      main_renderer = std::make_shared<SurfaceSpinRenderer>();
      break;
    case VisualizationMode::SPHERE:
      main_renderer = std::make_shared<SphereSpinRenderer>();
      break;
  }
  if (show_bounding_box && mode != VisualizationMode::SPHERE) {
    std::vector<std::shared_ptr<ISpinRenderer>> r = {
      main_renderer,
      std::make_shared<BoundingBoxRenderer>()
    };
    main_renderer = std::make_shared<CombinedSpinRenderer>(r);
  }
  _renderers.push_back({main_renderer, {0, 0, 1, 1}});

  if (show_coordinate_system) {
    std::shared_ptr<ISpinRenderer> renderer = std::make_shared<CoordinateSystemRenderer>();
    _renderers.push_back({renderer, locationToViewport(coordinate_system_location)});
  }
  if (show_miniview) {
    std::shared_ptr<ISpinRenderer> renderer;
    if (mode == VisualizationMode::SPHERE) {
      renderer = std::make_shared<SurfaceSpinRenderer>();
      if (show_bounding_box) {
        std::vector<std::shared_ptr<ISpinRenderer>> r = {
          renderer,
          std::make_shared<BoundingBoxRenderer>()
        };
        renderer = std::make_shared<CombinedSpinRenderer>(r);
      }
    } else {
      renderer = std::make_shared<SphereSpinRenderer>();
    }
    _renderers.push_back({renderer, locationToViewport(miniview_location)});
  }

  for (auto it : _renderers) {
    auto renderer = it.first;
    renderer->updateOptions(options());
  }
  CHECK_GL_ERROR;
}

void GLSpins::updateOptions(const Options<GLSpins>& options) {
  CHECK_GL_ERROR;
  auto changedOptions = _options.update(options);
  if (changedOptions.size() == 0) {
    return;
  }
  optionsHaveChanged(changedOptions);
  for (auto it : _renderers) {
    auto renderer = it.first;
    renderer->updateOptions(options);
  }
  CHECK_GL_ERROR;
}

void GLSpins::options(const Options<GLSpins>& options) {
  _options = options;
  updateOptions(Options<GLSpins>());
}

const Options<GLSpins>& GLSpins::options() const {
  return _options;
}

void GLSpins::optionsHaveChanged(const std::vector<int>& changedOptions) {
  CHECK_GL_ERROR;
  bool renderersChanged = false;
  for (int option_id : changedOptions) {
    switch (option_id) {
      case GLSpins::Option::SHOW_MINIVIEW:
      case GLSpins::Option::SHOW_COORDINATE_SYSTEM:
      case GLSpins::Option::SHOW_BOUNDING_BOX:
      case GLSpins::Option::MINIVIEW_LOCATION:
      case GLSpins::Option::COORDINATE_SYSTEM_LOCATION:
      case GLSpins::Option::VISUALIZATION_MODE:
        renderersChanged = true;
        break;
    }
  }
  if (renderersChanged) {
    updateRenderers();
  }
  CHECK_GL_ERROR;
}
<commit_msg>Modified the camera alignment methods<commit_after>
#ifndef __gl_h_
#include <glad/glad.h>
#endif

#include <iostream>
#include <cmath>
#include <memory>

// Include GLM
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/matrix_inverse.hpp"
#include "glm/gtx/string_cast.hpp"
#include <glm/gtx/transform.hpp>

#include "Camera.h"
#include "GLSpins.h"
#include "ISpinRenderer.h"
#include "ArrowSpinRenderer.h"
#include "SurfaceSpinRenderer.h"
#include "SphereSpinRenderer.h"
#include "BoundingBoxRenderer.h"
#include "CombinedSpinRenderer.h"
#include "CoordinateSystemRenderer.h"
#include "utilities.h"

#ifndef M_PI
	#define M_PI 3.14159265358979323846
#endif // !M_PI

GLSpins::GLSpins(std::vector<int> n_cells, bool threeD) {
  if (!gladLoadGL()) {
    std::cerr << "Failed to initialize glad" << std::endl;
  }

  // Reset any error potentially caused by glad
  glGetError();

  CHECK_GL_ERROR;
  setCameraToDefault();

  glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LESS);

  Options<GLSpins> options;
  options.set<ISpinRenderer::Option::COLORMAP_IMPLEMENTATION>(getColormapImplementation("hsv"));

  if (threeD)
  {
    //ToDo
  }
  else
  {
    options.set<SurfaceSpinRendererOptions::SURFACE_INDICES>(SurfaceSpinRenderer::generateCartesianSurfaceIndices(n_cells[0], n_cells[1]));
  }
  updateOptions(options);

  updateRenderers();
  CHECK_GL_ERROR;
}

GLSpins::~GLSpins() {
}

void GLSpins::updateSpins(const std::vector<glm::vec3>& positions, const std::vector<glm::vec3>& directions) {
  CHECK_GL_ERROR;
	for (auto it : _renderers) {
    auto renderer = it.first;
    renderer->updateSpins(positions, directions);
  }
  CHECK_GL_ERROR;
}

void GLSpins::updateSystemGeometry(glm::vec3 bounds_min, glm::vec3 center, glm::vec3 bounds_max) {
  Options<GLSpins> options;
  options.set<GLSpins::Option::BOUNDING_BOX_MIN>(bounds_min);
  options.set<GLSpins::Option::BOUNDING_BOX_MAX>(bounds_max);
  options.set<GLSpins::Option::SYSTEM_CENTER>(center);
  updateOptions(options);
}

void GLSpins::draw() {
  CHECK_GL_ERROR;
  // Clear the screen and the depth buffer
  auto background_color = _options.get<ISpinRenderer::Option::BACKGROUND_COLOR>();
  glClearColor(background_color.x, background_color.y, background_color.z, 1.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  Options<GLSpins> options;
  options.set<ISpinRenderer::Option::CAMERA_POSITION>(_camera.cameraPosition());
  options.set<ISpinRenderer::Option::CENTER_POSITION>(_camera.centerPosition());
  options.set<ISpinRenderer::Option::UP_VECTOR>(_camera.upVector());
  auto bounds_min = _options.get<GLSpins::Option::BOUNDING_BOX_MIN>();
  auto bounds_max = _options.get<GLSpins::Option::BOUNDING_BOX_MAX>();
  auto center = _options.get<GLSpins::Option::SYSTEM_CENTER>();
  options.set<CoordinateSystemRendererOptions::ORIGIN>(center);
  options.set<CoordinateSystemRendererOptions::AXIS_LENGTH>({
    fmax(fabs(bounds_max[0]-center[0]), 1.0),
    fmax(fabs(bounds_max[1]-center[1]), 1.0),
    fmax(fabs(bounds_max[2]-center[2]), 1.0)
  });
  updateOptions(options);

  glClear(GL_COLOR_BUFFER_BIT);
  for (auto it : _renderers) {
    auto renderer = it.first;
    auto viewport = it.second;
    glViewport((GLint)(viewport[0] * _width), (GLint)(viewport[1] * _height), (GLsizei)(viewport[2] * _width), (GLsizei)(viewport[3] * _height));
    glClear(GL_DEPTH_BUFFER_BIT);
    renderer->draw(viewport[2]/viewport[3] * _camera.aspectRatio());
  }
  _fps_counter.tick();
  CHECK_GL_ERROR;
}

float GLSpins::getFramerate() const {
  return _fps_counter.getFramerate();
}

void GLSpins::mouseMove(const glm::vec2& position_before, const glm::vec2& position_after, GLSpins::CameraMovementModes mode) {
  if (position_before == position_after) {
    return;
  }
  auto delta = position_after-position_before;
  auto length = glm::length(delta);
  auto forward = glm::normalize(_camera.centerPosition() - _camera.cameraPosition());
  auto camera_distance = glm::length(_camera.centerPosition() - _camera.cameraPosition());
  auto up = glm::normalize(_camera.upVector());
  auto right = glm::normalize(glm::cross(forward, up));
  up = glm::normalize(glm::cross(right, forward));
  delta = glm::normalize(delta);
  switch (mode) {
    case GLSpins::CameraMovementModes::ROTATE: {
      auto axis = glm::normalize(delta.x * up + delta.y * right);
      float angle = -length * 0.1f / 180 * 3.14f;
      auto rotation_matrix = glm::rotate(angle, axis);
      up = glm::mat3(rotation_matrix) * up;
      forward = glm::mat3(rotation_matrix) * forward;
      _camera.lookAt(_camera.centerPosition() - forward * camera_distance,
                     _camera.centerPosition(),
                     up);
    }
      break;
    case GLSpins::CameraMovementModes::TRANSLATE: {
      float factor = 0.001f * camera_distance * length;
      auto translation = factor * (delta.y * up - delta.x * right);
      _camera.lookAt(_camera.cameraPosition() + translation,
                     _camera.centerPosition() + translation,
                     up);
    }
      break;
    default:
      break;
  }
}

void GLSpins::mouseScroll(const float& wheel_delta) {
  auto forward = _camera.centerPosition() - _camera.cameraPosition();
  float camera_distance = glm::length(forward);
  float new_camera_distance = (float)(1+0.02*wheel_delta)*camera_distance;
  if (new_camera_distance < 2) {
    new_camera_distance = 2;
  }

  auto camera_position = _camera.centerPosition() - new_camera_distance/camera_distance * forward;
  _camera.lookAt(camera_position,
                 _camera.centerPosition(),
                 _camera.upVector());
}

void GLSpins::setFramebufferSize(float width, float height) {
  _width = width;
  _height = height;
  _camera.setAspectRatio(width / height);
}

void GLSpins::setCameraToDefault() {
  auto center = _options.get<GLSpins::Option::SYSTEM_CENTER>();
  _camera.lookAt(glm::vec3(center.x, center.y, center.z+30.0),
                 center,
                 glm::vec3(0.0f, 1.0f, 0.0f));
}

void GLSpins::setCameraToX() {
  auto center = _options.get<GLSpins::Option::SYSTEM_CENTER>();
  float camera_distance = glm::length(_camera.centerPosition() - _camera.cameraPosition());
  _camera.lookAt(glm::vec3(center.x+camera_distance, center.y, center.z),
                 center,
                 glm::vec3(0.0, 0.0, 1.0));
}

void GLSpins::setCameraToY() {
  auto center = _options.get<GLSpins::Option::SYSTEM_CENTER>();
  float camera_distance = glm::length(_camera.centerPosition() - _camera.cameraPosition());
  _camera.lookAt(glm::vec3(center.x, center.y-camera_distance, center.z),
                 center,
                 glm::vec3(0.0, 0.0, 1.0));
}

void GLSpins::setCameraToZ() {
  auto center = _options.get<GLSpins::Option::SYSTEM_CENTER>();
  float camera_distance = glm::length(_camera.centerPosition() - _camera.cameraPosition());
  _camera.lookAt(glm::vec3(center.x, center.y, center.z+camera_distance),
                 center,
                 glm::vec3(0.0, 1.0, 0.0));
}

static std::array<float, 4> locationToViewport(GLSpins::WidgetLocation location) {
  switch(location) {
    case GLSpins::WidgetLocation::BOTTOM_LEFT:
      return {0.0f, 0.0f, 0.2f, 0.2f};
    case GLSpins::WidgetLocation::BOTTOM_RIGHT:
      return {0.8f, 0.0f, 0.2f, 0.2f};
    case GLSpins::WidgetLocation::TOP_LEFT:
      return {0.0f, 0.8f, 0.2f, 0.2f};
    case GLSpins::WidgetLocation::TOP_RIGHT:
      return {0.8f, 0.8f, 0.2f, 0.2f};
  }
  return {0, 0, 1, 1};
}

void GLSpins::updateRenderers() {
  CHECK_GL_ERROR;
  bool show_bounding_box = options().get<GLSpins::Option::SHOW_BOUNDING_BOX>();
  bool show_coordinate_system = options().get<GLSpins::Option::SHOW_COORDINATE_SYSTEM>();
  bool show_miniview = options().get<GLSpins::Option::SHOW_MINIVIEW>();
  GLSpins::VisualizationMode mode = options().get<GLSpins::Option::VISUALIZATION_MODE>();
  GLSpins::WidgetLocation coordinate_system_location = options().get<GLSpins::Option::COORDINATE_SYSTEM_LOCATION>();
  GLSpins::WidgetLocation miniview_location = options().get<GLSpins::Option::MINIVIEW_LOCATION>();
  _renderers.clear();
  std::shared_ptr<ISpinRenderer> main_renderer;
  switch (mode) {
    case VisualizationMode::ARROWS:
      main_renderer = std::make_shared<ArrowSpinRenderer>();
      break;
    case VisualizationMode::SURFACE:
      main_renderer = std::make_shared<SurfaceSpinRenderer>();
      break;
    case VisualizationMode::SPHERE:
      main_renderer = std::make_shared<SphereSpinRenderer>();
      break;
  }
  if (show_bounding_box && mode != VisualizationMode::SPHERE) {
    std::vector<std::shared_ptr<ISpinRenderer>> r = {
      main_renderer,
      std::make_shared<BoundingBoxRenderer>()
    };
    main_renderer = std::make_shared<CombinedSpinRenderer>(r);
  }
  _renderers.push_back({main_renderer, {0, 0, 1, 1}});

  if (show_coordinate_system) {
    std::shared_ptr<ISpinRenderer> renderer = std::make_shared<CoordinateSystemRenderer>();
    _renderers.push_back({renderer, locationToViewport(coordinate_system_location)});
  }
  if (show_miniview) {
    std::shared_ptr<ISpinRenderer> renderer;
    if (mode == VisualizationMode::SPHERE) {
      renderer = std::make_shared<SurfaceSpinRenderer>();
      if (show_bounding_box) {
        std::vector<std::shared_ptr<ISpinRenderer>> r = {
          renderer,
          std::make_shared<BoundingBoxRenderer>()
        };
        renderer = std::make_shared<CombinedSpinRenderer>(r);
      }
    } else {
      renderer = std::make_shared<SphereSpinRenderer>();
    }
    _renderers.push_back({renderer, locationToViewport(miniview_location)});
  }

  for (auto it : _renderers) {
    auto renderer = it.first;
    renderer->updateOptions(options());
  }
  CHECK_GL_ERROR;
}

void GLSpins::updateOptions(const Options<GLSpins>& options) {
  CHECK_GL_ERROR;
  auto changedOptions = _options.update(options);
  if (changedOptions.size() == 0) {
    return;
  }
  optionsHaveChanged(changedOptions);
  for (auto it : _renderers) {
    auto renderer = it.first;
    renderer->updateOptions(options);
  }
  CHECK_GL_ERROR;
}

void GLSpins::options(const Options<GLSpins>& options) {
  _options = options;
  updateOptions(Options<GLSpins>());
}

const Options<GLSpins>& GLSpins::options() const {
  return _options;
}

void GLSpins::optionsHaveChanged(const std::vector<int>& changedOptions) {
  CHECK_GL_ERROR;
  bool renderersChanged = false;
  for (int option_id : changedOptions) {
    switch (option_id) {
      case GLSpins::Option::SHOW_MINIVIEW:
      case GLSpins::Option::SHOW_COORDINATE_SYSTEM:
      case GLSpins::Option::SHOW_BOUNDING_BOX:
      case GLSpins::Option::MINIVIEW_LOCATION:
      case GLSpins::Option::COORDINATE_SYSTEM_LOCATION:
      case GLSpins::Option::VISUALIZATION_MODE:
        renderersChanged = true;
        break;
    }
  }
  if (renderersChanged) {
    updateRenderers();
  }
  CHECK_GL_ERROR;
}
<|endoftext|>


<commit_before>// Copyright 2016 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cmath>

#include <Correlator.hpp>

namespace TuneBench {

CorrelatorConf::CorrelatorConf() : isa::OpenCL::KernelConf(), width(1), height(1) {}

std::string CorrelatorConf::print() const {
  return std::to_string(width) + " " + std::to_string(height) + " " + isa::OpenCL::KernelConf::print();
}

std::string * getCorrelatorOpenCL(const CorrelatorConf & conf, const std::string & dataName, const unsigned int padding, const unsigned int nrChannels, const unsigned int nrStations, const unsigned int nrSamples, const unsigned int nrPolarizations) {
  std::string * code = new std::string();

  // Begin kernel's template
  *code = "__kernel void correlator(__global const " + dataName + "4 * const restrict input, __global " + dataName + "8 * const restrict output, __global const unsigned int * const restrict cellMapX, __global const unsigned int * const restrict cellMapY) {\n"
    "const unsigned int cell = (get_group_id(0) * " + std::to_string(conf.getNrThreadsD0() * conf.getNrItemsD0()) + ") + get_local_id(0);\n"
    "const unsigned int channel = (get_group_id(2) * " + std::to_string(conf.getNrThreadsD2()) + ") + get_local_id(2);\n"
    "const unsigned int baseStationX = cellMapX[cell];\n"
    "const unsigned int baseStationY = cellMapY[cell];\n"
    "<%DEFINE_STATION%>"
    "<%DEFINE_CELL%>"
    "\n"
    "// Compute\n"
    "for ( unsigned int sample = 0; sample < " + std::to_string(nrSamples) + "; sample += " + std::to_string(conf.getNrItemsD1()) + " ) {\n"
    "<%LOAD_AND_COMPUTE%>"
    "}\n"
    "<%STORE%>"
    "}\n";
  std::string defineStationX_sTemplate = dataName + "4 sampleStation<%STATION%>XP0 = (" + dataName + "4)(0.0);\n";
  std::string defineStationY_sTemplate = dataName + "4 sampleStation<%STATION%>YP1 = (" + dataName + "4)(0.0);\n";
  std::string defineCell_sTemplate = dataName + "8 accumulator<%CELL%> = (" + dataName + "8)(0.0);\n";
  std::string loadX_sTemplate = "sampleStation<%STATION%>XP0 = input[(channel * " + std::to_string(nrStations * isa::utils::pad(nrSamples, padding / 4)) + ") + ((baseStationX + <%WIDTH%>) * " + std::to_string(isa::utils::pad(nrSamples, padding / 4)) + ") + (sample + <%OFFSETD1%>)];\n"
    "sampleStation<%STATION%>XP1 = input[(channel * " + std::to_string(nrStations * isa::utils::pad(nrSamples, padding / 4)) + ") + ((baseStationX + <%WIDTH%>) * " + std::to_string(isa::utils::pad(nrSamples, padding / 4)) + ") + (sample + <%OFFSETD1%>)];\n";
  std::string loadY_sTemplate = "sampleStation<%STATION%>YP0 = input[(channel * " + std::to_string(nrStations * isa::utils::pad(nrSamples, padding / 4)) + ") + ((baseStationY + <%HEIGHT%>) * " + std::to_string(isa::utils::pad(nrSamples, padding / 4)) + ") + (sample + <%OFFSETD1%>)];\n"
    "sampleStation<%STATION%>YP1 = input[(channel * " + std::to_string(nrStations * isa::utils::pad(nrSamples, padding / 4)) + ") + ((baseStationY + <%HEIGHT%>) * " + std::to_string(isa::utils::pad(nrSamples, padding / 4)) + ") + (sample + <%OFFSETD1%>)];\n";
  std::vector< std::string > compute_sTemplate(8);
  compute_sTemplate[0] = "accumulator<%CELL%>.s0 += (sampleStation<%STATION%>P0.x * sampleStation<%STATION%>P1.x) - (sampleStation<%STATION%>P0.y * (-sampleStation<%STATION%>P1.y));\n";
  compute_sTemplate[1] = "accumulator<%CELL%>.s1 += (sampleStation<%STATION%>P0.x * (-sampleStation<%STATION%>P1.y)) + (sampleStation<%STATION%>P0.y * sampleStation<%STATION%>P1.x);\n";
  compute_sTemplate[2] = "accumulator<%CELL%>.s2 += (sampleStation<%STATION%>P0.x * sampleStation<%STATION%>P1.z) - (sampleStation<%STATION%>P0.y * (-sampleStation<%STATION%>P1.w));\n";
  compute_sTemplate[3] = "accumulator<%CELL%>.s3 += (sampleStation<%STATION%>P0.x * (-sampleStation<%STATION%>P1.w)) + (sampleStation<%STATION%>P0.y * sampleStation<%STATION%>P1.z);\n";
  compute_sTemplate[4] = "accumulator<%CELL%>.s4 += (sampleStation<%STATION%>P0.z * sampleStation<%STATION%>P1.x) - (sampleStation<%STATION%>P0.w * (-sampleStation<%STATION%>P1.y));\n";
  compute_sTemplate[5] = "accumulator<%CELL%>.s5 += (sampleStation<%STATION%>P0.z * (-sampleStation<%STATION%>P1.y)) + (sampleStation<%STATION%>P0.w * sampleStation<%STATION%>P1.x);\n";
  compute_sTemplate[6] = "accumulator<%CELL%>.s6 += (sampleStation<%STATION%>P0.z * sampleStation<%STATION%>P1.z) - (sampleStation<%STATION%>P0.w * (-sampleStation<%STATION%>P1.w));\n";
  compute_sTemplate[7] = "accumulator<%CELL%>.s7 += (sampleStation<%STATION%>P0.z * (-sampleStation<%STATION%>P1.w)) + (sampleStation<%STATION%>P0.w * sampleStation<%STATION%>P1.z);\n";
  std::string store_sTemplate = "output[(((((stationY + <%HEIGHT%>) * (stationY + <%HEIGHT%> + 1)) / 2) + stationX + <%WIDTH%>) * " + std::to_string(nrChannels) + ") + channel] = accumulator<%CELL%>;\n";
  // End kernel's template

  std::string * defineStation_s = new std::string();
  std::string * defineCell_s = new std::string();
  std::string * loadCompute_s = new std::string();
  std::string * store_s = new std::string();
  std::string * temp = 0;
  std::string empty_s = "";

  for ( unsigned int width = 0; width < conf.getCellWidth(); width++ ) {
    std::string width_s = std::to_string(width);

    temp = isa::utils::replace(&defineStationX_sTemplate, "<%STATION%>", width_s);
    defineStation_s->append(*temp);
    delete temp;
  }
  for ( unsigned int height = 0; height < conf.getCellHeight(); height++ ) {
    std::string height_s = std::to_string(height);

    temp = isa::utils::replace(&defineStationY_sTemplate, "<%STATION%>", height_s);
    defineStation_s->append(*temp);
    delete temp;
  }
  for ( unsigned int width = 0; width < conf.getCellWidth(); width++ ) {
    for ( unsigned int height = 0; height < conf.getCellHeight(); height++ ) {
      std::string cell_s = std::to_string(width) + std::to_string(height);
      std::string width_s = std::to_string(width);
      std::string height_s = std::to_string(height);

      temp = isa::utils::replace(&defineCell_sTemplate, "<%CELL%>", cell_s);
      defineCell_s->append(*temp);
      delete temp;
      temp = isa::utils::replace(&store_sTemplate, "<%WIDTH%>", width_s);
      temp = isa::utils::replace(temp, "<%HEIGHT%>", height_s, true);
      store_s->append(*temp);
      delete temp;
    }
  }
  for ( unsigned int sample = 0; sample < conf.getNrItemsD1(); sample++ ) {
    std::string offsetD1_s = std::to_string(sample);

    for ( unsigned int width = 0; width < conf.getCellWidth(); width++ ) {
      std::string width_s = std::to_string(width);

      if ( width == 0 ) {
        temp = isa::utils::replace(&loadX_sTemplate, "+ <%WIDTH%>", empty_s);
      } else {
        temp = isa::utils::replace(&loadX_sTemplate, "<%WIDTH%>", width_s);
      }
      temp = isa::utils::replace(temp, "<%STATION%>", width_s, true);
      loadCompute_s->append(*temp);
      delete temp;
    }
    for ( unsigned int height = 0; height < conf.getCellHeight(); height++ ) {
      std::string height_s = std::to_string(height);

      if ( height == 0 ) {
        temp = isa::utils::replace(&loadY_sTemplate, "+ <%WIDTH%>", empty_s);
      } else {
        temp = isa::utils::replace(&loadY_sTemplate, "<%WIDTH%>", height_s);
      }
      temp = isa::utils::replace(temp, "<%STATION%>", height_s, true);
      loadCompute_s->append(*temp);
      delete temp;
    }
    loadCompute_s = isa::utils::replace(loadCompute_s, "<%OFFSETD1%>", offsetD1_s, true);
    for ( unsigned int computeStatement = 0; computeStatement < 8; computeStatement++ ) {
      for ( unsigned int width = 0; width < conf.getCellWidth(); width++ ) {
        for ( unsigned int height = 0; height < conf.getCellHeight(); height++ ) {
          std::string cell_s = std::to_string(width) + std::to_string(height);

          temp = isa::utils::replace(&compute_sTemplate[computeStatement], "<%CELL%>", cell_s);
          loadCompute_s->append(*temp);
          delete temp;
        }
      }
    }
  }

  code = isa::utils::replace(code, "<%DEFINE_STATION%>", *defineStation_s, true);
  code = isa::utils::replace(code, "<%DEFINE_CELL%>", *defineCell_s, true);
  code = isa::utils::replace(code, "<%LOAD_AND_COMPUTE%>", *loadCompute_s, true);
  code = isa::utils::replace(code, "<%STORE%>", *store_s, true);
  delete defineStation_s;
  delete defineCell_s;
  delete loadCompute_s;
  delete store_s;

  return code;
}

unsigned int generateCellMap(const CorrelatorConf & conf, std::vector< unsigned int > & cellMapX, std::vector< unsigned int > & cellMapY, const unsigned int nrStations) {
  unsigned int nrCells = 0;

  cellMapX.clear();
  cellMapY.clear();
  for ( int stationY = nrStations - conf.getCellHeight(); stationY >= 0; stationY -= conf.getCellHeight() ) {
    for ( int stationX = 0; stationX + static_cast< int >(conf.getCellWidth()) - 1 <= stationY; stationX += conf.getCellWidth() ) {
      nrCells++;
      cellMapX.push_back(stationX);
      cellMapY.push_back(stationY);
    }
  }

  return nrCells;
}

}; // TuneBench

<commit_msg>Cleaning the store statements.<commit_after>// Copyright 2016 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cmath>

#include <Correlator.hpp>

namespace TuneBench {

CorrelatorConf::CorrelatorConf() : isa::OpenCL::KernelConf(), width(1), height(1) {}

std::string CorrelatorConf::print() const {
  return std::to_string(width) + " " + std::to_string(height) + " " + isa::OpenCL::KernelConf::print();
}

std::string * getCorrelatorOpenCL(const CorrelatorConf & conf, const std::string & dataName, const unsigned int padding, const unsigned int nrChannels, const unsigned int nrStations, const unsigned int nrSamples, const unsigned int nrPolarizations) {
  std::string * code = new std::string();

  // Begin kernel's template
  *code = "__kernel void correlator(__global const " + dataName + "4 * const restrict input, __global " + dataName + "8 * const restrict output, __global const unsigned int * const restrict cellMapX, __global const unsigned int * const restrict cellMapY) {\n"
    "const unsigned int cell = (get_group_id(0) * " + std::to_string(conf.getNrThreadsD0() * conf.getNrItemsD0()) + ") + get_local_id(0);\n"
    "const unsigned int channel = (get_group_id(2) * " + std::to_string(conf.getNrThreadsD2()) + ") + get_local_id(2);\n"
    "const unsigned int baseStationX = cellMapX[cell];\n"
    "const unsigned int baseStationY = cellMapY[cell];\n"
    "<%DEFINE_STATION%>"
    "<%DEFINE_CELL%>"
    "\n"
    "// Compute\n"
    "for ( unsigned int sample = 0; sample < " + std::to_string(nrSamples) + "; sample += " + std::to_string(conf.getNrItemsD1()) + " ) {\n"
    "<%LOAD_AND_COMPUTE%>"
    "}\n"
    "<%STORE%>"
    "}\n";
  std::string defineStationX_sTemplate = dataName + "4 sampleStationX<%STATION%>P0 = (" + dataName + "4)(0.0);\n";
  std::string defineStationY_sTemplate = dataName + "4 sampleStationY<%STATION%>P1 = (" + dataName + "4)(0.0);\n";
  std::string defineCell_sTemplate = dataName + "8 accumulator<%CELL%> = (" + dataName + "8)(0.0);\n";
  std::string loadX_sTemplate = "sampleStationX<%STATION%>P0 = input[(channel * " + std::to_string(nrStations * isa::utils::pad(nrSamples, padding / 4)) + ") + ((baseStationX + <%WIDTH%>) * " + std::to_string(isa::utils::pad(nrSamples, padding / 4)) + ") + (sample + <%OFFSETD1%>)];\n"
    "sampleStationX<%STATION%>P1 = input[(channel * " + std::to_string(nrStations * isa::utils::pad(nrSamples, padding / 4)) + ") + ((baseStationX + <%WIDTH%>) * " + std::to_string(isa::utils::pad(nrSamples, padding / 4)) + ") + (sample + <%OFFSETD1%>)];\n";
  std::string loadY_sTemplate = "sampleStationY<%STATION%>P0 = input[(channel * " + std::to_string(nrStations * isa::utils::pad(nrSamples, padding / 4)) + ") + ((baseStationY + <%HEIGHT%>) * " + std::to_string(isa::utils::pad(nrSamples, padding / 4)) + ") + (sample + <%OFFSETD1%>)];\n"
    "sampleStationY<%STATION%>P1 = input[(channel * " + std::to_string(nrStations * isa::utils::pad(nrSamples, padding / 4)) + ") + ((baseStationY + <%HEIGHT%>) * " + std::to_string(isa::utils::pad(nrSamples, padding / 4)) + ") + (sample + <%OFFSETD1%>)];\n";
  std::vector< std::string > compute_sTemplate(8);
  compute_sTemplate[0] = "accumulator<%CELL%>.s0 += (sampleStation<%STATION%>P0.x * sampleStation<%STATION%>P1.x) - (sampleStation<%STATION%>P0.y * (-sampleStation<%STATION%>P1.y));\n";
  compute_sTemplate[1] = "accumulator<%CELL%>.s1 += (sampleStation<%STATION%>P0.x * (-sampleStation<%STATION%>P1.y)) + (sampleStation<%STATION%>P0.y * sampleStation<%STATION%>P1.x);\n";
  compute_sTemplate[2] = "accumulator<%CELL%>.s2 += (sampleStation<%STATION%>P0.x * sampleStation<%STATION%>P1.z) - (sampleStation<%STATION%>P0.y * (-sampleStation<%STATION%>P1.w));\n";
  compute_sTemplate[3] = "accumulator<%CELL%>.s3 += (sampleStation<%STATION%>P0.x * (-sampleStation<%STATION%>P1.w)) + (sampleStation<%STATION%>P0.y * sampleStation<%STATION%>P1.z);\n";
  compute_sTemplate[4] = "accumulator<%CELL%>.s4 += (sampleStation<%STATION%>P0.z * sampleStation<%STATION%>P1.x) - (sampleStation<%STATION%>P0.w * (-sampleStation<%STATION%>P1.y));\n";
  compute_sTemplate[5] = "accumulator<%CELL%>.s5 += (sampleStation<%STATION%>P0.z * (-sampleStation<%STATION%>P1.y)) + (sampleStation<%STATION%>P0.w * sampleStation<%STATION%>P1.x);\n";
  compute_sTemplate[6] = "accumulator<%CELL%>.s6 += (sampleStation<%STATION%>P0.z * sampleStation<%STATION%>P1.z) - (sampleStation<%STATION%>P0.w * (-sampleStation<%STATION%>P1.w));\n";
  compute_sTemplate[7] = "accumulator<%CELL%>.s7 += (sampleStation<%STATION%>P0.z * (-sampleStation<%STATION%>P1.w)) + (sampleStation<%STATION%>P0.w * sampleStation<%STATION%>P1.z);\n";
  std::string store_sTemplate = "output[(((((stationY + <%HEIGHT%>) * (stationY + <%HEIGHT%> + 1)) / 2) + stationX + <%WIDTH%>) * " + std::to_string(nrChannels) + ") + channel] = accumulator<%CELL%>;\n";
  // End kernel's template

  std::string * defineStation_s = new std::string();
  std::string * defineCell_s = new std::string();
  std::string * loadCompute_s = new std::string();
  std::string * store_s = new std::string();
  std::string * temp = 0;
  std::string empty_s = "";

  for ( unsigned int width = 0; width < conf.getCellWidth(); width++ ) {
    std::string width_s = std::to_string(width);

    temp = isa::utils::replace(&defineStationX_sTemplate, "<%STATION%>", width_s);
    defineStation_s->append(*temp);
    delete temp;
  }
  for ( unsigned int height = 0; height < conf.getCellHeight(); height++ ) {
    std::string height_s = std::to_string(height);

    temp = isa::utils::replace(&defineStationY_sTemplate, "<%STATION%>", height_s);
    defineStation_s->append(*temp);
    delete temp;
  }
  for ( unsigned int width = 0; width < conf.getCellWidth(); width++ ) {
    for ( unsigned int height = 0; height < conf.getCellHeight(); height++ ) {
      std::string cell_s = std::to_string(width) + std::to_string(height);
      std::string width_s = std::to_string(width);
      std::string height_s = std::to_string(height);

      temp = isa::utils::replace(&defineCell_sTemplate, "<%CELL%>", cell_s);
      defineCell_s->append(*temp);
      delete temp;
      if ( width == 0 ) {
        temp = isa::utils::replace(&store_sTemplate, " + <%WIDTH%>", empty_s);
      } else {
        temp = isa::utils::replace(&store_sTemplate, "<%WIDTH%>", width_s);
      }
      if ( height == 0 ) {
        temp = isa::utils::replace(temp, " + <%HEIGHT%>", empty_s, true);
      } else {
        temp = isa::utils::replace(temp, "<%HEIGHT%>", height_s, true);
      }
      temp = isa::utils::replace(temp, "<%CELL%>", cell_s, true);
      store_s->append(*temp);
      delete temp;
    }
  }
  for ( unsigned int sample = 0; sample < conf.getNrItemsD1(); sample++ ) {
    std::string offsetD1_s = std::to_string(sample);

    for ( unsigned int width = 0; width < conf.getCellWidth(); width++ ) {
      std::string width_s = std::to_string(width);

      if ( width == 0 ) {
        temp = isa::utils::replace(&loadX_sTemplate, "+ <%WIDTH%>", empty_s);
      } else {
        temp = isa::utils::replace(&loadX_sTemplate, "<%WIDTH%>", width_s);
      }
      temp = isa::utils::replace(temp, "<%STATION%>", width_s, true);
      loadCompute_s->append(*temp);
      delete temp;
    }
    for ( unsigned int height = 0; height < conf.getCellHeight(); height++ ) {
      std::string height_s = std::to_string(height);

      if ( height == 0 ) {
        temp = isa::utils::replace(&loadY_sTemplate, "+ <%WIDTH%>", empty_s);
      } else {
        temp = isa::utils::replace(&loadY_sTemplate, "<%WIDTH%>", height_s);
      }
      temp = isa::utils::replace(temp, "<%STATION%>", height_s, true);
      loadCompute_s->append(*temp);
      delete temp;
    }
    loadCompute_s = isa::utils::replace(loadCompute_s, "<%OFFSETD1%>", offsetD1_s, true);
    for ( unsigned int computeStatement = 0; computeStatement < 8; computeStatement++ ) {
      for ( unsigned int width = 0; width < conf.getCellWidth(); width++ ) {
        for ( unsigned int height = 0; height < conf.getCellHeight(); height++ ) {
          std::string cell_s = std::to_string(width) + std::to_string(height);

          temp = isa::utils::replace(&compute_sTemplate[computeStatement], "<%CELL%>", cell_s);
          loadCompute_s->append(*temp);
          delete temp;
        }
      }
    }
  }

  code = isa::utils::replace(code, "<%DEFINE_STATION%>", *defineStation_s, true);
  code = isa::utils::replace(code, "<%DEFINE_CELL%>", *defineCell_s, true);
  code = isa::utils::replace(code, "<%LOAD_AND_COMPUTE%>", *loadCompute_s, true);
  code = isa::utils::replace(code, "<%STORE%>", *store_s, true);
  delete defineStation_s;
  delete defineCell_s;
  delete loadCompute_s;
  delete store_s;

  return code;
}

unsigned int generateCellMap(const CorrelatorConf & conf, std::vector< unsigned int > & cellMapX, std::vector< unsigned int > & cellMapY, const unsigned int nrStations) {
  unsigned int nrCells = 0;

  cellMapX.clear();
  cellMapY.clear();
  for ( int stationY = nrStations - conf.getCellHeight(); stationY >= 0; stationY -= conf.getCellHeight() ) {
    for ( int stationX = 0; stationX + static_cast< int >(conf.getCellWidth()) - 1 <= stationY; stationX += conf.getCellWidth() ) {
      nrCells++;
      cellMapX.push_back(stationX);
      cellMapY.push_back(stationY);
    }
  }

  return nrCells;
}

}; // TuneBench

<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <cmath>
#include <nix/util/util.hpp>
#include <nix/Dimensions.hpp>
#include <nix/Exception.hpp>

using namespace std;
using namespace nix;
using namespace nix::base;

//-------------------------------------------------------
// Implementation of Dimension
//-------------------------------------------------------

Dimension::Dimension()
    : ImplContainer()
{
}

Dimension::Dimension(const shared_ptr<IDimension> &p_impl)
    : ImplContainer(p_impl)
{
}

Dimension::Dimension(shared_ptr<IDimension> &&ptr)
    : ImplContainer(std::move(ptr))
{
}

Dimension::Dimension(const Dimension &other)
    : ImplContainer(other)
{
}

Dimension::Dimension(const SampledDimension &other)
    : ImplContainer(dynamic_pointer_cast<IDimension>(other.impl()))
{
}

Dimension::Dimension(const RangeDimension &other)
    : ImplContainer(dynamic_pointer_cast<IDimension>(other.impl()))
{
}

Dimension::Dimension(const SetDimension &other)
    : ImplContainer(dynamic_pointer_cast<IDimension>(other.impl()))
{
}

SetDimension Dimension::asSetDimension() const {
    if (dimensionType() != DimensionType::Set) {
        throw IncompatibleDimensions("Dimension is not of type Set and thus cannot be cast to this type", "asSetDimension");
    }
    return SetDimension(std::dynamic_pointer_cast<base::ISetDimension>(impl()));
}

SampledDimension Dimension::asSampledDimension() const {
    if (dimensionType() != DimensionType::Sample) {
        throw IncompatibleDimensions("Dimension is not of type Sample and thus cannot be cast to this type", "asSampledDimension");
    }
    return SampledDimension(std::dynamic_pointer_cast<base::ISampledDimension>(impl()));
}

RangeDimension Dimension::asRangeDimension() const {
    if (dimensionType() != DimensionType::Range) {
        throw IncompatibleDimensions("Dimension is not of type Range and thus cannot be cast to this type", "asRangeDimension");
    }
    return RangeDimension(std::dynamic_pointer_cast<base::IRangeDimension>(impl()));
}

Dimension& Dimension::operator=(const SampledDimension &other) {
    shared_ptr<IDimension> tmp(dynamic_pointer_cast<IDimension>(other.impl()));

    if (impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

Dimension& Dimension::operator=(const RangeDimension &other) {
    shared_ptr<IDimension> tmp(dynamic_pointer_cast<IDimension>(other.impl()));

    if (impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

Dimension& Dimension::operator=(const SetDimension &other) {
    shared_ptr<IDimension> tmp(dynamic_pointer_cast<IDimension>(other.impl()));

    if (impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

//-------------------------------------------------------
// Implementation of SampledDimension
//-------------------------------------------------------

SampledDimension::SampledDimension()
    : ImplContainer()
{
}

SampledDimension::SampledDimension(const std::shared_ptr<ISampledDimension> &p_impl)
    : ImplContainer(p_impl)
{
}

SampledDimension::SampledDimension(std::shared_ptr<ISampledDimension> &&ptr)
    : ImplContainer(std::move(ptr))
{
}

SampledDimension::SampledDimension(const SampledDimension &other)
    : ImplContainer(other)
{
}

void SampledDimension::unit(const std::string &unit) {
    if (!(util::isSIUnit(unit))) {
        throw InvalidUnit("Unit is not a SI unit. Note: so far, only atomic SI units are supported.",
                          "SampledDimension::unit(const string &unit)");
    }
    backend()->unit(unit);
}

void SampledDimension::samplingInterval(double interval) {
    if (interval <= 0.0) {
        throw std::runtime_error("SampledDimenion::samplingInterval: Sampling intervals must be larger than 0.0!");
    }
    backend()->samplingInterval(interval);
}

size_t SampledDimension::indexOf(const double position) const {
    int index;
    double offset = backend()->offset() ? *(backend()->offset()) : 0.0;
    double sampling_interval = backend()->samplingInterval();
    index = round(( position - offset) / sampling_interval);
    if (index < 0) {
        throw nix::OutOfBounds("Position is out of bounds of this dimension!", 0);
    }
    return static_cast<size_t>(index);
}

double SampledDimension::positionAt(const size_t index) const {
    double offset = backend()->offset() ? *(backend()->offset()) : 0.0;
    double sampling_interval = backend()->samplingInterval();
    return index * sampling_interval + offset;
}

vector<double> SampledDimension::axis(const size_t count, const size_t startIndex) const {
    vector<double> axis(count);
    double offset =  backend()->offset() ? *(backend()->offset()) : 0.0;
    double sampling_interval = backend()->samplingInterval();
    for (size_t i = 0; i < axis.size(); ++i) {
        axis[i] = (i + startIndex) * sampling_interval + offset;
    }
    return axis;
}

SampledDimension& SampledDimension::operator=(const SampledDimension &other) {
    shared_ptr<ISampledDimension> tmp(other.impl());

    if (impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

SampledDimension& SampledDimension::operator=(const Dimension &other) {
    shared_ptr<ISampledDimension> tmp(dynamic_pointer_cast<ISampledDimension>(other.impl()));

    if (other.dimensionType() == DimensionType::Sample && impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

//-------------------------------------------------------
// Implementation of SetDimension
//-------------------------------------------------------

SetDimension::SetDimension()
    : ImplContainer()
{
}

SetDimension::SetDimension(const std::shared_ptr<ISetDimension> &p_impl)
    : ImplContainer(p_impl)
{
}

SetDimension::SetDimension(std::shared_ptr<ISetDimension> &&ptr)
    : ImplContainer(std::move(ptr))
{
}

SetDimension::SetDimension(const SetDimension &other)
    : ImplContainer(other)
{
}

SetDimension& SetDimension::operator=(const SetDimension &other) {
    shared_ptr<ISetDimension> tmp(other.impl());

    if (impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

SetDimension& SetDimension::operator=(const Dimension &other) {
    shared_ptr<ISetDimension> tmp(dynamic_pointer_cast<ISetDimension>(other.impl()));

    if (other.dimensionType() == DimensionType::Set && impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

//-------------------------------------------------------
// Implementation of RangeDimension
//-------------------------------------------------------

RangeDimension::RangeDimension()
    : ImplContainer()
{
}

RangeDimension::RangeDimension(const std::shared_ptr<IRangeDimension> &p_impl)
    : ImplContainer(p_impl)
{
}

RangeDimension::RangeDimension(std::shared_ptr<IRangeDimension> &&ptr)
    : ImplContainer(std::move(ptr))
{
}

RangeDimension::RangeDimension(const RangeDimension &other)
    : ImplContainer(other)
{
}

void RangeDimension::unit(const std::string &unit) {
    if (!(util::isSIUnit(unit))) {
        throw InvalidUnit("Unit is not an atomic SI. Note: So far composite units are not supported", "RangeDimension::unit(const string &unit)");
    }
    backend()->unit(unit);
}

void RangeDimension::ticks(const std::vector<double> &ticks) {
    if (!std::is_sorted(ticks.begin(), ticks.end())) {
        std::string caller = "Range::ticks()";
        throw UnsortedTicks(caller);
    }
    backend()->ticks(ticks);
}

double RangeDimension::tickAt(const size_t index) const {
    vector<double> ticks = this->ticks();
    if (index >= ticks.size()) {
        throw nix::OutOfBounds("RangeDimension::tickAt: Given index is out of bounds!", index);
    }
    return ticks[index];
}

size_t RangeDimension::indexOf(const double position) const {
    size_t index;
    vector<double> ticks = this->ticks();
    if (position < *ticks.begin()) {
        return 0;
    } else if (position > *prev(ticks.end())) {
        return prev(ticks.end()) - ticks.begin();
    }
    vector<double>::iterator low = std::lower_bound (ticks.begin(), ticks.end(), position);
    if (*low == position) {
        return low - ticks.begin();
    }
    if (low != ticks.begin() && *low != position) {
        double diff_low, diff_before;
        diff_low = fabs(*low - position);
        diff_before = fabs(*(std::prev(low)) - position);
        if (diff_low < diff_before) {
            index = low - ticks.begin();
        } else {
            index = low - ticks.begin() - 1;
        }
        return index;
    } else {
        return low - ticks.begin();
    }
}

vector<double> RangeDimension::axis(const size_t count, const size_t startIndex) const {
    vector<double> ticks = this->ticks();
    if ((startIndex + count) > ticks.size()) {
        throw nix::OutOfBounds("RangeDimension::axis: Count is invalid, reaches beyond the ticks stored in this dimension.");
    }
    vector<double>::const_iterator first = ticks.begin() + startIndex;
    vector<double> axis(first, first + count);
    return axis;
}

RangeDimension& RangeDimension::operator=(const RangeDimension &other) {
    shared_ptr<IRangeDimension> tmp(other.impl());

    if (impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

RangeDimension& RangeDimension::operator=(const Dimension &other) {
    shared_ptr<IRangeDimension> tmp(dynamic_pointer_cast<IRangeDimension>(other.impl()));

    if (other.dimensionType() == DimensionType::Range && impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

<commit_msg>Dimensions::indexOf: explicity cast result of round<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <cmath>
#include <nix/util/util.hpp>
#include <nix/Dimensions.hpp>
#include <nix/Exception.hpp>

using namespace std;
using namespace nix;
using namespace nix::base;

//-------------------------------------------------------
// Implementation of Dimension
//-------------------------------------------------------

Dimension::Dimension()
    : ImplContainer()
{
}

Dimension::Dimension(const shared_ptr<IDimension> &p_impl)
    : ImplContainer(p_impl)
{
}

Dimension::Dimension(shared_ptr<IDimension> &&ptr)
    : ImplContainer(std::move(ptr))
{
}

Dimension::Dimension(const Dimension &other)
    : ImplContainer(other)
{
}

Dimension::Dimension(const SampledDimension &other)
    : ImplContainer(dynamic_pointer_cast<IDimension>(other.impl()))
{
}

Dimension::Dimension(const RangeDimension &other)
    : ImplContainer(dynamic_pointer_cast<IDimension>(other.impl()))
{
}

Dimension::Dimension(const SetDimension &other)
    : ImplContainer(dynamic_pointer_cast<IDimension>(other.impl()))
{
}

SetDimension Dimension::asSetDimension() const {
    if (dimensionType() != DimensionType::Set) {
        throw IncompatibleDimensions("Dimension is not of type Set and thus cannot be cast to this type", "asSetDimension");
    }
    return SetDimension(std::dynamic_pointer_cast<base::ISetDimension>(impl()));
}

SampledDimension Dimension::asSampledDimension() const {
    if (dimensionType() != DimensionType::Sample) {
        throw IncompatibleDimensions("Dimension is not of type Sample and thus cannot be cast to this type", "asSampledDimension");
    }
    return SampledDimension(std::dynamic_pointer_cast<base::ISampledDimension>(impl()));
}

RangeDimension Dimension::asRangeDimension() const {
    if (dimensionType() != DimensionType::Range) {
        throw IncompatibleDimensions("Dimension is not of type Range and thus cannot be cast to this type", "asRangeDimension");
    }
    return RangeDimension(std::dynamic_pointer_cast<base::IRangeDimension>(impl()));
}

Dimension& Dimension::operator=(const SampledDimension &other) {
    shared_ptr<IDimension> tmp(dynamic_pointer_cast<IDimension>(other.impl()));

    if (impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

Dimension& Dimension::operator=(const RangeDimension &other) {
    shared_ptr<IDimension> tmp(dynamic_pointer_cast<IDimension>(other.impl()));

    if (impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

Dimension& Dimension::operator=(const SetDimension &other) {
    shared_ptr<IDimension> tmp(dynamic_pointer_cast<IDimension>(other.impl()));

    if (impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

//-------------------------------------------------------
// Implementation of SampledDimension
//-------------------------------------------------------

SampledDimension::SampledDimension()
    : ImplContainer()
{
}

SampledDimension::SampledDimension(const std::shared_ptr<ISampledDimension> &p_impl)
    : ImplContainer(p_impl)
{
}

SampledDimension::SampledDimension(std::shared_ptr<ISampledDimension> &&ptr)
    : ImplContainer(std::move(ptr))
{
}

SampledDimension::SampledDimension(const SampledDimension &other)
    : ImplContainer(other)
{
}

void SampledDimension::unit(const std::string &unit) {
    if (!(util::isSIUnit(unit))) {
        throw InvalidUnit("Unit is not a SI unit. Note: so far, only atomic SI units are supported.",
                          "SampledDimension::unit(const string &unit)");
    }
    backend()->unit(unit);
}

void SampledDimension::samplingInterval(double interval) {
    if (interval <= 0.0) {
        throw std::runtime_error("SampledDimenion::samplingInterval: Sampling intervals must be larger than 0.0!");
    }
    backend()->samplingInterval(interval);
}

size_t SampledDimension::indexOf(const double position) const {
    //FIXME: should we use NDSSize::value_type here instead of ssize_t?
    //FIXME: also, on the smae grounds, should the return not be NDSize::value_type?
    ssize_t index;
    double offset = backend()->offset() ? *(backend()->offset()) : 0.0;
    double sampling_interval = backend()->samplingInterval();
    index = static_cast<ssize_t>(round(( position - offset) / sampling_interval));
    if (index < 0) {
        throw nix::OutOfBounds("Position is out of bounds of this dimension!", 0);
    }
    return static_cast<size_t>(index);
}

double SampledDimension::positionAt(const size_t index) const {
    double offset = backend()->offset() ? *(backend()->offset()) : 0.0;
    double sampling_interval = backend()->samplingInterval();
    return index * sampling_interval + offset;
}

vector<double> SampledDimension::axis(const size_t count, const size_t startIndex) const {
    vector<double> axis(count);
    double offset =  backend()->offset() ? *(backend()->offset()) : 0.0;
    double sampling_interval = backend()->samplingInterval();
    for (size_t i = 0; i < axis.size(); ++i) {
        axis[i] = (i + startIndex) * sampling_interval + offset;
    }
    return axis;
}

SampledDimension& SampledDimension::operator=(const SampledDimension &other) {
    shared_ptr<ISampledDimension> tmp(other.impl());

    if (impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

SampledDimension& SampledDimension::operator=(const Dimension &other) {
    shared_ptr<ISampledDimension> tmp(dynamic_pointer_cast<ISampledDimension>(other.impl()));

    if (other.dimensionType() == DimensionType::Sample && impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

//-------------------------------------------------------
// Implementation of SetDimension
//-------------------------------------------------------

SetDimension::SetDimension()
    : ImplContainer()
{
}

SetDimension::SetDimension(const std::shared_ptr<ISetDimension> &p_impl)
    : ImplContainer(p_impl)
{
}

SetDimension::SetDimension(std::shared_ptr<ISetDimension> &&ptr)
    : ImplContainer(std::move(ptr))
{
}

SetDimension::SetDimension(const SetDimension &other)
    : ImplContainer(other)
{
}

SetDimension& SetDimension::operator=(const SetDimension &other) {
    shared_ptr<ISetDimension> tmp(other.impl());

    if (impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

SetDimension& SetDimension::operator=(const Dimension &other) {
    shared_ptr<ISetDimension> tmp(dynamic_pointer_cast<ISetDimension>(other.impl()));

    if (other.dimensionType() == DimensionType::Set && impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

//-------------------------------------------------------
// Implementation of RangeDimension
//-------------------------------------------------------

RangeDimension::RangeDimension()
    : ImplContainer()
{
}

RangeDimension::RangeDimension(const std::shared_ptr<IRangeDimension> &p_impl)
    : ImplContainer(p_impl)
{
}

RangeDimension::RangeDimension(std::shared_ptr<IRangeDimension> &&ptr)
    : ImplContainer(std::move(ptr))
{
}

RangeDimension::RangeDimension(const RangeDimension &other)
    : ImplContainer(other)
{
}

void RangeDimension::unit(const std::string &unit) {
    if (!(util::isSIUnit(unit))) {
        throw InvalidUnit("Unit is not an atomic SI. Note: So far composite units are not supported", "RangeDimension::unit(const string &unit)");
    }
    backend()->unit(unit);
}

void RangeDimension::ticks(const std::vector<double> &ticks) {
    if (!std::is_sorted(ticks.begin(), ticks.end())) {
        std::string caller = "Range::ticks()";
        throw UnsortedTicks(caller);
    }
    backend()->ticks(ticks);
}

double RangeDimension::tickAt(const size_t index) const {
    vector<double> ticks = this->ticks();
    if (index >= ticks.size()) {
        throw nix::OutOfBounds("RangeDimension::tickAt: Given index is out of bounds!", index);
    }
    return ticks[index];
}

size_t RangeDimension::indexOf(const double position) const {
    size_t index;
    vector<double> ticks = this->ticks();
    if (position < *ticks.begin()) {
        return 0;
    } else if (position > *prev(ticks.end())) {
        return prev(ticks.end()) - ticks.begin();
    }
    vector<double>::iterator low = std::lower_bound (ticks.begin(), ticks.end(), position);
    if (*low == position) {
        return low - ticks.begin();
    }
    if (low != ticks.begin() && *low != position) {
        double diff_low, diff_before;
        diff_low = fabs(*low - position);
        diff_before = fabs(*(std::prev(low)) - position);
        if (diff_low < diff_before) {
            index = low - ticks.begin();
        } else {
            index = low - ticks.begin() - 1;
        }
        return index;
    } else {
        return low - ticks.begin();
    }
}

vector<double> RangeDimension::axis(const size_t count, const size_t startIndex) const {
    vector<double> ticks = this->ticks();
    if ((startIndex + count) > ticks.size()) {
        throw nix::OutOfBounds("RangeDimension::axis: Count is invalid, reaches beyond the ticks stored in this dimension.");
    }
    vector<double>::const_iterator first = ticks.begin() + startIndex;
    vector<double> axis(first, first + count);
    return axis;
}

RangeDimension& RangeDimension::operator=(const RangeDimension &other) {
    shared_ptr<IRangeDimension> tmp(other.impl());

    if (impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

RangeDimension& RangeDimension::operator=(const Dimension &other) {
    shared_ptr<IRangeDimension> tmp(dynamic_pointer_cast<IRangeDimension>(other.impl()));

    if (other.dimensionType() == DimensionType::Range && impl() != tmp) {
        std::swap(impl(), tmp);
    }

    return *this;
}

<|endoftext|>


<commit_before><commit_msg>coverity#705150 Missing break in switch<commit_after><|endoftext|>


<commit_before>#include <cstdint>
#include <cstddef>
#include <cstdio>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#include <ObjBase.h>
#include <Shlwapi.h>
#include <Thumbcache.h>
#include <Unknwn.h>

#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "Ole32.lib")

const wchar_t* ProviderGUID = L"{35788B9B-04AB-4B75-AB3A-1ED403AFC746}";

using DllGetClassObjectT = HRESULT(const IID& rclsid, const IID& riid, void** ppv);

BOOL SaveHBITMAPToFile(HBITMAP Bitmap, const char* Filename);

int main(int argc, char** argv)
{
	GUID clsid;
	IIDFromString(ProviderGUID, &clsid);

	HMODULE DLLHandle = LoadLibraryA("SaiThumbs.dll");

	if( !DLLHandle )
	{
		std::puts("can't open DLL");
		return EXIT_FAILURE;
	}

	DllGetClassObjectT* DllGetClassObject = reinterpret_cast<DllGetClassObjectT*>(GetProcAddress(
		DLLHandle, "DllGetClassObject"));

	if( DllGetClassObject == nullptr )
	{
		std::puts("Failed: Unable to get DLLGetClassobject address");
		return EXIT_FAILURE;
	}

	IClassFactory* ClassFactory = nullptr;
	HRESULT Result = DllGetClassObject(clsid, IID_IClassFactory, reinterpret_cast<void**>(&ClassFactory));
	if( Result != S_OK )
	{
		std::printf("Failed: Unable to get IClassFactory: %08x\n", Result);
		return EXIT_FAILURE;
	}

	IInitializeWithFile* InitWithFile;
	Result = ClassFactory->CreateInstance(nullptr, IID_IInitializeWithFile, reinterpret_cast<void**>(&InitWithFile));
	if( Result != S_OK )
	{
		std::puts("Failed: Unable to get IInitializeWithFile");
		return EXIT_FAILURE;
	}
	ClassFactory->Release();

	IThumbnailProvider* ThumbProvider;
	Result = InitWithFile->QueryInterface(IID_IThumbnailProvider, reinterpret_cast<void**>(&ThumbProvider));
	if( Result != S_OK )
	{
		std::puts("Failed: Unable to get IThumbnailProvider");
		return EXIT_FAILURE;
	}

	Result = InitWithFile->Initialize(L"./test.sai", 0);
	InitWithFile->Release();
	if( Result != S_OK )
	{
		std::puts("Failed: Unable to initilize IInitializeWithFile");
		return EXIT_FAILURE;
	}

	HBITMAP ThumbImage;
	WTS_ALPHATYPE ThumbAlphaType;
	Result = ThumbProvider->GetThumbnail(256, &ThumbImage, &ThumbAlphaType);
	ThumbProvider->Release();
	if( Result != S_OK )
	{
		std::puts("Failed: GetThumbnail returned failure");
		return EXIT_FAILURE;
	}

	SaveHBITMAPToFile(
		ThumbImage,
		"./test.bmp"
	);

	return EXIT_SUCCESS;
}

BOOL SaveHBITMAPToFile(HBITMAP Bitmap, const char* Filename)
{
	const DWORD PaletteSize = 0;
	DWORD BmBitsSize = 0, HeaderSize = 0, Written = 0;
	BITMAP NewBitmap;
	BITMAPFILEHEADER Header;
	BITMAPINFOHEADER bi;
	HANDLE hOldPal2 = nullptr;
	HDC DeviceContext = CreateDC(TEXT("DISPLAY"), nullptr, nullptr, nullptr);
	const int Bits = GetDeviceCaps(DeviceContext, BITSPIXEL) * GetDeviceCaps(DeviceContext, PLANES);
	DeleteDC(DeviceContext);
	const WORD BitCount = Bits;
	GetObject(Bitmap, sizeof(NewBitmap), reinterpret_cast<char*>(&NewBitmap));
	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = NewBitmap.bmWidth;
	bi.biHeight = -NewBitmap.bmHeight;
	bi.biPlanes = 1;
	bi.biBitCount = BitCount;
	bi.biCompression = BI_RGB;
	bi.biSizeImage = 0;
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrImportant = 0;
	bi.biClrUsed = 256;
	BmBitsSize = ((NewBitmap.bmWidth * BitCount + 31) & ~31) / 8
		* NewBitmap.bmHeight;
	const HANDLE hDib = GlobalAlloc(GHND, BmBitsSize + PaletteSize + sizeof(BITMAPINFOHEADER));
	const LPBITMAPINFOHEADER lpbi = static_cast<LPBITMAPINFOHEADER>(GlobalLock(hDib));
	*lpbi = bi;

	const HANDLE hPal = GetStockObject(DEFAULT_PALETTE);
	if( hPal )
	{
		DeviceContext = GetDC(nullptr);
		hOldPal2 = SelectPalette(DeviceContext, static_cast<HPALETTE>(hPal), FALSE);
		RealizePalette(DeviceContext);
	}

	GetDIBits(
		DeviceContext, Bitmap, 0, static_cast<std::uint32_t>(NewBitmap.bmHeight),
		reinterpret_cast<char*>(lpbi) + sizeof(BITMAPINFOHEADER)
		+ PaletteSize, reinterpret_cast<BITMAPINFO *>(lpbi), DIB_RGB_COLORS);

	if( hOldPal2 )
	{
		SelectPalette(DeviceContext, static_cast<HPALETTE>(hOldPal2), TRUE);
		RealizePalette(DeviceContext);
		ReleaseDC(nullptr, DeviceContext);
	}

	const HANDLE FileHandle = CreateFileA(
		Filename, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr);

	if( FileHandle == INVALID_HANDLE_VALUE )
	{
		return FALSE;
	}

	Header.bfType = 0x4D42;
	HeaderSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + PaletteSize + BmBitsSize;
	Header.bfSize = HeaderSize;
	Header.bfReserved1 = 0;
	Header.bfReserved2 = 0;
	Header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
		PaletteSize;

	WriteFile(FileHandle, reinterpret_cast<char*>(&Header), sizeof(BITMAPFILEHEADER), &Written, nullptr);

	WriteFile(FileHandle, reinterpret_cast<char*>(lpbi), HeaderSize, &Written, nullptr);
	GlobalUnlock(hDib);
	GlobalFree(hDib);
	CloseHandle(FileHandle);
	return TRUE;
}
<commit_msg>Add unicode arguments<commit_after>#include <cstdint>
#include <cstddef>
#include <cstdio>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#include <ObjBase.h>
#include <Shlwapi.h>
#include <Thumbcache.h>
#include <Unknwn.h>
#include <string>

#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "Ole32.lib")

const wchar_t* ProviderGUID = L"{35788B9B-04AB-4B75-AB3A-1ED403AFC746}";

using DllGetClassObjectT = HRESULT(const IID& rclsid, const IID& riid, void** ppv);

BOOL SaveHBITMAPToFile(HBITMAP Bitmap, const wchar_t* Filename);

int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
	if( argc < 3)
	{
		std::wprintf(
			L"Usage: %s (Sai File) (output.bmp)\n",
			argv[0]
		);
		return EXIT_FAILURE;
	}
	GUID clsid;
	IIDFromString(ProviderGUID, &clsid);

	const HMODULE DLLHandle = LoadLibraryA("SaiThumbs.dll");

	if( !DLLHandle )
	{
		std::puts("Failed: Can't open DLL");
		return EXIT_FAILURE;
	}

	DllGetClassObjectT* DllGetClassObject = reinterpret_cast<DllGetClassObjectT*>(GetProcAddress(
		DLLHandle, "DllGetClassObject"));

	if( DllGetClassObject == nullptr )
	{
		std::puts("Failed: Unable to get DLLGetClassobject address");
		return EXIT_FAILURE;
	}

	IClassFactory* ClassFactory = nullptr;
	HRESULT Result = DllGetClassObject(clsid, IID_IClassFactory, reinterpret_cast<void**>(&ClassFactory));
	if( Result != S_OK )
	{
		std::printf("Failed: Unable to get IClassFactory: %08x\n", Result);
		return EXIT_FAILURE;
	}

	IInitializeWithFile* InitWithFile;
	Result = ClassFactory->CreateInstance(nullptr, IID_IInitializeWithFile, reinterpret_cast<void**>(&InitWithFile));
	if( Result != S_OK )
	{
		std::puts("Failed: Unable to get IInitializeWithFile");
		return EXIT_FAILURE;
	}
	ClassFactory->Release();

	IThumbnailProvider* ThumbProvider;
	Result = InitWithFile->QueryInterface(IID_IThumbnailProvider, reinterpret_cast<void**>(&ThumbProvider));
	if( Result != S_OK )
	{
		std::puts("Failed: Unable to get IThumbnailProvider");
		return EXIT_FAILURE;
	}

	Result = InitWithFile->Initialize(argv[1] , 0);
	InitWithFile->Release();
	if( Result != S_OK )
	{
		std::puts("Failed: Unable to initilize IInitializeWithFile");
		return EXIT_FAILURE;
	}

	HBITMAP ThumbImage;
	WTS_ALPHATYPE ThumbAlphaType;
	Result = ThumbProvider->GetThumbnail(256, &ThumbImage, &ThumbAlphaType);
	ThumbProvider->Release();
	if( Result != S_OK )
	{
		std::puts("Failed: GetThumbnail returned failure");
		return EXIT_FAILURE;
	}

	SaveHBITMAPToFile(
		ThumbImage,
		argv[2]
	);

	return EXIT_SUCCESS;
}

BOOL SaveHBITMAPToFile(HBITMAP Bitmap, const wchar_t* Filename)
{
	const DWORD PaletteSize = 0;
	DWORD BmBitsSize = 0, HeaderSize = 0, Written = 0;
	BITMAP NewBitmap;
	BITMAPFILEHEADER Header;
	BITMAPINFOHEADER bi;
	HANDLE hOldPal2 = nullptr;
	HDC DeviceContext = CreateDC(TEXT("DISPLAY"), nullptr, nullptr, nullptr);
	const int Bits = GetDeviceCaps(DeviceContext, BITSPIXEL) * GetDeviceCaps(DeviceContext, PLANES);
	DeleteDC(DeviceContext);
	const WORD BitCount = Bits;
	GetObject(Bitmap, sizeof(NewBitmap), reinterpret_cast<char*>(&NewBitmap));
	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = NewBitmap.bmWidth;
	bi.biHeight = -NewBitmap.bmHeight;
	bi.biPlanes = 1;
	bi.biBitCount = BitCount;
	bi.biCompression = BI_RGB;
	bi.biSizeImage = 0;
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrImportant = 0;
	bi.biClrUsed = 256;
	BmBitsSize = ((NewBitmap.bmWidth * BitCount + 31) & ~31) / 8
		* NewBitmap.bmHeight;
	const HANDLE hDib = GlobalAlloc(GHND, BmBitsSize + PaletteSize + sizeof(BITMAPINFOHEADER));
	const LPBITMAPINFOHEADER lpbi = static_cast<LPBITMAPINFOHEADER>(GlobalLock(hDib));
	*lpbi = bi;

	const HANDLE hPal = GetStockObject(DEFAULT_PALETTE);
	if( hPal )
	{
		DeviceContext = GetDC(nullptr);
		hOldPal2 = SelectPalette(DeviceContext, static_cast<HPALETTE>(hPal), FALSE);
		RealizePalette(DeviceContext);
	}

	GetDIBits(
		DeviceContext, Bitmap, 0, static_cast<std::uint32_t>(NewBitmap.bmHeight),
		reinterpret_cast<char*>(lpbi) + sizeof(BITMAPINFOHEADER)
		+ PaletteSize, reinterpret_cast<BITMAPINFO *>(lpbi), DIB_RGB_COLORS);

	if( hOldPal2 )
	{
		SelectPalette(DeviceContext, static_cast<HPALETTE>(hOldPal2), TRUE);
		RealizePalette(DeviceContext);
		ReleaseDC(nullptr, DeviceContext);
	}

	const HANDLE FileHandle = CreateFileW(
		Filename, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr);

	if( FileHandle == INVALID_HANDLE_VALUE )
	{
		return FALSE;
	}

	Header.bfType = 0x4D42;
	HeaderSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + PaletteSize + BmBitsSize;
	Header.bfSize = HeaderSize;
	Header.bfReserved1 = 0;
	Header.bfReserved2 = 0;
	Header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
		PaletteSize;

	WriteFile(FileHandle, reinterpret_cast<char*>(&Header), sizeof(BITMAPFILEHEADER), &Written, nullptr);

	WriteFile(FileHandle, reinterpret_cast<char*>(lpbi), HeaderSize, &Written, nullptr);
	GlobalUnlock(hDib);
	GlobalFree(hDib);
	CloseHandle(FileHandle);
	return TRUE;
}
<|endoftext|>


<commit_before>#include "gamestates/mainmenustate.hpp"

#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/BlendMode.hpp>
#include <SFML/Window/Event.hpp>

#include "config/settings.hpp"
#include "gui/texturemanager.hpp"
#include "gui/ng/button.hpp"

namespace qrw
{

MainMenuState::MainMenuState(sf::RenderWindow* renderWindow)
	: GameState(renderWindow, EGameStateId::EGSID_MAIN_MENU_STATE),
	  _quitClicked(false),
	  _mainWindow()
{
	_mainWindow.setSize(sf::Vector2f(145, 240));
	_mainWindow.setRelativePosition(sf::Vector2f(15, 15));

	namelessgui::Button* button = new namelessgui::Button();

	button->setText("Quit");
	button->setSize(sf::Vector2f(139, 50));
	button->signalclicked.connect(std::bind(&MainMenuState::quitClicked, this));
	button->setParentAnchor({0.5f, 0.0f});
	button->setAnchor({0.5f, 0.0f});
	button->setRelativePosition({0.0f, 0.0f});
	_mainWindow.addWidget(button);

	_mainWindow.setVisible(true);
}

void MainMenuState::init(GameState* previousState)
{
	Settings* settings = Settings::getInstance();

	sf::Uint32 style = sf::Style::Default;

	if(settings->getFullscreen())
		style = sf::Style::Fullscreen;

	_renderWindow->create(
		sf::VideoMode(settings->getResolutionX(), settings->getResolutionY()),
		"QRW",
		style
	);

	// Set up textures
	TextureManager* textureManager = TextureManager::getInstance();

	// Set background texture
	_background.setSize(sf::Vector2f(settings->getResolutionX(), settings->getResolutionY()));
	_background.setTexture(textureManager->getTexture("mainmenubackground"));
}

EGameStateId MainMenuState::update()
{
	if(_quitClicked)
		return EGSID_QUIT;
	return EGSID_NO_CHANGE;
}

void MainMenuState::draw()
{
	_renderWindow->draw(_background);
	_mainWindow.render(*_renderWindow, sf::RenderStates::Default);
}

void MainMenuState::handleEvent(sf::Event& event)
{
	if(event.type == sf::Event::Resized)
		_renderWindow->setView(sf::View(sf::FloatRect(0.0f, 0.0f, event.size.width, event.size.height)));
	_mainWindow.handleEvent(event);
}

void MainMenuState::quitClicked()
{
	_quitClicked = true;
}

} // namespace qrw

<commit_msg>Added missing buttons to main menu.<commit_after>#include "gamestates/mainmenustate.hpp"

#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/BlendMode.hpp>
#include <SFML/Window/Event.hpp>

#include "config/settings.hpp"
#include "gui/texturemanager.hpp"
#include "gui/ng/button.hpp"

namespace qrw
{

MainMenuState::MainMenuState(sf::RenderWindow* renderWindow)
	: GameState(renderWindow, EGameStateId::EGSID_MAIN_MENU_STATE),
	  _quitClicked(false),
	  _mainWindow()
{
	_mainWindow.setSize(sf::Vector2f(145, 204));
	_mainWindow.setRelativePosition(sf::Vector2f(15, 15));

	namelessgui::Button* button;
	sf::Vector2f buttonSize(139, 50);

	button = new namelessgui::Button();
	button->setText("New Match");
	button->setSize(buttonSize);
	button->setParentAnchor({0.5f, 0.01f});
	button->setAnchor({0.5f, 0.0f});
	button->setRelativePosition({0.0f, 0.0f});
	_mainWindow.addWidget(button);

	button = new namelessgui::Button();
	button->setText("Settings");
	button->setSize(buttonSize);
	button->setParentAnchor({0.5f, 0.01f});
	button->setAnchor({0.5f, 0.0f});
	button->setRelativePosition({0.0f, 50.0f});
	_mainWindow.addWidget(button);

	button = new namelessgui::Button();
	button->setText("About");
	button->setSize(buttonSize);
	button->setParentAnchor({0.5f, 0.01f});
	button->setAnchor({0.5f, 0.0f});
	button->setRelativePosition({0.0f, 100.0f});
	_mainWindow.addWidget(button);

	button = new namelessgui::Button();
	button->setText("Quit");
	button->setSize(buttonSize);
	button->signalclicked.connect(std::bind(&MainMenuState::quitClicked, this));
	button->setParentAnchor({0.5f, 0.01f});
	button->setAnchor({0.5f, 0.0f});
	button->setRelativePosition({0.0f, 150.0f});
	_mainWindow.addWidget(button);

	_mainWindow.setVisible(true);
}

void MainMenuState::init(GameState* previousState)
{
	Settings* settings = Settings::getInstance();

	sf::Uint32 style = sf::Style::Default;

	if(settings->getFullscreen())
		style = sf::Style::Fullscreen;

	_renderWindow->create(
		sf::VideoMode(settings->getResolutionX(), settings->getResolutionY()),
		"QRW",
		style
	);

	// Set up textures
	TextureManager* textureManager = TextureManager::getInstance();

	// Set background texture
	_background.setSize(sf::Vector2f(settings->getResolutionX(), settings->getResolutionY()));
	_background.setTexture(textureManager->getTexture("mainmenubackground"));
}

EGameStateId MainMenuState::update()
{
	if(_quitClicked)
		return EGSID_QUIT;
	return EGSID_NO_CHANGE;
}

void MainMenuState::draw()
{
	_renderWindow->draw(_background);
	_mainWindow.render(*_renderWindow, sf::RenderStates::Default);
}

void MainMenuState::handleEvent(sf::Event& event)
{
	if(event.type == sf::Event::Resized)
		_renderWindow->setView(sf::View(sf::FloatRect(0.0f, 0.0f, event.size.width, event.size.height)));
	_mainWindow.handleEvent(event);
}

void MainMenuState::quitClicked()
{
	_quitClicked = true;
}

} // namespace qrw

<|endoftext|>