<commit_before>/**
 * @file inverted_index_test.cpp
 * @author Sean Massung
 */

#include "test/inverted_index_test.h"

namespace meta
{
namespace testing
{

void create_config(const std::string& corpus_type)
{
    auto orig_config = cpptoml::parse_file("config.toml");
    std::string config_filename{"test-config.toml"};
    std::ofstream config_file{config_filename};

    auto stop_words = orig_config.get_as<std::string>("stop-words");
    if(!stop_words)
        throw std::runtime_error{"\"stop-words\" not in config"};

    auto libsvm_modules = orig_config.get_as<std::string>("libsvm-modules");
    if(!libsvm_modules)
        throw std::runtime_error{"\"libsvm-modules\" not in config"};

    auto query_judgements = orig_config.get_as<std::string>("query-judgements");
    if(!query_judgements)
        throw std::runtime_error{"\"query-judgements\" not in config"};

    auto punctuation = orig_config.get_as<std::string>("punctuation");
    if (!punctuation)
        throw std::runtime_error{"\"punctuation\" not in config"};

    auto start_exeptions = orig_config.get_as<std::string>("start-exceptions");
    if (!start_exeptions)
        throw std::runtime_error{"\"start-exceptions\" not in config"};

    auto end_exceptions = orig_config.get_as<std::string>("end-exceptions");
    if (!end_exceptions)
        throw std::runtime_error{"\"end-exceptions\" not in config"};

    config_file << "stop-words = \"" << *stop_words
                << "\"\n"
                << "punctuation = \"" << *punctuation << "\"\n"
                << "start-exceptions = \"" << *start_exeptions << "\"\n"
                << "end-exceptions = \"" << *end_exceptions << "\"\n"
                << "prefix = \"" << *orig_config.get_as<std::string>("prefix")
                << "\"\n"
                << "query-judgements = \"" << *query_judgements
                << "\"\n"
                << "libsvm-modules = \"" << *libsvm_modules
                << "\"\n"
                << "corpus-type = \"" << corpus_type << "-corpus\"\n"
                << "list= \"ceeaus\"\n"
                << "dataset = \"ceeaus\"\n"
                << "encoding = \"shift_jis\"\n"
                << "forward-index = \"ceeaus-fwd\"\n"
                << "inverted-index = \"ceeaus-inv\"\n"
                << "[[analyzers]]\n"
                << "method = \"ngram-word\"\n"
                << "ngram = 1\n"
                << "filter = \"default-chain\"";
}

template <class Index>
void check_ceeaus_expected(Index& idx)
{
    double epsilon = 0.000001;
    ASSERT_EQUAL(idx.num_docs(), 1008);
    ASSERT_LESS(std::abs(idx.avg_doc_length() - 128.556), epsilon);
    ASSERT_EQUAL(idx.unique_terms(), 3944);

    std::ifstream in{"../data/ceeaus-metadata.txt"};
    uint64_t size;
    uint64_t unique;
    doc_id id{0};
    while (in >> size >> unique)
    {
        ASSERT_EQUAL(idx.doc_size(id), size);
        ASSERT_EQUAL(idx.unique_terms(id), unique);
        ++id;
    }

    // make sure there's exactly the correct amount
    ASSERT_EQUAL(id, idx.num_docs());
}

template <class Index>
void check_term_id(Index& idx)
{
    term_id t_id = idx.get_term_id("japanes");
    ASSERT_EQUAL(idx.doc_freq(t_id), 69);

    term_id first;
    double second;
    std::ifstream in{"../data/ceeaus-term-count.txt"};
    auto pdata = idx.search_primary(t_id);
    for (auto& count : pdata->counts())
    {
        in >> first;
        in >> second;
        ASSERT_EQUAL(first, count.first);
        ASSERT_APPROX_EQUAL(second, count.second);
    }
}

int inverted_index_tests()
{
    create_config("file");

    int num_failed = 0;
    num_failed += testing::run_test("inverted-index-build-file-corpus", [&]()
    {
        system("rm -rf ceeaus-inv");
        auto idx =
            index::make_index<index::inverted_index, caching::splay_cache>(
                "test-config.toml", uint32_t{10000});
        check_ceeaus_expected(*idx);
    });

    num_failed += testing::run_test("inverted-index-read-file-corpus", [&]()
    {
        auto idx =
            index::make_index<index::inverted_index, caching::splay_cache>(
                "test-config.toml", uint32_t{10000});
        check_ceeaus_expected(*idx);
        check_term_id(*idx);
        system("rm -rf ceeaus-inv test-config.toml");
    });

    create_config("line");
    system("rm -rf ceeaus-inv");

    num_failed += testing::run_test("inverted-index-build-line-corpus", [&]()
    {
        auto idx =
            index::make_index<index::inverted_index, caching::splay_cache>(
                "test-config.toml", uint32_t{10000});
        check_ceeaus_expected(*idx);
    });

    num_failed += testing::run_test("inverted-index-read-line-corpus", [&]()
    {
        auto idx =
            index::make_index<index::inverted_index, caching::splay_cache>(
                "test-config.toml", uint32_t{10000});
        check_ceeaus_expected(*idx);
        check_term_id(*idx);
        check_term_id(*idx); // twice to check splay_caching
    });

    // test different caches

    num_failed += testing::run_test("inverted-index-dblru-cache", [&]()
    {
        auto idx = index::make_index<index::inverted_index,
                                     caching::default_dblru_cache>(
            "test-config.toml", uint64_t{1000});
        check_term_id(*idx);
        check_term_id(*idx);
    });

    num_failed += testing::run_test("inverted-index-no-evict-cache", [&]()
    {
        auto idx =
            index::make_index<index::inverted_index, caching::no_evict_cache>(
                "test-config.toml");
        check_term_id(*idx);
        check_term_id(*idx);
    });

    num_failed += testing::run_test("inverted-index-shard-cache", [&]()
    {
        auto idx = index::make_index<index::inverted_index,
                                     caching::splay_shard_cache>(
            "test-config.toml", uint8_t{8});
        check_term_id(*idx);
        check_term_id(*idx);
    });

    system("rm -rf ceeaus-inv test-config.toml");
    return num_failed;
}
}
}
<commit_msg>fix error masked by wrong call to integer abs (should have been std::abs)<commit_after>/**
 * @file inverted_index_test.cpp
 * @author Sean Massung
 */

#include "test/inverted_index_test.h"

namespace meta
{
namespace testing
{

void create_config(const std::string& corpus_type)
{
    auto orig_config = cpptoml::parse_file("config.toml");
    std::string config_filename{"test-config.toml"};
    std::ofstream config_file{config_filename};

    auto stop_words = orig_config.get_as<std::string>("stop-words");
    if(!stop_words)
        throw std::runtime_error{"\"stop-words\" not in config"};

    auto libsvm_modules = orig_config.get_as<std::string>("libsvm-modules");
    if(!libsvm_modules)
        throw std::runtime_error{"\"libsvm-modules\" not in config"};

    auto query_judgements = orig_config.get_as<std::string>("query-judgements");
    if(!query_judgements)
        throw std::runtime_error{"\"query-judgements\" not in config"};

    auto punctuation = orig_config.get_as<std::string>("punctuation");
    if (!punctuation)
        throw std::runtime_error{"\"punctuation\" not in config"};

    auto start_exeptions = orig_config.get_as<std::string>("start-exceptions");
    if (!start_exeptions)
        throw std::runtime_error{"\"start-exceptions\" not in config"};

    auto end_exceptions = orig_config.get_as<std::string>("end-exceptions");
    if (!end_exceptions)
        throw std::runtime_error{"\"end-exceptions\" not in config"};

    config_file << "stop-words = \"" << *stop_words
                << "\"\n"
                << "punctuation = \"" << *punctuation << "\"\n"
                << "start-exceptions = \"" << *start_exeptions << "\"\n"
                << "end-exceptions = \"" << *end_exceptions << "\"\n"
                << "prefix = \"" << *orig_config.get_as<std::string>("prefix")
                << "\"\n"
                << "query-judgements = \"" << *query_judgements
                << "\"\n"
                << "libsvm-modules = \"" << *libsvm_modules
                << "\"\n"
                << "corpus-type = \"" << corpus_type << "-corpus\"\n"
                << "list= \"ceeaus\"\n"
                << "dataset = \"ceeaus\"\n"
                << "encoding = \"shift_jis\"\n"
                << "forward-index = \"ceeaus-fwd\"\n"
                << "inverted-index = \"ceeaus-inv\"\n"
                << "[[analyzers]]\n"
                << "method = \"ngram-word\"\n"
                << "ngram = 1\n"
                << "filter = \"default-chain\"";
}

template <class Index>
void check_ceeaus_expected(Index& idx)
{
    double epsilon = 0.000001;
    ASSERT_EQUAL(idx.num_docs(), 1008);
    ASSERT_LESS(std::abs(idx.avg_doc_length() - 128.236), epsilon);
    ASSERT_EQUAL(idx.unique_terms(), 3944);

    std::ifstream in{"../data/ceeaus-metadata.txt"};
    uint64_t size;
    uint64_t unique;
    doc_id id{0};
    while (in >> size >> unique)
    {
        ASSERT_EQUAL(idx.doc_size(id), size);
        ASSERT_EQUAL(idx.unique_terms(id), unique);
        ++id;
    }

    // make sure there's exactly the correct amount
    ASSERT_EQUAL(id, idx.num_docs());
}

template <class Index>
void check_term_id(Index& idx)
{
    term_id t_id = idx.get_term_id("japanes");
    ASSERT_EQUAL(idx.doc_freq(t_id), 69);

    term_id first;
    double second;
    std::ifstream in{"../data/ceeaus-term-count.txt"};
    auto pdata = idx.search_primary(t_id);
    for (auto& count : pdata->counts())
    {
        in >> first;
        in >> second;
        ASSERT_EQUAL(first, count.first);
        ASSERT_APPROX_EQUAL(second, count.second);
    }
}

int inverted_index_tests()
{
    create_config("file");

    int num_failed = 0;
    num_failed += testing::run_test("inverted-index-build-file-corpus", [&]()
    {
        system("rm -rf ceeaus-inv");
        auto idx =
            index::make_index<index::inverted_index, caching::splay_cache>(
                "test-config.toml", uint32_t{10000});
        check_ceeaus_expected(*idx);
    });

    num_failed += testing::run_test("inverted-index-read-file-corpus", [&]()
    {
        auto idx =
            index::make_index<index::inverted_index, caching::splay_cache>(
                "test-config.toml", uint32_t{10000});
        check_ceeaus_expected(*idx);
        check_term_id(*idx);
        system("rm -rf ceeaus-inv test-config.toml");
    });

    create_config("line");
    system("rm -rf ceeaus-inv");

    num_failed += testing::run_test("inverted-index-build-line-corpus", [&]()
    {
        auto idx =
            index::make_index<index::inverted_index, caching::splay_cache>(
                "test-config.toml", uint32_t{10000});
        check_ceeaus_expected(*idx);
    });

    num_failed += testing::run_test("inverted-index-read-line-corpus", [&]()
    {
        auto idx =
            index::make_index<index::inverted_index, caching::splay_cache>(
                "test-config.toml", uint32_t{10000});
        check_ceeaus_expected(*idx);
        check_term_id(*idx);
        check_term_id(*idx); // twice to check splay_caching
    });

    // test different caches

    num_failed += testing::run_test("inverted-index-dblru-cache", [&]()
    {
        auto idx = index::make_index<index::inverted_index,
                                     caching::default_dblru_cache>(
            "test-config.toml", uint64_t{1000});
        check_term_id(*idx);
        check_term_id(*idx);
    });

    num_failed += testing::run_test("inverted-index-no-evict-cache", [&]()
    {
        auto idx =
            index::make_index<index::inverted_index, caching::no_evict_cache>(
                "test-config.toml");
        check_term_id(*idx);
        check_term_id(*idx);
    });

    num_failed += testing::run_test("inverted-index-shard-cache", [&]()
    {
        auto idx = index::make_index<index::inverted_index,
                                     caching::splay_shard_cache>(
            "test-config.toml", uint8_t{8});
        check_term_id(*idx);
        check_term_id(*idx);
    });

    system("rm -rf ceeaus-inv test-config.toml");
    return num_failed;
}
}
}
<|endoftext|>


