<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <functional>

// template<CopyConstructible Fn, CopyConstructible... Types>
//   unspecified bind(Fn, Types...);
// template<Returnable R, CopyConstructible Fn, CopyConstructible... Types>
//   unspecified bind(Fn, Types...);

#include <stdio.h>

#include <functional>
#include <cassert>

int count = 0;

// 1 arg, return void

void f_void_1(int i)
{
    count += i;
}

struct A_void_1
{
    void operator()(int i)
    {
        count += i;
    }

    void mem1() {++count;}
    void mem2() const {count += 2;}
};

void
test_void_1()
{
    using namespace std::placeholders;
    int save_count = count;
    // function
    {
    int i = 2;
    std::bind(f_void_1, _1)(i);
    assert(count == save_count + 2);
    save_count = count;
    }
    {
    int i = 2;
    std::bind(f_void_1, i)();
    assert(count == save_count + 2);
    save_count = count;
    }
    // function pointer
    {
    void (*fp)(int) = f_void_1;
    int i = 3;
    std::bind(fp, _1)(i);
    assert(count == save_count+3);
    save_count = count;
    }
    {
    void (*fp)(int) = f_void_1;
    int i = 3;
    std::bind(fp, i)();
    assert(count == save_count+3);
    save_count = count;
    }
    // functor
    {
    A_void_1 a0;
    int i = 4;
    std::bind(a0, _1)(i);
    assert(count == save_count+4);
    save_count = count;
    }
    {
    A_void_1 a0;
    int i = 4;
    std::bind(a0, i)();
    assert(count == save_count+4);
    save_count = count;
    }
    // member function pointer
    {
    void (A_void_1::*fp)() = &A_void_1::mem1;
    A_void_1 a;
    std::bind(fp, _1)(a);
    assert(count == save_count+1);
    save_count = count;
    A_void_1* ap = &a;
    std::bind(fp, _1)(ap);
    assert(count == save_count+1);
    save_count = count;
    }
    {
    void (A_void_1::*fp)() = &A_void_1::mem1;
    A_void_1 a;
    std::bind(fp, a)();
    assert(count == save_count+1);
    save_count = count;
    A_void_1* ap = &a;
    std::bind(fp, ap)();
    assert(count == save_count+1);
    save_count = count;
    }
    // const member function pointer
    {
    void (A_void_1::*fp)() const = &A_void_1::mem2;
    A_void_1 a;
    std::bind(fp, _1)(a);
    assert(count == save_count+2);
    save_count = count;
    A_void_1* ap = &a;
    std::bind(fp, _1)(ap);
    assert(count == save_count+2);
    save_count = count;
    }
    {
    void (A_void_1::*fp)() const = &A_void_1::mem2;
    A_void_1 a;
    std::bind(fp, a)();
    assert(count == save_count+2);
    save_count = count;
    A_void_1* ap = &a;
    std::bind(fp, ap)();
    assert(count == save_count+2);
    save_count = count;
    }
}

// 1 arg, return int

int f_int_1(int i)
{
    return i + 1;
}

struct A_int_1
{
    A_int_1() : data_(5) {}
    int operator()(int i)
    {
        return i - 1;
    }

    int mem1() {return 3;}
    int mem2() const {return 4;}
    int data_;
};

void
test_int_1()
{
    using namespace std::placeholders;
    // function
    {
    int i = 2;
    assert(std::bind(f_int_1, _1)(i) == 3);
    assert(std::bind(f_int_1, i)() == 3);
    }
    // function pointer
    {
    int (*fp)(int) = f_int_1;
    int i = 3;
    assert(std::bind(fp, _1)(i) == 4);
    assert(std::bind(fp, i)() == 4);
    }
    // functor
    {
    int i = 4;
    assert(std::bind(A_int_1(), _1)(i) == 3);
    assert(std::bind(A_int_1(), i)() == 3);
    }
    // member function pointer
    {
    A_int_1 a;
    assert(std::bind(&A_int_1::mem1, _1)(a) == 3);
    assert(std::bind(&A_int_1::mem1, a)() == 3);
    A_int_1* ap = &a;
    assert(std::bind(&A_int_1::mem1, _1)(ap) == 3);
    assert(std::bind(&A_int_1::mem1, ap)() == 3);
    }
    // const member function pointer
    {
    A_int_1 a;
    assert(std::bind(&A_int_1::mem2, _1)(A_int_1()) == 4);
    assert(std::bind(&A_int_1::mem2, A_int_1())() == 4);
    A_int_1* ap = &a;
    assert(std::bind(&A_int_1::mem2, _1)(ap) == 4);
    assert(std::bind(&A_int_1::mem2, ap)() == 4);
    }
    // member data pointer
    {
    A_int_1 a;
    assert(std::bind(&A_int_1::data_, _1)(a) == 5);
    assert(std::bind(&A_int_1::data_, a)() == 5);
    A_int_1* ap = &a;
    assert(std::bind(&A_int_1::data_, _1)(a) == 5);
    std::bind(&A_int_1::data_, _1)(a) = 6;
    assert(std::bind(&A_int_1::data_, _1)(a) == 6);
    assert(std::bind(&A_int_1::data_, _1)(ap) == 6);
    std::bind(&A_int_1::data_, _1)(ap) = 7;
    assert(std::bind(&A_int_1::data_, _1)(ap) == 7);
    }
}

// 2 arg, return void

void f_void_2(int i, int j)
{
    count += i+j;
}

struct A_void_2
{
    void operator()(int i, int j)
    {
        count += i+j;
    }

    void mem1(int i) {count += i;}
    void mem2(int i) const {count += i;}
};

void
test_void_2()
{
    using namespace std::placeholders;
    int save_count = count;
    // function
    {
    int i = 2;
    int j = 3;
    std::bind(f_void_2, _1, _2)(i, j);
    assert(count == save_count+5);
    save_count = count;
    std::bind(f_void_2, i, _1)(j);
    assert(count == save_count+5);
    save_count = count;
    std::bind(f_void_2, i, j)();
    assert(count == save_count+5);
    save_count = count;
    }
    // member function pointer
    {
    int j = 3;
    std::bind(&A_void_2::mem1, _1, _2)(A_void_2(), j);
    assert(count == save_count+3);
    save_count = count;
    std::bind(&A_void_2::mem1, _2, _1)(j, A_void_2());
    assert(count == save_count+3);
    save_count = count;
    }
}

int main()
{
    test_void_1();
    test_int_1();
    test_void_2();
}
<commit_msg>Remove cv qualifiers from member pointers in the __member_pointer_traits test.  This was causing a const-qualified bind result to malfunction.  This was a recent regression due to the new use of __member_pointer_traits in restricting the __invokable and __invoke_of tests.<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <functional>

// template<CopyConstructible Fn, CopyConstructible... Types>
//   unspecified bind(Fn, Types...);
// template<Returnable R, CopyConstructible Fn, CopyConstructible... Types>
//   unspecified bind(Fn, Types...);

#include <stdio.h>

#include <functional>
#include <cassert>

int count = 0;

// 1 arg, return void

void f_void_1(int i)
{
    count += i;
}

struct A_void_1
{
    void operator()(int i)
    {
        count += i;
    }

    void mem1() {++count;}
    void mem2() const {count += 2;}
};

void
test_void_1()
{
    using namespace std::placeholders;
    int save_count = count;
    // function
    {
    int i = 2;
    std::bind(f_void_1, _1)(i);
    assert(count == save_count + 2);
    save_count = count;
    }
    {
    int i = 2;
    std::bind(f_void_1, i)();
    assert(count == save_count + 2);
    save_count = count;
    }
    // function pointer
    {
    void (*fp)(int) = f_void_1;
    int i = 3;
    std::bind(fp, _1)(i);
    assert(count == save_count+3);
    save_count = count;
    }
    {
    void (*fp)(int) = f_void_1;
    int i = 3;
    std::bind(fp, i)();
    assert(count == save_count+3);
    save_count = count;
    }
    // functor
    {
    A_void_1 a0;
    int i = 4;
    std::bind(a0, _1)(i);
    assert(count == save_count+4);
    save_count = count;
    }
    {
    A_void_1 a0;
    int i = 4;
    std::bind(a0, i)();
    assert(count == save_count+4);
    save_count = count;
    }
    // member function pointer
    {
    void (A_void_1::*fp)() = &A_void_1::mem1;
    A_void_1 a;
    std::bind(fp, _1)(a);
    assert(count == save_count+1);
    save_count = count;
    A_void_1* ap = &a;
    std::bind(fp, _1)(ap);
    assert(count == save_count+1);
    save_count = count;
    }
    {
    void (A_void_1::*fp)() = &A_void_1::mem1;
    A_void_1 a;
    std::bind(fp, a)();
    assert(count == save_count+1);
    save_count = count;
    A_void_1* ap = &a;
    std::bind(fp, ap)();
    assert(count == save_count+1);
    save_count = count;
    }
    // const member function pointer
    {
    void (A_void_1::*fp)() const = &A_void_1::mem2;
    A_void_1 a;
    std::bind(fp, _1)(a);
    assert(count == save_count+2);
    save_count = count;
    A_void_1* ap = &a;
    std::bind(fp, _1)(ap);
    assert(count == save_count+2);
    save_count = count;
    }
    {
    void (A_void_1::*fp)() const = &A_void_1::mem2;
    A_void_1 a;
    std::bind(fp, a)();
    assert(count == save_count+2);
    save_count = count;
    A_void_1* ap = &a;
    std::bind(fp, ap)();
    assert(count == save_count+2);
    save_count = count;
    }
}

// 1 arg, return int

int f_int_1(int i)
{
    return i + 1;
}

struct A_int_1
{
    A_int_1() : data_(5) {}
    int operator()(int i)
    {
        return i - 1;
    }

    int mem1() {return 3;}
    int mem2() const {return 4;}
    int data_;
};

