<commit_before>#include "xchainer/routines/indexing.h"

#include <cstdint>
#include <string>
#include <vector>

#include <gtest/gtest.h>
#include <nonstd/optional.hpp>

#include "xchainer/array.h"
#include "xchainer/array_index.h"
#include "xchainer/check_backward.h"
#include "xchainer/error.h"
#include "xchainer/shape.h"
#include "xchainer/strides.h"
#include "xchainer/testing/array.h"
#include "xchainer/testing/array_check.h"
#include "xchainer/testing/device_session.h"

namespace xchainer {
namespace {

class IndexingTest : public ::testing::TestWithParam<std::string> {
protected:
    void SetUp() override {
        const std::string& backend_name = GetParam();
        device_session_.emplace(DeviceId{backend_name, 0});
    }

    void TearDown() override { device_session_.reset(); }

private:
    nonstd::optional<testing::DeviceSession> device_session_;
};

TEST_P(IndexingTest, At) {
    using T = int32_t;
    Shape input_shape{2, 3, 1};
    Shape output_shape{1, 2, 1};
    std::vector<ArrayIndex> indices{-1, NewAxis{}, Slice{1, 3}};
    Array a = testing::BuildArray(input_shape).WithLinearData<T>();
    Array b = internal::At(a, indices);

    EXPECT_EQ(output_shape, b.shape());
    Array e = testing::BuildArray(output_shape).WithData<T>({4, 5});
    EXPECT_ARRAY_EQ(e, b);

    // Check if strides are 0 for newaxis.
    EXPECT_EQ(0, b.strides()[0]);
    EXPECT_NE(0, b.strides()[1]);
    EXPECT_NE(0, b.strides()[2]);
}

// Index out of bounds
TEST_P(IndexingTest, InvalidAt1) {
    using T = int32_t;
    Shape input_shape{2, 3};
    std::vector<ArrayIndex> indices{0, 0, 0};
    Array a = testing::BuildArray(input_shape).WithLinearData<T>();
    EXPECT_THROW(internal::At(a, indices), DimensionError);
}

// Too large dimension
TEST_P(IndexingTest, InvalidAt2) {
    using T = int32_t;
    Shape input_shape{2, 3};
    std::vector<ArrayIndex> indices{2};
    Array a = testing::BuildArray(input_shape).WithLinearData<T>();
    EXPECT_THROW(internal::At(a, indices), DimensionError);
}

TEST_P(IndexingTest, AtBackward) {
    CheckBackward(
            [](const std::vector<Array>& xs) -> std::vector<Array> {
                std::vector<ArrayIndex> indices{1, NewAxis{}, Slice{1, 3}};
                return {internal::At(xs[0], indices)};
            },
            {(*testing::BuildArray({2, 3}).WithData<float>({1.f, -1.f, 2.f, -2.f, 3.f, -3.f})).RequireGrad()},
            {Ones({1, 2}, Dtype::kFloat32)},
            {Full({2, 3}, 1e-3f)});
}

TEST_P(IndexingTest, AtDoubleBackward) {
    CheckDoubleBackwardComputation(
            [](const std::vector<Array>& xs) -> std::vector<Array> {
                std::vector<ArrayIndex> indices{0, NewAxis{}, Slice{1, 3}};
                auto y = internal::At(xs[0], indices);
                return {y * y};  // to make it nonlinear
            },
            {(*testing::BuildArray({2, 3}).WithData<float>({1.f, -1.f, 2.f, -2.f, 3.f, -3.f})).RequireGrad()},
            {Ones({1, 2}, Dtype::kFloat32).RequireGrad()},
            {Ones({2, 3}, Dtype::kFloat32)},
            {Full({2, 3}, 1e-3f), Full({1, 2}, 1e-3f)});
}

TEST_P(IndexingTest, Take) {
    using T = int8_t;
    Shape input_shape{2, 4};
    Shape indices_shape{2, 3};
    Shape output_shape{2, 2, 3};
    int8_t axis = 1;
    Array a = testing::BuildArray(input_shape).WithLinearData<T>().WithPadding(1);
    Array indices = testing::BuildArray(indices_shape).WithData<int64_t>({0, 14, 3, 1, -10, 1});
    Array b = Take(a, indices, axis);

    EXPECT_EQ(output_shape, b.shape());
    Array e = testing::BuildArray(output_shape).WithData<T>({0, 2, 3, 1, 2, 1, 4, 6, 7, 5, 6, 5});
    EXPECT_ARRAY_EQ(e, b);
}

TEST_P(IndexingTest, TakeBackward) {
    using T = double;
    Shape input_shape{2, 4};
    Shape indices_shape{2, 3};
    Shape output_shape{2, 2, 3};
    int8_t axis = 1;
    Array a = (*testing::BuildArray(input_shape).WithLinearData<T>().WithPadding(1)).RequireGrad();
    Array indices = testing::BuildArray(indices_shape).WithData<int64_t>({0, 14, 3, 1, -10, 1});
    Array go = testing::BuildArray(output_shape).WithLinearData<T>(0.1, 0.1).WithPadding(1);
    Array eps = Full(input_shape, 1e-3);

    CheckBackward(
            [&indices, axis](const std::vector<Array>& xs) -> std::vector<Array> { return {Take(xs[0], indices, axis)}; },
            {a},
            {go},
            {eps});
}

TEST_P(IndexingTest, TakeDoubleBackward) {
    using T = double;
    Shape input_shape{2, 4};
    Shape indices_shape{2, 3};
    Shape output_shape{2, 2, 3};
    int8_t axis = 1;
    Array a = (*testing::BuildArray(input_shape).WithLinearData<T>().WithPadding(1)).RequireGrad();
    Array indices = testing::BuildArray(indices_shape).WithData<int64_t>({0, 14, 3, 1, -10, 1});
    Array go = (*testing::BuildArray(output_shape).WithLinearData<T>(0.1, 0.1).WithPadding(1)).RequireGrad();
    Array ggi = testing::BuildArray(input_shape).WithLinearData<T>(0.1, 0.1).WithPadding(1);
    Array epsi = Full(input_shape, 1e-3);
    Array epso = Full(output_shape, 1e-3);

    CheckDoubleBackwardComputation(
            [&indices, axis](const std::vector<Array>& xs) -> std::vector<Array> {
                auto y = Take(xs[0], indices, axis);
                return {y * y};  // to make it nonlinear
            },
            {a},
            {go},
            {ggi},
            {epsi, epso});
}

TEST_P(IndexingTest, TakeLongAxis) {
    Array a = testing::BuildArray({128}).WithLinearData<float>();
    Array indices = Full({1}, int64_t{10});
    Array b = Take(a, indices, 0);

    EXPECT_EQ(Shape{1}, b.shape());
    Array e = Full({1}, 10.f);
    EXPECT_ARRAY_EQ(e, b);
}

INSTANTIATE_TEST_CASE_P(
        ForEachBackend,
        IndexingTest,
        ::testing::Values(
#ifdef XCHAINER_ENABLE_CUDA
                std::string{"cuda"},
#endif  // XCHAINER_ENABLE_CUDA
                std::string{"native"}));

}  // namespace
}  // namespace xchainer
<commit_msg>indexing_test.cc: CheckForward<commit_after>#include "xchainer/routines/indexing.h"

#include <cstdint>
#include <string>
#include <vector>

#include <gtest/gtest.h>
#include <nonstd/optional.hpp>

#include "xchainer/array.h"
#include "xchainer/array_index.h"
#include "xchainer/check_backward.h"
#include "xchainer/error.h"
#include "xchainer/shape.h"
#include "xchainer/strides.h"
#include "xchainer/testing/array.h"
#include "xchainer/testing/array_check.h"
#include "xchainer/testing/device_session.h"
#include "xchainer/testing/routines.h"

namespace xchainer {
namespace {

class IndexingTest : public ::testing::TestWithParam<std::string> {
protected:
    void SetUp() override {
        const std::string& backend_name = GetParam();
        device_session_.emplace(DeviceId{backend_name, 0});
    }

    void TearDown() override { device_session_.reset(); }

private:
    nonstd::optional<testing::DeviceSession> device_session_;
};

TEST_P(IndexingTest, At) {
    using T = int32_t;
    Shape input_shape{2, 3, 1};
    Shape output_shape{1, 2, 1};
    std::vector<ArrayIndex> indices{-1, NewAxis{}, Slice{1, 3}};
    Array a = testing::BuildArray(input_shape).WithLinearData<T>();
    Array e = testing::BuildArray(output_shape).WithData<T>({4, 5});

    testing::CheckForward(
            [&indices](const std::vector<Array>& xs) {
                Array y = internal::At(xs[0], indices);
                // Check if strides are 0 for newaxis.
                EXPECT_EQ(0, y.strides()[0]);
                EXPECT_NE(0, y.strides()[1]);
                EXPECT_NE(0, y.strides()[2]);
                return std::vector<Array>{y};
            },
            {a},
            {e},
            // TODO(sonots): Run concurrency test in CUDA
            GetParam() == "cuda" ? 0 : 1);
}

// Index out of bounds
TEST_P(IndexingTest, InvalidAt1) {
    using T = int32_t;
    Shape input_shape{2, 3};
    std::vector<ArrayIndex> indices{0, 0, 0};
    Array a = testing::BuildArray(input_shape).WithLinearData<T>();
    EXPECT_THROW(internal::At(a, indices), DimensionError);
}

// Too large dimension
TEST_P(IndexingTest, InvalidAt2) {
    using T = int32_t;
    Shape input_shape{2, 3};
    std::vector<ArrayIndex> indices{2};
    Array a = testing::BuildArray(input_shape).WithLinearData<T>();
    EXPECT_THROW(internal::At(a, indices), DimensionError);
}

TEST_P(IndexingTest, AtBackward) {
    CheckBackward(
            [](const std::vector<Array>& xs) -> std::vector<Array> {
                std::vector<ArrayIndex> indices{1, NewAxis{}, Slice{1, 3}};
                return {internal::At(xs[0], indices)};
            },
            {(*testing::BuildArray({2, 3}).WithData<float>({1.f, -1.f, 2.f, -2.f, 3.f, -3.f})).RequireGrad()},
            {Ones({1, 2}, Dtype::kFloat32)},
            {Full({2, 3}, 1e-3f)});
}

TEST_P(IndexingTest, AtDoubleBackward) {
    CheckDoubleBackwardComputation(
            [](const std::vector<Array>& xs) -> std::vector<Array> {
                std::vector<ArrayIndex> indices{0, NewAxis{}, Slice{1, 3}};
                auto y = internal::At(xs[0], indices);
                return {y * y};  // to make it nonlinear
            },
            {(*testing::BuildArray({2, 3}).WithData<float>({1.f, -1.f, 2.f, -2.f, 3.f, -3.f})).RequireGrad()},
            {Ones({1, 2}, Dtype::kFloat32).RequireGrad()},
            {Ones({2, 3}, Dtype::kFloat32)},
            {Full({2, 3}, 1e-3f), Full({1, 2}, 1e-3f)});
}

TEST_P(IndexingTest, Take) {
    using T = int8_t;
    Shape input_shape{2, 4};
    Shape indices_shape{2, 3};
    Shape output_shape{2, 2, 3};
    int8_t axis = 1;
    Array a = testing::BuildArray(input_shape).WithLinearData<T>().WithPadding(1);
    Array indices = testing::BuildArray(indices_shape).WithData<int64_t>({0, 14, 3, 1, -10, 1});
    Array e = testing::BuildArray(output_shape).WithData<T>({0, 2, 3, 1, 2, 1, 4, 6, 7, 5, 6, 5});

    testing::CheckForward(
            [&indices, &axis](const std::vector<Array>& xs) { return std::vector<Array>{Take(xs[0], indices, axis)}; },
            {a},
            {e},
            // TODO(sonots): Run concurrency test in CUDA
            GetParam() == "cuda" ? 0 : 1);
}

TEST_P(IndexingTest, TakeBackward) {
    using T = double;
    Shape input_shape{2, 4};
    Shape indices_shape{2, 3};
    Shape output_shape{2, 2, 3};
    int8_t axis = 1;
    Array a = (*testing::BuildArray(input_shape).WithLinearData<T>().WithPadding(1)).RequireGrad();
    Array indices = testing::BuildArray(indices_shape).WithData<int64_t>({0, 14, 3, 1, -10, 1});
    Array go = testing::BuildArray(output_shape).WithLinearData<T>(0.1, 0.1).WithPadding(1);
    Array eps = Full(input_shape, 1e-3);

    CheckBackward(
            [&indices, axis](const std::vector<Array>& xs) -> std::vector<Array> { return {Take(xs[0], indices, axis)}; },
            {a},
            {go},
            {eps});
}

TEST_P(IndexingTest, TakeDoubleBackward) {
    using T = double;
    Shape input_shape{2, 4};
    Shape indices_shape{2, 3};
    Shape output_shape{2, 2, 3};
    int8_t axis = 1;
    Array a = (*testing::BuildArray(input_shape).WithLinearData<T>().WithPadding(1)).RequireGrad();
    Array indices = testing::BuildArray(indices_shape).WithData<int64_t>({0, 14, 3, 1, -10, 1});
    Array go = (*testing::BuildArray(output_shape).WithLinearData<T>(0.1, 0.1).WithPadding(1)).RequireGrad();
    Array ggi = testing::BuildArray(input_shape).WithLinearData<T>(0.1, 0.1).WithPadding(1);
    Array epsi = Full(input_shape, 1e-3);
    Array epso = Full(output_shape, 1e-3);

    CheckDoubleBackwardComputation(
            [&indices, axis](const std::vector<Array>& xs) -> std::vector<Array> {
                auto y = Take(xs[0], indices, axis);
                return {y * y};  // to make it nonlinear
            },
            {a},
            {go},
            {ggi},
            {epsi, epso});
}

TEST_P(IndexingTest, TakeLongAxis) {
    Array a = testing::BuildArray({128}).WithLinearData<float>();
    Array indices = Full({1}, int64_t{10});
    Array e = Full({1}, 10.f);

    testing::CheckForward(
            [&indices](const std::vector<Array>& xs) { return std::vector<Array>{Take(xs[0], indices, 0)}; },
            {a},
            {e},
            // TODO(sonots): Run concurrency test in CUDA
            GetParam() == "cuda" ? 0 : 1);
}

INSTANTIATE_TEST_CASE_P(
        ForEachBackend,
        IndexingTest,
        ::testing::Values(
#ifdef XCHAINER_ENABLE_CUDA
                std::string{"cuda"},
#endif  // XCHAINER_ENABLE_CUDA
                std::string{"native"}));

}  // namespace
}  // namespace xchainer
<|endoftext|>


