<commit_before>/**
 * @file VolumeData.cpp
 * @author Takashi Michikawa <michikawa@acm.org>
 */
#include <mi/VolumeData.hpp>
namespace mi
{
        template <typename T>
        class VolumeData<T>::Impl
        {
        public:
                Impl ( void ) : _isReadable ( false )
                {
                        return;
                }

                ~Impl ( void )
                {
                        return;
                }

                VolumeInfo& info ( void )
                {
                        return this->_info;
                }

                T& at ( const int x, const int y, const int z )
                {
                        return this->_data.at ( z ).at ( y ).at ( x );
                }

                bool allocate ( void )
                {
                        if ( ! this->isReadable() ) {
                                const Point3i& size = this->_info.getSize ();
                                this->_isReadable = false;
                                this->_data.assign ( size.z() , std::vector<std::vector<T> > ( size.y(), std::vector<T> ( size.x(), T() ) ) );

                                if ( this->_data.size() != static_cast<size_t> ( size.z() ) ) {
                                        return false;
                                }

                                this->_isReadable = true;
                        }

                        return true;
                }

                bool deallocate ( void )
                {
                        this->_data.erase ( this->_data.begin(), this->_data.end() );
                        this->_isReadable = false;
                        return true;
                }

                bool isReadable ( void ) const
                {
                        return this->_isReadable;
                }
        private:
                VolumeInfo _info;
                std::vector<std::vector<std::vector<T> > > _data;
                bool _isReadable;
        };

        template <typename T>
        VolumeData<T>::VolumeData ( void ) : _impl ( new VolumeData<T>::Impl() )
        {
                return;
        }

        template <typename T>
        VolumeData<T>::VolumeData ( const int x, const int y, const int z , const bool allocateMemory ) : _impl ( new VolumeData<T>::Impl() )
        {
                const Point3i size ( x, y, z );
                const VolumeInfo info ( size );
                this->init ( info, allocateMemory );
                return;
        }

        template <typename T>
        VolumeData<T>::VolumeData ( const Point3i& size, const bool allocateMemory ) : _impl ( new VolumeData<T>::Impl() )
        {
                const VolumeInfo info ( size );
                this->init ( info, allocateMemory );
                return;
        }

        template <typename T>
        VolumeData<T>::VolumeData ( const VolumeInfo& info, const bool allocateMemory ) : _impl ( new VolumeData<T>::Impl() )
        {
                this->init ( info, allocateMemory );
                return;
        }

        template <typename T>
        VolumeData<T>::~VolumeData ( void )
        {
                delete this->_impl;
                return;
        }

        template <typename T>
        VolumeData<T>&
        VolumeData<T>::init ( const Point3i& size, const bool allocateMemory )
        {
                const VolumeInfo info ( size );
                return this->init ( info, allocateMemory );
        }

        template <typename T>
        VolumeData<T>&
        VolumeData<T>::init ( const VolumeInfo& info, const bool allocateMemory )
        {
                this->deallocate();
                this->getInfo().init ( info.getSize(), info.getPitch(), info.getOrigin() );

                if ( allocateMemory ) {
                        this->allocate();
                }

                return *this;
        }

        template <typename T>
        VolumeData<T>&
        VolumeData<T>::fill ( const T& value )
        {
                const Point3i& size = this->getInfo().getSize();

                for ( int z = 0 ; z < size.z() ; ++z ) {
                        for ( int y = 0 ; y < size.y() ; ++y  ) {
                                for ( int x = 0 ; x < size.x() ; ++x ) {
                                        this->set ( Point3i ( x, y, z ), value );
                                }
                        }
                }

                return *this;
        }

        template <typename T>
        VolumeInfo&
        VolumeData<T>::getInfo ( void )
        {
                return this->_impl->info();
        }

        template <typename T>
        Point3i
        VolumeData<T>::getSize ( void )
        {
                return this->getInfo().getSize();
        }

        template <typename T>
        T
        VolumeData<T>::get ( const Point3i& p ) const
        {
                return this->get ( p.x(), p.y(), p.z()  );
        }

        template <typename T>
        T
        VolumeData<T>::get ( const int x, const int y, const int z ) const
        {
                return this->at ( x, y, z );
        }

        template <typename T>
        void
        VolumeData<T>::set ( const Point3i& p, const T v )
        {
                this->set ( p.x(), p.y(), p.z(), v );
                return;
        }

        template <typename T>
        void
        VolumeData<T>::set ( const int x, const int y, const int z , const T v )
        {
                this->at ( x, y, z ) = v;
                return;
        }

        template <typename T>
        T
        VolumeData<T>::at ( const Point3i& p ) const
        {
                return this->at ( p.x(), p.y(), p.z() );
        }

        template <typename T>
        T&
        VolumeData<T>::at ( const Point3i& p )
        {
                return this->at ( p.x(), p.y(), p.z() );
        }

        template <typename T>
        T
        VolumeData<T>::at ( const int x, const int y, const int z ) const
        {
                return this->_impl->at ( x, y, z );
        }

        template <typename T>
        T&
        VolumeData<T>::at ( const int x, const int y, const int z )
        {
                return this->_impl->at ( x, y, z );
        }

        template <typename T>
        void
        VolumeData<T>::clear ( void )
        {
                this->fill ( T() );
                return;
        }
        template <typename T>
        bool
<<<<<<< HEAD
        VolumeData<T>::clone( const VolumeData<T>& that )
        {
//                if ( that.getSize() != this->getSize() ) return false;
		const VolumeInfo & info = const_cast<VolumeData<T>&>(that).getInfo();
		this->init( info, true);
=======
        VolumeData<T>::clone ( VolumeData<T>& that )
        {
                if ( that.getSize() != this->getSize() ) {
                        return false;
                }

>>>>>>> 2b01e826d640dc4b42cc9e2e2be17c33824421c2
                const Point3i& size = this->getSize();

                for ( int z = 0 ; z < size.z() ; ++z ) {
                        for ( int y = 0 ; y < size.y() ; ++y ) {
                                for ( int x = 0 ; x < size.x() ; ++x ) {
                                        this->set ( x, y, z, that.get ( x, y, z ) );
                                }
                        }
                }

                return true;
        }

        template <typename T>
        bool
        VolumeData<T>::allocate ( void )
        {
                return this->_impl->allocate();
        }

        template <typename T>
        bool
        VolumeData<T>::deallocate ( void )
        {
                this->_impl->deallocate();
                return true;
        }

        template <typename T>
        bool
        VolumeData<T>::isReadable ( void ) const
        {
                return this->_impl->isReadable();
        }

        /*	template <typename T>
        	VolumeData<T>::iterator
        	VolumeData<T>::begin( void ) {
        		return VolumeData<T>::iterator( &( this->_data ), true );
        	}

        	template <typename T>
        	VolumeData<T>::iterator
        	VolumeData<T>::end( void ) {
        		return VolumeData<T>::iterator( &( this->_data ), false );
        	}
        */
        template <typename T>
        std::string
        VolumeData<T>::createFileName ( const std::string& name, const std::string& ext )
        {
                const Point3i& size  = this->getInfo().getSize();
                const Point3d& pitch = this->getInfo().getPitch();
                std::stringstream ss;
                ss << name << "-" << size.x() << "x" << size.y() << "x" << size.z() << "-" << pitch.x() << "x" << pitch.y() << "x" << pitch.z() << "." << ext;
                return ss.str();
        }

#define VOLUME_DATA(TYPE) template class VolumeData<TYPE>;
        VOLUME_DATA ( unsigned char );
        VOLUME_DATA ( char );
        VOLUME_DATA ( unsigned short );
        VOLUME_DATA ( short );
        VOLUME_DATA ( unsigned int );
        VOLUME_DATA ( int );
        VOLUME_DATA ( float );
        VOLUME_DATA ( double );

//        VOLUME_DATA( uint8_t );
//        VOLUME_DATA( int8_t );
//        VOLUME_DATA( uint16_t );
//        VOLUME_DATA( int16_t );
//        VOLUME_DATA( uint32_t );
//        VOLUME_DATA( int32_t );
//        VOLUME_DATA( uint64_t );
//        VOLUME_DATA( int64_t );
        VOLUME_DATA ( mi::Vector3s );

}
<commit_msg> snapshot<commit_after>/**
 * @file VolumeData.cpp
 * @author Takashi Michikawa <michikawa@acm.org>
 */
#include <mi/VolumeData.hpp>
namespace mi
{
        template <typename T>
        class VolumeData<T>::Impl
        {
        public:
                Impl ( void ) : _isReadable ( false )
                {
                        return;
                }

                ~Impl ( void )
                {
                        return;
                }

                VolumeInfo& info ( void )
                {
                        return this->_info;
                }

                T& at ( const int x, const int y, const int z )
                {
                        return this->_data.at ( z ).at ( y ).at ( x );
                }

                bool allocate ( void )
                {
                        if ( ! this->isReadable() ) {
                                const Point3i& size = this->_info.getSize ();
                                this->_isReadable = false;
                                this->_data.assign ( size.z() , std::vector<std::vector<T> > ( size.y(), std::vector<T> ( size.x(), T() ) ) );

                                if ( this->_data.size() != static_cast<size_t> ( size.z() ) ) {
                                        return false;
                                }

                                this->_isReadable = true;
                        }

                        return true;
                }

                bool deallocate ( void )
                {
                        this->_data.erase ( this->_data.begin(), this->_data.end() );
                        this->_isReadable = false;
                        return true;
                }

                bool isReadable ( void ) const
                {
                        return this->_isReadable;
                }
        private:
                VolumeInfo _info;
                std::vector<std::vector<std::vector<T> > > _data;
                bool _isReadable;
        };

        template <typename T>
        VolumeData<T>::VolumeData ( void ) : _impl ( new VolumeData<T>::Impl() )
        {
                return;
        }

        template <typename T>
        VolumeData<T>::VolumeData ( const int x, const int y, const int z , const bool allocateMemory ) : _impl ( new VolumeData<T>::Impl() )
        {
                const Point3i size ( x, y, z );
                const VolumeInfo info ( size );
                this->init ( info, allocateMemory );
                return;
        }

        template <typename T>
        VolumeData<T>::VolumeData ( const Point3i& size, const bool allocateMemory ) : _impl ( new VolumeData<T>::Impl() )
        {
                const VolumeInfo info ( size );
                this->init ( info, allocateMemory );
                return;
        }

        template <typename T>
        VolumeData<T>::VolumeData ( const VolumeInfo& info, const bool allocateMemory ) : _impl ( new VolumeData<T>::Impl() )
        {
                this->init ( info, allocateMemory );
                return;
        }

        template <typename T>
        VolumeData<T>::~VolumeData ( void )
        {
                delete this->_impl;
                return;
        }

        template <typename T>
        VolumeData<T>&
        VolumeData<T>::init ( const Point3i& size, const bool allocateMemory )
        {
                const VolumeInfo info ( size );
                return this->init ( info, allocateMemory );
        }

        template <typename T>
        VolumeData<T>&
        VolumeData<T>::init ( const VolumeInfo& info, const bool allocateMemory )
        {
                this->deallocate();
                this->getInfo().init ( info.getSize(), info.getPitch(), info.getOrigin() );

                if ( allocateMemory ) {
                        this->allocate();
                }

                return *this;
        }