void
test_int_1()
{
    using namespace std::placeholders;
    // function
    {
    int i = 2;
    assert(std::bind(f_int_1, _1)(i) == 3);
    assert(std::bind(f_int_1, i)() == 3);
    }
    // function pointer
    {
    int (*fp)(int) = f_int_1;
    int i = 3;
    assert(std::bind(fp, _1)(i) == 4);
    assert(std::bind(fp, i)() == 4);
    }
    // functor
    {
    int i = 4;
    assert(std::bind(A_int_1(), _1)(i) == 3);
    assert(std::bind(A_int_1(), i)() == 3);
    }
    // member function pointer
    {
    A_int_1 a;
    assert(std::bind(&A_int_1::mem1, _1)(a) == 3);
    assert(std::bind(&A_int_1::mem1, a)() == 3);
    A_int_1* ap = &a;
    assert(std::bind(&A_int_1::mem1, _1)(ap) == 3);
    assert(std::bind(&A_int_1::mem1, ap)() == 3);
    }
    // const member function pointer
    {
    A_int_1 a;
    assert(std::bind(&A_int_1::mem2, _1)(A_int_1()) == 4);
    assert(std::bind(&A_int_1::mem2, A_int_1())() == 4);
    A_int_1* ap = &a;
    assert(std::bind(&A_int_1::mem2, _1)(ap) == 4);
    assert(std::bind(&A_int_1::mem2, ap)() == 4);
    }
    // member data pointer
    {
    A_int_1 a;
    assert(std::bind(&A_int_1::data_, _1)(a) == 5);
    assert(std::bind(&A_int_1::data_, a)() == 5);
    A_int_1* ap = &a;
    assert(std::bind(&A_int_1::data_, _1)(a) == 5);
    std::bind(&A_int_1::data_, _1)(a) = 6;
    assert(std::bind(&A_int_1::data_, _1)(a) == 6);
    assert(std::bind(&A_int_1::data_, _1)(ap) == 6);
    std::bind(&A_int_1::data_, _1)(ap) = 7;
    assert(std::bind(&A_int_1::data_, _1)(ap) == 7);
    }
}

// 2 arg, return void

void f_void_2(int i, int j)
{
    count += i+j;
}

struct A_void_2
{
    void operator()(int i, int j)
    {
        count += i+j;
    }

    void mem1(int i) {count += i;}
    void mem2(int i) const {count += i;}
};

void
test_void_2()
{
    using namespace std::placeholders;
    int save_count = count;
    // function
    {
    int i = 2;
    int j = 3;
    std::bind(f_void_2, _1, _2)(i, j);
    assert(count == save_count+5);
    save_count = count;
    std::bind(f_void_2, i, _1)(j);
    assert(count == save_count+5);
    save_count = count;
    std::bind(f_void_2, i, j)();
    assert(count == save_count+5);
    save_count = count;
    }
    // member function pointer
    {
    int j = 3;
    std::bind(&A_void_2::mem1, _1, _2)(A_void_2(), j);
    assert(count == save_count+3);
    save_count = count;
    std::bind(&A_void_2::mem1, _2, _1)(j, A_void_2());
    assert(count == save_count+3);
    save_count = count;
    }
}

struct TFENode
{
    bool foo(unsigned long long) const
    {
        return true;
    }
};

void
test3()
{
    using namespace std;
    using namespace std::placeholders;
    const auto f = bind(&TFENode::foo, _1, 0UL);
    const TFENode n = TFENode{};
    bool b = f(n);
}

int main()
{
    test_void_1();
    test_int_1();
    test_void_2();
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file wr_vref_workarounds.C
/// @brief Workarounds for the WR VREF calibration logic
/// Workarounds are very deivce specific, so there is no attempt to generalize
/// this code in any way.
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <lib/workarounds/dp16_workarounds.H>
#include <lib/workarounds/wr_vref_workarounds.H>

namespace mss
{

namespace workarounds
{

namespace wr_vref
{

///
/// @brief Executes WR VREF workarounds
/// @param[in] i_target the fapi2 target of the port
/// @param[in] i_rp - the rank pair to execute the override on
/// @param[in] i_cal_steps_enabled - cal steps to exectue, used to see if WR VREF needs to be exectued
/// @param[out] o_vrefdq_train_range - training range value
/// @param[out] o_vrefdq_train_value - training value value
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
fapi2::ReturnCode execute( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
                           const uint64_t i_rp,
                           const fapi2::buffer<uint32_t>& i_cal_steps_enabled,
                           uint8_t& o_vrefdq_train_range,
                           uint8_t& o_vrefdq_train_value )
{
    // Skip running WR VREF workarounds if:
    // 1) the chip does not need to have the workaround run
    // 2) WR VREF has not been requested in the calibration steps
    if ((! mss::chip_ec_feature_mss_wr_vref(i_target)) || (!i_cal_steps_enabled.getBit<WRITE_CTR_2D_VREF>()))
    {
        return fapi2::FAPI2_RC_SUCCESS;
    }

    FAPI_TRY(mss::workarounds::dp16::wr_vref::error_dram23(i_target));
    FAPI_TRY(mss::workarounds::dp16::wr_vref::setup_values(i_target, i_rp, o_vrefdq_train_range, o_vrefdq_train_value));

fapi_try_exit:
    return fapi2::current_err;
}

} // close namespace wr_vref
} // close namespace workarounds
} // close namespace mss
<commit_msg>Update HPW Level for MSS API library<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file wr_vref_workarounds.C
/// @brief Workarounds for the WR VREF calibration logic
/// Workarounds are very deivce specific, so there is no attempt to generalize
/// this code in any way.
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <lib/workarounds/dp16_workarounds.H>
#include <lib/workarounds/wr_vref_workarounds.H>

namespace mss
{

namespace workarounds
{

namespace wr_vref
{

///
/// @brief Executes WR VREF workarounds
/// @param[in] i_target the fapi2 target of the port
/// @param[in] i_rp - the rank pair to execute the override on
/// @param[in] i_cal_steps_enabled - cal steps to exectue, used to see if WR VREF needs to be exectued
/// @param[out] o_vrefdq_train_range - training range value
/// @param[out] o_vrefdq_train_value - training value value
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
fapi2::ReturnCode execute( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
                           const uint64_t i_rp,
                           const fapi2::buffer<uint32_t>& i_cal_steps_enabled,
                           uint8_t& o_vrefdq_train_range,
                           uint8_t& o_vrefdq_train_value )
{
    // Skip running WR VREF workarounds if:
    // 1) the chip does not need to have the workaround run
    // 2) WR VREF has not been requested in the calibration steps
    if ((! mss::chip_ec_feature_mss_wr_vref(i_target)) || (!i_cal_steps_enabled.getBit<WRITE_CTR_2D_VREF>()))
    {
        return fapi2::FAPI2_RC_SUCCESS;
    }

    FAPI_TRY(mss::workarounds::dp16::wr_vref::error_dram23(i_target));
    FAPI_TRY(mss::workarounds::dp16::wr_vref::setup_values(i_target, i_rp, o_vrefdq_train_range, o_vrefdq_train_value));

fapi_try_exit:
    return fapi2::current_err;
}

} // close namespace wr_vref
} // close namespace workarounds
} // close namespace mss
<|endoftext|>


<commit_before>/**
 *  machina
 *
 *  Copyright (c) 2014, drmats
 *  All rights reserved.
 *
 *  https://github.com/drmats/machina
 */

#ifndef __SHADER_CPP_
#define __SHADER_CPP_ 1

#include "shader.hpp"

namespace machina {

/**
 *  Shader source helper macro.
 */
#define GLSL(version, src) "#version " #version "\n" #src

/**
 *  OpenGL messages buffer.
 */
GLchar Shader::message_buffer[GL_INFO_LOG_LENGTH] = { 0 };

/**
 *  Some shader sources.
 */
// basic vertex shader -- care about vertex position
const std::string Shader::vs_basic = GLSL(130,
    uniform mat4 mvp_matrix;
    in vec4 vertex_position;
    void main (void) {
        gl_Position = mvp_matrix * vertex_position;
    }
);

// basic fragment shader -- care about fragment color (from uniform)
const std::string Shader::fs_basic_color_uniform = GLSL(130,
    uniform vec4 uniform_color;
    out vec4 fragment_color;
    void main (void) {
        fragment_color = uniform_color;
    }
);

// basic vertex shader -- care about vertex position and color
const std::string Shader::vs_basic_attribute_color = GLSL(130,
    uniform mat4 mvp_matrix;
    in vec4 vertex_position;
    in vec4 vertex_color;
    smooth out vec4 vertex_fragment_color;
    void main (void) {
        vertex_fragment_color = vertex_color;
        gl_Position = mvp_matrix * vertex_position;
    }
);

// basic fragment shader -- care about fragment color (from vs)
const std::string Shader::fs_basic_color_in = GLSL(130,
    smooth in vec4 vertex_fragment_color;
    out vec4 fragment_color;
    void main (void) {
        fragment_color = vertex_fragment_color;
    }
);

/**
 *  Initialization with attribute binding.
 *  Example invocation:
 *      Shader some_shader(
 *          shader::vs_basic,
 *          shader::fs_basic, {
 *              std::make_tuple(
 *                  "vertex_position", Shader::attrib_index::vertex
 *              )
 *      });
 */
Shader::Shader (
    const std::string &vs, const std::string &fs,
    const std::initializer_list<
        std::tuple<std::string, Shader::attrib_index>
    > binding
) throw (std::runtime_error) {
    // temporary shader objects (load and compile from sources)
    GLuint
        vertex_shader = this->load_shader(GL_VERTEX_SHADER, vs),
        fragment_shader = this->load_shader(GL_FRAGMENT_SHADER, fs);

    // status variable (for testing errors)
    GLint status;

    // binding iterator
    std::initializer_list<
        std::tuple<std::string, Shader::attrib_index>
    >::iterator it;

    // attach shaders to gl program
    this->program = glCreateProgram();
    glAttachShader(this->program, vertex_shader);
    glAttachShader(this->program, fragment_shader);

    // bind attributes to the gl program
    for (it = binding.begin();  it != binding.end();  it++) {
        glBindAttribLocation(
            this->program,
            std::get<1>(*it),
            std::get<0>(*it).data()
        );
    }

    // link gl program
    glLinkProgram(this->program);

    // temporary shaders are no longer needed
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);

    // check for link errors
    glGetProgramiv(this->program, GL_LINK_STATUS, &status);
    if (status == GL_FALSE) {
        std::string error_message(this->get_program_info_log(this->program));
        glDeleteProgram(this->program);
        throw std::runtime_error(error_message);
    }
}

/**
 *  Clean-up.
 */
Shader::~Shader () {
    if (this->program != 0) {
        glDeleteProgram(this->program);
        this->program = 0;
    }
}

/**
 *  Assign uniforms and use shader.
 *  Example invocation:
 *      some_shader.use({
 *          std::make_tuple("mvp_matrix", [&] (GLuint location) {
 *              glUniformMatrix4fv(location, 1, GL_FALSE, *mvp_matrix);
 *          })
 *      });
 */
const Shader& Shader::use (
    std::initializer_list<
        std::tuple<std::string, std::function<void (GLint)>>
    > uniforms
) const {
    std::initializer_list<
        std::tuple<std::string, std::function<void (GLint)>>
    >::iterator it;

    glUseProgram(this->program);

    for (it = uniforms.begin();  it != uniforms.end();  it++) {
        std::get<1>(*it)(
            glGetUniformLocation(this->program, std::get<0>(*it).data())
        );
    }

    return *this;
}

/**
 *  Compile shader from a given source.
 */
GLuint Shader::load_shader (
    GLenum shader_type,
    const std::string &shader_src
) throw (std::runtime_error) {
    GLuint shader = glCreateShader(shader_type);
    const GLchar *src = (GLchar*)shader_src.data();
    GLint status;

    glShaderSource(shader, 1, &src, NULL);
    glCompileShader(shader);
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE) {
        std::string error_message(this->get_shader_info_log(shader));
        glDeleteShader(shader);
        throw std::runtime_error(error_message);
    }

    return shader;
}