<commit_before>
/*
    pbrt source code Copyright(c) 1998-2009 Matt Pharr and Greg Humphreys.

    This file is part of pbrt.

    pbrt is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.  Note that the text contents of
    the book "Physically Based Rendering" are *not* licensed under the
    GNU GPL.

    pbrt is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */

// main/pbrt.cpp*
#include "pbrt.h"
#include "api.h"
#include "probes.h"
#include "parser.h"
#ifdef PBRT_HAS_LIBSDL
#include "SDL_main.h"
#endif // PBRT_HAS_LIBSDL

// main program
int main(int argc, char *argv[]) {
    // Print welcome banner
    printf("pbrt version %s of %s at %s\n",
           PBRT_VERSION, __DATE__, __TIME__);
    printf("Copyright (c)1998-2009 Matt Pharr and "
           "Greg Humphreys.\n");
    printf("The source code to pbrt (but *not* the contents of the book) is\n");
    printf("covered by the GNU General Public License.  See the file COPYING.txt\n");
    printf("for the conditions of the license.\n");
    fflush(stdout);
    pbrtInit();
    // Process scene description
    PBRT_STARTED_PARSING();
    if (argc == 1) {
        // Parse scene from standard input
        ParseFile("-");
    } else {
        // Parse scene from input files
        for (int i = 1; i < argc; i++)
            if (!ParseFile(argv[i]))
                Error("Couldn't open scene file \"%s\"", argv[i]);
    }
    pbrtCleanup();
    return 0;
}

<commit_msg>John Danks: print number of cores detected in startup message<commit_after>
/*
    pbrt source code Copyright(c) 1998-2009 Matt Pharr and Greg Humphreys.

    This file is part of pbrt.

    pbrt is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.  Note that the text contents of
    the book "Physically Based Rendering" are *not* licensed under the
    GNU GPL.

    pbrt is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */

// main/pbrt.cpp*
#include "pbrt.h"
#include "api.h"
#include "probes.h"
#include "parser.h"
#include "parallel.h"
#ifdef PBRT_HAS_LIBSDL
#include "SDL_main.h"
#endif // PBRT_HAS_LIBSDL

// main program
int main(int argc, char *argv[]) {
    // Print welcome banner
    printf("pbrt version %s of %s at %s [%d core(s) detected]\n",
           PBRT_VERSION, __DATE__, __TIME__, NumSystemCores());
    printf("Copyright (c)1998-2009 Matt Pharr and "
           "Greg Humphreys.\n");
    printf("The source code to pbrt (but *not* the book contents) is covered by the GNU GPL.\n");
    printf("See the file COPYING.txt for the conditions of the license.\n");
    fflush(stdout);
    pbrtInit();
    // Process scene description
    PBRT_STARTED_PARSING();
    if (argc == 1) {
        // Parse scene from standard input
        ParseFile("-");
    } else {
        // Parse scene from input files
        for (int i = 1; i < argc; i++)
            if (!ParseFile(argv[i]))
                Error("Couldn't open scene file \"%s\"", argv[i]);
    }
    pbrtCleanup();
    return 0;
}

<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015 Relja Ljubobratovic, ljubobratovic.relja@gmail.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Description:
// Collection of functions for calibration pattern detection.
//
// Author:
// Relja Ljubobratovic, ljubobratovic.relja@gmail.com

#ifndef CALIBPATTERN_HPP_ORZQNP5Z
#define CALIBPATTERN_HPP_ORZQNP5Z

#include <vector>

#include <contour.hpp>
#include <vector.hpp>
#include <matrix.hpp>

std::vector<cv::vec2r> detect_pattern(const cv::matrixr &image, unsigned patternRows, unsigned patternCols,
		real_t angThresh = 15., real_t magThresh = 0.15, unsigned nnCount = 8);

std::vector<cv::vec2r> sub_pixel_detect(const std::vector<cv::vec2r> &corners, const cv::matrixr &src,
		const cv::vec2i &win = {10, 10}, real_t eps = 10e-6, unsigned maxIters = 100);

#endif /* end of include guard: CALIBPATTERN_HPP_ORZQNP5Z */

<commit_msg>added chessboard drawing function<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 Relja Ljubobratovic, ljubobratovic.relja@gmail.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Description:
// Collection of functions for calibration pattern detection.
//
// Author:
// Relja Ljubobratovic, ljubobratovic.relja@gmail.com

#ifndef CALIBPATTERN_HPP_ORZQNP5Z
#define CALIBPATTERN_HPP_ORZQNP5Z

#include <vector>

#include <contour.hpp>
#include <vector.hpp>
#include <matrix.hpp>
#include <draw.hpp>

std::vector<cv::vec2r> detect_pattern(const cv::matrixr &image, unsigned patternRows, unsigned patternCols,
		real_t angThresh = 15., real_t magThresh = 0.15, unsigned nnCount = 8);

std::vector<cv::vec2r> sub_pixel_detect(const std::vector<cv::vec2r> &corners, const cv::matrixr &src,
		const cv::vec2i &win = {10, 10}, real_t eps = 10e-6, unsigned maxIters = 100);

template<typename _Tp>
void draw_chessboard(cv::matrix<_Tp> &image, const std::vector<cv::vec2r> &pattern, const _Tp &color) {

	ASSERT(image && !pattern.empty());

	for (unsigned i = 1; i < pattern.size(); ++i) {
		cv::draw_line(image, pattern[i-1], pattern[i], color);
	}
}

#endif /* end of include guard: CALIBPATTERN_HPP_ORZQNP5Z */

<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>

#define DLL_PARALLEL
#define DLL_SVM_SUPPORT

#include "dll/conv_rbm.hpp"
#include "dll/conv_dbn.hpp"
#include "dll/test.hpp"
#include "dll/ocv_visualizer.hpp"

#include "dll/cpp_utils/algorithm.hpp"
#include "dll/cpp_utils/data.hpp"

#include "icdar/icdar_reader.hpp"

#include <opencv2/opencv.hpp>

static constexpr const std::size_t window = 16;
static constexpr const std::size_t step_size = 4;

static constexpr const std::size_t min_peaks = 2;
static constexpr const std::size_t max_peaks = 8;

static constexpr const std::size_t binary_threshold = 35;

cv::Mat open_image(const std::string& path);

constexpr uint8_t reduce_val(uint8_t val, uint8_t mul){
    //return val;
    //return (val / mul) * mul;
    return val / mul * mul + mul / 2;
    //if (val < 192) return uchar(val / 64.0 + 0.5) * 64;
    //return 255;
    //if (val < 64) return 0;
    //if (val < 128) return 64;
    //return 255;
}

void reduce_image(cv::Mat& image, uint8_t mul){
    for(std::size_t x = 0; x < image.cols; ++x){
        for(std::size_t y = 0; y < image.rows; ++y){
            image.at<cv::Vec3b>(cv::Point(x,y))[0] = reduce_val(image.at<cv::Vec3b>(cv::Point(x,y))[0], mul);
            image.at<cv::Vec3b>(cv::Point(x,y))[1] = reduce_val(image.at<cv::Vec3b>(cv::Point(x,y))[1], mul);
            image.at<cv::Vec3b>(cv::Point(x,y))[2] = reduce_val(image.at<cv::Vec3b>(cv::Point(x,y))[2], mul);
        }
    }
}

template<typename Iterator>
std::size_t count_peaks(Iterator first, Iterator last){
    std::size_t peaks = 0;
    bool current = false;

    while(first != last){
        auto c = *first;

        if(!current && c > 0){
            current = true;
        }

        if(current && c == 0){
            ++peaks;
            current = false;
        }

        ++first;
    }

    return peaks;
}

std::size_t count_peaks(cv::Mat& image, std::size_t channel){
    std::array<uint8_t, 256> intensities;
    std::fill(intensities.begin(), intensities.end(), 0);

    for(auto it = image.begin<cv::Vec3b>(), end = image.end<cv::Vec3b>(); it != end; ++it){
        ++intensities[(*it)[channel]];
    }

    return count_peaks(intensities.begin(), intensities.end());
}

std::size_t count_gray_peaks(cv::Mat& image){
    std::array<uint8_t, 256> intensities;
    std::fill(intensities.begin(), intensities.end(), 0);

    for(auto it = image.begin<uchar>(), end = image.end<uchar>(); it != end; ++it){
        ++intensities[(*it)];
    }

    return count_peaks(intensities.begin(), intensities.end());
}