        template <typename T>
        VolumeData<T>&
        VolumeData<T>::fill ( const T& value )
        {
                const Point3i& size = this->getInfo().getSize();

                for ( int z = 0 ; z < size.z() ; ++z ) {
                        for ( int y = 0 ; y < size.y() ; ++y  ) {
                                for ( int x = 0 ; x < size.x() ; ++x ) {
                                        this->set ( Point3i ( x, y, z ), value );
                                }
                        }
                }

                return *this;
        }

        template <typename T>
        VolumeInfo&
        VolumeData<T>::getInfo ( void )
        {
                return this->_impl->info();
        }

        template <typename T>
        Point3i
        VolumeData<T>::getSize ( void )
        {
                return this->getInfo().getSize();
        }

        template <typename T>
        T
        VolumeData<T>::get ( const Point3i& p ) const
        {
                return this->get ( p.x(), p.y(), p.z()  );
        }

        template <typename T>
        T
        VolumeData<T>::get ( const int x, const int y, const int z ) const
        {
                return this->at ( x, y, z );
        }

        template <typename T>
        void
        VolumeData<T>::set ( const Point3i& p, const T v )
        {
                this->set ( p.x(), p.y(), p.z(), v );
                return;
        }

        template <typename T>
        void
        VolumeData<T>::set ( const int x, const int y, const int z , const T v )
        {
                this->at ( x, y, z ) = v;
                return;
        }

        template <typename T>
        T
        VolumeData<T>::at ( const Point3i& p ) const
        {
                return this->at ( p.x(), p.y(), p.z() );
        }

        template <typename T>
        T&
        VolumeData<T>::at ( const Point3i& p )
        {
                return this->at ( p.x(), p.y(), p.z() );
        }

        template <typename T>
        T
        VolumeData<T>::at ( const int x, const int y, const int z ) const
        {
                return this->_impl->at ( x, y, z );
        }

        template <typename T>
        T&
        VolumeData<T>::at ( const int x, const int y, const int z )
        {
                return this->_impl->at ( x, y, z );
        }

        template <typename T>
        void
        VolumeData<T>::clear ( void )
        {
                this->fill ( T() );
                return;
        }
        template <typename T>
        bool
        VolumeData<T>::clone( const VolumeData<T>& that )
        {
		const VolumeInfo & info = const_cast<VolumeData<T>&>(that).getInfo();
		this->init( info, true);
                const Point3i& size = this->getSize();

                for ( int z = 0 ; z < size.z() ; ++z ) {
                        for ( int y = 0 ; y < size.y() ; ++y ) {
                                for ( int x = 0 ; x < size.x() ; ++x ) {
                                        this->set ( x, y, z, that.get ( x, y, z ) );
                                }
                        }
                }

                return true;
        }

        template <typename T>
        bool
        VolumeData<T>::allocate ( void )
        {
                return this->_impl->allocate();
        }

        template <typename T>
        bool
        VolumeData<T>::deallocate ( void )
        {
                this->_impl->deallocate();
                return true;
        }

        template <typename T>
        bool
        VolumeData<T>::isReadable ( void ) const
        {
                return this->_impl->isReadable();
        }