<commit_before>// $Id$
//
//  Copyright (C) 2002-2008 Greg Landrum and Rational Discovery LLC
//     All Rights Reserved
//
#ifdef WIN32
#define CALGORITHMS_EXPORTS
#endif
#define PYTH_FILE_WITH_INIT
#include "Clustering.h"
#include <numpy/arrayobject.h>

#ifdef WIN32
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
    switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
		case DLL_THREAD_ATTACH:
		case DLL_THREAD_DETACH:
		case DLL_PROCESS_DETACH:
			break;
    }
    return TRUE;
}
#endif

typedef double real;

extern "C"
void distdriver_(long int *n,long int *len,
		 real *dists,
		 long int *toggle,
		 long int *ia,long int *ib,real *crit);

//
// Rather than deal with any nonsense like trying to get
// the distance matrix built properly on the f2c side of things
// (thus drowning in the waves of f2c hate), we'll generate
// the distance matrix on our own here and then call distdriver_
//
void clusterit(real *dataP,long int n,long int m,long int iopt,
	       long int *ia,long int *ib,real *crit){
  real *dists;
  long int len;
  long int pos = 0;
  long int i,j,k,iTab,jTab;
  double tmp;

  len = (n*(n-1))/2;
  dists = (real *)calloc(len,sizeof(real));
  for(i=1;i<n;i++){
    iTab = i*m;
    for(j=0;j<i;j++){
      jTab = j*m;
      for(k=0;k<m;k++){
	tmp = dataP[iTab+k]-dataP[jTab+k];
	dists[pos] += tmp*tmp;
      }
      pos++;
    }
  }
  distdriver_(&n,&len,dists,&iopt,ia,ib,crit);
  free(dists);
};

static PyObject *
Clustering_MurtaghCluster(PyObject *self,PyObject *args)
{
  PyArrayObject *dataContig;
  PyObject *data;
  int nPts,sz,option;
  long int *ia,*ib;
  real *crit;
  PyObject *res;
  PyObject *tmp;
  npy_intp dims[2];

  if(!PyArg_ParseTuple(args,"Oiii",&data,&nPts,&sz,&option))
    return NULL;
  dataContig = (PyArrayObject *)PyArray_ContiguousFromObject(data,PyArray_DOUBLE,2,2);

  ia = (long int *)calloc(nPts,sizeof(long int));
  ib = (long int *)calloc(nPts,sizeof(long int));
  crit = (real *)calloc(nPts,sizeof(real));

  clusterit((real *)dataContig->data,nPts,sz,option,ia,ib,crit);

  dims[0] = nPts;
  res = PyTuple_New(3);

  //  NOTE: these operations maintain pointers to the respective arrays,
  //  that's why it's ok that we do not free them in this function,
  //  Python will take care of it for us.
  //
  tmp = PyArray_SimpleNewFromData(1,dims,NPY_LONG,(void *)ia);
  PyTuple_SetItem(res,0,(PyObject *)tmp);

  tmp = PyArray_SimpleNewFromData(1,dims,NPY_LONG,(void *)ib);
  PyTuple_SetItem(res,1,(PyObject *)tmp);

  tmp = PyArray_SimpleNewFromData(1,dims,NPY_DOUBLE,(void *)crit);
  PyTuple_SetItem(res,2,(PyObject *)tmp);

  Py_DECREF(dataContig);
  return res;
};

void distclusterit(real *dists,long int n,long int iopt,
		   long int *ia,long int *ib,real *crit){
  long int len;

  len = (n*(n-1))/2;
  distdriver_(&n,&len,dists,&iopt,ia,ib,crit);
};

static PyObject *
Clustering_MurtaghDistCluster(PyObject *self,PyObject *args)
{
  PyArrayObject *dataContig;
  PyObject *data;
  long int nPts,option;
  long int *ia,*ib;
  real *crit;
  PyObject *res=PyTuple_New(3);
  PyObject *tmp;
  npy_intp dims[] = {1};

  if(!PyArg_ParseTuple(args,"Oii",&data,&nPts,&option))
    return NULL;

  dataContig = (PyArrayObject *)PyArray_ContiguousFromObject(data,PyArray_DOUBLE,1,1);
  ia = (long int *)calloc(nPts,sizeof(long int));
  ib = (long int *)calloc(nPts,sizeof(long int));
  crit = (real *)calloc(nPts,sizeof(real));
  distclusterit((real *)dataContig->data,nPts,option,ia,ib,crit);

  dims[0] = nPts;

  //
  //  NOTE: these operations maintain pointers to the respective arrays,
  //  that's why it's ok that we do not free them in this function,
  //  Python will take care of it for us.
  //
  tmp = PyArray_SimpleNewFromData(1,dims,NPY_LONG,(void *)ia);
  PyTuple_SetItem(res,0,tmp);

  tmp = PyArray_SimpleNewFromData(1,dims,NPY_LONG,(void *)ib);
  PyTuple_SetItem(res,1,tmp);

  tmp = PyArray_SimpleNewFromData(1,dims,NPY_DOUBLE,(void *)crit);
  PyTuple_SetItem(res,2,tmp);

  Py_DECREF(dataContig);
  return res;
};

static PyMethodDef locMethods[] = {
  {"MurtaghCluster",Clustering_MurtaghCluster,METH_VARARGS},
  {"MurtaghDistCluster",Clustering_MurtaghDistCluster,METH_VARARGS},
  {NULL,NULL}
};

CALGORITHMS_API void initClustering()
{
  (void) Py_InitModule("Clustering",locMethods);
#ifndef NO_IMPORT_ARRAY
  import_array();
#endif
}

<commit_msg>fix argument parsing problem on snow leopard<commit_after>// $Id$
//
//  Copyright (C) 2002-2010 Greg Landrum and Rational Discovery LLC
//     All Rights Reserved
//
#ifdef WIN32
#define CALGORITHMS_EXPORTS
#endif
#define PYTH_FILE_WITH_INIT
#include "Clustering.h"
#include <numpy/arrayobject.h>
#include <boost/cstdint.hpp>
#include <iostream>

#ifdef WIN32
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
    switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
		case DLL_THREAD_ATTACH:
		case DLL_THREAD_DETACH:
		case DLL_PROCESS_DETACH:
			break;
    }
    return TRUE;
}
#endif

typedef double real;

extern "C"
void distdriver_(boost::int64_t *n,boost::int64_t *len,
		 real *dists,
		 boost::int64_t *toggle,
		 boost::int64_t *ia,boost::int64_t *ib,real *crit);

//
// Rather than deal with any nonsense like trying to get
// the distance matrix built properly on the f2c side of things
// (thus drowning in the waves of f2c hate), we'll generate
// the distance matrix on our own here and then call distdriver_
//
void clusterit(real *dataP,boost::int64_t n,boost::int64_t m,boost::int64_t iopt,
	       boost::int64_t *ia,boost::int64_t *ib,real *crit){
  real *dists;
  boost::int64_t len;
  boost::int64_t pos = 0;
  boost::int64_t i,j,k,iTab,jTab;
  double tmp;
  len = (n*(n-1))/2;
  dists = (real *)calloc(len,sizeof(real));
  for(i=1;i<n;i++){
    iTab = i*m;
    for(j=0;j<i;j++){
      jTab = j*m;
      for(k=0;k<m;k++){
	tmp = dataP[iTab+k]-dataP[jTab+k];
	dists[pos] += tmp*tmp;
      }
      pos++;
    }
  }
  distdriver_(&n,&len,dists,&iopt,ia,ib,crit);
  free(dists);
};

static PyObject *
Clustering_MurtaghCluster(PyObject *self,PyObject *args)
{
  PyArrayObject *dataContig;
  PyObject *data;
  int nPts,sz,option;
  boost::int64_t *ia,*ib;
  real *crit;
  PyObject *res;
  PyObject *tmp;
  npy_intp dims[2];

  if(!PyArg_ParseTuple(args,"Oiii",&data,&nPts,&sz,&option))
    return NULL;
  dataContig = (PyArrayObject *)PyArray_ContiguousFromObject(data,PyArray_DOUBLE,2,2);

  ia = (boost::int64_t *)calloc(nPts,sizeof(boost::int64_t));
  ib = (boost::int64_t *)calloc(nPts,sizeof(boost::int64_t));
  crit = (real *)calloc(nPts,sizeof(real));

  clusterit((real *)dataContig->data,nPts,sz,option,ia,ib,crit);

  dims[0] = nPts;
  res = PyTuple_New(3);

  //  NOTE: these operations maintain pointers to the respective arrays,
  //  that's why it's ok that we do not free them in this function,
  //  Python will take care of it for us.
  //
  tmp = PyArray_SimpleNewFromData(1,dims,NPY_LONG,(void *)ia);
  PyTuple_SetItem(res,0,(PyObject *)tmp);

  tmp = PyArray_SimpleNewFromData(1,dims,NPY_LONG,(void *)ib);
  PyTuple_SetItem(res,1,(PyObject *)tmp);

  tmp = PyArray_SimpleNewFromData(1,dims,NPY_DOUBLE,(void *)crit);
  PyTuple_SetItem(res,2,(PyObject *)tmp);

  Py_DECREF(dataContig);
  return res;
};

void distclusterit(real *dists,boost::int64_t n,boost::int64_t iopt,
		   boost::int64_t *ia,boost::int64_t *ib,real *crit){
  boost::int64_t len;

  len = (n*(n-1))/2;
  distdriver_(&n,&len,dists,&iopt,ia,ib,crit);
};

static PyObject *
Clustering_MurtaghDistCluster(PyObject *self,PyObject *args)
{
  PyArrayObject *dataContig;
  PyObject *data;
  int nPts,option;
  boost::int64_t *ia,*ib;
  real *crit;
  PyObject *res=PyTuple_New(3);
  PyObject *tmp;
  npy_intp dims[] = {1};

  if(!PyArg_ParseTuple(args,"Oii",&data,&nPts,&option))
    return NULL;

  dataContig = (PyArrayObject *)PyArray_ContiguousFromObject(data,PyArray_DOUBLE,1,1);
  ia = (boost::int64_t *)calloc(nPts,sizeof(boost::int64_t));
  ib = (boost::int64_t *)calloc(nPts,sizeof(boost::int64_t));
  crit = (real *)calloc(nPts,sizeof(real));
  distclusterit((real *)dataContig->data,nPts,option,ia,ib,crit);

  dims[0] = nPts;

  //
  //  NOTE: these operations maintain pointers to the respective arrays,
  //  that's why it's ok that we do not free them in this function,
  //  Python will take care of it for us.
  //
  tmp = PyArray_SimpleNewFromData(1,dims,NPY_LONG,(void *)ia);
  PyTuple_SetItem(res,0,tmp);

  tmp = PyArray_SimpleNewFromData(1,dims,NPY_LONG,(void *)ib);
  PyTuple_SetItem(res,1,tmp);

  tmp = PyArray_SimpleNewFromData(1,dims,NPY_DOUBLE,(void *)crit);
  PyTuple_SetItem(res,2,tmp);

  Py_DECREF(dataContig);
  return res;
};

