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

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "CompressIndices.h"

#include <cstring>
#include <algorithm>
#include <Corrade/Containers/Array.h>

#include "Magnum/Math/Functions.h"

namespace Magnum { namespace MeshTools {

namespace {

template<class T> inline Containers::Array<char> compress(const std::vector<UnsignedInt>& indices) {
    Containers::Array<char> buffer(indices.size()*sizeof(T));
    for(std::size_t i = 0; i != indices.size(); ++i) {
        T index = static_cast<T>(indices[i]);
        std::memcpy(buffer.begin()+i*sizeof(T), &index, sizeof(T));
    }

    return buffer;
}

}

std::tuple<Containers::Array<char>, Mesh::IndexType, UnsignedInt, UnsignedInt> compressIndices(const std::vector<UnsignedInt>& indices) {
    /** @todo Performance hint when range can be represented by smaller value? */
    const auto minmax = std::minmax_element(indices.begin(), indices.end());
    Containers::Array<char> data;
    Mesh::IndexType type;
    switch(Math::log(256, *minmax.second)) {
        case 0:
            data = compress<UnsignedByte>(indices);
            type = Mesh::IndexType::UnsignedByte;
            break;
        case 1:
            data = compress<UnsignedShort>(indices);
            type = Mesh::IndexType::UnsignedShort;
            break;
        case 2:
        case 3:
            data = compress<UnsignedInt>(indices);
            type = Mesh::IndexType::UnsignedInt;
            break;

        default:
            CORRADE_ASSERT(false, "MeshTools::compressIndices(): no type able to index" << *minmax.second << "elements.", {});
    }

    return std::make_tuple(std::move(data), type, *minmax.first, *minmax.second);
}

template<class T> Containers::Array<T> compressIndicesAs(const std::vector<UnsignedInt>& indices) {
    #if !defined(CORRADE_NO_ASSERT) || defined(CORRADE_GRACEFUL_ASSERT)
    const auto max = std::max_element(indices.begin(), indices.end());
    CORRADE_ASSERT(Math::log(256, *max) < sizeof(T), "MeshTools::compressIndicesAs(): type too small to represent value" << *max, {});
    #endif

    Containers::Array<T> buffer(indices.size());
    for(std::size_t i = 0; i != indices.size(); ++i)
        buffer[i] = indices[i];

    return buffer;
}

template Containers::Array<UnsignedByte> compressIndicesAs(const std::vector<UnsignedInt>& indices);
template Containers::Array<UnsignedShort> compressIndicesAs(const std::vector<UnsignedInt>& indices);
template Containers::Array<UnsignedInt> compressIndicesAs(const std::vector<UnsignedInt>& indices);

}}
<commit_msg>MeshTools: silence conversion warning on MSVC.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "CompressIndices.h"

#include <cstring>
#include <algorithm>
#include <Corrade/Containers/Array.h>

#include "Magnum/Math/Functions.h"

namespace Magnum { namespace MeshTools {

namespace {

template<class T> inline Containers::Array<char> compress(const std::vector<UnsignedInt>& indices) {
    Containers::Array<char> buffer(indices.size()*sizeof(T));
    for(std::size_t i = 0; i != indices.size(); ++i) {
        T index = static_cast<T>(indices[i]);
        std::memcpy(buffer.begin()+i*sizeof(T), &index, sizeof(T));
    }

    return buffer;
}

}

std::tuple<Containers::Array<char>, Mesh::IndexType, UnsignedInt, UnsignedInt> compressIndices(const std::vector<UnsignedInt>& indices) {
    /** @todo Performance hint when range can be represented by smaller value? */
    const auto minmax = std::minmax_element(indices.begin(), indices.end());
    Containers::Array<char> data;
    Mesh::IndexType type;
    switch(Math::log(256, *minmax.second)) {
        case 0:
            data = compress<UnsignedByte>(indices);
            type = Mesh::IndexType::UnsignedByte;
            break;
        case 1:
            data = compress<UnsignedShort>(indices);
            type = Mesh::IndexType::UnsignedShort;
            break;
        case 2:
        case 3:
            data = compress<UnsignedInt>(indices);
            type = Mesh::IndexType::UnsignedInt;
            break;

        default:
            CORRADE_ASSERT(false, "MeshTools::compressIndices(): no type able to index" << *minmax.second << "elements.", {});
    }

    return std::make_tuple(std::move(data), type, *minmax.first, *minmax.second);
}

template<class T> Containers::Array<T> compressIndicesAs(const std::vector<UnsignedInt>& indices) {
    #if !defined(CORRADE_NO_ASSERT) || defined(CORRADE_GRACEFUL_ASSERT)
    const auto max = std::max_element(indices.begin(), indices.end());
    CORRADE_ASSERT(Math::log(256, *max) < sizeof(T), "MeshTools::compressIndicesAs(): type too small to represent value" << *max, {});
    #endif

    Containers::Array<T> buffer(indices.size());
    for(std::size_t i = 0; i != indices.size(); ++i)
        buffer[i] = T(indices[i]);

    return buffer;
}

template Containers::Array<UnsignedByte> compressIndicesAs(const std::vector<UnsignedInt>& indices);
template Containers::Array<UnsignedShort> compressIndicesAs(const std::vector<UnsignedInt>& indices);
template Containers::Array<UnsignedInt> compressIndicesAs(const std::vector<UnsignedInt>& indices);

}}
<|endoftext|>