        /*	template <typename T>
        	VolumeData<T>::iterator
        	VolumeData<T>::begin( void ) {
        		return VolumeData<T>::iterator( &( this->_data ), true );
        	}

        	template <typename T>
        	VolumeData<T>::iterator
        	VolumeData<T>::end( void ) {
        		return VolumeData<T>::iterator( &( this->_data ), false );
        	}
        */
        template <typename T>
        std::string
        VolumeData<T>::createFileName ( const std::string& name, const std::string& ext )
        {
                const Point3i& size  = this->getInfo().getSize();
                const Point3d& pitch = this->getInfo().getPitch();
                std::stringstream ss;
                ss << name << "-" << size.x() << "x" << size.y() << "x" << size.z() << "-" << pitch.x() << "x" << pitch.y() << "x" << pitch.z() << "." << ext;
                return ss.str();
        }

#define VOLUME_DATA(TYPE) template class VolumeData<TYPE>;
        VOLUME_DATA ( unsigned char );
        VOLUME_DATA ( char );
        VOLUME_DATA ( unsigned short );
        VOLUME_DATA ( short );
        VOLUME_DATA ( unsigned int );
        VOLUME_DATA ( int );
        VOLUME_DATA ( float );
        VOLUME_DATA ( double );

//        VOLUME_DATA( uint8_t );
//        VOLUME_DATA( int8_t );
//        VOLUME_DATA( uint16_t );
//        VOLUME_DATA( int16_t );
//        VOLUME_DATA( uint32_t );
//        VOLUME_DATA( int32_t );
//        VOLUME_DATA( uint64_t );
//        VOLUME_DATA( int64_t );
        VOLUME_DATA ( mi::Vector3s );

}
<|endoftext|>


<commit_before>//
// Created by ante on 10/28/16.
//
#include "algorithms.h"
#include <iostream>
#include <malloc.h>
#include <queue>
#include "divsufsort.h"

using namespace std;

/**
 * Function compute number of occurrences letters smaller than 'c' from alphabet defined at 'bigSigma'.
 * @param c: letter for searching number of all occurrances letters that are before 'c' in ordered alphaber 'bigSigma'
 * @return: int that represent number of occurrances
 * */
int computeNumberOfOccurrencesLetterSmallerThenC(const Alphabet &a, const BWTree &bwt, char c) {
    int index = a[c];  // index of char c
    int sum = 0;
    for (int i = 0; i < index; ++i)
        sum += bwt.get_symbol_count(a[i]);  //number of occurrences letter bigSigma[i] in string S
    return sum;
}

/**
 * Function return number of occurrances bool value 'identity' in 'bitVec' in interval [start, end>.
 * @param identity: bool that represent value that we count in bitVector. It can be false(0) or true(1).
 * @param bitVec: indicator vector that tell us whatever char c goes in left or right subtree
 * @return: value that represents number of 'identity' value in bitVector
 * */
int rankFun(bool identity, const bitvector &bitVec, int start, int end) {
    int sum = 0;
    for (int i = start; i < end; ++i)
        sum += bitVec[i] == identity ? 1 : 0;
    return sum;
}

/**
 * Recurisve function that we need to compute all c-omega intervals.
 * @param bwt: bwt form what we try to get all c-omega intervals
 * @param ij: interval of bwt that we give to function
 * @param lr: interval of subalphabet
 * @param list: list of all c-omega intervals of given bwt
 * */
void getIntervalsRec(const Alphabet &a, const BWTree &bwt, int indexOfNode, interval &ij, interval &lr,
                     std::vector<interval> &list) {
    if (lr.first == lr.second) {
        char c = a[lr.first];
        int Cc = computeNumberOfOccurrencesLetterSmallerThenC(a, bwt, c);
        list.push_back(make_pair(Cc + ij.first, Cc + ij.second));
    } else {
        int m = (lr.first + lr.second) / 2;

        auto &bitVec = bwt.get_bitvector_for_index(indexOfNode);

        int a0 = rankFun(0, bitVec, 0, ij.first - 1);
        int b0 = a0 + rankFun(0, bitVec, ij.first - 1, ij.second);

        int a1 = ij.first - 1 - a0;
        int b1 = ij.second - b0;

        if (b0 > a0) {
            interval int1 = make_pair(a0 + 1, b0);
            interval int2 = make_pair(lr.first, m);
            getIntervalsRec(a, bwt, indexOfNode * 2, int1, int2, list);
        }
        if (b1 > a1) {
            interval int1 = make_pair(a1 + 1, b1);
            interval int2 = make_pair(m + 1, lr.second);
            getIntervalsRec(a, bwt, indexOfNode * 2 + 1, int1, int2, list);
        }
    }
}

/**
 * Function that accept interval ij as argument and retunr all c-omega intervals.
 * @param ij: interval form which we want to get all c-omega subintervals
 * @return: all c-omega intervals
 * */
std::vector<interval> getIntervals(const Alphabet &a, const BWTree &bwt, interval ij) {
    std::vector<interval> list;
    interval alp = make_pair(0, a.length());

    // func that compute all subinterval
    getIntervalsRec(a, bwt, 1, ij, alp, list);
    return list;
}

std::string bw_transformation(std::string S) {
    std::string BWTrans = std::string();
    auto n = S.length();
    int *SA = (int *) malloc(n * sizeof(int));
    BWTrans.resize(n);

    // sort
    divsufsort((const unsigned char *) S.c_str(), SA, static_cast<int>(S.length()), 0);

    for (auto i = 0u, tmp = 0u; i < n; ++i) {
        tmp = SA[i];
        BWTrans[i] = tmp == 0 ? '$' : S[tmp - 1];
    }
    free(SA);
    return BWTrans;
}

vector<int> calculate_lcp(string s) {
    string BWTrans = bw_transformation(s);
    Alphabet a(s, true);
    BWTree bwt(BWTrans, a);
    auto n = s.length();
    const int bottom = -2;
    vector<int> lcp(n + 1, bottom);
    lcp[0] = lcp[n] = -1;
    queue<pair<interval, int>> q;
    q.push(make_pair(make_pair(1, n), 0));
    cout << "BWTrans:" << endl;
    cout << BWTrans << endl;
    cout << "BWTree:" << endl;
    cout << bwt.show() << endl;
    for (; !q.empty(); q.pop()) {
        auto dq = q.front();
        auto list = (vector<interval> &&) getIntervals(a, bwt, dq.first);
        for (auto interv : list) {
            // NB: interval indices start from 1, but indexing in arrays starts from 0; hence we use interv.second not interv.second+1
            if (lcp[interv.second] == bottom) {
                q.push(make_pair(interv, dq.second + 1));
                lcp[interv.second] = dq.second;
            }
        }
        pretty_print(lcp);
    }
    return lcp;
}
<commit_msg>Debug getIntervals<commit_after>//
// Created by ante on 10/28/16.
//
#include "algorithms.h"
#include <iostream>
#include <malloc.h>
#include <queue>
#include "divsufsort.h"

using namespace std;

/**
 * Function compute number of occurrences letters smaller than 'c' from alphabet defined at 'bigSigma'.
 * @param c: letter for searching number of all occurrances letters that are before 'c' in ordered alphaber 'bigSigma'
 * @return: int that represent number of occurrances
 * */
int computeNumberOfOccurrencesLetterSmallerThenC(const Alphabet &a, const BWTree &bwt, char c) {
    int index = a[c];  // index of char c
    int sum = 0;
    for (int i = 0; i < index; ++i)
        sum += bwt.get_symbol_count(a[i]);  //number of occurrences letter bigSigma[i] in string S
    return sum;
}

/**
 * Function return number of occurrances bool value 'identity' in 'bitVec' in interval [start, end>.
 * @param identity: bool that represent value that we count in bitVector. It can be false(0) or true(1).
 * @param bitVec: indicator vector that tell us whatever char c goes in left or right subtree
 * @return: value that represents number of 'identity' value in bitVector
 * */
int rankFun(bool identity, const bitvector &bitVec, int start, int end) {
    int sum = 0;
    for (int i = start; i < end; ++i)
        sum += bitVec[i] == identity ? 1 : 0;
    return sum;
}

/**
 * Recurisve function that we need to compute all c-omega intervals.
 * @param bwt: bwt form what we try to get all c-omega intervals
 * @param ij: interval of bwt that we give to function
 * @param lr: interval of subalphabet
 * @param list: list of all c-omega intervals of given bwt
 * */
void getIntervalsRec(const Alphabet &a, const BWTree &bwt, int indexOfNode, interval &ij, interval &lr,
                     std::vector<interval> &list) {
    if (lr.first == lr.second) {
        char c = a[lr.first];
        int Cc = computeNumberOfOccurrencesLetterSmallerThenC(a, bwt, c);
        list.push_back(make_pair(Cc + ij.first, Cc + ij.second));
    } else {
        int m = (lr.first + lr.second) / 2;

        auto &bitVec = bwt.get_bitvector_for_index(indexOfNode);

        int a0 = rankFun(0, bitVec, 0, ij.first - 1);
        int b0 = a0 + rankFun(0, bitVec, ij.first - 1, ij.second);

        int a1 = ij.first - 1 - a0;
        int b1 = ij.second - b0;

        if (b0 > a0) {
            interval int1 = make_pair(a0 + 1, b0);
            interval int2 = make_pair(lr.first, m);
            getIntervalsRec(a, bwt, indexOfNode * 2, int1, int2, list);
        }
        if (b1 > a1) {
            interval int1 = make_pair(a1 + 1, b1);
            interval int2 = make_pair(m + 1, lr.second);
            getIntervalsRec(a, bwt, indexOfNode * 2 + 1, int1, int2, list);
        }
    }
}

/**
 * Function that accept interval ij as argument and retunr all c-omega intervals.
 * @param ij: interval form which we want to get all c-omega subintervals
 * @return: all c-omega intervals
 * */
std::vector<interval> getIntervals(const Alphabet &a, const BWTree &bwt, interval ij) {
    std::vector<interval> list;
    interval alp = make_pair(0, a.length());

    // func that compute all subinterval
    getIntervalsRec(a, bwt, 1, ij, alp, list);
    return list;
}

std::string bw_transformation(std::string S) {
    std::string BWTrans = std::string();
    auto n = S.length();
    int *SA = (int *) malloc(n * sizeof(int));
    BWTrans.resize(n);

    // sort
    divsufsort((const unsigned char *) S.c_str(), SA, static_cast<int>(S.length()), 0);

    for (auto i = 0u, tmp = 0u; i < n; ++i) {
        tmp = SA[i];
        BWTrans[i] = tmp == 0 ? '$' : S[tmp - 1];
    }
    free(SA);
    return BWTrans;
}

vector<int> calculate_lcp(string s) {
    string BWTrans = bw_transformation(s);
    Alphabet a(s, true);
    BWTree bwt(BWTrans, a);
    auto n = s.length();
    const int bottom = -2;
    vector<int> lcp(n + 1, bottom);
    lcp[0] = lcp[n] = -1;
    queue<pair<interval, int>> q;
    q.push(make_pair(make_pair(1, n), 0));
    cout << "BWTrans:" << endl;
    cout << BWTrans << endl;
    cout << "BWTree:" << endl;
    cout << bwt.show() << endl;
    for (; !q.empty(); q.pop()) {
        auto dq = q.front();
        cout << "q: " << dq.first.first << ", " << dq.first.second << endl;
        auto list = getIntervals(a, bwt, dq.first);
        for (auto interv : list) {
            cout << interv.first << ", " << interv.second << endl;
            // NB: interval indices start from 1, but indexing in arrays starts from 0; hence we use interv.second not interv.second+1
            if (lcp[interv.second] == bottom) {
                q.push(make_pair(interv, dq.second + 1));
                lcp[interv.second] = dq.second;
            }
        }
        pretty_print(lcp);
    }
    return lcp;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 Intel Corp
// Copyright (c) 2012 The Chromium Authors
//
// 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 co
// pies 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 al
// l copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IM
// PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNES
// S FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
//  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH
// ETHER 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 "content/nw/src/api/app/app.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/values.h"
#include "content/nw/src/api/api_messages.h"
#include "content/nw/src/browser/net_disk_cache_remover.h"
#include "content/nw/src/nw_package.h"
#include "content/nw/src/nw_shell.h"
#include "content/nw/src/shell_browser_context.h"
#include "content/common/view_messages.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/render_process_host.h"

using base::MessageLoop;
using content::Shell;
using content::ShellBrowserContext;
using content::RenderProcessHost;

namespace api {

namespace {

// Get render process host.
RenderProcessHost* GetRenderProcessHost() {
  RenderProcessHost* render_process_host = NULL;
  std::vector<Shell*> windows = Shell::windows();
  for (size_t i = 0; i < windows.size(); ++i) {
    if (!windows[i]->is_devtools()) {
      render_process_host = windows[i]->web_contents()->GetRenderProcessHost();
      break;
    }
  }

  return render_process_host;
}

void GetRenderProcessHosts(std::set<RenderProcessHost*>& rphs) {
  RenderProcessHost* render_process_host = NULL;
  std::vector<Shell*> windows = Shell::windows();
  for (size_t i = 0; i < windows.size(); ++i) {
    if (!windows[i]->is_devtools()) {
      render_process_host = windows[i]->web_contents()->GetRenderProcessHost();
      rphs.insert(render_process_host);
    }
  }
}

}  // namespace

// static
void App::Call(const std::string& method,
               const base::ListValue& arguments) {
  if (method == "Quit") {
    Quit();
    return;
  } else if (method == "CloseAllWindows") {
    CloseAllWindows();
    return;
  }
  NOTREACHED() << "Calling unknown method " << method << " of App";
}

// static
void App::Call(Shell* shell,
               const std::string& method,
               const base::ListValue& arguments,
               base::ListValue* result) {
  if (method == "GetDataPath") {
    ShellBrowserContext* browser_context =
      static_cast<ShellBrowserContext*>(shell->web_contents()->GetBrowserContext());
    result->AppendString(browser_context->GetPath().value());
    return;
  }else if (method == "GetArgv") {
    nw::Package* package = shell->GetPackage();
    CommandLine* command_line = CommandLine::ForCurrentProcess();
    CommandLine::StringVector args = command_line->GetArgs();
    CommandLine::StringVector argv = command_line->original_argv();

    // Ignore first non-switch arg if it's not a standalone package.
    bool ignore_arg = !package->self_extract();
    for (unsigned i = 1; i < argv.size(); ++i) {
      if (ignore_arg && argv[i] == args[0]) {
        ignore_arg = false;
        continue;
      }

      result->AppendString(argv[i]);
    }

    return;
  } else if (method == "ClearCache") {
    ClearCache(GetRenderProcessHost());
  } else if (method == "GetPackage") {
    result->AppendString(shell->GetPackage()->package_string());
    return;
  }

  NOTREACHED() << "Calling unknown sync method " << method << " of App";
}

// static
void App::CloseAllWindows(bool force) {
  std::vector<Shell*> windows = Shell::windows();

  for (size_t i = 0; i < windows.size(); ++i) {
    // Only send close event to browser windows, since devtools windows will
    // be automatically closed.
    if (!windows[i]->is_devtools()) {
      // If there is no js object bound to the window, then just close.
      if (force || windows[i]->ShouldCloseWindow())
        delete windows[i];
    }
  }
}

// static
void App::Quit(RenderProcessHost* render_process_host) {
  // Send the quit message.
  int no_use;
  if (render_process_host) {
    render_process_host->Send(new ViewMsg_WillQuit(&no_use));
  }else{
    std::set<RenderProcessHost*> rphs;
    std::set<RenderProcessHost*>::iterator it;

    GetRenderProcessHosts(rphs);
    for (it = rphs.begin(); it != rphs.end(); it++) {
      RenderProcessHost* rph = *it;
      DCHECK(rph != NULL);

      rph->Send(new ViewMsg_WillQuit(&no_use));
    }
    CloseAllWindows(true);
  }
  // Then quit.
  MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
}

// static
void App::EmitOpenEvent(const std::string& path) {
  std::set<RenderProcessHost*> rphs;
  std::set<RenderProcessHost*>::iterator it;

  GetRenderProcessHosts(rphs);
  for (it = rphs.begin(); it != rphs.end(); it++) {
    RenderProcessHost* rph = *it;
    DCHECK(rph != NULL);

    rph->Send(new ShellViewMsg_Open(path));
  }
}

void App::ClearCache(content::RenderProcessHost* render_process_host) {
  render_process_host->Send(new ShellViewMsg_ClearCache());
  nw::RemoveHttpDiskCache(render_process_host->GetBrowserContext(),
                          render_process_host->GetID());
}

}  // namespace api
<commit_msg>Fix #486: should delete Shell object on native window destruction<commit_after>// Copyright (c) 2012 Intel Corp
// Copyright (c) 2012 The Chromium Authors
//
// 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 co
// pies 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 al
// l copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IM
// PLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNES
// S FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
//  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WH
// ETHER 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 "content/nw/src/api/app/app.h"

#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/values.h"
#include "content/nw/src/api/api_messages.h"
#include "content/nw/src/browser/native_window.h"
#include "content/nw/src/browser/net_disk_cache_remover.h"
#include "content/nw/src/nw_package.h"
#include "content/nw/src/nw_shell.h"
#include "content/nw/src/shell_browser_context.h"
#include "content/common/view_messages.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/render_process_host.h"

using base::MessageLoop;
using content::Shell;
using content::ShellBrowserContext;
using content::RenderProcessHost;

namespace api {

namespace {

// Get render process host.
RenderProcessHost* GetRenderProcessHost() {
  RenderProcessHost* render_process_host = NULL;
  std::vector<Shell*> windows = Shell::windows();
  for (size_t i = 0; i < windows.size(); ++i) {
    if (!windows[i]->is_devtools()) {
      render_process_host = windows[i]->web_contents()->GetRenderProcessHost();
      break;
    }
  }

  return render_process_host;
}

void GetRenderProcessHosts(std::set<RenderProcessHost*>& rphs) {
  RenderProcessHost* render_process_host = NULL;
  std::vector<Shell*> windows = Shell::windows();
  for (size_t i = 0; i < windows.size(); ++i) {
    if (!windows[i]->is_devtools()) {
      render_process_host = windows[i]->web_contents()->GetRenderProcessHost();
      rphs.insert(render_process_host);
    }
  }
}

}  // namespace

// static
void App::Call(const std::string& method,
               const base::ListValue& arguments) {
  if (method == "Quit") {
    Quit();
    return;
  } else if (method == "CloseAllWindows") {
    CloseAllWindows();
    return;
  }
  NOTREACHED() << "Calling unknown method " << method << " of App";
}

// static
void App::Call(Shell* shell,
               const std::string& method,
               const base::ListValue& arguments,
               base::ListValue* result) {
  if (method == "GetDataPath") {
    ShellBrowserContext* browser_context =
      static_cast<ShellBrowserContext*>(shell->web_contents()->GetBrowserContext());
    result->AppendString(browser_context->GetPath().value());
    return;
  }else if (method == "GetArgv") {
    nw::Package* package = shell->GetPackage();
    CommandLine* command_line = CommandLine::ForCurrentProcess();
    CommandLine::StringVector args = command_line->GetArgs();
    CommandLine::StringVector argv = command_line->original_argv();

    // Ignore first non-switch arg if it's not a standalone package.
    bool ignore_arg = !package->self_extract();
    for (unsigned i = 1; i < argv.size(); ++i) {
      if (ignore_arg && argv[i] == args[0]) {
        ignore_arg = false;
        continue;
      }

      result->AppendString(argv[i]);
    }

    return;
  } else if (method == "ClearCache") {
    ClearCache(GetRenderProcessHost());
  } else if (method == "GetPackage") {
    result->AppendString(shell->GetPackage()->package_string());
    return;
  }

  NOTREACHED() << "Calling unknown sync method " << method << " of App";
}

// static
void App::CloseAllWindows(bool force) {
  std::vector<Shell*> windows = Shell::windows();

  for (size_t i = 0; i < windows.size(); ++i) {
    // Only send close event to browser windows, since devtools windows will
    // be automatically closed.
    if (!windows[i]->is_devtools()) {
      // If there is no js object bound to the window, then just close.
      if (force || windows[i]->ShouldCloseWindow())
        // we used to delete the Shell object here
        // but it should be deleted on native window destruction
        windows[i]->window()->Close();
    }
  }
}

// static
void App::Quit(RenderProcessHost* render_process_host) {
  // Send the quit message.
  int no_use;
  if (render_process_host) {
    render_process_host->Send(new ViewMsg_WillQuit(&no_use));
  }else{
    std::set<RenderProcessHost*> rphs;
    std::set<RenderProcessHost*>::iterator it;

    GetRenderProcessHosts(rphs);
    for (it = rphs.begin(); it != rphs.end(); it++) {
      RenderProcessHost* rph = *it;
      DCHECK(rph != NULL);

      rph->Send(new ViewMsg_WillQuit(&no_use));
    }
    CloseAllWindows(true);
  }
  // Then quit.
  MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
}

// static
void App::EmitOpenEvent(const std::string& path) {
  std::set<RenderProcessHost*> rphs;
  std::set<RenderProcessHost*>::iterator it;

  GetRenderProcessHosts(rphs);
  for (it = rphs.begin(); it != rphs.end(); it++) {
    RenderProcessHost* rph = *it;
    DCHECK(rph != NULL);

    rph->Send(new ShellViewMsg_Open(path));
  }
}

void App::ClearCache(content::RenderProcessHost* render_process_host) {
  render_process_host->Send(new ShellViewMsg_ClearCache());
  nw::RemoveHttpDiskCache(render_process_host->GetBrowserContext(),
                          render_process_host->GetID());
}

}  // namespace api
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>
#include <qsystemlock.h>

//TESTED_CLASS=
//TESTED_FILES=

#ifdef Q_OS_SYMBIAN
// In Symbian OS test data is located in applications private dir
// And underlying Open C have application private dir in default search path
#define SRCDIR ""
#endif

#define EXISTING_SHARE "existing"

class tst_QSystemLock : public QObject
{
    Q_OBJECT

public:
    tst_QSystemLock();
    virtual ~tst_QSystemLock();

public Q_SLOTS:
    void init();
    void cleanup();

private slots:
    void key_data();
    void key();

    void basicLock();
    void complexLock();
    void lockModes();
    void sucessive();
    void processes_data();
    void processes();

private:
    QSystemLock *existingLock;

};

tst_QSystemLock::tst_QSystemLock()
{
}

tst_QSystemLock::~tst_QSystemLock()
{
}

void tst_QSystemLock::init()
{
    existingLock = new QSystemLock(EXISTING_SHARE);
}

void tst_QSystemLock::cleanup()
{
    delete existingLock;
}

void tst_QSystemLock::key_data()
{
    QTest::addColumn<QString>("constructorKey");
    QTest::addColumn<QString>("setKey");

    QTest::newRow("null, null") << QString() << QString();
    QTest::newRow("null, one") << QString() << QString("one");
    QTest::newRow("one, two") << QString("one") << QString("two");
}

/*!
    Basic key testing
 */
void tst_QSystemLock::key()
{
    QFETCH(QString, constructorKey);
    QFETCH(QString, setKey);

    QSystemLock sl(constructorKey);
    QCOMPARE(sl.key(), constructorKey);
    sl.setKey(setKey);
    QCOMPARE(sl.key(), setKey);
}

void tst_QSystemLock::basicLock()
{
    QSystemLock lock("foo");
    QVERIFY(lock.lock());
    QVERIFY(lock.unlock());
}

void tst_QSystemLock::complexLock()
{
    QSystemLock lock("foo");
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.unlock());

    QVERIFY(lock.lock(QSystemLock::ReadWrite));
    QVERIFY(lock.unlock());

    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.unlock());
    QVERIFY(lock.unlock());
}