static PyMethodDef locMethods[] = {
  {"MurtaghCluster",Clustering_MurtaghCluster,METH_VARARGS},
  {"MurtaghDistCluster",Clustering_MurtaghDistCluster,METH_VARARGS},
  {NULL,NULL}
};

CALGORITHMS_API void initClustering()
{
  (void) Py_InitModule("Clustering",locMethods);
#ifndef NO_IMPORT_ARRAY
  import_array();
#endif
}

<|endoftext|>


<commit_before>#ifndef SILICIUM_ERROR_OR_HPP
#define SILICIUM_ERROR_OR_HPP

#include <silicium/optional.hpp>
#include <boost/system/system_error.hpp>
#include <boost/throw_exception.hpp>
#include <system_error>

namespace Si
{
	inline SILICIUM_NORETURN void throw_error(boost::system::error_code error)
	{
		boost::throw_exception(boost::system::system_error(error));
	}

	inline SILICIUM_NORETURN void throw_error(std::error_code error)
	{
		boost::throw_exception(std::system_error(error));
	}

	template <class Value, class Error = boost::system::error_code>
	struct error_or
	{
		error_or() BOOST_NOEXCEPT
			: value(Value()) //initialize so that reading the value does not have undefined behaviour
		{
		}

		template <class ConvertibleToValue, class = typename std::enable_if<std::is_convertible<ConvertibleToValue, Value>::value, void>::type>
		error_or(ConvertibleToValue &&value) BOOST_NOEXCEPT
			: value(std::forward<ConvertibleToValue>(value))
		{
		}

		error_or(Error error) BOOST_NOEXCEPT
			: error_(std::move(error))
		{
		}

#ifdef _MSC_VER
		error_or(error_or &&other) BOOST_NOEXCEPT
			: error_(std::move(other.error_))
			, value(std::move(other.value))
		{
		}

		error_or(error_or const &other)
			: error_(other.error_)
			, value(other.value)
		{
		}

		error_or &operator = (error_or &&other) BOOST_NOEXCEPT
		{
			error_ = std::move(other.error_);
			value = std::move(other.value);
			return *this;
		}

		error_or &operator = (error_or const &other)
		{
			error_ = other.error_;
			value = other.value;
			return *this;
		}
#endif

		bool is_error() const BOOST_NOEXCEPT
		{
			return !!error_;
		}

		Si::optional<Error> error() const BOOST_NOEXCEPT
		{
			if (error_)
			{
				return error_;
			}
			return none;
		}

		Value &get()
#if SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER
			&
#endif
		{
			if (error_)
			{
				throw_error(error_);
			}
			return value;
		}

#if SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER
		Value &&get() &&
		{
			if (error_)
			{
				throw_error(error_);
			}
			return std::move(value);
		}
#endif

		Value const &get() const
#if SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER
			&
#endif
		{
			if (error_)
			{
				throw_error(error_);
			}
			return value;
		}

		Value *get_ptr() BOOST_NOEXCEPT
		{
			if (error_)
			{
				return nullptr;
			}
			return &value;
		}

		Value const *get_ptr() const BOOST_NOEXCEPT
		{
			if (error_)
			{
				return nullptr;
			}
			return &value;
		}

		Value *operator -> ()
		{
			return &get();
		}

		Value const *operator -> () const
		{
			return &get();
		}

		boost::optional<Value> get_optional()
#if SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER
			&&
#endif
		{
			auto *value = get_ptr();
			if (!value)
			{
				return boost::none;
			}
			return std::move(*value);
		}

		bool equals(error_or const &other) const
		{
			if (is_error() != other.is_error())
			{
				return false;
			}
			if (is_error())
			{
				return error_ == other.error_;
			}
			return value == other.value;
		}

	private:

		Error error_;
		Value value;
	};

	namespace detail
	{
		template <class To, class From>
		From &&convert_if_necessary(From &&from, std::true_type)
		{
			return std::forward<From>(from);
		}

		template <class To, class From>
		To convert_if_necessary(From &&from, std::false_type)
		{
			return To(std::forward<From>(from));
		}
	}

	template <class Value, class Error>
	bool operator == (error_or<Value, Error> const &left, error_or<Value, Error> const &right)
	{
		return left.equals(right);
	}

	template <class Value, class Error, class ConvertibleToValue, class = typename std::enable_if<std::is_convertible<ConvertibleToValue, Value>::value, void>::type>
	bool operator == (error_or<Value, Error> const &left, ConvertibleToValue const &right)
	{
		if (left.is_error())
		{
			return false;
		}
		return left.get() == detail::convert_if_necessary<Value>(right, std::is_same<typename std::decay<Value>::type, typename std::decay<ConvertibleToValue>::type>());
	}

	template <class Value, class Error>
	bool operator == (error_or<Value, Error> const &left, Error const &right)
	{
		if (!left.is_error())
		{
			return false;
		}
		return *left.error() == right;
	}

	template <class Anything, class Value, class Error>
	bool operator == (Anything const &left, error_or<Value, Error> const &right)
	{
		return (right == left);
	}

	template <class Anything, class Value, class Error>
	bool operator != (Anything const &left, error_or<Value, Error> const &right)
	{
		return !(left == right);
	}

	template <class Anything, class Value, class Error>
	bool operator != (error_or<Value, Error> const &left, Anything const &right)
	{
		return !(left == right);
	}

	template <class Value, class Error>
	std::ostream &operator << (std::ostream &out, error_or<Value, Error> const &value)
	{
		if (value.error())
		{
			return out << *value.error();
		}
		return out << value.get();
	}

	template <class T>
	struct is_error_or : std::false_type
	{
	};

	template <class Value, class Error>
	struct is_error_or<error_or<Value, Error>> : std::true_type
	{
	};

	template <class ErrorOr, class OnValue, class CleanErrorOr = typename std::decay<ErrorOr>::type, class = typename std::enable_if<is_error_or<CleanErrorOr>::value, void>>
	auto map(ErrorOr &&maybe, OnValue &&on_value) -> CleanErrorOr
	{
		if (maybe.is_error())
		{
			return *maybe.error();
		}
		return std::forward<OnValue>(on_value)(std::forward<ErrorOr>(maybe).get());
	}
}

#endif
<commit_msg>fix infinite recursion bug in error_or operator ==<commit_after>#ifndef SILICIUM_ERROR_OR_HPP
#define SILICIUM_ERROR_OR_HPP

#include <silicium/optional.hpp>
#include <boost/system/system_error.hpp>
#include <boost/throw_exception.hpp>
#include <system_error>

namespace Si
{
	inline SILICIUM_NORETURN void throw_error(boost::system::error_code error)
	{
		boost::throw_exception(boost::system::system_error(error));
	}

	inline SILICIUM_NORETURN void throw_error(std::error_code error)
	{
		boost::throw_exception(std::system_error(error));
	}

	namespace detail
	{
		template <class To, class From>
		From &&convert_if_necessary(From &&from, std::true_type)
		{
			return std::forward<From>(from);
		}

		template <class To, class From>
		To convert_if_necessary(From &&from, std::false_type)
		{
			return To(std::forward<From>(from));
		}
	}

	template <class Value, class Error = boost::system::error_code>
	struct error_or
	{
		error_or() BOOST_NOEXCEPT
			: value(Value()) //initialize so that reading the value does not have undefined behaviour
		{
		}

		template <class ConvertibleToValue, class = typename std::enable_if<std::is_convertible<ConvertibleToValue, Value>::value, void>::type>
		error_or(ConvertibleToValue &&value) BOOST_NOEXCEPT
			: value(std::forward<ConvertibleToValue>(value))
		{
		}

		error_or(Error error) BOOST_NOEXCEPT
			: error_(std::move(error))
		{
		}

#ifdef _MSC_VER
		error_or(error_or &&other) BOOST_NOEXCEPT
			: error_(std::move(other.error_))
			, value(std::move(other.value))
		{
		}

		error_or(error_or const &other)
			: error_(other.error_)
			, value(other.value)
		{
		}

		error_or &operator = (error_or &&other) BOOST_NOEXCEPT
		{
			error_ = std::move(other.error_);
			value = std::move(other.value);
			return *this;
		}

		error_or &operator = (error_or const &other)
		{
			error_ = other.error_;
			value = other.value;
			return *this;
		}
#endif

		bool is_error() const BOOST_NOEXCEPT
		{
			return !!error_;
		}

		Si::optional<Error> error() const BOOST_NOEXCEPT
		{
			if (error_)
			{
				return error_;
			}
			return none;
		}

		Value &get()
#if SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER
			&
#endif
		{
			if (error_)
			{
				throw_error(error_);
			}
			return value;
		}

#if SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER
		Value &&get() &&
		{
			if (error_)
			{
				throw_error(error_);
			}
			return std::move(value);
		}
#endif

		Value const &get() const
#if SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER
			&
#endif
		{
			if (error_)
			{
				throw_error(error_);
			}
			return value;
		}

		Value *get_ptr() BOOST_NOEXCEPT
		{
			if (error_)
			{
				return nullptr;
			}
			return &value;
		}

		Value const *get_ptr() const BOOST_NOEXCEPT
		{
			if (error_)
			{
				return nullptr;
			}
			return &value;
		}

		Value *operator -> ()
		{
			return &get();
		}

		Value const *operator -> () const
		{
			return &get();
		}

		boost::optional<Value> get_optional()
#if SILICIUM_COMPILER_HAS_RVALUE_THIS_QUALIFIER
			&&
#endif
		{
			auto *value = get_ptr();
			if (!value)
			{
				return boost::none;
			}
			return std::move(*value);
		}

		template <class ComparableToValue>
		bool equals(error_or<ComparableToValue, Error> const &other) const
		{
			if (is_error() != other.is_error())
			{
				return false;
			}
			if (is_error())
			{
				return error_ == *other.error();
			}
			return value == other.get();
		}

		template <class ConvertibleToValue, class = typename std::enable_if<std::is_convertible<ConvertibleToValue, Value>::value, void>::type>
		bool equals(ConvertibleToValue const &right) const
		{
			if (is_error())
			{
				return false;
			}
			return get() == detail::convert_if_necessary<Value>(right, std::is_same<typename std::decay<Value>::type, typename std::decay<ConvertibleToValue>::type>());
		}

		bool equals(Error const &right) const
		{
			if (!is_error())
			{
				return false;
			}
			return *error() == right;
		}

	private:

		Error error_;
		Value value;
	};

	template <class T>
	struct is_error_or : std::false_type
	{
	};

	template <class Value, class Error>
	struct is_error_or<error_or<Value, Error>> : std::true_type
	{
	};

	template <class Value, class Error, class Anything>
	bool operator == (error_or<Value, Error> const &left, Anything const &right)
	{
		return left.equals(right);
	}

	template <class Anything, class Value, class Error, class = typename std::enable_if<!is_error_or<Anything>::value, void>::type>
	bool operator == (Anything const &left, error_or<Value, Error> const &right)
	{
		return right.equals(left);
	}

	template <class Anything, class Value, class Error>
	bool operator != (Anything const &left, error_or<Value, Error> const &right)
	{
		return !(left == right);
	}

	template <class Anything, class Value, class Error>
	bool operator != (error_or<Value, Error> const &left, Anything const &right)
	{
		return !(left == right);
	}

	template <class Value, class Error>
	std::ostream &operator << (std::ostream &out, error_or<Value, Error> const &value)
	{
		if (value.error())
		{
			return out << *value.error();
		}
		return out << value.get();
	}