/**
 *  Get shader compilation log message.
 */
std::string Shader::get_shader_info_log (GLuint shader) {
    glGetShaderInfoLog(
        shader, GL_INFO_LOG_LENGTH, NULL, Shader::message_buffer
    );
    return "GLSL shader: " + std::string(Shader::message_buffer);
}

/**
 *  Get program linking log.
 */
std::string Shader::get_program_info_log (GLuint program) {
    glGetProgramInfoLog(
        program, GL_INFO_LOG_LENGTH, NULL, Shader::message_buffer
    );
    return "GLSL program: " + std::string(Shader::message_buffer);
}

} // namespace machina

#endif
<commit_msg>Shader::use -- missing cast added.<commit_after>/**
 *  machina
 *
 *  Copyright (c) 2014, drmats
 *  All rights reserved.
 *
 *  https://github.com/drmats/machina
 */

#ifndef __SHADER_CPP_
#define __SHADER_CPP_ 1

#include "shader.hpp"

namespace machina {

/**
 *  Shader source helper macro.
 */
#define GLSL(version, src) "#version " #version "\n" #src

/**
 *  OpenGL messages buffer.
 */
GLchar Shader::message_buffer[GL_INFO_LOG_LENGTH] = { 0 };

/**
 *  Some shader sources.
 */
// basic vertex shader -- care about vertex position
const std::string Shader::vs_basic = GLSL(130,
    uniform mat4 mvp_matrix;
    in vec4 vertex_position;
    void main (void) {
        gl_Position = mvp_matrix * vertex_position;
    }
);

// basic fragment shader -- care about fragment color (from uniform)
const std::string Shader::fs_basic_color_uniform = GLSL(130,
    uniform vec4 uniform_color;
    out vec4 fragment_color;
    void main (void) {
        fragment_color = uniform_color;
    }
);

// basic vertex shader -- care about vertex position and color
const std::string Shader::vs_basic_attribute_color = GLSL(130,
    uniform mat4 mvp_matrix;
    in vec4 vertex_position;
    in vec4 vertex_color;
    smooth out vec4 vertex_fragment_color;
    void main (void) {
        vertex_fragment_color = vertex_color;
        gl_Position = mvp_matrix * vertex_position;
    }
);

// basic fragment shader -- care about fragment color (from vs)
const std::string Shader::fs_basic_color_in = GLSL(130,
    smooth in vec4 vertex_fragment_color;
    out vec4 fragment_color;
    void main (void) {
        fragment_color = vertex_fragment_color;
    }
);

/**
 *  Initialization with attribute binding.
 *  Example invocation:
 *      Shader some_shader(
 *          shader::vs_basic,
 *          shader::fs_basic, {
 *              std::make_tuple(
 *                  "vertex_position", Shader::attrib_index::vertex
 *              )
 *      });
 */
Shader::Shader (
    const std::string &vs, const std::string &fs,
    const std::initializer_list<
        std::tuple<std::string, Shader::attrib_index>
    > binding
) throw (std::runtime_error) {
    // temporary shader objects (load and compile from sources)
    GLuint
        vertex_shader = this->load_shader(GL_VERTEX_SHADER, vs),
        fragment_shader = this->load_shader(GL_FRAGMENT_SHADER, fs);

    // status variable (for testing errors)
    GLint status;

    // binding iterator
    std::initializer_list<
        std::tuple<std::string, Shader::attrib_index>
    >::iterator it;

    // attach shaders to gl program
    this->program = glCreateProgram();
    glAttachShader(this->program, vertex_shader);
    glAttachShader(this->program, fragment_shader);

    // bind attributes to the gl program
    for (it = binding.begin();  it != binding.end();  it++) {
        glBindAttribLocation(
            this->program,
            std::get<1>(*it),
            std::get<0>(*it).data()
        );
    }

    // link gl program
    glLinkProgram(this->program);

    // temporary shaders are no longer needed
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);

    // check for link errors
    glGetProgramiv(this->program, GL_LINK_STATUS, &status);
    if (status == GL_FALSE) {
        std::string error_message(this->get_program_info_log(this->program));
        glDeleteProgram(this->program);
        throw std::runtime_error(error_message);
    }
}

/**
 *  Clean-up.
 */
Shader::~Shader () {
    if (this->program != 0) {
        glDeleteProgram(this->program);
        this->program = 0;
    }
}

/**
 *  Assign uniforms and use shader.
 *  Example invocation:
 *      some_shader.use({
 *          std::make_tuple("mvp_matrix", [&] (GLuint location) {
 *              glUniformMatrix4fv(location, 1, GL_FALSE, *mvp_matrix);
 *          })
 *      });
 */
const Shader& Shader::use (
    std::initializer_list<
        std::tuple<std::string, std::function<void (GLint)>>
    > uniforms
) const {
    std::initializer_list<
        std::tuple<std::string, std::function<void (GLint)>>
    >::iterator it;

    glUseProgram(this->program);

    for (it = uniforms.begin();  it != uniforms.end();  it++) {
        std::get<1>(*it)(
            glGetUniformLocation(
                this->program, (GLchar*)std::get<0>(*it).data()
            )
        );
    }

    return *this;
}

/**
 *  Compile shader from a given source.
 */
GLuint Shader::load_shader (
    GLenum shader_type,
    const std::string &shader_src
) throw (std::runtime_error) {
    GLuint shader = glCreateShader(shader_type);
    const GLchar *src = (GLchar*)shader_src.data();
    GLint status;

    glShaderSource(shader, 1, &src, NULL);
    glCompileShader(shader);
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE) {
        std::string error_message(this->get_shader_info_log(shader));
        glDeleteShader(shader);
        throw std::runtime_error(error_message);
    }

    return shader;
}

/**
 *  Get shader compilation log message.
 */
std::string Shader::get_shader_info_log (GLuint shader) {
    glGetShaderInfoLog(
        shader, GL_INFO_LOG_LENGTH, NULL, Shader::message_buffer
    );
    return "GLSL shader: " + std::string(Shader::message_buffer);
}

/**
 *  Get program linking log.
 */
std::string Shader::get_program_info_log (GLuint program) {
    glGetProgramInfoLog(
        program, GL_INFO_LOG_LENGTH, NULL, Shader::message_buffer
    );
    return "GLSL program: " + std::string(Shader::message_buffer);
}

} // namespace machina

#endif
<|endoftext|>


<commit_before>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2006 Artem Pavlenko
 *
 * Mapnik 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 any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//$Id$

// stl
#include <iostream>

// qt
#include <QtGui>
#include <QSplitter>
#include <QTreeView>
#include <QListView>
#include <QTabWidget>
#include <QList>
#include <QItemDelegate>
#include <QSlider>

// mapnik
#include <mapnik/config_error.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/save_map.hpp>

// qt
#include "mainwindow.hpp"
#include "layerlistmodel.hpp"
#include "styles_model.hpp"
#include "layerwidget.hpp"
#include "layerdelegate.hpp"
#include "about_dialog.hpp"

MainWindow::MainWindow()
    : filename_(),
      default_extent_(-20037508.3428,-20037508.3428,20037508.3428,20037508.3428)
{
    mapWidget_ = new MapWidget(this);
    QSplitter *splitter = new QSplitter(this);
    QTabWidget *tabWidget=new QTabWidget;
    layerTab_ = new LayerTab;
    layerTab_->setFocusPolicy(Qt::NoFocus);
    layerTab_->setIconSize(QSize(16,16));

    //LayerDelegate *delegate = new LayerDelegate(this);
    //layerTab_->setItemDelegate(delegate);
    //layerTab_->setItemDelegate(new QItemDelegate(this));
    //layerTab_->setViewMode(QListView::IconMode);

    layerTab_->setFlow(QListView::TopToBottom);
    tabWidget->addTab(layerTab_,tr("Layers"));

    // Styles tab
    styleTab_ = new StyleTab;
    tabWidget->addTab(styleTab_,tr("Styles"));
    splitter->addWidget(tabWidget);
    splitter->addWidget(mapWidget_);
    QList<int> list;
    list.push_back(200);
    list.push_back(600);
    splitter->setSizes(list);

    mapWidget_->setFocusPolicy(Qt::StrongFocus);
    mapWidget_->setFocus();

    //setCentralWidget(mapWidget_);
    setCentralWidget(splitter);
    createActions();
    createMenus();
    createToolBars();
    createContextMenu();

    setWindowTitle(tr("Mapnik Viewer"));
    status=new QStatusBar(this);
    status->showMessage(tr(""));
    setStatusBar(status);
    resize(800,600);

    //connect mapview to layerlist
    connect(mapWidget_, SIGNAL(mapViewChanged()),layerTab_, SLOT(update()));
    // slider
    connect(slider_,SIGNAL(valueChanged(int)),mapWidget_,SLOT(zoomToLevel(int)));
    //
    connect(layerTab_,SIGNAL(update_mapwidget()),mapWidget_,SLOT(updateMap()));
    connect(layerTab_,SIGNAL(layerSelected(int)),
            mapWidget_,SLOT(layerSelected(int)));
}