void tst_QSystemLock::lockModes()
{
    QSystemLock reader1("library");
    QSystemLock reader2("library");

    QSystemLock librarian("library");
    QVERIFY(reader1.lock(QSystemLock::ReadOnly));
    QVERIFY(reader2.lock(QSystemLock::ReadOnly));
    QVERIFY(reader1.unlock());
    QVERIFY(reader2.unlock());
    QVERIFY(librarian.lock(QSystemLock::ReadWrite));
    QVERIFY(librarian.unlock());
}

void tst_QSystemLock::sucessive()
{
    QSystemLock lock("library");
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.unlock());
    QVERIFY(lock.unlock());
    QVERIFY(lock.unlock());
    QVERIFY(lock.unlock());
    QVERIFY(lock.unlock());
    QVERIFY(!lock.unlock());
}

void tst_QSystemLock::processes_data()
{
    QTest::addColumn<int>("readOnly");
    QTest::addColumn<int>("readWrite");
    for (int i = 0; i < 5; ++i) {
        QTest::newRow("1/0 process") << 1 << 0;
        QTest::newRow("0/1 process") << 0 << 1;
    	QTest::newRow("0/4 process") << 0 << 4;
        QTest::newRow("1/1 process") << 1 << 1;
        QTest::newRow("10/1 process") << 10 << 1;
        QTest::newRow("1/10 process") << 1 << 10;
        QTest::newRow("10/10 processes") << 10 << 10;
    }
}

/*!
    Create external processes
 */
void tst_QSystemLock::processes()
{
    QFETCH(int, readOnly);
    QFETCH(int, readWrite);

    QStringList scripts;
    for (int i = 0; i < readOnly; ++i)
        scripts.append(QFileInfo(SRCDIR "lackey/scripts/ systemlock_read.js").absoluteFilePath() );
    for (int i = 0; i < readWrite; ++i)
        scripts.append(QFileInfo(SRCDIR "lackey/scripts/systemlock_readwrite.js").absoluteFilePath());

    QList<QProcess*> consumers;
    unsigned int failedProcesses = 0;
    for (int i = 0; i < scripts.count(); ++i) {

        QStringList arguments = QStringList() << scripts.at(i);
        QProcess *p = new QProcess;
        p->setProcessChannelMode(QProcess::ForwardedChannels);

        p->start(QFileInfo(SRCDIR "lackey/lackey").absoluteFilePath(), arguments);
        // test, if the process could be started.

        if (p->waitForStarted(2000))
            consumers.append(p);
        else
            ++failedProcesses;
    }

    while (!consumers.isEmpty()) {
        consumers.first()->waitForFinished(3000);
        consumers.first()->kill();
        QCOMPARE(consumers.first()->exitStatus(), QProcess::NormalExit);
        QCOMPARE(consumers.first()->exitCode(), 0);
        delete consumers.takeFirst();
    }
    QCOMPARE(failedProcesses, (unsigned int)(0));
}

QTEST_MAIN(tst_QSystemLock)
#include "tst_qsystemlock.moc"

<commit_msg>Fix tst_QSystemLock::processes<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>
#include <qsystemlock.h>

//TESTED_CLASS=
//TESTED_FILES=

#ifdef Q_OS_SYMBIAN
// In Symbian OS test data is located in applications private dir
// And underlying Open C have application private dir in default search path
#define SRCDIR ""
#endif

#define EXISTING_SHARE "existing"

class tst_QSystemLock : public QObject
{
    Q_OBJECT

public:
    tst_QSystemLock();
    virtual ~tst_QSystemLock();

public Q_SLOTS:
    void init();
    void cleanup();

private slots:
    void key_data();
    void key();

    void basicLock();
    void complexLock();
    void lockModes();
    void sucessive();
    void processes_data();
    void processes();

private:
    QSystemLock *existingLock;

};

tst_QSystemLock::tst_QSystemLock()
{
}

tst_QSystemLock::~tst_QSystemLock()
{
}

void tst_QSystemLock::init()
{
    existingLock = new QSystemLock(EXISTING_SHARE);
}

void tst_QSystemLock::cleanup()
{
    delete existingLock;
}

void tst_QSystemLock::key_data()
{
    QTest::addColumn<QString>("constructorKey");
    QTest::addColumn<QString>("setKey");

    QTest::newRow("null, null") << QString() << QString();
    QTest::newRow("null, one") << QString() << QString("one");
    QTest::newRow("one, two") << QString("one") << QString("two");
}

/*!
    Basic key testing
 */
void tst_QSystemLock::key()
{
    QFETCH(QString, constructorKey);
    QFETCH(QString, setKey);

    QSystemLock sl(constructorKey);
    QCOMPARE(sl.key(), constructorKey);
    sl.setKey(setKey);
    QCOMPARE(sl.key(), setKey);
}

void tst_QSystemLock::basicLock()
{
    QSystemLock lock("foo");
    QVERIFY(lock.lock());
    QVERIFY(lock.unlock());
}

void tst_QSystemLock::complexLock()
{
    QSystemLock lock("foo");
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.unlock());

    QVERIFY(lock.lock(QSystemLock::ReadWrite));
    QVERIFY(lock.unlock());

    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.unlock());
    QVERIFY(lock.unlock());
}

void tst_QSystemLock::lockModes()
{
    QSystemLock reader1("library");
    QSystemLock reader2("library");

    QSystemLock librarian("library");
    QVERIFY(reader1.lock(QSystemLock::ReadOnly));
    QVERIFY(reader2.lock(QSystemLock::ReadOnly));
    QVERIFY(reader1.unlock());
    QVERIFY(reader2.unlock());
    QVERIFY(librarian.lock(QSystemLock::ReadWrite));
    QVERIFY(librarian.unlock());
}

void tst_QSystemLock::sucessive()
{
    QSystemLock lock("library");
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.lock(QSystemLock::ReadOnly));
    QVERIFY(lock.unlock());
    QVERIFY(lock.unlock());
    QVERIFY(lock.unlock());
    QVERIFY(lock.unlock());
    QVERIFY(lock.unlock());
    QVERIFY(!lock.unlock());
}

void tst_QSystemLock::processes_data()
{
    QTest::addColumn<int>("readOnly");
    QTest::addColumn<int>("readWrite");
    for (int i = 0; i < 5; ++i) {
        QTest::newRow("1/0 process") << 1 << 0;
        QTest::newRow("0/1 process") << 0 << 1;
    	QTest::newRow("0/4 process") << 0 << 4;
        QTest::newRow("1/1 process") << 1 << 1;
        QTest::newRow("10/1 process") << 10 << 1;
        QTest::newRow("1/10 process") << 1 << 10;
        QTest::newRow("10/10 processes") << 10 << 10;
    }
}

/*!
    Create external processes
 */