	template <class ErrorOr, class OnValue, class CleanErrorOr = typename std::decay<ErrorOr>::type, class = typename std::enable_if<is_error_or<CleanErrorOr>::value, void>>
	auto map(ErrorOr &&maybe, OnValue &&on_value) -> error_or<decltype(std::forward<OnValue>(on_value)(std::forward<ErrorOr>(maybe).get()))>
	{
		if (maybe.is_error())
		{
			return *maybe.error();
		}
		return std::forward<OnValue>(on_value)(std::forward<ErrorOr>(maybe).get());
	}
}

#endif
<|endoftext|>


<commit_before>/***********************************************************************
    created:    Wed, 8th Feb 2012
    author:     Lukas E Meindl (based on code by Paul D Turner)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2012 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/RendererModules/OpenGL/RenderTarget.h"
#include "CEGUI/RenderQueue.h"
#include "CEGUI/RendererModules/OpenGL/GeometryBufferBase.h"

#include <cmath>

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
template <typename T>
const double OpenGLRenderTarget<T>::d_yfov_tan = 0.267949192431123;

//----------------------------------------------------------------------------//
template <typename T>
OpenGLRenderTarget<T>::OpenGLRenderTarget(OpenGLRendererBase& owner) :
    d_owner(owner),
    d_area(0, 0, 0, 0),
    d_matrix(1.0f),
    d_matrixValid(false),
    d_viewDistance(0)
{
}

//----------------------------------------------------------------------------//
template <typename T>
OpenGLRenderTarget<T>::~OpenGLRenderTarget()
{
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::draw(const GeometryBuffer& buffer)
{
    buffer.draw();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::draw(const RenderQueue& queue)
{
    queue.draw();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::setArea(const Rectf& area)
{
    d_area = area;
    d_matrixValid = false;

    RenderTargetEventArgs args(this);
    T::fireEvent(RenderTarget::EventAreaChanged, args);
}

//----------------------------------------------------------------------------//
template <typename T>
const Rectf& OpenGLRenderTarget<T>::getArea() const
{
    return d_area;
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::activate()
{
    glViewport(static_cast<GLsizei>(d_area.left()),
               static_cast<GLsizei>(d_area.top()),
               static_cast<GLsizei>(d_area.getWidth()),
               static_cast<GLsizei>(d_area.getHeight()));

    if (!d_matrixValid)
        updateMatrix();

    d_owner.setViewProjectionMatrix(d_matrix);

    RenderTarget::activate();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::deactivate()
{
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::unprojectPoint(const GeometryBuffer& buff,
    const Vector2f& p_in, Vector2f& p_out) const
{
    if (!d_matrixValid)
        updateMatrix();

    const OpenGLGeometryBufferBase& gb =
        static_cast<const OpenGLGeometryBufferBase&>(buff);

    const GLint vp[4] = {
        static_cast<GLint>(d_area.left()),
        static_cast<GLint>(d_area.top()),
        static_cast<GLint>(d_area.getWidth()),
        static_cast<GLint>(d_area.getHeight())
    };

    GLdouble in_x, in_y, in_z;

    glm::ivec4 viewPort = glm::ivec4(vp[0], vp[1], vp[2], vp[3]);
    const glm::mat4& projMatrix = d_matrix;
    const glm::mat4& modelMatrix = gb.getMatrix();

    // unproject the ends of the ray
    glm::vec3 unprojected1;
    glm::vec3 unprojected2;
    in_x = vp[2] * 0.5;
    in_y = vp[3] * 0.5;
    in_z = -d_viewDistance;
    unprojected1 =  glm::unProject(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = p_in.d_x;
    in_y = vp[3] - p_in.d_y;
    in_z = 0.0;
    unprojected2 = glm::unProject(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);

    // project points to orientate them with GeometryBuffer plane
    glm::vec3 projected1;
    glm::vec3 projected2;
    glm::vec3 projected3;
    in_x = 0.0;
    in_y = 0.0;
    projected1 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = 1.0;
    in_y = 0.0;
    projected2 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = 0.0;
    in_y = 1.0;
    projected3 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);

    // calculate vectors for generating the plane
    const glm::vec3 pv1 = projected2 - projected1;
    const glm::vec3 pv2 = projected3 - projected1;
    // given the vectors, calculate the plane normal
    const glm::vec3 planeNormal = glm::cross(pv1, pv2);
    // calculate plane
    const glm::vec3 planeNormalNormalized = glm::normalize(planeNormal);
    const double pl_d = - glm::dot(projected1, planeNormalNormalized);
    // calculate vector of picking ray
    const glm::vec3 rv = unprojected1 - unprojected2;
    // calculate intersection of ray and plane
    const double pn_dot_r1 = glm::dot(unprojected1, planeNormal);
    const double pn_dot_rv = glm::dot(rv, planeNormal);
    const double tmp1 = pn_dot_rv != 0.0 ? (pn_dot_r1 + pl_d) / pn_dot_rv : 0.0;
    const double is_x = unprojected1.x - rv.x * tmp1;
    const double is_y = unprojected1.y - rv.y * tmp1;

    p_out.d_x = static_cast<float>(is_x);
    p_out.d_y = static_cast<float>(is_y);

    p_out = p_in; // CrazyEddie wanted this
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::updateMatrix() const
{
    const float w = d_area.getWidth();
    const float h = d_area.getHeight();

    // We need to check if width or height are zero and act accordingly to prevent running into issues
    // with divisions by zero which would lead to undefined values, as well as faulty clipping planes
    // This is mostly important for avoiding asserts
    const bool widthAndHeightNotZero = ( w != 0.0f ) && ( h != 0.0f);

    const float aspect = widthAndHeightNotZero ? w / h : 1.0f;
    const float midx = widthAndHeightNotZero ? w * 0.5f : 0.5f;
    const float midy = widthAndHeightNotZero ? h * 0.5f : 0.5f;
    d_viewDistance = midx / (aspect * d_yfov_tan);

    glm::vec3 eye = glm::vec3(midx, midy, float(-d_viewDistance));
    glm::vec3 center = glm::vec3(midx, midy, 1);
    glm::vec3 up = glm::vec3(0, -1, 0);

    glm::mat4 projectionMatrix = glm::perspective(30.f, aspect, float(d_viewDistance * 0.5), float(d_viewDistance * 2.0));
    // Projection matrix abuse!
    glm::mat4 viewMatrix = glm::lookAt(eye, center, up);

    d_matrix = projectionMatrix * viewMatrix;

    d_matrixValid = true;
}

//----------------------------------------------------------------------------//
template <typename T>
Renderer& OpenGLRenderTarget<T>::getOwner()
{
    return d_owner;
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section
<commit_msg>MOD: Fixing activation counter<commit_after>/***********************************************************************
    created:    Wed, 8th Feb 2012
    author:     Lukas E Meindl (based on code by Paul D Turner)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2012 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/RendererModules/OpenGL/RenderTarget.h"
#include "CEGUI/RenderQueue.h"
#include "CEGUI/RendererModules/OpenGL/GeometryBufferBase.h"

#include <cmath>

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
template <typename T>
const double OpenGLRenderTarget<T>::d_yfov_tan = 0.267949192431123;

//----------------------------------------------------------------------------//
template <typename T>
OpenGLRenderTarget<T>::OpenGLRenderTarget(OpenGLRendererBase& owner) :
    d_owner(owner),
    d_area(0, 0, 0, 0),
    d_matrix(1.0f),
    d_matrixValid(false),
    d_viewDistance(0)
{
}

//----------------------------------------------------------------------------//
template <typename T>
OpenGLRenderTarget<T>::~OpenGLRenderTarget()
{
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::draw(const GeometryBuffer& buffer)
{
    buffer.draw();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::draw(const RenderQueue& queue)
{
    queue.draw();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::setArea(const Rectf& area)
{
    d_area = area;
    d_matrixValid = false;

    RenderTargetEventArgs args(this);
    T::fireEvent(RenderTarget::EventAreaChanged, args);
}

//----------------------------------------------------------------------------//
template <typename T>
const Rectf& OpenGLRenderTarget<T>::getArea() const
{
    return d_area;
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::activate()
{
    glViewport(static_cast<GLsizei>(d_area.left()),
               static_cast<GLsizei>(d_area.top()),
               static_cast<GLsizei>(d_area.getWidth()),
               static_cast<GLsizei>(d_area.getHeight()));

    if (!d_matrixValid)
        updateMatrix();

    d_owner.setViewProjectionMatrix(d_matrix);

    RenderTarget::activate();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::deactivate()
{
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::unprojectPoint(const GeometryBuffer& buff,
    const Vector2f& p_in, Vector2f& p_out) const
{
    if (!d_matrixValid)
        updateMatrix();

    const OpenGLGeometryBufferBase& gb =
        static_cast<const OpenGLGeometryBufferBase&>(buff);

    const GLint vp[4] = {
        static_cast<GLint>(d_area.left()),
        static_cast<GLint>(d_area.top()),
        static_cast<GLint>(d_area.getWidth()),
        static_cast<GLint>(d_area.getHeight())
    };

    GLdouble in_x, in_y, in_z;

    glm::ivec4 viewPort = glm::ivec4(vp[0], vp[1], vp[2], vp[3]);
    const glm::mat4& projMatrix = d_matrix;
    const glm::mat4& modelMatrix = gb.getMatrix();

    // unproject the ends of the ray
    glm::vec3 unprojected1;
    glm::vec3 unprojected2;
    in_x = vp[2] * 0.5;
    in_y = vp[3] * 0.5;
    in_z = -d_viewDistance;
    unprojected1 =  glm::unProject(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = p_in.d_x;
    in_y = vp[3] - p_in.d_y;
    in_z = 0.0;
    unprojected2 = glm::unProject(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);

    // project points to orientate them with GeometryBuffer plane
    glm::vec3 projected1;
    glm::vec3 projected2;
    glm::vec3 projected3;
    in_x = 0.0;
    in_y = 0.0;
    projected1 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = 1.0;
    in_y = 0.0;
    projected2 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = 0.0;
    in_y = 1.0;
    projected3 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);

    // calculate vectors for generating the plane
    const glm::vec3 pv1 = projected2 - projected1;
    const glm::vec3 pv2 = projected3 - projected1;
    // given the vectors, calculate the plane normal
    const glm::vec3 planeNormal = glm::cross(pv1, pv2);
    // calculate plane
    const glm::vec3 planeNormalNormalized = glm::normalize(planeNormal);
    const double pl_d = - glm::dot(projected1, planeNormalNormalized);
    // calculate vector of picking ray
    const glm::vec3 rv = unprojected1 - unprojected2;
    // calculate intersection of ray and plane
    const double pn_dot_r1 = glm::dot(unprojected1, planeNormal);
    const double pn_dot_rv = glm::dot(rv, planeNormal);
    const double tmp1 = pn_dot_rv != 0.0 ? (pn_dot_r1 + pl_d) / pn_dot_rv : 0.0;
    const double is_x = unprojected1.x - rv.x * tmp1;
    const double is_y = unprojected1.y - rv.y * tmp1;

    p_out.d_x = static_cast<float>(is_x);
    p_out.d_y = static_cast<float>(is_y);

    p_out = p_in; // CrazyEddie wanted this
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::updateMatrix() const
{
    const float w = d_area.getWidth();
    const float h = d_area.getHeight();

    // We need to check if width or height are zero and act accordingly to prevent running into issues
    // with divisions by zero which would lead to undefined values, as well as faulty clipping planes
    // This is mostly important for avoiding asserts
    const bool widthAndHeightNotZero = ( w != 0.0f ) && ( h != 0.0f);

    const float aspect = widthAndHeightNotZero ? w / h : 1.0f;
    const float midx = widthAndHeightNotZero ? w * 0.5f : 0.5f;
    const float midy = widthAndHeightNotZero ? h * 0.5f : 0.5f;
    d_viewDistance = midx / (aspect * d_yfov_tan);

    glm::vec3 eye = glm::vec3(midx, midy, float(-d_viewDistance));
    glm::vec3 center = glm::vec3(midx, midy, 1);
    glm::vec3 up = glm::vec3(0, -1, 0);

    glm::mat4 projectionMatrix = glm::perspective(30.f, aspect, float(d_viewDistance * 0.5), float(d_viewDistance * 2.0));
    // Projection matrix abuse!
    glm::mat4 viewMatrix = glm::lookAt(eye, center, up);

    d_matrix = projectionMatrix * viewMatrix;

    d_matrixValid = true;
    //! This triggers all GeometryBuffers to regenerate their matrices
    d_activationCounter = 0;
}

//----------------------------------------------------------------------------//
template <typename T>
Renderer& OpenGLRenderTarget<T>::getOwner()
{
    return d_owner;
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>/***********************************************************************
    created:    Wed, 8th Feb 2012
    author:     Lukas E Meindl (based on code by Paul D Turner)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2012 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/RendererModules/OpenGL/RenderTarget.h"
#include "CEGUI/RenderQueue.h"
#include "CEGUI/RendererModules/OpenGL/GeometryBufferBase.h"

#include <cmath>

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
template <typename T>
const double OpenGLRenderTarget<T>::d_yfov_tan = 0.267949192431123;

//----------------------------------------------------------------------------//
template <typename T>
OpenGLRenderTarget<T>::OpenGLRenderTarget(OpenGLRendererBase& owner) :
    d_owner(owner),
    d_area(0, 0, 0, 0),
    d_matrix(1.0f),
    d_matrixValid(false),
    d_viewDistance(0)
{
}

//----------------------------------------------------------------------------//
template <typename T>
OpenGLRenderTarget<T>::~OpenGLRenderTarget()
{
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::draw(const GeometryBuffer& buffer)
{
    buffer.draw();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::draw(const RenderQueue& queue)
{
    queue.draw();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::setArea(const Rectf& area)
{
    d_area = area;
    d_matrixValid = false;

    RenderTargetEventArgs args(this);
    T::fireEvent(RenderTarget::EventAreaChanged, args);
}

//----------------------------------------------------------------------------//
template <typename T>
const Rectf& OpenGLRenderTarget<T>::getArea() const
{
    return d_area;
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::activate()
{
    glViewport(static_cast<GLsizei>(d_area.left()),
               static_cast<GLsizei>(d_area.top()),
               static_cast<GLsizei>(d_area.getWidth()),
               static_cast<GLsizei>(d_area.getHeight()));

    if (!d_matrixValid)
        updateMatrix();

    d_owner.setViewProjectionMatrix(d_matrix);

    RenderTarget::activate();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::deactivate()
{
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::unprojectPoint(const GeometryBuffer& buff,
    const Vector2f& p_in, Vector2f& p_out) const
{
    if (!d_matrixValid)
        updateMatrix();

    const OpenGLGeometryBufferBase& gb =
        static_cast<const OpenGLGeometryBufferBase&>(buff);

    const GLint vp[4] = {
        static_cast<GLint>(d_area.left()),
        static_cast<GLint>(d_area.top()),
        static_cast<GLint>(d_area.getWidth()),
        static_cast<GLint>(d_area.getHeight())
    };

    GLdouble in_x, in_y, in_z;

    glm::ivec4 viewPort = glm::ivec4(vp[0], vp[1], vp[2], vp[3]);
    const glm::mat4& projMatrix = d_matrix;
    const glm::mat4& modelMatrix = gb.getModelMatrix();

    // unproject the ends of the ray
    glm::vec3 unprojected1;
    glm::vec3 unprojected2;
    in_x = vp[2] * 0.5;
    in_y = vp[3] * 0.5;
    in_z = -d_viewDistance;
    unprojected1 =  glm::unProject(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = p_in.d_x;
    in_y = vp[3] - p_in.d_y;
    in_z = 0.0;
    unprojected2 = glm::unProject(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);

    // project points to orientate them with GeometryBuffer plane
    glm::vec3 projected1;
    glm::vec3 projected2;
    glm::vec3 projected3;
    in_x = 0.0;
    in_y = 0.0;
    projected1 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = 1.0;
    in_y = 0.0;
    projected2 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = 0.0;
    in_y = 1.0;
    projected3 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);

    // calculate vectors for generating the plane
    const glm::vec3 pv1 = projected2 - projected1;
    const glm::vec3 pv2 = projected3 - projected1;
    // given the vectors, calculate the plane normal
    const glm::vec3 planeNormal = glm::cross(pv1, pv2);
    // calculate plane
    const glm::vec3 planeNormalNormalized = glm::normalize(planeNormal);
    const double pl_d = - glm::dot(projected1, planeNormalNormalized);
    // calculate vector of picking ray
    const glm::vec3 rv = unprojected1 - unprojected2;
    // calculate intersection of ray and plane
    const double pn_dot_r1 = glm::dot(unprojected1, planeNormal);
    const double pn_dot_rv = glm::dot(rv, planeNormal);
    const double tmp1 = pn_dot_rv != 0.0 ? (pn_dot_r1 + pl_d) / pn_dot_rv : 0.0;
    const double is_x = unprojected1.x - rv.x * tmp1;
    const double is_y = unprojected1.y - rv.y * tmp1;

    p_out.d_x = static_cast<float>(is_x);
    p_out.d_y = static_cast<float>(is_y);
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::updateMatrix() const
{
    const float w = d_area.getWidth();
    const float h = d_area.getHeight();

    // We need to check if width or height are zero and act accordingly to prevent running into issues
    // with divisions by zero which would lead to undefined values, as well as faulty clipping planes
    // This is mostly important for avoiding asserts
    const bool widthAndHeightNotZero = ( w != 0.0f ) && ( h != 0.0f);

    const float aspect = widthAndHeightNotZero ? w / h : 1.0f;
    const float midx = widthAndHeightNotZero ? w * 0.5f : 0.5f;
    const float midy = widthAndHeightNotZero ? h * 0.5f : 0.5f;
    d_viewDistance = midx / (aspect * d_yfov_tan);

    glm::vec3 eye = glm::vec3(midx, midy, float(-d_viewDistance));
    glm::vec3 center = glm::vec3(midx, midy, 1);
    glm::vec3 up = glm::vec3(0, -1, 0);

    glm::mat4 projectionMatrix = glm::perspective(30.f, aspect, float(d_viewDistance * 0.5), float(d_viewDistance * 2.0));
    // Projection matrix abuse!
    glm::mat4 viewMatrix = glm::lookAt(eye, center, up);

    d_matrix = projectionMatrix * viewMatrix;

    d_matrixValid = true;
    //! This triggers all GeometryBuffers to regenerate their matrices
    d_activationCounter = -1;
}

//----------------------------------------------------------------------------//
template <typename T>
Renderer& OpenGLRenderTarget<T>::getOwner()
{
    return d_owner;
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section
<commit_msg>MOD: Docu<commit_after>/***********************************************************************
    created:    Wed, 8th Feb 2012
    author:     Lukas E Meindl (based on code by Paul D Turner)
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2012 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUI/RendererModules/OpenGL/RenderTarget.h"
#include "CEGUI/RenderQueue.h"
#include "CEGUI/RendererModules/OpenGL/GeometryBufferBase.h"

#include <cmath>

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

// Start of CEGUI namespace section
namespace CEGUI
{
//----------------------------------------------------------------------------//
template <typename T>
const double OpenGLRenderTarget<T>::d_yfov_tan = 0.267949192431123;

//----------------------------------------------------------------------------//
template <typename T>
OpenGLRenderTarget<T>::OpenGLRenderTarget(OpenGLRendererBase& owner) :
    d_owner(owner),
    d_area(0, 0, 0, 0),
    d_matrix(1.0f),
    d_matrixValid(false),
    d_viewDistance(0)
{
}

//----------------------------------------------------------------------------//
template <typename T>
OpenGLRenderTarget<T>::~OpenGLRenderTarget()
{
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::draw(const GeometryBuffer& buffer)
{
    buffer.draw();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::draw(const RenderQueue& queue)
{
    queue.draw();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::setArea(const Rectf& area)
{
    d_area = area;
    d_matrixValid = false;

    RenderTargetEventArgs args(this);
    T::fireEvent(RenderTarget::EventAreaChanged, args);
}

//----------------------------------------------------------------------------//
template <typename T>
const Rectf& OpenGLRenderTarget<T>::getArea() const
{
    return d_area;
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::activate()
{
    glViewport(static_cast<GLsizei>(d_area.left()),
               static_cast<GLsizei>(d_area.top()),
               static_cast<GLsizei>(d_area.getWidth()),
               static_cast<GLsizei>(d_area.getHeight()));

    if (!d_matrixValid)
        updateMatrix();

    d_owner.setViewProjectionMatrix(d_matrix);

    RenderTarget::activate();
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::deactivate()
{
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::unprojectPoint(const GeometryBuffer& buff,
    const Vector2f& p_in, Vector2f& p_out) const
{
    if (!d_matrixValid)
        updateMatrix();

    const OpenGLGeometryBufferBase& gb =
        static_cast<const OpenGLGeometryBufferBase&>(buff);

    const GLint vp[4] = {
        static_cast<GLint>(d_area.left()),
        static_cast<GLint>(d_area.top()),
        static_cast<GLint>(d_area.getWidth()),
        static_cast<GLint>(d_area.getHeight())
    };

    GLdouble in_x, in_y, in_z;

    glm::ivec4 viewPort = glm::ivec4(vp[0], vp[1], vp[2], vp[3]);
    const glm::mat4& projMatrix = d_matrix;
    const glm::mat4& modelMatrix = gb.getModelMatrix();

    // unproject the ends of the ray
    glm::vec3 unprojected1;
    glm::vec3 unprojected2;
    in_x = vp[2] * 0.5;
    in_y = vp[3] * 0.5;
    in_z = -d_viewDistance;
    unprojected1 =  glm::unProject(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = p_in.d_x;
    in_y = vp[3] - p_in.d_y;
    in_z = 0.0;
    unprojected2 = glm::unProject(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);

    // project points to orientate them with GeometryBuffer plane
    glm::vec3 projected1;
    glm::vec3 projected2;
    glm::vec3 projected3;
    in_x = 0.0;
    in_y = 0.0;
    projected1 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = 1.0;
    in_y = 0.0;
    projected2 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);
    in_x = 0.0;
    in_y = 1.0;
    projected3 = glm::project(glm::vec3(in_x, in_y, in_z), modelMatrix, projMatrix, viewPort);

    // calculate vectors for generating the plane
    const glm::vec3 pv1 = projected2 - projected1;
    const glm::vec3 pv2 = projected3 - projected1;
    // given the vectors, calculate the plane normal
    const glm::vec3 planeNormal = glm::cross(pv1, pv2);
    // calculate plane
    const glm::vec3 planeNormalNormalized = glm::normalize(planeNormal);
    const double pl_d = - glm::dot(projected1, planeNormalNormalized);
    // calculate vector of picking ray
    const glm::vec3 rv = unprojected1 - unprojected2;
    // calculate intersection of ray and plane
    const double pn_dot_r1 = glm::dot(unprojected1, planeNormal);
    const double pn_dot_rv = glm::dot(rv, planeNormal);
    const double tmp1 = pn_dot_rv != 0.0 ? (pn_dot_r1 + pl_d) / pn_dot_rv : 0.0;
    const double is_x = unprojected1.x - rv.x * tmp1;
    const double is_y = unprojected1.y - rv.y * tmp1;

    p_out.d_x = static_cast<float>(is_x);
    p_out.d_y = static_cast<float>(is_y);
}

//----------------------------------------------------------------------------//
template <typename T>
void OpenGLRenderTarget<T>::updateMatrix() const
{
    const float w = d_area.getWidth();
    const float h = d_area.getHeight();

    // We need to check if width or height are zero and act accordingly to prevent running into issues
    // with divisions by zero which would lead to undefined values, as well as faulty clipping planes
    // This is mostly important for avoiding asserts
    const bool widthAndHeightNotZero = ( w != 0.0f ) && ( h != 0.0f);

    const float aspect = widthAndHeightNotZero ? w / h : 1.0f;
    const float midx = widthAndHeightNotZero ? w * 0.5f : 0.5f;
    const float midy = widthAndHeightNotZero ? h * 0.5f : 0.5f;
    d_viewDistance = midx / (aspect * d_yfov_tan);

    glm::vec3 eye = glm::vec3(midx, midy, float(-d_viewDistance));
    glm::vec3 center = glm::vec3(midx, midy, 1);
    glm::vec3 up = glm::vec3(0, -1, 0);

    glm::mat4 projectionMatrix = glm::perspective(30.f, aspect, float(d_viewDistance * 0.5), float(d_viewDistance * 2.0));
    // Projection matrix abuse!
    glm::mat4 viewMatrix = glm::lookAt(eye, center, up);

    d_matrix = projectionMatrix * viewMatrix;

    d_matrixValid = true;
    //! This will trigger the RenderTarget to notify all of its GeometryBuffers to regenerate their matrices
    d_activationCounter = -1;
}

//----------------------------------------------------------------------------//
template <typename T>
Renderer& OpenGLRenderTarget<T>::getOwner()
{
    return d_owner;
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>/** @file

  Class to execute one (or more) remap plugin(s).

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include "RemapPlugins.h"

ClassAllocator<RemapPlugins> pluginAllocator("RemapPluginsAlloc");

TSRemapStatus
RemapPlugins::run_plugin(remap_plugin_info* plugin)
{
  TSRemapStatus plugin_retcode;
  TSRemapRequestInfo rri;
  url_mapping *map = _s->url_map.getMapping();
  URL *map_from = &(map->fromURL);
  URL *map_to = _s->url_map.getToURL();

  // This is the equivalent of TSHttpTxnClientReqGet(), which every remap plugin would
  // have to call.
  rri.requestBufp = reinterpret_cast<TSMBuffer>(_request_header);
  rri.requestHdrp = reinterpret_cast<TSMLoc>(_request_header->m_http);

  // Read-only URL's (TSMLoc's to the SDK)
  rri.mapFromUrl = reinterpret_cast<TSMLoc>(map_from->m_url_impl);
  rri.mapToUrl = reinterpret_cast<TSMLoc>(map_to->m_url_impl);
  rri.requestUrl = reinterpret_cast<TSMLoc>(_request_url->m_url_impl);

  rri.redirect = 0;

  // These are made to reflect the "defaults" that will be used in
  // the case where the plugins don't modify them. It's semi-weird
  // that the "from" and "to" URLs changes when chaining happens, but
  // it is necessary to get predictable behavior.
#if 0
  if (_cur == 0) {
    rri.remap_from_host = map_from->host_get(&rri.remap_from_host_size);
    rri.remap_from_port = map_from->port_get();
    rri.remap_from_path = map_from->path_get(&rri.remap_from_path_size);
    rri.from_scheme = map_from->scheme_get(&rri.from_scheme_len);
  } else {
    rri.remap_from_host = _request_url->host_get(&rri.remap_from_host_size);
    rri.remap_from_port = _request_url->port_get();
    rri.remap_from_path = _request_url->path_get(&rri.remap_from_path_size);
    rri.from_scheme = _request_url->scheme_get(&rri.from_scheme_len);
  }
#endif

  void* ih = map->get_instance(_cur);

  // Prepare State for the future
  if (_s && _cur == 0) {
    _s->fp_tsremap_os_response = plugin->fp_tsremap_os_response;
    _s->remap_plugin_instance = ih;
  }

  plugin_retcode = plugin->fp_tsremap_do_remap(ih, _s ? reinterpret_cast<TSHttpTxn>(_s->state_machine) : NULL, &rri);
  // TODO: Deal with negative return codes here
  if (plugin_retcode < 0)
    plugin_retcode = TSREMAP_NO_REMAP;

  // First step after plugin remap must be "redirect url" check
  if ((TSREMAP_DID_REMAP == plugin_retcode || TSREMAP_DID_REMAP_STOP == plugin_retcode) && rri.redirect)
    _s->remap_redirect = _request_url->string_get(NULL);

  return plugin_retcode;
}

/**
  This is the equivalent of the old DoRemap().

  @return 1 when you are done doing crap (otherwise, you get re-called
    with scheudle_imm and i hope you have something more to do), else
    0 if you have something more do do (this isnt strict and we check
    there actually *is* something to do).

*/
int
RemapPlugins::run_single_remap()
{
  // I should patent this
  Debug("url_rewrite", "Running single remap rule for the %d%s time", _cur, _cur == 1 ? "st" : _cur == 2 ? "nd" : _cur == 3 ? "rd" : "th");

  remap_plugin_info *plugin = NULL;
  TSRemapStatus plugin_retcode = TSREMAP_NO_REMAP;

  const char *requestPath;
  int requestPathLen;
  url_mapping *map = _s->url_map.getMapping();
  URL *map_from = &(map->fromURL);
  URL *map_to = _s->url_map.getToURL();

  int redirect_host_len;

  // Debugging vars
  bool debug_on = false;
  int retcode = 0;              // 0 - no redirect, !=0 - redirected

  requestPath = _request_url->path_get(&requestPathLen);
  debug_on = is_debug_tag_set("url_rewrite");

  if (_request_header)
    plugin = map->get_plugin(_cur);    //get the nth plugin in our list of plugins

  if (plugin) {
    Debug("url_rewrite", "Remapping rule id: %d matched; running it now", map->map_id);
    plugin_retcode = run_plugin(plugin);
  } else if (_cur > 0) {
    _cur++;
    Debug("url_rewrite", "There wasn't a plugin available for us to run. Completing all remap processing immediately");
    return 1;
  }

  if (_s->remap_redirect)     //if redirect was set, we need to use that.
    return 1;

  // skip the !plugin_modified_* stuff if we are on our 2nd plugin (or greater) and there's no more plugins
  if (_cur > 0 && (_cur + 1) >= map->_plugin_count)
    goto done;

  if (TSREMAP_NO_REMAP == plugin_retcode || TSREMAP_NO_REMAP_STOP == plugin_retcode) {
    if (_cur > 0 ) {
      //plugin didn't do anything for us, but maybe another will down the chain so lets assume there is something more for us to process
      ++_cur;
      Debug("url_rewrite", "Plugin didn't change anything, but we'll try the next one right now");
      return 0;
    }

    Debug("url_rewrite", "plugin did not change host, port or path, copying from mapping rule");

    int fromPathLen;
    const char *toHost;
    const char *toPath;
    int toPathLen;
    int toHostLen;

    map_from->path_get(&fromPathLen);
    toHost = map_to->host_get(&toHostLen);
    toPath = map_to->path_get(&toPathLen);

    _request_url->host_set(toHost, toHostLen);

    int to_port = map_to->port_get_raw();

    if (to_port != _request_url->port_get_raw())
      _request_url->port_set(to_port);

    int to_scheme_len, from_scheme_len;
    const char *to_scheme = map_to->scheme_get(&to_scheme_len);

    if (to_scheme != map_from->scheme_get(&from_scheme_len))
      _request_url->scheme_set(to_scheme, to_scheme_len);

    // Extra byte is potentially needed for prefix path '/'.
    // Added an extra 3 so that TS wouldn't crash in the field.
    // Allocate a large buffer to avoid problems.
    char newPathTmp[2048];
    char *newPath;
    char *newPathAlloc = NULL;
    unsigned int newPathLen = 0;
    unsigned int newPathLenNeed = (requestPathLen - fromPathLen) + toPathLen + 8; // 3 + some padding

    if (newPathLenNeed > sizeof(newPathTmp)) {
      newPath = (newPathAlloc = (char *)ats_malloc(newPathLenNeed));
      if (debug_on) {
        memset(newPath, 0, newPathLenNeed);
      }
    } else {
      newPath = &newPathTmp[0];
      if (debug_on) {
        memset(newPath, 0, sizeof(newPathTmp));
      }
    }

    *newPath = 0;

    // Purify load run with QT in a reverse proxy indicated
    // a UMR/ABR/MSE in the line where we do a *newPath == '/' and the ink_strlcpy
    // that follows it.  The problem occurs if
    // requestPathLen,fromPathLen,toPathLen are all 0; in this case, we never
    // initialize newPath, but still de-ref it in *newPath == '/' comparison.
    // The memset fixes that problem.
    if (toPath) {
      memcpy(newPath, toPath, toPathLen);
      newPathLen += toPathLen;
    }
    // We might need to insert a trailing slash in the new portion of the path
    // if more will be added and none is present and one will be needed.
    if (!fromPathLen && requestPathLen && toPathLen && *(newPath + newPathLen - 1) != '/') {
      *(newPath + newPathLen) = '/';
      newPathLen++;
    }

    if (requestPath) {
      //avoid adding another trailing slash if the requestPath already had one and so does the toPath
      if (requestPathLen < fromPathLen) {
        if (toPathLen && requestPath[requestPathLen - 1] == '/' && toPath[toPathLen - 1] == '/') {
          fromPathLen++;
        }
      } else {
        if (toPathLen && requestPath[fromPathLen] == '/' && toPath[toPathLen - 1] == '/') {
          fromPathLen++;
        }
      }
      // copy the end of the path past what has been mapped
      if ((requestPathLen - fromPathLen) > 0) {
        memcpy(newPath + newPathLen, requestPath + fromPathLen, requestPathLen - fromPathLen);
        newPathLen += (requestPathLen - fromPathLen);
      }
    }
    // We need to remove the leading slash in newPath if one is
    // present.
    if (*newPath == '/') {
      memmove(newPath, newPath + 1, --newPathLen);
    }

    _request_url->path_set(newPath, newPathLen);

    // TODO: This is horribly wrong and broken, when can this trigger??? Check
    // above, we already return on _s->remap_redirect ...
    if (map->homePageRedirect && fromPathLen == requestPathLen && _s->remap_redirect) {
      URL redirect_url;

      redirect_url.create(NULL);
      redirect_url.copy(_request_url);

      ink_assert(fromPathLen > 0);

      // Extra byte for trailing '/' in redirect
      if (newPathLen > 0 && newPath[newPathLen - 1] != '/') {
        newPath[newPathLen] = '/';
        newPath[++newPathLen] = '\0';
        redirect_url.path_set(newPath, newPathLen);
      }
      // If we have host header information,
      //   put it back into redirect URL
      //
      if (_hh_ptr != NULL) {
        redirect_url.host_set(_hh_ptr->request_host, _hh_ptr->host_len);
        if (redirect_url.port_get() != _hh_ptr->request_port) {
          redirect_url.port_set(_hh_ptr->request_port);
        }
      }
      // If request came in without a host, send back
      //  the redirect with the name the proxy is known by
      if (redirect_url.host_get(&redirect_host_len) == NULL)
        redirect_url.host_set(rewrite_table->ts_name, strlen(rewrite_table->ts_name));

      if ((_s->remap_redirect = redirect_url.string_get(NULL)) != NULL)
        retcode = strlen(_s->remap_redirect);
      Debug("url_rewrite", "Redirected %.*s to %.*s", requestPathLen, requestPath, retcode, _s->remap_redirect);
      redirect_url.destroy();
    }

    ats_free(newPathAlloc);
  }

done:
  if (_cur > MAX_REMAP_PLUGIN_CHAIN) {
    Error("Called run_single_remap more than 10 times. Stopping this remapping insanity now");
    Debug("url_rewrite", "Called run_single_remap more than 10 times. Stopping this remapping insanity now");
    return 1;
  }

  if (++_cur >= map->_plugin_count) {
    //normally, we would callback into this function but we dont have anything more to do!
    Debug("url_rewrite", "We completed all remap plugins for this rule");
    return 1;
  } else {
    Debug("url_rewrite", "Completed single remap. Attempting another via immediate callback");
    return 0;
  }

  return 1;
  ink_debug_assert(!"not reached");
}