cv::Mat binarize(cv::Mat& source_image, uint8_t mul){
    auto image = source_image.clone();

    cv::Mat gray_image;
    cv::cvtColor(source_image, gray_image, CV_RGB2GRAY);

    //cv::namedWindow("Gray", cv::WINDOW_AUTOSIZE);
    //cv::imshow("Gray", gray_image);

    cv::Mat binary_map_image(image.rows, image.cols, CV_8U);
    binary_map_image = cv::Scalar(0);

    std::vector<std::size_t> intensity_map(image.cols * image.rows, 0);

    reduce_image(image, mul);
    //reduce_image(gray_image, mul);

    //cv::namedWindow("Reduced", cv::WINDOW_AUTOSIZE);
    //cv::imshow("Reduced", image);

    //cv::namedWindow("Reduced Gray", cv::WINDOW_AUTOSIZE);
    //cv::imshow("Reduced Gray", gray_image);

    for(std::size_t x = 0; x * step_size + window < image.cols; ++x){
        for(std::size_t y = 0; y * step_size + window < image.rows; ++y){
            cv::Rect rect(x*step_size, y*step_size, window,window);
            cv::Mat roi(image, rect);
            cv::Mat gray_roi(gray_image, rect);

            auto r_peaks = count_peaks(roi, 0);
            auto g_peaks = count_peaks(roi, 1);
            auto b_peaks = count_peaks(roi, 2);
            auto gray_peaks = count_gray_peaks(gray_roi);

            //auto value = gray_peaks > 1 [>&& gray_peaks < max_peaks <] ? 1 : 0;

            std::size_t value =
                    (r_peaks > min_peaks && r_peaks < max_peaks ? 1 : 0)
                +   (g_peaks > min_peaks && g_peaks < max_peaks ? 1 : 0)
                +   (b_peaks > min_peaks && b_peaks < max_peaks ? 1 : 0);

            if(value > 0){
                for(std::size_t xx = 0; xx < window; ++xx){
                    for(std::size_t yy = 0; yy < window; ++yy){
                        intensity_map[(xx + x * step_size) * image.rows + yy + y * step_size] += value;
                    }
                }
            }
        }
    }

    for(std::size_t x = 0; x < image.cols; ++x){
        for(std::size_t y = 0; y < image.rows; ++y){
            if(x > image.cols - window){
                if(intensity_map[x * image.rows + y] < (binary_threshold - 5 * (image.cols - x))){
                    binary_map_image.at<uchar>(cv::Point(x,y)) = 0;
                } else {
                    binary_map_image.at<uchar>(cv::Point(x,y)) = 255;
                }
            } else {
                if(intensity_map[x * image.rows + y] < binary_threshold){
                    binary_map_image.at<uchar>(cv::Point(x,y)) = 0;
                } else {
                    binary_map_image.at<uchar>(cv::Point(x,y)) = 255;
                }
            }
        }
    }

    return binary_map_image;
}

cv::Mat combine(const std::vector<cv::Mat>& binary_maps){
    if(binary_maps.size() == 1){
        return binary_maps[0];
    }

    cv::Mat binary_map_image(binary_maps[0].rows, binary_maps[0].cols, CV_8U);
    binary_map_image = cv::Scalar(0);

    for(auto& binary_map : binary_maps){
        for(std::size_t x = 0; x < binary_map.cols; ++x){
            for(std::size_t y = 0; y < binary_map.rows; ++y){
                if(binary_map.at<uchar>(cv::Point(x,y)) == 255){
                    binary_map_image.at<uchar>(cv::Point(x,y)) = 255;
                }
            }
        }
    }

    return binary_map_image;
}

void process_image(const std::string& source_path, bool display = false){
    auto image = open_image(source_path);

    std::vector<cv::Mat> binary_maps;

    binary_maps.push_back(binarize(image, 32));
    binary_maps.push_back(binarize(image, 48));
    binary_maps.push_back(binarize(image, 64));

    auto binary_map_image = combine(binary_maps);

    auto structure_elem = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(9, 9));
    cv::morphologyEx(binary_map_image, binary_map_image, cv::MORPH_OPEN, structure_elem);
    cv::morphologyEx(binary_map_image, binary_map_image, cv::MORPH_CLOSE, structure_elem);

    auto dst_image = image.clone();
    for(std::size_t x = 0; x < image.cols; ++x){
        for(std::size_t y = 0; y < image.rows; ++y){
            if(binary_map_image.at<uchar>(cv::Point(x,y)) != 255){
                dst_image.at<cv::Vec3b>(cv::Point(x,y))[0] = 0;
                dst_image.at<cv::Vec3b>(cv::Point(x,y))[1] = 0;
                dst_image.at<cv::Vec3b>(cv::Point(x,y))[2] = 0;
            }
        }
    }

    auto dest_path = source_path;
    dest_path.insert(dest_path.rfind('.'), ".map");
    imwrite(dest_path.c_str(), dst_image);

    if(display){
        cv::namedWindow("Source", cv::WINDOW_AUTOSIZE);
        cv::imshow("Source", image);

        cv::namedWindow("Dest", cv::WINDOW_AUTOSIZE);
        cv::imshow("Dest", dst_image);

        cv::namedWindow("Map", cv::WINDOW_AUTOSIZE);
        cv::imshow("Map", binary_map_image);

        cv::waitKey(0);
    }
}

int main(int argc, char* argv[]){
    if(argc > 1){
        std::string source_path = "/home/wichtounet/datasets/icdar_2013_natural_wip/train/";
        source_path += argv[1];
        source_path += ".jpg";
        process_image(source_path, true);
    } else {
        for(std::size_t i = 100; i <= 328; ++i){
            std::string source_path = "/home/wichtounet/datasets/icdar_2013_natural_wip/train/" + std::to_string(i) + ".jpg";
            process_image(source_path);
        }
    }

    return 0;
}

cv::Mat open_image(const std::string& path){
    auto source_image = cv::imread(path.c_str(), 1);

    if (!source_image.data){
        return source_image;
    }

    if(source_image.rows > 1000 || source_image.cols > 1000){
        auto factor = 1000.0f / std::max(source_image.rows, source_image.cols);

        cv::Mat resized_image;

        cv::resize(source_image, resized_image, cv::Size(), factor, factor, cv::INTER_AREA);

        return resized_image;
    }

    return source_image;
}
<commit_msg>Not working code<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>

#define DLL_PARALLEL
#define DLL_SVM_SUPPORT

#include "dll/conv_rbm.hpp"
#include "dll/conv_dbn.hpp"
#include "dll/test.hpp"
#include "dll/ocv_visualizer.hpp"

#include "dll/cpp_utils/algorithm.hpp"
#include "dll/cpp_utils/data.hpp"

#include "icdar/icdar_reader.hpp"

#include <opencv2/opencv.hpp>

static constexpr const std::size_t window = 16;
static constexpr const std::size_t step_size = 4;

static constexpr const std::size_t min_peaks = 2;
static constexpr const std::size_t max_peaks = 8;

static constexpr const std::size_t binary_threshold = 35;

cv::Mat open_image(const std::string& path);

constexpr uint8_t reduce_val(uint8_t val, uint8_t mul){
    return val / mul * mul + mul / 2;
}

void reduce_image(cv::Mat& image, uint8_t mul){
    for(std::size_t x = 0; x < image.cols; ++x){
        for(std::size_t y = 0; y < image.rows; ++y){
            image.at<cv::Vec3b>(cv::Point(x,y))[0] = reduce_val(image.at<cv::Vec3b>(cv::Point(x,y))[0], mul);
            image.at<cv::Vec3b>(cv::Point(x,y))[1] = reduce_val(image.at<cv::Vec3b>(cv::Point(x,y))[1], mul);
            image.at<cv::Vec3b>(cv::Point(x,y))[2] = reduce_val(image.at<cv::Vec3b>(cv::Point(x,y))[2], mul);
        }
    }
}

template<typename Iterator>
std::size_t count_peaks(Iterator first, Iterator last){
    std::size_t peaks = 0;
    bool current = false;

    while(first != last){
        auto c = *first;

        if(!current && c > 0){
            current = true;
        }

        if(current && c == 0){
            ++peaks;
            current = false;
        }

        ++first;
    }

    return peaks;
}

std::size_t count_peaks(cv::Mat& image, std::size_t channel){
    std::array<uint8_t, 256> intensities;
    std::fill(intensities.begin(), intensities.end(), 0);

    for(auto it = image.begin<cv::Vec3b>(), end = image.end<cv::Vec3b>(); it != end; ++it){
        ++intensities[(*it)[channel]];
    }

    static std::size_t zzz = 0;

    if(zzz == 666/* || count_gray_peaks(intensities.begin(), intensities.end()) > 1*/){
        for(std::size_t c = 0; c < 256; ++c){
            std::cout << c << ":" << static_cast<std::size_t>(intensities[c]) << std::endl;
        }

        std::cout << "peaks => " << count_peaks(intensities.begin(), intensities.end()) << std::endl;
    }

    ++zzz;

    return count_peaks(intensities.begin(), intensities.end());
}

template<typename Iterator>
std::size_t count_gray_peaks(Iterator first, Iterator last){
    std::size_t peaks = 0;

    bool current = false;
    bool up = false;
    std::size_t distance = 0;
    std::size_t prev = 0;
    std::size_t intensity = 0;

    while(first != last){
        auto c = *first;

        if(current){

            if(c < 1){
                ++distance;

                if(distance > 5){
                    current = false;

                    if(intensity > 25){
                        ++peaks;
                    }
                }
            } else {
                distance = 0;
                prev = c;
                if(c > intensity){
                    intensity = c;
                }
            }

        } else {

            if(c > 1){
                current = true;
                up = true;
                prev = c;
                distance = 0;
                intensity = c;
            }

        }

        ++first;
    }

    if(current && distance <= 5 && intensity > 25){
        ++peaks;
    }

    return peaks;
}

std::size_t count_gray_peaks(cv::Mat& image){
    std::array<uint8_t, 256> intensities;
    std::fill(intensities.begin(), intensities.end(), 0);

    for(auto it = image.begin<uchar>(), end = image.end<uchar>(); it != end; ++it){
        ++intensities[(*it)];
    }

    //static std::size_t zzz = 0;

    //if(zzz == 3333 || count_gray_peaks(intensities.begin(), intensities.end()) > 1){
        //for(std::size_t c = 0; c < 256; ++c){
            //std::cout << c << ":" << static_cast<std::size_t>(intensities[c]) << std::endl;
        //}

        //std::cout << "peaks => " << count_gray_peaks(intensities.begin(), intensities.end()) << std::endl;
    //}

    //++zzz;

    return count_gray_peaks(intensities.begin(), intensities.end());
}

cv::Mat binarize(cv::Mat& source_image, uint8_t mul){
    auto image = source_image.clone();

    std::size_t width = image.cols;
    std::size_t height = image.rows;

    cv::Mat gray_image;
    cv::cvtColor(source_image, gray_image, CV_RGB2GRAY);

    cv::equalizeHist(gray_image, gray_image);

    //cv::namedWindow("Gray", cv::WINDOW_AUTOSIZE);
    //cv::imshow("Gray", gray_image);

    cv::Mat binary_map_image(image.rows, image.cols, CV_8U);
    binary_map_image = cv::Scalar(0);

    std::vector<std::size_t> intensity_map(image.cols * image.rows, 0);

    reduce_image(image, mul);
    //reduce_image(gray_image, mul);

    //cv::namedWindow(std::to_string(mul) + "_reduced", cv::WINDOW_AUTOSIZE);
    //cv::imshow(std::to_string(mul) + "_reduced", image);

    //cv::namedWindow("Reduced Gray", cv::WINDOW_AUTOSIZE);
    //cv::imshow("Reduced Gray", gray_image);

    for(std::size_t x = 0; x * step_size + window < width; ++x){
        for(std::size_t y = 0; y * step_size + window < height; ++y){
            cv::Rect rect(x*step_size, y*step_size, window,window);
            cv::Mat roi(image, rect);
            cv::Mat gray_roi(gray_image, rect);

            auto r_peaks = count_peaks(roi, 0);
            auto g_peaks = count_peaks(roi, 1);
            auto b_peaks = count_peaks(roi, 2);
            auto gray_peaks = count_gray_peaks(gray_roi);

            //auto value = gray_peaks > 1 && gray_peaks < max_peaks - 2 ? 1 : 0;

            std::size_t value =
                    (r_peaks > min_peaks && r_peaks < max_peaks ? 1 : 0)
                +   (g_peaks > min_peaks && g_peaks < max_peaks ? 1 : 0)
                +   (b_peaks > min_peaks && b_peaks < max_peaks ? 1 : 0)
                //+   (gray_peaks > 1 && gray_peaks < max_peaks ? 1 : 0)
                    ;

            if(value > 0){
                for(std::size_t xx = 0; xx < window; ++xx){
                    for(std::size_t yy = 0; yy < window; ++yy){
                        intensity_map[(xx + x * step_size) * height + yy + y * step_size] += value;
                    }
                }
            }
        }
    }

    for(std::size_t x = 0; x < width; ++x){
        for(std::size_t y = 0; y < height; ++y){
            if(x > image.cols - window){
                if(intensity_map[x * height + y] < (binary_threshold - 5 * (width - x))){
                    binary_map_image.at<uchar>(cv::Point(x,y)) = 0;
                } else {
                    binary_map_image.at<uchar>(cv::Point(x,y)) = 255;
                }
            } else {
                if(intensity_map[x * image.rows + y] < binary_threshold){
                    binary_map_image.at<uchar>(cv::Point(x,y)) = 0;
                } else {
                    binary_map_image.at<uchar>(cv::Point(x,y)) = 255;
                }
            }
        }
    }

    return binary_map_image;
}