void tst_QSystemLock::processes()
{
    QFETCH(int, readOnly);
    QFETCH(int, readWrite);

    QStringList scripts;
    for (int i = 0; i < readOnly; ++i)
        scripts.append(QFileInfo(SRCDIR "/../lackey/scripts/systemlock_read.js").absoluteFilePath() );
    for (int i = 0; i < readWrite; ++i)
        scripts.append(QFileInfo(SRCDIR "/../lackey/scripts/systemlock_readwrite.js").absoluteFilePath());

    QList<QProcess*> consumers;
    unsigned int failedProcesses = 0;
    for (int i = 0; i < scripts.count(); ++i) {

        QStringList arguments = QStringList() << scripts.at(i);
        QProcess *p = new QProcess;
        p->setProcessChannelMode(QProcess::ForwardedChannels);

        p->start("../lackey/lackey", arguments);
        // test, if the process could be started.

        if (p->waitForStarted(2000))
            consumers.append(p);
        else
            ++failedProcesses;
    }

    while (!consumers.isEmpty()) {
        consumers.first()->waitForFinished(3000);
        consumers.first()->kill();
        QCOMPARE(consumers.first()->exitStatus(), QProcess::NormalExit);
        QCOMPARE(consumers.first()->exitCode(), 0);
        delete consumers.takeFirst();
    }
    QCOMPARE(failedProcesses, (unsigned int)(0));
}

QTEST_MAIN(tst_QSystemLock)
#include "tst_qsystemlock.moc"

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include "qsysteminfo.h"

QTM_USE_NAMESPACE
class tst_QSystemDisplayInfo : public QObject
{
    Q_OBJECT

private slots:
    void tst_displayBrightness();
    void tst_colorDepth();
 //   void tst_isScreenLockOn();

};

void tst_QSystemDisplayInfo::tst_displayBrightness()
{
    QSystemDisplayInfo di;
    QVERIFY(di.displayBrightness(0) > -2);
}

void tst_QSystemDisplayInfo::tst_colorDepth()
{
    QSystemDisplayInfo di;
    QVERIFY(di.colorDepth(0) > 0);
}

//void tst_QSystemDisplayInfo::tst_isScreenLockOn()
//{
//    QSystemDisplayInfo di;
//    bool lock = di.isScreenLockOn();
//    QVERIFY(lock == true || lock == false);
//}

QTEST_MAIN(tst_QSystemDisplayInfo)
#include "tst_qsystemdisplayinfo.moc"
<commit_msg>allow 0 to be a true color depth.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include "qsysteminfo.h"

QTM_USE_NAMESPACE
class tst_QSystemDisplayInfo : public QObject
{
    Q_OBJECT

private slots:
    void tst_displayBrightness();
    void tst_colorDepth();

};

void tst_QSystemDisplayInfo::tst_displayBrightness()
{
    QSystemDisplayInfo di;
    QVERIFY(di.displayBrightness(0) > -2);
}

void tst_QSystemDisplayInfo::tst_colorDepth()
{
    QSystemDisplayInfo di;
    int depth = di.colorDepth(0);
    QVERIFY(depth == 0
            || depth == 8
            || depth == 16
            || depth == 32
            || depth == 64);
}

QTEST_MAIN(tst_QSystemDisplayInfo)
#include "tst_qsystemdisplayinfo.moc"
<|endoftext|>


<commit_before>#include "headers/dungeon_data.h"

#define TAB "\t"

using namespace std;

string DungeonRoom::toString()
{
	ostringstream sout;
	sout << "{" << endl;
	sout << TAB << TAB << TAB << "\"ID\":\"" << uid << "\"," << endl;
	sout << TAB << TAB << TAB << "\"Name\":\"" << name << "\"," << endl;
	sout << TAB << TAB << TAB << "\"Description\":\"" << description << "\"," << endl;

	sout << TAB << TAB << TAB << "\"Objects\":[" << endl;
	for (int i = 0; i < objects.size(); i++) {
		sout << TAB << TAB << TAB << TAB << "{" << objects[i]->toString() << "}," << endl;
	}
	sout << TAB << TAB << TAB << "]," << endl;

	sout << TAB << TAB << TAB << "\"Creatures\":[" << endl;
	for (int i = 0; i < creatures.size(); i++) {
		sout << TAB << TAB << TAB << TAB << "{" << creatures[i]->toString() << "}," << endl;
	}
	sout << TAB << TAB << TAB << "]," << endl;

	sout << TAB << TAB << TAB << "\"Exits\":[" << endl;
	for (int i = 0; i < exits.size(); i++) {
		sout << TAB << TAB << TAB << TAB << "{" << exits[i]->toString() << "}," << endl;
	}
	sout << TAB << TAB << TAB << "]" << endl;
	sout << TAB << TAB << "}" << endl;
	return sout.str();
}
string DungeonExit::toString()
{
	ostringstream sout;
	return sout.str();
}
string DungeonObject::toString()
{
	ostringstream sout;
	return sout.str();
}
string DungeonCreature::toString()
{
	ostringstream sout;
	return sout.str();
}<commit_msg>Now does one room JSON.<commit_after>#include "headers/dungeon_data.h"

#define TAB "\t"

using namespace std;

string DungeonRoom::toString()
{
	ostringstream sout;
	sout << "{" << endl;
	sout << TAB << TAB << TAB << "\"ID\":\"" << uid << "\"," << endl;
	sout << TAB << TAB << TAB << "\"Name\":\"" << name << "\"," << endl;
	sout << TAB << TAB << TAB << "\"Description\":\"" << description << "\"," << endl;

	sout << TAB << TAB << TAB << "\"Objects\":[" << endl;
	for (int i = 0; i < objects.size(); i++) {
		sout << TAB << TAB << TAB << TAB << "{" << objects[i]->toString() << "}," << endl;
	}
	sout << TAB << TAB << TAB << "]," << endl;

	sout << TAB << TAB << TAB << "\"Creatures\":[" << endl;
	for (int i = 0; i < creatures.size(); i++) {
		sout << TAB << TAB << TAB << TAB << "{" << creatures[i]->toString() << "}," << endl;
	}
	sout << TAB << TAB << TAB << "]," << endl;

	sout << TAB << TAB << TAB << "\"Exits\":[" << endl;
	for (int i = 0; i < exits.size(); i++) {
		sout << TAB << TAB << TAB << TAB << "{" << exits[i]->toString() << "}," << endl;
	}
	sout << TAB << TAB << TAB << "]" << endl;
	sout << TAB << TAB << "}" << endl;
	return sout.str();
}
string DungeonExit::toString()
{
	ostringstream sout;
	sout << "\"Name\":\"" << name << "\", \"Description\":\"" << description
		 << "\", \"links\":" << room->uid;
	return sout.str();
}
string DungeonObject::toString()
{
	ostringstream sout;
	sout << "\"Name\":\"" << name << "\", \"Description\":\"" << description << "\"";
	return sout.str();
}
string DungeonCreature::toString()
{
	ostringstream sout;
	sout << "\"Name\":\"" << name << "\", \"Description\":\"" << description
		 << "\", \"hitpoints\":" << hitpoints << ", \"Alignment\":" << alignment;
	return sout.str();
}<|endoftext|>


<commit_before>
#include <QApplication>
#include <QPixmap>
#include <QImage>
#include <QPainter>
#include <QGLWidget>
#include <QTextLayout>
#include <QVBoxLayout>
#include <QTime>
#include <QDebug>

#ifdef HAVE_STATICTEXT
#include <private/qstatictext_p.h>
#endif

int iterations = 20;
const int count = 6;
const int lines = 12;
const int spacing = 36;
QSizeF size(1000, 800);
const qreal lineWidth = 1000;
QString strings[lines];

void paint_QTextLayout(QPainter &p, bool useCache)
{
    static bool first = true;
    static QTextLayout *textLayout[lines];
    if (first) {
        for (int i = 0; i < lines; ++i) {
            textLayout[i] = new QTextLayout(strings[i]);
            int leading = p.fontMetrics().leading();
            qreal height = 0;
            qreal widthUsed = 0;
            textLayout[i]->setCacheEnabled(useCache);
            textLayout[i]->beginLayout();
            while (1) {
                QTextLine line = textLayout[i]->createLine();
                if (!line.isValid())
                        break;

                line.setLineWidth(lineWidth);
                height += leading;
                line.setPosition(QPointF(0, height));
                height += line.height();
                widthUsed = qMax(widthUsed, line.naturalTextWidth());
            }
            textLayout[i]->endLayout();
        }
        first = false;
    }
    for (int i = 0; i < count; ++i) {
        for (int j = 0; j < lines; ++j) {
            textLayout[j]->draw(&p, QPoint(0, j*spacing));
        }
    }
}

void paint_QTextLayout_noCache(QPainter &p)
{
    paint_QTextLayout(p, false);
}

void paint_QTextLayout_cache(QPainter &p)
{
    paint_QTextLayout(p, true);
}

#ifdef HAVE_STATICTEXT
void paint_QStaticText(QPainter &p, bool useOptimizations)
{
    static QStaticText *staticText[lines];
    static bool first = true;
    if (first) {
        for (int i = 0; i < lines; ++i) {
            staticText[i] = new QStaticText(strings[i]);
            staticText[i]->setUseBackendOptimizations(useOptimizations);
        }
        first = false;
    }
    for (int i = 0; i < count; ++i) {
        for (int j = 0; j < lines; ++j) {
            p.drawStaticText(QPointF(0, 30 + j*spacing), *staticText[j]);
        }
    }
}

void paint_QStaticText_noOptimizations(QPainter &p)
{
    paint_QStaticText(p, false);
}

void paint_QStaticText_optimizations(QPainter &p)
{
    paint_QStaticText(p, true);
}
#endif

void paint_QPixmapCachedText(QPainter &p)
{
    static bool first = true;
    static QPixmap cacheText[lines];
    if (first) {
        for (int i = 0; i < lines; ++i) {
            QRectF trueSize;
            trueSize = p.boundingRect(QRectF(QPointF(0,0), size), 0, strings[i]);
            cacheText[i] = QPixmap(trueSize.size().toSize());
            cacheText[i].fill(Qt::transparent);
            QPainter paint(&cacheText[i]);
            paint.setPen(Qt::black);
            paint.drawText(QRectF(QPointF(0,0), trueSize.size().toSize()), strings[i]);
        }
        first = false;
    }
    for (int i = 0; i < count; i++) {
        for (int j = 0; j < lines; ++j) {
            p.drawPixmap(0,j*spacing,cacheText[j]);
        }
    }
}

void paint_RoundedRect(QPainter &p)
{
    p.setRenderHint(QPainter::Antialiasing, true);
    p.setPen(Qt::black);
    p.setBrush(Qt::red);
    for (int i = 0; i < count; i++) {
        for (int j = 0; j < lines; ++j) {
            QSize size((j+1)*50, spacing-1);
            p.drawRoundedRect(QRectF(QPointF(0,j*spacing), size), 8, 8);
        }
    }
}

void paint_QPixmapCachedRoundedRect(QPainter &p)
{
    static bool first = true;
    static QPixmap cacheRect[lines];
    if (first) {
        for (int i = 0; i < lines; ++i) {
            QSize size((i+1)*50, spacing-1);
            cacheRect[i] = QPixmap(size);
            cacheRect[i].fill(Qt::transparent);
            QPainter paint(&cacheRect[i]);
            paint.setRenderHint(QPainter::Antialiasing);
            paint.setPen(Qt::black);
            paint.setBrush(Qt::red);
            paint.drawRoundedRect(QRect(QPoint(0,0), size), 8, 8);
        }
        first = false;
    }
    for (int i = 0; i < count; i++) {
        for (int j = 0; j < lines; ++j) {
            p.drawPixmap(0,j*spacing,cacheRect[j]);
        }
    }
}