MainWindow::~MainWindow()
{
    delete mapWidget_;
}

void MainWindow::closeEvent(QCloseEvent* event)
{
    event->accept();
}

void MainWindow::createContextMenu()
{
    layerTab_->setContextMenuPolicy(Qt::ActionsContextMenu);
    layerTab_->addAction(openAct);
    layerTab_->addAction(layerInfo);
}

void MainWindow::open(QString const& path)
{
    if (path.isNull())
    {
        filename_ = QFileDialog::getOpenFileName(this,tr("Open Mapnik file"),
                                                 currentPath,"*.xml");
    }
    else
    {
        filename_ = path;
    }

    if (!filename_.isEmpty())
    {
        load_map_file(filename_);
        setWindowTitle(tr("%1 - Mapnik Viewer").arg(filename_));
    }

}

void MainWindow::reload()
{
    if (!filename_.isEmpty())
    {

        mapnik::box2d<double> bbox = mapWidget_->getMap()->getCurrentExtent();
        load_map_file(filename_);
        mapWidget_->zoomToBox(bbox);
        setWindowTitle(tr("%1 - *Reloaded*").arg(filename_));
    }
}

void MainWindow::save()
{
    QString initialPath = QDir::currentPath() + "/untitled.xml";
    QString filename = QFileDialog::getSaveFileName(this, tr("Save"),
                                                    initialPath,
                                                    tr("%1 Files (*.xml)")
                                                    .arg(QString("Mapnik definition")));
    if (!filename.isEmpty())
    {
        std::cout<<"saving "<< filename.toStdString() << std::endl;
        mapnik::save_map(*mapWidget_->getMap(),filename.toStdString());
    }
}

void MainWindow::load_map_file(QString const& filename)
{
    std::cout<<"loading "<< filename.toStdString() << std::endl;
    unsigned width = mapWidget_->width();
    unsigned height = mapWidget_->height();
    boost::shared_ptr<mapnik::Map> map(new mapnik::Map(width,height));
    mapWidget_->setMap(map);
    try
    {
        mapnik::load_map(*map,filename.toStdString());
    }
    catch (mapnik::config_error & ex)
    {
        std::cout << ex.what() << "\n";
    }
    layerTab_->setModel(new LayerListModel(map,this));
    styleTab_->setModel(new StyleModel(map,this));
}

void MainWindow::zoom_to_box()
{
    mapWidget_->setTool(MapWidget::ZoomToBox);
}

void MainWindow::pan()
{
    mapWidget_->setTool(MapWidget::Pan);
}

void MainWindow::info()
{
    mapWidget_->setTool(MapWidget::Info);
}

void MainWindow::pan_left()
{
    mapWidget_->panLeft();
}

void MainWindow::pan_right()
{
    mapWidget_->panRight();
}

void MainWindow::pan_up()
{
    mapWidget_->panUp();
}

void MainWindow::pan_down()
{
    mapWidget_->panDown();
}

void MainWindow::about()
{
    about_dialog dlg;
    dlg.exec();
}

void MainWindow::export_as()
{
    QAction *action = qobject_cast<QAction *>(sender());
    QByteArray fileFormat = action->data().toByteArray();
    QString initialPath = QDir::currentPath() + "/map." + fileFormat;

    QString fileName = QFileDialog::getSaveFileName(this, tr("Export As"),
                                                    initialPath,
                                                    tr("%1 Files (*.%2);;All Files (*)")
                                                    .arg(QString(fileFormat.toUpper()))
                                                    .arg(QString(fileFormat)));
    if (!fileName.isEmpty())
    {
        QPixmap const& pix = mapWidget_->pixmap();
        pix.save(fileName);
    }
}

void MainWindow::print()
{

    //Q_ASSERT(mapWidget_->pixmap());
    //QPrintDialog dialog(&printer, this);
    //if (dialog.exec()) {
    //   QPainter painter(&printer);
    //   QRect rect = painter.viewport();
    //   QSize size = mapWidget_->pixmap()->size();
    //   size.scale(rect.size(), Qt::KeepAspectRatio);
    //   painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
    //   painter.setWindow(mapWidget_->pixmap()->rect());
    //   painter.drawPixmap(0, 0, *mapWidget_->pixmap());
    //}
}

void MainWindow::createActions()
{
    //exportAct = new QAction(tr("&Export as ..."),this);
    //exportAct->setShortcut(tr("Ctrl+E"));
    //connect(exportAct, SIGNAL(triggered()), this, SLOT(export_as()));
    zoomAllAct = new QAction(QIcon(":/images/home.png"),tr("Zoom All"),this);
    connect(zoomAllAct, SIGNAL(triggered()), this, SLOT(zoom_all()));

    zoomBoxAct = new QAction(QIcon(":/images/zoombox.png"),tr("Zoom To Box"),this);
    zoomBoxAct->setCheckable(true);
    connect(zoomBoxAct, SIGNAL(triggered()), this, SLOT(zoom_to_box()));

    panAct = new QAction(QIcon(":/images/pan.png"),tr("Pan"),this);
    panAct->setCheckable(true);
    connect(panAct, SIGNAL(triggered()), this, SLOT(pan()));

    infoAct = new QAction(QIcon(":/images/info.png"),tr("Info"),this);
    infoAct->setCheckable(true);
    connect(infoAct, SIGNAL(triggered()), this, SLOT(info()));

    toolsGroup=new QActionGroup(this);
    toolsGroup->addAction(zoomBoxAct);
    toolsGroup->addAction(panAct);
    toolsGroup->addAction(infoAct);
    zoomBoxAct->setChecked(true);

    openAct=new QAction(tr("Open Map definition"),this);
    connect(openAct,SIGNAL(triggered()),this,SLOT(open()));
    saveAct=new QAction(tr("Save Map definition"),this);
    connect(saveAct,SIGNAL(triggered()),this,SLOT(save()));

    panLeftAct = new QAction(QIcon(":/images/left.png"),tr("&Pan Left"),this);
    connect(panLeftAct, SIGNAL(triggered()), this, SLOT(pan_left()));
    panRightAct = new QAction(QIcon(":/images/right.png"),tr("&Pan Right"),this);
    connect(panRightAct, SIGNAL(triggered()), this, SLOT(pan_right()));
    panUpAct = new QAction(QIcon(":/images/up.png"),tr("&Pan Up"),this);
    connect(panUpAct, SIGNAL(triggered()), this, SLOT(pan_up()));
    panDownAct = new QAction(QIcon(":/images/down.png"),tr("&Pan Down"),this);
    connect(panDownAct, SIGNAL(triggered()), this, SLOT(pan_down()));

    reloadAct = new QAction(QIcon(":/images/reload.png"),tr("Reload"),this);
    connect(reloadAct, SIGNAL(triggered()), this, SLOT(reload()));

    layerInfo = new QAction(QIcon(":/images/info.png"),tr("&Layer info"),layerTab_);
    connect(layerInfo, SIGNAL(triggered()), layerTab_,SLOT(layerInfo()));
    connect(layerTab_, SIGNAL(doubleClicked(QModelIndex const&)), layerTab_,SLOT(layerInfo2(QModelIndex const&)));
    foreach (QByteArray format, QImageWriter::supportedImageFormats())
    {
        QString text = tr("%1...").arg(QString(format).toUpper());

        QAction *action = new QAction(text, this);
        action->setData(format);
        connect(action, SIGNAL(triggered()), this, SLOT(export_as()));
        exportAsActs.append(action);
    }

    printAct = new QAction(QIcon(":/images/print.png"),tr("&Print ..."),this);
    printAct->setShortcut(tr("Ctrl+E"));
    connect(printAct, SIGNAL(triggered()), this, SLOT(print()));

    exitAct = new QAction(tr("E&xit"), this);
    exitAct->setShortcut(tr("Ctrl+Q"));
    connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));

    aboutAct = new QAction(QIcon(":/images/about.png"),tr("&About"), this);
    connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
}

void MainWindow::createMenus()
{
    exportMenu = new QMenu(tr("&Export As"), this);
    foreach (QAction *action, exportAsActs)
        exportMenu->addAction(action);

    fileMenu = new QMenu(tr("&File"),this);
    fileMenu->addAction(openAct);
    fileMenu->addAction(saveAct);
    fileMenu->addMenu(exportMenu);
    fileMenu->addAction(printAct);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAct);
    menuBar()->addMenu(fileMenu);

    helpMenu = new QMenu(tr("&Help"), this);
    helpMenu->addAction(aboutAct);
    menuBar()->addMenu(helpMenu);
}

void MainWindow::createToolBars()
{
    fileToolBar = addToolBar(tr("Actions"));
    fileToolBar->addAction(zoomAllAct);
    fileToolBar->addAction(zoomBoxAct);
    fileToolBar->addAction(panAct);
    fileToolBar->addAction(panLeftAct);
    fileToolBar->addAction(panRightAct);
    fileToolBar->addAction(panUpAct);
    fileToolBar->addAction(panDownAct);
    fileToolBar->addAction(infoAct);
    fileToolBar->addAction(reloadAct);
    fileToolBar->addAction(printAct);
    slider_ = new QSlider(Qt::Horizontal,fileToolBar);
    slider_->setRange(1,18);
    slider_->setTickPosition(QSlider::TicksBelow);
    slider_->setTickInterval(1);
    slider_->setTracking(false);
    fileToolBar->addWidget(slider_);
    fileToolBar->addAction(aboutAct);
}

void MainWindow::set_default_extent(double x0,double y0, double x1, double y1)
{
    try
    {
        boost::shared_ptr<mapnik::Map> map_ptr = mapWidget_->getMap();
        if (map_ptr)
        {
            mapnik::projection prj(map_ptr->srs());
            prj.forward(x0,y0);
            prj.forward(x1,y1);
            default_extent_=mapnik::box2d<double>(x0,y0,x1,y1);
            mapWidget_->zoomToBox(default_extent_);
            std::cout << "SET DEFAULT EXT\n";
        }
    }
    catch (...) {}
}