cv::Mat combine(const std::vector<cv::Mat>& binary_maps){
    if(binary_maps.size() == 1){
        return binary_maps[0];
    }

    cv::Mat binary_map_image(binary_maps[0].rows, binary_maps[0].cols, CV_8U);
    binary_map_image = cv::Scalar(0);

    for(auto& binary_map : binary_maps){
        for(std::size_t x = 0; x < binary_map.cols; ++x){
            for(std::size_t y = 0; y < binary_map.rows; ++y){
                if(binary_map.at<uchar>(cv::Point(x,y)) == 255){
                    binary_map_image.at<uchar>(cv::Point(x,y)) = 255;
                }
            }
        }
    }

    return binary_map_image;
}

void process_image(const std::string& source_path, bool display = false){
    auto image = open_image(source_path);

    std::vector<cv::Mat> binary_maps;

    //binary_maps.push_back(binarize(image, 2));
    binary_maps.push_back(binarize(image, 32));
    binary_maps.push_back(binarize(image, 48));
    binary_maps.push_back(binarize(image, 64));

    auto binary_map_image = combine(binary_maps);

    auto structure_elem = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(9, 9));
    cv::morphologyEx(binary_map_image, binary_map_image, cv::MORPH_OPEN, structure_elem);
    cv::morphologyEx(binary_map_image, binary_map_image, cv::MORPH_CLOSE, structure_elem);

    auto dst_image = image.clone();
    for(std::size_t x = 0; x < image.cols; ++x){
        for(std::size_t y = 0; y < image.rows; ++y){
            if(binary_map_image.at<uchar>(cv::Point(x,y)) != 255){
                dst_image.at<cv::Vec3b>(cv::Point(x,y))[0] = 0;
                dst_image.at<cv::Vec3b>(cv::Point(x,y))[1] = 0;
                dst_image.at<cv::Vec3b>(cv::Point(x,y))[2] = 0;
            }
        }
    }

    auto dest_path = source_path;
    dest_path.insert(dest_path.rfind('.'), ".map");
    imwrite(dest_path.c_str(), dst_image);

    if(display){
        cv::namedWindow("Source", cv::WINDOW_AUTOSIZE);
        cv::imshow("Source", image);

        cv::namedWindow("Dest", cv::WINDOW_AUTOSIZE);
        cv::imshow("Dest", dst_image);

        cv::namedWindow("Map", cv::WINDOW_AUTOSIZE);
        cv::imshow("Map", binary_map_image);

        cv::waitKey(0);
    }
}

int main(int argc, char* argv[]){
    if(argc > 1){
        std::string source_path = "/home/wichtounet/datasets/icdar_2013_natural_wip/train/";
        source_path += argv[1];
        source_path += ".jpg";
        process_image(source_path, true);
    } else {
        for(std::size_t i = 100; i <= 328; ++i){
            std::string source_path = "/home/wichtounet/datasets/icdar_2013_natural_wip/train/" + std::to_string(i) + ".jpg";
            process_image(source_path);
        }
    }

    return 0;
}

cv::Mat open_image(const std::string& path){
    auto source_image = cv::imread(path.c_str(), 1);

    if (!source_image.data){
        return source_image;
    }

    if(source_image.rows > 1000 || source_image.cols > 1000){
        auto factor = 1000.0f / std::max(source_image.rows, source_image.cols);

        cv::Mat resized_image;

        cv::resize(source_image, resized_image, cv::Size(), factor, factor, cv::INTER_AREA);

        return resized_image;
    }

    return source_image;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <math.h>
#include "chunk_shader.h"
#include "matrix.h"
#include "util.h"

namespace konstructs {

    const Array3i chunk_offset = Vector3i(CHUNK_SIZE, CHUNK_SIZE, CHUNK_SIZE).array();

    ChunkModel::ChunkModel(const shared_ptr<ChunkModelResult> &data,
                           GLuint _position_attr, GLuint _normal_attr, GLuint _uv_attr) :
        position(data->position),
        size(data->size),
        faces(data->faces),
        position_attr(_position_attr),
        normal_attr(_normal_attr),
        uv_attr(_uv_attr) {
        glGenBuffers(1, &buffer);
        glBindBuffer(GL_ARRAY_BUFFER, buffer);
        glBufferData(GL_ARRAY_BUFFER, size * sizeof(GLfloat),
                     data->data(), GL_STATIC_DRAW);
        Vector3f pos =
            (position.array() * chunk_offset).matrix().cast<float>();

        Vector3f rpos = Vector3f(pos[0], pos[2], pos[1]);
        translation = Affine3f(Translation3f(rpos)).matrix();
    }

    void ChunkModel::bind() {
        glBindBuffer(GL_ARRAY_BUFFER, buffer);
        glEnableVertexAttribArray(position_attr);
        glEnableVertexAttribArray(normal_attr);
        glEnableVertexAttribArray(uv_attr);
        glVertexAttribPointer(position_attr, 3, GL_FLOAT, GL_FALSE,
                              sizeof(GLfloat) * 10, 0);
        glVertexAttribPointer(normal_attr, 3, GL_FLOAT, GL_FALSE,
                              sizeof(GLfloat) * 10, (GLvoid *)(sizeof(GLfloat) * 3));
        glVertexAttribPointer(uv_attr, 4, GL_FLOAT, GL_FALSE,
                              sizeof(GLfloat) * 10, (GLvoid *)(sizeof(GLfloat) * 6));
    }

    void ChunkShader::add(const shared_ptr<ChunkModelResult> &data) {
        auto it = models.find(data->position);
        auto model = new ChunkModel(data, position_attr,
                                    normal_attr, uv_attr);
        if (it != models.end()) {
            auto second = it->second;
            it->second = model;
            delete second;
        } else {
            models.insert({data->position, model});
        }

    }

    void shtxt_path(const char *name, const char *type, char *path, size_t max_len) {
        snprintf(path, max_len, "%s/%s", type, name);

        if (!file_exist(path)) {
            snprintf(path, max_len, "/usr/local/share/konstructs-client/%s/%s", type, name);
        }

        if (!file_exist(path)) {
            printf("Error, no %s for %s found.\n", type, name);
            exit(1);
        }
    }

    void texture_path(const char *name, char *path, size_t max_len) {
        shtxt_path(name, "textures", path, max_len);
    }

    void load_textures() {
        char txtpth[KONSTRUCTS_PATH_SIZE];

        GLuint sky;
        glGenTextures(1, &sky);
        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_2D, sky);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        texture_path("sky.png", txtpth, KONSTRUCTS_PATH_SIZE);
        load_png_texture(txtpth);
    }

    ChunkShader::ChunkShader(const int _radius, const float _fov) :
        ShaderProgram(
        "chunk",
        "#version 330\n"
        "uniform mat4 matrix;\n"
        "uniform float fog_distance;\n"
        "uniform mat4 translation;\n"
        "in vec4 position;\n"
        "in vec3 normal;\n"
        "in vec4 uv;\n"
        "out vec2 fragment_uv;\n"
        "out float fragment_ao;\n"
        "out float fragment_light;\n"
        "out float fog_factor;\n"
        "out float fog_height;\n"
        "out float diffuse;\n"
        "const float pi = 3.14159265;\n"
        "const vec3 light_direction = normalize(vec3(-1.0, 1.0, -1.0));\n"
        "void main() {\n"
        "    vec4 global_position = translation * position;\n"
        "    gl_Position = matrix * global_position;\n"
        "    fragment_uv = uv.xy;\n"
        "    fragment_ao = 0.3 + (1.0 - uv.z) * 0.7;\n"
        "    fragment_light = uv.w;\n"
        "    diffuse = max(0.0, dot(normal, light_direction));\n"
        "}\n",
        "#version 330\n"
        "uniform sampler2D sampler;\n"
        "uniform sampler2D sky_sampler;\n"
        "uniform float timer;\n"
        "uniform float daylight;\n"
        "in vec2 fragment_uv;\n"
        "in float fragment_ao;\n"
        "in float fragment_light;\n"
        "in float diffuse;\n"
        "out vec4 frag_color;\n"
        "const float pi = 3.14159265;\n"
        "void main() {\n"
        "    vec3 color = vec3(texture2D(sampler, fragment_uv));\n"
        "    if (color == vec3(1.0, 0.0, 1.0)) {\n"
        "        discard;\n"
        "    }\n"
        "    float df = diffuse;\n"
        "    float ao = fragment_ao;\n"
        "    ao = min(1.0, ao + fragment_light);\n"
        "    df = min(1.0, df + fragment_light);\n"
        "    float value = min(1.0, daylight + fragment_light);\n"
        "    vec3 light_color = vec3(value * 0.3 + 0.2);\n"
        "    vec3 ambient = vec3(value * 0.3 + 0.2) + vec3(sin(pi*daylight)/2, sin(pi*daylight)/4, 0.0);\n"
        "    vec3 light = ambient + light_color * df;\n"
        "    color = clamp(color * light * ao, vec3(0.0), vec3(1.0));\n"
        "    frag_color = vec4(color, 1.0);\n"
        "}\n"),
        position_attr(attributeId("position")),
        normal_attr(attributeId("normal")),
        uv_attr(attributeId("uv")),
        matrix(uniformId("matrix")),
        translation(uniformId("translation")),
        sampler(uniformId("sampler")),
        daylight(uniformId("daylight")),
        radius(_radius),
        fov(_fov) {
        load_textures();
    }

    int ChunkShader::render(const Player &p, const int width, const int height) {
        int faces = 0;
        int visible = 0;
        bind([&](Context c) {
                c.enable(GL_DEPTH_TEST);
                c.enable(GL_CULL_FACE);
                float aspect_ratio = (float)width / (float)height;
                float max_distance = (radius - 1) * CHUNK_SIZE;
                const Matrix4f m = matrix::projection_perspective(fov, aspect_ratio, 0.25, max_distance) * p.view();
                c.set(matrix, m);
                c.set(sampler, 0);
                c.set(daylight, 0.25f);
                float planes[6][4];
                matrix::ext_frustum_planes(planes, radius, m);
                for(const auto &pair : models) {
                    const auto &m = pair.second;
                    if(!chunk_visible(planes, m->position))
                        continue;
                    visible++;
                    c.set(translation, m->translation);
                    c.draw(m, 0, m->size);
                    faces += m->faces;
                }
                c.disable(GL_CULL_FACE);
                c.disable(GL_DEPTH_TEST);
            });
        std::cout << "CHUNKS: " << models.size() << " VISIBLE: " << visible << std::endl;
        return faces;
    }

    bool chunk_visible(const float planes[6][4], const Vector3i &position) {
        float x = position[0] * CHUNK_SIZE - 1;
        float z = position[1] * CHUNK_SIZE - 1;
        float y = position[2] * CHUNK_SIZE - 1;
        float d = CHUNK_SIZE + 1;
        float points[8][3] = {
            {x + 0, y + 0, z + 0},
            {x + d, y + 0, z + 0},
            {x + 0, y + 0, z + d},
            {x + d, y + 0, z + d},
            {x + 0, y + d, z + 0},
            {x + d, y + d, z + 0},
            {x + 0, y + d, z + d},
            {x + d, y + d, z + d}
        };
        for (int i = 0; i < 6; i++) {
            int in = 0;
            int out = 0;
            for (int j = 0; j < 8; j++) {
                float d =
                    planes[i][0] * points[j][0] +
                    planes[i][1] * points[j][1] +
                    planes[i][2] * points[j][2] +
                    planes[i][3];
                if (d < 0) {
                    out++;
                }
                else {
                    in++;
                }
                if (in && out) {
                    break;
                }
            }
            if (in == 0) {
                return false;
            }
        }
        return true;
    }

};
<commit_msg>Fix invalid size of vertices to render<commit_after>#include <iostream>
#include <math.h>
#include "chunk_shader.h"
#include "matrix.h"
#include "util.h"

namespace konstructs {

    const Array3i chunk_offset = Vector3i(CHUNK_SIZE, CHUNK_SIZE, CHUNK_SIZE).array();