typedef void(*PaintFunc)(QPainter &);

struct {
    const char *name;
    PaintFunc func;
} funcs[] = {
    { "QTextLayoutNoCache", &paint_QTextLayout_noCache },
    { "QTextLayoutWithCache", &paint_QTextLayout_cache },
#ifdef HAVE_STATICTEXT
    { "QStaticTextNoBackendOptimizations", &paint_QStaticText_noOptimizations },
    { "QStaticTextWithBackendOptimizations", &paint_QStaticText_optimizations },
#endif
    { "CachedText", &paint_QPixmapCachedText },
    { "RoundedRect", &paint_RoundedRect },
    { "CachedRoundedRect", &paint_QPixmapCachedRoundedRect },
    { 0, 0 }
};

PaintFunc testFunc = 0;

class MyGLWidget : public QGLWidget
{
public:
    MyGLWidget(const QGLFormat &format) : QGLWidget(format), frames(0) {
        const char chars[] = "abcd efgh ijkl mnop qrst uvwx yz!$. ABCD 1234";
        int len = strlen(chars);
        for (int i = 0; i < lines; ++i) {
            for (int j = 0; j < 60; j++) {
                strings[i] += QChar(chars[rand() % len]);
            }
        }
    }

    void paintEvent(QPaintEvent *) {
        static int last = 0;
        static bool firstRun = true;
        if (firstRun == 0) {
            timer.start();
            firstRun = false;
        } else {
            int elapsed = timer.elapsed();
            qDebug() << "frame elapsed:" << elapsed - last;
            last = elapsed;
        }
        QPainter p(this);
	p.fillRect(rect(), Qt::white);
	p.setPen(Qt::black);
        QTime drawTimer;
        drawTimer.start();
        testFunc(p);
        qDebug() << "draw time" << drawTimer.elapsed();
        if (iterations--)
            update();
        else
            qApp->quit();
    }

    QTime timer;
    int frames;
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    bool sampleBuffers = false;

    for (int i = 1; i < argc; ++i) {
        QString arg = argv[i];
        if (arg == "-test") {
            arg = argv[++i];
            int j = 0;
            while (funcs[j].name) {
                if (arg == funcs[j].name) {
                    testFunc = funcs[j].func;
                    qDebug() << "Running test" << arg;
                    break;
                }
                ++j;
            }
        } else if (arg == "-iterations") {
            arg = argv[++i];
            iterations = arg.toInt();
        } else if (arg == "-sampleBuffers") {
            sampleBuffers = true;
        }
    }

    if (testFunc == 0) {
        qDebug() << "Usage: textspeed -test <test> [-sampleBuffers] [-iterations n]";
        qDebug() << "where <test> can be:";
        int j = 0;
        while (funcs[j].name) {
            qDebug() << "  " << funcs[j].name;
            ++j;
        }
        exit(1);
    }

    QWidget w;
    QGLFormat format = QGLFormat::defaultFormat();
    format.setSampleBuffers(sampleBuffers);
    MyGLWidget *glw = new MyGLWidget(format);
    glw->setAutoFillBackground(false);
    QVBoxLayout *layout = new QVBoxLayout(&w);
    w.setLayout(layout);
    layout->addWidget(glw);
    w.showFullScreen();
    app.exec();

    return 0;
}
<commit_msg>Add license header.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QApplication>
#include <QPixmap>
#include <QImage>
#include <QPainter>
#include <QGLWidget>
#include <QTextLayout>
#include <QVBoxLayout>
#include <QTime>
#include <QDebug>

#ifdef HAVE_STATICTEXT
#include <private/qstatictext_p.h>
#endif

int iterations = 20;
const int count = 600;
const int lines = 12;
const int spacing = 36;
QSizeF size(1000, 800);
const qreal lineWidth = 1000;
QString strings[lines];

void paint_QTextLayout(QPainter &p, bool useCache)
{
    static bool first = true;
    static QTextLayout *textLayout[lines];
    if (first) {
        for (int i = 0; i < lines; ++i) {
            textLayout[i] = new QTextLayout(strings[i]);
            int leading = p.fontMetrics().leading();
            qreal height = 0;
            qreal widthUsed = 0;
            textLayout[i]->setCacheEnabled(useCache);
            textLayout[i]->beginLayout();
            while (1) {
                QTextLine line = textLayout[i]->createLine();
                if (!line.isValid())
                        break;

                line.setLineWidth(lineWidth);
                height += leading;
                line.setPosition(QPointF(0, height));
                height += line.height();
                widthUsed = qMax(widthUsed, line.naturalTextWidth());
            }
            textLayout[i]->endLayout();
        }
        first = false;
    }
    for (int i = 0; i < count; ++i) {
        for (int j = 0; j < lines; ++j) {
            textLayout[j]->draw(&p, QPoint(0, j*spacing));
        }
    }
}

void paint_QTextLayout_noCache(QPainter &p)
{
    paint_QTextLayout(p, false);
}

void paint_QTextLayout_cache(QPainter &p)
{
    paint_QTextLayout(p, true);
}

#ifdef HAVE_STATICTEXT
void paint_QStaticText(QPainter &p, bool useOptimizations)
{
    static QStaticText *staticText[lines];
    static bool first = true;
    if (first) {
        for (int i = 0; i < lines; ++i) {
            staticText[i] = new QStaticText(strings[i]);
            staticText[i]->setUseBackendOptimizations(useOptimizations);
        }
        first = false;
    }
    for (int i = 0; i < count; ++i) {
        for (int j = 0; j < lines; ++j) {
            p.drawStaticText(QPointF(0, 30 + j*spacing), *staticText[j]);
        }
    }
}

void paint_QStaticText_noOptimizations(QPainter &p)
{
    paint_QStaticText(p, false);
}

void paint_QStaticText_optimizations(QPainter &p)
{
    paint_QStaticText(p, true);
}
#endif

void paint_QPixmapCachedText(QPainter &p)
{
    static bool first = true;
    static QPixmap cacheText[lines];
    if (first) {
        for (int i = 0; i < lines; ++i) {
            QRectF trueSize;
            trueSize = p.boundingRect(QRectF(QPointF(0,0), size), 0, strings[i]);
            cacheText[i] = QPixmap(trueSize.size().toSize());
            cacheText[i].fill(Qt::transparent);
            QPainter paint(&cacheText[i]);
            paint.setPen(Qt::black);
            paint.drawText(QRectF(QPointF(0,0), trueSize.size().toSize()), strings[i]);
        }
        first = false;
    }
    for (int i = 0; i < count; i++) {
        for (int j = 0; j < lines; ++j) {
            p.drawPixmap(0,j*spacing,cacheText[j]);
        }
    }
}

void paint_RoundedRect(QPainter &p)
{
    p.setRenderHint(QPainter::Antialiasing, true);
    p.setPen(Qt::black);
    p.setBrush(Qt::red);
    for (int i = 0; i < count; i++) {
        for (int j = 0; j < lines; ++j) {
            QSize size((j+1)*50, spacing-1);
            p.drawRoundedRect(QRectF(QPointF(0,j*spacing), size), 8, 8);
        }
    }
}

void paint_QPixmapCachedRoundedRect(QPainter &p)
{
    static bool first = true;
    static QPixmap cacheRect[lines];
    if (first) {
        for (int i = 0; i < lines; ++i) {
            QSize size((i+1)*50, spacing-1);
            cacheRect[i] = QPixmap(size);
            cacheRect[i].fill(Qt::transparent);
            QPainter paint(&cacheRect[i]);
            paint.setRenderHint(QPainter::Antialiasing);
            paint.setPen(Qt::black);
            paint.setBrush(Qt::red);
            paint.drawRoundedRect(QRect(QPoint(0,0), size), 8, 8);
        }
        first = false;
    }
    for (int i = 0; i < count; i++) {
        for (int j = 0; j < lines; ++j) {
            p.drawPixmap(0,j*spacing,cacheRect[j]);
        }
    }
}

typedef void(*PaintFunc)(QPainter &);

struct {
    const char *name;
    PaintFunc func;
} funcs[] = {
    { "QTextLayoutNoCache", &paint_QTextLayout_noCache },
    { "QTextLayoutWithCache", &paint_QTextLayout_cache },
#ifdef HAVE_STATICTEXT
    { "QStaticTextNoBackendOptimizations", &paint_QStaticText_noOptimizations },
    { "QStaticTextWithBackendOptimizations", &paint_QStaticText_optimizations },
#endif
    { "CachedText", &paint_QPixmapCachedText },
    { "RoundedRect", &paint_RoundedRect },
    { "CachedRoundedRect", &paint_QPixmapCachedRoundedRect },
    { 0, 0 }
};

PaintFunc testFunc = 0;

class MyGLWidget : public QGLWidget
{
public:
    MyGLWidget(const QGLFormat &format) : QGLWidget(format), frames(0) {
        const char chars[] = "abcd efgh ijkl mnop qrst uvwx yz!$. ABCD 1234";
        int len = strlen(chars);
        for (int i = 0; i < lines; ++i) {
            for (int j = 0; j < 60; j++) {
                strings[i] += QChar(chars[rand() % len]);
            }
        }
    }

    void paintEvent(QPaintEvent *) {
        static int last = 0;
        static bool firstRun = true;
        if (firstRun == 0) {
            timer.start();
            firstRun = false;
        } else {
            int elapsed = timer.elapsed();
            qDebug() << "frame elapsed:" << elapsed - last;
            last = elapsed;
        }
        QPainter p(this);
	p.fillRect(rect(), Qt::white);
	p.setPen(Qt::black);
        QTime drawTimer;
        drawTimer.start();
        testFunc(p);
        qDebug() << "draw time" << drawTimer.elapsed();
        if (iterations--)
            update();
        else
            qApp->quit();
    }

    QTime timer;
    int frames;
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    bool sampleBuffers = false;

    for (int i = 1; i < argc; ++i) {
        QString arg = argv[i];
        if (arg == "-test") {
            arg = argv[++i];
            int j = 0;
            while (funcs[j].name) {
                if (arg == funcs[j].name) {
                    testFunc = funcs[j].func;
                    qDebug() << "Running test" << arg;
                    break;
                }
                ++j;
            }
        } else if (arg == "-iterations") {
            arg = argv[++i];
            iterations = arg.toInt();
        } else if (arg == "-sampleBuffers") {
            sampleBuffers = true;
        }
    }

    if (testFunc == 0) {
        qDebug() << "Usage: textspeed -test <test> [-sampleBuffers] [-iterations n]";
        qDebug() << "where <test> can be:";
        int j = 0;
        while (funcs[j].name) {
            qDebug() << "  " << funcs[j].name;
            ++j;
        }
        exit(1);
    }

    QWidget w;
    QGLFormat format = QGLFormat::defaultFormat();
    format.setSampleBuffers(sampleBuffers);
    MyGLWidget *glw = new MyGLWidget(format);
    glw->setAutoFillBackground(false);
    QVBoxLayout *layout = new QVBoxLayout(&w);
    w.setLayout(layout);
    layout->addWidget(glw);
    w.showFullScreen();
    app.exec();

    return 0;
}
<|endoftext|>


<commit_before>#include <drafts/OpenCL/GL.hpp>

