<commit_before>#ifndef NCA_HPP
#define NCA_HPP

#include <iostream>
#include <limits>
#include <vector>

#include <Eigen/Core>

void nearest_neighbors(const std::vector<Eigen::VectorXd>& input, const std::vector<std::string> label) {
    unsigned int correct = 0;

    for(unsigned int i = 0; i < input.size(); ++i) {
        double min_norm = std::numeric_limits<double>::infinity();
        std::string min_norm_label;
        for(unsigned int j = 0; j < input.size(); ++j) {
            if(i == j) continue;
            double norm = (input[i] - input[j]).norm();
            if(norm < min_norm) {
                min_norm = norm;
                min_norm_label = label[j];
            }
        }

        if(label[i] == min_norm_label) {
            ++correct;
        }
    }

    std::cout << "Got " << correct << " correct out of " << input.size() << std::endl;
}

Eigen::MatrixXd scaling_matrix(const std::vector<Eigen::VectorXd>& input) {
    Eigen::MatrixXd A;
    if(input.size() == 0) return A;

    int size = input[0].size();

    std::vector< std::pair<double, double> > minmax(size, std::make_pair(std::numeric_limits<double>::infinity(), -std::numeric_limits<double>::infinity()));
    for(std::vector<Eigen::VectorXd>::const_iterator i = input.begin(); i != input.end(); ++i) {
        for(int j = 0; j < i->size(); ++j) {
            double val = (*i)[j];
            if(val < minmax[j].first) {
                minmax[j] = std::make_pair(val, minmax[j].second);
            }
            if(val > minmax[j].second) {
                minmax[j] = std::make_pair(minmax[j].first, val);
            }
        }
    }

    A = Eigen::MatrixXd::Identity(size, size);
    for(unsigned int i = 0; i < minmax.size(); ++i) {
        A(i, i) = 1.0/(minmax[i].second - minmax[i].first);
    }

    return A;
}

std::vector<Eigen::VectorXd> scale(const Eigen::MatrixXd ScaleA, const std::vector<Eigen::VectorXd>& input) {
    std::vector<Eigen::VectorXd> scaled_input;
    for(std::vector<Eigen::VectorXd>::const_iterator i = input.begin(); i != input.end(); ++i) {
        scaled_input.push_back(ScaleA * (*i));
    }

    return scaled_input;
}

Eigen::MatrixXd neighborhood_components_analysis(const std::vector<Eigen::VectorXd>& input, const std::vector<std::string> label, const Eigen::MatrixXd& init, unsigned int iterations, double learning_rate) {
    Eigen::MatrixXd A = init;
    for(unsigned int it = 0; it < iterations; ++it) {
        unsigned int i = it % input.size();

        double softmax_normalization = 0.0;
        for(unsigned int k = 0; k < input.size(); ++k) {
            if(k == i) continue;
            softmax_normalization += std::exp(-(A*input[i] - A*input[k]).squaredNorm());
        }

        std::vector<double> softmax;
        for(unsigned int k = 0; k < input.size(); ++k) {
            if(k == i) softmax.push_back(0.0);
            else {
                softmax.push_back(std::exp(-(A*input[i] - A*input[k]).squaredNorm()) / softmax_normalization);
            }
        }

        double p = 0.0;
        for(unsigned int k = 0; k < softmax.size(); ++k) {
            if(label[k] == label[i]) p += softmax[k];
        }

        Eigen::MatrixXd first_term = Eigen::MatrixXd::Zero(input[0].size(), input[0].size());
        Eigen::MatrixXd second_term = Eigen::MatrixXd::Zero(input[0].size(), input[0].size());
        for(unsigned int k = 0; k < input.size(); ++k) {
            if(k == i) continue;
            Eigen::VectorXd xik = input[i] - input[k];
            Eigen::MatrixXd term = softmax[k] * (xik * xik.transpose());

            first_term += term;
            if(label[k] == label[i]) second_term += term;
        }
        first_term *= p;

        A += learning_rate*A*(first_term - second_term);
    }

    return A;
}

#endif // NCA_HPP
<commit_msg>add references<commit_after>#ifndef NCA_HPP
#define NCA_HPP

#include <iostream>
#include <limits>
#include <vector>

#include <Eigen/Core>

void nearest_neighbors(const std::vector<Eigen::VectorXd>& input, const std::vector<std::string>& label) {
    unsigned int correct = 0;

    for(unsigned int i = 0; i < input.size(); ++i) {
        double min_norm = std::numeric_limits<double>::infinity();
        std::string min_norm_label;
        for(unsigned int j = 0; j < input.size(); ++j) {
            if(i == j) continue;
            double norm = (input[i] - input[j]).norm();
            if(norm < min_norm) {
                min_norm = norm;
                min_norm_label = label[j];
            }
        }

        if(label[i] == min_norm_label) {
            ++correct;
        }
    }

    std::cout << "Got " << correct << " correct out of " << input.size() << std::endl;
}

Eigen::MatrixXd scaling_matrix(const std::vector<Eigen::VectorXd>& input) {
    Eigen::MatrixXd A;
    if(input.size() == 0) return A;

    int size = input[0].size();

    std::vector< std::pair<double, double> > minmax(size, std::make_pair(std::numeric_limits<double>::infinity(), -std::numeric_limits<double>::infinity()));
    for(std::vector<Eigen::VectorXd>::const_iterator i = input.begin(); i != input.end(); ++i) {
        for(int j = 0; j < i->size(); ++j) {
            double val = (*i)[j];
            if(val < minmax[j].first) {
                minmax[j] = std::make_pair(val, minmax[j].second);
            }
            if(val > minmax[j].second) {
                minmax[j] = std::make_pair(minmax[j].first, val);
            }
        }
    }

    A = Eigen::MatrixXd::Identity(size, size);
    for(unsigned int i = 0; i < minmax.size(); ++i) {
        A(i, i) = 1.0/(minmax[i].second - minmax[i].first);
    }

    return A;
}

std::vector<Eigen::VectorXd> scale(const Eigen::MatrixXd& ScaleA, const std::vector<Eigen::VectorXd>& input) {
    std::vector<Eigen::VectorXd> scaled_input;
    for(std::vector<Eigen::VectorXd>::const_iterator i = input.begin(); i != input.end(); ++i) {
        scaled_input.push_back(ScaleA * (*i));
    }

    return scaled_input;
}

Eigen::MatrixXd neighborhood_components_analysis(const std::vector<Eigen::VectorXd>& input, const std::vector<std::string>& label, const Eigen::MatrixXd& init, unsigned int iterations, double learning_rate) {
    Eigen::MatrixXd A = init;
    for(unsigned int it = 0; it < iterations; ++it) {
        unsigned int i = it % input.size();

        double softmax_normalization = 0.0;
        for(unsigned int k = 0; k < input.size(); ++k) {
            if(k == i) continue;
            softmax_normalization += std::exp(-(A*input[i] - A*input[k]).squaredNorm());
        }

        std::vector<double> softmax;
        for(unsigned int k = 0; k < input.size(); ++k) {
            if(k == i) softmax.push_back(0.0);
            else {
                softmax.push_back(std::exp(-(A*input[i] - A*input[k]).squaredNorm()) / softmax_normalization);
            }
        }

        double p = 0.0;
        for(unsigned int k = 0; k < softmax.size(); ++k) {
            if(label[k] == label[i]) p += softmax[k];
        }

        Eigen::MatrixXd first_term = Eigen::MatrixXd::Zero(input[0].size(), input[0].size());
        Eigen::MatrixXd second_term = Eigen::MatrixXd::Zero(input[0].size(), input[0].size());
        for(unsigned int k = 0; k < input.size(); ++k) {
            if(k == i) continue;
            Eigen::VectorXd xik = input[i] - input[k];
            Eigen::MatrixXd term = softmax[k] * (xik * xik.transpose());

            first_term += term;
            if(label[k] == label[i]) second_term += term;
        }
        first_term *= p;

        A += learning_rate*A*(first_term - second_term);
    }

    return A;
}

#endif // NCA_HPP
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file net.cpp
 * @author Alex Leverington <nessence@gmail.com>
 * @date 2014
 */

#include <boost/test/unit_test.hpp>
#include <libdevcore/Worker.h>
#include <libdevcrypto/Common.h>
#include <libp2p/UDP.h>
#include <libp2p/NodeTable.h>
using namespace std;
using namespace dev;
using namespace dev::p2p;
namespace ba = boost::asio;
namespace bi = ba::ip;

BOOST_AUTO_TEST_SUITE(p2p)

/**
 * Only used for testing. Not useful beyond tests.
 */
class TestHost: public Worker
{
public:
	TestHost(): Worker("test",0), m_io() {};
	virtual ~TestHost() { m_io.stop(); stopWorking(); }
	void start() { startWorking(); }
	void doWork() { m_io.run(); }
	void doneWorking() { m_io.reset(); m_io.poll(); m_io.reset(); }

protected:
	ba::io_service m_io;
};

struct TestNodeTable: public NodeTable
{
	/// Constructor
	using NodeTable::NodeTable;

	static std::vector<std::pair<KeyPair,unsigned>> createTestNodes(unsigned _count)
	{
		std::vector<std::pair<KeyPair,unsigned>> ret;
		asserts(_count < 1000);
		static uint16_t s_basePort = 30500;

		ret.clear();
		for (unsigned i = 0; i < _count; i++)
		{
			KeyPair k = KeyPair::create();
			ret.push_back(make_pair(k,s_basePort+i));
		}

		return std::move(ret);
	}

	void pingTestNodes(std::vector<std::pair<KeyPair,unsigned>> const& _testNodes)
	{
		bi::address ourIp = bi::address::from_string("127.0.0.1");
		for (auto& n: _testNodes)
		{
			ping(bi::udp::endpoint(ourIp, n.second));
			this_thread::sleep_for(chrono::milliseconds(2));
		}
	}

	void populateTestNodes(std::vector<std::pair<KeyPair,unsigned>> const& _testNodes, size_t _count = 0)
	{
		if (!_count)
			_count = _testNodes.size();

		bi::address ourIp = bi::address::from_string("127.0.0.1");
		for (auto& n: _testNodes)
			if (_count--)
				noteNode(n.first.pub(), bi::udp::endpoint(ourIp, n.second));
			else
				break;
	}

	void reset()
	{
		Guard l(x_state);
		for (auto& n: m_state) n.nodes.clear();
	}
};

/**
 * Only used for testing. Not useful beyond tests.
 */
struct TestNodeTableHost: public TestHost
{
	TestNodeTableHost(unsigned _count = 8): m_alias(KeyPair::create()), nodeTable(new TestNodeTable(m_io, m_alias)), testNodes(TestNodeTable::createTestNodes(_count)) {};
	~TestNodeTableHost() { m_io.stop(); stopWorking(); }

	void setup() { for (auto n: testNodes) nodeTables.push_back(make_shared<TestNodeTable>(m_io,n.first,n.second)); }

	void pingAll() { for (auto& t: nodeTables) t->pingTestNodes(testNodes); }

	void populateAll(size_t _count = 0) { for (auto& t: nodeTables) t->populateTestNodes(testNodes, _count); }

	void populate(size_t _count = 0) { nodeTable->populateTestNodes(testNodes, _count); }

	KeyPair m_alias;
	shared_ptr<TestNodeTable> nodeTable;
	std::vector<std::pair<KeyPair,unsigned>> testNodes; // keypair and port
	std::vector<shared_ptr<TestNodeTable>> nodeTables;
};

class TestUDPSocket: UDPSocketEvents, public TestHost
{
public:
	TestUDPSocket(): m_socket(new UDPSocket<TestUDPSocket, 1024>(m_io, *this, 30300)) {}

	void onDisconnected(UDPSocketFace*) {};
	void onReceived(UDPSocketFace*, bi::udp::endpoint const&, bytesConstRef _packet) { if (_packet.toString() == "AAAA") success = true; }

	shared_ptr<UDPSocket<TestUDPSocket, 1024>> m_socket;

	bool success = false;
};