void MainWindow::set_scaling_factor(double scaling_factor)
{
    mapWidget_->set_scaling_factor(scaling_factor);
}

void MainWindow::zoom_all()
{
    boost::shared_ptr<mapnik::Map> map_ptr = mapWidget_->getMap();
    if (map_ptr)
    {
        map_ptr->zoom_all();
        mapnik::box2d<double> const& ext = map_ptr->getCurrentExtent();
        mapWidget_->zoomToBox(ext);
    }
}
<commit_msg>+ catch all exceptions in load_map_file<commit_after>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2006 Artem Pavlenko
 *
 * Mapnik 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 any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//$Id$

// stl
#include <iostream>

// qt
#include <QtGui>
#include <QSplitter>
#include <QTreeView>
#include <QListView>
#include <QTabWidget>
#include <QList>
#include <QItemDelegate>
#include <QSlider>

// mapnik
#include <mapnik/config_error.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/save_map.hpp>

// qt
#include "mainwindow.hpp"
#include "layerlistmodel.hpp"
#include "styles_model.hpp"
#include "layerwidget.hpp"
#include "layerdelegate.hpp"
#include "about_dialog.hpp"

MainWindow::MainWindow()
    : filename_(),
      default_extent_(-20037508.3428,-20037508.3428,20037508.3428,20037508.3428)
{
    mapWidget_ = new MapWidget(this);
    QSplitter *splitter = new QSplitter(this);
    QTabWidget *tabWidget=new QTabWidget;
    layerTab_ = new LayerTab;
    layerTab_->setFocusPolicy(Qt::NoFocus);
    layerTab_->setIconSize(QSize(16,16));

    //LayerDelegate *delegate = new LayerDelegate(this);
    //layerTab_->setItemDelegate(delegate);
    //layerTab_->setItemDelegate(new QItemDelegate(this));
    //layerTab_->setViewMode(QListView::IconMode);

    layerTab_->setFlow(QListView::TopToBottom);
    tabWidget->addTab(layerTab_,tr("Layers"));

    // Styles tab
    styleTab_ = new StyleTab;
    tabWidget->addTab(styleTab_,tr("Styles"));
    splitter->addWidget(tabWidget);
    splitter->addWidget(mapWidget_);
    QList<int> list;
    list.push_back(200);
    list.push_back(600);
    splitter->setSizes(list);

    mapWidget_->setFocusPolicy(Qt::StrongFocus);
    mapWidget_->setFocus();

    //setCentralWidget(mapWidget_);
    setCentralWidget(splitter);
    createActions();
    createMenus();
    createToolBars();
    createContextMenu();

    setWindowTitle(tr("Mapnik Viewer"));
    status=new QStatusBar(this);
    status->showMessage(tr(""));
    setStatusBar(status);
    resize(800,600);

    //connect mapview to layerlist
    connect(mapWidget_, SIGNAL(mapViewChanged()),layerTab_, SLOT(update()));
    // slider
    connect(slider_,SIGNAL(valueChanged(int)),mapWidget_,SLOT(zoomToLevel(int)));
    //
    connect(layerTab_,SIGNAL(update_mapwidget()),mapWidget_,SLOT(updateMap()));
    connect(layerTab_,SIGNAL(layerSelected(int)),
            mapWidget_,SLOT(layerSelected(int)));
}

MainWindow::~MainWindow()
{
    delete mapWidget_;
}

void MainWindow::closeEvent(QCloseEvent* event)
{
    event->accept();
}

void MainWindow::createContextMenu()
{
    layerTab_->setContextMenuPolicy(Qt::ActionsContextMenu);
    layerTab_->addAction(openAct);
    layerTab_->addAction(layerInfo);
}

void MainWindow::open(QString const& path)
{
    if (path.isNull())
    {
        filename_ = QFileDialog::getOpenFileName(this,tr("Open Mapnik file"),
                                                 currentPath,"*.xml");
    }
    else
    {
        filename_ = path;
    }

    if (!filename_.isEmpty())
    {

        load_map_file(filename_);
        setWindowTitle(tr("%1 - Mapnik Viewer").arg(filename_));
    }

}

void MainWindow::reload()
{
    if (!filename_.isEmpty())
    {

        mapnik::box2d<double> bbox = mapWidget_->getMap()->getCurrentExtent();
        load_map_file(filename_);
        mapWidget_->zoomToBox(bbox);
        setWindowTitle(tr("%1 - *Reloaded*").arg(filename_));
    }
}

void MainWindow::save()
{
    QString initialPath = QDir::currentPath() + "/untitled.xml";
    QString filename = QFileDialog::getSaveFileName(this, tr("Save"),
                                                    initialPath,
                                                    tr("%1 Files (*.xml)")
                                                    .arg(QString("Mapnik definition")));
    if (!filename.isEmpty())
    {
        std::cout<<"saving "<< filename.toStdString() << std::endl;
        mapnik::save_map(*mapWidget_->getMap(),filename.toStdString());
    }
}

void MainWindow::load_map_file(QString const& filename)
{
    std::cout<<"loading "<< filename.toStdString() << std::endl;
    unsigned width = mapWidget_->width();
    unsigned height = mapWidget_->height();
    boost::shared_ptr<mapnik::Map> map(new mapnik::Map(width,height));
    mapWidget_->setMap(map);
    try
    {
        mapnik::load_map(*map,filename.toStdString());
    }
    catch (mapnik::config_error & ex)
    {
        std::cout << ex.what() << "\n";
    }
    catch (...)
    {
        std::cerr << "Exception caught in load_map\n";
    }
    layerTab_->setModel(new LayerListModel(map,this));
    styleTab_->setModel(new StyleModel(map,this));
}

void MainWindow::zoom_to_box()
{
    mapWidget_->setTool(MapWidget::ZoomToBox);
}

void MainWindow::pan()
{
    mapWidget_->setTool(MapWidget::Pan);
}

void MainWindow::info()
{
    mapWidget_->setTool(MapWidget::Info);
}

void MainWindow::pan_left()
{
    mapWidget_->panLeft();
}

void MainWindow::pan_right()
{
    mapWidget_->panRight();
}

void MainWindow::pan_up()
{
    mapWidget_->panUp();
}

void MainWindow::pan_down()
{
    mapWidget_->panDown();
}

void MainWindow::about()
{
    about_dialog dlg;
    dlg.exec();
}

void MainWindow::export_as()
{
    QAction *action = qobject_cast<QAction *>(sender());
    QByteArray fileFormat = action->data().toByteArray();
    QString initialPath = QDir::currentPath() + "/map." + fileFormat;

    QString fileName = QFileDialog::getSaveFileName(this, tr("Export As"),
                                                    initialPath,
                                                    tr("%1 Files (*.%2);;All Files (*)")
                                                    .arg(QString(fileFormat.toUpper()))
                                                    .arg(QString(fileFormat)));
    if (!fileName.isEmpty())
    {
        QPixmap const& pix = mapWidget_->pixmap();
        pix.save(fileName);
    }
}

void MainWindow::print()
{

    //Q_ASSERT(mapWidget_->pixmap());
    //QPrintDialog dialog(&printer, this);
    //if (dialog.exec()) {
    //   QPainter painter(&printer);
    //   QRect rect = painter.viewport();
    //   QSize size = mapWidget_->pixmap()->size();
    //   size.scale(rect.size(), Qt::KeepAspectRatio);
    //   painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
    //   painter.setWindow(mapWidget_->pixmap()->rect());
    //   painter.drawPixmap(0, 0, *mapWidget_->pixmap());
    //}
}

void MainWindow::createActions()
{
    //exportAct = new QAction(tr("&Export as ..."),this);
    //exportAct->setShortcut(tr("Ctrl+E"));
    //connect(exportAct, SIGNAL(triggered()), this, SLOT(export_as()));
    zoomAllAct = new QAction(QIcon(":/images/home.png"),tr("Zoom All"),this);
    connect(zoomAllAct, SIGNAL(triggered()), this, SLOT(zoom_all()));

    zoomBoxAct = new QAction(QIcon(":/images/zoombox.png"),tr("Zoom To Box"),this);
    zoomBoxAct->setCheckable(true);
    connect(zoomBoxAct, SIGNAL(triggered()), this, SLOT(zoom_to_box()));

    panAct = new QAction(QIcon(":/images/pan.png"),tr("Pan"),this);
    panAct->setCheckable(true);
    connect(panAct, SIGNAL(triggered()), this, SLOT(pan()));

    infoAct = new QAction(QIcon(":/images/info.png"),tr("Info"),this);
    infoAct->setCheckable(true);
    connect(infoAct, SIGNAL(triggered()), this, SLOT(info()));

    toolsGroup=new QActionGroup(this);
    toolsGroup->addAction(zoomBoxAct);
    toolsGroup->addAction(panAct);
    toolsGroup->addAction(infoAct);
    zoomBoxAct->setChecked(true);

    openAct=new QAction(tr("Open Map definition"),this);
    connect(openAct,SIGNAL(triggered()),this,SLOT(open()));
    saveAct=new QAction(tr("Save Map definition"),this);
    connect(saveAct,SIGNAL(triggered()),this,SLOT(save()));

    panLeftAct = new QAction(QIcon(":/images/left.png"),tr("&Pan Left"),this);
    connect(panLeftAct, SIGNAL(triggered()), this, SLOT(pan_left()));
    panRightAct = new QAction(QIcon(":/images/right.png"),tr("&Pan Right"),this);
    connect(panRightAct, SIGNAL(triggered()), this, SLOT(pan_right()));
    panUpAct = new QAction(QIcon(":/images/up.png"),tr("&Pan Up"),this);
    connect(panUpAct, SIGNAL(triggered()), this, SLOT(pan_up()));
    panDownAct = new QAction(QIcon(":/images/down.png"),tr("&Pan Down"),this);
    connect(panDownAct, SIGNAL(triggered()), this, SLOT(pan_down()));

    reloadAct = new QAction(QIcon(":/images/reload.png"),tr("Reload"),this);
    connect(reloadAct, SIGNAL(triggered()), this, SLOT(reload()));

    layerInfo = new QAction(QIcon(":/images/info.png"),tr("&Layer info"),layerTab_);
    connect(layerInfo, SIGNAL(triggered()), layerTab_,SLOT(layerInfo()));
    connect(layerTab_, SIGNAL(doubleClicked(QModelIndex const&)), layerTab_,SLOT(layerInfo2(QModelIndex const&)));
    foreach (QByteArray format, QImageWriter::supportedImageFormats())
    {
        QString text = tr("%1...").arg(QString(format).toUpper());

        QAction *action = new QAction(text, this);
        action->setData(format);
        connect(action, SIGNAL(triggered()), this, SLOT(export_as()));
        exportAsActs.append(action);
    }

    printAct = new QAction(QIcon(":/images/print.png"),tr("&Print ..."),this);
    printAct->setShortcut(tr("Ctrl+E"));
    connect(printAct, SIGNAL(triggered()), this, SLOT(print()));

    exitAct = new QAction(tr("E&xit"), this);
    exitAct->setShortcut(tr("Ctrl+Q"));
    connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));

    aboutAct = new QAction(QIcon(":/images/about.png"),tr("&About"), this);
    connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
}