int
RemapPlugins::run_remap(int event, Event* e)
{
  Debug("url_rewrite", "Inside RemapPlugins::run_remap with cur = %d", _cur);

  ink_debug_assert(action.continuation);
  ink_assert(action.continuation);

  int ret = 0;

  /* make sure we weren't cancelled */
  if (action.cancelled) {
    mutex.clear();
    pluginAllocator.free(this); //ugly
    return EVENT_DONE;
  }

  switch (event) {
  case EVENT_IMMEDIATE:
    Debug("url_rewrite", "handling immediate event inside RemapPlugins::run_remap");
    ret = run_single_remap();
    /**
     * If ret !=0 then we are done with this processor and we call back into the SM;
     * otherwise, we call this function again immediately (which really isn't immediate)
     * thru the eventProcessor, thus forcing another run of run_single_remap() which will
     * then operate on _request_url, etc performing additional remaps (mainly another plugin run)
     **/
    if (ret) {
      action.continuation->handleEvent(EVENT_REMAP_COMPLETE, NULL);
      mutex.clear();
      action.mutex.clear();
      mutex = NULL;
      action.mutex = NULL;
      //THREAD_FREE(this, pluginAllocator, t);
      pluginAllocator.free(this);       //ugly
      return EVENT_DONE;
    } else {
      e->schedule_imm(event);
      return EVENT_CONT;
    }

    break;
  default:
    ink_assert(!"unknown event type");
    break;
  };
  return EVENT_DONE;
}
<commit_msg>requestPath needs to be set after modifying the _request_url or it maybe invalid.  Moved setting of this variable<commit_after>/** @file

  Class to execute one (or more) remap plugin(s).

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include "RemapPlugins.h"

ClassAllocator<RemapPlugins> pluginAllocator("RemapPluginsAlloc");

TSRemapStatus
RemapPlugins::run_plugin(remap_plugin_info* plugin)
{
  TSRemapStatus plugin_retcode;
  TSRemapRequestInfo rri;
  url_mapping *map = _s->url_map.getMapping();
  URL *map_from = &(map->fromURL);
  URL *map_to = _s->url_map.getToURL();

  // This is the equivalent of TSHttpTxnClientReqGet(), which every remap plugin would
  // have to call.
  rri.requestBufp = reinterpret_cast<TSMBuffer>(_request_header);
  rri.requestHdrp = reinterpret_cast<TSMLoc>(_request_header->m_http);

  // Read-only URL's (TSMLoc's to the SDK)
  rri.mapFromUrl = reinterpret_cast<TSMLoc>(map_from->m_url_impl);
  rri.mapToUrl = reinterpret_cast<TSMLoc>(map_to->m_url_impl);
  rri.requestUrl = reinterpret_cast<TSMLoc>(_request_url->m_url_impl);

  rri.redirect = 0;

  // These are made to reflect the "defaults" that will be used in
  // the case where the plugins don't modify them. It's semi-weird
  // that the "from" and "to" URLs changes when chaining happens, but
  // it is necessary to get predictable behavior.
#if 0
  if (_cur == 0) {
    rri.remap_from_host = map_from->host_get(&rri.remap_from_host_size);
    rri.remap_from_port = map_from->port_get();
    rri.remap_from_path = map_from->path_get(&rri.remap_from_path_size);
    rri.from_scheme = map_from->scheme_get(&rri.from_scheme_len);
  } else {
    rri.remap_from_host = _request_url->host_get(&rri.remap_from_host_size);
    rri.remap_from_port = _request_url->port_get();
    rri.remap_from_path = _request_url->path_get(&rri.remap_from_path_size);
    rri.from_scheme = _request_url->scheme_get(&rri.from_scheme_len);
  }
#endif

  void* ih = map->get_instance(_cur);

  // Prepare State for the future
  if (_s && _cur == 0) {
    _s->fp_tsremap_os_response = plugin->fp_tsremap_os_response;
    _s->remap_plugin_instance = ih;
  }

  plugin_retcode = plugin->fp_tsremap_do_remap(ih, _s ? reinterpret_cast<TSHttpTxn>(_s->state_machine) : NULL, &rri);
  // TODO: Deal with negative return codes here
  if (plugin_retcode < 0)
    plugin_retcode = TSREMAP_NO_REMAP;

  // First step after plugin remap must be "redirect url" check
  if ((TSREMAP_DID_REMAP == plugin_retcode || TSREMAP_DID_REMAP_STOP == plugin_retcode) && rri.redirect)
    _s->remap_redirect = _request_url->string_get(NULL);

  return plugin_retcode;
}

/**
  This is the equivalent of the old DoRemap().

  @return 1 when you are done doing crap (otherwise, you get re-called
    with scheudle_imm and i hope you have something more to do), else
    0 if you have something more do do (this isnt strict and we check
    there actually *is* something to do).

*/
int
RemapPlugins::run_single_remap()
{
  // I should patent this
  Debug("url_rewrite", "Running single remap rule for the %d%s time", _cur, _cur == 1 ? "st" : _cur == 2 ? "nd" : _cur == 3 ? "rd" : "th");

  remap_plugin_info *plugin = NULL;
  TSRemapStatus plugin_retcode = TSREMAP_NO_REMAP;

  const char *requestPath;
  int requestPathLen;
  url_mapping *map = _s->url_map.getMapping();
  URL *map_from = &(map->fromURL);
  URL *map_to = _s->url_map.getToURL();

  int redirect_host_len;

  // Debugging vars
  bool debug_on = false;
  int retcode = 0;              // 0 - no redirect, !=0 - redirected

  debug_on = is_debug_tag_set("url_rewrite");

  if (_request_header)
    plugin = map->get_plugin(_cur);    //get the nth plugin in our list of plugins

  if (plugin) {
    Debug("url_rewrite", "Remapping rule id: %d matched; running it now", map->map_id);
    plugin_retcode = run_plugin(plugin);
  } else if (_cur > 0) {
    _cur++;
    Debug("url_rewrite", "There wasn't a plugin available for us to run. Completing all remap processing immediately");
    return 1;
  }

  if (_s->remap_redirect)     //if redirect was set, we need to use that.
    return 1;

  // skip the !plugin_modified_* stuff if we are on our 2nd plugin (or greater) and there's no more plugins
  if (_cur > 0 && (_cur + 1) >= map->_plugin_count)
    goto done;

  if (TSREMAP_NO_REMAP == plugin_retcode || TSREMAP_NO_REMAP_STOP == plugin_retcode) {
    if (_cur > 0 ) {
      //plugin didn't do anything for us, but maybe another will down the chain so lets assume there is something more for us to process
      ++_cur;
      Debug("url_rewrite", "Plugin didn't change anything, but we'll try the next one right now");
      return 0;
    }

    Debug("url_rewrite", "plugin did not change host, port or path, copying from mapping rule");

    int fromPathLen;
    const char *toHost;
    const char *toPath;
    int toPathLen;
    int toHostLen;

    map_from->path_get(&fromPathLen);
    toHost = map_to->host_get(&toHostLen);
    toPath = map_to->path_get(&toPathLen);

    _request_url->host_set(toHost, toHostLen);

    int to_port = map_to->port_get_raw();

    if (to_port != _request_url->port_get_raw())
      _request_url->port_set(to_port);

    int to_scheme_len, from_scheme_len;
    const char *to_scheme = map_to->scheme_get(&to_scheme_len);

    if (to_scheme != map_from->scheme_get(&from_scheme_len))
      _request_url->scheme_set(to_scheme, to_scheme_len);

    requestPath = _request_url->path_get(&requestPathLen);
    // Extra byte is potentially needed for prefix path '/'.
    // Added an extra 3 so that TS wouldn't crash in the field.
    // Allocate a large buffer to avoid problems.
    char newPathTmp[2048];
    char *newPath;
    char *newPathAlloc = NULL;
    unsigned int newPathLen = 0;
    unsigned int newPathLenNeed = (requestPathLen - fromPathLen) + toPathLen + 8; // 3 + some padding

    if (newPathLenNeed > sizeof(newPathTmp)) {
      newPath = (newPathAlloc = (char *)ats_malloc(newPathLenNeed));
      if (debug_on) {
        memset(newPath, 0, newPathLenNeed);
      }
    } else {
      newPath = &newPathTmp[0];
      if (debug_on) {
        memset(newPath, 0, sizeof(newPathTmp));
      }
    }

    *newPath = 0;

    // Purify load run with QT in a reverse proxy indicated
    // a UMR/ABR/MSE in the line where we do a *newPath == '/' and the ink_strlcpy
    // that follows it.  The problem occurs if
    // requestPathLen,fromPathLen,toPathLen are all 0; in this case, we never
    // initialize newPath, but still de-ref it in *newPath == '/' comparison.
    // The memset fixes that problem.
    if (toPath) {
      memcpy(newPath, toPath, toPathLen);
      newPathLen += toPathLen;
    }
    // We might need to insert a trailing slash in the new portion of the path
    // if more will be added and none is present and one will be needed.
    if (!fromPathLen && requestPathLen && toPathLen && *(newPath + newPathLen - 1) != '/') {
      *(newPath + newPathLen) = '/';
      newPathLen++;
    }

    if (requestPath) {
      //avoid adding another trailing slash if the requestPath already had one and so does the toPath
      if (requestPathLen < fromPathLen) {
        if (toPathLen && requestPath[requestPathLen - 1] == '/' && toPath[toPathLen - 1] == '/') {
          fromPathLen++;
        }
      } else {
        if (toPathLen && requestPath[fromPathLen] == '/' && toPath[toPathLen - 1] == '/') {
          fromPathLen++;
        }
      }
      // copy the end of the path past what has been mapped
      if ((requestPathLen - fromPathLen) > 0) {
        memcpy(newPath + newPathLen, requestPath + fromPathLen, requestPathLen - fromPathLen);
        newPathLen += (requestPathLen - fromPathLen);
      }
    }
    // We need to remove the leading slash in newPath if one is
    // present.
    if (*newPath == '/') {
      memmove(newPath, newPath + 1, --newPathLen);
    }

    _request_url->path_set(newPath, newPathLen);

    // TODO: This is horribly wrong and broken, when can this trigger??? Check
    // above, we already return on _s->remap_redirect ...
    if (map->homePageRedirect && fromPathLen == requestPathLen && _s->remap_redirect) {
      URL redirect_url;

      redirect_url.create(NULL);
      redirect_url.copy(_request_url);

      ink_assert(fromPathLen > 0);

      // Extra byte for trailing '/' in redirect
      if (newPathLen > 0 && newPath[newPathLen - 1] != '/') {
        newPath[newPathLen] = '/';
        newPath[++newPathLen] = '\0';
        redirect_url.path_set(newPath, newPathLen);
      }
      // If we have host header information,
      //   put it back into redirect URL
      //
      if (_hh_ptr != NULL) {
        redirect_url.host_set(_hh_ptr->request_host, _hh_ptr->host_len);
        if (redirect_url.port_get() != _hh_ptr->request_port) {
          redirect_url.port_set(_hh_ptr->request_port);
        }
      }
      // If request came in without a host, send back
      //  the redirect with the name the proxy is known by
      if (redirect_url.host_get(&redirect_host_len) == NULL)
        redirect_url.host_set(rewrite_table->ts_name, strlen(rewrite_table->ts_name));

      if ((_s->remap_redirect = redirect_url.string_get(NULL)) != NULL)
        retcode = strlen(_s->remap_redirect);
      Debug("url_rewrite", "Redirected %.*s to %.*s", requestPathLen, requestPath, retcode, _s->remap_redirect);
      redirect_url.destroy();
    }

    ats_free(newPathAlloc);
  }

done:
  if (_cur > MAX_REMAP_PLUGIN_CHAIN) {
    Error("Called run_single_remap more than 10 times. Stopping this remapping insanity now");
    Debug("url_rewrite", "Called run_single_remap more than 10 times. Stopping this remapping insanity now");
    return 1;
  }

  if (++_cur >= map->_plugin_count) {
    //normally, we would callback into this function but we dont have anything more to do!
    Debug("url_rewrite", "We completed all remap plugins for this rule");
    return 1;
  } else {
    Debug("url_rewrite", "Completed single remap. Attempting another via immediate callback");
    return 0;
  }

  return 1;
  ink_debug_assert(!"not reached");
}