#include <DO/Sara/Core/DebugUtilities.hpp>
#include <DO/Sara/Core/HDF5.hpp>
#include <DO/Sara/Core/StringFormat.hpp>
#include <DO/Sara/Core/Timer.hpp>
#include <DO/Sara/ImageIO.hpp>
#include <DO/Sara/ImageProcessing/Flip.hpp>

#include <DO/Kalpana/Math/Projection.hpp>

#ifdef _WIN32
#include <windows.h>
#endif

#include <GLFW/glfw3.h>

#include <Eigen/Geometry>

#include <map>

using namespace DO::Sara;
using namespace std;

namespace kalpana = DO::Kalpana;

auto resize_framebuffer(GLFWwindow*, int width, int height)
{
  // make sure the viewport matches the new window dimensions; note that width
  // and height will be significantly larger than specified on retina displays.
  glViewport(0, 0, width, height);
}

inline auto init_glfw_boilerplate()
{
  // Initialize the windows manager.
  if (!glfwInit())
    throw std::runtime_error{"Error: failed to initialize GLFW!"};

  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

}

inline auto init_glew_boilerplate()
{
#ifndef __APPLE__
  // Initialize GLEW.
  auto err = glewInit();
  if (err != GLEW_OK)
  {
    std::cerr << format("Error: failed to initialize GLEW: %s",
                        glewGetErrorString(err))
              << std::endl;
  }
#endif
}

struct View
{
  View()
  {
    view.setIdentity();
    view.translate(Vector3f{0.f, 0.f, -100.f});
  }

  auto move_left(float delta)
  {
    view.translate(-scale * delta * Vector3f::UnitX());
  }

  auto move_right(float delta)
  {
    view.translate(scale * delta * Vector3f::UnitX());
  }

  auto move_backward(float delta)
  {
    view.translate(-scale * delta * Vector3f::UnitZ());
  }

  auto move_forward(float delta)
  {
    view.translate(scale * delta * Vector3f::UnitZ());
  }

  auto matrix() const -> const Matrix4f&
  {
    return view.matrix();
  }

  Transform<float, 3, Eigen::Projective> view;

  float scale = 1e-1f;
};

// Default camera values
static const float YAW         = -90.0f;
static const float PITCH       =  0.0f;
static const float SPEED       =  2.5f;
static const float SENSITIVITY =  0.1f;
static const float ZOOM        =  45.0f;

// The explorer's eye.
struct Eye
{
  Vector3f position{Vector3f::Zero()};
  Vector3f front{-Vector3f::UnitZ()};
  Vector3f up{Vector3f::UnitY()};
  Vector3f right;
  Vector3f world_up;

  float yaw{YAW};
  float pitch{PITCH};

  float movement_speed{SPEED};
  float movement_sensitivity{SENSITIVITY};
  float zoom{ZOOM};

  auto move_x(float delta)
  {
    position.x() += movement_speed * delta;
  }

  auto move_y(float delta)
  {
    position.y() += movement_speed * delta;
  }

  auto move_z(float delta)
  {
    position.z() += movement_speed * delta;
  }

  // pitch
  auto yes_head_move(float delta)
  {
    pitch += movement_sensitivity * delta;
  }

  // yaw
  auto no_head_movement(float delta)
  {
    yaw += movement_sensitivity * delta;
  }

  auto update()
  {
    Vector3f front1;
    front1 << cos(yaw * M_PI / 180) * cos(pitch * M_PI / 180.f),
              sin(pitch * M_PI / 180.f),
              sin(yaw * M_PI / 180.f) * cos(pitch * M_PI / 180.f);
    front = front1.normalized();

    right = front.cross(world_up).normalized();
    up = right.cross(front).normalized();
  }

  auto view_matrix() -> Matrix4f
  {
    return {};
  }
};

struct Time
{
  void update()
  {
    last_frame = current_frame;
    current_frame = timer.elapsed_ms();
    delta_time = current_frame - last_frame;
  }

  Timer timer;
  float delta_time = 0.f;
  float last_frame = 0.f;
  float current_frame = 0.f;
};

auto move_camera_from_keyboard(GLFWwindow* window, View& view, Time& time)
{
  if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
    view.move_forward(time.delta_time);
  if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
    view.move_backward(time.delta_time);
  if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
    view.move_left(time.delta_time);
  if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
    view.move_right(time.delta_time);
}

auto first_mouse = true;
float last_x = 800.f / 2.f;
float last_y = 600.f / 2.f;

auto move_camera_from_mouse(GLFWwindow* window, double x_pos, double y_pos)
{
  if (first_mouse)
  {
    last_x = x_pos;
    last_y = y_pos;
    first_mouse = false;
  }

  const auto xoff = x_pos - last_x;
  const auto yoff = y_pos - last_y;

  last_x = x_pos;
  last_y = y_pos;
}

auto read_point_cloud(const std::string& h5_filepath) -> Tensor_<float, 2>
{
  auto h5_file = H5File{h5_filepath, H5F_ACC_RDONLY};

  auto coords = Tensor_<double, 2>{};
  h5_file.read_dataset("points", coords);
  coords.matrix() *= -1;

  auto colors = Tensor_<double, 2>{};
  h5_file.read_dataset("colors", colors);
  SARA_DEBUG << "OK" << std::endl;

  // Concatenate the data.
  auto vertex_data = Tensor_<double, 2>{{coords.size(0), 6}};
  vertex_data.matrix() << coords.matrix(), colors.matrix();

  return vertex_data.cast<float>();
}

auto make_point_cloud()
{
  // Encode the vertex data in a tensor.
#ifdef __APPLE__
  const auto vertex_data = read_point_cloud("/Users/david/Desktop/geometry.h5");
#else
  const auto vertex_data = read_point_cloud("/home/david/Desktop/geometry.h5");
#endif
  SARA_DEBUG << "vertices =\n" << vertex_data.matrix() << std::endl;
  return vertex_data;
}

int main()
{
  // ==========================================================================
  // Display initialization.
  //
  init_glfw_boilerplate();

  // Create a window.
  const auto width = 800;
  const auto height = 600;
  auto window =
      glfwCreateWindow(width, height, "Hello Point Cloud", nullptr, nullptr);
  glfwMakeContextCurrent(window);
  glfwSetFramebufferSizeCallback(window, resize_framebuffer);
  glfwSetCursorPosCallback(window, move_camera_from_mouse);

  init_glew_boilerplate();

  // ==========================================================================
  // Shader program setup.
  //
  std::map<std::string, int> arg_pos = {{"in_coords", 0},  //
                                        {"in_color", 1}};

  const auto vertex_shader_source = R"shader(
#version 330 core
  layout (location = 0) in vec3 in_coords;
  layout (location = 1) in vec3 in_color;

  uniform mat4 transform;
  uniform mat4 view;
  uniform mat4 projection;

  out vec3 out_color;

  void main()
  {
    gl_Position = projection * view * transform * vec4(in_coords, 1.0);
    gl_PointSize = 5.0;
    out_color = in_color;
  }
  )shader";
  auto vertex_shader = GL::Shader{};
  vertex_shader.create_from_source(GL_VERTEX_SHADER, vertex_shader_source);

  const auto fragment_shader_source = R"shader(
#version 330 core
  in vec3 out_color;
  out vec4 frag_color;

  void main()
  {
    vec2 circCoord = 2.0 * gl_PointCoord - 1.0;
    if (dot(circCoord, circCoord) > 1.0)
        discard;

    float dist = length(gl_PointCoord - vec2(0.5));
    float alpha = 1.0 - smoothstep(0.2, 0.5, dist);

    frag_color = vec4(out_color, alpha);
  }
  )shader";
  auto fragment_shader = GL::Shader{};
  fragment_shader.create_from_source(GL_FRAGMENT_SHADER,
                                     fragment_shader_source);

  auto shader_program = GL::ShaderProgram{};
  shader_program.create();
  shader_program.attach(vertex_shader, fragment_shader);

  vertex_shader.destroy();
  fragment_shader.destroy();

  // ==========================================================================
  // Encode the vertex data in a tensor.
  //
  auto vertices = make_point_cloud();

  const auto row_bytes = [](const TensorView_<float, 2>& data) {
    return data.size(1) * sizeof(float);
  };
  const auto float_pointer = [](int offset) {
    return reinterpret_cast<void*>(offset * sizeof(float));
  };

  auto vao = GL::VertexArray{};
  vao.generate();

  // ==========================================================================
  // Setup Vertex attributes on the GPU side.
  //
  auto vbo = GL::Buffer{};
  vbo.generate();
  {
    glBindVertexArray(vao);

    // Copy vertex data.
    vbo.bind_vertex_data(vertices);

    // Map the parameters to the argument position for the vertex shader.
    //
    // Vertex coordinates.
    glVertexAttribPointer(arg_pos["in_coords"], 3 /* 3D points */, GL_FLOAT,
                          GL_FALSE, row_bytes(vertices), float_pointer(0));
    glEnableVertexAttribArray(arg_pos["in_coords"]);

    // Texture coordinates.
    glVertexAttribPointer(arg_pos["in_color"], 3 /* RGB_COLOR */, GL_FLOAT,
                          GL_FALSE, row_bytes(vertices), float_pointer(3));
    glEnableVertexAttribArray(arg_pos["in_color"]);
  }

  shader_program.use(true);

  // ==========================================================================
  // Setup options for point cloud rendering.
  glEnable(GL_POINT_SMOOTH);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glEnable(GL_PROGRAM_POINT_SIZE);

  // You absolutely need this for 3D objects!
  glEnable(GL_DEPTH_TEST);

  auto view = View{};
  auto time = Time{};

  // Display image.
  glfwSwapInterval(1);
  while (!glfwWindowShouldClose(window))
  {
    // Calculate the elapsed time.
    time.update();

    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
      glfwSetWindowShouldClose(window, true);

    // Camera interaction with keyboard.
    move_camera_from_keyboard(window, view, time);
    view.view.matrix() = rot_mat * view.view.matrix();

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    // Important.
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Transform matrix.
    auto transform = Transform<float, 3, Eigen::Projective>{};
    transform.setIdentity();
    //transform.rotate(AngleAxisf(std::pow(1.5, 5) * time.last_frame / 10000,
    //                            Vector3f{0.5f, 1.0f, 0.0f}.normalized()));
    shader_program.set_uniform_matrix4f("transform", transform.matrix().data());

    // View matrix.
    shader_program.set_uniform_matrix4f("view", view.matrix().data());

    // Projection matrix.
    const Matrix4f projection =
        kalpana::perspective(45., 800. / 600., .1, 1000.).cast<float>();
    shader_program.set_uniform_matrix4f("projection", projection.data());

    // Draw triangles.
    glBindVertexArray(vao);
    glDrawArrays(GL_POINTS, 0, vertices.size(0));

    glfwSwapBuffers(window);
    glfwPollEvents();
  }

  vao.destroy();
  vbo.destroy();

  // Clean up resources.
  glfwDestroyWindow(window);
  glfwTerminate();

  return EXIT_SUCCESS;
}
<commit_msg>MAINT: add movable eye to explore the point cloud.<commit_after>#include <drafts/OpenCL/GL.hpp>

#include <DO/Sara/Core/DebugUtilities.hpp>
#include <DO/Sara/Core/HDF5.hpp>
#include <DO/Sara/Core/StringFormat.hpp>
#include <DO/Sara/Core/Timer.hpp>
#include <DO/Sara/ImageIO.hpp>
#include <DO/Sara/ImageProcessing/Flip.hpp>