    ChunkModel::ChunkModel(const shared_ptr<ChunkModelResult> &data,
                           GLuint _position_attr, GLuint _normal_attr, GLuint _uv_attr) :
        position(data->position),
        size(data->size),
        faces(data->faces),
        position_attr(_position_attr),
        normal_attr(_normal_attr),
        uv_attr(_uv_attr) {
        glGenBuffers(1, &buffer);
        glBindBuffer(GL_ARRAY_BUFFER, buffer);
        glBufferData(GL_ARRAY_BUFFER, size * sizeof(GLfloat),
                     data->data(), GL_STATIC_DRAW);
        Vector3f pos =
            (position.array() * chunk_offset).matrix().cast<float>();

        Vector3f rpos = Vector3f(pos[0], pos[2], pos[1]);
        translation = Affine3f(Translation3f(rpos)).matrix();
    }

    void ChunkModel::bind() {
        glBindBuffer(GL_ARRAY_BUFFER, buffer);
        glEnableVertexAttribArray(position_attr);
        glEnableVertexAttribArray(normal_attr);
        glEnableVertexAttribArray(uv_attr);
        glVertexAttribPointer(position_attr, 3, GL_FLOAT, GL_FALSE,
                              sizeof(GLfloat) * 10, 0);
        glVertexAttribPointer(normal_attr, 3, GL_FLOAT, GL_FALSE,
                              sizeof(GLfloat) * 10, (GLvoid *)(sizeof(GLfloat) * 3));
        glVertexAttribPointer(uv_attr, 4, GL_FLOAT, GL_FALSE,
                              sizeof(GLfloat) * 10, (GLvoid *)(sizeof(GLfloat) * 6));
    }

    void ChunkShader::add(const shared_ptr<ChunkModelResult> &data) {
        auto it = models.find(data->position);
        auto model = new ChunkModel(data, position_attr,
                                    normal_attr, uv_attr);
        if (it != models.end()) {
            auto second = it->second;
            it->second = model;
            delete second;
        } else {
            models.insert({data->position, model});
        }

    }

    void shtxt_path(const char *name, const char *type, char *path, size_t max_len) {
        snprintf(path, max_len, "%s/%s", type, name);

        if (!file_exist(path)) {
            snprintf(path, max_len, "/usr/local/share/konstructs-client/%s/%s", type, name);
        }

        if (!file_exist(path)) {
            printf("Error, no %s for %s found.\n", type, name);
            exit(1);
        }
    }

    void texture_path(const char *name, char *path, size_t max_len) {
        shtxt_path(name, "textures", path, max_len);
    }

    void load_textures() {
        char txtpth[KONSTRUCTS_PATH_SIZE];

        GLuint sky;
        glGenTextures(1, &sky);
        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_2D, sky);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        texture_path("sky.png", txtpth, KONSTRUCTS_PATH_SIZE);
        load_png_texture(txtpth);
    }

    ChunkShader::ChunkShader(const int _radius, const float _fov) :
        ShaderProgram(
        "chunk",
        "#version 330\n"
        "uniform mat4 matrix;\n"
        "uniform float fog_distance;\n"
        "uniform mat4 translation;\n"
        "in vec4 position;\n"
        "in vec3 normal;\n"
        "in vec4 uv;\n"
        "out vec2 fragment_uv;\n"
        "out float fragment_ao;\n"
        "out float fragment_light;\n"
        "out float fog_factor;\n"
        "out float fog_height;\n"
        "out float diffuse;\n"
        "const float pi = 3.14159265;\n"
        "const vec3 light_direction = normalize(vec3(-1.0, 1.0, -1.0));\n"
        "void main() {\n"
        "    vec4 global_position = translation * position;\n"
        "    gl_Position = matrix * global_position;\n"
        "    fragment_uv = uv.xy;\n"
        "    fragment_ao = 0.3 + (1.0 - uv.z) * 0.7;\n"
        "    fragment_light = uv.w;\n"
        "    diffuse = max(0.0, dot(normal, light_direction));\n"
        "}\n",
        "#version 330\n"
        "uniform sampler2D sampler;\n"
        "uniform sampler2D sky_sampler;\n"
        "uniform float timer;\n"
        "uniform float daylight;\n"
        "in vec2 fragment_uv;\n"
        "in float fragment_ao;\n"
        "in float fragment_light;\n"
        "in float diffuse;\n"
        "out vec4 frag_color;\n"
        "const float pi = 3.14159265;\n"
        "void main() {\n"
        "    vec3 color = vec3(texture2D(sampler, fragment_uv));\n"
        "    if (color == vec3(1.0, 0.0, 1.0)) {\n"
        "        discard;\n"
        "    }\n"
        "    float df = diffuse;\n"
        "    float ao = fragment_ao;\n"
        "    ao = min(1.0, ao + fragment_light);\n"
        "    df = min(1.0, df + fragment_light);\n"
        "    float value = min(1.0, daylight + fragment_light);\n"
        "    vec3 light_color = vec3(value * 0.3 + 0.2);\n"
        "    vec3 ambient = vec3(value * 0.3 + 0.2) + vec3(sin(pi*daylight)/2, sin(pi*daylight)/4, 0.0);\n"
        "    vec3 light = ambient + light_color * df;\n"
        "    color = clamp(color * light * ao, vec3(0.0), vec3(1.0));\n"
        "    frag_color = vec4(color, 1.0);\n"
        "}\n"),
        position_attr(attributeId("position")),
        normal_attr(attributeId("normal")),
        uv_attr(attributeId("uv")),
        matrix(uniformId("matrix")),
        translation(uniformId("translation")),
        sampler(uniformId("sampler")),
        daylight(uniformId("daylight")),
        radius(_radius),
        fov(_fov) {
        load_textures();
    }

    int ChunkShader::render(const Player &p, const int width, const int height) {
        int faces = 0;
        int visible = 0;
        bind([&](Context c) {
                c.enable(GL_DEPTH_TEST);
                c.enable(GL_CULL_FACE);
                float aspect_ratio = (float)width / (float)height;
                float max_distance = (radius - 1) * CHUNK_SIZE;
                const Matrix4f m = matrix::projection_perspective(fov, aspect_ratio, 0.25, max_distance) * p.view();
                c.set(matrix, m);
                c.set(sampler, 0);
                c.set(daylight, 0.25f);
                float planes[6][4];
                matrix::ext_frustum_planes(planes, radius, m);
                for(const auto &pair : models) {
                    const auto &m = pair.second;
                    if(!chunk_visible(planes, m->position))
                        continue;
                    visible++;
                    c.set(translation, m->translation);
                    c.draw(m, 0, m->faces*6);
                    faces += m->faces;
                }
                c.disable(GL_CULL_FACE);
                c.disable(GL_DEPTH_TEST);
            });
        std::cout << "CHUNKS: " << models.size() << " VISIBLE: " << visible << std::endl;
        return faces;
    }

    bool chunk_visible(const float planes[6][4], const Vector3i &position) {
        float x = position[0] * CHUNK_SIZE - 1;
        float z = position[1] * CHUNK_SIZE - 1;
        float y = position[2] * CHUNK_SIZE - 1;
        float d = CHUNK_SIZE + 1;
        float points[8][3] = {
            {x + 0, y + 0, z + 0},
            {x + d, y + 0, z + 0},
            {x + 0, y + 0, z + d},
            {x + d, y + 0, z + d},
            {x + 0, y + d, z + 0},
            {x + d, y + d, z + 0},
            {x + 0, y + d, z + d},
            {x + d, y + d, z + d}
        };
        for (int i = 0; i < 6; i++) {
            int in = 0;
            int out = 0;
            for (int j = 0; j < 8; j++) {
                float d =
                    planes[i][0] * points[j][0] +
                    planes[i][1] * points[j][1] +
                    planes[i][2] * points[j][2] +
                    planes[i][3];
                if (d < 0) {
                    out++;
                }
                else {
                    in++;
                }
                if (in && out) {
                    break;
                }
            }
            if (in == 0) {
                return false;
            }
        }
        return true;
    }

};
<|endoftext|>


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

#include <string>

#include <gtest/gtest.h>

#include <gmock/gmock.h>

#include <stout/check.hpp>
#include <stout/gtest.hpp>
#include <stout/uuid.hpp>

using std::string;

TEST(UUIDTest, Test)
{
  UUID uuid1 = UUID::random();
  UUID uuid2 = UUID::fromBytes(uuid1.toBytes()).get();
  UUID uuid3 = uuid2;

  EXPECT_EQ(uuid1, uuid2);
  EXPECT_EQ(uuid2, uuid3);
  EXPECT_EQ(uuid1, uuid3);

  string bytes1 = uuid1.toBytes();
  string bytes2 = uuid2.toBytes();
  string bytes3 = uuid3.toBytes();

  EXPECT_EQ(bytes1, bytes2);
  EXPECT_EQ(bytes2, bytes3);
  EXPECT_EQ(bytes1, bytes3);

  string string1 = uuid1.toString();
  string string2 = uuid2.toString();
  string string3 = uuid3.toString();

  EXPECT_EQ(string1, string2);
  EXPECT_EQ(string2, string3);
  EXPECT_EQ(string1, string3);

  EXPECT_SOME_EQ(uuid1, UUID::fromString(string1));
  EXPECT_SOME_EQ(uuid2, UUID::fromString(string2));
  EXPECT_SOME_EQ(uuid3, UUID::fromString(string3));
}

TEST(UUIDTest, MalformedUUID)
{
  EXPECT_SOME(UUID::fromBytes(UUID::random().toBytes()));
  EXPECT_ERROR(UUID::fromBytes("malformed-uuid"));
  EXPECT_ERROR(UUID::fromBytes("invalidstringmsg"));

  EXPECT_ERROR(UUID::fromString("malformed-uuid"));
}
<commit_msg>Adding fromString test in UUIDTest testcase.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License

#include <string>

#include <gtest/gtest.h>

#include <gmock/gmock.h>

#include <stout/check.hpp>
#include <stout/gtest.hpp>
#include <stout/uuid.hpp>

using std::string;

TEST(UUIDTest, Test)
{
  UUID uuid1 = UUID::random();
  UUID uuid2 = UUID::fromBytes(uuid1.toBytes()).get();
  UUID uuid3 = uuid2;

  EXPECT_EQ(uuid1, uuid2);
  EXPECT_EQ(uuid2, uuid3);
  EXPECT_EQ(uuid1, uuid3);

  string bytes1 = uuid1.toBytes();
  string bytes2 = uuid2.toBytes();
  string bytes3 = uuid3.toBytes();

  EXPECT_EQ(bytes1, bytes2);
  EXPECT_EQ(bytes2, bytes3);
  EXPECT_EQ(bytes1, bytes3);

  string string1 = uuid1.toString();
  string string2 = uuid2.toString();
  string string3 = uuid3.toString();

  EXPECT_EQ(string1, string2);
  EXPECT_EQ(string2, string3);
  EXPECT_EQ(string1, string3);

  EXPECT_SOME_EQ(uuid1, UUID::fromString(string1));
  EXPECT_SOME_EQ(uuid2, UUID::fromString(string2));
  EXPECT_SOME_EQ(uuid3, UUID::fromString(string3));
}

TEST(UUIDTest, MalformedUUID)
{
  EXPECT_SOME(UUID::fromBytes(UUID::random().toBytes()));
  EXPECT_ERROR(UUID::fromBytes("malformed-uuid"));
  EXPECT_ERROR(UUID::fromBytes("invalidstringmsg"));
  EXPECT_SOME(UUID::fromString(UUID::random().toString()));
  EXPECT_ERROR(UUID::fromString("malformed-uuid"));
}
<|endoftext|>


<commit_before>#include "GameProcess.h"
#include "Object.h"
#include "Engine.h"
#include "World.h"
using namespace MathLib;

CGameProcess::CGameProcess(void)
{

}

CGameProcess::~CGameProcess(void)
{

}
int CGameProcess::Init()
{
	g_Engine.pFileSystem->CacheFilesFormExt("char");
	g_Engine.pFileSystem->CacheFilesFormExt("node");
	g_Engine.pFileSystem->CacheFilesFormExt("smesh");
	g_Engine.pFileSystem->CacheFilesFormExt("sanim");

}<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "GameProcess.h"
#include "Object.h"
#include "Engine.h"
#include "World.h"
using namespace MathLib;