int
RemapPlugins::run_remap(int event, Event* e)
{
  Debug("url_rewrite", "Inside RemapPlugins::run_remap with cur = %d", _cur);

  ink_debug_assert(action.continuation);
  ink_assert(action.continuation);

  int ret = 0;

  /* make sure we weren't cancelled */
  if (action.cancelled) {
    mutex.clear();
    pluginAllocator.free(this); //ugly
    return EVENT_DONE;
  }

  switch (event) {
  case EVENT_IMMEDIATE:
    Debug("url_rewrite", "handling immediate event inside RemapPlugins::run_remap");
    ret = run_single_remap();
    /**
     * If ret !=0 then we are done with this processor and we call back into the SM;
     * otherwise, we call this function again immediately (which really isn't immediate)
     * thru the eventProcessor, thus forcing another run of run_single_remap() which will
     * then operate on _request_url, etc performing additional remaps (mainly another plugin run)
     **/
    if (ret) {
      action.continuation->handleEvent(EVENT_REMAP_COMPLETE, NULL);
      mutex.clear();
      action.mutex.clear();
      mutex = NULL;
      action.mutex = NULL;
      //THREAD_FREE(this, pluginAllocator, t);
      pluginAllocator.free(this);       //ugly
      return EVENT_DONE;
    } else {
      e->schedule_imm(event);
      return EVENT_CONT;
    }

    break;
  default:
    ink_assert(!"unknown event type");
    break;
  };
  return EVENT_DONE;
}
<|endoftext|>