#include <DO/Kalpana/Math/Projection.hpp>

#ifdef _WIN32
#include <windows.h>
#endif

#include <GLFW/glfw3.h>

#include <Eigen/Geometry>

#include <map>

using namespace DO::Sara;
using namespace std;

namespace kalpana = DO::Kalpana;

auto resize_framebuffer(GLFWwindow*, int width, int height)
{
  // make sure the viewport matches the new window dimensions; note that width
  // and height will be significantly larger than specified on retina displays.
  glViewport(0, 0, width, height);
}

inline auto init_glfw_boilerplate()
{
  // Initialize the windows manager.
  if (!glfwInit())
    throw std::runtime_error{"Error: failed to initialize GLFW!"};

  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

}

inline auto init_glew_boilerplate()
{
#ifndef __APPLE__
  // Initialize GLEW.
  auto err = glewInit();
  if (err != GLEW_OK)
  {
    std::cerr << format("Error: failed to initialize GLEW: %s",
                        glewGetErrorString(err))
              << std::endl;
  }
#endif
}

// Default camera values
static const float YAW         = -90.0f;
static const float PITCH       =  0.0f;
static const float SPEED       =  1e-1f;
static const float SENSITIVITY =  1e-1f;
static const float ZOOM        =  45.0f;

// The explorer's eye.
struct Eye
{
  Vector3f position{Vector3f::Zero()};
  Vector3f front{-Vector3f::UnitZ()};
  Vector3f up{Vector3f::UnitY()}; Vector3f right;
  Vector3f world_up{Vector3f::UnitY()};

  float yaw{YAW};
  float pitch{PITCH};
  float roll{0.f};

  float movement_speed{SPEED};
  float movement_sensitivity{SENSITIVITY};
  float zoom{ZOOM};

  auto move_left(float delta)
  {
    position -= movement_speed * delta * right;
  }

  auto move_right(float delta)
  {
    position += movement_speed * delta * right;
  }

  auto move_forward(float delta)
  {
    position += movement_speed * delta * front;
  }

  auto move_backward(float delta)
  {
    position -= movement_speed * delta * front;
  }

  auto move_up(float delta)
  {
    position += movement_speed * delta * up;
  }

  auto move_down(float delta)
  {
    position -= movement_speed * delta * up;
  }

  // pitch
  auto yes_head_movement(float delta)
  {
    pitch += movement_sensitivity * delta;
  }

  // yaw
  auto no_head_movement(float delta)
  {
    yaw += movement_sensitivity * delta;
  }

  auto maybe_head_movement(float delta)
  {
    roll += movement_sensitivity * delta;
  }

  auto update()
  {
    Vector3f front1;

    front1 << cos(yaw * M_PI / 180) * cos(pitch * M_PI / 180.f),
              sin(pitch * M_PI / 180.f),
              sin(yaw * M_PI / 180.f) * cos(pitch * M_PI / 180.f);
    front = front1.normalized();

    right = front.cross(world_up).normalized();
    up = right.cross(front).normalized();

    SARA_DEBUG << "front = " << front.transpose() << std::endl;
    SARA_DEBUG << "right = " << right.transpose() << std::endl;
    SARA_DEBUG << "up = " << up.transpose() << std::endl;
  }

  auto view_matrix() -> Matrix4f
  {
    return look_at(position, position + front, up);
  }

  auto look_at(const Vector3f& eye, const Vector3f& center, const Vector3f& up)
      -> Matrix4f
  {
    Vector3f f = (center - eye).normalized();
    Vector3f u = up.normalized();
    Vector3f s = f.cross(u).normalized();
    u = s.cross(f);

    Matrix4f res;
    res <<
       s.x(),  s.y(),  s.z(), -s.dot(eye),
       u.x(),  u.y(),  u.z(), -u.dot(eye),
      -f.x(), -f.y(), -f.z(),  f.dot(eye),
           0,      0,      0,           1;

    return res;
    }
};

struct Time
{
  void update()
  {
    last_frame = current_frame;
    current_frame = timer.elapsed_ms();
    delta_time = current_frame - last_frame;
  }

  Timer timer;
  float delta_time = 0.f;
  float last_frame = 0.f;
  float current_frame = 0.f;
};

auto move_camera_from_keyboard(GLFWwindow* window, Eye& eye, Time& time)
{
  if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
    eye.move_forward(time.delta_time);
  if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
    eye.move_backward(time.delta_time);
  if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
    eye.move_left(time.delta_time);
  if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
    eye.move_right(time.delta_time);

  if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS)
    eye.no_head_movement(-time.delta_time); // CCW
  if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
    eye.no_head_movement(+time.delta_time); // CW

  if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS)
    eye.yes_head_movement(+time.delta_time);
  if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS)
    eye.yes_head_movement(-time.delta_time);

  if (glfwGetKey(window, GLFW_KEY_T) == GLFW_PRESS)
    eye.move_up(time.delta_time);
  if (glfwGetKey(window, GLFW_KEY_G) == GLFW_PRESS)
    eye.move_down(time.delta_time);

  eye.update();
}

auto read_point_cloud(const std::string& h5_filepath) -> Tensor_<float, 2>
{
  auto h5_file = H5File{h5_filepath, H5F_ACC_RDONLY};

  auto coords = Tensor_<double, 2>{};
  h5_file.read_dataset("points", coords);
  coords.matrix() *= -1;

  auto colors = Tensor_<double, 2>{};
  h5_file.read_dataset("colors", colors);
  SARA_DEBUG << "OK" << std::endl;

  // Concatenate the data.
  auto vertex_data = Tensor_<double, 2>{{coords.size(0), 6}};
  vertex_data.matrix() << coords.matrix(), colors.matrix();

  return vertex_data.cast<float>();
}

auto make_point_cloud()
{
  // Encode the vertex data in a tensor.
#ifdef __APPLE__
  const auto vertex_data = read_point_cloud("/Users/david/Desktop/geometry.h5");
#else
  const auto vertex_data = read_point_cloud("/home/david/Desktop/geometry.h5");
#endif
  SARA_DEBUG << "vertices =\n" << vertex_data.matrix() << std::endl;
  return vertex_data;
}

int main()
{
  // ==========================================================================
  // Display initialization.
  //
  init_glfw_boilerplate();

  // Create a window.
  const auto width = 800;
  const auto height = 600;
  auto window =
      glfwCreateWindow(width, height, "Hello Point Cloud", nullptr, nullptr);
  glfwMakeContextCurrent(window);
  glfwSetFramebufferSizeCallback(window, resize_framebuffer);
  //glfwSetCursorPosCallback(window, move_camera_from_mouse);

  init_glew_boilerplate();

  // ==========================================================================
  // Shader program setup.
  //
  std::map<std::string, int> arg_pos = {{"in_coords", 0},  //
                                        {"in_color", 1}};

  const auto vertex_shader_source = R"shader(
#version 330 core
  layout (location = 0) in vec3 in_coords;
  layout (location = 1) in vec3 in_color;

  uniform mat4 transform;
  uniform mat4 view;
  uniform mat4 projection;

  out vec3 out_color;

  void main()
  {
    gl_Position = projection * view * transform * vec4(in_coords, 1.0);
    gl_PointSize = 5.0;
    out_color = in_color;
  }
  )shader";
  auto vertex_shader = GL::Shader{};
  vertex_shader.create_from_source(GL_VERTEX_SHADER, vertex_shader_source);

  const auto fragment_shader_source = R"shader(
#version 330 core
  in vec3 out_color;
  out vec4 frag_color;

  void main()
  {
    vec2 circCoord = 2.0 * gl_PointCoord - 1.0;
    if (dot(circCoord, circCoord) > 1.0)
        discard;

    float dist = length(gl_PointCoord - vec2(0.5));
    float alpha = 1.0 - smoothstep(0.2, 0.5, dist);

    frag_color = vec4(out_color, alpha);
  }
  )shader";
  auto fragment_shader = GL::Shader{};
  fragment_shader.create_from_source(GL_FRAGMENT_SHADER,
                                     fragment_shader_source);

  auto shader_program = GL::ShaderProgram{};
  shader_program.create();
  shader_program.attach(vertex_shader, fragment_shader);

  vertex_shader.destroy();
  fragment_shader.destroy();

  // ==========================================================================
  // Encode the vertex data in a tensor.
  //
  auto vertices = make_point_cloud();

  const auto row_bytes = [](const TensorView_<float, 2>& data) {
    return data.size(1) * sizeof(float);
  };
  const auto float_pointer = [](int offset) {
    return reinterpret_cast<void*>(offset * sizeof(float));
  };

  auto vao = GL::VertexArray{};
  vao.generate();

  // ==========================================================================
  // Setup Vertex attributes on the GPU side.
  //
  auto vbo = GL::Buffer{};
  vbo.generate();
  {
    glBindVertexArray(vao);

    // Copy vertex data.
    vbo.bind_vertex_data(vertices);

    // Map the parameters to the argument position for the vertex shader.
    //
    // Vertex coordinates.
    glVertexAttribPointer(arg_pos["in_coords"], 3 /* 3D points */, GL_FLOAT,
                          GL_FALSE, row_bytes(vertices), float_pointer(0));
    glEnableVertexAttribArray(arg_pos["in_coords"]);

    // Texture coordinates.
    glVertexAttribPointer(arg_pos["in_color"], 3 /* RGB_COLOR */, GL_FLOAT,
                          GL_FALSE, row_bytes(vertices), float_pointer(3));
    glEnableVertexAttribArray(arg_pos["in_color"]);
  }

  shader_program.use(true);

  // ==========================================================================
  // Setup options for point cloud rendering.
  glEnable(GL_POINT_SMOOTH);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glEnable(GL_PROGRAM_POINT_SIZE);

  // You absolutely need this for 3D objects!
  glEnable(GL_DEPTH_TEST);

  auto eye = Eye{};
  auto time = Time{};

  // Display image.
  glfwSwapInterval(1);
  while (!glfwWindowShouldClose(window))
  {
    // Calculate the elapsed time.
    time.update();

    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
      glfwSetWindowShouldClose(window, true);

    // Camera interaction with keyboard.
    move_camera_from_keyboard(window, eye, time);
    auto view_matrix = eye.view_matrix();

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    // Important.
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Transform matrix.
    auto transform = Transform<float, 3, Eigen::Projective>{};
    transform.setIdentity();
    transform.rotate(AngleAxisf(std::pow(1.5, 5) * time.last_frame / 10000,
                                Vector3f{0.5f, 1.0f, 0.0f}.normalized()));
    shader_program.set_uniform_matrix4f("transform", transform.matrix().data());

    // View matrix.
    shader_program.set_uniform_matrix4f("view", view_matrix.data());

    // Projection matrix.
    const Matrix4f projection =
        kalpana::perspective(45., 800. / 600., .1, 1000.).cast<float>();
    shader_program.set_uniform_matrix4f("projection", projection.data());

    // Draw triangles.
    glBindVertexArray(vao);
    glDrawArrays(GL_POINTS, 0, vertices.size(0));

    glfwSwapBuffers(window);
    glfwPollEvents();
  }

  vao.destroy();
  vbo.destroy();

  // Clean up resources.
  glfwDestroyWindow(window);
  glfwTerminate();

  return EXIT_SUCCESS;
}
<|endoftext|>