CGameProcess::CGameProcess(void)
{

}

CGameProcess::~CGameProcess(void)
{

}
int CGameProcess::Init()
{
	g_Engine.pFileSystem->CacheFilesFormExt("char");
	g_Engine.pFileSystem->CacheFilesFormExt("node");
	g_Engine.pFileSystem->CacheFilesFormExt("smesh");
	g_Engine.pFileSystem->CacheFilesFormExt("sanim");

	g_Engine.pWorld->LoadWorld("data/scene/terrain/test/test.world");
}<|endoftext|>


<commit_before>#include "StaticImageRenderer.h"
#include "CommandLineArguments.h"

#include <iostream>
#include <fstream>
#include <string>
#include <thread>
#include <chrono>
#include <atomic>

PH_CLI_NAMESPACE_BEGIN

StaticImageRenderer::StaticImageRenderer(const CommandLineArguments& args) :
	m_engineId(0),
	m_sceneFilePath(args.getSceneFilePath()),
	m_imageFilePath(args.getImageFilePath()),
	m_numRenderThreads(args.getNumRenderThreads()),
	m_isPostProcessRequested(args.isPostProcessRequested())
{
	phCreateEngine(&m_engineId, static_cast<PHuint32>(m_numRenderThreads));
}

StaticImageRenderer::~StaticImageRenderer()
{
	phDeleteEngine(m_engineId);
}

void StaticImageRenderer::render() const
{
	if(!loadCommandsFromSceneFile())
	{
		return;
	}

	phUpdate(m_engineId);

	std::thread renderThread([=]()
	{
		phRender(m_engineId);
	});

	std::atomic<bool> isRenderingCompleted = false;
	std::thread queryThread([&]()
	{
		/*PHuint32 x, y, w, h;
		int regionStatus = phAsyncPollUpdatedFilmRegion(engineId, &x, &y, &w, &h);
		if(regionStatus != PH_FILM_REGION_STATUS_INVALID)
		{
			std::cout << "xywh: " << x << ", " << y << ", " << w << ", " << h << std::endl;
		}*/

		using namespace std::chrono_literals;

		PHfloat32 currentProgress = 0, samplesPerSecond = 0;
		PHfloat32 lastProgress = 0;
		while(!isRenderingCompleted)
		{
			phAsyncGetRendererStatistics(m_engineId, &currentProgress, &samplesPerSecond);

			if((currentProgress - lastProgress) > 1.0f)
			{
				lastProgress = currentProgress;
				std::cout << "progress: " << currentProgress << " % | "
				          << "samples/sec: " << samplesPerSecond << std::endl;
			}

			std::this_thread::sleep_for(2s);
		}
	});

	renderThread.join();
	isRenderingCompleted = true;
	std::cout << "render completed" << std::endl;

	PHuint32 filmWpx, filmHpx;
	phGetFilmDimension(m_engineId, &filmWpx, &filmHpx);

	PHuint64 frameId;
	phCreateFrame(&frameId, filmWpx, filmHpx);
	if(m_isPostProcessRequested)
	{
		phDevelopFilm(m_engineId, frameId);
	}
	else
	{
		phDevelopFilmRaw(m_engineId, frameId);
	}

	std::cout << "saving image to <" << m_imageFilePath << ">" << std::endl;
	phSaveFrame(frameId, m_imageFilePath.c_str());

	phDeleteFrame(frameId);

	queryThread.join();
}

void StaticImageRenderer::setSceneFilePath(const std::string& path)
{
	m_sceneFilePath = path;
}

void StaticImageRenderer::setImageFilePath(const std::string& path)
{
	m_imageFilePath = path;
}

bool StaticImageRenderer::loadCommandsFromSceneFile() const
{
	std::ifstream sceneFile;
	sceneFile.open(m_sceneFilePath, std::ios::in);
	if(!sceneFile.is_open())
	{
		std::cerr << "warning: scene file <" << m_sceneFilePath << "> opening failed" << std::endl;
		return false;
	}
	else
	{
		std::cerr << "loading scene file <" << m_sceneFilePath << ">" << std::endl;

		std::string lineCommand;
		while(sceneFile.good())
		{
			std::getline(sceneFile, lineCommand);
			lineCommand += '\n';
			phEnterCommand(m_engineId, lineCommand.c_str());
		}
		phEnterCommand(m_engineId, "->");

		return true;
	}
}

PH_CLI_NAMESPACE_END<commit_msg>[bugfix] set engine working directory<commit_after>#include "StaticImageRenderer.h"
#include "CommandLineArguments.h"

#include <iostream>
#include <fstream>
#include <string>
#include <thread>
#include <chrono>
#include <atomic>
#include <experimental/filesystem>

PH_CLI_NAMESPACE_BEGIN

StaticImageRenderer::StaticImageRenderer(const CommandLineArguments& args) :
	m_engineId(0),
	m_sceneFilePath(args.getSceneFilePath()),
	m_imageFilePath(args.getImageFilePath()),
	m_numRenderThreads(args.getNumRenderThreads()),
	m_isPostProcessRequested(args.isPostProcessRequested())
{
	phCreateEngine(&m_engineId, static_cast<PHuint32>(m_numRenderThreads));
}

StaticImageRenderer::~StaticImageRenderer()
{
	phDeleteEngine(m_engineId);
}

void StaticImageRenderer::render() const
{
	if(!loadCommandsFromSceneFile())
	{
		return;
	}

	phUpdate(m_engineId);

	std::thread renderThread([=]()
	{
		phRender(m_engineId);
	});

	std::atomic<bool> isRenderingCompleted = false;
	std::thread queryThread([&]()
	{
		/*PHuint32 x, y, w, h;
		int regionStatus = phAsyncPollUpdatedFilmRegion(engineId, &x, &y, &w, &h);
		if(regionStatus != PH_FILM_REGION_STATUS_INVALID)
		{
			std::cout << "xywh: " << x << ", " << y << ", " << w << ", " << h << std::endl;
		}*/

		using namespace std::chrono_literals;

		PHfloat32 currentProgress = 0, samplesPerSecond = 0;
		PHfloat32 lastProgress = 0;
		while(!isRenderingCompleted)
		{
			phAsyncGetRendererStatistics(m_engineId, &currentProgress, &samplesPerSecond);

			if((currentProgress - lastProgress) > 1.0f)
			{
				lastProgress = currentProgress;
				std::cout << "progress: " << currentProgress << " % | "
				          << "samples/sec: " << samplesPerSecond << std::endl;
			}

			std::this_thread::sleep_for(2s);
		}
	});

	renderThread.join();
	isRenderingCompleted = true;
	std::cout << "render completed" << std::endl;

	PHuint32 filmWpx, filmHpx;
	phGetFilmDimension(m_engineId, &filmWpx, &filmHpx);

	PHuint64 frameId;
	phCreateFrame(&frameId, filmWpx, filmHpx);
	if(m_isPostProcessRequested)
	{
		phDevelopFilm(m_engineId, frameId);
	}
	else
	{
		phDevelopFilmRaw(m_engineId, frameId);
	}

	std::cout << "saving image to <" << m_imageFilePath << ">" << std::endl;
	phSaveFrame(frameId, m_imageFilePath.c_str());

	phDeleteFrame(frameId);

	queryThread.join();
}

void StaticImageRenderer::setSceneFilePath(const std::string& path)
{
	m_sceneFilePath = path;

	namespace fs = std::experimental::filesystem;
	const std::string sceneDirectory = fs::path(path).parent_path().string();
	phSetWorkingDirectory(m_engineId, sceneDirectory.c_str());
}

void StaticImageRenderer::setImageFilePath(const std::string& path)
{
	m_imageFilePath = path;
}

bool StaticImageRenderer::loadCommandsFromSceneFile() const
{
	std::ifstream sceneFile;
	sceneFile.open(m_sceneFilePath, std::ios::in);
	if(!sceneFile.is_open())
	{
		std::cerr << "warning: scene file <" << m_sceneFilePath << "> opening failed" << std::endl;
		return false;
	}
	else
	{
		std::cerr << "loading scene file <" << m_sceneFilePath << ">" << std::endl;

		std::string lineCommand;
		while(sceneFile.good())
		{
			std::getline(sceneFile, lineCommand);
			lineCommand += '\n';
			phEnterCommand(m_engineId, lineCommand.c_str());
		}
		phEnterCommand(m_engineId, "->");

		return true;
	}
}

PH_CLI_NAMESPACE_END<|endoftext|>


<commit_before>/*
* Copyright (C) 2012 David Edmundson <kde@davidedmundson.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "contact.h"

#include <TelepathyQt/ContactManager>
#include <TelepathyQt/Connection>
#include <TelepathyQt/ContactCapabilities>
#include <TelepathyQt/AvatarData>
#include <TelepathyQt/Utils>

#include <QBitmap>
#include <QPixmap>
#include <QPixmapCache>

#include <KIconLoader>
#include <KConfigGroup>
#include <KConfig>

#include "capabilities-hack-private.h"

KTp::Contact::Contact(Tp::ContactManager *manager, const Tp::ReferencedHandles &handle, const Tp::Features &requestedFeatures, const QVariantMap &attributes)
    : Tp::Contact(manager, handle, requestedFeatures, attributes)
{
    m_accountUniqueIdentifier = manager->connection()->property("accountUID").toString();

    connect(manager->connection().data(), SIGNAL(destroyed()), SIGNAL(invalidated()));
    connect(manager->connection().data(), SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)), SIGNAL(invalidated()));
    connect(this, SIGNAL(avatarTokenChanged(QString)), SLOT(invalidateAvatarCache()));
    connect(this, SIGNAL(avatarDataChanged(Tp::AvatarData)), SLOT(invalidateAvatarCache()));
    connect(this, SIGNAL(presenceChanged(Tp::Presence)), SLOT(onPresenceChanged(Tp::Presence)));
}

void KTp::Contact::onPresenceChanged(const Tp::Presence &presence)
{
    Q_UNUSED(presence)
    /* Temporary workaround for upstream bug https://bugs.freedesktop.org/show_bug.cgi?id=55883)
     * Close https://bugs.kde.org/show_bug.cgi?id=308217 when fixed upstream */
    Q_EMIT clientTypesChanged(clientTypes());
}

QString KTp::Contact::accountUniqueIdentifier() const
{
    return m_accountUniqueIdentifier;
}

KTp::Presence KTp::Contact::presence() const
{
    return KTp::Presence(Tp::Contact::presence());
}

bool KTp::Contact::textChatCapability() const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    return capabilities().textChats();
}

bool KTp::Contact::audioCallCapability() const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    Tp::ConnectionPtr connection = manager()->connection();
    bool contactCanStreamAudio = CapabilitiesHackPrivate::audioCalls(
                capabilities(), connection->cmName());
    bool selfCanStreamAudio = CapabilitiesHackPrivate::audioCalls(
                connection->selfContact()->capabilities(), connection->cmName());
    return contactCanStreamAudio && selfCanStreamAudio;
}

bool KTp::Contact::videoCallCapability() const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    Tp::ConnectionPtr connection = manager()->connection();
    bool contactCanStreamVideo = CapabilitiesHackPrivate::videoCalls(
                capabilities(), connection->cmName());
    bool selfCanStreamVideo = CapabilitiesHackPrivate::videoCalls(
                connection->selfContact()->capabilities(), connection->cmName());
    return contactCanStreamVideo && selfCanStreamVideo;
}

bool KTp::Contact::fileTransferCapability()  const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    bool contactCanHandleFiles = capabilities().fileTransfers();
    bool selfCanHandleFiles = manager()->connection()->selfContact()->capabilities().fileTransfers();
    return contactCanHandleFiles && selfCanHandleFiles;
}

bool KTp::Contact::collaborativeEditingCapability() const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    static const QString collab(QLatin1String("infinote"));
    bool selfCanShare = manager()->connection()->selfContact()->capabilities().streamTubes(collab);
    bool otherCanShare = capabilities().streamTubes(collab);
    return selfCanShare && otherCanShare;
}

QStringList KTp::Contact::dbusTubeServicesCapability() const
{
    if (!manager() || !manager()->connection()) {
        return QStringList();
    }

    return getCommonElements(capabilities().dbusTubeServices(),
                             manager()->connection()->selfContact()->capabilities().dbusTubeServices());
}