void MainWindow::createMenus()
{
    exportMenu = new QMenu(tr("&Export As"), this);
    foreach (QAction *action, exportAsActs)
        exportMenu->addAction(action);

    fileMenu = new QMenu(tr("&File"),this);
    fileMenu->addAction(openAct);
    fileMenu->addAction(saveAct);
    fileMenu->addMenu(exportMenu);
    fileMenu->addAction(printAct);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAct);
    menuBar()->addMenu(fileMenu);

    helpMenu = new QMenu(tr("&Help"), this);
    helpMenu->addAction(aboutAct);
    menuBar()->addMenu(helpMenu);
}

void MainWindow::createToolBars()
{
    fileToolBar = addToolBar(tr("Actions"));
    fileToolBar->addAction(zoomAllAct);
    fileToolBar->addAction(zoomBoxAct);
    fileToolBar->addAction(panAct);
    fileToolBar->addAction(panLeftAct);
    fileToolBar->addAction(panRightAct);
    fileToolBar->addAction(panUpAct);
    fileToolBar->addAction(panDownAct);
    fileToolBar->addAction(infoAct);
    fileToolBar->addAction(reloadAct);
    fileToolBar->addAction(printAct);
    slider_ = new QSlider(Qt::Horizontal,fileToolBar);
    slider_->setRange(1,18);
    slider_->setTickPosition(QSlider::TicksBelow);
    slider_->setTickInterval(1);
    slider_->setTracking(false);
    fileToolBar->addWidget(slider_);
    fileToolBar->addAction(aboutAct);
}

void MainWindow::set_default_extent(double x0,double y0, double x1, double y1)
{
    try
    {
        boost::shared_ptr<mapnik::Map> map_ptr = mapWidget_->getMap();
        if (map_ptr)
        {
            mapnik::projection prj(map_ptr->srs());
            prj.forward(x0,y0);
            prj.forward(x1,y1);
            default_extent_=mapnik::box2d<double>(x0,y0,x1,y1);
            mapWidget_->zoomToBox(default_extent_);
            std::cout << "SET DEFAULT EXT\n";
        }
    }
    catch (...) {}
}

void MainWindow::set_scaling_factor(double scaling_factor)
{
    mapWidget_->set_scaling_factor(scaling_factor);
}

void MainWindow::zoom_all()
{
    boost::shared_ptr<mapnik::Map> map_ptr = mapWidget_->getMap();
    if (map_ptr)
    {
        map_ptr->zoom_all();
        mapnik::box2d<double> const& ext = map_ptr->getCurrentExtent();
        mapWidget_->zoomToBox(ext);
    }
}
<|endoftext|>


<commit_before>#include <string>

#include <nds.h>
#include <nds/debug.h>

#include "./math.h"
#include "./sprite.h"
#include "./debug.h"