BOOST_AUTO_TEST_CASE(test_neighbors_packet)
{
	KeyPair k = KeyPair::create();
	std::vector<std::pair<KeyPair,unsigned>> testNodes(TestNodeTable::createTestNodes(16));
	bi::udp::endpoint to(boost::asio::ip::address::from_string("127.0.0.1"), 30000);

	Neighbors out(to);
	for (auto n: testNodes)
	{
		Neighbors::Node node;
		node.ipAddress = boost::asio::ip::address::from_string("127.0.0.1").to_string();
		node.port = n.second;
		node.node = n.first.pub();
		out.nodes.push_back(node);
	}
	out.sign(k.sec());

	bytesConstRef packet(out.data.data(), out.data.size());
	bytesConstRef rlpBytes(packet.cropped(97, packet.size() - 97));
	Neighbors in = Neighbors::fromBytesConstRef(to, rlpBytes);
	int count = 0;
	for (auto n: in.nodes)
	{
		BOOST_REQUIRE_EQUAL(testNodes[count].second, n.port);
		BOOST_REQUIRE_EQUAL(testNodes[count].first.pub(), n.node);
		BOOST_REQUIRE_EQUAL(sha3(testNodes[count].first.pub()), sha3(n.node));
		count++;
	}
}

BOOST_AUTO_TEST_CASE(test_findnode_neighbors)
{
	// Executing findNode should result in a list which is serialized
	// into Neighbors packet. Neighbors packet should then be deserialized
	// into the same list of nearest nodes.
}

BOOST_AUTO_TEST_CASE(test_windows_template)
{
	bi::udp::endpoint ep;
	PingNode p(ep);
}

BOOST_AUTO_TEST_CASE(kademlia)
{
	// Not yet a 'real' test.
	TestNodeTableHost node(8);
	node.start();
	node.nodeTable->join(); // ideally, joining with empty node table logs warning we can check for
	node.setup();
	node.populate();
	clog << "NodeTable:\n" << *node.nodeTable.get() << endl;

	node.populateAll();
	clog << "NodeTable:\n" << *node.nodeTable.get() << endl;

	node.nodeTable->reset();
	clog << "NodeTable:\n" << *node.nodeTable.get() << endl;

	node.populate(1);
	clog << "NodeTable:\n" << *node.nodeTable.get() << endl;

	node.nodeTable->join();
	this_thread::sleep_for(chrono::milliseconds(2000));
	clog << "NodeTable:\n" << *node.nodeTable.get() << endl;
}

BOOST_AUTO_TEST_CASE(test_udp_once)
{
	UDPDatagram d(bi::udp::endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 30300), bytes({65,65,65,65}));
	TestUDPSocket a; a.m_socket->connect(); a.start();
	a.m_socket->send(d);
	sleep(1);
	BOOST_REQUIRE_EQUAL(true, a.success);
}

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>code review<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file net.cpp
 * @author Alex Leverington <nessence@gmail.com>
 * @date 2014
 */

#include <boost/test/unit_test.hpp>
#include <libdevcore/Worker.h>
#include <libdevcrypto/Common.h>
#include <libp2p/UDP.h>
#include <libp2p/NodeTable.h>
using namespace std;
using namespace dev;
using namespace dev::p2p;
namespace ba = boost::asio;
namespace bi = ba::ip;

BOOST_AUTO_TEST_SUITE(p2p)

/**
 * Only used for testing. Not useful beyond tests.
 */
class TestHost: public Worker
{
public:
	TestHost(): Worker("test",0), m_io() {};
	virtual ~TestHost() { m_io.stop(); stopWorking(); }
	void start() { startWorking(); }
	void doWork() { m_io.run(); }
	void doneWorking() { m_io.reset(); m_io.poll(); m_io.reset(); }

protected:
	ba::io_service m_io;
};

struct TestNodeTable: public NodeTable
{
	/// Constructor
	using NodeTable::NodeTable;

	static std::vector<std::pair<KeyPair,unsigned>> createTestNodes(unsigned _count)
	{
		std::vector<std::pair<KeyPair,unsigned>> ret;
		asserts(_count < 1000);
		static uint16_t s_basePort = 30500;

		ret.clear();
		for (unsigned i = 0; i < _count; i++)
		{
			KeyPair k = KeyPair::create();
			ret.push_back(make_pair(k,s_basePort+i));
		}

		return std::move(ret);
	}

	void pingTestNodes(std::vector<std::pair<KeyPair,unsigned>> const& _testNodes)
	{
		bi::address ourIp = bi::address::from_string("127.0.0.1");
		for (auto& n: _testNodes)
		{
			ping(bi::udp::endpoint(ourIp, n.second));
			this_thread::sleep_for(chrono::milliseconds(2));
		}
	}

	void populateTestNodes(std::vector<std::pair<KeyPair,unsigned>> const& _testNodes, size_t _count = 0)
	{
		if (!_count)
			_count = _testNodes.size();

		bi::address ourIp = bi::address::from_string("127.0.0.1");
		for (auto& n: _testNodes)
			if (_count--)
				noteNode(n.first.pub(), bi::udp::endpoint(ourIp, n.second));
			else
				break;
	}

	void reset()
	{
		Guard l(x_state);
		for (auto& n: m_state) n.nodes.clear();
	}
};

/**
 * Only used for testing. Not useful beyond tests.
 */
struct TestNodeTableHost: public TestHost
{
	TestNodeTableHost(unsigned _count = 8): m_alias(KeyPair::create()), nodeTable(new TestNodeTable(m_io, m_alias)), testNodes(TestNodeTable::createTestNodes(_count)) {};
	~TestNodeTableHost() { m_io.stop(); stopWorking(); }

	void setup() { for (auto n: testNodes) nodeTables.push_back(make_shared<TestNodeTable>(m_io,n.first,n.second)); }

	void pingAll() { for (auto& t: nodeTables) t->pingTestNodes(testNodes); }

	void populateAll(size_t _count = 0) { for (auto& t: nodeTables) t->populateTestNodes(testNodes, _count); }

	void populate(size_t _count = 0) { nodeTable->populateTestNodes(testNodes, _count); }

	KeyPair m_alias;
	shared_ptr<TestNodeTable> nodeTable;
	std::vector<std::pair<KeyPair,unsigned>> testNodes; // keypair and port
	std::vector<shared_ptr<TestNodeTable>> nodeTables;
};

class TestUDPSocket: UDPSocketEvents, public TestHost
{
public:
	TestUDPSocket(): m_socket(new UDPSocket<TestUDPSocket, 1024>(m_io, *this, 30300)) {}

	void onDisconnected(UDPSocketFace*) {};
	void onReceived(UDPSocketFace*, bi::udp::endpoint const&, bytesConstRef _packet) { if (_packet.toString() == "AAAA") success = true; }

	shared_ptr<UDPSocket<TestUDPSocket, 1024>> m_socket;

	bool success = false;
};

BOOST_AUTO_TEST_CASE(test_neighbours_packet)
{
	KeyPair k = KeyPair::create();
	std::vector<std::pair<KeyPair,unsigned>> testNodes(TestNodeTable::createTestNodes(16));
	bi::udp::endpoint to(boost::asio::ip::address::from_string("127.0.0.1"), 30000);

	Neighbours out(to);
	for (auto n: testNodes)
	{
		Neighbours::Node node;
		node.ipAddress = boost::asio::ip::address::from_string("127.0.0.1").to_string();
		node.port = n.second;
		node.node = n.first.pub();
		out.nodes.push_back(node);
	}
	out.sign(k.sec());

	bytesConstRef packet(out.data.data(), out.data.size());
	bytesConstRef rlpBytes(packet.cropped(97, packet.size() - 97));
	Neighbours in = Neighbours::fromBytesConstRef(to, rlpBytes);
	int count = 0;
	for (auto n: in.nodes)
	{
		BOOST_REQUIRE_EQUAL(testNodes[count].second, n.port);
		BOOST_REQUIRE_EQUAL(testNodes[count].first.pub(), n.node);
		BOOST_REQUIRE_EQUAL(sha3(testNodes[count].first.pub()), sha3(n.node));
		count++;
	}
}

BOOST_AUTO_TEST_CASE(test_findnode_neighbours)
{
	// Executing findNode should result in a list which is serialized
	// into Neighbours packet. Neighbours packet should then be deserialized
	// into the same list of nearest nodes.
}

BOOST_AUTO_TEST_CASE(test_windows_template)
{
	bi::udp::endpoint ep;
	PingNode p(ep);
}

BOOST_AUTO_TEST_CASE(kademlia)
{
	// Not yet a 'real' test.
	TestNodeTableHost node(8);
	node.start();
	node.nodeTable->join(); // ideally, joining with empty node table logs warning we can check for
	node.setup();
	node.populate();
	clog << "NodeTable:\n" << *node.nodeTable.get() << endl;

	node.populateAll();
	clog << "NodeTable:\n" << *node.nodeTable.get() << endl;

	node.nodeTable->reset();
	clog << "NodeTable:\n" << *node.nodeTable.get() << endl;

	node.populate(1);
	clog << "NodeTable:\n" << *node.nodeTable.get() << endl;

	node.nodeTable->join();
	this_thread::sleep_for(chrono::milliseconds(2000));
	clog << "NodeTable:\n" << *node.nodeTable.get() << endl;
}

BOOST_AUTO_TEST_CASE(test_udp_once)
{
	UDPDatagram d(bi::udp::endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 30300), bytes({65,65,65,65}));
	TestUDPSocket a; a.m_socket->connect(); a.start();
	a.m_socket->send(d);
	sleep(1);
	BOOST_REQUIRE_EQUAL(true, a.success);
}

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before>// -*- c++ -*-
/* $Id$ */

/* Copyright (C) 1998-2002 The gtkmm Development Team
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <glibmm/class.h>
#include <glibmm/property.h>
#include <glibmm/ustring.h>
#include <glibmm/utility.h>

namespace Glib
{

void Class::register_derived_type(GType base_type)
{
  return register_derived_type(base_type, 0);
}

void Class::register_derived_type(GType base_type, GTypeModule* module)
{
  if(gtype_)
    return; // already initialized

  //0 is not a valid GType.
  //It would lead to a crash later.
  //We allow this, failing silently, to make life easier for gstreamermm.
  if(base_type == 0)
    return; // already initialized

  GTypeQuery base_query = { 0, 0, 0, 0, };
  g_type_query(base_type, &base_query);

  //GTypeQuery::class_size is guint but GTypeInfo::class_size is guint16.
  const guint16 class_size =
   (guint16)base_query.class_size;

  //GTypeQuery::instance_size is guint but GTypeInfo::instance_size is guint16.
  const guint16 instance_size =
   (guint16)base_query.instance_size;

  const GTypeInfo derived_info =
  {
    class_size,
    0, // base_init
    0, // base_finalize
    class_init_func_,
    0, // class_finalize
    0, // class_data
    instance_size,
    0, // n_preallocs
    0, // instance_init
    0, // value_table
  };

  if(!(base_query.type_name))
  {
    g_critical("Class::register_derived_type(): base_query.type_name is NULL.");
    return;
  }

  gchar* derived_name = g_strconcat("gtkmm__", base_query.type_name, (void*)0);

  if(module)
    gtype_ = g_type_module_register_type(module, base_type, derived_name, &derived_info, GTypeFlags(0));
  else
    gtype_ = g_type_register_static(base_type, derived_name, &derived_info, GTypeFlags(0));

  g_free(derived_name);
}

GType Class::clone_custom_type(const char* custom_type_name) const
{
  std::string full_name ("gtkmm__CustomObject_");
  Glib::append_canonical_typename(full_name, custom_type_name);

  GType custom_type = g_type_from_name(full_name.c_str());

  if(!custom_type)
  {
    g_return_val_if_fail(gtype_ != 0, 0);

    // Cloned custom types derive from the wrapper's parent type,
    // so that g_type_class_peek_parent() works correctly.
    const GType base_type = g_type_parent(gtype_);

    GTypeQuery base_query = { 0, 0, 0, 0, };
    g_type_query(base_type, &base_query);

    //GTypeQuery::class_size is guint but GTypeInfo::class_size is guint16.
    const guint16 class_size =
      (guint16)base_query.class_size;

    //GTypeQuery::instance_size is guint but GTypeInfo::instance_size is guint16.
    const guint16 instance_size =
      (guint16)base_query.instance_size;

    const GTypeInfo derived_info =
    {
      class_size,
      0, // base_init
      0, // base_finalize
      &Class::custom_class_init_function,
      0, // class_finalize
      this, // class_data
      instance_size,
      0, // n_preallocs
      0, // instance_init
      0, // value_table
    };

    custom_type = g_type_register_static(
        base_type, full_name.c_str(), &derived_info, GTypeFlags(0));
  }

  return custom_type;
}

// static
void Class::custom_class_init_function(void* g_class, void* class_data)
{
  // The class_data pointer is set to 'this' by clone_custom_type().
  const Class *const self = static_cast<Class*>(class_data);

  g_return_if_fail(self->class_init_func_ != 0);

  // Call the wrapper's class_init_function() to redirect
  // the vfunc and default signal handler callbacks.
  (*self->class_init_func_)(g_class, 0);

  GObjectClass *const gobject_class = static_cast<GObjectClass*>(g_class);
  gobject_class->get_property = &Glib::custom_get_property_callback;
  gobject_class->set_property = &Glib::custom_set_property_callback;
}

} // namespace Glib

<commit_msg>Add a comment<commit_after>// -*- c++ -*-
/* $Id$ */