QStringList KTp::Contact::streamTubeServicesCapability() const
{
    if (!manager() || !manager()->connection()) {
        return QStringList();
    }

    return getCommonElements(capabilities().streamTubeServices(),
                             manager()->connection()->selfContact()->capabilities().streamTubeServices());
}

QStringList KTp::Contact::clientTypes() const
{
    /* Temporary workaround for upstream bug https://bugs.freedesktop.org/show_bug.cgi?id=55883)
     * Close https://bugs.kde.org/show_bug.cgi?id=308217 when fixed upstream */
    if (Tp::Contact::presence().type() == Tp::ConnectionPresenceTypeOffline) {
        return QStringList();
    }

    //supress any errors trying to access ClientTypes when we don't have them
    if (! actualFeatures().contains(Tp::Contact::FeatureClientTypes)) {
        return QStringList();
    }

    return Tp::Contact::clientTypes();
}

QPixmap KTp::Contact::avatarPixmap()
{
    QPixmap avatar;

    //check pixmap cache for the avatar, if not present, load the avatar
    if (!QPixmapCache::find(keyCache(), avatar)){
        QString file = avatarData().fileName;

        //if contact does not provide path, let's see if we have avatar for the stored token
        if (file.isEmpty()) {
            KConfig config(QLatin1String("ktelepathy-avatarsrc"));
            KConfigGroup avatarTokenGroup = config.group(id());
            QString avatarToken = avatarTokenGroup.readEntry(QLatin1String("avatarToken"));
            //only bother loading the pixmap if the token is not empty
            if (!avatarToken.isEmpty()) {
                avatar.load(buildAvatarPath(avatarToken));
            }
        } else {
            avatar.load(file);
        }

        //if neither above succeeded, we need to load the icon
        if (avatar.isNull()) {
            avatar = KIconLoader::global()->loadIcon(QLatin1String("im-user"), KIconLoader::NoGroup, 96);
        }

        //if the contact is offline, gray it out
        if (presence().type() == Tp::ConnectionPresenceTypeOffline) {
            avatarToGray(avatar);
        }

        //insert the contact into pixmap cache for faster lookup
        QPixmapCache::insert(keyCache(), avatar);
    }

    return avatar;
}

void KTp::Contact::avatarToGray(QPixmap &avatar)
{
    QImage image = avatar.toImage();
    QImage alpha= image.alphaChannel();
    for (int i = 0; i < image.width(); ++i) {
        for (int j = 0; j < image.height(); ++j) {
            int colour = qGray(image.pixel(i, j));
            image.setPixel(i, j, qRgb(colour, colour, colour));
        }
    }
    image.setAlphaChannel(alpha);
    avatar = QPixmap::fromImage(image);
}

QString KTp::Contact::keyCache() const
{
    return id() + (presence().type() == Tp::ConnectionPresenceTypeOffline ? QLatin1String("-offline") : QLatin1String("-online"));
}

QString KTp::Contact::buildAvatarPath(const QString &avatarToken)
{
    QString cacheDir = QString::fromLatin1(qgetenv("XDG_CACHE_HOME"));
    if (cacheDir.isEmpty()) {
        cacheDir = QString::fromLatin1("%1/.cache").arg(QLatin1String(qgetenv("HOME")));
    }

    if (manager().isNull()) {
        return QString();
    }

    if (manager()->connection().isNull()) {
        return QString();
    }

    Tp::ConnectionPtr conn = manager()->connection();
    QString path = QString::fromLatin1("%1/telepathy/avatars/%2/%3").
        arg(cacheDir).arg(conn->cmName()).arg(conn->protocolName());

    QString avatarFileName = QString::fromLatin1("%1/%2").arg(path).arg(Tp::escapeAsIdentifier(avatarToken));

    return avatarFileName;
}

void KTp::Contact::invalidateAvatarCache()
{
    QPixmapCache::remove(id() + QLatin1String("-offline"));
    QPixmapCache::remove(id() + QLatin1String("-online"));
}

QStringList KTp::Contact::getCommonElements(const QStringList &list1, const QStringList &list2)
{
    /* QStringList::contains(QString) perform iterative comparsion, so there is no reason
     * to select smaller list as base for this cycle. */
    QStringList commonElements;
    Q_FOREACH(const QString &i, list1) {
        if (list2.contains(i)) {
            commonElements << i;
        }
    }
    return commonElements;
}
<commit_msg>Return null pixmap if none can be loaded<commit_after>/*
* Copyright (C) 2012 David Edmundson <kde@davidedmundson.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "contact.h"

#include <TelepathyQt/ContactManager>
#include <TelepathyQt/Connection>
#include <TelepathyQt/ContactCapabilities>
#include <TelepathyQt/AvatarData>
#include <TelepathyQt/Utils>

#include <QBitmap>
#include <QPixmap>
#include <QPixmapCache>

#include <KIconLoader>
#include <KConfigGroup>
#include <KConfig>

#include "capabilities-hack-private.h"

KTp::Contact::Contact(Tp::ContactManager *manager, const Tp::ReferencedHandles &handle, const Tp::Features &requestedFeatures, const QVariantMap &attributes)
    : Tp::Contact(manager, handle, requestedFeatures, attributes)
{
    m_accountUniqueIdentifier = manager->connection()->property("accountUID").toString();

    connect(manager->connection().data(), SIGNAL(destroyed()), SIGNAL(invalidated()));
    connect(manager->connection().data(), SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)), SIGNAL(invalidated()));
    connect(this, SIGNAL(avatarTokenChanged(QString)), SLOT(invalidateAvatarCache()));
    connect(this, SIGNAL(avatarDataChanged(Tp::AvatarData)), SLOT(invalidateAvatarCache()));
    connect(this, SIGNAL(presenceChanged(Tp::Presence)), SLOT(onPresenceChanged(Tp::Presence)));
}

void KTp::Contact::onPresenceChanged(const Tp::Presence &presence)
{
    Q_UNUSED(presence)
    /* Temporary workaround for upstream bug https://bugs.freedesktop.org/show_bug.cgi?id=55883)
     * Close https://bugs.kde.org/show_bug.cgi?id=308217 when fixed upstream */
    Q_EMIT clientTypesChanged(clientTypes());
}

QString KTp::Contact::accountUniqueIdentifier() const
{
    return m_accountUniqueIdentifier;
}

KTp::Presence KTp::Contact::presence() const
{
    return KTp::Presence(Tp::Contact::presence());
}

bool KTp::Contact::textChatCapability() const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    return capabilities().textChats();
}

bool KTp::Contact::audioCallCapability() const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    Tp::ConnectionPtr connection = manager()->connection();
    bool contactCanStreamAudio = CapabilitiesHackPrivate::audioCalls(
                capabilities(), connection->cmName());
    bool selfCanStreamAudio = CapabilitiesHackPrivate::audioCalls(
                connection->selfContact()->capabilities(), connection->cmName());
    return contactCanStreamAudio && selfCanStreamAudio;
}

bool KTp::Contact::videoCallCapability() const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    Tp::ConnectionPtr connection = manager()->connection();
    bool contactCanStreamVideo = CapabilitiesHackPrivate::videoCalls(
                capabilities(), connection->cmName());
    bool selfCanStreamVideo = CapabilitiesHackPrivate::videoCalls(
                connection->selfContact()->capabilities(), connection->cmName());
    return contactCanStreamVideo && selfCanStreamVideo;
}

bool KTp::Contact::fileTransferCapability()  const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    bool contactCanHandleFiles = capabilities().fileTransfers();
    bool selfCanHandleFiles = manager()->connection()->selfContact()->capabilities().fileTransfers();
    return contactCanHandleFiles && selfCanHandleFiles;
}

bool KTp::Contact::collaborativeEditingCapability() const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    static const QString collab(QLatin1String("infinote"));
    bool selfCanShare = manager()->connection()->selfContact()->capabilities().streamTubes(collab);
    bool otherCanShare = capabilities().streamTubes(collab);
    return selfCanShare && otherCanShare;
}

QStringList KTp::Contact::dbusTubeServicesCapability() const
{
    if (!manager() || !manager()->connection()) {
        return QStringList();
    }

    return getCommonElements(capabilities().dbusTubeServices(),
                             manager()->connection()->selfContact()->capabilities().dbusTubeServices());
}

QStringList KTp::Contact::streamTubeServicesCapability() const
{
    if (!manager() || !manager()->connection()) {
        return QStringList();
    }

    return getCommonElements(capabilities().streamTubeServices(),
                             manager()->connection()->selfContact()->capabilities().streamTubeServices());
}

QStringList KTp::Contact::clientTypes() const
{
    /* Temporary workaround for upstream bug https://bugs.freedesktop.org/show_bug.cgi?id=55883)
     * Close https://bugs.kde.org/show_bug.cgi?id=308217 when fixed upstream */
    if (Tp::Contact::presence().type() == Tp::ConnectionPresenceTypeOffline) {
        return QStringList();
    }

    //supress any errors trying to access ClientTypes when we don't have them
    if (! actualFeatures().contains(Tp::Contact::FeatureClientTypes)) {
        return QStringList();
    }

    return Tp::Contact::clientTypes();
}

QPixmap KTp::Contact::avatarPixmap()
{
    QPixmap avatar;

    //check pixmap cache for the avatar, if not present, load the avatar
    if (!QPixmapCache::find(keyCache(), avatar)){
        QString file = avatarData().fileName;

        //if contact does not provide path, let's see if we have avatar for the stored token
        if (file.isEmpty()) {
            KConfig config(QLatin1String("ktelepathy-avatarsrc"));
            KConfigGroup avatarTokenGroup = config.group(id());
            QString avatarToken = avatarTokenGroup.readEntry(QLatin1String("avatarToken"));
            //only bother loading the pixmap if the token is not empty
            if (!avatarToken.isEmpty()) {
                avatar.load(buildAvatarPath(avatarToken));
            }
        } else {
            avatar.load(file);
        }

        //if neither above succeeded, return empty QPixmap,
        //PersonsModel will return the default icon instead
        if (avatar.isNull()) {

            return QPixmap();
        }

        //if the contact is offline, gray it out
        if (presence().type() == Tp::ConnectionPresenceTypeOffline) {
            avatarToGray(avatar);
        }

        //insert the contact into pixmap cache for faster lookup
        QPixmapCache::insert(keyCache(), avatar);
    }

    return avatar;
}

void KTp::Contact::avatarToGray(QPixmap &avatar)
{
    QImage image = avatar.toImage();
    QImage alpha= image.alphaChannel();
    for (int i = 0; i < image.width(); ++i) {
        for (int j = 0; j < image.height(); ++j) {
            int colour = qGray(image.pixel(i, j));
            image.setPixel(i, j, qRgb(colour, colour, colour));
        }
    }
    image.setAlphaChannel(alpha);
    avatar = QPixmap::fromImage(image);
}

QString KTp::Contact::keyCache() const
{
    return id() + (presence().type() == Tp::ConnectionPresenceTypeOffline ? QLatin1String("-offline") : QLatin1String("-online"));
}

QString KTp::Contact::buildAvatarPath(const QString &avatarToken)
{
    QString cacheDir = QString::fromLatin1(qgetenv("XDG_CACHE_HOME"));
    if (cacheDir.isEmpty()) {
        cacheDir = QString::fromLatin1("%1/.cache").arg(QLatin1String(qgetenv("HOME")));
    }

    if (manager().isNull()) {
        return QString();
    }

    if (manager()->connection().isNull()) {
        return QString();
    }

    Tp::ConnectionPtr conn = manager()->connection();
    QString path = QString::fromLatin1("%1/telepathy/avatars/%2/%3").
        arg(cacheDir).arg(conn->cmName()).arg(conn->protocolName());

    QString avatarFileName = QString::fromLatin1("%1/%2").arg(path).arg(Tp::escapeAsIdentifier(avatarToken));

    return avatarFileName;
}

void KTp::Contact::invalidateAvatarCache()
{
    QPixmapCache::remove(id() + QLatin1String("-offline"));
    QPixmapCache::remove(id() + QLatin1String("-online"));
}