<commit_before>#include <QMessageBox>
#include <QFontDatabase>
#include <QFile>
#include <QSize>
#include <QApplication>

#ifdef Q_OS_WIN
#include "BorderlessWindow.h"
#else
#include "UnixWindow.h"
#endif

void g_loadFonts(QApplication* application)
{
    // Font
    QFont mainFont = application->font();
    mainFont.setStyleStrategy(QFont::PreferAntialias);
    application->setFont(mainFont);

    // Dynamically load fonts
    QStringList list;
    list << "Montserrat-Black.ttf" <<
        "Montserrat-Bold.ttf" <<
        "Montserrat-Light.ttf" <<
        "Montserrat-Regular.ttf" <<
        "Montserrat-Thin.ttf" <<
        "Roboto-BlackItalic.ttf" <<
        "Roboto-Black.ttf" <<
        "Roboto-BoldItalic.ttf" <<
        "Roboto-Bold.ttf" <<
        "Roboto-Italic.ttf" <<
        "Roboto-LightItalic.ttf" <<
        "Roboto-Light.ttf" <<
        "Roboto-MediumItalic.ttf" <<
        "Roboto-Medium.ttf" <<
        "Roboto-Regular.ttf" <<
        "Roboto-ThinItalic.ttf" <<
        "Roboto-Thin.ttf" <<
        "SourceCodePro-Black.ttf" <<
        "SourceCodePro-Bold.ttf" <<
        "SourceCodePro-ExtraLight.ttf" <<
        "SourceCodePro-Light.ttf" <<
        "SourceCodePro-Medium.ttf" <<
        "SourceCodePro-Regular.ttf" <<
        "SourceCodePro-Semibold.ttf" <<
        "SourceSansPro-BlackItalic.ttf" <<
        "SourceSansPro-Black.ttf" <<
        "SourceSansPro-BoldItalic.ttf" <<
        "SourceSansPro-Bold.ttf" <<
        "SourceSansPro-ExtraLightItalic.ttf" <<
        "SourceSansPro-ExtraLight.ttf" <<
        "SourceSansPro-Italic.ttf" <<
        "SourceSansPro-LightItalic.ttf" <<
        "SourceSansPro-Light.ttf" <<
        "SourceSansPro-Regular.ttf" <<
        "SourceSansPro-SemiboldItalic.ttf" <<
        "SourceSansPro-Semibold.ttf";

    int fontID(-1);
    bool fontWarningShown(false);
    for (auto font : list)
    {
        QFile res(":/Typeface/" + font);
        if (!res.open(QIODevice::ReadOnly))
        {
            if (!fontWarningShown)
            {
                QMessageBox::warning(0, "Application", (QString) "Warning: Unable to load font " + QChar(0x00AB) + font + QChar(0x00BB) + ".");
                fontWarningShown = true;
            }
        }
        else
        {
            fontID = QFontDatabase::addApplicationFontFromData(res.readAll());
            if (fontID == -1 && !fontWarningShown)
            {
                QMessageBox::warning(0, "Application", (QString) "Warning: Unable to load font " + QChar(0x00AB) + font + QChar(0x00BB) + ".");
                fontWarningShown = true;
            }
        }
    }

}