/* Copyright (C) 1998-2002 The gtkmm Development Team
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <glibmm/class.h>
#include <glibmm/property.h>
#include <glibmm/ustring.h>
#include <glibmm/utility.h>

namespace Glib
{

void Class::register_derived_type(GType base_type)
{
  return register_derived_type(base_type, 0);
}

void Class::register_derived_type(GType base_type, GTypeModule* module)
{
  if(gtype_)
    return; // already initialized

  //0 is not a valid GType.
  //It would lead to a crash later.
  //We allow this, failing silently, to make life easier for gstreamermm.
  if(base_type == 0)
    return; // already initialized

  GTypeQuery base_query = { 0, 0, 0, 0, };
  g_type_query(base_type, &base_query);

  //GTypeQuery::class_size is guint but GTypeInfo::class_size is guint16.
  const guint16 class_size =
   (guint16)base_query.class_size;

  //GTypeQuery::instance_size is guint but GTypeInfo::instance_size is guint16.
  const guint16 instance_size =
   (guint16)base_query.instance_size;

  const GTypeInfo derived_info =
  {
    class_size,
    0, // base_init
    0, // base_finalize
    class_init_func_, //Set by the caller ( *_Class::init() ).
    0, // class_finalize
    0, // class_data
    instance_size,
    0, // n_preallocs
    0, // instance_init
    0, // value_table
  };

  if(!(base_query.type_name))
  {
    g_critical("Class::register_derived_type(): base_query.type_name is NULL.");
    return;
  }

  gchar* derived_name = g_strconcat("gtkmm__", base_query.type_name, (void*)0);

  if(module)
    gtype_ = g_type_module_register_type(module, base_type, derived_name, &derived_info, GTypeFlags(0));
  else
    gtype_ = g_type_register_static(base_type, derived_name, &derived_info, GTypeFlags(0));

  g_free(derived_name);
}

GType Class::clone_custom_type(const char* custom_type_name) const
{
  std::string full_name ("gtkmm__CustomObject_");
  Glib::append_canonical_typename(full_name, custom_type_name);

  GType custom_type = g_type_from_name(full_name.c_str());

  if(!custom_type)
  {
    g_return_val_if_fail(gtype_ != 0, 0);

    // Cloned custom types derive from the wrapper's parent type,
    // so that g_type_class_peek_parent() works correctly.
    const GType base_type = g_type_parent(gtype_);

    GTypeQuery base_query = { 0, 0, 0, 0, };
    g_type_query(base_type, &base_query);

    //GTypeQuery::class_size is guint but GTypeInfo::class_size is guint16.
    const guint16 class_size =
      (guint16)base_query.class_size;

    //GTypeQuery::instance_size is guint but GTypeInfo::instance_size is guint16.
    const guint16 instance_size =
      (guint16)base_query.instance_size;

    const GTypeInfo derived_info =
    {
      class_size,
      0, // base_init
      0, // base_finalize
      &Class::custom_class_init_function,
      0, // class_finalize
      this, // class_data
      instance_size,
      0, // n_preallocs
      0, // instance_init
      0, // value_table
    };

    custom_type = g_type_register_static(
        base_type, full_name.c_str(), &derived_info, GTypeFlags(0));
  }

  return custom_type;
}

// static
void Class::custom_class_init_function(void* g_class, void* class_data)
{
  // The class_data pointer is set to 'this' by clone_custom_type().
  const Class *const self = static_cast<Class*>(class_data);

  g_return_if_fail(self->class_init_func_ != 0);

  // Call the wrapper's class_init_function() to redirect
  // the vfunc and default signal handler callbacks.
  (*self->class_init_func_)(g_class, 0);

  GObjectClass *const gobject_class = static_cast<GObjectClass*>(g_class);
  gobject_class->get_property = &Glib::custom_get_property_callback;
  gobject_class->set_property = &Glib::custom_set_property_callback;
}

} // namespace Glib

<|endoftext|>


<commit_before>// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// 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 <gtest/gtest.h>

#include <string>
#include <memory>

#include "rclcpp/rclcpp.hpp"

#include "rcl_interfaces/msg/parameter_event.hpp"

class TestParameterClient : public ::testing::Test
{
public:
  void OnMessage(const rcl_interfaces::msg::ParameterEvent::SharedPtr event)
  {
    (void)event;
  }

protected:
  static void SetUpTestCase()
  {
    rclcpp::init(0, nullptr);
  }

  void SetUp()
  {
    node = std::make_shared<rclcpp::Node>("test_parameter_client", "/ns");
  }

  void TearDown()
  {
    node.reset();
  }

  rclcpp::Node::SharedPtr node;
};

/*
   Testing async parameter client construction and destruction.
 */
TEST_F(TestParameterClient, async_construction_and_destruction) {
  {
    auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(node);
    (void)asynchronous_client;
  }

  {
    auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(
      node->get_node_base_interface(),
      node->get_node_topics_interface(),
      node->get_node_graph_interface(),
      node->get_node_services_interface());
    (void)asynchronous_client;
  }

  {
    ASSERT_THROW(
    {
      auto asynchronous_client =
        std::make_shared<rclcpp::AsyncParametersClient>(node, "invalid_remote_node?");
      (void)asynchronous_client;
    }, rclcpp::exceptions::InvalidServiceNameError);
  }
}

/*
   Testing sync parameter client construction and destruction.
 */
TEST_F(TestParameterClient, sync_construction_and_destruction) {
  {
    auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(node);
    (void)synchronous_client;
  }

  {
    auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(
      std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
      node);
    (void)synchronous_client;
  }

  {
    auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(
      std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
      node->get_node_base_interface(),
      node->get_node_topics_interface(),
      node->get_node_graph_interface(),
      node->get_node_services_interface());
    (void)synchronous_client;
  }

  {
    ASSERT_THROW(
    {
      auto synchronous_client =
        std::make_shared<rclcpp::SyncParametersClient>(node, "invalid_remote_node?");
      (void)synchronous_client;
    }, rclcpp::exceptions::InvalidServiceNameError);
  }
}

/*
   Testing different methods for parameter event subscription from asynchronous clients.
 */
TEST_F(TestParameterClient, async_parameter_event_subscription) {
  auto callback = std::bind(&TestParameterClient::OnMessage, this, std::placeholders::_1);
  {
    auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(node);
    auto event_sub = asynchronous_client->on_parameter_event(callback);
    (void)event_sub;
  }

  {
    auto event_sub = rclcpp::AsyncParametersClient::on_parameter_event(node, callback);
    (void)event_sub;
  }

  {
    auto event_sub = rclcpp::AsyncParametersClient::on_parameter_event(
      node->get_node_topics_interface(),
      callback);
    (void)event_sub;
  }
}

/*
   Testing different methods for parameter event subscription from synchronous clients.
 */
TEST_F(TestParameterClient, sync_parameter_event_subscription) {
  auto callback = std::bind(&TestParameterClient::OnMessage, this, std::placeholders::_1);
  {
    auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(node);
    auto event_sub = synchronous_client->on_parameter_event(callback);
    (void)event_sub;
  }

  {
    auto event_sub = rclcpp::SyncParametersClient::on_parameter_event(node, callback);
    (void)event_sub;
  }

  {
    auto event_sub = rclcpp::SyncParametersClient::on_parameter_event(
      node->get_node_topics_interface(),
      callback);
    (void)event_sub;
  }
}
<commit_msg>fix style from #963<commit_after>// Copyright 2019 Open Source Robotics Foundation, Inc.
//
// 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 <gtest/gtest.h>

#include <string>
#include <memory>

#include "rclcpp/rclcpp.hpp"

#include "rcl_interfaces/msg/parameter_event.hpp"

class TestParameterClient : public ::testing::Test
{
public:
  void OnMessage(const rcl_interfaces::msg::ParameterEvent::SharedPtr event)
  {
    (void)event;
  }

protected:
  static void SetUpTestCase()
  {
    rclcpp::init(0, nullptr);
  }

  void SetUp()
  {
    node = std::make_shared<rclcpp::Node>("test_parameter_client", "/ns");
  }

  void TearDown()
  {
    node.reset();
  }

  rclcpp::Node::SharedPtr node;
};

/*
   Testing async parameter client construction and destruction.
 */
TEST_F(TestParameterClient, async_construction_and_destruction) {
  {
    auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(node);
    (void)asynchronous_client;
  }

  {
    auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(
      node->get_node_base_interface(),
      node->get_node_topics_interface(),
      node->get_node_graph_interface(),
      node->get_node_services_interface());
    (void)asynchronous_client;
  }

  {
    ASSERT_THROW(
    {
      auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(
        node, "invalid_remote_node?");
      (void)asynchronous_client;
    }, rclcpp::exceptions::InvalidServiceNameError);
  }
}

/*
   Testing sync parameter client construction and destruction.
 */
TEST_F(TestParameterClient, sync_construction_and_destruction) {
  {
    auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(node);
    (void)synchronous_client;
  }

  {
    auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(
      std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
      node);
    (void)synchronous_client;
  }

  {
    auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(
      std::make_shared<rclcpp::executors::SingleThreadedExecutor>(),
      node->get_node_base_interface(),
      node->get_node_topics_interface(),
      node->get_node_graph_interface(),
      node->get_node_services_interface());
    (void)synchronous_client;
  }

  {
    ASSERT_THROW(
    {
      auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(
        node, "invalid_remote_node?");
      (void)synchronous_client;
    }, rclcpp::exceptions::InvalidServiceNameError);
  }
}

/*
   Testing different methods for parameter event subscription from asynchronous clients.
 */
TEST_F(TestParameterClient, async_parameter_event_subscription) {
  auto callback = std::bind(&TestParameterClient::OnMessage, this, std::placeholders::_1);
  {
    auto asynchronous_client = std::make_shared<rclcpp::AsyncParametersClient>(node);
    auto event_sub = asynchronous_client->on_parameter_event(callback);
    (void)event_sub;
  }

  {
    auto event_sub = rclcpp::AsyncParametersClient::on_parameter_event(node, callback);
    (void)event_sub;
  }

  {
    auto event_sub = rclcpp::AsyncParametersClient::on_parameter_event(
      node->get_node_topics_interface(),
      callback);
    (void)event_sub;
  }
}

/*
   Testing different methods for parameter event subscription from synchronous clients.
 */
TEST_F(TestParameterClient, sync_parameter_event_subscription) {
  auto callback = std::bind(&TestParameterClient::OnMessage, this, std::placeholders::_1);
  {
    auto synchronous_client = std::make_shared<rclcpp::SyncParametersClient>(node);
    auto event_sub = synchronous_client->on_parameter_event(callback);
    (void)event_sub;
  }

  {
    auto event_sub = rclcpp::SyncParametersClient::on_parameter_event(node, callback);
    (void)event_sub;
  }

  {
    auto event_sub = rclcpp::SyncParametersClient::on_parameter_event(
      node->get_node_topics_interface(),
      callback);
    (void)event_sub;
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/sad_tab_helper.h"

#include "chrome/browser/browser_shutdown.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"

#if defined(OS_MACOSX)
#include "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h"
#elif defined(TOOLKIT_VIEWS)
#include "chrome/browser/ui/views/sad_tab_view.h"
#include "ui/views/widget/widget.h"
#elif defined(TOOLKIT_GTK)

#include <gtk/gtk.h>

#include "chrome/browser/tab_contents/chrome_web_contents_view_delegate_gtk.h"
#include "chrome/browser/ui/gtk/sad_tab_gtk.h"
#endif

using content::WebContents;

SadTabHelper::SadTabHelper(WebContents* web_contents)
    : content::WebContentsObserver(web_contents) {
  registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
                 content::Source<WebContents>(web_contents));
}

SadTabHelper::~SadTabHelper() {
}

void SadTabHelper::RenderViewGone(base::TerminationStatus status) {
  // Only show the sad tab if we're not in browser shutdown, so that TabContents
  // objects that are not in a browser (e.g., HTML dialogs) and thus are
  // visible do not flash a sad tab page.
  if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID)
    return;

  if (HasSadTab())
    return;

  InstallSadTab(status);
}