namespace FMAW {

//------------------------------------------------------------------------------
// Common sprite helpers.
//------------------------------------------------------------------------------

void clearAllSprites() {
    for ( sprite_id id = 0; id < TOTAL_SPRITES; id++ ) {
        Sprite sprite (id);
        sprite.clear();
    }
}

//------------------------------------------------------------------------------
// Sprite class.
//------------------------------------------------------------------------------

uint8 Sprite::nextEmptySprite = 0;

//----------//------------------------------------------------------------------
//----------// Position.
//----------//------------------------------------------------------------------

bool Sprite::setXPosition( int x ) {
    bool isNegative = x < 0;
    if ( isNegative ) x = -x;

    uint16 xCapped = x & 0x00FF;
    printf("X Original: %d New: %u", x, xCapped);
    if ( x != xCapped ) return false;

    // If x was negative we have to apply 2's complement.
    if ( isNegative ) x = twosComplement9B(x);

    // We have to set the upper part of the half-word to 1 so AND doesn't
    // break anything.
    x |= 0xFE00;
    // We have to set position's bits to 1 so we can then make an AND.
    sprites[this->id].attr1 |= 0x01FF;
    // Now we can set position with a simple AND.
    sprites[this->id].attr1 &= x;

    return true;
}

bool Sprite::setYPosition( int y ) {
    bool isNegative = y < 0;
    if ( isNegative ) y = -y;

    uint16 yCapped = y & 0x007F;
    printf("Y Original: %d New: %u", y, yCapped);
    if ( y != yCapped ) return false;

    // If x was negative we have to apply 2's complement.
    if ( isNegative ) y = twosComplement8B(y);

    // We have to set the upper part of the half-word to 1 so AND doesn't
    // break anything.
    y |= 0xFF00;
    // We have to set position's bits to 1 so we can then make an AND.
    sprites[this->id].attr0 |= 0x00FF;
    // Now we can set position with a simple AND.
    sprites[this->id].attr0 &= y;

    return true;
}

bool Sprite::setPosition( int x, int y ) {
    Point previousPosition = this->getPosition();
    if ( this->setXPosition( x ) && this->setYPosition( y ) ) return true;
    else {
        this->setXPosition( previousPosition.x );
        this->setYPosition( previousPosition.y );
        return false;
    }
    return true;
}

bool Sprite::setPosition( Point point ) {
    return this->setPosition( point.x, point.y );
}

int Sprite::getXPosition() {
    uint8 x = sprites[this->id].attr1 & 0x01FF;
    // If x-position was a negative number...
    if ( (x & 0x0100) != 0 ) return -twosComplement9B(x);
    return x;
}

int Sprite::getYPosition() {
    uint8 y = sprites[this->id].attr0 & 0x00FF;
    // If y-position was a negative number...
    if ( (y & 0x0080) != 0 ) return -twosComplement8B(y);
    return y;
}

Point Sprite::getPosition() {
    Point p {};
    p.x = this->getXPosition();
    p.y = this->getYPosition();
    return p;
}

//----------//------------------------------------------------------------------
//----------// Tile & palette settings.
//----------//------------------------------------------------------------------

bool Sprite::setTile( uint16 tileIndex ) {
    uint16 tileIndexCapped = tileIndex & 0x01FF;
    if ( tileIndex != tileIndexCapped ) return false;
    // We first set tile bits to 1 so we can apply an AND later.
    sprites[this->id].attr2 |= 0x01FF;
    // We apply and AND to set the bits properly.
    sprites[this->id].attr2 &= tileIndexCapped;
    return true;
}

uint16 Sprite::getTile() {
    return sprites[this->id].attr2 & 0x01FF;
}

bool Sprite::setPalette( uint8 paletteIndex ) {
    uint8 paletteIndexCapped = paletteIndex & 0x000F;
    if ( paletteIndex != paletteIndexCapped ) return false;
    // We first set tile bits to 1 so we can apply an AND later.
    sprites[this->id].attr2 |= 0xF000;
    // We apply and AND to set the bits properly.
    sprites[this->id].attr2 &= paletteIndexCapped << 12;
    return true;
}

uint8 Sprite::getPalette() {
    return (sprites[this->id].attr2 & 0xF000) >> 12;
}

//----------//------------------------------------------------------------------
//----------// Rotation & scale settings.
//----------//------------------------------------------------------------------

void Sprite::enableRotationAndScale() {
    sprites[this->id].attr0 |= 0x0100;
}

void Sprite::disableRotationAndScale() {
    sprites[this->id].attr0 &= 0xFEFF;
}

bool Sprite::rotationAndScaleAreEnabled() {
    return (sprites[this->id].attr0 & 0x0100) != 0 ;
}

bool Sprite::rotationAndScaleAreDisabled() {
    return !this->rotationAndScaleAreEnabled();
}

void Sprite::enableDoubleSize() {
    sprites[this->id].attr0 |= 0x0200;
}

void Sprite::disableDoubleSize() {
    sprites[this->id].attr0 &= 0xFDFF;
}

bool Sprite::doubleSizeEnabled() {
    return (sprites[this->id].attr0 = 0x0200) != 0;
}

bool Sprite::doubleSizeDisabled() {
    return !this->doubleSizeEnabled();
}

//----------//------------------------------------------------------------------
//----------// Object mode settings.
//----------//------------------------------------------------------------------

void Sprite::setObjectMode( SpriteObjectMode newMode ) {
    sprites[this->id].attr0 |= 0x0C00;
    sprites[this->id].attr0 &= newMode;
}

SpriteObjectMode Sprite::getObjectMode() {
    uint16 half_word = sprites[this->id].attr0 | 0xF3FF;

    switch (half_word) {
        case normal:
            return normal;
        case alpha_first_target:
            return normal;
        case add_to_window:
            return add_to_window;
        case bitmap:
            return bitmap;
        default:
            // This won't happen ever.
            return normal;
    }
}

//----------//------------------------------------------------------------------
//----------// Mosaic & color settings.
//----------//------------------------------------------------------------------

void Sprite::enableMosaic() {
    sprites[this->id].attr0 |= 0x1000;
}

void Sprite::disableMosaic() {
    sprites[this->id].attr0 &= 0xEFFF;
}

bool Sprite::mosaicIsEnabled() {
    return (sprites[this->id].attr0 & 0x1000) != 0;
}

bool Sprite::mosaicIsDisabled() {
    return !this->mosaicIsEnabled();
}

void Sprite::use16BitColors() {
    sprites[this->id].attr0 &= 0xDFFF;
}

void Sprite::use256BitColors() {
    sprites[this->id].attr0 |= 0x2000;
}

bool Sprite::isUsing16BitColors() {
    return (sprites[this->id].attr0 & 0x2000) != 0;
}

bool Sprite::isUsing256BitColors() {
    return !this->isUsing16BitColors();
}

//----------//------------------------------------------------------------------
//----------// Shape & size settings.
//----------//------------------------------------------------------------------

bool Sprite::setSizeMode( SpriteSizeMode newMode ) {
    uint16 attr0mask;
    uint16 attr1mask;

    switch ( newMode ) {
        case square8x8:
        case square16x16:
        case square32x32:
        case square64x64:
            attr0mask = 0x3FFF;
            break;
        case wide16x8:
        case wide32x8:
        case wide32x16:
        case wide64x32:
            attr0mask = 0x7FFF;
            break;
        case tall8x16:
        case tall8x32:
        case tall16x32:
        case tall32x64:
            attr0mask = 0xBFFF;
            break;
        default:
            return false;
    }

    switch ( newMode ) {
        case square8x8:
        case wide16x8:
        case tall8x16:
            attr1mask = 0x3FFF;
            break;
        case square16x16:
        case wide32x8:
        case tall8x32:
            attr1mask = 0x7FFF;
            break;

        case square32x32:
        case wide32x16:
        case tall16x32:
            attr1mask = 0xBFFF;
            break;
        case square64x64:
        case wide64x32:
        case tall32x64:
            attr1mask = 0xFFFF;
            break;
        default:
            return false;
    }

    // We first set the size bits to 1.
    sprites[this->id].attr0 |= 0XC000;
    sprites[this->id].attr1 |= 0XC000;
    // And then we apply the mask.
    sprites[this->id].attr0 &= attr0mask;
    sprites[this->id].attr1 &= attr1mask;

    return true;
}

SpriteSizeMode Sprite::getSizeMode() {
    uint16 shape = sprites[this->id].attr0 & 0xC000;
    uint16 size  = sprites[this->id].attr1 & 0xC000;
    SpriteSizeMode sizeMode;

    switch ( shape ) {
        // Square.
        case 0x0000:
            switch (size) {
                case 0x0000:
                    sizeMode = square8x8;
                    break;
                case 0x4000:
                    sizeMode = square16x16;
                    break;
                case 0x8000:
                    sizeMode = square32x32;
                    break;
                case 0xC000:
                    sizeMode = square64x64;
                    break;
                default:
                    sizeMode = unknown;
                    break;
            }
            break;
        // Wide.
        case 0x4000:
            switch (size) {
                case 0x0000:
                    sizeMode = wide16x8;
                    break;
                case 0x4000:
                    sizeMode = wide32x8;
                    break;
                case 0x8000:
                    sizeMode = wide32x16;
                    break;
                case 0xC000:
                    sizeMode = wide64x32;
                    break;
                default:
                    sizeMode = unknown;
                    break;
            }
            break;
        // Tall.
        case 0x8000:
            switch (size) {
                case 0x0000:
                    sizeMode = tall8x16;
                    break;
                case 0x4000:
                    sizeMode = tall8x32;
                    break;
                case 0x8000:
                    sizeMode = tall16x32;
                    break;
                case 0xC000:
                    sizeMode = tall32x64;
                    break;
                default:
                    sizeMode = unknown;
                    break;
            }
            break;
        // Not used.
        case 0xC000:
        default:
            sizeMode = unknown;
            break;
    }

    return sizeMode;
}

//----------//------------------------------------------------------------------
//----------// Flip settings.
//----------//------------------------------------------------------------------

void Sprite::enableHorizontalFlip() {
    this->disableRotationAndScale();
    sprites[this->id].attr1 |= 0x1000;
}

void Sprite::disableHorizontalFlip() {
    this->disableRotationAndScale();
    sprites[this->id].attr1 &= 0xEFFF;
}

// If rotation/scaling is disabled it'll return false.
bool Sprite::horizontalFlipIsEnabled() {
    if ( this->rotationAndScaleAreDisabled() )
        return false;
    return (sprites[this->id].attr1 & 0x1000) != 0;
}

// If rotation/scaling is disabled it'll return false.
// THIS IS NOT EQUIVALENT TO !horizontalFlipIsEnabled() !!
bool Sprite::horizontalFlipIsDisabled() {
    if ( this->rotationAndScaleAreDisabled() )
        return false;
    return (sprites[this->id].attr1 & 0x1000) == 0;
}

void Sprite::enableVerticalFlip() {
    sprites[this->id].attr1 |= 0x2000;
}

void Sprite::disableVerticalFlip() {
    sprites[this->id].attr1 &= 0xDFFF;
}

// If rotation/scaling is disabled it'll return false.
bool Sprite::verticalFlipIsEnabled() {
    if ( this->rotationAndScaleAreDisabled() )
        return false;
    return (sprites[this->id].attr1 & 0x2000) != 0;
}

// If rotation/scaling is disabled it'll return false.
// THIS IS NOT EQUIVALENT TO !verticalFlipIsEnabled() !!
bool Sprite::verticalFlipIsDisabled() {
    if ( this->rotationAndScaleAreDisabled() )
        return false;
    return (sprites[this->id].attr1 & 0x2000) == 0;
}

//----------//------------------------------------------------------------------
//----------// Priority settings.
//----------//------------------------------------------------------------------

void Sprite::setPriority( SpritePriority priority ) {
    TO_BE_IMPLEMENTED
}

SpritePriority Sprite::getPriority() {
    TO_BE_IMPLEMENTED
    return spLOW;
}

//----------//------------------------------------------------------------------
//----------// Other settings.
//----------//------------------------------------------------------------------

void Sprite::clear() {
    sprites[this->id].attr0 = ATTR0_DISABLED;
    sprites[this->id].attr1 = 0;
    sprites[this->id].attr2 = 0;
    sprites[this->id].affine_data = 0;
}

void Sprite::disable() {
    uint16 disableMask = 0xFEFF;
    sprites[this->id].attr0 &= disableMask;
}

void Sprite::enable() {
    uint16 enableMask = 0xFCFF;
    sprites[this->id].attr0 &= enableMask;
}

void Sprite::print() {
    FMAW::printf("%s\r\n  Sprite %u:%s\r\n|%s|",
                 "\r\n|----------------|", this->id, "\r\n|----------------|",
                 half_word_to_binary(sprites[this->id].attr0).c_str());
    FMAW::printf("|%s|\r\n|%s|",
                 half_word_to_binary(sprites[this->id].attr1).c_str(),
                 half_word_to_binary(sprites[this->id].attr2).c_str());
    FMAW::printf("|%s|\r\n%s",
                 half_word_to_binary(sprites[this->id].affine_data).c_str(),
                 "|----------------|");
}

}<commit_msg>Sprite class completely implemented<commit_after>#include <string>

#include <nds.h>
#include <nds/debug.h>

#include "./math.h"
#include "./sprite.h"
#include "./debug.h"