int main(int argc, char* argv[])
{
    QApplication::setStyle("fusion");
    QApplication* application = new QApplication(argc, argv);

    // Stylesheet
    QFile stylesheet(":/Styles/PAClient.css");
    if (stylesheet.open(QFile::ReadOnly))
    {
        QString styleSheet = stylesheet.readAll();
        application->setStyleSheet(styleSheet);
    }

    g_loadFonts(application);

    #ifdef Q_OS_WIN
        // Background color
        // This is only for WinApi window, Qt widgets use BorderlessWindow.css stylesheet
        HBRUSH windowBackground = CreateSolidBrush(RGB(34, 38, 47));

        // Create a Win window
        BorderlessWindow window(application, windowBackground, 1152, 648);
        window.setMinimumSize(830, 550);
    #else
        // Create a Unix window
        UnixWindow window;
        QSize* size = new QSize(1152, 648);
        window.resize(*size);
        window.setMinimumSize(830, 550);
    #endif

    // Launch
    application->exec();

    return 0;
}
<commit_msg>Add icon to apps under unix/linux<commit_after>#include <QMessageBox>
#include <QFontDatabase>
#include <QFile>
#include <QSize>
#include <QApplication>

#ifdef Q_OS_WIN
#include "BorderlessWindow.h"
#else
#include "UnixWindow.h"
#endif

void g_loadFonts(QApplication* application)
{
    // Font
    QFont mainFont = application->font();
    mainFont.setStyleStrategy(QFont::PreferAntialias);
    application->setFont(mainFont);

    // Dynamically load fonts
    QStringList list;
    list << "Montserrat-Black.ttf" <<
        "Montserrat-Bold.ttf" <<
        "Montserrat-Light.ttf" <<
        "Montserrat-Regular.ttf" <<
        "Montserrat-Thin.ttf" <<
        "Roboto-BlackItalic.ttf" <<
        "Roboto-Black.ttf" <<
        "Roboto-BoldItalic.ttf" <<
        "Roboto-Bold.ttf" <<
        "Roboto-Italic.ttf" <<
        "Roboto-LightItalic.ttf" <<
        "Roboto-Light.ttf" <<
        "Roboto-MediumItalic.ttf" <<
        "Roboto-Medium.ttf" <<
        "Roboto-Regular.ttf" <<
        "Roboto-ThinItalic.ttf" <<
        "Roboto-Thin.ttf" <<
        "SourceCodePro-Black.ttf" <<
        "SourceCodePro-Bold.ttf" <<
        "SourceCodePro-ExtraLight.ttf" <<
        "SourceCodePro-Light.ttf" <<
        "SourceCodePro-Medium.ttf" <<
        "SourceCodePro-Regular.ttf" <<
        "SourceCodePro-Semibold.ttf" <<
        "SourceSansPro-BlackItalic.ttf" <<
        "SourceSansPro-Black.ttf" <<
        "SourceSansPro-BoldItalic.ttf" <<
        "SourceSansPro-Bold.ttf" <<
        "SourceSansPro-ExtraLightItalic.ttf" <<
        "SourceSansPro-ExtraLight.ttf" <<
        "SourceSansPro-Italic.ttf" <<
        "SourceSansPro-LightItalic.ttf" <<
        "SourceSansPro-Light.ttf" <<
        "SourceSansPro-Regular.ttf" <<
        "SourceSansPro-SemiboldItalic.ttf" <<
        "SourceSansPro-Semibold.ttf";

    int fontID(-1);
    bool fontWarningShown(false);
    for (auto font : list)
    {
        QFile res(":/Typeface/" + font);
        if (!res.open(QIODevice::ReadOnly))
        {
            if (!fontWarningShown)
            {
                QMessageBox::warning(0, "Application", (QString) "Warning: Unable to load font " + QChar(0x00AB) + font + QChar(0x00BB) + ".");
                fontWarningShown = true;
            }
        }
        else
        {
            fontID = QFontDatabase::addApplicationFontFromData(res.readAll());
            if (fontID == -1 && !fontWarningShown)
            {
                QMessageBox::warning(0, "Application", (QString) "Warning: Unable to load font " + QChar(0x00AB) + font + QChar(0x00BB) + ".");
                fontWarningShown = true;
            }
        }
    }

}

int main(int argc, char* argv[])
{
    QApplication::setStyle("fusion");
    QApplication* application = new QApplication(argc, argv);

    #ifndef Q_OS_WIN
        // dynamic loading of the icon under Linux/UNIX
        application->setWindowIcon(QIcon(":/SystemMenu/Icons/Ascension_Icon.ico"));
    #endif

    // Stylesheet
    QFile stylesheet(":/Styles/PAClient.css");
    if (stylesheet.open(QFile::ReadOnly))
    {
        QString styleSheet = stylesheet.readAll();
        application->setStyleSheet(styleSheet);
    }

    g_loadFonts(application);

    #ifdef Q_OS_WIN
        // Background color
        // This is only for WinApi window, Qt widgets use BorderlessWindow.css stylesheet
        HBRUSH windowBackground = CreateSolidBrush(RGB(34, 38, 47));

        // Create a Win window
        BorderlessWindow window(application, windowBackground, 1152, 648);
        window.setMinimumSize(830, 550);
    #else
        // Create a Unix window
        UnixWindow window;
        QSize* size = new QSize(1152, 648);
        window.resize(*size);
        window.setMinimumSize(830, 550);
    #endif

    // Launch
    application->exec();

    return 0;
}
<|endoftext|>