void SadTabHelper::Observe(int type,
                           const content::NotificationSource& source,
                           const content::NotificationDetails& details) {
  switch (type) {
    case content::NOTIFICATION_WEB_CONTENTS_CONNECTED:
      if (HasSadTab()) {
#if defined(OS_MACOSX)
        sad_tab_controller_mac::RemoveSadTab(sad_tab_.get());
#elif defined(TOOLKIT_VIEWS)
        sad_tab_->Close();
#elif defined(TOOLKIT_GTK)
        GtkWidget* expanded_container =
            ChromeWebContentsViewDelegateGtk::GetFor(web_contents())->
                expanded_container();
        gtk_container_remove(
            GTK_CONTAINER(expanded_container), sad_tab_->widget());
#else
#error Unknown platform
#endif
        sad_tab_.reset();
      }
      break;

    default:
      NOTREACHED() << "Got a notification we didn't register for.";
  }
}

void SadTabHelper::InstallSadTab(base::TerminationStatus status) {
#if defined(OS_MACOSX)
  sad_tab_.reset(
      sad_tab_controller_mac::CreateSadTabController(web_contents()));
#elif defined(TOOLKIT_VIEWS)
  SadTabView::Kind kind =
      status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
      SadTabView::KILLED : SadTabView::CRASHED;
  views::Widget::InitParams sad_tab_params(
      views::Widget::InitParams::TYPE_CONTROL);
  // It is not possible to create a native_widget_win that has no parent in
  // and later re-parent it.
  // TODO(avi): This is a cheat. Can this be made cleaner?
  sad_tab_params.parent = web_contents()->GetView()->GetNativeView();
  sad_tab_params.ownership =
      views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  sad_tab_.reset(new views::Widget);
  sad_tab_->Init(sad_tab_params);
  sad_tab_->SetContentsView(new SadTabView(web_contents(), kind));

  views::Widget::ReparentNativeView(
      sad_tab_->GetNativeView(), web_contents()->GetView()->GetNativeView());
  gfx::Rect bounds;
  web_contents()->GetView()->GetContainerBounds(&bounds);
  sad_tab_->SetBounds(gfx::Rect(bounds.size()));
#elif defined(TOOLKIT_GTK)
  sad_tab_.reset(new SadTabGtk(
      web_contents(),
      status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED
          ? SadTabGtk::KILLED
          : SadTabGtk::CRASHED));
  GtkWidget* expanded_container =
      ChromeWebContentsViewDelegateGtk::GetFor(web_contents())->
          expanded_container();
  gtk_container_add(GTK_CONTAINER(expanded_container), sad_tab_->widget());
  gtk_widget_show(sad_tab_->widget());
#else
#error Unknown platform
#endif
}

bool SadTabHelper::HasSadTab() {
  return sad_tab_.get() != NULL;
}
<commit_msg>Fix crash in TabContentsViewViews::Focus. This was caused by r125126. The subtle bug is that the SadTabHelper's Observe function use to reset TabContentsViewView's Widget pointer before it deleted the sad tab Widget. With my change, TabContentsViewWin would call SadTabHelper in the middle of its sad_tab_.reset() call and would use a Widget that's being destructed.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/sad_tab_helper.h"

#include "chrome/browser/browser_shutdown.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"

#if defined(OS_MACOSX)
#include "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h"
#elif defined(TOOLKIT_VIEWS)
#include "chrome/browser/ui/views/sad_tab_view.h"
#include "ui/views/widget/widget.h"
#elif defined(TOOLKIT_GTK)

#include <gtk/gtk.h>

#include "chrome/browser/tab_contents/chrome_web_contents_view_delegate_gtk.h"
#include "chrome/browser/ui/gtk/sad_tab_gtk.h"
#endif

using content::WebContents;

SadTabHelper::SadTabHelper(WebContents* web_contents)
    : content::WebContentsObserver(web_contents) {
  registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
                 content::Source<WebContents>(web_contents));
}

SadTabHelper::~SadTabHelper() {
}

void SadTabHelper::RenderViewGone(base::TerminationStatus status) {
  // Only show the sad tab if we're not in browser shutdown, so that TabContents
  // objects that are not in a browser (e.g., HTML dialogs) and thus are
  // visible do not flash a sad tab page.
  if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID)
    return;

  if (HasSadTab())
    return;

  InstallSadTab(status);
}

void SadTabHelper::Observe(int type,
                           const content::NotificationSource& source,
                           const content::NotificationDetails& details) {
  switch (type) {
    case content::NOTIFICATION_WEB_CONTENTS_CONNECTED:
      if (HasSadTab()) {
#if defined(OS_MACOSX)
        sad_tab_controller_mac::RemoveSadTab(sad_tab_.get());
#elif defined(TOOLKIT_VIEWS)
        sad_tab_->Close();
        // See http://crbug.com/117668. When the Widget is being destructed, we
        // want calls to sad_tab() to return NULL.
        scoped_ptr<views::Widget> local_sad_tab;
        local_sad_tab.swap(sad_tab_);
#elif defined(TOOLKIT_GTK)
        GtkWidget* expanded_container =
            ChromeWebContentsViewDelegateGtk::GetFor(web_contents())->
                expanded_container();
        gtk_container_remove(
            GTK_CONTAINER(expanded_container), sad_tab_->widget());
#else
#error Unknown platform
#endif
        sad_tab_.reset();
      }
      break;

    default:
      NOTREACHED() << "Got a notification we didn't register for.";
  }
}

void SadTabHelper::InstallSadTab(base::TerminationStatus status) {
#if defined(OS_MACOSX)
  sad_tab_.reset(
      sad_tab_controller_mac::CreateSadTabController(web_contents()));
#elif defined(TOOLKIT_VIEWS)
  SadTabView::Kind kind =
      status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
      SadTabView::KILLED : SadTabView::CRASHED;
  views::Widget::InitParams sad_tab_params(
      views::Widget::InitParams::TYPE_CONTROL);
  // It is not possible to create a native_widget_win that has no parent in
  // and later re-parent it.
  // TODO(avi): This is a cheat. Can this be made cleaner?
  sad_tab_params.parent = web_contents()->GetView()->GetNativeView();
  sad_tab_params.ownership =
      views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  sad_tab_.reset(new views::Widget);
  sad_tab_->Init(sad_tab_params);
  sad_tab_->SetContentsView(new SadTabView(web_contents(), kind));

  views::Widget::ReparentNativeView(
      sad_tab_->GetNativeView(), web_contents()->GetView()->GetNativeView());
  gfx::Rect bounds;
  web_contents()->GetView()->GetContainerBounds(&bounds);
  sad_tab_->SetBounds(gfx::Rect(bounds.size()));
#elif defined(TOOLKIT_GTK)
  sad_tab_.reset(new SadTabGtk(
      web_contents(),
      status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED
          ? SadTabGtk::KILLED
          : SadTabGtk::CRASHED));
  GtkWidget* expanded_container =
      ChromeWebContentsViewDelegateGtk::GetFor(web_contents())->
          expanded_container();
  gtk_container_add(GTK_CONTAINER(expanded_container), sad_tab_->widget());
  gtk_widget_show(sad_tab_->widget());
#else
#error Unknown platform
#endif
}

bool SadTabHelper::HasSadTab() {
  return sad_tab_.get() != NULL;
}
<|endoftext|>


<commit_before>// @(#)root/gpad:$Name:  $:$Id: TButton.cxx,v 1.2 2000/06/13 11:25:02 brun Exp $
// Author: Rene Brun   01/07/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <fstream.h>
#include "TROOT.h"
#include "TButton.h"
#include "TCanvas.h"
#include "TLatex.h"

#include <string.h>

ClassImp(TButton)

//______________________________________________________________________________
//  A TButton object is a user interface object.
//  A TButton has a name and an associated action.
//  When the button is clicked with the left mouse button, the cooresponding
//  action is executed.
//  A Tbutton can be created by direct invokation of the constructors
//  or via the graphics editor.
//  The Action can be set via TButton::SetMethod.
//  The action can be any command. Examples of actions:
//     "34+78" When the button is clicked, the result of addition is printed.
//     ".x macro.C" . Clicking the button executes the macro macro.C
//  The action can be modified at any time via TButton::SetMethod.
//
//  To modify the layout/size/contents of one or several buttons
//  in a canvas, you must set the canvas editable via TCanvas::SetEditable.
//  By default a TCanvas is editable.
//  By default a TDialogCanvas is not editable.
//  TButtons are in general placed in a TDialogCanvas.
//
//  A TButton being a TPad, one can draw graphics primitives in it
//  when the TCanvas/TDialogCanvas is editable.
//
//       Example of a macro creating a dialogcanvas with buttons
//void but() {
////   example of a dialogcanvas with a few buttons
//
//   TDialogCanvas *dialog = new TDialogCanvas("dialog","",200,300);
//
//// Create first button. Clicking on this button will execute 34+56
//   TButton *but1 = new TButton("button1","34+56",.05,.8,.45,.88);
//   but1->Draw();
//
//// Create second button. Clicking on this button will create a new canvas
//   TButton *but2 = new TButton("canvas","c2 = new TCanvas(\"c2\")",.55,.8,.95,.88);
//   but2->Draw();
//
//// Create third button. Clicking on this button will invoke the browser
//   but3 = new TButton("Browser","br = new TBrowser(\"br\")",0.25,0.54,0.75,0.64);
//   but3->SetFillColor(42);
//   but3->Draw();
//
//// Create last button with no name. Instead a graph is draw inside the button
//// Clicking on this button will invoke the macro tutorials/graph.C
//   button = new TButton("",".x tutorials/graph.C",0.15,0.15,0.85,0.38);
//   button->SetFillColor(42);
//   button->Draw();
//   button->cd();
//
//   Double_t x[8] = {0.08,0.21,0.34,0.48,0.61,0.7,0.81,0.92};
//   Double_t y[8] = {0.2,0.65,0.4,0.34,0.24,0.43,0.75,0.52};
//   TGraph *graph = new TGraph(8,x,y);
//   graph->SetMarkerColor(4);
//   graph->SetMarkerStyle(21);
//   graph->Draw("lp");
//
//   dialog->cd();
//}
//
//   Executing the macro above produces the following dialogcanvas
//Begin_Html
/*

*/
//End_Html

//______________________________________________________________________________
TButton::TButton(): TPad()
{
//*-*-*-*-*-*-*-*-*-*-*Button default constructor*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ==========================

   SetEditable(kFALSE);
}

//______________________________________________________________________________
TButton::TButton(const char *title, const char *method, Double_t x1, Double_t y1,Double_t x2, Double_t  y2)
           :TPad("button",title,x1,y1,x2,y2,18,2,1), TAttText(22,0,1,61,0.65)
{
//*-*-*-*-*-*-*-*-*-*-*Button normal constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  =========================
//
//   Note that the button coordinates x1,y1,x2,y2 are always in the range [0,1]
//
   //SetEditable(kFALSE);
   fFraming=0;
   SetBit(kCanDelete);
   fModified = kTRUE;
   fMethod = method;
   if (strlen(title)) {
      TLatex *text = new TLatex(0.5*(fX1+fX2),0.5*(fY1+fY2),title);
      fPrimitives->Add(text);
   }
   SetEditable(kFALSE);
}

//______________________________________________________________________________
TButton::~TButton()
{
//*-*-*-*-*-*-*-*-*-*-*Button default destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  =========================

   if (fPrimitives) fPrimitives->Delete();
}

//______________________________________________________________________________
void TButton::Draw(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this button with its current attributes*-*-*-*-*
//*-*                  ============================================

   AppendPad(option);
}