namespace FMAW {

//------------------------------------------------------------------------------
// Common sprite helpers.
//------------------------------------------------------------------------------

void clearAllSprites() {
    for ( sprite_id id = 0; id < TOTAL_SPRITES; id++ ) {
        Sprite sprite (id);
        sprite.clear();
    }
}

//------------------------------------------------------------------------------
// Sprite class.
//------------------------------------------------------------------------------

uint8 Sprite::nextEmptySprite = 0;

//----------//------------------------------------------------------------------
//----------// Position.
//----------//------------------------------------------------------------------

bool Sprite::setXPosition( int x ) {
    bool isNegative = x < 0;
    if ( isNegative ) x = -x;

    uint16 xCapped = x & 0x00FF;
    printf("X Original: %d New: %u", x, xCapped);
    if ( x != xCapped ) return false;

    // If x was negative we have to apply 2's complement.
    if ( isNegative ) x = twosComplement9B(x);

    // We have to set the upper part of the half-word to 1 so AND doesn't
    // break anything.
    x |= 0xFE00;
    // We have to set position's bits to 1 so we can then make an AND.
    sprites[this->id].attr1 |= 0x01FF;
    // Now we can set position with a simple AND.
    sprites[this->id].attr1 &= x;

    return true;
}

bool Sprite::setYPosition( int y ) {
    bool isNegative = y < 0;
    if ( isNegative ) y = -y;

    uint16 yCapped = y & 0x007F;
    printf("Y Original: %d New: %u", y, yCapped);
    if ( y != yCapped ) return false;

    // If x was negative we have to apply 2's complement.
    if ( isNegative ) y = twosComplement8B(y);

    // We have to set the upper part of the half-word to 1 so AND doesn't
    // break anything.
    y |= 0xFF00;
    // We have to set position's bits to 1 so we can then make an AND.
    sprites[this->id].attr0 |= 0x00FF;
    // Now we can set position with a simple AND.
    sprites[this->id].attr0 &= y;

    return true;
}

bool Sprite::setPosition( int x, int y ) {
    Point previousPosition = this->getPosition();
    if ( this->setXPosition( x ) && this->setYPosition( y ) ) return true;
    else {
        this->setXPosition( previousPosition.x );
        this->setYPosition( previousPosition.y );
        return false;
    }
    return true;
}

bool Sprite::setPosition( Point point ) {
    return this->setPosition( point.x, point.y );
}

int Sprite::getXPosition() {
    uint8 x = sprites[this->id].attr1 & 0x01FF;
    // If x-position was a negative number...
    if ( (x & 0x0100) != 0 ) return -twosComplement9B(x);
    return x;
}

int Sprite::getYPosition() {
    uint8 y = sprites[this->id].attr0 & 0x00FF;
    // If y-position was a negative number...
    if ( (y & 0x0080) != 0 ) return -twosComplement8B(y);
    return y;
}

Point Sprite::getPosition() {
    Point p {};
    p.x = this->getXPosition();
    p.y = this->getYPosition();
    return p;
}

//----------//------------------------------------------------------------------
//----------// Tile & palette settings.
//----------//------------------------------------------------------------------

bool Sprite::setTile( uint16 tileIndex ) {
    uint16 tileIndexCapped = tileIndex & 0x01FF;
    if ( tileIndex != tileIndexCapped ) return false;
    // We first set tile bits to 1 so we can apply an AND later.
    sprites[this->id].attr2 |= 0x01FF;
    // We apply and AND to set the bits properly.
    sprites[this->id].attr2 &= tileIndexCapped;
    return true;
}

uint16 Sprite::getTile() {
    return sprites[this->id].attr2 & 0x01FF;
}

bool Sprite::setPalette( uint8 paletteIndex ) {
    uint8 paletteIndexCapped = paletteIndex & 0x000F;
    if ( paletteIndex != paletteIndexCapped ) return false;
    // We first set tile bits to 1 so we can apply an AND later.
    sprites[this->id].attr2 |= 0xF000;
    // We apply and AND to set the bits properly.
    sprites[this->id].attr2 &= paletteIndexCapped << 12;
    return true;
}

uint8 Sprite::getPalette() {
    return (sprites[this->id].attr2 & 0xF000) >> 12;
}

//----------//------------------------------------------------------------------
//----------// Rotation & scale settings.
//----------//------------------------------------------------------------------

void Sprite::enableRotationAndScale() {
    sprites[this->id].attr0 |= 0x0100;
}

void Sprite::disableRotationAndScale() {
    sprites[this->id].attr0 &= 0xFEFF;
}

bool Sprite::rotationAndScaleAreEnabled() {
    return (sprites[this->id].attr0 & 0x0100) != 0 ;
}

bool Sprite::rotationAndScaleAreDisabled() {
    return !this->rotationAndScaleAreEnabled();
}

void Sprite::enableDoubleSize() {
    sprites[this->id].attr0 |= 0x0200;
}

void Sprite::disableDoubleSize() {
    sprites[this->id].attr0 &= 0xFDFF;
}

bool Sprite::doubleSizeEnabled() {
    return (sprites[this->id].attr0 = 0x0200) != 0;
}

bool Sprite::doubleSizeDisabled() {
    return !this->doubleSizeEnabled();
}

//----------//------------------------------------------------------------------
//----------// Object mode settings.
//----------//------------------------------------------------------------------

void Sprite::setObjectMode( SpriteObjectMode newMode ) {
    sprites[this->id].attr0 |= 0x0C00;
    sprites[this->id].attr0 &= newMode;
}

SpriteObjectMode Sprite::getObjectMode() {
    uint16 half_word = sprites[this->id].attr0 | 0xF3FF;

    switch (half_word) {
        case normal:
            return normal;
        case alpha_first_target:
            return normal;
        case add_to_window:
            return add_to_window;
        case bitmap:
            return bitmap;
        default:
            // This won't ever happen.
            return normal;
    }
}

//----------//------------------------------------------------------------------
//----------// Mosaic & color settings.
//----------//------------------------------------------------------------------

void Sprite::enableMosaic() {
    sprites[this->id].attr0 |= 0x1000;
}

void Sprite::disableMosaic() {
    sprites[this->id].attr0 &= 0xEFFF;
}

bool Sprite::mosaicIsEnabled() {
    return (sprites[this->id].attr0 & 0x1000) != 0;
}

bool Sprite::mosaicIsDisabled() {
    return !this->mosaicIsEnabled();
}

void Sprite::use16BitColors() {
    sprites[this->id].attr0 &= 0xDFFF;
}

void Sprite::use256BitColors() {
    sprites[this->id].attr0 |= 0x2000;
}

bool Sprite::isUsing16BitColors() {
    return (sprites[this->id].attr0 & 0x2000) != 0;
}

bool Sprite::isUsing256BitColors() {
    return !this->isUsing16BitColors();
}

//----------//------------------------------------------------------------------
//----------// Shape & size settings.
//----------//------------------------------------------------------------------

bool Sprite::setSizeMode( SpriteSizeMode newMode ) {
    uint16 attr0mask;
    uint16 attr1mask;

    switch ( newMode ) {
        case square8x8:
        case square16x16:
        case square32x32:
        case square64x64:
            attr0mask = 0x3FFF;
            break;
        case wide16x8:
        case wide32x8:
        case wide32x16:
        case wide64x32:
            attr0mask = 0x7FFF;
            break;
        case tall8x16:
        case tall8x32:
        case tall16x32:
        case tall32x64:
            attr0mask = 0xBFFF;
            break;
        default:
            return false;
    }

    switch ( newMode ) {
        case square8x8:
        case wide16x8:
        case tall8x16:
            attr1mask = 0x3FFF;
            break;
        case square16x16:
        case wide32x8:
        case tall8x32:
            attr1mask = 0x7FFF;
            break;

        case square32x32:
        case wide32x16:
        case tall16x32:
            attr1mask = 0xBFFF;
            break;
        case square64x64:
        case wide64x32:
        case tall32x64:
            attr1mask = 0xFFFF;
            break;
        default:
            return false;
    }

    // We first set the size bits to 1.
    sprites[this->id].attr0 |= 0XC000;
    sprites[this->id].attr1 |= 0XC000;
    // And then we apply the mask.
    sprites[this->id].attr0 &= attr0mask;
    sprites[this->id].attr1 &= attr1mask;

    return true;
}

SpriteSizeMode Sprite::getSizeMode() {
    uint16 shape = sprites[this->id].attr0 & 0xC000;
    uint16 size  = sprites[this->id].attr1 & 0xC000;
    SpriteSizeMode sizeMode;

    switch ( shape ) {
        // Square.
        case 0x0000:
            switch (size) {
                case 0x0000:
                    sizeMode = square8x8;
                    break;
                case 0x4000:
                    sizeMode = square16x16;
                    break;
                case 0x8000:
                    sizeMode = square32x32;
                    break;
                case 0xC000:
                    sizeMode = square64x64;
                    break;
                default:
                    sizeMode = unknown;
                    break;
            }
            break;
        // Wide.
        case 0x4000:
            switch (size) {
                case 0x0000:
                    sizeMode = wide16x8;
                    break;
                case 0x4000:
                    sizeMode = wide32x8;
                    break;
                case 0x8000:
                    sizeMode = wide32x16;
                    break;
                case 0xC000:
                    sizeMode = wide64x32;
                    break;
                default:
                    sizeMode = unknown;
                    break;
            }
            break;
        // Tall.
        case 0x8000:
            switch (size) {
                case 0x0000:
                    sizeMode = tall8x16;
                    break;
                case 0x4000:
                    sizeMode = tall8x32;
                    break;
                case 0x8000:
                    sizeMode = tall16x32;
                    break;
                case 0xC000:
                    sizeMode = tall32x64;
                    break;
                default:
                    sizeMode = unknown;
                    break;
            }
            break;
        // Not used.
        case 0xC000:
        default:
            sizeMode = unknown;
            break;
    }

    return sizeMode;
}

//----------//------------------------------------------------------------------
//----------// Flip settings.
//----------//------------------------------------------------------------------

void Sprite::enableHorizontalFlip() {
    this->disableRotationAndScale();
    sprites[this->id].attr1 |= 0x1000;
}

void Sprite::disableHorizontalFlip() {
    this->disableRotationAndScale();
    sprites[this->id].attr1 &= 0xEFFF;
}

// If rotation/scaling is disabled it'll return false.
bool Sprite::horizontalFlipIsEnabled() {
    if ( this->rotationAndScaleAreDisabled() )
        return false;
    return (sprites[this->id].attr1 & 0x1000) != 0;
}

// If rotation/scaling is disabled it'll return false.
// THIS IS NOT EQUIVALENT TO !horizontalFlipIsEnabled() !!
bool Sprite::horizontalFlipIsDisabled() {
    if ( this->rotationAndScaleAreDisabled() )
        return false;
    return (sprites[this->id].attr1 & 0x1000) == 0;
}

void Sprite::enableVerticalFlip() {
    sprites[this->id].attr1 |= 0x2000;
}

void Sprite::disableVerticalFlip() {
    sprites[this->id].attr1 &= 0xDFFF;
}

// If rotation/scaling is disabled it'll return false.
bool Sprite::verticalFlipIsEnabled() {
    if ( this->rotationAndScaleAreDisabled() )
        return false;
    return (sprites[this->id].attr1 & 0x2000) != 0;
}

// If rotation/scaling is disabled it'll return false.
// THIS IS NOT EQUIVALENT TO !verticalFlipIsEnabled() !!
bool Sprite::verticalFlipIsDisabled() {
    if ( this->rotationAndScaleAreDisabled() )
        return false;
    return (sprites[this->id].attr1 & 0x2000) == 0;
}

//----------//------------------------------------------------------------------
//----------// Priority settings.
//----------//------------------------------------------------------------------

void Sprite::setPriority( SpritePriority priority ) {
    sprites[this->id].attr2 |= 0x0C00;
    sprites[this->id].attr2 &= priority;
}

SpritePriority Sprite::getPriority() {
    uint16 half_word = sprites[this->id].attr2 | 0xF3FF;

    switch (half_word) {
        case spHIGHEST:
            return spHIGHEST;
        case spHIGH:
            return spHIGH;
        case spLOW:
            return spLOW;
        case spLOWEST:
            return spLOWEST;
        default:
            // This won't ever happen.
            return spHIGHEST;
    }
}

//----------//------------------------------------------------------------------
//----------// Other settings.
//----------//------------------------------------------------------------------

void Sprite::clear() {
    sprites[this->id].attr0 = ATTR0_DISABLED;
    sprites[this->id].attr1 = 0;
    sprites[this->id].attr2 = 0;
    sprites[this->id].affine_data = 0;
}

void Sprite::disable() {
    uint16 disableMask = 0xFEFF;
    sprites[this->id].attr0 &= disableMask;
}

void Sprite::enable() {
    uint16 enableMask = 0xFCFF;
    sprites[this->id].attr0 &= enableMask;
}

void Sprite::print() {
    FMAW::printf("%s\r\n  Sprite %u:%s\r\n|%s|",
                 "\r\n|----------------|", this->id, "\r\n|----------------|",
                 half_word_to_binary(sprites[this->id].attr0).c_str());
    FMAW::printf("|%s|\r\n|%s|",
                 half_word_to_binary(sprites[this->id].attr1).c_str(),
                 half_word_to_binary(sprites[this->id].attr2).c_str());
    FMAW::printf("|%s|\r\n%s",
                 half_word_to_binary(sprites[this->id].affine_data).c_str(),
                 "|----------------|");
}

}<|endoftext|>