<commit_before>//=============================================================================================================
/**
* @file     main.cpp
* @author   Lorenz Esch <lorenz.esch@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     April, 2019
*
* @section  LICENSE
*
* Copyright (C) 2019, Lorenz Esch and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Example of using the MNE-CPP Connectivity library
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <connectivity/connectivity.h>
#include <connectivity/connectivitysettings.h>
#include <connectivity/network/network.h>
#include <connectivity/metrics/abstractmetric.h>

#include <fiff/fiff_raw_data.h>

#include <utils/ioutils.h>

#include <mne/mne_epoch_data_list.h>
#include <mne/mne.h>

#include <stdio.h>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QDebug>
#include <QFile>
#include <QDateTime>
#include <QDir>
#include <QCoreApplication>
#include <QHostInfo>
#include <QElapsedTimer>
#include <QThreadPool>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace Eigen;
using namespace FIFFLIB;
using namespace CONNECTIVITYLIB;
using namespace Eigen;
using namespace UTILSLIB;
using namespace MNELIB;

//*************************************************************************************************************
//=============================================================================================================
// Global Defines
//=============================================================================================================

QString m_sCurrentDir;
int m_iCurrentIteration = 0;
int m_iNumberTrials;
int m_iNumberChannels;
int m_iNumberSamples;

void customMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    Q_UNUSED(context);

    QString dt = QDateTime::currentDateTime().toString("dd/MM/yyyy hh:mm:ss");
    QString txt;// = QString("[%1] ").arg(dt);

    bool writeToLog = false;

    switch (type) {
        case QtWarningMsg:
            //txt += QString("{Warning} \t %1").arg(msg);
            txt += QString("%1").arg(msg);
            writeToLog=true;
            break;
    }

    if(!writeToLog) {
        return;
    }

    QString sFileName = m_sCurrentDir + "/" + QString::number(m_iNumberChannels) + "_" + QString::number(m_iNumberSamples) + "_" + QString::number(m_iNumberTrials) + ".log";

    QFile outFile(sFileName);
    outFile.open(QIODevice::WriteOnly | QIODevice::Append);

    QTextStream textStream(&outFile);
    textStream << txt << endl;
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

//=============================================================================================================
/**
* The function main marks the entry point of the program.
* By default, main has the storage class extern.
*
* @param [in] argc (argument count) is an integer that indicates how many arguments were entered on the command line when the program was started.
* @param [in] argv (argument vector) is an array of pointers to arrays of character objects. The array objects are null-terminated strings, representing the arguments that were entered on the command line when the program was started.
* @return the value that was set to exit() (which is 0 if exit() is called via quit()).
*/
int main(int argc, char *argv[])
{
    qInstallMessageHandler(customMessageHandler);

//    printf("globalInstance()->maxThreadCount(): %d\n",QThreadPool::globalInstance()->maxThreadCount());
//    QThreadPool::globalInstance()->setMaxThreadCount(24);

    //Parameters for performance test
    QStringList sConnectivityMethodList = QStringList() << "COR" << "XCOR" << "COH" << "IMAGCOH" << "PLI" << "WPLI" << "USPLI" << "DSWPLI" << "PLV";
    QList<int> lNumberTrials = QList<int>() << 1 << 5 << 10 << 20 << 50 << 100 << 200;
    QList<int> lNumberChannels = QList<int>() << 32 << 64 << 128 << 256;
    QList<int> lNumberSamples = QList<int>() << 100 << 200 << 300 << 400 << 500 << 600 << 700 << 800 << 900 << 1000 << 2000 << 3000 << 4000 << 5000 << 6000 << 7000 << 8000 << 9000 << 10000 << 20000 << 30000 << 40000 << 50000 << 60000 << 70000 << 80000 << 90000 << 100000;

    int iNumberRepeats = 5;
    int iStorageModeActive = 0;

    AbstractMetric::m_bStorageModeIsActive = iStorageModeActive;
    AbstractMetric::m_iNumberBinStart = 8;
    AbstractMetric::m_iNumberBinAmount = 4;

    // Create sensor level data
    QElapsedTimer timer;
    qint64 iTime = 0;
    timer.start();

    QString sRaw = "/cluster/fusion/lesch/Git/mne-cpp-lorenze/bin/MNE-sample-data/MEG/sample/sample_audvis_raw.fif";
    MatrixXd matDataOrig, matData;
    MatrixXd times;
    QFile t_fileRaw(sRaw);
    FiffRawData raw(t_fileRaw);

    raw.read_raw_segment(matDataOrig, times, raw.first_samp, raw.first_samp+100001);

    //Perform connectivity performance tests
    Connectivity connectivityObj;

    ConnectivitySettings connectivitySettings;
    connectivitySettings.setSamplingFrequency(raw.info.sfreq);
    connectivitySettings.setWindowType("hanning");

    QMap<int, QMap<int, MatrixXd > > matInputData;

    for(int j = 0; j < lNumberChannels.size(); ++j) {
        QMap<int, MatrixXd > mapChannelsSamples;

        for(int i = 0; i < lNumberSamples.size(); ++i) {
            mapChannelsSamples[lNumberSamples.at(i)] = matDataOrig.block(0,0,lNumberChannels.at(j), lNumberSamples.at(i));
        }

        matInputData[lNumberChannels.at(j)] = mapChannelsSamples;
    }

    iTime = timer.elapsed();
    printf("Prepare data %d\n", iTime);
    timer.restart();

    qWarning() << "matInputData[256][40000].first().rows()" << matInputData[256][40000].rows();
    qWarning() << "matInputData[256][40000].first().cols()" << matInputData[256][40000].cols();
    qWarning() << "matInputData[32][500].rows()" << matInputData[32][500].rows();
    qWarning() << "matInputData[32][500].cols()" << matInputData[32][500].cols();
    qWarning() << "matInputData[64][100000].rows()" << matInputData[64][100000].rows();
    qWarning() << "matInputData[64][100000].cols()" << matInputData[64][100000].cols();

    for(int j = 0; j < lNumberSamples.size(); ++j) {
        for(int k = 0; k < lNumberChannels.size(); ++k) {
            connectivitySettings.clearAllData();

            matData = matInputData[lNumberChannels.at(k)][lNumberSamples.at(j)];

            RowVectorXi picks = RowVectorXi::LinSpaced(lNumberChannels.at(k),1,lNumberChannels.at(k)+1);
            connectivitySettings.setNodePositions(raw.info, picks);

            for(int l = 0; l < lNumberTrials.size(); ++l) {
                //Create data to work on

                while(connectivitySettings.size() < lNumberTrials.at(l)) {
                    connectivitySettings.append(matData);
                }

                for(int i = 0; i < sConnectivityMethodList.size(); ++i) {
                    m_iNumberTrials = lNumberTrials.at(l);
                    m_iNumberChannels = lNumberChannels.at(k);
                    m_iNumberSamples = lNumberSamples.at(j);

                    //Create new folder
                    m_sCurrentDir = QString("/cluster/fusion/lesch/connectivity_performance_%1_%2_%3/%4/%5_%6_%7").arg(QHostInfo::localHostName()).arg(AbstractMetric::m_iNumberBinAmount).arg(iStorageModeActive).arg(sConnectivityMethodList.at(i)).arg(QString::number(lNumberChannels.at(k))).arg(QString::number(lNumberSamples.at(j))).arg(QString::number(lNumberTrials.at(l)));
                    QDir().mkpath(m_sCurrentDir);

                    //Write basic information to file
                    qWarning() << "sConnectivityMethod" << sConnectivityMethodList.at(i);
                    qWarning() << "sRaw" << sRaw;
                    qWarning() << "storageModeActive" << iStorageModeActive;
                    qWarning() << "iNumberSamples" << lNumberSamples.at(j);
                    qWarning() << "iNumberChannels" << lNumberChannels.at(k);
                    qWarning() << "iNumberTrials" << lNumberTrials.at(l);
                    qWarning() << "iNumberCSDFreqBins" << AbstractMetric::m_iNumberBinAmount;
                    qWarning() << "rows" << matData.rows();
                    qWarning() << "cols" << matData.cols();
                    qWarning() << "numberNodes" << connectivitySettings.getNodePositions().rows();

                    // Check that iNfft >= signal length
                    int iSignalLength = lNumberSamples.at(j);
                    int iNfft = int(raw.info.sfreq/1.0);
                    if(iNfft > iSignalLength) {
                        iNfft = iSignalLength;
                    }

                    qWarning() << "iNfft" << iNfft;

                    int iNFreqs = int(floor(iNfft / 2.0)) + 1;
                    qWarning() << "iNFreqs" << iNFreqs;

                    connectivitySettings.setConnectivityMethods(QStringList() << sConnectivityMethodList.at(i));

                    m_iCurrentIteration = 0;
                    for(int u = 0; u < iNumberRepeats; ++u) {
                        connectivitySettings.clearIntermediateData();

                        qWarning() << "iteration" << m_iCurrentIteration;

                        //Do connectivity estimation
                        connectivityObj.calculate(connectivitySettings);

                        printf("Iteration %d: Calculating %s for %d trials, %d channels, %d samples\n", m_iCurrentIteration, sConnectivityMethodList.at(i).toLatin1().data(), connectivitySettings.size(), lNumberChannels.at(k), lNumberSamples.at(j));

                        m_iCurrentIteration++;
                    }
                }
            }
        }
    }

    return 0;
}
<commit_msg>changed printf to qDebug for var of type long long<commit_after>//=============================================================================================================
/**
* @file     main.cpp
* @author   Lorenz Esch <lorenz.esch@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     April, 2019
*
* @section  LICENSE
*
* Copyright (C) 2019, Lorenz Esch and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Example of using the MNE-CPP Connectivity library
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <connectivity/connectivity.h>
#include <connectivity/connectivitysettings.h>
#include <connectivity/network/network.h>
#include <connectivity/metrics/abstractmetric.h>

#include <fiff/fiff_raw_data.h>

#include <utils/ioutils.h>

#include <mne/mne_epoch_data_list.h>
#include <mne/mne.h>

#include <stdio.h>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QDebug>
#include <QFile>
#include <QDateTime>
#include <QDir>
#include <QCoreApplication>
#include <QHostInfo>
#include <QElapsedTimer>
#include <QThreadPool>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace Eigen;
using namespace FIFFLIB;
using namespace CONNECTIVITYLIB;
using namespace Eigen;
using namespace UTILSLIB;
using namespace MNELIB;

//*************************************************************************************************************
//=============================================================================================================
// Global Defines
//=============================================================================================================

QString m_sCurrentDir;
int m_iCurrentIteration = 0;
int m_iNumberTrials;
int m_iNumberChannels;
int m_iNumberSamples;

void customMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    Q_UNUSED(context);

    QString dt = QDateTime::currentDateTime().toString("dd/MM/yyyy hh:mm:ss");
    QString txt;// = QString("[%1] ").arg(dt);

    bool writeToLog = false;

    switch (type) {
        case QtWarningMsg:
            //txt += QString("{Warning} \t %1").arg(msg);
            txt += QString("%1").arg(msg);
            writeToLog=true;
            break;
    }

    if(!writeToLog) {
        return;
    }

    QString sFileName = m_sCurrentDir + "/" + QString::number(m_iNumberChannels) + "_" + QString::number(m_iNumberSamples) + "_" + QString::number(m_iNumberTrials) + ".log";

    QFile outFile(sFileName);
    outFile.open(QIODevice::WriteOnly | QIODevice::Append);

    QTextStream textStream(&outFile);
    textStream << txt << endl;
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

//=============================================================================================================
/**
* The function main marks the entry point of the program.
* By default, main has the storage class extern.
*
* @param [in] argc (argument count) is an integer that indicates how many arguments were entered on the command line when the program was started.
* @param [in] argv (argument vector) is an array of pointers to arrays of character objects. The array objects are null-terminated strings, representing the arguments that were entered on the command line when the program was started.
* @return the value that was set to exit() (which is 0 if exit() is called via quit()).
*/
int main(int argc, char *argv[])
{
    qInstallMessageHandler(customMessageHandler);

//    printf("globalInstance()->maxThreadCount(): %d\n",QThreadPool::globalInstance()->maxThreadCount());
//    QThreadPool::globalInstance()->setMaxThreadCount(24);

    //Parameters for performance test
    QStringList sConnectivityMethodList = QStringList() << "COR" << "XCOR" << "COH" << "IMAGCOH" << "PLI" << "WPLI" << "USPLI" << "DSWPLI" << "PLV";
    QList<int> lNumberTrials = QList<int>() << 1 << 5 << 10 << 20 << 50 << 100 << 200;
    QList<int> lNumberChannels = QList<int>() << 32 << 64 << 128 << 256;
    QList<int> lNumberSamples = QList<int>() << 100 << 200 << 300 << 400 << 500 << 600 << 700 << 800 << 900 << 1000 << 2000 << 3000 << 4000 << 5000 << 6000 << 7000 << 8000 << 9000 << 10000 << 20000 << 30000 << 40000 << 50000 << 60000 << 70000 << 80000 << 90000 << 100000;

    int iNumberRepeats = 5;
    int iStorageModeActive = 0;

    AbstractMetric::m_bStorageModeIsActive = iStorageModeActive;
    AbstractMetric::m_iNumberBinStart = 8;
    AbstractMetric::m_iNumberBinAmount = 4;

    // Create sensor level data
    QElapsedTimer timer;
    qint64 iTime = 0;
    timer.start();

    QString sRaw = "/cluster/fusion/lesch/Git/mne-cpp-lorenze/bin/MNE-sample-data/MEG/sample/sample_audvis_raw.fif";
    MatrixXd matDataOrig, matData;
    MatrixXd times;
    QFile t_fileRaw(sRaw);
    FiffRawData raw(t_fileRaw);

    raw.read_raw_segment(matDataOrig, times, raw.first_samp, raw.first_samp+100001);

    //Perform connectivity performance tests
    Connectivity connectivityObj;

    ConnectivitySettings connectivitySettings;
    connectivitySettings.setSamplingFrequency(raw.info.sfreq);
    connectivitySettings.setWindowType("hanning");

    QMap<int, QMap<int, MatrixXd > > matInputData;

    for(int j = 0; j < lNumberChannels.size(); ++j) {
        QMap<int, MatrixXd > mapChannelsSamples;

        for(int i = 0; i < lNumberSamples.size(); ++i) {
            mapChannelsSamples[lNumberSamples.at(i)] = matDataOrig.block(0,0,lNumberChannels.at(j), lNumberSamples.at(i));
        }

        matInputData[lNumberChannels.at(j)] = mapChannelsSamples;
    }

    iTime = timer.elapsed();
    qDebug() << "Prepare data " << iTime;
    timer.restart();

    qWarning() << "matInputData[256][40000].first().rows()" << matInputData[256][40000].rows();
    qWarning() << "matInputData[256][40000].first().cols()" << matInputData[256][40000].cols();
    qWarning() << "matInputData[32][500].rows()" << matInputData[32][500].rows();
    qWarning() << "matInputData[32][500].cols()" << matInputData[32][500].cols();
    qWarning() << "matInputData[64][100000].rows()" << matInputData[64][100000].rows();
    qWarning() << "matInputData[64][100000].cols()" << matInputData[64][100000].cols();

    for(int j = 0; j < lNumberSamples.size(); ++j) {
        for(int k = 0; k < lNumberChannels.size(); ++k) {
            connectivitySettings.clearAllData();

            matData = matInputData[lNumberChannels.at(k)][lNumberSamples.at(j)];

            RowVectorXi picks = RowVectorXi::LinSpaced(lNumberChannels.at(k),1,lNumberChannels.at(k)+1);
            connectivitySettings.setNodePositions(raw.info, picks);

            for(int l = 0; l < lNumberTrials.size(); ++l) {
                //Create data to work on

                while(connectivitySettings.size() < lNumberTrials.at(l)) {
                    connectivitySettings.append(matData);
                }

                for(int i = 0; i < sConnectivityMethodList.size(); ++i) {
                    m_iNumberTrials = lNumberTrials.at(l);
                    m_iNumberChannels = lNumberChannels.at(k);
                    m_iNumberSamples = lNumberSamples.at(j);

                    //Create new folder
                    m_sCurrentDir = QString("/cluster/fusion/lesch/connectivity_performance_%1_%2_%3/%4/%5_%6_%7").arg(QHostInfo::localHostName()).arg(AbstractMetric::m_iNumberBinAmount).arg(iStorageModeActive).arg(sConnectivityMethodList.at(i)).arg(QString::number(lNumberChannels.at(k))).arg(QString::number(lNumberSamples.at(j))).arg(QString::number(lNumberTrials.at(l)));
                    QDir().mkpath(m_sCurrentDir);

                    //Write basic information to file
                    qWarning() << "sConnectivityMethod" << sConnectivityMethodList.at(i);
                    qWarning() << "sRaw" << sRaw;
                    qWarning() << "storageModeActive" << iStorageModeActive;
                    qWarning() << "iNumberSamples" << lNumberSamples.at(j);
                    qWarning() << "iNumberChannels" << lNumberChannels.at(k);
                    qWarning() << "iNumberTrials" << lNumberTrials.at(l);
                    qWarning() << "iNumberCSDFreqBins" << AbstractMetric::m_iNumberBinAmount;
                    qWarning() << "rows" << matData.rows();
                    qWarning() << "cols" << matData.cols();
                    qWarning() << "numberNodes" << connectivitySettings.getNodePositions().rows();

                    // Check that iNfft >= signal length
                    int iSignalLength = lNumberSamples.at(j);
                    int iNfft = int(raw.info.sfreq/1.0);
                    if(iNfft > iSignalLength) {
                        iNfft = iSignalLength;
                    }

                    qWarning() << "iNfft" << iNfft;

                    int iNFreqs = int(floor(iNfft / 2.0)) + 1;
                    qWarning() << "iNFreqs" << iNFreqs;

                    connectivitySettings.setConnectivityMethods(QStringList() << sConnectivityMethodList.at(i));

                    m_iCurrentIteration = 0;
                    for(int u = 0; u < iNumberRepeats; ++u) {
                        connectivitySettings.clearIntermediateData();

                        qWarning() << "iteration" << m_iCurrentIteration;

                        //Do connectivity estimation
                        connectivityObj.calculate(connectivitySettings);

                        printf("Iteration %d: Calculating %s for %d trials, %d channels, %d samples\n", m_iCurrentIteration, sConnectivityMethodList.at(i).toLatin1().data(), connectivitySettings.size(), lNumberChannels.at(k), lNumberSamples.at(j));

                        m_iCurrentIteration++;
                    }
                }
            }
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 * [ Copyright (C) 2011 August Sodora <augsod@gmail.com> (initial developer) ]
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */

#include "baside2.hxx"
#include "linenumberwindow.hxx"

#include <vcl/xtextedt.hxx>
#include <vcl/textview.hxx>

namespace basctl
{

LineNumberWindow::LineNumberWindow (Window* pParent, ModulWindow* pModulWindow) :
    Window(pParent, WB_BORDER),
    m_pModulWindow(pModulWindow),
    m_nCurYOffset(0)
{
    SetBackground(Wallpaper(GetSettings().GetStyleSettings().GetFieldColor()));
    m_nBaseWidth = GetTextWidth('8');
    m_nWidth = m_nBaseWidth * 3 + m_nBaseWidth / 2;
}

LineNumberWindow::~LineNumberWindow()
{ }

void LineNumberWindow::Paint( const Rectangle& )
{
    if(SyncYOffset())
        return;

    ExtTextEngine* txtEngine = m_pModulWindow->GetEditEngine();
    if(!txtEngine)
        return;

    TextView* txtView = m_pModulWindow->GetEditView();
    if(!txtView)
        return;

    GetParent()->Resize();

    int windowHeight = GetOutputSize().Height();
    int nLineHeight = GetTextHeight();

    int startY = txtView->GetStartDocPos().Y();
    int nStartLine = startY / nLineHeight + 1;
    int nEndLine = (startY + windowHeight) / nLineHeight + 1;

    if(txtEngine->GetParagraphCount() + 1 < (unsigned int)nEndLine)
        nEndLine = txtEngine->GetParagraphCount() + 1;

    // FIXME: it would be best if we could get notified of a font change
    // rather than doing that re-calculation at each Paint event
    m_nBaseWidth = GetTextWidth(OUString('8'));

    // reserve enough for 3 sigit minimum, with a bit to spare for confort
    m_nWidth = m_nBaseWidth * 3 + m_nBaseWidth / 2;
    int i = (nEndLine + 1) / 1000;
    while(i)
    {
        i /= 10;
        m_nWidth += m_nBaseWidth;
    }

    sal_Int64 y = (nStartLine - 1) * nLineHeight;
    for(sal_Int32 n = nStartLine; n <= nEndLine; ++n, y += nLineHeight)
        DrawText(Point(0, y - m_nCurYOffset), OUString::valueOf(n));
}

void LineNumberWindow::DataChanged(DataChangedEvent const & rDCEvt)
{
    Window::DataChanged(rDCEvt);
    if (rDCEvt.GetType() == DATACHANGED_SETTINGS
        && (rDCEvt.GetFlags() & SETTINGS_STYLE) != 0)
    {
        Color aColor(GetSettings().GetStyleSettings().GetFieldColor());
        const AllSettings* pOldSettings = rDCEvt.GetOldSettings();
        if (!pOldSettings || aColor != pOldSettings->GetStyleSettings().GetFieldColor())
        {
            SetBackground(Wallpaper(aColor));
            Invalidate();
        }
    }
}

void LineNumberWindow::DoScroll(long nHorzScroll, long nVertScroll)
{
    m_nCurYOffset -= nVertScroll;
    Window::Scroll(nHorzScroll, nVertScroll);
}

long& LineNumberWindow::GetCurYOffset()
{
    return m_nCurYOffset;
}

bool LineNumberWindow::SyncYOffset()
{
    TextView* pView = m_pModulWindow->GetEditView();
    if (!pView)
        return false;

    long nViewYOffset = pView->GetStartDocPos().Y();
    if (m_nCurYOffset == nViewYOffset)
        return false;

    m_nCurYOffset = nViewYOffset;
    Invalidate();
    return true;
}

int LineNumberWindow::GetWidth()
{
    return m_nWidth;
}

} // namespace basctl

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#735601 coverity#736164<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License or as specified alternatively below. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Major Contributor(s):
 * [ Copyright (C) 2011 August Sodora <augsod@gmail.com> (initial developer) ]
 *
 * All Rights Reserved.
 *
 * For minor contributions see the git repository.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */

#include "baside2.hxx"
#include "linenumberwindow.hxx"

#include <vcl/xtextedt.hxx>
#include <vcl/textview.hxx>

namespace basctl
{

LineNumberWindow::LineNumberWindow (Window* pParent, ModulWindow* pModulWindow) :
    Window(pParent, WB_BORDER),
    m_pModulWindow(pModulWindow),
    m_nCurYOffset(0)
{
    SetBackground(Wallpaper(GetSettings().GetStyleSettings().GetFieldColor()));
    m_nBaseWidth = GetTextWidth('8');
    m_nWidth = m_nBaseWidth * 3 + m_nBaseWidth / 2;
}

LineNumberWindow::~LineNumberWindow()
{ }

void LineNumberWindow::Paint( const Rectangle& )
{
    if(SyncYOffset())
        return;

    ExtTextEngine* txtEngine = m_pModulWindow->GetEditEngine();
    if(!txtEngine)
        return;

    TextView* txtView = m_pModulWindow->GetEditView();
    if(!txtView)
        return;

    GetParent()->Resize();

    int windowHeight = GetOutputSize().Height();
    int nLineHeight = GetTextHeight();
    if(!nLineHeight)
    {
        return;
    }

    int startY = txtView->GetStartDocPos().Y();
    int nStartLine = startY / nLineHeight + 1;
    int nEndLine = (startY + windowHeight) / nLineHeight + 1;

    if(txtEngine->GetParagraphCount() + 1 < (unsigned int)nEndLine)
        nEndLine = txtEngine->GetParagraphCount() + 1;

    // FIXME: it would be best if we could get notified of a font change
    // rather than doing that re-calculation at each Paint event
    m_nBaseWidth = GetTextWidth(OUString('8'));

    // reserve enough for 3 sigit minimum, with a bit to spare for confort
    m_nWidth = m_nBaseWidth * 3 + m_nBaseWidth / 2;
    int i = (nEndLine + 1) / 1000;
    while(i)
    {
        i /= 10;
        m_nWidth += m_nBaseWidth;
    }

    sal_Int64 y = (nStartLine - 1) * (sal_Int64)nLineHeight;
    for(sal_Int32 n = nStartLine; n <= nEndLine; ++n, y += nLineHeight)
        DrawText(Point(0, y - m_nCurYOffset), OUString::valueOf(n));
}

void LineNumberWindow::DataChanged(DataChangedEvent const & rDCEvt)
{
    Window::DataChanged(rDCEvt);
    if (rDCEvt.GetType() == DATACHANGED_SETTINGS
        && (rDCEvt.GetFlags() & SETTINGS_STYLE) != 0)
    {
        Color aColor(GetSettings().GetStyleSettings().GetFieldColor());
        const AllSettings* pOldSettings = rDCEvt.GetOldSettings();
        if (!pOldSettings || aColor != pOldSettings->GetStyleSettings().GetFieldColor())
        {
            SetBackground(Wallpaper(aColor));
            Invalidate();
        }
    }
}

void LineNumberWindow::DoScroll(long nHorzScroll, long nVertScroll)
{
    m_nCurYOffset -= nVertScroll;
    Window::Scroll(nHorzScroll, nVertScroll);
}

long& LineNumberWindow::GetCurYOffset()
{
    return m_nCurYOffset;
}

bool LineNumberWindow::SyncYOffset()
{
    TextView* pView = m_pModulWindow->GetEditView();
    if (!pView)
        return false;

    long nViewYOffset = pView->GetStartDocPos().Y();
    if (m_nCurYOffset == nViewYOffset)
        return false;

    m_nCurYOffset = nViewYOffset;
    Invalidate();
    return true;
}

int LineNumberWindow::GetWidth()
{
    return m_nWidth;
}

} // namespace basctl

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008 James Molloy, Jörg Pfähler, Matthew Iselin
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "Ext2Node.h"
#include "Ext2Filesystem.h"
#include <utilities/assert.h>
#include <syscallError.h>

Ext2Node::Ext2Node(uintptr_t inode_num, Inode *pInode, Ext2Filesystem *pFs) :
    m_pInode(pInode), m_InodeNumber(inode_num), m_pExt2Fs(pFs), m_pBlocks(0),
    m_nBlocks(LITTLE_TO_HOST32(pInode->i_blocks)), m_nSize(LITTLE_TO_HOST32(pInode->i_size))
{
    m_pBlocks = new uint32_t[m_nBlocks];
    memset(m_pBlocks, ~0, sizeof(uint32_t)*m_nBlocks);

    for (size_t i = 0; i < 12 && i < m_nBlocks; i++)
        m_pBlocks[i] = LITTLE_TO_HOST32(m_pInode->i_block[i]);
}

Ext2Node::~Ext2Node()
{
}

uint64_t Ext2Node::read(uint64_t location, uint64_t size, uintptr_t buffer)
{
    // Reads get clamped to the filesize.
    if (location >= m_nSize) return 0;
    if ( (location+size) >= m_nSize) size = m_nSize - location;

    if (size == 0) return 0;

    // Special case for symlinks - if we have no blocks but have positive size,
    // We interpret the i_blocks member as data.
    if (m_pInode->i_blocks == 0 && m_nSize > 0)
    {
        memcpy(reinterpret_cast<uint8_t*>(buffer+location),
               reinterpret_cast<uint8_t*>(m_pInode->i_block),
               size);
        return size;
    }

    size_t nBs = m_pExt2Fs->m_BlockSize;

    size_t nBytes = size;
    uint32_t nBlock = location / nBs;
    while (nBytes)
    {
        // If the current location is block-aligned and we have to read at least a
        // block in, we can read directly to the buffer.
        if ( (location % nBs) == 0 && nBytes >= nBs )
        {
            ensureBlockLoaded(nBlock);
            uintptr_t buf = m_pExt2Fs->readBlock(m_pBlocks[nBlock]);
            memcpy(reinterpret_cast<uint8_t*>(buffer),
                   reinterpret_cast<uint8_t*>(buf),
                   nBs);
            buffer += nBs;
            location += nBs;
            nBytes -= nBs;
            nBlock++;
        }
        // Else we have to read in a partial block.
        else
        {
            // Create a buffer for the block.
            ensureBlockLoaded(nBlock);
            uintptr_t buf = m_pExt2Fs->readBlock(m_pBlocks[nBlock]);
            // memcpy the relevant block area.
            uintptr_t start = location % nBs;
            uintptr_t size = (start+nBytes >= nBs) ? nBs-start : nBytes;
            memcpy(reinterpret_cast<uint8_t*>(buffer),
                   reinterpret_cast<uint8_t*>(buf+start),
                   size);
            buffer += size;
            location += size;
            nBytes -= size;
            nBlock++;
        }
    }

    return size;
}

uint64_t Ext2Node::write(uint64_t location, uint64_t size, uintptr_t buffer)
{
    ensureLargeEnough(location+size);

    size_t nBs = m_pExt2Fs->m_BlockSize;

    size_t nBytes = size;
    uint32_t nBlock = location / nBs;
    while (nBytes)
    {
        // If the current location is block-aligned and we have to write at least a
        // block out, we can write directly to the buffer.
        if ( (location % nBs) == 0 && nBytes >= nBs )
        {
            ensureBlockLoaded(nBlock);
            uintptr_t buf = m_pExt2Fs->readBlock(m_pBlocks[nBlock]);
            memcpy(reinterpret_cast<uint8_t*>(buf),
                   reinterpret_cast<uint8_t*>(buffer),
                   nBs);
            buffer += nBs;
            location += nBs;
            nBytes -= nBs;
            nBlock++;
        }
        // Else we have to read in a block, partially edit it and write back.
        else
        {
            // Create a buffer for the block.
            ensureBlockLoaded(nBlock);
            uintptr_t buf = m_pExt2Fs->readBlock(m_pBlocks[nBlock]);
            // memcpy the relevant block area.
            uintptr_t start = location % nBs;
            uintptr_t size = (start+nBytes >= nBs) ? nBs-start : nBytes;
            memcpy(reinterpret_cast<uint8_t*>(buf+start),
                   reinterpret_cast<uint8_t*>(buffer), size);
            buffer += size;
            location += size;
            nBytes -= size;
            nBlock++;
        }
    }

    return size;
}

uintptr_t Ext2Node::readBlock(uint64_t location)
{
    ensureLargeEnough(location+m_pExt2Fs->m_BlockSize);

    size_t nBs = m_pExt2Fs->m_BlockSize;

    uint32_t nBlock = location / nBs;

    ensureBlockLoaded(nBlock);
    return m_pExt2Fs->readBlock(m_pBlocks[nBlock]);
}

void Ext2Node::truncate()
{
    for (size_t i = 0; i < m_nBlocks; i++)
    {
        ensureBlockLoaded(i);
        m_pExt2Fs->releaseBlock(m_pBlocks[i]);
    }

    m_nSize = 0;
    m_nBlocks = 0;

    m_pInode->i_size = 0;
    m_pInode->i_blocks = 0;
}

bool Ext2Node::ensureLargeEnough(size_t size)
{
    if (size > m_nSize)
    {
        m_nSize = size;
        fileAttributeChanged(m_nSize, LITTLE_TO_HOST32(m_pInode->i_atime),
                             LITTLE_TO_HOST32(m_pInode->i_mtime),
                             LITTLE_TO_HOST32(m_pInode->i_ctime));
    }

    while (size > m_nBlocks*m_pExt2Fs->m_BlockSize)
    {
        uint32_t block = m_pExt2Fs->findFreeBlock(m_InodeNumber);
        if (block == 0)
        {
            // We had a problem.
            SYSCALL_ERROR(NoSpaceLeftOnDevice);
            return false;
        }
        if (!addBlock(block)) return false;
        // Load the block and zero it.
        uint8_t *pBuffer = reinterpret_cast<uint8_t*>(m_pExt2Fs->readBlock(block));
        memset(pBuffer, 0, m_pExt2Fs->m_BlockSize);
    }
    return true;
}

bool Ext2Node::ensureBlockLoaded(size_t nBlock)
{
    if (nBlock >= m_nBlocks)
    {
        FATAL("EXT2: ensureBlockLoaded: Algorithmic error.");
    }
    if (m_pBlocks[nBlock] == ~0U)
        getBlockNumber(nBlock);

    return true;
}

bool Ext2Node::getBlockNumber(size_t nBlock)
{
    size_t nPerBlock = m_pExt2Fs->m_BlockSize/4;

    assert (nBlock >= 12);

    if (nBlock < nPerBlock+12)
    {
        getBlockNumberIndirect(LITTLE_TO_HOST32(m_pInode->i_block[12]), 12, nBlock);
        return true;
    }

    if (nBlock < (nPerBlock*nPerBlock)+nPerBlock+12)
    {
        getBlockNumberBiindirect(LITTLE_TO_HOST32(m_pInode->i_block[13]), nPerBlock+12, nBlock);
        return true;
    }

    getBlockNumberTriindirect(LITTLE_TO_HOST32(m_pInode->i_block[14]),
                              (nPerBlock*nPerBlock)+nPerBlock+12, nBlock);

    return true;
}

bool Ext2Node::getBlockNumberIndirect(uint32_t inode_block, size_t nBlocks, size_t nBlock)
{
    uint32_t *buffer = reinterpret_cast<uint32_t*>(m_pExt2Fs->readBlock(inode_block));

    for (size_t i = 0; i < m_pExt2Fs->m_BlockSize/4 && nBlocks < m_nBlocks; i++)
    {
        m_pBlocks[nBlocks++] = LITTLE_TO_HOST32(buffer[i]);
    }

    return true;
}

bool Ext2Node::getBlockNumberBiindirect(uint32_t inode_block, size_t nBlocks, size_t nBlock)
{
    size_t nPerBlock = m_pExt2Fs->m_BlockSize/4;

    uint32_t *buffer = reinterpret_cast<uint32_t*>(m_pExt2Fs->readBlock(inode_block));

    // What indirect block does nBlock exist on?
    size_t nIndirectBlock = (nBlock-nBlocks) / nPerBlock;

    getBlockNumberIndirect(LITTLE_TO_HOST32(buffer[nIndirectBlock]),
                           nBlocks+nIndirectBlock*nPerBlock, nBlock);

    return true;
}

bool Ext2Node::getBlockNumberTriindirect(uint32_t inode_block, size_t nBlocks, size_t nBlock)
{
    size_t nPerBlock = m_pExt2Fs->m_BlockSize/4;

    uint32_t *buffer = reinterpret_cast<uint32_t*>(m_pExt2Fs->readBlock(inode_block));

    // What biindirect block does nBlock exist on?
    size_t nBiBlock = (nBlock-nBlocks) / (nPerBlock*nPerBlock);

    getBlockNumberBiindirect(LITTLE_TO_HOST32(buffer[nBiBlock]),
                             nBlocks+nBiBlock*nPerBlock*nPerBlock, nBlock);

    delete [] buffer;

    return true;
}

bool Ext2Node::addBlock(uint32_t blockValue)
{
    size_t nEntriesPerBlock = m_pExt2Fs->m_BlockSize/4;

    // Calculate whether direct, indirect or tri-indirect addressing is needed.
    if (m_nBlocks < 12)
    {
        // Direct addressing is possible.
        m_pInode->i_block[m_nBlocks] = HOST_TO_LITTLE32(blockValue);
    }
    else if (m_nBlocks < 12 + nEntriesPerBlock)
    {
        // Indirect addressing needed.

        // If this is the first indirect block, we need to reserve a new table block.
        if (m_nBlocks == 12)
        {
            m_pInode->i_block[12] = HOST_TO_LITTLE32(m_pExt2Fs->findFreeBlock(m_InodeNumber));
            if (m_pInode->i_block[12] == 0)
            {
                // We had a problem.
                SYSCALL_ERROR(NoSpaceLeftOnDevice);
                return false;
            }
        }

        // Now we can set the block.
        uint32_t *buffer = reinterpret_cast<uint32_t*>(m_pExt2Fs->readBlock(LITTLE_TO_HOST32(m_pInode->i_block[12])));

        buffer[m_nBlocks-12] = HOST_TO_LITTLE32(blockValue);
    }
    else if (m_nBlocks < 12 + nEntriesPerBlock + nEntriesPerBlock*nEntriesPerBlock)
    {
        // Bi-indirect addressing required.

        // Index from the start of the bi-indirect block (i.e. ignore the 12 direct entries and one indirect block).
        size_t biIdx = m_nBlocks - 12 - nEntriesPerBlock;
        // Block number inside the bi-indirect table of where to find the indirect block table.
        size_t indirectBlock = biIdx / nEntriesPerBlock;
        // Index inside the indirect block table.
        size_t indirectIdx = biIdx % nEntriesPerBlock;

        // If this is the first bi-indirect block, we need to reserve a bi-indirect table block.
        if (biIdx == 0)
        {
            m_pInode->i_block[13] = HOST_TO_LITTLE32(m_pExt2Fs->findFreeBlock(m_InodeNumber));
            if (m_pInode->i_block[13] == 0)
            {
                // We had a problem.
                SYSCALL_ERROR(NoSpaceLeftOnDevice);
                return false;
            }
        }

        // Now we can safely read the bi-indirect block.
        uint32_t *pBlock = reinterpret_cast<uint32_t*>(m_pExt2Fs->readBlock(LITTLE_TO_HOST32(m_pInode->i_block[13])));

        // Do we need to start a new indirect block?
        if (indirectIdx == 0)
        {
            pBlock[indirectBlock] = HOST_TO_LITTLE32(m_pExt2Fs->findFreeBlock(m_InodeNumber));
            if (pBlock[indirectBlock] == 0)
            {
                // We had a problem.
                SYSCALL_ERROR(NoSpaceLeftOnDevice);
                return false;
            }
        }

        // Cache this as it gets clobbered by the readBlock call (using the same buffer).
        uint32_t nIndirectBlockNum = LITTLE_TO_HOST32(pBlock[indirectBlock]);

        // Grab the indirect block.
        pBlock = reinterpret_cast<uint32_t*>(m_pExt2Fs->readBlock(nIndirectBlockNum));

        // Set the correct entry.
        pBlock[indirectIdx] = HOST_TO_LITTLE32(blockValue);

        // Done.
        delete [] pBlock;
    }
    else
    {
        // Tri-indirect addressing required.
        FATAL("EXT2: Tri-indirect addressing required, but not implemented.");
        return false;
    }

    uint32_t *pTmp = new uint32_t[m_nBlocks+1];
    memcpy(pTmp, m_pBlocks, m_nBlocks*4);
    delete [] m_pBlocks;
    m_pBlocks = pTmp;
    m_pBlocks[m_nBlocks] = blockValue;

    m_nBlocks++;
    m_pInode->i_blocks = HOST_TO_LITTLE32(m_nBlocks);

    return true;
}

void Ext2Node::fileAttributeChanged(size_t size, size_t atime, size_t mtime, size_t ctime)
{
    // Reconstruct the inode from the cached fields.
    m_pInode->i_blocks = HOST_TO_LITTLE32(m_nBlocks);
    m_pInode->i_size = HOST_TO_LITTLE32(size); /// \todo 4GB files.
    m_pInode->i_atime = HOST_TO_LITTLE32(atime);
    m_pInode->i_mtime = HOST_TO_LITTLE32(mtime);
    m_pInode->i_ctime = HOST_TO_LITTLE32(ctime);
}
<commit_msg>Commented a line that caused a assertion failed in SlamAllocator when copying some file on a ext2 volume.<commit_after>/*
 * Copyright (c) 2008 James Molloy, Jörg Pfähler, Matthew Iselin
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "Ext2Node.h"
#include "Ext2Filesystem.h"
#include <utilities/assert.h>
#include <syscallError.h>

Ext2Node::Ext2Node(uintptr_t inode_num, Inode *pInode, Ext2Filesystem *pFs) :
    m_pInode(pInode), m_InodeNumber(inode_num), m_pExt2Fs(pFs), m_pBlocks(0),
    m_nBlocks(LITTLE_TO_HOST32(pInode->i_blocks)), m_nSize(LITTLE_TO_HOST32(pInode->i_size))
{
    m_pBlocks = new uint32_t[m_nBlocks];
    memset(m_pBlocks, ~0, sizeof(uint32_t)*m_nBlocks);

    for (size_t i = 0; i < 12 && i < m_nBlocks; i++)
        m_pBlocks[i] = LITTLE_TO_HOST32(m_pInode->i_block[i]);
}

Ext2Node::~Ext2Node()
{
}

uint64_t Ext2Node::read(uint64_t location, uint64_t size, uintptr_t buffer)
{
    // Reads get clamped to the filesize.
    if (location >= m_nSize) return 0;
    if ( (location+size) >= m_nSize) size = m_nSize - location;

    if (size == 0) return 0;

    // Special case for symlinks - if we have no blocks but have positive size,
    // We interpret the i_blocks member as data.
    if (m_pInode->i_blocks == 0 && m_nSize > 0)
    {
        memcpy(reinterpret_cast<uint8_t*>(buffer+location),
               reinterpret_cast<uint8_t*>(m_pInode->i_block),
               size);
        return size;
    }

    size_t nBs = m_pExt2Fs->m_BlockSize;

    size_t nBytes = size;
    uint32_t nBlock = location / nBs;
    while (nBytes)
    {
        // If the current location is block-aligned and we have to read at least a
        // block in, we can read directly to the buffer.
        if ( (location % nBs) == 0 && nBytes >= nBs )
        {
            ensureBlockLoaded(nBlock);
            uintptr_t buf = m_pExt2Fs->readBlock(m_pBlocks[nBlock]);
            memcpy(reinterpret_cast<uint8_t*>(buffer),
                   reinterpret_cast<uint8_t*>(buf),
                   nBs);
            buffer += nBs;
            location += nBs;
            nBytes -= nBs;
            nBlock++;
        }
        // Else we have to read in a partial block.
        else
        {
            // Create a buffer for the block.
            ensureBlockLoaded(nBlock);
            uintptr_t buf = m_pExt2Fs->readBlock(m_pBlocks[nBlock]);
            // memcpy the relevant block area.
            uintptr_t start = location % nBs;
            uintptr_t size = (start+nBytes >= nBs) ? nBs-start : nBytes;
            memcpy(reinterpret_cast<uint8_t*>(buffer),
                   reinterpret_cast<uint8_t*>(buf+start),
                   size);
            buffer += size;
            location += size;
            nBytes -= size;
            nBlock++;
        }
    }

    return size;
}

uint64_t Ext2Node::write(uint64_t location, uint64_t size, uintptr_t buffer)
{
    ensureLargeEnough(location+size);

    size_t nBs = m_pExt2Fs->m_BlockSize;

    size_t nBytes = size;
    uint32_t nBlock = location / nBs;
    while (nBytes)
    {
        // If the current location is block-aligned and we have to write at least a
        // block out, we can write directly to the buffer.
        if ( (location % nBs) == 0 && nBytes >= nBs )
        {
            ensureBlockLoaded(nBlock);
            uintptr_t buf = m_pExt2Fs->readBlock(m_pBlocks[nBlock]);
            memcpy(reinterpret_cast<uint8_t*>(buf),
                   reinterpret_cast<uint8_t*>(buffer),
                   nBs);
            buffer += nBs;
            location += nBs;
            nBytes -= nBs;
            nBlock++;
        }
        // Else we have to read in a block, partially edit it and write back.
        else
        {
            // Create a buffer for the block.
            ensureBlockLoaded(nBlock);
            uintptr_t buf = m_pExt2Fs->readBlock(m_pBlocks[nBlock]);
            // memcpy the relevant block area.
            uintptr_t start = location % nBs;
            uintptr_t size = (start+nBytes >= nBs) ? nBs-start : nBytes;
            memcpy(reinterpret_cast<uint8_t*>(buf+start),
                   reinterpret_cast<uint8_t*>(buffer), size);
            buffer += size;
            location += size;
            nBytes -= size;
            nBlock++;
        }
    }

    return size;
}

uintptr_t Ext2Node::readBlock(uint64_t location)
{
    ensureLargeEnough(location+m_pExt2Fs->m_BlockSize);

    size_t nBs = m_pExt2Fs->m_BlockSize;

    uint32_t nBlock = location / nBs;

    ensureBlockLoaded(nBlock);
    return m_pExt2Fs->readBlock(m_pBlocks[nBlock]);
}

void Ext2Node::truncate()
{
    for (size_t i = 0; i < m_nBlocks; i++)
    {
        ensureBlockLoaded(i);
        m_pExt2Fs->releaseBlock(m_pBlocks[i]);
    }

    m_nSize = 0;
    m_nBlocks = 0;

    m_pInode->i_size = 0;
    m_pInode->i_blocks = 0;
}

bool Ext2Node::ensureLargeEnough(size_t size)
{
    if (size > m_nSize)
    {
        m_nSize = size;
        fileAttributeChanged(m_nSize, LITTLE_TO_HOST32(m_pInode->i_atime),
                             LITTLE_TO_HOST32(m_pInode->i_mtime),
                             LITTLE_TO_HOST32(m_pInode->i_ctime));
    }

    while (size > m_nBlocks*m_pExt2Fs->m_BlockSize)
    {
        uint32_t block = m_pExt2Fs->findFreeBlock(m_InodeNumber);
        if (block == 0)
        {
            // We had a problem.
            SYSCALL_ERROR(NoSpaceLeftOnDevice);
            return false;
        }
        if (!addBlock(block)) return false;
        // Load the block and zero it.
        uint8_t *pBuffer = reinterpret_cast<uint8_t*>(m_pExt2Fs->readBlock(block));
        memset(pBuffer, 0, m_pExt2Fs->m_BlockSize);
    }
    return true;
}

bool Ext2Node::ensureBlockLoaded(size_t nBlock)
{
    if (nBlock >= m_nBlocks)
    {
        FATAL("EXT2: ensureBlockLoaded: Algorithmic error.");
    }
    if (m_pBlocks[nBlock] == ~0U)
        getBlockNumber(nBlock);

    return true;
}

bool Ext2Node::getBlockNumber(size_t nBlock)
{
    size_t nPerBlock = m_pExt2Fs->m_BlockSize/4;

    assert (nBlock >= 12);

    if (nBlock < nPerBlock+12)
    {
        getBlockNumberIndirect(LITTLE_TO_HOST32(m_pInode->i_block[12]), 12, nBlock);
        return true;
    }

    if (nBlock < (nPerBlock*nPerBlock)+nPerBlock+12)
    {
        getBlockNumberBiindirect(LITTLE_TO_HOST32(m_pInode->i_block[13]), nPerBlock+12, nBlock);
        return true;
    }

    getBlockNumberTriindirect(LITTLE_TO_HOST32(m_pInode->i_block[14]),
                              (nPerBlock*nPerBlock)+nPerBlock+12, nBlock);

    return true;
}

bool Ext2Node::getBlockNumberIndirect(uint32_t inode_block, size_t nBlocks, size_t nBlock)
{
    uint32_t *buffer = reinterpret_cast<uint32_t*>(m_pExt2Fs->readBlock(inode_block));

    for (size_t i = 0; i < m_pExt2Fs->m_BlockSize/4 && nBlocks < m_nBlocks; i++)
    {
        m_pBlocks[nBlocks++] = LITTLE_TO_HOST32(buffer[i]);
    }

    return true;
}

bool Ext2Node::getBlockNumberBiindirect(uint32_t inode_block, size_t nBlocks, size_t nBlock)
{
    size_t nPerBlock = m_pExt2Fs->m_BlockSize/4;

    uint32_t *buffer = reinterpret_cast<uint32_t*>(m_pExt2Fs->readBlock(inode_block));

    // What indirect block does nBlock exist on?
    size_t nIndirectBlock = (nBlock-nBlocks) / nPerBlock;

    getBlockNumberIndirect(LITTLE_TO_HOST32(buffer[nIndirectBlock]),
                           nBlocks+nIndirectBlock*nPerBlock, nBlock);

    return true;
}

bool Ext2Node::getBlockNumberTriindirect(uint32_t inode_block, size_t nBlocks, size_t nBlock)
{
    size_t nPerBlock = m_pExt2Fs->m_BlockSize/4;

    uint32_t *buffer = reinterpret_cast<uint32_t*>(m_pExt2Fs->readBlock(inode_block));

    // What biindirect block does nBlock exist on?
    size_t nBiBlock = (nBlock-nBlocks) / (nPerBlock*nPerBlock);

    getBlockNumberBiindirect(LITTLE_TO_HOST32(buffer[nBiBlock]),
                             nBlocks+nBiBlock*nPerBlock*nPerBlock, nBlock);

    delete [] buffer;

    return true;
}

bool Ext2Node::addBlock(uint32_t blockValue)
{
    size_t nEntriesPerBlock = m_pExt2Fs->m_BlockSize/4;

    // Calculate whether direct, indirect or tri-indirect addressing is needed.
    if (m_nBlocks < 12)
    {
        // Direct addressing is possible.
        m_pInode->i_block[m_nBlocks] = HOST_TO_LITTLE32(blockValue);
    }
    else if (m_nBlocks < 12 + nEntriesPerBlock)
    {
        // Indirect addressing needed.

        // If this is the first indirect block, we need to reserve a new table block.
        if (m_nBlocks == 12)
        {
            m_pInode->i_block[12] = HOST_TO_LITTLE32(m_pExt2Fs->findFreeBlock(m_InodeNumber));
            if (m_pInode->i_block[12] == 0)
            {
                // We had a problem.
                SYSCALL_ERROR(NoSpaceLeftOnDevice);
                return false;
            }
        }

        // Now we can set the block.
        uint32_t *buffer = reinterpret_cast<uint32_t*>(m_pExt2Fs->readBlock(LITTLE_TO_HOST32(m_pInode->i_block[12])));

        buffer[m_nBlocks-12] = HOST_TO_LITTLE32(blockValue);
    }
    else if (m_nBlocks < 12 + nEntriesPerBlock + nEntriesPerBlock*nEntriesPerBlock)
    {
        // Bi-indirect addressing required.

        // Index from the start of the bi-indirect block (i.e. ignore the 12 direct entries and one indirect block).
        size_t biIdx = m_nBlocks - 12 - nEntriesPerBlock;
        // Block number inside the bi-indirect table of where to find the indirect block table.
        size_t indirectBlock = biIdx / nEntriesPerBlock;
        // Index inside the indirect block table.
        size_t indirectIdx = biIdx % nEntriesPerBlock;

        // If this is the first bi-indirect block, we need to reserve a bi-indirect table block.
        if (biIdx == 0)
        {
            m_pInode->i_block[13] = HOST_TO_LITTLE32(m_pExt2Fs->findFreeBlock(m_InodeNumber));
            if (m_pInode->i_block[13] == 0)
            {
                // We had a problem.
                SYSCALL_ERROR(NoSpaceLeftOnDevice);
                return false;
            }
        }

        // Now we can safely read the bi-indirect block.
        uint32_t *pBlock = reinterpret_cast<uint32_t*>(m_pExt2Fs->readBlock(LITTLE_TO_HOST32(m_pInode->i_block[13])));

        // Do we need to start a new indirect block?
        if (indirectIdx == 0)
        {
            pBlock[indirectBlock] = HOST_TO_LITTLE32(m_pExt2Fs->findFreeBlock(m_InodeNumber));
            if (pBlock[indirectBlock] == 0)
            {
                // We had a problem.
                SYSCALL_ERROR(NoSpaceLeftOnDevice);
                return false;
            }
        }

        // Cache this as it gets clobbered by the readBlock call (using the same buffer).
        uint32_t nIndirectBlockNum = LITTLE_TO_HOST32(pBlock[indirectBlock]);

        // Grab the indirect block.
        pBlock = reinterpret_cast<uint32_t*>(m_pExt2Fs->readBlock(nIndirectBlockNum));

        // Set the correct entry.
        pBlock[indirectIdx] = HOST_TO_LITTLE32(blockValue);

        /// This causes a assertion failed in SlamAllocator when copying some file on a ext2 volume
        /// (eddyb)
        // Done.
        //delete [] pBlock;
    }
    else
    {
        // Tri-indirect addressing required.
        FATAL("EXT2: Tri-indirect addressing required, but not implemented.");
        return false;
    }

    uint32_t *pTmp = new uint32_t[m_nBlocks+1];
    memcpy(pTmp, m_pBlocks, m_nBlocks*4);
    delete [] m_pBlocks;
    m_pBlocks = pTmp;
    m_pBlocks[m_nBlocks] = blockValue;

    m_nBlocks++;
    m_pInode->i_blocks = HOST_TO_LITTLE32(m_nBlocks);

    return true;
}

void Ext2Node::fileAttributeChanged(size_t size, size_t atime, size_t mtime, size_t ctime)
{
    // Reconstruct the inode from the cached fields.
    m_pInode->i_blocks = HOST_TO_LITTLE32(m_nBlocks);
    m_pInode->i_size = HOST_TO_LITTLE32(size); /// \todo 4GB files.
    m_pInode->i_atime = HOST_TO_LITTLE32(atime);
    m_pInode->i_mtime = HOST_TO_LITTLE32(mtime);
    m_pInode->i_ctime = HOST_TO_LITTLE32(ctime);
}
<|endoftext|>


<commit_before><commit_msg>Remove incorrect comment from GetInfoFromDataURL<commit_after><|endoftext|>


<commit_before>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Utility/Formats/MD2Loader.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Stream.hpp>
#include <Nazara/Math/Algorithm.hpp>
#include <Nazara/Math/Quaternion.hpp>
#include <Nazara/Utility/BufferMapper.hpp>
#include <Nazara/Utility/MaterialData.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <Nazara/Utility/StaticMesh.hpp>
#include <Nazara/Utility/Formats/MD2Constants.hpp>
#include <cstddef>
#include <cstring>
#include <memory>
#include <Nazara/Utility/Debug.hpp>

namespace Nz
{
	namespace
	{
		bool IsSupported(const String& extension)
		{
			return (extension == "md2");
		}

		Ternary Check(Stream& stream, const MeshParams& parameters)
		{
			bool skip;
			if (parameters.custom.GetBooleanParameter("SkipNativeMD2Loader", &skip) && skip)
				return Ternary_False;

			UInt32 magic[2];
			if (stream.Read(&magic[0], 2*sizeof(UInt32)) == 2*sizeof(UInt32))
			{
				#ifdef NAZARA_BIG_ENDIAN
				SwapBytes(&magic[0], sizeof(UInt32));
				SwapBytes(&magic[1], sizeof(UInt32));
				#endif

				if (magic[0] == md2Ident && magic[1] == 8)
					return Ternary_True;
			}

			return Ternary_False;
		}

		bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters)
		{
			MD2_Header header;
			if (stream.Read(&header, sizeof(MD2_Header)) != sizeof(MD2_Header))
			{
				NazaraError("Failed to read header");
				return false;
			}

			#ifdef NAZARA_BIG_ENDIAN
			SwapBytes(&header.skinwidth, sizeof(UInt32));
			SwapBytes(&header.skinheight, sizeof(UInt32));
			SwapBytes(&header.framesize, sizeof(UInt32));
			SwapBytes(&header.num_skins, sizeof(UInt32));
			SwapBytes(&header.num_vertices, sizeof(UInt32));
			SwapBytes(&header.num_st, sizeof(UInt32));
			SwapBytes(&header.num_tris, sizeof(UInt32));
			SwapBytes(&header.num_glcmds, sizeof(UInt32));
			SwapBytes(&header.num_frames, sizeof(UInt32));
			SwapBytes(&header.offset_skins, sizeof(UInt32));
			SwapBytes(&header.offset_st, sizeof(UInt32));
			SwapBytes(&header.offset_tris, sizeof(UInt32));
			SwapBytes(&header.offset_frames, sizeof(UInt32));
			SwapBytes(&header.offset_glcmds, sizeof(UInt32));
			SwapBytes(&header.offset_end, sizeof(UInt32));
			#endif

			if (stream.GetSize() < header.offset_end)
			{
				NazaraError("Incomplete MD2 file");
				return false;
			}

			/// Création du mesh
			// Le moteur ne supporte plus les animations image-clé, nous ne pouvons charger qu'en statique
			if (!mesh->CreateStatic()) // Ne devrait jamais échouer
			{
				NazaraInternalError("Failed to create mesh");
				return false;
			}

			/// Chargement des skins
			if (header.num_skins > 0)
			{
				mesh->SetMaterialCount(header.num_skins);
				stream.SetCursorPos(header.offset_skins);
				{
					String baseDir = stream.GetDirectory();
					char skin[68];
					for (unsigned int i = 0; i < header.num_skins; ++i)
					{
						stream.Read(skin, 68*sizeof(char));

						ParameterList matData;
						matData.SetParameter(MaterialData::FilePath, baseDir + skin);

						mesh->SetMaterialData(i, std::move(matData));
					}
				}
			}

			/// Chargement des submesh
			// Actuellement le loader ne charge qu'un submesh
			IndexBufferRef indexBuffer = IndexBuffer::New(false, header.num_tris*3, parameters.storage, BufferUsage_Static);

			/// Lecture des triangles
			std::vector<MD2_Triangle> triangles(header.num_tris);

			stream.SetCursorPos(header.offset_tris);
			stream.Read(&triangles[0], header.num_tris*sizeof(MD2_Triangle));

			BufferMapper<IndexBuffer> indexMapper(indexBuffer, BufferAccess_DiscardAndWrite);
			UInt16* index = static_cast<UInt16*>(indexMapper.GetPointer());

			for (unsigned int i = 0; i < header.num_tris; ++i)
			{
				#ifdef NAZARA_BIG_ENDIAN
				SwapBytes(&triangles[i].vertices[0], sizeof(UInt16));
				SwapBytes(&triangles[i].texCoords[0], sizeof(UInt16));

				SwapBytes(&triangles[i].vertices[1], sizeof(UInt16));
				SwapBytes(&triangles[i].texCoords[1], sizeof(UInt16));

				SwapBytes(&triangles[i].vertices[2], sizeof(UInt16));
				SwapBytes(&triangles[i].texCoords[2], sizeof(UInt16));
				#endif

				// On respécifie le triangle dans l'ordre attendu
				*index++ = triangles[i].vertices[0];
				*index++ = triangles[i].vertices[2];
				*index++ = triangles[i].vertices[1];
			}

			indexMapper.Unmap();

			if (parameters.optimizeIndexBuffers)
				indexBuffer->Optimize();

			/// Lecture des coordonnées de texture
			std::vector<MD2_TexCoord> texCoords(header.num_st);

			stream.SetCursorPos(header.offset_st);
			stream.Read(&texCoords[0], header.num_st*sizeof(MD2_TexCoord));

			#ifdef NAZARA_BIG_ENDIAN
			for (unsigned int i = 0; i < header.num_st; ++i)
			{
				SwapBytes(&texCoords[i].u, sizeof(Int16));
				SwapBytes(&texCoords[i].v, sizeof(Int16));
			}
			#endif

			VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent), header.num_vertices, parameters.storage, BufferUsage_Static);
			StaticMeshRef subMesh = StaticMesh::New(mesh);
			if (!subMesh->Create(vertexBuffer))
			{
				NazaraError("Failed to create SubMesh");
				return false;
			}

			/// Chargement des vertices
			stream.SetCursorPos(header.offset_frames);

			std::unique_ptr<MD2_Vertex[]> vertices(new MD2_Vertex[header.num_vertices]);
			Vector3f scale, translate;
			stream.Read(scale, sizeof(Vector3f));
			stream.Read(translate, sizeof(Vector3f));
			stream.Read(nullptr, 16*sizeof(char)); // Nom de la frame, inutile ici
			stream.Read(vertices.get(), header.num_vertices*sizeof(MD2_Vertex));

			#ifdef NAZARA_BIG_ENDIAN
			SwapBytes(&scale.x, sizeof(float));
			SwapBytes(&scale.y, sizeof(float));
			SwapBytes(&scale.z, sizeof(float));

			SwapBytes(&translate.x, sizeof(float));
			SwapBytes(&translate.y, sizeof(float));
			SwapBytes(&translate.z, sizeof(float));
			#endif

			constexpr float ScaleAdjust = 1.f / 27.8f; // Make a 50 Quake 2 units character a 1.8 unit long

			scale *= ScaleAdjust;
			translate *= ScaleAdjust;

			BufferMapper<VertexBuffer> vertexMapper(vertexBuffer, BufferAccess_DiscardAndWrite);
			MeshVertex* vertex = static_cast<MeshVertex*>(vertexMapper.GetPointer());

			/// Chargement des coordonnées de texture
			const unsigned int indexFix[3] = {0, 2, 1}; // Pour respécifier les indices dans le bon ordre
			for (unsigned int i = 0; i < header.num_tris; ++i)
			{
				for (unsigned int j = 0; j < 3; ++j)
				{
					const unsigned int fixedIndex = indexFix[j];
					const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]];
					float u = static_cast<float>(texC.u) / header.skinwidth;
					float v = static_cast<float>(texC.v) / header.skinheight;

					vertex[triangles[i].vertices[fixedIndex]].uv.Set(u, (parameters.flipUVs) ? 1.f - v : v);
				}
			}

			/// Chargement des positions
			// Pour que le modèle soit correctement aligné, on génère un quaternion que nous appliquerons à chacune des vertices
			Quaternionf rotationQuat = EulerAnglesf(-90.f, 90.f, 0.f);
			Nz::Matrix4f matrix = Matrix4f::Transform(translate, rotationQuat, scale);
			matrix *= parameters.matrix;

			for (unsigned int v = 0; v < header.num_vertices; ++v)
			{
				const MD2_Vertex& vert = vertices[v];
				Vector3f position = matrix * Vector3f(vert.x, vert.y, vert.z);

				vertex->position = position;
				vertex->normal = rotationQuat * md2Normals[vert.n];

				vertex++;
			}

			vertexMapper.Unmap();

			subMesh->SetIndexBuffer(indexBuffer);
			subMesh->SetMaterialIndex(0);

			subMesh->GenerateAABB();
			subMesh->GenerateTangents();

			mesh->AddSubMesh(subMesh);

			if (parameters.center)
				mesh->Recenter();

			return true;
		}
	}

	namespace Loaders
	{
		void RegisterMD2()
		{
			MeshLoader::RegisterLoader(IsSupported, Check, Load);
		}

		void UnregisterMD2()
		{
			MeshLoader::UnregisterLoader(IsSupported, Check, Load);
		}
	}
}
<commit_msg>Utility/Formats: Make MD2Loader specify diffuse texture path instead of material filepath<commit_after>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Utility/Formats/MD2Loader.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Stream.hpp>
#include <Nazara/Math/Algorithm.hpp>
#include <Nazara/Math/Quaternion.hpp>
#include <Nazara/Utility/BufferMapper.hpp>
#include <Nazara/Utility/MaterialData.hpp>
#include <Nazara/Utility/Mesh.hpp>
#include <Nazara/Utility/StaticMesh.hpp>
#include <Nazara/Utility/Formats/MD2Constants.hpp>
#include <cstddef>
#include <cstring>
#include <memory>
#include <Nazara/Utility/Debug.hpp>

namespace Nz
{
	namespace
	{
		bool IsSupported(const String& extension)
		{
			return (extension == "md2");
		}

		Ternary Check(Stream& stream, const MeshParams& parameters)
		{
			bool skip;
			if (parameters.custom.GetBooleanParameter("SkipNativeMD2Loader", &skip) && skip)
				return Ternary_False;

			UInt32 magic[2];
			if (stream.Read(&magic[0], 2*sizeof(UInt32)) == 2*sizeof(UInt32))
			{
				#ifdef NAZARA_BIG_ENDIAN
				SwapBytes(&magic[0], sizeof(UInt32));
				SwapBytes(&magic[1], sizeof(UInt32));
				#endif

				if (magic[0] == md2Ident && magic[1] == 8)
					return Ternary_True;
			}

			return Ternary_False;
		}

		bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters)
		{
			MD2_Header header;
			if (stream.Read(&header, sizeof(MD2_Header)) != sizeof(MD2_Header))
			{
				NazaraError("Failed to read header");
				return false;
			}

			#ifdef NAZARA_BIG_ENDIAN
			SwapBytes(&header.skinwidth, sizeof(UInt32));
			SwapBytes(&header.skinheight, sizeof(UInt32));
			SwapBytes(&header.framesize, sizeof(UInt32));
			SwapBytes(&header.num_skins, sizeof(UInt32));
			SwapBytes(&header.num_vertices, sizeof(UInt32));
			SwapBytes(&header.num_st, sizeof(UInt32));
			SwapBytes(&header.num_tris, sizeof(UInt32));
			SwapBytes(&header.num_glcmds, sizeof(UInt32));
			SwapBytes(&header.num_frames, sizeof(UInt32));
			SwapBytes(&header.offset_skins, sizeof(UInt32));
			SwapBytes(&header.offset_st, sizeof(UInt32));
			SwapBytes(&header.offset_tris, sizeof(UInt32));
			SwapBytes(&header.offset_frames, sizeof(UInt32));
			SwapBytes(&header.offset_glcmds, sizeof(UInt32));
			SwapBytes(&header.offset_end, sizeof(UInt32));
			#endif

			if (stream.GetSize() < header.offset_end)
			{
				NazaraError("Incomplete MD2 file");
				return false;
			}

			/// Création du mesh
			// Le moteur ne supporte plus les animations image-clé, nous ne pouvons charger qu'en statique
			if (!mesh->CreateStatic()) // Ne devrait jamais échouer
			{
				NazaraInternalError("Failed to create mesh");
				return false;
			}

			/// Chargement des skins
			if (header.num_skins > 0)
			{
				mesh->SetMaterialCount(header.num_skins);
				stream.SetCursorPos(header.offset_skins);
				{
					String baseDir = stream.GetDirectory();
					char skin[68];
					for (unsigned int i = 0; i < header.num_skins; ++i)
					{
						stream.Read(skin, 68*sizeof(char));

						ParameterList matData;
						matData.SetParameter(MaterialData::CustomDefined, true);
						matData.SetParameter(MaterialData::DiffuseTexturePath, baseDir + skin);

						mesh->SetMaterialData(i, std::move(matData));
					}
				}
			}

			/// Chargement des submesh
			// Actuellement le loader ne charge qu'un submesh
			IndexBufferRef indexBuffer = IndexBuffer::New(false, header.num_tris*3, parameters.storage, BufferUsage_Static);

			/// Lecture des triangles
			std::vector<MD2_Triangle> triangles(header.num_tris);

			stream.SetCursorPos(header.offset_tris);
			stream.Read(&triangles[0], header.num_tris*sizeof(MD2_Triangle));

			BufferMapper<IndexBuffer> indexMapper(indexBuffer, BufferAccess_DiscardAndWrite);
			UInt16* index = static_cast<UInt16*>(indexMapper.GetPointer());

			for (unsigned int i = 0; i < header.num_tris; ++i)
			{
				#ifdef NAZARA_BIG_ENDIAN
				SwapBytes(&triangles[i].vertices[0], sizeof(UInt16));
				SwapBytes(&triangles[i].texCoords[0], sizeof(UInt16));

				SwapBytes(&triangles[i].vertices[1], sizeof(UInt16));
				SwapBytes(&triangles[i].texCoords[1], sizeof(UInt16));

				SwapBytes(&triangles[i].vertices[2], sizeof(UInt16));
				SwapBytes(&triangles[i].texCoords[2], sizeof(UInt16));
				#endif

				// On respécifie le triangle dans l'ordre attendu
				*index++ = triangles[i].vertices[0];
				*index++ = triangles[i].vertices[2];
				*index++ = triangles[i].vertices[1];
			}

			indexMapper.Unmap();

			if (parameters.optimizeIndexBuffers)
				indexBuffer->Optimize();

			/// Lecture des coordonnées de texture
			std::vector<MD2_TexCoord> texCoords(header.num_st);

			stream.SetCursorPos(header.offset_st);
			stream.Read(&texCoords[0], header.num_st*sizeof(MD2_TexCoord));

			#ifdef NAZARA_BIG_ENDIAN
			for (unsigned int i = 0; i < header.num_st; ++i)
			{
				SwapBytes(&texCoords[i].u, sizeof(Int16));
				SwapBytes(&texCoords[i].v, sizeof(Int16));
			}
			#endif

			VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent), header.num_vertices, parameters.storage, BufferUsage_Static);
			StaticMeshRef subMesh = StaticMesh::New(mesh);
			if (!subMesh->Create(vertexBuffer))
			{
				NazaraError("Failed to create SubMesh");
				return false;
			}

			/// Chargement des vertices
			stream.SetCursorPos(header.offset_frames);

			std::unique_ptr<MD2_Vertex[]> vertices(new MD2_Vertex[header.num_vertices]);
			Vector3f scale, translate;
			stream.Read(scale, sizeof(Vector3f));
			stream.Read(translate, sizeof(Vector3f));
			stream.Read(nullptr, 16*sizeof(char)); // Nom de la frame, inutile ici
			stream.Read(vertices.get(), header.num_vertices*sizeof(MD2_Vertex));

			#ifdef NAZARA_BIG_ENDIAN
			SwapBytes(&scale.x, sizeof(float));
			SwapBytes(&scale.y, sizeof(float));
			SwapBytes(&scale.z, sizeof(float));

			SwapBytes(&translate.x, sizeof(float));
			SwapBytes(&translate.y, sizeof(float));
			SwapBytes(&translate.z, sizeof(float));
			#endif

			constexpr float ScaleAdjust = 1.f / 27.8f; // Make a 50 Quake 2 units character a 1.8 unit long

			scale *= ScaleAdjust;
			translate *= ScaleAdjust;

			BufferMapper<VertexBuffer> vertexMapper(vertexBuffer, BufferAccess_DiscardAndWrite);
			MeshVertex* vertex = static_cast<MeshVertex*>(vertexMapper.GetPointer());

			/// Chargement des coordonnées de texture
			const unsigned int indexFix[3] = {0, 2, 1}; // Pour respécifier les indices dans le bon ordre
			for (unsigned int i = 0; i < header.num_tris; ++i)
			{
				for (unsigned int j = 0; j < 3; ++j)
				{
					const unsigned int fixedIndex = indexFix[j];
					const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]];
					float u = static_cast<float>(texC.u) / header.skinwidth;
					float v = static_cast<float>(texC.v) / header.skinheight;

					vertex[triangles[i].vertices[fixedIndex]].uv.Set(u, (parameters.flipUVs) ? 1.f - v : v);
				}
			}

			/// Chargement des positions
			// Pour que le modèle soit correctement aligné, on génère un quaternion que nous appliquerons à chacune des vertices
			Quaternionf rotationQuat = EulerAnglesf(-90.f, 90.f, 0.f);
			Nz::Matrix4f matrix = Matrix4f::Transform(translate, rotationQuat, scale);
			matrix *= parameters.matrix;

			for (unsigned int v = 0; v < header.num_vertices; ++v)
			{
				const MD2_Vertex& vert = vertices[v];
				Vector3f position = matrix * Vector3f(vert.x, vert.y, vert.z);

				vertex->position = position;
				vertex->normal = rotationQuat * md2Normals[vert.n];

				vertex++;
			}

			vertexMapper.Unmap();

			subMesh->SetIndexBuffer(indexBuffer);
			subMesh->SetMaterialIndex(0);

			subMesh->GenerateAABB();
			subMesh->GenerateTangents();

			mesh->AddSubMesh(subMesh);

			if (parameters.center)
				mesh->Recenter();

			return true;
		}
	}

	namespace Loaders
	{
		void RegisterMD2()
		{
			MeshLoader::RegisterLoader(IsSupported, Check, Load);
		}

		void UnregisterMD2()
		{
			MeshLoader::UnregisterLoader(IsSupported, Check, Load);
		}
	}
}
<|endoftext|>


<commit_before>//
// Copyright Copyright 2009-2021, AMT – The Association For Manufacturing Technology (“AMT”)
// All rights reserved.
//
//    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.
//

#pragma once

#include <boost/asio.hpp>
#include <boost/bind.hpp>

#include <condition_variable>
#include <mutex>
#include <vector>

#include "utilities.hpp"

namespace mtconnect {
  namespace observation {
    class ChangeSignaler;
    class ChangeObserver
    {
    public:
      ChangeObserver(boost::asio::io_context::strand &strand)
        : m_strand(strand), m_timer(strand.context())
      {}

      virtual ~ChangeObserver();

      bool wait(std::chrono::milliseconds duration,
                std::function<void(boost::system::error_code)> handler)
      {
        std::unique_lock<std::recursive_mutex> lock(m_mutex);

        if (m_sequence != UINT64_MAX)
        {
          boost::asio::post(boost::asio::bind_executor(
              m_strand, boost::bind(handler, boost::system::error_code {})));
        }
        else
        {
          m_timer.expires_from_now(duration);
          m_timer.async_wait(handler);
        }
        return true;
      }

      void signal(uint64_t sequence)
      {
        std::lock_guard<std::recursive_mutex> scopedLock(m_mutex);

        if (m_sequence > sequence && sequence)
          m_sequence = sequence;

        m_timer.cancel();
      }

      uint64_t getSequence() const { return m_sequence; }

      bool wasSignaled() const { return m_sequence != UINT64_MAX; }

      void reset()
      {
        std::lock_guard<std::recursive_mutex> scopedLock(m_mutex);
        m_sequence = UINT64_MAX;
      }

    private:
      boost::asio::io_context::strand &m_strand;
      mutable std::recursive_mutex m_mutex;
      boost::asio::steady_timer m_timer;

      std::list<ChangeSignaler *> m_signalers;
      volatile uint64_t m_sequence = UINT64_MAX;

    protected:
      friend class ChangeSignaler;
      void addSignaler(ChangeSignaler *sig);
      bool removeSignaler(ChangeSignaler *sig);
    };

    class ChangeSignaler
    {
    public:
      // Observer Management
      void addObserver(ChangeObserver *observer);
      bool removeObserver(ChangeObserver *observer);
      bool hasObserver(ChangeObserver *observer) const;
      void signalObservers(uint64_t sequence) const;

      virtual ~ChangeSignaler();

    protected:
      // Observer Lists
      mutable std::recursive_mutex m_observerMutex;
      std::list<ChangeObserver *> m_observers;
    };
  }  // namespace observation
}  // namespace mtconnect
<commit_msg>Removed include of boost/bind. Corrected<commit_after>//
// Copyright Copyright 2009-2021, AMT – The Association For Manufacturing Technology (“AMT”)
// All rights reserved.
//
//    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.
//

#pragma once

#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>

#include <condition_variable>
#include <mutex>
#include <vector>

#include "utilities.hpp"

namespace mtconnect {
  namespace observation {
    class ChangeSignaler;
    class ChangeObserver
    {
    public:
      ChangeObserver(boost::asio::io_context::strand &strand)
        : m_strand(strand), m_timer(strand.context())
      {}

      virtual ~ChangeObserver();

      bool wait(std::chrono::milliseconds duration,
                std::function<void(boost::system::error_code)> handler)
      {
        std::unique_lock<std::recursive_mutex> lock(m_mutex);

        if (m_sequence != UINT64_MAX)
        {
          boost::asio::post(boost::asio::bind_executor(
              m_strand, boost::bind(handler, boost::system::error_code {})));
        }
        else
        {
          m_timer.expires_from_now(duration);
          m_timer.async_wait(handler);
        }
        return true;
      }

      void signal(uint64_t sequence)
      {
        std::lock_guard<std::recursive_mutex> scopedLock(m_mutex);

        if (m_sequence > sequence && sequence)
          m_sequence = sequence;

        m_timer.cancel();
      }

      uint64_t getSequence() const { return m_sequence; }

      bool wasSignaled() const { return m_sequence != UINT64_MAX; }

      void reset()
      {
        std::lock_guard<std::recursive_mutex> scopedLock(m_mutex);
        m_sequence = UINT64_MAX;
      }

    private:
      boost::asio::io_context::strand &m_strand;
      mutable std::recursive_mutex m_mutex;
      boost::asio::steady_timer m_timer;

      std::list<ChangeSignaler *> m_signalers;
      volatile uint64_t m_sequence = UINT64_MAX;

    protected:
      friend class ChangeSignaler;
      void addSignaler(ChangeSignaler *sig);
      bool removeSignaler(ChangeSignaler *sig);
    };

    class ChangeSignaler
    {
    public:
      // Observer Management
      void addObserver(ChangeObserver *observer);
      bool removeObserver(ChangeObserver *observer);
      bool hasObserver(ChangeObserver *observer) const;
      void signalObservers(uint64_t sequence) const;

      virtual ~ChangeSignaler();

    protected:
      // Observer Lists
      mutable std::recursive_mutex m_observerMutex;
      std::list<ChangeObserver *> m_observers;
    };
  }  // namespace observation
}  // namespace mtconnect
<|endoftext|>


<commit_before>/*$Id$
 *
 * This source file is a part of the Fresco Project.
 * Copyright (C) 1999 Stefan Seefeld <stefan@fresco.org>
 * http://www.fresco.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */

#include "TextDemo.hh"

using namespace Fresco;

TextDemo::TextDemo(Application *a)
  : Demo(a)
{
  TextKit_var text = application->resolve<TextKit>("IDL:fresco.org/Fresco/TextKit:1.0");
  ToolKit_var tools = application->resolve<ToolKit>("IDL:fresco.org/Fresco/ToolKit:1.0");

  Babylon::Char chars[] =
    {
      0x004d, 0x0061, 0x0067, 0x0079, 0x0061, 0x0072, 0x0020, 0x0420,
      0x0443, 0x0441, 0x0441, 0x043a, 0x0438, 0x0439, 0x0020, 0x0395,
      0x039b, 0x039b, 0x0397, 0x039d, 0x0399, 0x039a, 0x0391, 0x0020,
      0x65e5, 0x672c, 0x8a9e, 0x0020, 0x4e2d, 0x6587, 0x0020, 0xd55c,
      0xad6d, 0xc5b4
    };

  Babylon::String str(34, chars);
  Graphic_var txt = text->chunk(Unicode::to_CORBA(str));
  Controller_var group = tools->group(Graphic_var(tools->rgb(txt, 0.7, 0.8, 1.0)));
  application->append(group, Babylon::String("text"));
};
<commit_msg>Update colour of text to something legible.<commit_after>/*$Id$
 *
 * This source file is a part of the Fresco Project.
 * Copyright (C) 1999 Stefan Seefeld <stefan@fresco.org>
 * http://www.fresco.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */

#include "TextDemo.hh"

using namespace Fresco;

TextDemo::TextDemo(Application *a)
  : Demo(a)
{
  TextKit_var text = application->resolve<TextKit>("IDL:fresco.org/Fresco/TextKit:1.0");
  ToolKit_var tools = application->resolve<ToolKit>("IDL:fresco.org/Fresco/ToolKit:1.0");

  Babylon::Char chars[] =
    {
      0x004d, 0x0061, 0x0067, 0x0079, 0x0061, 0x0072, 0x0020, 0x0420,
      0x0443, 0x0441, 0x0441, 0x043a, 0x0438, 0x0439, 0x0020, 0x0395,
      0x039b, 0x039b, 0x0397, 0x039d, 0x0399, 0x039a, 0x0391, 0x0020,
      0x65e5, 0x672c, 0x8a9e, 0x0020, 0x4e2d, 0x6587, 0x0020, 0xd55c,
      0xad6d, 0xc5b4
    };

  Babylon::String str(34, chars);
  Graphic_var txt = text->chunk(Unicode::to_CORBA(str));
  Controller_var group = tools->group(Graphic_var(tools->rgb(txt, 0.2, 0.3, 0.5)));
  application->append(group, Babylon::String("text"));
};
<|endoftext|>