//______________________________________________________________________________
void TButton::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*-*Execute action corresponding to one event*-*-*-*
//*-*                  =========================================
//  This member function is called when a Button object is clicked.
//

   //check case where pressing a button deletes itself
   if (!TestBit(kNotDeleted)) return;

   if (IsEditable()) {
      TPad::ExecuteEvent(event,px,py);
      return;
   }

   TPad *cdpad = (TPad*)gROOT->GetSelectedPad();
   HideToolTip(event);

   switch (event) {

   case kMouseEnter:
      TPad::ExecuteEvent(event,px,py);
      break;

   case kButton1Down:
      SetBorderMode(-1);
      fFocused=1;
      Modified();
//      GetCanvas()->Modified();
      Update();
      break;

   case kMouseMotion:

      break;

   case kButton1Motion:
      if (px<XtoAbsPixel(1) && px>XtoAbsPixel(0) &&
          py<YtoAbsPixel(0) && py>YtoAbsPixel(1)) {
         if (!fFocused) {
            SetBorderMode(-1);
            fFocused=1;
            Modified();
            GetCanvas()->Modified();
            Update();
         }
      } else if (fFocused) {
         SetBorderMode(1);
         fFocused=0;
         Modified();
         GetCanvas()->Modified();
         Update();
      }
      break;

   case kButton1Up:
      SetCursor(kWatch);
      if (fFocused) {
         if (cdpad) cdpad->cd();
         gROOT->ProcessLine(GetMethod());
      }
      //check case where pressing a button deletes itself
     if (!TestBit(kNotDeleted)) return;
#ifndef WIN32
      SetBorderMode(1);
      Modified();
//      GetCanvas()->Modified();
      Update();
#else
      // The following instructions must be executed via the interpreter
      // Otherwise, we get a Thread problem under WindowsNT
      gROOT->ProcessLine(Form("((TButton*)0x%lx)->SetBorderMode(1);",(Long_t)this));
      gROOT->ProcessLine(Form("((TButton*)0x%lx)->Modified();",(Long_t)this));
      gROOT->ProcessLine(Form("((TButton*)0x%lx)->GetCanvas()->Modified();",(Long_t)this));
      gROOT->ProcessLine(Form("((TButton*)0x%lx)->Update();",(Long_t)this));
#endif
      SetCursor(kCross);
      break;
   }
}

//______________________________________________________________________________
void TButton::Paint(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*Paint this button with its current attributes*-*-*-*
//*-*                  =============================================

   TPad::Paint(option);  //only called for Postscript print
}

//______________________________________________________________________________
void TButton::PaintModified()
{
   TObject *obj = GetListOfPrimitives()->First();
   if (obj && obj->InheritsFrom("TText")) {
      TLatex *text = (TLatex*)obj;
//TVirtualPad *padsav = gPad;
//gPad = 0;
      text->SetTitle(GetTitle());
//gPad = padsav;
      text->SetTextSize(GetTextSize());
      text->SetTextFont(GetTextFont());
      text->SetTextAlign(GetTextAlign());
      text->SetTextColor(GetTextColor());
      text->SetTextAngle(GetTextAngle());
   }
   TPad::PaintModified();
}

//______________________________________________________________________________
void TButton::Range(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
{
//*-*-*-*-*-*-*-*-*-*-*Set world coordinate system for the pad*-*-*-*-*-*-*
//*-*                  =======================================

   TPad::Range(x1,y1,x2,y2);
}

//______________________________________________________________________________
void TButton::SavePrimitive(ofstream &out, Option_t *)
{
    // Save primitive as a C++ statement(s) on output stream out

   TPad *padsav = (TPad*)gPad;
   char quote = '"';
   if (gROOT->ClassSaved(TButton::Class())) {
       out<<"   ";
   } else {
       out<<"   TButton *";
   }
   out<<"button = new TButton("<<quote<<GetTitle()
      <<quote<<","<<quote<<GetMethod()<<quote
      <<","<<fXlowNDC
      <<","<<fYlowNDC
      <<","<<fXlowNDC+fWNDC
      <<","<<fYlowNDC+fHNDC
      <<");"<<endl;

   SaveFillAttributes(out,"button",0,1001);
   SaveLineAttributes(out,"button",1,1,1);
   SaveTextAttributes(out,"button",22,0,1,61,.65);

   if (GetBorderSize() != 2) {
      out<<"   button->SetBorderSize("<<GetBorderSize()<<");"<<endl;
   }
   if (GetBorderMode() != 1) {
      out<<"   button->SetBorderMode("<<GetBorderMode()<<");"<<endl;
   }

   if (GetFraming()) out<<"button->SetFraming();"<<endl;
   if (IsEditable()) out<<"button->SetEditable(kTRUE);"<<endl;

   out<<"   button->Draw();"<<endl;

   TIter next(GetListOfPrimitives());
   TObject *obj = next();  //do not save first primitive

   Int_t nprim = 0;
   while ((obj = next())) {
       if (!nprim) out<<"   button->cd();"<<endl;
       nprim++;
       obj->SavePrimitive(out, (Option_t *)next.GetOption());
   }

   if (nprim) out<<"   "<<padsav->GetName()<<"->cd();"<<endl;
   padsav->cd();
}

//______________________________________________________________________________
void TButton::SetFraming(Bool_t f)
{
// if framing is set, button will be highlighted

   fFraming=f;
   if (f) SetBit(kFraming);
   else   ResetBit(kFraming);
}
<commit_msg> In TButton::SavePrimitive insert a backslash in the printed button method in case the method includes double quotes.<commit_after>// @(#)root/gpad:$Name:  $:$Id: TButton.cxx,v 1.3 2001/05/28 06:21:47 brun Exp $
// Author: Rene Brun   01/07/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <fstream.h>
#include "TROOT.h"
#include "TButton.h"
#include "TCanvas.h"
#include "TLatex.h"

#include <string.h>

ClassImp(TButton)

//______________________________________________________________________________
//  A TButton object is a user interface object.
//  A TButton has a name and an associated action.
//  When the button is clicked with the left mouse button, the cooresponding
//  action is executed.
//  A Tbutton can be created by direct invokation of the constructors
//  or via the graphics editor.
//  The Action can be set via TButton::SetMethod.
//  The action can be any command. Examples of actions:
//     "34+78" When the button is clicked, the result of addition is printed.
//     ".x macro.C" . Clicking the button executes the macro macro.C
//  The action can be modified at any time via TButton::SetMethod.
//
//  To modify the layout/size/contents of one or several buttons
//  in a canvas, you must set the canvas editable via TCanvas::SetEditable.
//  By default a TCanvas is editable.
//  By default a TDialogCanvas is not editable.
//  TButtons are in general placed in a TDialogCanvas.
//
//  A TButton being a TPad, one can draw graphics primitives in it
//  when the TCanvas/TDialogCanvas is editable.
//
//       Example of a macro creating a dialogcanvas with buttons
//void but() {
////   example of a dialogcanvas with a few buttons
//
//   TDialogCanvas *dialog = new TDialogCanvas("dialog","",200,300);
//
//// Create first button. Clicking on this button will execute 34+56
//   TButton *but1 = new TButton("button1","34+56",.05,.8,.45,.88);
//   but1->Draw();
//
//// Create second button. Clicking on this button will create a new canvas
//   TButton *but2 = new TButton("canvas","c2 = new TCanvas(\"c2\")",.55,.8,.95,.88);
//   but2->Draw();
//
//// Create third button. Clicking on this button will invoke the browser
//   but3 = new TButton("Browser","br = new TBrowser(\"br\")",0.25,0.54,0.75,0.64);
//   but3->SetFillColor(42);
//   but3->Draw();
//
//// Create last button with no name. Instead a graph is draw inside the button
//// Clicking on this button will invoke the macro tutorials/graph.C
//   button = new TButton("",".x tutorials/graph.C",0.15,0.15,0.85,0.38);
//   button->SetFillColor(42);
//   button->Draw();
//   button->cd();
//
//   Double_t x[8] = {0.08,0.21,0.34,0.48,0.61,0.7,0.81,0.92};
//   Double_t y[8] = {0.2,0.65,0.4,0.34,0.24,0.43,0.75,0.52};
//   TGraph *graph = new TGraph(8,x,y);
//   graph->SetMarkerColor(4);
//   graph->SetMarkerStyle(21);
//   graph->Draw("lp");
//
//   dialog->cd();
//}
//
//   Executing the macro above produces the following dialogcanvas
//Begin_Html
/*

*/
//End_Html

//______________________________________________________________________________
TButton::TButton(): TPad()
{
//*-*-*-*-*-*-*-*-*-*-*Button default constructor*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ==========================

   SetEditable(kFALSE);
}

//______________________________________________________________________________
TButton::TButton(const char *title, const char *method, Double_t x1, Double_t y1,Double_t x2, Double_t  y2)
           :TPad("button",title,x1,y1,x2,y2,18,2,1), TAttText(22,0,1,61,0.65)
{
//*-*-*-*-*-*-*-*-*-*-*Button normal constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  =========================
//
//   Note that the button coordinates x1,y1,x2,y2 are always in the range [0,1]
//
   //SetEditable(kFALSE);
   fFraming=0;
   SetBit(kCanDelete);
   fModified = kTRUE;
   fMethod = method;
   if (strlen(title)) {
      TLatex *text = new TLatex(0.5*(fX1+fX2),0.5*(fY1+fY2),title);
      fPrimitives->Add(text);
   }
   SetEditable(kFALSE);
}

//______________________________________________________________________________
TButton::~TButton()
{
//*-*-*-*-*-*-*-*-*-*-*Button default destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  =========================

   if (fPrimitives) fPrimitives->Delete();
}

//______________________________________________________________________________
void TButton::Draw(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this button with its current attributes*-*-*-*-*
//*-*                  ============================================

   AppendPad(option);
}

//______________________________________________________________________________
void TButton::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*-*Execute action corresponding to one event*-*-*-*
//*-*                  =========================================
//  This member function is called when a Button object is clicked.
//

   //check case where pressing a button deletes itself
   if (!TestBit(kNotDeleted)) return;

   if (IsEditable()) {
      TPad::ExecuteEvent(event,px,py);
      return;
   }

   TPad *cdpad = (TPad*)gROOT->GetSelectedPad();
   HideToolTip(event);

   switch (event) {

   case kMouseEnter:
      TPad::ExecuteEvent(event,px,py);
      break;

   case kButton1Down:
      SetBorderMode(-1);
      fFocused=1;
      Modified();
//      GetCanvas()->Modified();
      Update();
      break;

   case kMouseMotion:

      break;

   case kButton1Motion:
      if (px<XtoAbsPixel(1) && px>XtoAbsPixel(0) &&
          py<YtoAbsPixel(0) && py>YtoAbsPixel(1)) {
         if (!fFocused) {
            SetBorderMode(-1);
            fFocused=1;
            Modified();
            GetCanvas()->Modified();
            Update();
         }
      } else if (fFocused) {
         SetBorderMode(1);
         fFocused=0;
         Modified();
         GetCanvas()->Modified();
         Update();
      }
      break;

   case kButton1Up:
      SetCursor(kWatch);
      if (fFocused) {
         if (cdpad) cdpad->cd();
         gROOT->ProcessLine(GetMethod());
      }
      //check case where pressing a button deletes itself
     if (!TestBit(kNotDeleted)) return;
#ifndef WIN32
      SetBorderMode(1);
      Modified();
//      GetCanvas()->Modified();
      Update();
#else
      // The following instructions must be executed via the interpreter
      // Otherwise, we get a Thread problem under WindowsNT
      gROOT->ProcessLine(Form("((TButton*)0x%lx)->SetBorderMode(1);",(Long_t)this));
      gROOT->ProcessLine(Form("((TButton*)0x%lx)->Modified();",(Long_t)this));
      gROOT->ProcessLine(Form("((TButton*)0x%lx)->GetCanvas()->Modified();",(Long_t)this));
      gROOT->ProcessLine(Form("((TButton*)0x%lx)->Update();",(Long_t)this));
#endif
      SetCursor(kCross);
      break;
   }
}

//______________________________________________________________________________
void TButton::Paint(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*Paint this button with its current attributes*-*-*-*
//*-*                  =============================================

   TPad::Paint(option);  //only called for Postscript print
}

//______________________________________________________________________________
void TButton::PaintModified()
{
   TObject *obj = GetListOfPrimitives()->First();
   if (obj && obj->InheritsFrom("TText")) {
      TLatex *text = (TLatex*)obj;
//TVirtualPad *padsav = gPad;
//gPad = 0;
      text->SetTitle(GetTitle());
//gPad = padsav;
      text->SetTextSize(GetTextSize());
      text->SetTextFont(GetTextFont());
      text->SetTextAlign(GetTextAlign());
      text->SetTextColor(GetTextColor());
      text->SetTextAngle(GetTextAngle());
   }
   TPad::PaintModified();
}