QStringList KTp::Contact::getCommonElements(const QStringList &list1, const QStringList &list2)
{
    /* QStringList::contains(QString) perform iterative comparsion, so there is no reason
     * to select smaller list as base for this cycle. */
    QStringList commonElements;
    Q_FOREACH(const QString &i, list1) {
        if (list2.contains(i)) {
            commonElements << i;
        }
    }
    return commonElements;
}
<|endoftext|>


<commit_before>/*
 *  Debug.cpp
 *  OpenLieroX
 *
 *  Created by Albert Zeyer on 01.01.09.
 *  code under LGPL
 *
 */

#include "Debug.h"

#if (defined(__GLIBCXX__) || defined(__GLIBC__) || !defined(WIN32)) && !defined(__MINGW32_VERSION)

#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>

void DumpCallstackPrintf(void* callpnt) {
	void *callstack[128];
	int framesC = backtrace(callstack, sizeof(callstack));
	printf("backtrace() returned %d addresses\n", framesC);
	if(callpnt != NULL && framesC > 3) callstack[3] = callpnt; // expected to be called from signal handler
	char** strs = backtrace_symbols(callstack, framesC);
	for(int i = 0; i < framesC; ++i) {
		if(strs[i])
			printf("%s\n", strs[i]);
		else
			break;
	}
	free(strs);
}

void DumpCallstack(void (*PrintOutFct) (const std::string&)) {
	void *callstack[128];
	int framesC = backtrace(callstack, sizeof(callstack));
	(*PrintOutFct) ("DumpCallstack: " + itoa(framesC) + " addresses:");
	char** strs = backtrace_symbols(callstack, framesC);
	for(int i = 0; i < framesC; ++i) {
		if(strs[i])
			(*PrintOutFct) (std::string(" ") + strs[i] + "\n");
		else
			break;
	}
	free(strs);
}

#else

#include "StackWalker.h"  // Call Luke Stackwalker for help

typedef void (*PrintOutFct) (const std::string&);

// Override the default stackwalker with our own print functions
class PrintStackWalker : public StackWalker  {
private:
	PrintOutFct m_print;

public:
	PrintStackWalker(PrintOutFct fct = NULL) : StackWalker(RetrieveVerbose) { m_print = fct; }
	void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion)
	{

	}

	void OnOutput(LPCSTR szText)
	{
		if (m_print == NULL)
			printf(szText);
		else
			m_print(std::string(szText));
		StackWalker::OnOutput(szText);
	}
};

void DumpCallstackPrintf(void* callpnt)
{
	PrintStackWalker sw;
	sw.ShowCallstack();

}
void DumpCallstack(void (*LineOutFct) (const std::string&))
{
	PrintStackWalker sw(LineOutFct);
	sw.ShowCallstack();
}

#endif

Logger notes(0,2,1000, "n: ");
Logger hints(0,1,100, "H: ");
Logger warnings(0,0,10, "W: ");
Logger errors(-1,-1,1, "E: ");

#include <iostream>
#include <sstream>
#include "ThreadPool.h"
#include "Options.h"
#include "console.h"
#include "StringUtils.h"

static SDL_mutex* globalCoutMutex = NULL;

Logger::Logger(int o, int ingame, int callst, const std::string& p)
: minCoutVerb(o), minIngameConVerb(ingame), minCallstackVerb(callst), prefix(p), lastWasNewline(true), mutex(NULL) {
	mutex = SDL_CreateMutex();
	if(!globalCoutMutex)
		globalCoutMutex = SDL_CreateMutex();
}

Logger::~Logger() {
	SDL_DestroyMutex(mutex); mutex = NULL;
	if(globalCoutMutex) {
		SDL_DestroyMutex(globalCoutMutex);
		globalCoutMutex = NULL;
	}
}

void Logger::lock() {
	SDL_mutexP(mutex);
}

void Logger::unlock() {
	SDL_mutexV(mutex);
}

static void CoutPrint(const std::string& str) {
	printf("%s", str.c_str());
}

template<int col> void ConPrint(const std::string& str) {
	// TODO: Con_AddText adds a line but we only want to add str
	std::string buf = str;
	if(buf.size() > 0 && buf[buf.size()-1] == '\n') buf.erase(buf.size()-1);
	Con_AddText(col, buf, false);
}

// true if last was newline
static bool logger_output(Logger& log, const std::string& buf) {
	bool ret = true;
	if(!tLXOptions || tLXOptions->iVerbosity >= log.minCoutVerb) {
		SDL_mutexP(globalCoutMutex);
		ret = PrettyPrint(log.prefix, buf, CoutPrint, log.lastWasNewline);
		//std::cout.flush();
		SDL_mutexV(globalCoutMutex);
	}
	if(tLXOptions && tLXOptions->iVerbosity >= log.minCallstackVerb) {
		DumpCallstackPrintf();
	}
	if(tLXOptions && Con_IsInited() && tLXOptions->iVerbosity >= log.minIngameConVerb) {
		// the check is a bit hacky (see Con_AddText) but I really dont want to overcomplicate this
		if(!strStartsWith(buf, "Ingame console: ")) {
			// we are not safing explicitly a color in the Logger, thus we try to assume a good color from the verbosity level
			if(log.minIngameConVerb < 0)
				ret = PrettyPrint(log.prefix, buf, ConPrint<CNC_ERROR>, log.lastWasNewline);
			else if(log.minIngameConVerb == 0)
				ret = PrettyPrint(log.prefix, buf, ConPrint<CNC_WARNING>, log.lastWasNewline);
			else if(log.minIngameConVerb == 1)
				ret = PrettyPrint(log.prefix, buf, ConPrint<CNC_NOTIFY>, log.lastWasNewline);
			else if(log.minIngameConVerb < 5)
				ret = PrettyPrint(log.prefix, buf, ConPrint<CNC_NORMAL>, log.lastWasNewline);
			else // >=5
				ret = PrettyPrint(log.prefix, buf, ConPrint<CNC_DEV>, log.lastWasNewline);
		}
		if(tLXOptions->iVerbosity >= log.minCallstackVerb) {
			DumpCallstack(ConPrint<CNC_DEV>);
		}
	}
	return ret;
}

Logger& Logger::flush() {
	lock();
	lastWasNewline = logger_output(*this, buffer);
	buffer = "";
	unlock();
	return *this;
}
<commit_msg>comment<commit_after>/*
 *  Debug.cpp
 *  OpenLieroX
 *
 *  Created by Albert Zeyer on 01.01.09.
 *  code under LGPL
 *
 */

#include "Debug.h"

#if (defined(__GLIBCXX__) || defined(__GLIBC__) || !defined(WIN32)) && !defined(__MINGW32_VERSION)

#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>

void DumpCallstackPrintf(void* callpnt) {
	void *callstack[128];
	int framesC = backtrace(callstack, sizeof(callstack));
	printf("backtrace() returned %d addresses\n", framesC);
	if(callpnt != NULL && framesC > 3) callstack[3] = callpnt; // expected to be called from signal handler
	char** strs = backtrace_symbols(callstack, framesC);
	for(int i = 0; i < framesC; ++i) {
		if(strs[i])
			printf("%s\n", strs[i]);
		else
			break;
	}
	free(strs);
}

void DumpCallstack(void (*PrintOutFct) (const std::string&)) {
	void *callstack[128];
	int framesC = backtrace(callstack, sizeof(callstack));
	(*PrintOutFct) ("DumpCallstack: " + itoa(framesC) + " addresses:");
	char** strs = backtrace_symbols(callstack, framesC);
	for(int i = 0; i < framesC; ++i) {
		if(strs[i])
			(*PrintOutFct) (std::string(" ") + strs[i] + "\n");
		else
			break;
	}
	free(strs);
}

#else

#include "StackWalker.h"  // Call Luke Stackwalker for help

typedef void (*PrintOutFct) (const std::string&);

// Override the default stackwalker with our own print functions
class PrintStackWalker : public StackWalker  {
private:
	PrintOutFct m_print;

public:
	PrintStackWalker(PrintOutFct fct = NULL) : StackWalker(RetrieveVerbose) { m_print = fct; }
	void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion)
	{

	}

	void OnOutput(LPCSTR szText)
	{
		if (m_print == NULL)
			printf(szText);
		else
			m_print(std::string(szText));
		StackWalker::OnOutput(szText);
	}
};

void DumpCallstackPrintf(void* callpnt)
{
	PrintStackWalker sw;
	sw.ShowCallstack();

}
void DumpCallstack(void (*LineOutFct) (const std::string&))
{
	PrintStackWalker sw(LineOutFct);
	sw.ShowCallstack();
}

#endif

Logger notes(0,2,1000, "n: ");
Logger hints(0,1,100, "H: ");
Logger warnings(0,0,10, "W: ");
Logger errors(-1,-1,1, "E: ");

#include <iostream>
#include <sstream>
#include "ThreadPool.h"
#include "Options.h"
#include "console.h"
#include "StringUtils.h"

static SDL_mutex* globalCoutMutex = NULL;

Logger::Logger(int o, int ingame, int callst, const std::string& p)
: minCoutVerb(o), minIngameConVerb(ingame), minCallstackVerb(callst), prefix(p), lastWasNewline(true), mutex(NULL) {
	mutex = SDL_CreateMutex();
	if(!globalCoutMutex)
		globalCoutMutex = SDL_CreateMutex();
}

Logger::~Logger() {
	SDL_DestroyMutex(mutex); mutex = NULL;
	if(globalCoutMutex) {
		SDL_DestroyMutex(globalCoutMutex);
		globalCoutMutex = NULL;
	}
}

void Logger::lock() {
	SDL_mutexP(mutex);
}

void Logger::unlock() {
	SDL_mutexV(mutex);
}

static void CoutPrint(const std::string& str) {
	// TODO: We have used std::cout here before but it doesn't seem to work after a while for some reason.
	// TODO: c_str() is slow and not really needed here.
	printf("%s", str.c_str());
}

template<int col> void ConPrint(const std::string& str) {
	// TODO: Con_AddText adds a line but we only want to add str
	std::string buf = str;
	if(buf.size() > 0 && buf[buf.size()-1] == '\n') buf.erase(buf.size()-1);
	Con_AddText(col, buf, false);
}

// true if last was newline
static bool logger_output(Logger& log, const std::string& buf) {
	bool ret = true;
	if(!tLXOptions || tLXOptions->iVerbosity >= log.minCoutVerb) {
		SDL_mutexP(globalCoutMutex);
		ret = PrettyPrint(log.prefix, buf, CoutPrint, log.lastWasNewline);
		//std::cout.flush();
		SDL_mutexV(globalCoutMutex);
	}
	if(tLXOptions && tLXOptions->iVerbosity >= log.minCallstackVerb) {
		DumpCallstackPrintf();
	}
	if(tLXOptions && Con_IsInited() && tLXOptions->iVerbosity >= log.minIngameConVerb) {
		// the check is a bit hacky (see Con_AddText) but I really dont want to overcomplicate this
		if(!strStartsWith(buf, "Ingame console: ")) {
			// we are not safing explicitly a color in the Logger, thus we try to assume a good color from the verbosity level
			if(log.minIngameConVerb < 0)
				ret = PrettyPrint(log.prefix, buf, ConPrint<CNC_ERROR>, log.lastWasNewline);
			else if(log.minIngameConVerb == 0)
				ret = PrettyPrint(log.prefix, buf, ConPrint<CNC_WARNING>, log.lastWasNewline);
			else if(log.minIngameConVerb == 1)
				ret = PrettyPrint(log.prefix, buf, ConPrint<CNC_NOTIFY>, log.lastWasNewline);
			else if(log.minIngameConVerb < 5)
				ret = PrettyPrint(log.prefix, buf, ConPrint<CNC_NORMAL>, log.lastWasNewline);
			else // >=5
				ret = PrettyPrint(log.prefix, buf, ConPrint<CNC_DEV>, log.lastWasNewline);
		}
		if(tLXOptions->iVerbosity >= log.minCallstackVerb) {
			DumpCallstack(ConPrint<CNC_DEV>);
		}
	}
	return ret;
}

Logger& Logger::flush() {
	lock();
	lastWasNewline = logger_output(*this, buffer);
	buffer = "";
	unlock();
	return *this;
}
<|endoftext|>