//______________________________________________________________________________
void TButton::Range(Double_t x1, Double_t y1, Double_t x2, Double_t y2)
{
//*-*-*-*-*-*-*-*-*-*-*Set world coordinate system for the pad*-*-*-*-*-*-*
//*-*                  =======================================

   TPad::Range(x1,y1,x2,y2);
}

//______________________________________________________________________________
void TButton::SavePrimitive(ofstream &out, Option_t *)
{
    // Save primitive as a C++ statement(s) on output stream out

   TPad *padsav = (TPad*)gPad;
   char quote = '"';
   if (gROOT->ClassSaved(TButton::Class())) {
       out<<"   ";
   } else {
       out<<"   TButton *";
   }
   char *cm = (char*)GetMethod();
   Int_t nch = strlen(cm);
   char *cmethod = new char[nch+10];
   Int_t i = 0;
   while(*cm) {
      if (*cm == '"') {
         cmethod[i] = '\\';
         i++;
      }
      cmethod[i] = *cm;
      i++;
      cm++;
   }
   cmethod[i] = 0;
   out<<"button = new TButton("<<quote<<GetTitle()
      <<quote<<","<<quote<<cmethod<<quote
      <<","<<fXlowNDC
      <<","<<fYlowNDC
      <<","<<fXlowNDC+fWNDC
      <<","<<fYlowNDC+fHNDC
      <<");"<<endl;
   delete [] cmethod;

   SaveFillAttributes(out,"button",0,1001);
   SaveLineAttributes(out,"button",1,1,1);
   SaveTextAttributes(out,"button",22,0,1,61,.65);

   if (GetBorderSize() != 2) {
      out<<"   button->SetBorderSize("<<GetBorderSize()<<");"<<endl;
   }
   if (GetBorderMode() != 1) {
      out<<"   button->SetBorderMode("<<GetBorderMode()<<");"<<endl;
   }

   if (GetFraming()) out<<"button->SetFraming();"<<endl;
   if (IsEditable()) out<<"button->SetEditable(kTRUE);"<<endl;

   out<<"   button->Draw();"<<endl;

   TIter next(GetListOfPrimitives());
   TObject *obj = next();  //do not save first primitive

   Int_t nprim = 0;
   while ((obj = next())) {
       if (!nprim) out<<"   button->cd();"<<endl;
       nprim++;
       obj->SavePrimitive(out, (Option_t *)next.GetOption());
   }

   if (nprim) out<<"   "<<padsav->GetName()<<"->cd();"<<endl;
   padsav->cd();
}

//______________________________________________________________________________
void TButton::SetFraming(Bool_t f)
{
// if framing is set, button will be highlighted

   fFraming=f;
   if (f) SetBit(kFraming);
   else   ResetBit(kFraming);
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	スケーリング（拡大、縮小）
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include <cstdint>
#include <cmath>
#include "common/vtx.hpp"
#include "graphics/color.hpp"
// #include <unordered_map>

namespace img {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	スケーリング・クラス
		@param[in]	RENDER	レンダー・クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class RENDER>
	class scaling {

		RENDER&		render_;

		struct xy_pad {
			uint32_t	r;
			uint32_t	g;
			uint32_t	b;
			uint32_t	cnt;
		};

//		typedef std::unordered_map<uint32_t, xy_pad> MAP;
//		MAP			map_;

#if 0
		static float sinc_(float l)
		{
			return std::sin(vtx::get_pi<float>() * l) / (vtx::get_pi<float>() * l);
		}

		static float lanczos_(float d, float n)
		{
			if(d == 0.0f) {
				return 1.0f;
			} else if(std::abs(d) >= n) {
				return 0.0f;
			} else {
				return sinc_(d) * sinc_(d / n);
			}
		}

		float lanczos_tbl_[(12 + 1) * (12 + 1)];
		float lanczos_n_;
		// -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0
		void init_lanczos_(float n)
		{
			if(lanczos_n_ == n) return;

			float y = -3.0f;
			for(int i = 0; i < (12 + 1); ++i) {
				float yl = lanczos_(y, n);
				float x = -3.0f;
				for(int j = 0; j < (12 + 1); ++j) {
					float xl = lanczos_(x, n);
					lanczos_tbl_[i * (12 + 1) + j] = xl * yl;
					x += 0.5f;
				}
				y += 0.5f;
			}
			lanczos_n_ = n;
		}

		float lanczos_t_(float x, float y, float n)
		{
			int i = static_cast<int>(y * 2.0f);
			i += 6;
			int j = static_cast<int>(x * 2.0f);
			j += 6;
			if(i >= 0 && i < (12 + 1) && j >= 0 && j < (12 + 1)) {
				return lanczos_tbl_[i * (12 + 1) + j];
			} else {
				return lanczos_(x, n) * lanczos_(y, n);
			}
		}
#endif

#if 0
	static void color_div_(const rgbaf& col, float total, rgba8& c)
	{
		rgbaf cc;
		if(total != 0.0f) {
			float sf = 1.0f / total;
			cc.r = col.r * sf;
			cc.g = col.g * sf;
			cc.b = col.b * sf;
			cc.a = col.a * sf;
		} else {
			cc = col;
		}

		if(cc.r < 0.0f) {
			c.r = 0;
		} else if(cc.r > 255.0f) {
			c.r = 255;
		} else {
			c.r = static_cast<unsigned char>(cc.r);
		}

		if(cc.g < 0.0f) {
			c.g = 0;
		} else if(cc.g > 255.0f) {
			c.g = 255;
		} else {
			c.g = static_cast<unsigned char>(cc.g);
		}

		if(cc.b < 0.0f) {
			c.b = 0;
		} else if(cc.b > 255.0f) {
			c.b = 255;
		} else {
			c.b = static_cast<unsigned char>(cc.b);
		}

		if(cc.a < 0.0f) {
			c.a = 0;
		} else if(cc.a > 255.0f) {
			c.a = 255;
		} else {
			c.a = static_cast<unsigned char>(cc.a);
		}
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	画像をリサイズする（lanczos-3 アルゴリズム）
		@param[in]	src	ソースのイメージ
		@param[out]	dst	リサイズイメージ
		@param[in]	scale	スケール・ファクター
	*/
	//-----------------------------------------------------------------//
	void resize_image(const i_img* src, img_rgba8& dst, float scale)
	{
		if(scale <= 0.0f) return;

		int sw = src->get_size().x;
		int sh = src->get_size().y;
		int dw = static_cast<int>(static_cast<float>(sw) * scale);
		int dh = static_cast<int>(static_cast<float>(sh) * scale);
		dst.create(vtx::spos(dw, dh), src->test_alpha());

		float n = 3.0f;
		init_lanczos_(n);

		float scn = 1.0f / scale;
		if(scale > 1.0f) {
			vtx::spos out;
			for(out.y = 0; out.y < dh; ++out.y) {
				float yy = (static_cast<float>(out.y) + 0.5f) * scn;
				int ys = static_cast<int>(yy - n);
				if(ys < 0) ys = 0;
				int ye = static_cast<int>(yy + n);
				if(ye > (sh - 1)) ye = sh - 1;
				for(out.x = 0; out.x < dw; ++out.x) {
					float xx = (static_cast<float>(out.x) + 0.5f) * scn;
					int xs = static_cast<int>(xx - n);
					if(xs < 0) xs = 0;
					int xe = static_cast<int>(xx + n);
					if(xe > (sw - 1)) xe = sw - 1;

					rgbaf col(0.0f);
					float weight_total = 0.0f;
					vtx::spos pos;
					for(pos.y = ys; pos.y <= ye; ++pos.y) {
						float yl = fabs((pos.y + 0.5f) - yy);
						for(pos.x = xs; pos.x <= xe; ++pos.x) {
							float xl = std::abs((static_cast<float>(pos.x) + 0.5f) - xx);
							float weight = lanczos_t_(xl, yl, n);
							rgba8 c;
							src->get_pixel(pos, c);
							col.r += c.r * weight;
							col.g += c.g * weight;
							col.b += c.b * weight;
							col.a += c.a * weight;
							weight_total += weight;
						}
					}
					rgba8 c;
					color_div_(col, weight_total, c);
					dst.put_pixel(out, c);
				}
			}
		} else {
			vtx::spos out;
			for(out.y = 0; out.y < dh; ++out.y) {
				float yy = static_cast<float>(out.y) + 0.5f;
				int ys = static_cast<int>((yy - n) * scn);
				if(ys < 0) ys = 0;
				int ye = static_cast<int>((yy + n) * scn);
				if(ye > (sh - 1)) ye = sh - 1;
				for(out.x = 0; out.x < dw; ++out.x) {
					float xx = static_cast<float>(out.x) + 0.5f;
					int xs = static_cast<int>((xx - n) * scn);
					if(xs < 0) xs = 0;
					int xe = static_cast<int>((xx + n) * scn);
					if(xe > (sw - 1)) xe = sw - 1;

					rgbaf col(0.0f);
					float weight_total = 0.0f;
					vtx::spos pos;
					for(pos.y = ys; pos.y <= ye; ++pos.y) {
						float yl = std::abs(((static_cast<float>(pos.y) + 0.5f) * scale) - yy);
						for(pos.x = xs; pos.x <= xe; ++pos.x) {
							float xl = std::abs(((static_cast<float>(pos.x) + 0.5f) * scale) - xx);
							float weight = lanczos_t_(xl, yl, n);
							rgba8 c;
							src->get_pixel(pos, c);
							col.r += static_cast<float>(c.r) * weight;
							col.g += static_cast<float>(c.g) * weight;
							col.b += static_cast<float>(c.b) * weight;
							col.a += static_cast<float>(c.a) * weight;
							weight_total += weight;
						}
					}
					rgba8 c;
					color_div_(col, weight_total, c);
					dst.put_pixel(out, c);
				}
			}
		}
	}
#endif

		vtx::spos	ofs_;
		struct step_t {
			int32_t	up;
			int32_t	dn;
			step_t(uint32_t u = 1, uint32_t d = 1) noexcept : up(u), dn(d) { }
		};
		step_t		scale_;

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクタ
			@param[in]	render	レンダークラス（参照）
		*/
		//-----------------------------------------------------------------//
		scaling(RENDER& render) noexcept : render_(render),
//			lanczos_n_(0.0f),
			ofs_(0), scale_()
		{ }

		//-----------------------------------------------------------------//
		/*!
			@brief	オフセットを設定
			@param[in]	ofs	オフセット
		*/
		//-----------------------------------------------------------------//
		void set_offset(const vtx::spos& ofs = vtx::spos(0)) noexcept { ofs_ = ofs; }

		//-----------------------------------------------------------------//
		/*!
			@brief	スケールを設定
			@param[in]	up		分子
			@param[in]	dn		分母
		*/
		//-----------------------------------------------------------------//
		void set_scale(uint32_t up = 1, uint32_t dn = 1) noexcept { scale_ = step_t(up, dn); }

		//-----------------------------------------------------------------//
		/*!
			@brief	描画ファンクタ
			@param[in]	x	X 座標
			@param[in]	y	Y 座標
			@param[in]	r	R カラー
			@param[in]	g	G カラー
			@param[in]	b	B カラー
		*/
		//-----------------------------------------------------------------//
		void operator() (int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) noexcept
		{
			if(a == 0) return;

			auto sc = graphics::share_color(r, g, b);
			if(scale_.up < scale_.dn) {
				if(sc.rgb565 == 0) sc = graphics::share_color(0, 0, 1);
				auto xx = x * scale_.up / scale_.dn;
				auto yy = y * scale_.up / scale_.dn;
				auto rc = render_.get_plot(vtx::spos(xx + ofs_.x, yy + ofs_.y));
				if(rc == 0) {
					render_.plot(vtx::spos(xx + ofs_.x, yy + ofs_.y), sc.rgb565);
				} else {
					auto nc = graphics::share_color::color_sum(sc.rgb565, rc);
					render_.plot(vtx::spos(xx + ofs_.x, yy + ofs_.y), nc);
				}
			} else if(scale_.up > scale_.dn) {
				auto d  = (scale_.up + (scale_.dn - 1)) / scale_.dn;
				auto xx = x * scale_.up / scale_.dn;
				auto yy = y * scale_.up / scale_.dn;
				render_.set_fore_color(sc);
				render_.fill_box(vtx::srect(xx + ofs_.x, yy + ofs_.y, d, d));
			} else {
				if(a == 255) {
					render_.plot(vtx::spos(x + ofs_.x, y + ofs_.y), sc.rgb565);
				} else {
// utils::format("Alpha: %d\n") % static_cast<int>(a);
					auto rc = render_.get_plot(vtx::spos(x + ofs_.x, y + ofs_.y));
					auto ac = graphics::share_color::conv_rgba8(rc);
					auto t = graphics::share_color::blend(ac, graphics::rgba8_t(r, g, b, a));
					auto dc = graphics::share_color(t.r, t.g, t.b);
					render_.plot(vtx::spos(x + ofs_.x, y + ofs_.y), dc.rgb565);
				}
			}
#if 0
			uint32_t key = static_cast<uint16_t>(xx) | (static_cast<uint16_t>(yy) << 16);
			auto it = map_.find(key);
			if(it != map_.end()) {
//				it->first.r += r;
//				it->first.g += g;
//				it->first.b += b;
//				++it->first.cnt;
//				if(it->first.cnt >= 4) {
//					auto c = RENDER::COLOR::rgb(r, g, b);
//					render_.plot(xx + ofs_.x, yy + ofs_.y, c);
//				}
			} else {
				map_.emplace(r, g, b, 1);
			}
#endif
		}
	};
}
<commit_msg>Update: cleanup<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	スケーリング（拡大、縮小）
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include <cstdint>
#include <cmath>
#include "common/vtx.hpp"
#include "graphics/color.hpp"
// #include <unordered_map>

namespace img {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	スケーリング・クラス
		@param[in]	RENDER	レンダー・クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class RENDER>
	class scaling {

		RENDER&		render_;

		struct xy_pad {
			uint32_t	r;
			uint32_t	g;
			uint32_t	b;
			uint32_t	cnt;
		};

//		typedef std::unordered_map<uint32_t, xy_pad> MAP;
//		MAP			map_;

#if 0
		static float sinc_(float l)
		{
			return std::sin(vtx::get_pi<float>() * l) / (vtx::get_pi<float>() * l);
		}

		static float lanczos_(float d, float n)
		{
			if(d == 0.0f) {
				return 1.0f;
			} else if(std::abs(d) >= n) {
				return 0.0f;
			} else {
				return sinc_(d) * sinc_(d / n);
			}
		}

		float lanczos_tbl_[(12 + 1) * (12 + 1)];
		float lanczos_n_;
		// -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0
		void init_lanczos_(float n)
		{
			if(lanczos_n_ == n) return;

			float y = -3.0f;
			for(int i = 0; i < (12 + 1); ++i) {
				float yl = lanczos_(y, n);
				float x = -3.0f;
				for(int j = 0; j < (12 + 1); ++j) {
					float xl = lanczos_(x, n);
					lanczos_tbl_[i * (12 + 1) + j] = xl * yl;
					x += 0.5f;
				}
				y += 0.5f;
			}
			lanczos_n_ = n;
		}

		float lanczos_t_(float x, float y, float n)
		{
			int i = static_cast<int>(y * 2.0f);
			i += 6;
			int j = static_cast<int>(x * 2.0f);
			j += 6;
			if(i >= 0 && i < (12 + 1) && j >= 0 && j < (12 + 1)) {
				return lanczos_tbl_[i * (12 + 1) + j];
			} else {
				return lanczos_(x, n) * lanczos_(y, n);
			}
		}
#endif

#if 0
	static void color_div_(const rgbaf& col, float total, rgba8& c)
	{
		rgbaf cc;
		if(total != 0.0f) {
			float sf = 1.0f / total;
			cc.r = col.r * sf;
			cc.g = col.g * sf;
			cc.b = col.b * sf;
			cc.a = col.a * sf;
		} else {
			cc = col;
		}

		if(cc.r < 0.0f) {
			c.r = 0;
		} else if(cc.r > 255.0f) {
			c.r = 255;
		} else {
			c.r = static_cast<unsigned char>(cc.r);
		}

		if(cc.g < 0.0f) {
			c.g = 0;
		} else if(cc.g > 255.0f) {
			c.g = 255;
		} else {
			c.g = static_cast<unsigned char>(cc.g);
		}

		if(cc.b < 0.0f) {
			c.b = 0;
		} else if(cc.b > 255.0f) {
			c.b = 255;
		} else {
			c.b = static_cast<unsigned char>(cc.b);
		}

		if(cc.a < 0.0f) {
			c.a = 0;
		} else if(cc.a > 255.0f) {
			c.a = 255;
		} else {
			c.a = static_cast<unsigned char>(cc.a);
		}
	}

	//-----------------------------------------------------------------//
	/*!
		@brief	画像をリサイズする（lanczos-3 アルゴリズム）
		@param[in]	src	ソースのイメージ
		@param[out]	dst	リサイズイメージ
		@param[in]	scale	スケール・ファクター
	*/
	//-----------------------------------------------------------------//
	void resize_image(const i_img* src, img_rgba8& dst, float scale)
	{
		if(scale <= 0.0f) return;

		int sw = src->get_size().x;
		int sh = src->get_size().y;
		int dw = static_cast<int>(static_cast<float>(sw) * scale);
		int dh = static_cast<int>(static_cast<float>(sh) * scale);
		dst.create(vtx::spos(dw, dh), src->test_alpha());

		float n = 3.0f;
		init_lanczos_(n);

		float scn = 1.0f / scale;
		if(scale > 1.0f) {
			vtx::spos out;
			for(out.y = 0; out.y < dh; ++out.y) {
				float yy = (static_cast<float>(out.y) + 0.5f) * scn;
				int ys = static_cast<int>(yy - n);
				if(ys < 0) ys = 0;
				int ye = static_cast<int>(yy + n);
				if(ye > (sh - 1)) ye = sh - 1;
				for(out.x = 0; out.x < dw; ++out.x) {
					float xx = (static_cast<float>(out.x) + 0.5f) * scn;
					int xs = static_cast<int>(xx - n);
					if(xs < 0) xs = 0;
					int xe = static_cast<int>(xx + n);
					if(xe > (sw - 1)) xe = sw - 1;

					rgbaf col(0.0f);
					float weight_total = 0.0f;
					vtx::spos pos;
					for(pos.y = ys; pos.y <= ye; ++pos.y) {
						float yl = fabs((pos.y + 0.5f) - yy);
						for(pos.x = xs; pos.x <= xe; ++pos.x) {
							float xl = std::abs((static_cast<float>(pos.x) + 0.5f) - xx);
							float weight = lanczos_t_(xl, yl, n);
							rgba8 c;
							src->get_pixel(pos, c);
							col.r += c.r * weight;
							col.g += c.g * weight;
							col.b += c.b * weight;
							col.a += c.a * weight;
							weight_total += weight;
						}
					}
					rgba8 c;
					color_div_(col, weight_total, c);
					dst.put_pixel(out, c);
				}
			}
		} else {
			vtx::spos out;
			for(out.y = 0; out.y < dh; ++out.y) {
				float yy = static_cast<float>(out.y) + 0.5f;
				int ys = static_cast<int>((yy - n) * scn);
				if(ys < 0) ys = 0;
				int ye = static_cast<int>((yy + n) * scn);
				if(ye > (sh - 1)) ye = sh - 1;
				for(out.x = 0; out.x < dw; ++out.x) {
					float xx = static_cast<float>(out.x) + 0.5f;
					int xs = static_cast<int>((xx - n) * scn);
					if(xs < 0) xs = 0;
					int xe = static_cast<int>((xx + n) * scn);
					if(xe > (sw - 1)) xe = sw - 1;

					rgbaf col(0.0f);
					float weight_total = 0.0f;
					vtx::spos pos;
					for(pos.y = ys; pos.y <= ye; ++pos.y) {
						float yl = std::abs(((static_cast<float>(pos.y) + 0.5f) * scale) - yy);
						for(pos.x = xs; pos.x <= xe; ++pos.x) {
							float xl = std::abs(((static_cast<float>(pos.x) + 0.5f) * scale) - xx);
							float weight = lanczos_t_(xl, yl, n);
							rgba8 c;
							src->get_pixel(pos, c);
							col.r += static_cast<float>(c.r) * weight;
							col.g += static_cast<float>(c.g) * weight;
							col.b += static_cast<float>(c.b) * weight;
							col.a += static_cast<float>(c.a) * weight;
							weight_total += weight;
						}
					}
					rgba8 c;
					color_div_(col, weight_total, c);
					dst.put_pixel(out, c);
				}
			}
		}
	}
#endif

		vtx::spos	ofs_;
		struct step_t {
			int32_t	up;
			int32_t	dn;
			step_t(uint32_t u = 1, uint32_t d = 1) noexcept : up(u), dn(d) { }
		};
		step_t		scale_;

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクタ
			@param[in]	render	レンダークラス（参照）
		*/
		//-----------------------------------------------------------------//
		scaling(RENDER& render) noexcept : render_(render),
//			lanczos_n_(0.0f),
			ofs_(0), scale_()
		{ }

		//-----------------------------------------------------------------//
		/*!
			@brief	オフセットを設定
			@param[in]	ofs	オフセット
		*/
		//-----------------------------------------------------------------//
		void set_offset(const vtx::spos& ofs = vtx::spos(0)) noexcept { ofs_ = ofs; }

		//-----------------------------------------------------------------//
		/*!
			@brief	スケールを設定
			@param[in]	up		分子
			@param[in]	dn		分母
		*/
		//-----------------------------------------------------------------//
		void set_scale(uint32_t up = 1, uint32_t dn = 1) noexcept { scale_ = step_t(up, dn); }

		//-----------------------------------------------------------------//
		/*!
			@brief	描画ファンクタ
			@param[in]	x	X 座標
			@param[in]	y	Y 座標
			@param[in]	r	R カラー
			@param[in]	g	G カラー
			@param[in]	b	B カラー
		*/
		//-----------------------------------------------------------------//
		void operator() (int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) noexcept
		{
			if(a == 0) return;

			auto sc = graphics::share_color(r, g, b);
			if(scale_.up < scale_.dn) {
				if(sc.rgb565 == 0) sc = graphics::share_color(0, 0, 1);
				auto xx = x * scale_.up / scale_.dn;
				auto yy = y * scale_.up / scale_.dn;
				auto rc = render_.get_plot(vtx::spos(xx + ofs_.x, yy + ofs_.y));
				if(rc == 0) {
					render_.plot(vtx::spos(xx + ofs_.x, yy + ofs_.y), sc.rgb565);
				} else {
					if(a == 255) {
						auto nc = graphics::share_color::color_sum(sc.rgb565, rc);
						render_.plot(vtx::spos(xx + ofs_.x, yy + ofs_.y), nc);
					} else {
						auto ac = graphics::share_color::conv_rgba8(rc);
						auto t = graphics::share_color::blend(ac, graphics::rgba8_t(r, g, b, a));
						auto dc = graphics::share_color(t.r, t.g, t.b);
						render_.plot(vtx::spos(x + ofs_.x, y + ofs_.y), dc.rgb565);
					}
				}
			} else if(scale_.up > scale_.dn) {
				auto d  = (scale_.up + (scale_.dn - 1)) / scale_.dn;
				auto xx = x * scale_.up / scale_.dn;
				auto yy = y * scale_.up / scale_.dn;
				render_.set_fore_color(sc);
				render_.fill_box(vtx::srect(xx + ofs_.x, yy + ofs_.y, d, d));
			} else {
				if(a == 255) {
					render_.plot(vtx::spos(x + ofs_.x, y + ofs_.y), sc.rgb565);
				} else {
					auto rc = render_.get_plot(vtx::spos(x + ofs_.x, y + ofs_.y));
					auto ac = graphics::share_color::conv_rgba8(rc);
					auto t = graphics::share_color::blend(ac, graphics::rgba8_t(r, g, b, a));
					auto dc = graphics::share_color(t.r, t.g, t.b);
					render_.plot(vtx::spos(x + ofs_.x, y + ofs_.y), dc.rgb565);
				}
			}
#if 0
			uint32_t key = static_cast<uint16_t>(xx) | (static_cast<uint16_t>(yy) << 16);
			auto it = map_.find(key);
			if(it != map_.end()) {
//				it->first.r += r;
//				it->first.g += g;
//				it->first.b += b;
//				++it->first.cnt;
//				if(it->first.cnt >= 4) {
//					auto c = RENDER::COLOR::rgb(r, g, b);
//					render_.plot(xx + ofs_.x, yy + ofs_.y, c);
//				}
			} else {
				map_.emplace(r, g, b, 1);
			}
#endif
		}
	};
}
<|endoftext|>


<commit_before>#pragma once

#include "../util.hpp"

using Point = complex<ld>;
using Polygon = vector<Point>;

const ld eps = 1e-10;

Point at(const Polygon &g, int i) {
  i %= (int)g.size();
  return g[i < 0 ? i + g.size() : i];
}

bool comp(Point a, Point b) { return real(a - b) * 1.347589 + imag(a - b) > 0; }

ld dot(Point a, Point b) { return real(conj(a) * b); }
ld cross(Point a, Point b) { return imag(conj(a) * b); }

struct Segment {
  Point a, b;
  Segment(Point p, Point q) : a(p), b(q) { ; }
};

struct Line {
  Point a, b;
  Line(Point p, Point q) : a(p), b(q) { ; }
  explicit Line(Segment s) : a(s.a), b(s.b) { ; }
};

struct Circle {
  Point p;
  ld r;
  Circle(Point a, ld b) : p(a), r(b) { ; }
};

// counter clockwise
int ccw(Point a, Point b, Point c) {
  b -= a;
  c -= a;
  if (cross(b, c) > eps) return 1;    // counter clockwise
  if (cross(b, c) < -eps) return -1;  // clockwise
  if (dot(b, c) < 0) return 2;        // c--a--b on line
  if (norm(b) < norm(c)) return -2;   // a--b--c on line
  return 0;                           // a--c--b on line
}

vector<Point> unique(vector<Point> ps) {
  sort(begin(ps), end(ps), comp);
  vector<Point> res;
  for (Point p : ps)
    if (res.empty() || abs(res.back() - p) > eps) res.push_back(p);
  return res;
}
<commit_msg>Add definition of point<commit_after>#pragma once

#include "../template/const_value.hpp"
#include "../template/float_torelance.hpp"
#include "../template/includes.hpp"

template <typename real_t> using Vector = std::complex<real_t>;

template <typename real_t> class Point {
  std::complex<real_t> p;
  Point() : p(0.0, 0.0) { ; }
  Point(std::complex<real_t> p_) : p(p_) { ; }
  Point(real_t x, real_t y) : p(x, y) { ; }
  Vector<real_t> operator-(const Point &r){ return p - r.p } Point
  operator+(const Vector<real_t> &r){ return p + r.p } Point
  operator-(const Vector<real_t> &r) {
    return p - r.p
  }
};

template <typename real_t>
std::istream &operator>>(std::istream &is, Point<real_t> &p) {
  is >> x.p.real() >> x.p.imag();
  return is;
}

template <typename float_type, const float_type &eps>
std::ostream &operator<<(std::ostream &os, const Point<real_t> &p) {
  os << x.p.real() << " " << x.p.imag();
  return os;
}

template <typename point_t> class Polygon {
  std::vector<point_t> g;
  Polygon() : g(0) { ; }
  Polygon(const int n) : g(n, point_t()) { ; }
  Polygon(const std::vector<point_t> &g_) : g(g_) { ; }
  void push_back(const point_t &p) { g.push_back(p); }
  point_t &front() { return g.front(); }
  point_t &back() { return g.back(); }
  int size() const { return g.size(); }
  point_t &operator[](int i) {
    i %= size();
    return g[i < 0 ? i + size() : i];
  }
};

// ld dot(Point a, Point b) { return real(conj(a) * b); }
// ld cross(Point a, Point b) { return imag(conj(a) * b); }

// // counter clockwise
// int ccw(Point a, Point b, Point c) {
//   b -= a;
//   c -= a;
//   if (cross(b, c) > 0) return 1;    // counter clockwise
//   else if (cross(b, c) < 0) return -1;  // clockwise
//   else if (dot(b, c) < 0) return 2;        // c--a--b on line
//   else if (norm(b) < norm(c)) return -2;   // a--b--c on line
//   else return 0;                           // a--c--b on line
// }

// std::vector<Point> unique(std::vector<Point> ps) {
//   std::sort(std::begin(ps), std::end(ps), comp);
//   std::vector<Point> res;
//   for (Point p : ps)
//     if (res.empty() || std::abs(res.back() - p) != 0) res.push_back(p);
//   return res;
// }
<|endoftext|>


<commit_before>/*
 * This provides specialized C runtime startup for our memory map.
 */

#include "runtime/startup.h"

#include "lib/common/attribute_macros.h"

#include "lib/armv7m/types.h"
#include "lib/armv7m/instructions.h"
#include "lib/armv7m/scb.h"

#include "lib/stm32f4xx/rcc.h"
#include "lib/stm32f4xx/syscfg.h"

using armv7m::Word;
using armv7m::scb;

using stm32f4xx::ApbPeripheral;
using stm32f4xx::rcc;
using stm32f4xx::SysCfg;
using stm32f4xx::syscfg;

typedef void (*InitFnPtr)();

/*
 * These symbols are provided by the linker script.
 */
extern "C" {
  // Start of image to be copied.
  extern Word _sram_image_start;
  // End of image to be copied.
  extern Word _sram_image_end;
  // Destination for copy (RAM).
  extern Word _sram_image_dest;

  // Start/end of memory to be zeroed.
  extern Word _bss_start, _bss_end;

  // Start/end of initializer arrays.
  extern InitFnPtr _preinit_array_start, _preinit_array_end;
  extern InitFnPtr _init_array_start, _init_array_end;

  // Generated initializer function.
  extern void _init();

  // Init epilogue, defined below, called implicitly.
  void init_epilogue();
}

void crt_init() {
  // Enable fault reporting.
  armv7m::scb.write_shcsr(armv7m::scb.read_shcsr()
                          .with_memfaultena(true)
                          .with_busfaultena(true)
                          .with_usgfaultena(true));

  // Enable floating point automatic/lazy state preservation.
  // The CONTROL bit governing FP will be set automatically when first used.
  armv7m::scb_fp.write_fpccr(armv7m::scb_fp.read_fpccr()
                             .with_aspen(true)
                             .with_lspen(true));
  armv7m::instruction_synchronization_barrier();  // Now please.

  // Enable access to the floating point coprocessor.
  armv7m::scb.write_cpacr(armv7m::scb.read_cpacr()
                          .with_cp11(armv7m::Scb::CpAccess::full)
                          .with_cp10(armv7m::Scb::CpAccess::full));

  // It is now safe to use floating point.

  // Remap SRAM.
  // Power on syscfg, so we can mess with its registers.
  rcc.enable_clock(ApbPeripheral::syscfg);

  // VTOR starts out at zero, which points to Flash and is good.
  // But now things are about to change.
  // Interrupts are disabled, but to be safe in case we fault (due to a bug),
  // go ahead and give VTOR the true address of the Flash table.
  scb.write_vtor(reinterpret_cast<unsigned>(&_sram_image_dest));
  armv7m::data_synchronization_barrier();  // Write it now.
  armv7m::instruction_synchronization_barrier();  // Flush pipeline just in case

  // Remap!
  auto mode = SysCfg::memrmp_value_t::mem_mode_t::embedded_sram;
  syscfg.write_memrmp(syscfg.read_memrmp()
                      .with_mem_mode(mode));
  armv7m::data_synchronization_barrier();  // Write it now.
  armv7m::instruction_synchronization_barrier();  // Flush pipeline just in cas

  // Copy image into SRAM.
  for (Word *src = &_sram_image_start, *dest = &_sram_image_dest;
       src != &_sram_image_end;
       ++src, ++dest) {
    *dest = *src;
  }

  // Zero BSS.
  for (Word *dest = &_bss_start; dest != &_bss_end; ++dest) {
    *dest = 0;
  }

  // Run the funky three-phase init process.
  for (InitFnPtr *f = &_preinit_array_start; f != &_preinit_array_end; ++f) {
    (*f)();
  }

  _init();

  for (InitFnPtr *f = &_init_array_start; f != &_init_array_end; ++f) {
    (*f)();
  }
}

SECTION(".init_prologue")
NAKED void _init() {
  asm volatile ("push {r4-r11, lr}");
}

SECTION(".init_epilogue")
NAKED void init_epilogue() {
  asm volatile ("pop {r4-r11, pc}");
}
<commit_msg>runtime: move ISB in FPU initialization.<commit_after>/*
 * This provides specialized C runtime startup for our memory map.
 */

#include "runtime/startup.h"

#include "lib/common/attribute_macros.h"

#include "lib/armv7m/types.h"
#include "lib/armv7m/instructions.h"
#include "lib/armv7m/scb.h"

#include "lib/stm32f4xx/rcc.h"
#include "lib/stm32f4xx/syscfg.h"

using armv7m::Word;
using armv7m::scb;

using stm32f4xx::ApbPeripheral;
using stm32f4xx::rcc;
using stm32f4xx::SysCfg;
using stm32f4xx::syscfg;

typedef void (*InitFnPtr)();

/*
 * These symbols are provided by the linker script.
 */
extern "C" {
  // Start of image to be copied.
  extern Word _sram_image_start;
  // End of image to be copied.
  extern Word _sram_image_end;
  // Destination for copy (RAM).
  extern Word _sram_image_dest;

  // Start/end of memory to be zeroed.
  extern Word _bss_start, _bss_end;

  // Start/end of initializer arrays.
  extern InitFnPtr _preinit_array_start, _preinit_array_end;
  extern InitFnPtr _init_array_start, _init_array_end;

  // Generated initializer function.
  extern void _init();

  // Init epilogue, defined below, called implicitly.
  void init_epilogue();
}

void crt_init() {
  // Enable fault reporting.
  armv7m::scb.write_shcsr(armv7m::scb.read_shcsr()
                          .with_memfaultena(true)
                          .with_busfaultena(true)
                          .with_usgfaultena(true));

  // Enable floating point automatic/lazy state preservation.
  // The CONTROL bit governing FP will be set automatically when first used.
  armv7m::scb_fp.write_fpccr(armv7m::scb_fp.read_fpccr()
                             .with_aspen(true)
                             .with_lspen(true));

  // Enable access to the floating point coprocessor.
  armv7m::scb.write_cpacr(armv7m::scb.read_cpacr()
                          .with_cp11(armv7m::Scb::CpAccess::full)
                          .with_cp10(armv7m::Scb::CpAccess::full));
  armv7m::instruction_synchronization_barrier();  // Now please.

  // It is now safe to use floating point.

  // Remap SRAM.
  // Power on syscfg, so we can mess with its registers.
  rcc.enable_clock(ApbPeripheral::syscfg);

  // VTOR starts out at zero, which points to Flash and is good.
  // But now things are about to change.
  // Interrupts are disabled, but to be safe in case we fault (due to a bug),
  // go ahead and give VTOR the true address of the Flash table.
  scb.write_vtor(reinterpret_cast<unsigned>(&_sram_image_dest));
  armv7m::data_synchronization_barrier();  // Write it now.
  armv7m::instruction_synchronization_barrier();  // Flush pipeline just in case

  // Remap!
  auto mode = SysCfg::memrmp_value_t::mem_mode_t::embedded_sram;
  syscfg.write_memrmp(syscfg.read_memrmp()
                      .with_mem_mode(mode));
  armv7m::data_synchronization_barrier();  // Write it now.
  armv7m::instruction_synchronization_barrier();  // Flush pipeline just in cas

  // Copy image into SRAM.
  for (Word *src = &_sram_image_start, *dest = &_sram_image_dest;
       src != &_sram_image_end;
       ++src, ++dest) {
    *dest = *src;
  }

  // Zero BSS.
  for (Word *dest = &_bss_start; dest != &_bss_end; ++dest) {
    *dest = 0;
  }

  // Run the funky three-phase init process.
  for (InitFnPtr *f = &_preinit_array_start; f != &_preinit_array_end; ++f) {
    (*f)();
  }

  _init();

  for (InitFnPtr *f = &_init_array_start; f != &_init_array_end; ++f) {
    (*f)();
  }
}

SECTION(".init_prologue")
NAKED void _init() {
  asm volatile ("push {r4-r11, lr}");
}

SECTION(".init_epilogue")
NAKED void init_epilogue() {
  asm volatile ("pop {r4-r11, pc}");
}
<|endoftext|>