<commit_before>#include <x0/buffer.hpp>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>

#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cassert>
#include <strings.h>

class buffer_test :
	public CPPUNIT_NS::TestFixture
{
public:
	CPPUNIT_TEST_SUITE(buffer_test);
		// buffer
		CPPUNIT_TEST(ctor0);
		CPPUNIT_TEST(const_buffer1);
		CPPUNIT_TEST(resize);
		CPPUNIT_TEST(capacity);
		CPPUNIT_TEST(reserve);
		CPPUNIT_TEST(clear);
		CPPUNIT_TEST(operator_bool);
		CPPUNIT_TEST(operator_not);
		CPPUNIT_TEST(iterators);
		CPPUNIT_TEST(const_iterators);
		CPPUNIT_TEST(push_back);
		CPPUNIT_TEST(random_access);
		CPPUNIT_TEST(sub);
		CPPUNIT_TEST(call);
		CPPUNIT_TEST(std_string);

		// buffer::view
		CPPUNIT_TEST(view_ctor);
		CPPUNIT_TEST(view_begins);
	CPPUNIT_TEST_SUITE_END();

private:
	// {{{ buffer tests
	void ctor0()
	{
		x0::buffer a;

		CPPUNIT_ASSERT(a.empty());
		CPPUNIT_ASSERT(a.size() == 0);
		CPPUNIT_ASSERT(!a);
		CPPUNIT_ASSERT(!static_cast<bool>(a));
	}

	void const_buffer1()
	{
		x0::const_buffer empty("");
		CPPUNIT_ASSERT(empty.empty());
		CPPUNIT_ASSERT(empty.size() == 0);
		CPPUNIT_ASSERT(empty == "");

		x0::const_buffer hello("hello");
		CPPUNIT_ASSERT(!hello.empty());
		CPPUNIT_ASSERT(hello.size() == 5);
		CPPUNIT_ASSERT(hello == "hello");

		//! \todo ensure const buffers are unmutable
	}

	void resize()
	{
		// test modifying buffer size
		x0::buffer buf;
		buf.push_back("hello");
		CPPUNIT_ASSERT(buf.size() == 5);

		buf.size(4);
		CPPUNIT_ASSERT(buf.size() == 4);
		CPPUNIT_ASSERT(buf == "hell");

		//! \todo should not be resizable (const_buffer)
		//x0::const_buffer cbuf("hello");
		//cbuf.size(4);
	}

	// test modifying capacity
	void capacity()
	{
		x0::buffer buf;
		CPPUNIT_ASSERT(buf.capacity() == 0);

		buf.push_back("hello");
		CPPUNIT_ASSERT(buf.capacity() >= 5);

		buf.capacity(4);
		CPPUNIT_ASSERT(buf.capacity() == 4);
		CPPUNIT_ASSERT(buf.size() == 4);
		CPPUNIT_ASSERT(buf == "hell");
	}

	// test reserve()
	void reserve()
	{
	}

	void clear()
	{
		x0::buffer buf;
		buf.push_back("hello");

		const std::size_t capacity = buf.capacity();

		buf.clear();
		CPPUNIT_ASSERT(buf.empty());
		CPPUNIT_ASSERT(buf.size() == 0);

		// shouldn't have changed internal buffer
		CPPUNIT_ASSERT(buf.capacity() == capacity);
	}

	void operator_bool()
	{
		x0::buffer buf;
		CPPUNIT_ASSERT(buf.operator bool() == false);

		buf.push_back("hello");
		CPPUNIT_ASSERT(buf.operator bool() == true);
	}

	void operator_not()
	{
		x0::buffer buf;
		CPPUNIT_ASSERT(buf.operator!() == true);

		buf.push_back("hello");
		CPPUNIT_ASSERT(buf.operator!() == false);
	}

	void iterators()
	{
		{
			x0::buffer buf;
			buf.push_back("hello");

			x0::buffer::iterator i = buf.begin();
			CPPUNIT_ASSERT(i != buf.end());
			CPPUNIT_ASSERT(*i == 'h');
			CPPUNIT_ASSERT(*++i == 'e');
			CPPUNIT_ASSERT(i != buf.end());
			CPPUNIT_ASSERT(*i++ == 'e');
			CPPUNIT_ASSERT(*i == 'l');
			CPPUNIT_ASSERT(i != buf.end());
			CPPUNIT_ASSERT(*++i == 'l');
			CPPUNIT_ASSERT(i != buf.end());
			CPPUNIT_ASSERT(*++i == 'o');
			CPPUNIT_ASSERT(i != buf.end());
			CPPUNIT_ASSERT(++i == buf.end());
		}

		{
			x0::buffer buf;
			buf.push_back("hello");

			for (x0::buffer::iterator i = buf.begin(); i != buf.end(); ++i)
				*i = std::toupper(*i);

			CPPUNIT_ASSERT(buf == "HELLO");
		}
	}

	void const_iterators()
	{
		x0::buffer buf;
		buf.push_back("hello");

		x0::const_buffer::const_iterator i = buf.cbegin();
		CPPUNIT_ASSERT(i != buf.cend());
		CPPUNIT_ASSERT(*i == 'h');
		CPPUNIT_ASSERT(*++i == 'e');
		CPPUNIT_ASSERT(i != buf.cend());
		CPPUNIT_ASSERT(*i++ == 'e');
		CPPUNIT_ASSERT(*i == 'l');
		CPPUNIT_ASSERT(i != buf.cend());
		CPPUNIT_ASSERT(*++i == 'l');
		CPPUNIT_ASSERT(i != buf.cend());
		CPPUNIT_ASSERT(*++i == 'o');
		CPPUNIT_ASSERT(i != buf.cend());
		CPPUNIT_ASSERT(++i == buf.cend());
	}

	void push_back()
	{
		x0::buffer buf;

		buf.push_back('h');
		CPPUNIT_ASSERT(buf == "h");

		buf.push_back("");
		CPPUNIT_ASSERT(buf == "h");
		buf.push_back("e");
		CPPUNIT_ASSERT(buf == "he");

		buf.push_back("llo");
		CPPUNIT_ASSERT(buf == "hello");

		std::string s(" world");
		buf.push_back(s);
		CPPUNIT_ASSERT(buf == "hello world");

		buf.clear();
		buf.push_back(s.data(), s.size());
		CPPUNIT_ASSERT(buf == " world");
	}

	void random_access()
	{
		// test operator[](...)
	}

	void sub()
	{
		x0::const_buffer a("hello");

		CPPUNIT_ASSERT(a == "hello");
		CPPUNIT_ASSERT(a.sub(0) == "hello");
		CPPUNIT_ASSERT(a.sub(1) == "ello");
		CPPUNIT_ASSERT(a.sub(2) == "llo");
		CPPUNIT_ASSERT(a.sub(5) == "");
	}

	void call()
	{
		x0::const_buffer a("hello");

		CPPUNIT_ASSERT(a() == "hello");
		CPPUNIT_ASSERT(a(0) == "hello");
		CPPUNIT_ASSERT(a(1) == "ello");
		CPPUNIT_ASSERT(a(2) == "llo");
		CPPUNIT_ASSERT(a(5) == "");
	}

	void std_string()
	{
		// test std::string() utility functions

		x0::const_buffer a("hello");
		std::string s(a.str());

		CPPUNIT_ASSERT(a.data() != s.data());
		CPPUNIT_ASSERT(a.size() == s.size());
		CPPUNIT_ASSERT(s == "hello");
	}
	// }}}

	// {{{ buffer::view tests
	void view_ctor()
	{
	}

	void view_ctor1()
	{
	}

	void view_ctor_buffer()
	{
	}

	void view_ctor_ctor()
	{
	}

	void view_operator_asn_buffer()
	{
	}

	void view_operator_asn_view()
	{
	}

	void view_empty()
	{
	}

	void view_offset()
	{
	}

	void view_size()
	{
	}

	void view_data()
	{
	}

	void view_operator_bool()
	{
	}

	void view_operator_not()
	{
	}

	void view_iterator()
	{
	}

	void view_find_view()
	{
	}

	void view_find_value_ptr()
	{
	}

	void view_find_value()
	{
	}

	void view_rfind_view()
	{
	}

	void view_rfind_value_ptr()
	{
	}

	void view_rfind_value()
	{
	}

	void view_begins()
	{
		x0::const_buffer b("hello");
		x0::buffer::view v(b);

		CPPUNIT_ASSERT(v.begins((const char *)0));
		CPPUNIT_ASSERT(v.begins(""));
		CPPUNIT_ASSERT(v.begins("hello"));
	}

	void view_ibegins()
	{
	}
	// }}}

private: // {{{ debug helper
	void print(const x0::buffer& b, const char *msg = 0)
	{
		if (msg && *msg)
			printf("buffer(%s): '%s'\n", msg, b.str().c_str());
		else
			printf("buffer: '%s'\n", b.str().c_str());
	}

	void print(const x0::buffer::view& v, const char *msg = 0)
	{
		if (msg && *msg)
			printf("buffer.view(%s): '%s'\n", msg, v.str().c_str());
		else
			printf("buffer.view: '%s'\n", v.str().c_str());

		printf("  view.offset=%ld, size=%ld\n", v.offset(), v.size());
	}
	//}}}
};

CPPUNIT_TEST_SUITE_REGISTRATION(buffer_test);
<commit_msg>added test to `void buffer::reserve(std::size_t)`<commit_after>#include <x0/buffer.hpp>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>

#include <iostream>
#include <cstdlib>
#include <cctype>
#include <cassert>
#include <strings.h>

class buffer_test :
	public CPPUNIT_NS::TestFixture
{
public:
	CPPUNIT_TEST_SUITE(buffer_test);
		// buffer
		CPPUNIT_TEST(ctor0);
		CPPUNIT_TEST(const_buffer1);
		CPPUNIT_TEST(resize);
		CPPUNIT_TEST(capacity);
		CPPUNIT_TEST(reserve);
		CPPUNIT_TEST(clear);
		CPPUNIT_TEST(operator_bool);
		CPPUNIT_TEST(operator_not);
		CPPUNIT_TEST(iterators);
		CPPUNIT_TEST(const_iterators);
		CPPUNIT_TEST(push_back);
		CPPUNIT_TEST(random_access);
		CPPUNIT_TEST(sub);
		CPPUNIT_TEST(call);
		CPPUNIT_TEST(std_string);

		// buffer::view
		CPPUNIT_TEST(view_ctor);
		CPPUNIT_TEST(view_begins);
	CPPUNIT_TEST_SUITE_END();

private:
	// {{{ buffer tests
	void ctor0()
	{
		x0::buffer a;

		CPPUNIT_ASSERT(a.empty());
		CPPUNIT_ASSERT(a.size() == 0);
		CPPUNIT_ASSERT(!a);
		CPPUNIT_ASSERT(!static_cast<bool>(a));
	}

	void const_buffer1()
	{
		x0::const_buffer empty("");
		CPPUNIT_ASSERT(empty.empty());
		CPPUNIT_ASSERT(empty.size() == 0);
		CPPUNIT_ASSERT(empty == "");

		x0::const_buffer hello("hello");
		CPPUNIT_ASSERT(!hello.empty());
		CPPUNIT_ASSERT(hello.size() == 5);
		CPPUNIT_ASSERT(hello == "hello");

		//! \todo ensure const buffers are unmutable
	}

	void resize()
	{
		// test modifying buffer size
		x0::buffer buf;
		buf.push_back("hello");
		CPPUNIT_ASSERT(buf.size() == 5);

		buf.size(4);
		CPPUNIT_ASSERT(buf.size() == 4);
		CPPUNIT_ASSERT(buf == "hell");

		//! \todo should not be resizable (const_buffer)
		//x0::const_buffer cbuf("hello");
		//cbuf.size(4);
	}

	// test modifying capacity
	void capacity()
	{
		x0::buffer buf;
		CPPUNIT_ASSERT(buf.capacity() == 0);

		buf.push_back("hello");
		CPPUNIT_ASSERT(buf.capacity() >= 5);

		buf.capacity(4);
		CPPUNIT_ASSERT(buf.capacity() == 4);
		CPPUNIT_ASSERT(buf.size() == 4);
		CPPUNIT_ASSERT(buf == "hell");
	}

	// test reserve()
	void reserve()
	{
		x0::buffer buf;

		buf.reserve(1);

		CPPUNIT_ASSERT(buf.size() == 0);
		CPPUNIT_ASSERT(buf.capacity() == x0::buffer::CHUNK_SIZE);
	}

	void clear()
	{
		x0::buffer buf;
		buf.push_back("hello");

		const std::size_t capacity = buf.capacity();

		buf.clear();
		CPPUNIT_ASSERT(buf.empty());
		CPPUNIT_ASSERT(buf.size() == 0);

		// shouldn't have changed internal buffer
		CPPUNIT_ASSERT(buf.capacity() == capacity);
	}

	void operator_bool()
	{
		x0::buffer buf;
		CPPUNIT_ASSERT(buf.operator bool() == false);

		buf.push_back("hello");
		CPPUNIT_ASSERT(buf.operator bool() == true);
	}

	void operator_not()
	{
		x0::buffer buf;
		CPPUNIT_ASSERT(buf.operator!() == true);

		buf.push_back("hello");
		CPPUNIT_ASSERT(buf.operator!() == false);
	}

	void iterators()
	{
		{
			x0::buffer buf;
			buf.push_back("hello");

			x0::buffer::iterator i = buf.begin();
			CPPUNIT_ASSERT(i != buf.end());
			CPPUNIT_ASSERT(*i == 'h');
			CPPUNIT_ASSERT(*++i == 'e');
			CPPUNIT_ASSERT(i != buf.end());
			CPPUNIT_ASSERT(*i++ == 'e');
			CPPUNIT_ASSERT(*i == 'l');
			CPPUNIT_ASSERT(i != buf.end());
			CPPUNIT_ASSERT(*++i == 'l');
			CPPUNIT_ASSERT(i != buf.end());
			CPPUNIT_ASSERT(*++i == 'o');
			CPPUNIT_ASSERT(i != buf.end());
			CPPUNIT_ASSERT(++i == buf.end());
		}

		{
			x0::buffer buf;
			buf.push_back("hello");

			for (x0::buffer::iterator i = buf.begin(); i != buf.end(); ++i)
				*i = std::toupper(*i);

			CPPUNIT_ASSERT(buf == "HELLO");
		}
	}

	void const_iterators()
	{
		x0::buffer buf;
		buf.push_back("hello");

		x0::const_buffer::const_iterator i = buf.cbegin();
		CPPUNIT_ASSERT(i != buf.cend());
		CPPUNIT_ASSERT(*i == 'h');
		CPPUNIT_ASSERT(*++i == 'e');
		CPPUNIT_ASSERT(i != buf.cend());
		CPPUNIT_ASSERT(*i++ == 'e');
		CPPUNIT_ASSERT(*i == 'l');
		CPPUNIT_ASSERT(i != buf.cend());
		CPPUNIT_ASSERT(*++i == 'l');
		CPPUNIT_ASSERT(i != buf.cend());
		CPPUNIT_ASSERT(*++i == 'o');
		CPPUNIT_ASSERT(i != buf.cend());
		CPPUNIT_ASSERT(++i == buf.cend());
	}

	void push_back()
	{
		x0::buffer buf;

		buf.push_back('h');
		CPPUNIT_ASSERT(buf == "h");

		buf.push_back("");
		CPPUNIT_ASSERT(buf == "h");
		buf.push_back("e");
		CPPUNIT_ASSERT(buf == "he");

		buf.push_back("llo");
		CPPUNIT_ASSERT(buf == "hello");

		std::string s(" world");
		buf.push_back(s);
		CPPUNIT_ASSERT(buf == "hello world");

		buf.clear();
		buf.push_back(s.data(), s.size());
		CPPUNIT_ASSERT(buf == " world");
	}

	void random_access()
	{
		// test operator[](...)
	}

	void sub()
	{
		x0::const_buffer a("hello");

		CPPUNIT_ASSERT(a == "hello");
		CPPUNIT_ASSERT(a.sub(0) == "hello");
		CPPUNIT_ASSERT(a.sub(1) == "ello");
		CPPUNIT_ASSERT(a.sub(2) == "llo");
		CPPUNIT_ASSERT(a.sub(5) == "");
	}

	void call()
	{
		x0::const_buffer a("hello");

		CPPUNIT_ASSERT(a() == "hello");
		CPPUNIT_ASSERT(a(0) == "hello");
		CPPUNIT_ASSERT(a(1) == "ello");
		CPPUNIT_ASSERT(a(2) == "llo");
		CPPUNIT_ASSERT(a(5) == "");
	}

	void std_string()
	{
		// test std::string() utility functions

		x0::const_buffer a("hello");
		std::string s(a.str());

		CPPUNIT_ASSERT(a.data() != s.data());
		CPPUNIT_ASSERT(a.size() == s.size());
		CPPUNIT_ASSERT(s == "hello");
	}
	// }}}

	// {{{ buffer::view tests
	void view_ctor()
	{
	}

	void view_ctor1()
	{
	}

	void view_ctor_buffer()
	{
	}

	void view_ctor_ctor()
	{
	}

	void view_operator_asn_buffer()
	{
	}

	void view_operator_asn_view()
	{
	}

	void view_empty()
	{
	}

	void view_offset()
	{
	}

	void view_size()
	{
	}

	void view_data()
	{
	}

	void view_operator_bool()
	{
	}

	void view_operator_not()
	{
	}

	void view_iterator()
	{
	}

	void view_find_view()
	{
	}

	void view_find_value_ptr()
	{
	}

	void view_find_value()
	{
	}

	void view_rfind_view()
	{
	}

	void view_rfind_value_ptr()
	{
	}

	void view_rfind_value()
	{
	}

	void view_begins()
	{
		x0::const_buffer b("hello");
		x0::buffer::view v(b);

		CPPUNIT_ASSERT(v.begins((const char *)0));
		CPPUNIT_ASSERT(v.begins(""));
		CPPUNIT_ASSERT(v.begins("hello"));
	}

	void view_ibegins()
	{
	}
	// }}}

private: // {{{ debug helper
	void print(const x0::buffer& b, const char *msg = 0)
	{
		if (msg && *msg)
			printf("buffer(%s): '%s'\n", msg, b.str().c_str());
		else
			printf("buffer: '%s'\n", b.str().c_str());
	}

	void print(const x0::buffer::view& v, const char *msg = 0)
	{
		if (msg && *msg)
			printf("buffer.view(%s): '%s'\n", msg, v.str().c_str());
		else
			printf("buffer.view: '%s'\n", v.str().c_str());

		printf("  view.offset=%ld, size=%ld\n", v.offset(), v.size());
	}
	//}}}
};

CPPUNIT_TEST_SUITE_REGISTRATION(buffer_test);
<|endoftext|>


<commit_before>// $Id$
// (c) Guido Kanschat
//
// Compute support points

#include <base/quadrature_lib.h>
#include <base/logstream.h>
#include <lac/vector.h>
#include <grid/tria.h>
#include <grid/tria_iterator.h>
#include <dofs/dof_accessor.h>
#include <grid/grid_generator.h>
#include <fe/fe_lib.lagrange.h>
#include <fe/fe_lib.dg.h>
#include <fe/fe_values.h>
#include <vector>
#include <fstream>
#include <iomanip>
#include <string>

template <int dim>
inline void
check_support (FiniteElement<dim>& finel, const char* name)
{
  Triangulation<dim> tr;
  GridGenerator::hyper_cube(tr, 0., 1.);
  DoFHandler<dim> dof (tr);
  dof.distribute_dofs (finel);

  vector<Point<dim> > cell_points (finel.dofs_per_cell);
  vector<Point<dim> > face_points (finel.dofs_per_face);

  DoFHandler<dim>::active_cell_iterator cell = dof.begin_active();
  finel.get_support_points (cell, cell_points);

  cout << name << '<' << dim << '>' << " cell support points" << endl;

  for (unsigned int k=0;k<cell_points.size();++k)
    cout << setprecision(3) << cell_points[k] << endl;

  for (unsigned int i=0;i<GeometryInfo<dim>::faces_per_cell;++i)
    {
      cout << name << '<' << dim << '>' << " face " << i << " support points" << endl;
      DoFHandler<dim>::active_face_iterator face = cell->face(i);
      finel.get_face_support_points (face, face_points);

      for (unsigned int k=0;k<face_points.size();++k)
	cout << setprecision(3) << face_points[k] << endl;
    }
}

template <int dim>
inline void
check_matrices (FiniteElement<dim>& fe, const char* name)
{
  cout << name << '<' << dim << '>' << " constraint " << endl;
  fe.constraints().print_formatted (cout, 7, false, 10, "~");

  for (unsigned int i=0;i<GeometryInfo<dim>::children_per_cell;++i)
    {
      cout << name << '<' << dim << '>' << " restriction " << i << endl;
      fe.restrict(i).print_formatted (cout, 3, false, 6, "~");
      cout << name << '<' << dim << '>' << " embedding " << i << endl;
      fe.prolongate(i).print_formatted (cout, 3, false, 6, "~");
    }
}

#define CHECK_S(EL,dim) FE ## EL<dim> EL; check_support(EL, #EL);
#define CHECK_M(EL,dim) FE ## EL<dim> EL; check_matrices(EL, #EL);
#define CHECK_ALL(EL,dim) FE ## EL<dim> EL; check_support(EL, #EL); check_matrices(EL,#EL)

int
main()
{
  if (true)
    {
      CHECK_ALL(Q1,2);
      CHECK_ALL(Q2,2);
      CHECK_ALL(Q3,2);
      CHECK_ALL(Q4,2);
      CHECK_ALL(DG_Q0,2);
      CHECK_ALL(DG_Q1,2);
      CHECK_ALL(DG_Q2,2);
      CHECK_ALL(DG_Q3,2);
    }
  if (true)
    {
      CHECK_ALL(Q1,3);
      CHECK_ALL(Q2,3);
      CHECK_ALL(DG_Q0,3);
      CHECK_ALL(DG_Q1,3);
    }

  return 0;
}
<commit_msg>more checks<commit_after>// $Id$
// (c) Guido Kanschat
//
// Compute support points

#include <base/quadrature_lib.h>
#include <base/logstream.h>
#include <lac/vector.h>
#include <grid/tria.h>
#include <grid/tria_iterator.h>
#include <dofs/dof_accessor.h>
#include <grid/grid_generator.h>
#include <fe/fe_lib.lagrange.h>
#include <fe/fe_lib.dg.h>
#include <fe/fe_values.h>
#include <vector>
#include <fstream>
#include <iomanip>
#include <string>

template <int dim>
inline void
check_support (FiniteElement<dim>& finel, const char* name)
{
  Triangulation<dim> tr;
  GridGenerator::hyper_cube(tr, 0., 1.);
  DoFHandler<dim> dof (tr);
  dof.distribute_dofs (finel);

  cout << name << '<' << dim << '>' << " cell support points" << endl;

  vector<Point<dim> > cell_points (finel.dofs_per_cell);
  vector<Point<dim> > face_points (finel.dofs_per_face);

  DoFHandler<dim>::active_cell_iterator cell = dof.begin_active();
  finel.get_support_points (cell, cell_points);

  for (unsigned int k=0;k<cell_points.size();++k)
    cout << setprecision(3) << cell_points[k] << endl;

  for (unsigned int i=0;i<GeometryInfo<dim>::faces_per_cell;++i)
    {
      cout << name << '<' << dim << '>' << " face " << i << " support points" << endl;
      DoFHandler<dim>::active_face_iterator face = cell->face(i);
      finel.get_face_support_points (face, face_points);

      for (unsigned int k=0;k<face_points.size();++k)
	cout << setprecision(3) << face_points[k] << endl;
    }
}

template <int dim>
inline void
check_matrices (FiniteElement<dim>& fe, const char* name)
{
  cout << name << '<' << dim << '>' << " constraint " << endl;
  fe.constraints().print_formatted (cout, 7, false, 10, "~");

  for (unsigned int i=0;i<GeometryInfo<dim>::children_per_cell;++i)
    {
      cout << name << '<' << dim << '>' << " restriction " << i << endl;
      fe.restrict(i).print_formatted (cout, 3, false, 6, "~");
      cout << name << '<' << dim << '>' << " embedding " << i << endl;
      fe.prolongate(i).print_formatted (cout, 3, false, 6, "~");
    }
}

#define CHECK_S(EL,dim) { FE ## EL<dim> EL; check_support(EL, #EL); }
#define CHECK_M(EL,dim) { FE ## EL<dim> EL; check_matrices(EL, #EL); }
#define CHECK_ALL(EL,dim) { FE ## EL<dim> EL; check_support(EL, #EL); check_matrices(EL,#EL); }

int
main()
{
  CHECK_M(DG_Q0,2);
  CHECK_M(DG_Q1,2);
  CHECK_M(DG_Q2,2);
  CHECK_M(DG_Q3,2);
  CHECK_ALL(Q1,2);
  CHECK_ALL(Q2,2);
  CHECK_ALL(Q3,2);
  CHECK_ALL(Q4,2);
  CHECK_ALL(Q1,3);
  CHECK_ALL(Q2,3);
  CHECK_M(DG_Q0,3);
  CHECK_M(DG_Q1,3);
  return 0;
}
<|endoftext|>


<commit_before>#include "storage/storage_helpers.hpp"

#include "storage/country_info_getter.hpp"
#include "storage/storage.hpp"

#include "platform/platform.hpp"

namespace storage
{
bool IsPointCoveredByDownloadedMaps(m2::PointD const & position,
                                    Storage const & storage,
                                    CountryInfoGetter const & countryInfoGetter)
{
  return storage.IsNodeDownloaded(countryInfoGetter.GetRegionCountryId(position));
}

bool IsDownloadFailed(Status status)
{
  return status == Status::EDownloadFailed || status == Status::EOutOfMemFailed ||
         status == Status::EUnknown;
}

bool IsEnoughSpaceForDownload(TMwmSize mwmSize)
{
  return GetPlatform().GetWritableStorageStatus(mwmSize) ==
         Platform::TStorageStatus::STORAGE_OK;
}

bool IsEnoughSpaceForDownload(TMwmSize mwmSizeDiff, TMwmSize maxMwmSize)
{
  // Mwm size is less than |maxMwmSize|. In case of map update at first we download updated map
  // and only after that we do delete the obsolete map. So in such a case we might need up to
  // |maxMwmSize| of extra space.
  return IsEnoughSpaceForDownload(mwmSizeDiff + maxMwmSize);
}

bool IsEnoughSpaceForDownload(TCountryId const & countryId, Storage const & storage)
{
  NodeAttrs nodeAttrs;
  storage.GetNodeAttrs(countryId, nodeAttrs);
  return IsEnoughSpaceForDownload(nodeAttrs.m_mwmSize);
}

bool IsEnoughSpaceForUpdate(TCountryId const & countryId, Storage const & storage)
{
  Storage::UpdateInfo updateInfo;

  storage.GetUpdateInfo(countryId, updateInfo);
  TMwmSize spaceNeedForUpdate = updateInfo.m_sizeDifference > 0 ? updateInfo.m_sizeDifference : 0;
  return IsEnoughSpaceForDownload(spaceNeedForUpdate, storage.GetMaxMwmSizeBytes());
}

m2::RectD CalcLimitRect(TCountryId const & countryId,
                        Storage const & storage,
                        CountryInfoGetter const & countryInfoGetter)
{
  m2::RectD boundingBox;
  auto const accumulator =
      [&countryInfoGetter, &boundingBox](TCountryId const & descendantId, bool groupNode)
  {
    if (!groupNode)
      boundingBox.Add(countryInfoGetter.GetLimitRectForLeaf(descendantId));
  };

  storage.ForEachInSubtree(countryId, accumulator);

  ASSERT(boundingBox.IsValid(), ());
  return boundingBox;
}
} // namespace storage
<commit_msg>Review fixes.<commit_after>#include "storage/storage_helpers.hpp"

#include "storage/country_info_getter.hpp"
#include "storage/storage.hpp"

#include "platform/platform.hpp"

namespace storage
{
bool IsPointCoveredByDownloadedMaps(m2::PointD const & position,
                                    Storage const & storage,
                                    CountryInfoGetter const & countryInfoGetter)
{
  return storage.IsNodeDownloaded(countryInfoGetter.GetRegionCountryId(position));
}

bool IsDownloadFailed(Status status)
{
  return status == Status::EDownloadFailed || status == Status::EOutOfMemFailed ||
         status == Status::EUnknown;
}

bool IsEnoughSpaceForDownload(TMwmSize mwmSize)
{
  // Additional size which is necessary to have on flash card to download file of mwmSize bytes.
  TMwmSize constexpr kExtraSizeBytes = 10 * 1024 * 1024;
  return GetPlatform().GetWritableStorageStatus(mwmSize + kExtraSizeBytes) ==
         Platform::TStorageStatus::STORAGE_OK;
}

bool IsEnoughSpaceForDownload(TMwmSize mwmSizeDiff, TMwmSize maxMwmSize)
{
  // Mwm size is less than |maxMwmSize|. In case of map update at first we download updated map
  // and only after that we do delete the obsolete map. So in such a case we might need up to
  // |maxMwmSize| of extra space.
  return IsEnoughSpaceForDownload(mwmSizeDiff + maxMwmSize);
}

bool IsEnoughSpaceForDownload(TCountryId const & countryId, Storage const & storage)
{
  NodeAttrs nodeAttrs;
  storage.GetNodeAttrs(countryId, nodeAttrs);
  return IsEnoughSpaceForDownload(nodeAttrs.m_mwmSize);
}

bool IsEnoughSpaceForUpdate(TCountryId const & countryId, Storage const & storage)
{
  Storage::UpdateInfo updateInfo;

  storage.GetUpdateInfo(countryId, updateInfo);
  TMwmSize spaceNeedForUpdate = updateInfo.m_sizeDifference > 0 ? updateInfo.m_sizeDifference : 0;
  return IsEnoughSpaceForDownload(spaceNeedForUpdate, storage.GetMaxMwmSizeBytes());
}

m2::RectD CalcLimitRect(TCountryId const & countryId,
                        Storage const & storage,
                        CountryInfoGetter const & countryInfoGetter)
{
  m2::RectD boundingBox;
  auto const accumulator =
      [&countryInfoGetter, &boundingBox](TCountryId const & descendantId, bool groupNode)
  {
    if (!groupNode)
      boundingBox.Add(countryInfoGetter.GetLimitRectForLeaf(descendantId));
  };

  storage.ForEachInSubtree(countryId, accumulator);

  ASSERT(boundingBox.IsValid(), ());
  return boundingBox;
}
} // namespace storage
<|endoftext|>


<commit_before>/*
 * File:   AlarmClockSpeedTest.cpp
 * Author: Amanda Carbonari
 * Created: January 6, 2015 9:00am
 *
 * WARNING: This only measures CPU time
 */

#include <ctime>
#include <iostream>
#include <AlarmClock.h>
#include <chrono>
using namespace std;
typedef std::chrono::microseconds microseconds;
typedef std::chrono::milliseconds milliseconds;
typedef std::chrono::seconds seconds;

template<typename T> void WaitForAlarmClockToExpire(AlarmClock<T>& alerter) {
   while(!alerter.Expired());
}

int main(int, const char**) {
   clock_t start;
   clock_t end;
   unsigned int us = 389;

   cout << "Creating Alarm Clock" << endl;
   AlarmClock<microseconds> alerter(us);
   // Give some time for the countdown to start
   this_thread::sleep_for(chrono::microseconds(20));
   cout << "Starting clock and resetting" << endl;
   start = clock();
   alerter.Reset();
   end = clock();
   clock_t reset_time = (end - start) / (double) (CLOCKS_PER_SEC);
   cout << "Start: " << start << ", End: " << end << endl;
   cout << "Waiting for the clock to expire" << endl;
   WaitForAlarmClockToExpire(alerter);

   cout << "Time: " << reset_time << " us" << endl;
}<commit_msg>Implemented timing mechanism with chrono<commit_after>/*
 * File:   AlarmClockSpeedTest.cpp
 * Author: Amanda Carbonari
 * Created: January 6, 2015 9:00am
 *
 * WARNING: This only measures CPU time
 */

#include <ctime>
#include <iostream>
#include <AlarmClock.h>
#include <chrono>
using namespace std;
using namespace std::chrono;
typedef std::chrono::microseconds microseconds;
typedef std::chrono::milliseconds milliseconds;
typedef std::chrono::seconds seconds;

template<typename T> void WaitForAlarmClockToExpire(AlarmClock<T>& alerter) {
   while(!alerter.Expired());
}

int main(int, const char**) {
   unsigned int us = 389;

   cout << "Creating Alarm Clock" << endl;
   AlarmClock<microseconds> alerter(us);
   // Give some time for the countdown to start
   this_thread::sleep_for(chrono::microseconds(20));
   cout << "Starting clock and resetting" << endl;
   high_resolution_clock::time_point start = high_resolution_clock::now();
   alerter.Reset();
   high_resolution_clock::time_point end = high_resolution_clock::now();
   auto reset_time = duration_cast<microseconds>(end - start).count();
   cout << "Start: " << start << ", End: " << end << endl;
   cout << "Waiting for the clock to expire" << endl;
   WaitForAlarmClockToExpire(alerter);

   cout << "Time: " << reset_time << " us" << endl;
}<|endoftext|>


<commit_before>/*
 * source.cpp
 *
 *  Created on: Feb 8, 2012
 *      Author: mpetkova
 */

#include <slsimlib.h>
#include <sstream>

const string escape = "#";
char dummy[300];

Source::Source(){
}

SourceUniform::SourceUniform(string filename) : Source(){
	readParamfile(filename);
}

SourceGaussian::SourceGaussian(string filename) : Source(){
	readParamfile(filename);
}

SourceBLR::SourceBLR(string filename) : Source(){
	readParamfile(filename);
}

SourceBLRDisk::SourceBLRDisk(string filename) : SourceBLR(filename){

}

SourceBLRSph1::SourceBLRSph1(string filename) : SourceBLR(filename){

}

SourceBLRSph2::SourceBLRSph2(string filename) : SourceBLR(filename){

}

Source::~Source(){
}

SourceUniform::~SourceUniform(){
}

SourceGaussian::~SourceGaussian(){
}

SourceBLR::~SourceBLR(){
}

SourceBLRDisk::~SourceBLRDisk(){
}

SourceBLRSph1::~SourceBLRSph1(){
}

SourceBLRSph2::~SourceBLRSph2(){
}

void SourceUniform::readParamfile(string filename){
	  string label, rlabel, rvalue;
	  stringstream ss;
	  double mydouble;
	  int flag;

	  label = "z_source";

	  cout << "uniform source: reading from " << filename << endl;

	  ifstream file_in(filename.c_str());
	  if(!file_in){
	    cout << "Can't open file " << filename << endl;
	    exit(1);
	  }

	  flag = 1;

	  // output file
	  while(!file_in.eof()){
		  file_in >> rlabel >> rvalue;
		  file_in.getline(dummy,100);

		  if(rlabel[0] == escape[0])
			  continue;

		  if(rlabel == label){

			  flag = 0;
			  ss << rvalue;

			  ss >> mydouble;
			  zsource = mydouble;

			  ss.clear();
			  ss.str(string());
		  }
	  }

	  file_in.close();

	  if(flag > 0){
		  ERROR_MESSAGE();
		  cout << "parameter " << label << " needs to be set!" << endl;
		  exit(0);
	  }

	  printSource();
}

void SourceGaussian::readParamfile(string filename){
	  string label[2], rlabel, rvalue;
	  stringstream ss;
	  void *addr[2];
	  int id[2];
	  int i;
	  double mydouble;
	  int flag;

	  addr[0] = &zsource;
	  id[0] = 0;
	  label[0] = "z_source";

	  addr[1] = &source_gauss_r2;
	  id[1] = 0;
	  label[1] = "gauss_r2";

	  cout << "gaussian source: reading from " << filename << endl;

	  ifstream file_in(filename.c_str());
	  if(!file_in){
	    cout << "Can't open file " << filename << endl;
	    exit(1);
	  }

	  // output file
	  while(!file_in.eof()){
		  file_in >> rlabel >> rvalue;
		  file_in.getline(dummy,100);

		  if(rlabel[0] == escape[0])
			  continue;

		  flag = 1;

		  for(i = 0; i < 2; i++){

			  if(rlabel == label[i]){

				  flag = 0;
				  ss << rvalue;
				  ss >> mydouble;

				  *((double *)addr[i]) = mydouble;

				  ss.clear();
				  ss.str(string());
			  }

			  id[i] = -1;
		  }
	  }

	  file_in.close();

	  for(i = 0; i < 2; i++){
		  if(id[i] > 0){
			  ERROR_MESSAGE();
			  cout << "parameter " << label[i] << " needs to be set!" << endl;
			  exit(0);
		  }
	  }

	  printSource();
}

void SourceBLR::readParamfile(string filename){
	  string label[9], rlabel, rvalue;
	  stringstream ss;
	  void *addr[9];
	  int id[9];
	  int i, n;
	  float myfloat;
	  int flag;

	  n = 0;

	  addr[n] = &zsource;
	  id[n] = 0;
	  label[n++] = "z_source";

	  addr[n] = &source_BHmass;
	  id[n] = 0;
	  label[n++] = "BHmass";

	  addr[n] = &source_gamma;
	  id[n] = 0;
	  label[n++] = "gamma";

	  addr[n] = &source_inclination;
	  id[n] = 0;
	  label[n++] = "inclin";

	  addr[n] = &source_opening_angle;
	  id[n] = 0;
	  label[n++] = "opening_ang";

	  addr[n] = &source_r_in;
	  id[n] = 0;
	  label[n++] = "r_in";

	  addr[n] = &source_r_out;
	  id[n] = 0;
	  label[n++] = "r_out";

	  addr[n] = &source_nuo;
	  id[n] = 0;
	  label[n++] = "nuo";

	  addr[n] = &source_fK;
	  id[n] = 0;
	  label[n++] = "source_sigma";

	  cout << "BLR source: reading from " << filename << endl;

	  ifstream file_in(filename.c_str());
	  if(!file_in){
	    cout << "Can't open file " << filename << endl;
	    exit(1);
	  }

	  // output file
	  while(!file_in.eof()){
		  file_in >> rlabel >> rvalue;
		  file_in.getline(dummy,100);

		  if(rlabel[0] == escape[0])
			  continue;

		  flag = 1;

		  for(i = 0; i < 9; i++){
			  if(rlabel == label[i]){

				  flag = 0;
				  ss << rvalue;
				  ss >> myfloat;

				  *((float *)addr[i]) = myfloat;

				  ss.clear();
				  ss.str(string());

				  id[i] = -1;
			  }
		  }
	  }

	  file_in.close();

	  for(i = 0; i < n; i++){
		  if(id[i] > 0){
			  ERROR_MESSAGE();
			  cout << "parameter " << label[i] << " needs to be set!" << endl;
			  exit(0);
		  }
	  }

	  source_inclination *= pi/180;
	  source_opening_angle *= pi/180;
	  source_monocrome = false;

	  printSource();
}

void SourceUniform::printSource(){
	cout << endl << "**Source model**" << endl;

	cout << "z_source " << zsource << endl << endl;
}

void SourceGaussian::printSource(){
	cout << endl << "**Source model**" << endl;

	cout << "z_source " << zsource << endl;
	cout << "gauss_r2 " << source_gauss_r2 << endl << endl;
}

void SourceBLR::printSource(){
	cout << endl << "**Source model**" << endl;

	cout << "z_source " << zsource << endl;
	cout << "BHmass " << source_BHmass << endl;
	cout << "gamma " << source_gamma << endl;
	cout << "incl " << source_inclination << endl;
	cout << "opening angl " << source_opening_angle << endl;
	cout << "r_in " << source_r_in << endl;
	cout << "r_out " << source_r_out << endl;
	cout << "nuo " << source_nuo << endl;
	cout << "source_sigma " << source_fK << endl << endl;
}

double SourceUniform::source_sb_func(double *y){
	return (double)( (y[0]*y[0] + y[1]*y[1]) < source_r*source_r );
}

double SourceGaussian::source_sb_func(double *y){
	return exp( -(y[0]*y[0] + y[1]*y[1])/source_gauss_r2 );
}

// surface brightness for models of the Broad Line Region
double SourceBLRDisk::source_sb_func(double *y){
	return blr_surface_brightness_disk(y,this);
}

double SourceBLRSph1::source_sb_func(double *y){
	return blr_surface_brightness_spherical_circular_motions(sqrt(y[0]*y[0] + y[1]*y[1]),this);
}
double SourceBLRSph2::source_sb_func(double *y){
	return blr_surface_brightness_spherical_random_motions(sqrt(y[0]*y[0] + y[1]*y[1]),this);
}

void in_source(double *y_source,ListHndl sourcelist){
  return;
}
<commit_msg>fixed the double/float param input for the BLR source<commit_after>/*
 * source.cpp
 *
 *  Created on: Feb 8, 2012
 *      Author: mpetkova
 */

#include <slsimlib.h>
#include <sstream>

const string escape = "#";
char dummy[300];

Source::Source(){
}

SourceUniform::SourceUniform(string filename) : Source(){
	readParamfile(filename);
}

SourceGaussian::SourceGaussian(string filename) : Source(){
	readParamfile(filename);
}

SourceBLR::SourceBLR(string filename) : Source(){
	readParamfile(filename);
}

SourceBLRDisk::SourceBLRDisk(string filename) : SourceBLR(filename){

}

SourceBLRSph1::SourceBLRSph1(string filename) : SourceBLR(filename){

}

SourceBLRSph2::SourceBLRSph2(string filename) : SourceBLR(filename){

}

Source::~Source(){
}

SourceUniform::~SourceUniform(){
}

SourceGaussian::~SourceGaussian(){
}

SourceBLR::~SourceBLR(){
}

SourceBLRDisk::~SourceBLRDisk(){
}

SourceBLRSph1::~SourceBLRSph1(){
}

SourceBLRSph2::~SourceBLRSph2(){
}

void SourceUniform::readParamfile(string filename){
	  string label, rlabel, rvalue;
	  stringstream ss;
	  double mydouble;
	  int flag;

	  label = "z_source";

	  cout << "uniform source: reading from " << filename << endl;

	  ifstream file_in(filename.c_str());
	  if(!file_in){
	    cout << "Can't open file " << filename << endl;
	    exit(1);
	  }

	  flag = 1;

	  // output file
	  while(!file_in.eof()){
		  file_in >> rlabel >> rvalue;
		  file_in.getline(dummy,100);

		  if(rlabel[0] == escape[0])
			  continue;

		  if(rlabel == label){

			  flag = 0;
			  ss << rvalue;

			  ss >> mydouble;
			  zsource = mydouble;

			  ss.clear();
			  ss.str(string());
		  }
	  }

	  file_in.close();

	  if(flag > 0){
		  ERROR_MESSAGE();
		  cout << "parameter " << label << " needs to be set!" << endl;
		  exit(0);
	  }

	  printSource();
}

void SourceGaussian::readParamfile(string filename){
	  string label[2], rlabel, rvalue;
	  stringstream ss;
	  void *addr[2];
	  int id[2];
	  int i;
	  double mydouble;
	  int flag;

	  addr[0] = &zsource;
	  id[0] = 0;
	  label[0] = "z_source";

	  addr[1] = &source_gauss_r2;
	  id[1] = 0;
	  label[1] = "gauss_r2";

	  cout << "gaussian source: reading from " << filename << endl;

	  ifstream file_in(filename.c_str());
	  if(!file_in){
	    cout << "Can't open file " << filename << endl;
	    exit(1);
	  }

	  // output file
	  while(!file_in.eof()){
		  file_in >> rlabel >> rvalue;
		  file_in.getline(dummy,100);

		  if(rlabel[0] == escape[0])
			  continue;

		  flag = 1;

		  for(i = 0; i < 2; i++){

			  if(rlabel == label[i]){

				  flag = 0;
				  ss << rvalue;
				  ss >> mydouble;

				  *((double *)addr[i]) = mydouble;

				  ss.clear();
				  ss.str(string());
			  }

			  id[i] = -1;
		  }
	  }

	  file_in.close();

	  for(i = 0; i < 2; i++){
		  if(id[i] > 0){
			  ERROR_MESSAGE();
			  cout << "parameter " << label[i] << " needs to be set!" << endl;
			  exit(0);
		  }
	  }

	  printSource();
}

void SourceBLR::readParamfile(string filename){
	  string label[9], rlabel, rvalue;
	  stringstream ss;
	  void *addr[9];
	  int id[9];
	  int i, n;
	  float myfloat;
	  double mydouble;
	  int flag;

	  n = 0;

	  addr[n] = &zsource;
	  id[n] = 1;
	  label[n++] = "z_source";

	  addr[n] = &source_BHmass;
	  id[n] = 0;
	  label[n++] = "BHmass";

	  addr[n] = &source_gamma;
	  id[n] = 0;
	  label[n++] = "gamma";

	  addr[n] = &source_inclination;
	  id[n] = 0;
	  label[n++] = "inclin";

	  addr[n] = &source_opening_angle;
	  id[n] = 0;
	  label[n++] = "opening_ang";

	  addr[n] = &source_r_in;
	  id[n] = 0;
	  label[n++] = "r_in";

	  addr[n] = &source_r_out;
	  id[n] = 0;
	  label[n++] = "r_out";

	  addr[n] = &source_nuo;
	  id[n] = 0;
	  label[n++] = "nuo";

	  addr[n] = &source_fK;
	  id[n] = 0;
	  label[n++] = "source_sigma";

	  cout << "BLR source: reading from " << filename << endl;

	  ifstream file_in(filename.c_str());
	  if(!file_in){
	    cout << "Can't open file " << filename << endl;
	    exit(1);
	  }

	  // output file
	  while(!file_in.eof()){
		  file_in >> rlabel >> rvalue;
		  file_in.getline(dummy,100);

		  if(rlabel[0] == escape[0])
			  continue;

		  flag = 1;

		  for(i = 0; i < n; i++){
			  if(rlabel == label[i]){

				  flag = 0;
				  ss << rvalue;

				  switch(id[i]){
				  case 0:
					  ss >> myfloat;
					  *((float *)addr[i]) = myfloat;
					  break;
				  case 1:
					  ss >> mydouble;
					  *((double *)addr[i]) = mydouble;
					  break;
				  }

				  ss.clear();
				  ss.str(string());

				  id[i] = -1;
			  }
		  }
	  }

	  file_in.close();

	  for(i = 0; i < n; i++){
		  if(id[i] > 0){
			  ERROR_MESSAGE();
			  cout << "parameter " << label[i] << " needs to be set!" << endl;
			  exit(0);
		  }
	  }

	  source_inclination *= pi/180;
	  source_opening_angle *= pi/180;
	  source_monocrome = false;

	  printSource();
}

void SourceUniform::printSource(){
	cout << endl << "**Source model**" << endl;

	cout << "z_source " << zsource << endl << endl;
}

void SourceGaussian::printSource(){
	cout << endl << "**Source model**" << endl;

	cout << "z_source " << zsource << endl;
	cout << "gauss_r2 " << source_gauss_r2 << endl << endl;
}

void SourceBLR::printSource(){
	cout << endl << "**Source model**" << endl;

	cout << "z_source " << zsource << endl;
	cout << "BHmass " << source_BHmass << endl;
	cout << "gamma " << source_gamma << endl;
	cout << "incl " << source_inclination << endl;
	cout << "opening angl " << source_opening_angle << endl;
	cout << "r_in " << source_r_in << endl;
	cout << "r_out " << source_r_out << endl;
	cout << "nuo " << source_nuo << endl;
	cout << "source_sigma " << source_fK << endl << endl;
}

double SourceUniform::source_sb_func(double *y){
	return (double)( (y[0]*y[0] + y[1]*y[1]) < source_r*source_r );
}

double SourceGaussian::source_sb_func(double *y){
	return exp( -(y[0]*y[0] + y[1]*y[1])/source_gauss_r2 );
}

// surface brightness for models of the Broad Line Region
double SourceBLRDisk::source_sb_func(double *y){
	return blr_surface_brightness_disk(y,this);
}

double SourceBLRSph1::source_sb_func(double *y){
	return blr_surface_brightness_spherical_circular_motions(sqrt(y[0]*y[0] + y[1]*y[1]),this);
}
double SourceBLRSph2::source_sb_func(double *y){
	return blr_surface_brightness_spherical_random_motions(sqrt(y[0]*y[0] + y[1]*y[1]),this);
}

void in_source(double *y_source,ListHndl sourcelist){
  return;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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 <jni.h>
#include <errno.h>
#include <android_native_app_glue.h>

#include "UtH/Platform/OpenGL.hpp"

#ifndef MATH_H_UMATH
namespace umath
{
	struct vector2
	{
		int x,y;
	};
}
#endif

//Struct containing EGL stugg and android app
struct AndroidEngine
{
	android_app* app;

	//Below this to Graphics-classs?
	EGLDisplay display;
	EGLSurface surface;
	EGLContext context;
	EGLConfig config;

	umath::vector2 resolution;
};

//To Graphics init or Renderer class
int displayInit(AndroidEngine* androidengine)
{
	const EGLint attribs[] =
	{
		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
		EGL_RED_SIZE, 8,
		EGL_GREEN_SIZE, 8,
		EGL_BLUE_SIZE, 8,
		EGL_ALPHA_SIZE, 8,
		EGL_NONE
	};

	EGLint attribList[] =
	{
		EGL_CONTEXT_CLIENT_VERSION, 2,
		EGL_NONE
	};

	EGLint format, numConfigs;

	androidengine->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	eglInitialize(androidengine->display,0,0);

	eglChooseConfig(androidengine->display, attribs, &androidengine->config, 1, &numConfigs);
	eglGetConfigAttrib(androidengine->display, androidengine->config, EGL_NATIVE_VISUAL_ID, &format);

	ANativeWindow_setBuffersGeometry(androidengine->app->window, 0, 0, format);

	androidengine->surface = eglCreateWindowSurface(androidengine->display, androidengine->surface, androidengine->app->window, NULL);
	androidengine->context = eglCreateContext(androidengine->display, androidengine->config, NULL, attribList);

	if(eglMakeCurrent(androidengine->display, androidengine->surface, androidengine->surface, androidengine->context) == false)
	{
		//WriteLog("eglMakeCurrent failed");
		return -1;
	}

	eglQuerySurface(androidengine->display, androidengine->surface, EGL_WIDTH, &androidengine->resolution.x);
	eglQuerySurface(androidengine->display, androidengine->surface, EGL_HEIGHT, &androidengine->resolution.y);

	glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST);
	glEnable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);
	glViewport(0,0,androidengine->resolution.x,androidengine->resolution.y);

	return 0;
}

void displayDestroy(AndroidEngine* androidengine)
{
	if(androidengine->display != EGL_NO_DISPLAY)
	{
		eglMakeCurrent(androidengine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
		if(androidengine->display != EGL_NO_DISPLAY)
		{
			eglDestroyContext(androidengine->display, androidengine->context);
		}
		if (androidengine->surface != EGL_NO_SURFACE)
		{
			eglDestroySurface(androidengine->display, androidengine->surface);
		}
		eglTerminate(androidengine->display);
	}
	androidengine->display = EGL_NO_DISPLAY;
	androidengine->context = EGL_NO_CONTEXT;
	androidengine->surface = EGL_NO_SURFACE;
}

//After input manager
int handle_input(android_app* app, AInputEvent* event)
{
	AndroidEngine* androidengine = (AndroidEngine*)app->userData;
	//Input should be places here
	return 0;
}

void draw_frame(AndroidEngine* androidengine)
{

}

//This is sort of state manager. Checks is Activity on top or not and does it have saved state
void handle_cmd(android_app* app, int cmd)
{
	AndroidEngine* androidengine = (AndroidEngine*)app->userData;

	switch (cmd)
	{
	case APP_CMD_SAVE_STATE:
		break;
	case APP_CMD_INIT_WINDOW:
		if (androidengine->app->window != NULL)
		{
			displayInit(androidengine);
			draw_frame(androidengine);
		}
		break;
	case APP_CMD_TERM_WINDOW:
		displayDestroy(androidengine);
		break;
	case APP_CMD_LOST_FOCUS:
		draw_frame(androidengine);
		break;
	}
}

void android_main(android_app* state)
{
	AndroidEngine androidengine;

	app_dummy();

	memset(&androidengine, 0, sizeof(AndroidEngine));

	state->userData = &androidengine;
	state->onAppCmd = handle_cmd;
	state->onInputEvent = handle_input;

	androidengine.app = state;

	while(1)
	{
		int ident;
		int events;
		android_poll_source* source;

		while ((ident=ALooper_pollAll(0, NULL, &events,(void**)&source)) >= 0)
		{
			//Insteads of these two 'if' statement proper exit should be placed
			if (source != NULL)
			{
				source->process(state, source);
			}
			if (state->destroyRequested != 0)
			{
				displayDestroy(&androidengine);
				return;
			}
		}

		if(androidengine.display == NULL)
		{
			;//Do nothing
		}
		else
		{
			//engine->Update();
		}
	}
}<commit_msg>Added UtH Debug<commit_after>/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * 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 <jni.h>
#include <errno.h>
#include <android_native_app_glue.h>

#include "UtH/Platform/OpenGL.hpp"
#include "UtH/Platform/Debug.hpp"

#ifndef MATH_H_UMATH
namespace umath
{
	struct vector2
	{
		int x,y;
	};
}
#endif

//Struct containing EGL stugg and android app
struct AndroidEngine
{
	android_app* app;

	//Below this to Graphics-classs?
	EGLDisplay display;
	EGLSurface surface;
	EGLContext context;
	EGLConfig config;

	umath::vector2 resolution;
};

//To Graphics init or Renderer class
int displayInit(AndroidEngine* androidengine)
{
	const EGLint attribs[] =
	{
		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
		EGL_RED_SIZE, 8,
		EGL_GREEN_SIZE, 8,
		EGL_BLUE_SIZE, 8,
		EGL_ALPHA_SIZE, 8,
		EGL_NONE
	};

	EGLint attribList[] =
	{
		EGL_CONTEXT_CLIENT_VERSION, 2,
		EGL_NONE
	};

	EGLint format, numConfigs;

	androidengine->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	eglInitialize(androidengine->display,0,0);

	eglChooseConfig(androidengine->display, attribs, &androidengine->config, 1, &numConfigs);
	eglGetConfigAttrib(androidengine->display, androidengine->config, EGL_NATIVE_VISUAL_ID, &format);

	ANativeWindow_setBuffersGeometry(androidengine->app->window, 0, 0, format);

	androidengine->surface = eglCreateWindowSurface(androidengine->display, androidengine->surface, androidengine->app->window, NULL);
	androidengine->context = eglCreateContext(androidengine->display, androidengine->config, NULL, attribList);

	if(eglMakeCurrent(androidengine->display, androidengine->surface, androidengine->surface, androidengine->context) == false)
	{
		WriteLog("eglMakeCurrent failed");
		return -1;
	}

	eglQuerySurface(androidengine->display, androidengine->surface, EGL_WIDTH, &androidengine->resolution.x);
	eglQuerySurface(androidengine->display, androidengine->surface, EGL_HEIGHT, &androidengine->resolution.y);

	glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST);
	glEnable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);
	glViewport(0,0,androidengine->resolution.x,androidengine->resolution.y);

	return 0;
}

void displayDestroy(AndroidEngine* androidengine)
{
	if(androidengine->display != EGL_NO_DISPLAY)
	{
		eglMakeCurrent(androidengine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
		if(androidengine->display != EGL_NO_DISPLAY)
		{
			eglDestroyContext(androidengine->display, androidengine->context);
		}
		if (androidengine->surface != EGL_NO_SURFACE)
		{
			eglDestroySurface(androidengine->display, androidengine->surface);
		}
		eglTerminate(androidengine->display);
	}
	androidengine->display = EGL_NO_DISPLAY;
	androidengine->context = EGL_NO_CONTEXT;
	androidengine->surface = EGL_NO_SURFACE;
}

//After input manager
int handle_input(android_app* app, AInputEvent* event)
{
	AndroidEngine* androidengine = (AndroidEngine*)app->userData;
	//Input should be places here
	return 0;
}

void draw_frame(AndroidEngine* androidengine)
{

}

//This is sort of state manager. Checks is Activity on top or not and does it have saved state
void handle_cmd(android_app* app, int cmd)
{
	AndroidEngine* androidengine = (AndroidEngine*)app->userData;

	switch (cmd)
	{
	case APP_CMD_SAVE_STATE:
		break;
	case APP_CMD_INIT_WINDOW:
		if (androidengine->app->window != NULL)
		{
			displayInit(androidengine);
			draw_frame(androidengine);
		}
		break;
	case APP_CMD_TERM_WINDOW:
		displayDestroy(androidengine);
		break;
	case APP_CMD_LOST_FOCUS:
		draw_frame(androidengine);
		break;
	}
}

void android_main(android_app* state)
{
	AndroidEngine androidengine;

	app_dummy();

	memset(&androidengine, 0, sizeof(AndroidEngine));

	state->userData = &androidengine;
	state->onAppCmd = handle_cmd;
	state->onInputEvent = handle_input;

	androidengine.app = state;

	while(1)
	{
		int ident;
		int events;
		android_poll_source* source;

		while ((ident=ALooper_pollAll(0, NULL, &events,(void**)&source)) >= 0)
		{
			//Insteads of these two 'if' statement proper exit should be placed
			if (source != NULL)
			{
				source->process(state, source);
			}
			if (state->destroyRequested != 0)
			{
				displayDestroy(&androidengine);
				return;
			}
		}

		if(androidengine.display == NULL)
		{
			;//Do nothing
		}
		else
		{
			//engine->Update();
		}
	}
}<|endoftext|>


<commit_before>// Copyright 2017 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 "flutter/lib/ui/painting/codec.h"

#include "flutter/common/task_runners.h"
#include "flutter/glue/trace_event.h"
#include "flutter/lib/ui/painting/frame_info.h"
#include "lib/fxl/functional/make_copyable.h"
#include "lib/fxl/logging.h"
#include "lib/tonic/dart_binding_macros.h"
#include "lib/tonic/dart_library_natives.h"
#include "lib/tonic/dart_state.h"
#include "lib/tonic/logging/dart_invoke.h"
#include "lib/tonic/typed_data/uint8_list.h"
#include "third_party/skia/include/codec/SkCodec.h"
#include "third_party/skia/include/core/SkPixelRef.h"

#ifdef ERROR
#undef ERROR
#endif

using tonic::DartInvoke;
using tonic::DartPersistentValue;
using tonic::ToDart;

namespace blink {

namespace {

static constexpr const char* kInitCodecTraceTag = "InitCodec";
static constexpr const char* kCodecNextFrameTraceTag = "CodecNextFrame";

static void InvokeCodecCallback(fxl::RefPtr<Codec> codec,
                                std::unique_ptr<DartPersistentValue> callback,
                                size_t trace_id) {
  tonic::DartState* dart_state = callback->dart_state().get();
  if (!dart_state) {
    TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id);
    return;
  }
  tonic::DartState::Scope scope(dart_state);
  if (!codec) {
    DartInvoke(callback->value(), {Dart_Null()});
  } else {
    DartInvoke(callback->value(), {ToDart(codec)});
  }
  TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id);
}

static sk_sp<SkImage> DecodeImage(fml::WeakPtr<GrContext> context,
                                  sk_sp<SkData> buffer,
                                  size_t trace_id) {
  TRACE_FLOW_STEP("flutter", kInitCodecTraceTag, trace_id);
  TRACE_EVENT0("flutter", "DecodeImage");

  if (buffer == nullptr || buffer->isEmpty()) {
    return nullptr;
  }

  if (context) {
    // This indicates that we do not want a "linear blending" decode.
    sk_sp<SkColorSpace> dstColorSpace = nullptr;
    return SkImage::MakeCrossContextFromEncoded(
        context.get(), std::move(buffer), false, dstColorSpace.get());
  } else {
    // Defer decoding until time of draw later on the GPU thread. Can happen
    // when GL operations are currently forbidden such as in the background
    // on iOS.
    return SkImage::MakeFromEncoded(std::move(buffer));
  }
}

fxl::RefPtr<Codec> InitCodec(fml::WeakPtr<GrContext> context,
                             sk_sp<SkData> buffer,
                             fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
                             size_t trace_id) {
  TRACE_FLOW_STEP("flutter", kInitCodecTraceTag, trace_id);
  TRACE_EVENT0("blink", "InitCodec");

  if (buffer == nullptr || buffer->isEmpty()) {
    FXL_LOG(ERROR) << "InitCodec failed - buffer was empty ";
    return nullptr;
  }

  std::unique_ptr<SkCodec> skCodec = SkCodec::MakeFromData(buffer);
  if (!skCodec) {
    FXL_LOG(ERROR) << "Failed decoding image. Data is either invalid, or it is "
                      "encoded using an unsupported format.";
    return nullptr;
  }
  if (skCodec->getFrameCount() > 1) {
    return fxl::MakeRefCounted<MultiFrameCodec>(std::move(skCodec));
  }
  auto skImage = DecodeImage(context, buffer, trace_id);
  if (!skImage) {
    FXL_LOG(ERROR) << "DecodeImage failed";
    return nullptr;
  }
  auto image = CanvasImage::Create();
  image->set_image({skImage, unref_queue});
  auto frameInfo = fxl::MakeRefCounted<FrameInfo>(std::move(image), 0);
  return fxl::MakeRefCounted<SingleFrameCodec>(std::move(frameInfo));
}

void InitCodecAndInvokeCodecCallback(
    fxl::RefPtr<fxl::TaskRunner> ui_task_runner,
    fml::WeakPtr<GrContext> context,
    fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
    std::unique_ptr<DartPersistentValue> callback,
    sk_sp<SkData> buffer,
    size_t trace_id) {
  auto codec =
      InitCodec(context, std::move(buffer), std::move(unref_queue), trace_id);
  ui_task_runner->PostTask(
      fxl::MakeCopyable([callback = std::move(callback),
                         codec = std::move(codec), trace_id]() mutable {
        InvokeCodecCallback(std::move(codec), std::move(callback), trace_id);
      }));
}

void InstantiateImageCodec(Dart_NativeArguments args) {
  static size_t trace_counter = 1;
  const size_t trace_id = trace_counter++;
  TRACE_FLOW_BEGIN("flutter", kInitCodecTraceTag, trace_id);

  Dart_Handle exception = nullptr;

  tonic::Uint8List list =
      tonic::DartConverter<tonic::Uint8List>::FromArguments(args, 0, exception);
  if (exception) {
    TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id);
    Dart_SetReturnValue(args, exception);
    return;
  }

  Dart_Handle callback_handle = Dart_GetNativeArgument(args, 1);
  if (!Dart_IsClosure(callback_handle)) {
    TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id);
    Dart_SetReturnValue(args, ToDart("Callback must be a function"));
    return;
  }

  auto buffer = SkData::MakeWithCopy(list.data(), list.num_elements());

  auto dart_state = UIDartState::Current();

  const auto& task_runners = dart_state->GetTaskRunners();
  task_runners.GetIOTaskRunner()->PostTask(fxl::MakeCopyable(
      [callback = std::make_unique<DartPersistentValue>(
           tonic::DartState::Current(), callback_handle),
       buffer = std::move(buffer), trace_id,
       ui_task_runner = task_runners.GetUITaskRunner(),
       context = dart_state->GetResourceContext(),
       queue = UIDartState::Current()->GetSkiaUnrefQueue()]() mutable {
        InitCodecAndInvokeCodecCallback(std::move(ui_task_runner), context,
                                        std::move(queue), std::move(callback),
                                        std::move(buffer), trace_id);
      }));
}

bool copy_to(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src) {
  SkPixmap srcPM;
  if (!src.peekPixels(&srcPM)) {
    return false;
  }

  SkBitmap tmpDst;
  SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
  if (!tmpDst.setInfo(dstInfo)) {
    return false;
  }

  if (!tmpDst.tryAllocPixels()) {
    return false;
  }

  SkPixmap dstPM;
  if (!tmpDst.peekPixels(&dstPM)) {
    return false;
  }

  if (!srcPM.readPixels(dstPM)) {
    return false;
  }

  dst->swap(tmpDst);
  return true;
}

void InvokeNextFrameCallback(fxl::RefPtr<FrameInfo> frameInfo,
                             std::unique_ptr<DartPersistentValue> callback,
                             size_t trace_id) {
  tonic::DartState* dart_state = callback->dart_state().get();
  if (!dart_state) {
    TRACE_FLOW_END("flutter", kCodecNextFrameTraceTag, trace_id);
    return;
  }
  tonic::DartState::Scope scope(dart_state);
  if (!frameInfo) {
    DartInvoke(callback->value(), {Dart_Null()});
  } else {
    DartInvoke(callback->value(), {ToDart(frameInfo)});
  }
  TRACE_FLOW_END("flutter", kCodecNextFrameTraceTag, trace_id);
}

}  // namespace

IMPLEMENT_WRAPPERTYPEINFO(ui, Codec);

#define FOR_EACH_BINDING(V) \
  V(Codec, getNextFrame)    \
  V(Codec, frameCount)      \
  V(Codec, repetitionCount) \
  V(Codec, dispose)

FOR_EACH_BINDING(DART_NATIVE_CALLBACK)

void Codec::dispose() {
  ClearDartWrapper();
}

MultiFrameCodec::MultiFrameCodec(std::unique_ptr<SkCodec> codec)
    : codec_(std::move(codec)) {
  repetitionCount_ = codec_->getRepetitionCount();
  frameInfos_ = codec_->getFrameInfo();
  frameBitmaps_.resize(frameInfos_.size());
  nextFrameIndex_ = 0;
}

sk_sp<SkImage> MultiFrameCodec::GetNextFrameImage(
    fml::WeakPtr<GrContext> resourceContext) {
  SkBitmap& bitmap = frameBitmaps_[nextFrameIndex_];
  if (!bitmap.getPixels()) {  // We haven't decoded this frame yet
    const SkImageInfo info = codec_->getInfo().makeColorType(kN32_SkColorType);
    bitmap.allocPixels(info);

    SkCodec::Options options;
    options.fFrameIndex = nextFrameIndex_;
    const int requiredFrame = frameInfos_[nextFrameIndex_].fRequiredFrame;
    if (requiredFrame != SkCodec::kNone) {
      if (requiredFrame < 0 ||
          static_cast<size_t>(requiredFrame) >= frameBitmaps_.size()) {
        FXL_LOG(ERROR) << "Frame " << nextFrameIndex_ << " depends on frame "
                       << requiredFrame << " which out of range (0,"
                       << frameBitmaps_.size() << ").";
        return NULL;
      }
      SkBitmap& requiredBitmap = frameBitmaps_[requiredFrame];
      // For simplicity, do not try to cache old frames
      if (requiredBitmap.getPixels() &&
          copy_to(&bitmap, requiredBitmap.colorType(), requiredBitmap)) {
        options.fPriorFrame = requiredFrame;
      }
    }

    if (SkCodec::kSuccess != codec_->getPixels(info, bitmap.getPixels(),
                                               bitmap.rowBytes(), &options)) {
      FXL_LOG(ERROR) << "Could not getPixels for frame " << nextFrameIndex_;
      return NULL;
    }
  }

  if (resourceContext) {
    SkPixmap pixmap(bitmap.info(), bitmap.pixelRef()->pixels(),
                    bitmap.pixelRef()->rowBytes());
    // This indicates that we do not want a "linear blending" decode.
    sk_sp<SkColorSpace> dstColorSpace = nullptr;
    return SkImage::MakeCrossContextFromPixmap(resourceContext.get(), pixmap,
                                               false, dstColorSpace.get());
  } else {
    // Defer decoding until time of draw later on the GPU thread. Can happen
    // when GL operations are currently forbidden such as in the background
    // on iOS.
    return SkImage::MakeFromBitmap(bitmap);
  }
}

void MultiFrameCodec::GetNextFrameAndInvokeCallback(
    std::unique_ptr<DartPersistentValue> callback,
    fxl::RefPtr<fxl::TaskRunner> ui_task_runner,
    fml::WeakPtr<GrContext> resourceContext,
    fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
    size_t trace_id) {
  fxl::RefPtr<FrameInfo> frameInfo = NULL;
  sk_sp<SkImage> skImage = GetNextFrameImage(resourceContext);
  if (skImage) {
    fxl::RefPtr<CanvasImage> image = CanvasImage::Create();
    image->set_image({skImage, std::move(unref_queue)});
    frameInfo = fxl::MakeRefCounted<FrameInfo>(
        std::move(image), frameInfos_[nextFrameIndex_].fDuration);
  }
  nextFrameIndex_ = (nextFrameIndex_ + 1) % frameInfos_.size();

  ui_task_runner->PostTask(fxl::MakeCopyable(
      [callback = std::move(callback), frameInfo, trace_id]() mutable {
        InvokeNextFrameCallback(frameInfo, std::move(callback), trace_id);
      }));

  TRACE_FLOW_END("flutter", kCodecNextFrameTraceTag, trace_id);
}

Dart_Handle MultiFrameCodec::getNextFrame(Dart_Handle callback_handle) {
  static size_t trace_counter = 1;
  const size_t trace_id = trace_counter++;
  TRACE_FLOW_BEGIN("flutter", kCodecNextFrameTraceTag, trace_id);

  if (!Dart_IsClosure(callback_handle)) {
    TRACE_FLOW_END("flutter", kCodecNextFrameTraceTag, trace_id);
    return ToDart("Callback must be a function");
  }

  auto dart_state = UIDartState::Current();

  const auto& task_runners = dart_state->GetTaskRunners();

  task_runners.GetIOTaskRunner()->PostTask(fxl::MakeCopyable(
      [callback = std::make_unique<DartPersistentValue>(
           tonic::DartState::Current(), callback_handle),
       this, trace_id, ui_task_runner = task_runners.GetUITaskRunner(),
       queue = UIDartState::Current()->GetSkiaUnrefQueue(),
       context = dart_state->GetResourceContext()]() mutable {
        GetNextFrameAndInvokeCallback(std::move(callback),
                                      std::move(ui_task_runner), context,
                                      std::move(queue), trace_id);
      }));

  return Dart_Null();
}

Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle callback_handle) {
  if (!Dart_IsClosure(callback_handle)) {
    return ToDart("Callback must be a function");
  }

  auto callback = std::make_unique<DartPersistentValue>(
      tonic::DartState::Current(), callback_handle);
  tonic::DartState* dart_state = callback->dart_state().get();
  if (!dart_state) {
    return ToDart("Invalid dart state");
  }

  tonic::DartState::Scope scope(dart_state);
  DartInvoke(callback->value(), {ToDart(frame_)});
  return Dart_Null();
}

void Codec::RegisterNatives(tonic::DartLibraryNatives* natives) {
  natives->Register({
      {"instantiateImageCodec", InstantiateImageCodec, 2, true},
  });
  natives->Register({FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}

}  // namespace blink
<commit_msg>Enable downscale of very large images when uploading on IO thread (#5011)<commit_after>// Copyright 2017 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 "flutter/lib/ui/painting/codec.h"

#include "flutter/common/task_runners.h"
#include "flutter/glue/trace_event.h"
#include "flutter/lib/ui/painting/frame_info.h"
#include "lib/fxl/functional/make_copyable.h"
#include "lib/fxl/logging.h"
#include "lib/tonic/dart_binding_macros.h"
#include "lib/tonic/dart_library_natives.h"
#include "lib/tonic/dart_state.h"
#include "lib/tonic/logging/dart_invoke.h"
#include "lib/tonic/typed_data/uint8_list.h"
#include "third_party/skia/include/codec/SkCodec.h"
#include "third_party/skia/include/core/SkPixelRef.h"

#ifdef ERROR
#undef ERROR
#endif

using tonic::DartInvoke;
using tonic::DartPersistentValue;
using tonic::ToDart;

namespace blink {

namespace {

static constexpr const char* kInitCodecTraceTag = "InitCodec";
static constexpr const char* kCodecNextFrameTraceTag = "CodecNextFrame";

static void InvokeCodecCallback(fxl::RefPtr<Codec> codec,
                                std::unique_ptr<DartPersistentValue> callback,
                                size_t trace_id) {
  tonic::DartState* dart_state = callback->dart_state().get();
  if (!dart_state) {
    TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id);
    return;
  }
  tonic::DartState::Scope scope(dart_state);
  if (!codec) {
    DartInvoke(callback->value(), {Dart_Null()});
  } else {
    DartInvoke(callback->value(), {ToDart(codec)});
  }
  TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id);
}

static sk_sp<SkImage> DecodeImage(fml::WeakPtr<GrContext> context,
                                  sk_sp<SkData> buffer,
                                  size_t trace_id) {
  TRACE_FLOW_STEP("flutter", kInitCodecTraceTag, trace_id);
  TRACE_EVENT0("flutter", "DecodeImage");

  if (buffer == nullptr || buffer->isEmpty()) {
    return nullptr;
  }

  if (context) {
    // This indicates that we do not want a "linear blending" decode.
    sk_sp<SkColorSpace> dstColorSpace = nullptr;
    return SkImage::MakeCrossContextFromEncoded(
        context.get(), std::move(buffer), false, dstColorSpace.get(), true);
  } else {
    // Defer decoding until time of draw later on the GPU thread. Can happen
    // when GL operations are currently forbidden such as in the background
    // on iOS.
    return SkImage::MakeFromEncoded(std::move(buffer));
  }
}

fxl::RefPtr<Codec> InitCodec(fml::WeakPtr<GrContext> context,
                             sk_sp<SkData> buffer,
                             fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
                             size_t trace_id) {
  TRACE_FLOW_STEP("flutter", kInitCodecTraceTag, trace_id);
  TRACE_EVENT0("blink", "InitCodec");

  if (buffer == nullptr || buffer->isEmpty()) {
    FXL_LOG(ERROR) << "InitCodec failed - buffer was empty ";
    return nullptr;
  }

  std::unique_ptr<SkCodec> skCodec = SkCodec::MakeFromData(buffer);
  if (!skCodec) {
    FXL_LOG(ERROR) << "Failed decoding image. Data is either invalid, or it is "
                      "encoded using an unsupported format.";
    return nullptr;
  }
  if (skCodec->getFrameCount() > 1) {
    return fxl::MakeRefCounted<MultiFrameCodec>(std::move(skCodec));
  }
  auto skImage = DecodeImage(context, buffer, trace_id);
  if (!skImage) {
    FXL_LOG(ERROR) << "DecodeImage failed";
    return nullptr;
  }
  auto image = CanvasImage::Create();
  image->set_image({skImage, unref_queue});
  auto frameInfo = fxl::MakeRefCounted<FrameInfo>(std::move(image), 0);
  return fxl::MakeRefCounted<SingleFrameCodec>(std::move(frameInfo));
}

void InitCodecAndInvokeCodecCallback(
    fxl::RefPtr<fxl::TaskRunner> ui_task_runner,
    fml::WeakPtr<GrContext> context,
    fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
    std::unique_ptr<DartPersistentValue> callback,
    sk_sp<SkData> buffer,
    size_t trace_id) {
  auto codec =
      InitCodec(context, std::move(buffer), std::move(unref_queue), trace_id);
  ui_task_runner->PostTask(
      fxl::MakeCopyable([callback = std::move(callback),
                         codec = std::move(codec), trace_id]() mutable {
        InvokeCodecCallback(std::move(codec), std::move(callback), trace_id);
      }));
}

void InstantiateImageCodec(Dart_NativeArguments args) {
  static size_t trace_counter = 1;
  const size_t trace_id = trace_counter++;
  TRACE_FLOW_BEGIN("flutter", kInitCodecTraceTag, trace_id);

  Dart_Handle exception = nullptr;

  tonic::Uint8List list =
      tonic::DartConverter<tonic::Uint8List>::FromArguments(args, 0, exception);
  if (exception) {
    TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id);
    Dart_SetReturnValue(args, exception);
    return;
  }

  Dart_Handle callback_handle = Dart_GetNativeArgument(args, 1);
  if (!Dart_IsClosure(callback_handle)) {
    TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id);
    Dart_SetReturnValue(args, ToDart("Callback must be a function"));
    return;
  }

  auto buffer = SkData::MakeWithCopy(list.data(), list.num_elements());

  auto dart_state = UIDartState::Current();

  const auto& task_runners = dart_state->GetTaskRunners();
  task_runners.GetIOTaskRunner()->PostTask(fxl::MakeCopyable(
      [callback = std::make_unique<DartPersistentValue>(
           tonic::DartState::Current(), callback_handle),
       buffer = std::move(buffer), trace_id,
       ui_task_runner = task_runners.GetUITaskRunner(),
       context = dart_state->GetResourceContext(),
       queue = UIDartState::Current()->GetSkiaUnrefQueue()]() mutable {
        InitCodecAndInvokeCodecCallback(std::move(ui_task_runner), context,
                                        std::move(queue), std::move(callback),
                                        std::move(buffer), trace_id);
      }));
}

bool copy_to(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src) {
  SkPixmap srcPM;
  if (!src.peekPixels(&srcPM)) {
    return false;
  }

  SkBitmap tmpDst;
  SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
  if (!tmpDst.setInfo(dstInfo)) {
    return false;
  }

  if (!tmpDst.tryAllocPixels()) {
    return false;
  }

  SkPixmap dstPM;
  if (!tmpDst.peekPixels(&dstPM)) {
    return false;
  }

  if (!srcPM.readPixels(dstPM)) {
    return false;
  }

  dst->swap(tmpDst);
  return true;
}

void InvokeNextFrameCallback(fxl::RefPtr<FrameInfo> frameInfo,
                             std::unique_ptr<DartPersistentValue> callback,
                             size_t trace_id) {
  tonic::DartState* dart_state = callback->dart_state().get();
  if (!dart_state) {
    TRACE_FLOW_END("flutter", kCodecNextFrameTraceTag, trace_id);
    return;
  }
  tonic::DartState::Scope scope(dart_state);
  if (!frameInfo) {
    DartInvoke(callback->value(), {Dart_Null()});
  } else {
    DartInvoke(callback->value(), {ToDart(frameInfo)});
  }
  TRACE_FLOW_END("flutter", kCodecNextFrameTraceTag, trace_id);
}

}  // namespace

IMPLEMENT_WRAPPERTYPEINFO(ui, Codec);

#define FOR_EACH_BINDING(V) \
  V(Codec, getNextFrame)    \
  V(Codec, frameCount)      \
  V(Codec, repetitionCount) \
  V(Codec, dispose)

FOR_EACH_BINDING(DART_NATIVE_CALLBACK)

void Codec::dispose() {
  ClearDartWrapper();
}

MultiFrameCodec::MultiFrameCodec(std::unique_ptr<SkCodec> codec)
    : codec_(std::move(codec)) {
  repetitionCount_ = codec_->getRepetitionCount();
  frameInfos_ = codec_->getFrameInfo();
  frameBitmaps_.resize(frameInfos_.size());
  nextFrameIndex_ = 0;
}

sk_sp<SkImage> MultiFrameCodec::GetNextFrameImage(
    fml::WeakPtr<GrContext> resourceContext) {
  SkBitmap& bitmap = frameBitmaps_[nextFrameIndex_];
  if (!bitmap.getPixels()) {  // We haven't decoded this frame yet
    const SkImageInfo info = codec_->getInfo().makeColorType(kN32_SkColorType);
    bitmap.allocPixels(info);

    SkCodec::Options options;
    options.fFrameIndex = nextFrameIndex_;
    const int requiredFrame = frameInfos_[nextFrameIndex_].fRequiredFrame;
    if (requiredFrame != SkCodec::kNone) {
      if (requiredFrame < 0 ||
          static_cast<size_t>(requiredFrame) >= frameBitmaps_.size()) {
        FXL_LOG(ERROR) << "Frame " << nextFrameIndex_ << " depends on frame "
                       << requiredFrame << " which out of range (0,"
                       << frameBitmaps_.size() << ").";
        return NULL;
      }
      SkBitmap& requiredBitmap = frameBitmaps_[requiredFrame];
      // For simplicity, do not try to cache old frames
      if (requiredBitmap.getPixels() &&
          copy_to(&bitmap, requiredBitmap.colorType(), requiredBitmap)) {
        options.fPriorFrame = requiredFrame;
      }
    }

    if (SkCodec::kSuccess != codec_->getPixels(info, bitmap.getPixels(),
                                               bitmap.rowBytes(), &options)) {
      FXL_LOG(ERROR) << "Could not getPixels for frame " << nextFrameIndex_;
      return NULL;
    }
  }

  if (resourceContext) {
    SkPixmap pixmap(bitmap.info(), bitmap.pixelRef()->pixels(),
                    bitmap.pixelRef()->rowBytes());
    // This indicates that we do not want a "linear blending" decode.
    sk_sp<SkColorSpace> dstColorSpace = nullptr;
    return SkImage::MakeCrossContextFromPixmap(resourceContext.get(), pixmap,
                                               false, dstColorSpace.get());
  } else {
    // Defer decoding until time of draw later on the GPU thread. Can happen
    // when GL operations are currently forbidden such as in the background
    // on iOS.
    return SkImage::MakeFromBitmap(bitmap);
  }
}

void MultiFrameCodec::GetNextFrameAndInvokeCallback(
    std::unique_ptr<DartPersistentValue> callback,
    fxl::RefPtr<fxl::TaskRunner> ui_task_runner,
    fml::WeakPtr<GrContext> resourceContext,
    fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
    size_t trace_id) {
  fxl::RefPtr<FrameInfo> frameInfo = NULL;
  sk_sp<SkImage> skImage = GetNextFrameImage(resourceContext);
  if (skImage) {
    fxl::RefPtr<CanvasImage> image = CanvasImage::Create();
    image->set_image({skImage, std::move(unref_queue)});
    frameInfo = fxl::MakeRefCounted<FrameInfo>(
        std::move(image), frameInfos_[nextFrameIndex_].fDuration);
  }
  nextFrameIndex_ = (nextFrameIndex_ + 1) % frameInfos_.size();

  ui_task_runner->PostTask(fxl::MakeCopyable(
      [callback = std::move(callback), frameInfo, trace_id]() mutable {
        InvokeNextFrameCallback(frameInfo, std::move(callback), trace_id);
      }));

  TRACE_FLOW_END("flutter", kCodecNextFrameTraceTag, trace_id);
}

Dart_Handle MultiFrameCodec::getNextFrame(Dart_Handle callback_handle) {
  static size_t trace_counter = 1;
  const size_t trace_id = trace_counter++;
  TRACE_FLOW_BEGIN("flutter", kCodecNextFrameTraceTag, trace_id);

  if (!Dart_IsClosure(callback_handle)) {
    TRACE_FLOW_END("flutter", kCodecNextFrameTraceTag, trace_id);
    return ToDart("Callback must be a function");
  }

  auto dart_state = UIDartState::Current();

  const auto& task_runners = dart_state->GetTaskRunners();

  task_runners.GetIOTaskRunner()->PostTask(fxl::MakeCopyable(
      [callback = std::make_unique<DartPersistentValue>(
           tonic::DartState::Current(), callback_handle),
       this, trace_id, ui_task_runner = task_runners.GetUITaskRunner(),
       queue = UIDartState::Current()->GetSkiaUnrefQueue(),
       context = dart_state->GetResourceContext()]() mutable {
        GetNextFrameAndInvokeCallback(std::move(callback),
                                      std::move(ui_task_runner), context,
                                      std::move(queue), trace_id);
      }));

  return Dart_Null();
}

Dart_Handle SingleFrameCodec::getNextFrame(Dart_Handle callback_handle) {
  if (!Dart_IsClosure(callback_handle)) {
    return ToDart("Callback must be a function");
  }

  auto callback = std::make_unique<DartPersistentValue>(
      tonic::DartState::Current(), callback_handle);
  tonic::DartState* dart_state = callback->dart_state().get();
  if (!dart_state) {
    return ToDart("Invalid dart state");
  }

  tonic::DartState::Scope scope(dart_state);
  DartInvoke(callback->value(), {ToDart(frame_)});
  return Dart_Null();
}

void Codec::RegisterNatives(tonic::DartLibraryNatives* natives) {
  natives->Register({
      {"instantiateImageCodec", InstantiateImageCodec, 2, true},
  });
  natives->Register({FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}

}  // namespace blink
<|endoftext|>


<commit_before>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999, 2000 Stefan Seefeld <stefan@berlin-consortium.org>
 * Copyright (C) 1999 Graydon Hoare <graydon@pobox.com>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */

#include <Prague/Sys/Tracer.hh>
#include <Prague/Sys/Signal.hh>
#include <Prague/Sys/Profiler.hh>
#include <Prague/Sys/Timer.hh>
#include <Prague/Sys/Path.hh>
#include <Prague/Sys/User.hh>
#include <Prague/Sys/Fork.hh>
#include <Prague/Sys/GetOpt.hh>
#include <Warsaw/config.hh>
#include <Warsaw/resolve.hh>
#include <Warsaw/LayoutKit.hh>
#include <Warsaw/ToolKit.hh>
#include <Warsaw/DrawingKit.hh>
#include <Berlin/RCManager.hh>
#include <Berlin/ScreenImpl.hh>
#include <Berlin/ScreenManager.hh>
#include <Berlin/ServerImpl.hh>
#include <Berlin/Console.hh>
#include <Berlin/Logger.hh>
#include <Berlin/DesktopImpl.hh>
#include <fstream>

#ifdef RC_PREFIX
const std::string prefix = RC_PREFIX;
#else
const std::string prefix = "";
#endif

#ifdef VERSION
const std::string version = VERSION;
#else
const std::string version = "unknown";
#endif

#ifdef JPROF
// probably need to change include path
#include "jprof.h"
#endif

using namespace Prague;
using namespace Warsaw;

struct Dump : Signal::Notifier
{
  void notify(int signo)
    {
      switch (signo)
	{
	case Signal::usr2:
	  Console::activate_autoplay();
	  Console::wakeup();
	  return;
	case Signal::hangup: Profiler::dump(cerr); break;
	case Signal::abort:
	case Signal::segv:
          {
            std::string output = "server.log";
            std::ofstream ofs(output.c_str());
	    Logger::dump(ofs);
	    Tracer::dump(ofs);
	    std::cerr << "Something went wrong. '" << output << "' contains a debugging log.\n"
		      << "Please mail this output to bugs@berlin-consortium.org\n\n";
            exit(-1);
          }
	}
    }
};

//. Execute a client using the command in 'value'. The process is stored in
//. client
void exec_child(Fork*& child, std::string& value)
{
  // Fork to create child process to execute client in
  child = new Fork(true, true);
  if (child->child())
    {
      std::vector<char*> args;
      // Split 'value' into command and arguments for execvp
      int start = 0, index = 0;
      value.push_back('\0');
      while ( (index = value.find(' ', index)) != std::string::npos)
	{
	  value[index] = '\0';
	  args.push_back(value.begin() + start);
	  start = index + 1;
	}
      args.push_back(value.begin() + start);
      args.push_back(NULL);

      // Execute command
      execvp(args[0], args.begin());

      // Should not get here
      perror("client execvp");
      exit(1);
    }
  // Attempt to kill client on these signals
  child->suicide_on_signal(Signal::interrupt);
  child->suicide_on_signal(Signal::quit);
  child->suicide_on_signal(Signal::abort);
  child->suicide_on_signal(Signal::segv);
}

int main(int argc, char **argv)
{
  /*
   * start with some administrative stuff...
   */
  Dump *dump = new Dump;
  Signal::set(Signal::usr2, dump);
  Signal::set(Signal::abort, dump);
  Signal::set(Signal::segv, dump);
  Signal::set(Signal::hangup, dump);
  if (~prefix.empty()) RCManager::read(prefix + "/share/berlin/berlinrc");

  const char *rcfile = getenv("BERLINRC");
  if (rcfile) RCManager::read(Prague::Path::expand_user(rcfile));
  else RCManager::read(std::string(User().home()) + "/.berlin");
  GetOpt getopt(argv[0], "a berlin display server");
  getopt.add('h', "help", GetOpt::novalue, "help message");
  getopt.add('v', "version", GetOpt::novalue, "version number");
  getopt.add('l', "logging", GetOpt::novalue, "switch logging on");
  getopt.add('p', "profiling", GetOpt::novalue, "switch profiling on");
  getopt.add('d', "drawing", GetOpt::mandatory, "the DrawingKit to choose");
  getopt.add('r', "resource", GetOpt::mandatory, "the resource file to load");
  getopt.add('e', "execute", GetOpt::mandatory, "the command to execute upon startup");
  size_t argo = getopt.parse(argc, argv);
  argc -= argo;
  argv += argo;
  std::string value;
  getopt.get("version", &value);
  if (value == "true") { cout << "version is " << version << endl; return 0;}
  value = "";
  getopt.get("help", &value);
  if (value == "true") { getopt.usage(); return 0;}
  value = "";
  getopt.get("resource", &value);
  if (!value.empty()) RCManager::read(Prague::Path::expand_user(value));
  value = "";
  getopt.get("logging", &value);
  if (value == "true")
    {
      Logger::set(Logger::corba);
      Logger::set(Logger::focus);
      Logger::set(Logger::image);
      Logger::set(Logger::loader);
      Logger::set(Logger::subject);
      Logger::set(Logger::layout);
      Logger::set(Logger::picking);
      Logger::set(Logger::drawing);
      Logger::set(Logger::traversal);
      Logger::set(Logger::widget);
      Logger::set(Logger::text);
      Tracer::logging(true);
    }

#ifdef JPROF
  value = "";
  getopt.get("profiling", &value);
  if (value == "true") setupProfilingStuff();
#endif

  /*
   * ...then start the ORB...
   */
  CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "omniORB3");
  PortableServer::POA_var poa = resolve_init<PortableServer::POA>(orb, "RootPOA");
  PortableServer::POAManager_var pman = poa->the_POAManager();
  pman->activate();

  Logger::log(Logger::corba) << "root POA is activated" << std::endl;

  Console::open(argc, argv, poa);

  Logger::log(Logger::main) << "console is initialized" << std::endl;

  /*
   * ...and finally construct the server.
   */
  ServerImpl *server = ServerImpl::instance();

  Prague::Path path = RCManager::get_path("modulepath");
  for (Prague::Path::iterator i = path.begin(); i != path.end(); ++i)
    server->scan(*i);

  Logger::log(Logger::loader) << "modules are loaded" << std::endl;

  Kit::PropertySeq props;
  props.length(1);
  props[0].name = CORBA::string_dup("implementation");
  value = "";
  getopt.get("drawing", &value);
  if (!value.empty()) props[0].value = CORBA::string_dup(value.c_str());
  else props[0].value = CORBA::string_dup("LibArtDrawingKit");
  DrawingKit_var drawing = server->resolve<DrawingKit>("IDL:Warsaw/DrawingKit:1.0", props, poa);
  if (CORBA::is_nil(drawing))
    {
      std::cerr << "unable to open " << "IDL:Warsaw/DrawingKit:1.0" << " with attribute "
		<< props[0].name << '=' << props[0].value << std::endl;
      return -1;
    }

  Logger::log(Logger::drawing) << "drawing system is built" << std::endl;

  // make a Screen graphic to hold this server's scene graph
  ScreenImpl *screen = new ScreenImpl();
  EventManager *emanager = new EventManager(Controller_var(screen->_this()), screen->allocation());
  ScreenManager *smanager = new ScreenManager(Graphic_var(screen->_this()), emanager, drawing);
  screen->bind_managers(emanager, smanager);
  props.length(0);
  ToolKit_var tools = server->resolve<ToolKit>("IDL:Warsaw/ToolKit:1.0", props, poa);
  LayoutKit_var layout = server->resolve<LayoutKit>("IDL:Warsaw/LayoutKit:1.0", props, poa);
  Layout::Stage_var stage = layout->create_stage();
  DesktopImpl *desktop = new DesktopImpl(stage);
  screen->body(Desktop_var(desktop->_this()));
  screen->append_controller(Desktop_var(desktop->_this()));

  Logger::log(Logger::layout) << "desktop is created" << std::endl;

  // initialize the client listener
  server->set_singleton("IDL:Warsaw/Desktop:1.0", Desktop_var(desktop->_this()));
  server->set_singleton("IDL:Warsaw/DrawingKit:1.0", drawing);
  server->start();

  Logger::log(Logger::layout) << "started server" << std::endl;
  bind_name(orb, Server_var(server->_this()), "IDL:Warsaw/Server:1.0");

  Logger::log(Logger::corba) << "listening for clients" << std::endl;
  // initialize the event distributor and draw thread
  Logger::log(Logger::corba) << "event manager is constructed" << std::endl;

  // Start client via --execute argument
  Fork *child = NULL;
  value = "";
  getopt.get("execute", &value);
  if (!value.empty())
    exec_child(child, value);

  try
    {
      smanager->run();
    }
  catch (CORBA::SystemException &se)
    {
      std::cout << "system exception " << std::endl;
    }
  catch(omniORB::fatalException &fe)
    {
      std::cerr << "fatal exception at " << fe.file() << " " << fe.line() << ":" << fe.errmsg() << std::endl;
    }
  catch (...)
    {
      std::cout << "unknown exception caught" << std::endl;
    };

  if (child) delete child;
  orb->destroy();
  return 0;
}
<commit_msg>Increase maxTcpConnectionPerServer so that the new menutest doesnt run out<commit_after>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999, 2000 Stefan Seefeld <stefan@berlin-consortium.org>
 * Copyright (C) 1999 Graydon Hoare <graydon@pobox.com>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */

#include <Prague/Sys/Tracer.hh>
#include <Prague/Sys/Signal.hh>
#include <Prague/Sys/Profiler.hh>
#include <Prague/Sys/Timer.hh>
#include <Prague/Sys/Path.hh>
#include <Prague/Sys/User.hh>
#include <Prague/Sys/Fork.hh>
#include <Prague/Sys/GetOpt.hh>
#include <Warsaw/config.hh>
#include <Warsaw/resolve.hh>
#include <Warsaw/LayoutKit.hh>
#include <Warsaw/ToolKit.hh>
#include <Warsaw/DrawingKit.hh>
#include <Berlin/RCManager.hh>
#include <Berlin/ScreenImpl.hh>
#include <Berlin/ScreenManager.hh>
#include <Berlin/ServerImpl.hh>
#include <Berlin/Console.hh>
#include <Berlin/Logger.hh>
#include <Berlin/DesktopImpl.hh>
#include <fstream>

#ifdef RC_PREFIX
const std::string prefix = RC_PREFIX;
#else
const std::string prefix = "";
#endif

#ifdef VERSION
const std::string version = VERSION;
#else
const std::string version = "unknown";
#endif

#ifdef JPROF
// probably need to change include path
#include "jprof.h"
#endif

using namespace Prague;
using namespace Warsaw;

struct Dump : Signal::Notifier
{
  void notify(int signo)
    {
      switch (signo)
	{
	case Signal::usr2:
	  Console::activate_autoplay();
	  Console::wakeup();
	  return;
	case Signal::hangup: Profiler::dump(cerr); break;
	case Signal::abort:
	case Signal::segv:
          {
            std::string output = "server.log";
            std::ofstream ofs(output.c_str());
	    Logger::dump(ofs);
	    Tracer::dump(ofs);
	    std::cerr << "Something went wrong. '" << output << "' contains a debugging log.\n"
		      << "Please mail this output to bugs@berlin-consortium.org\n\n";
            exit(-1);
          }
	}
    }
};

//. Execute a client using the command in 'value'. The process is stored in
//. client
void exec_child(Fork*& child, std::string& value)
{
  // Fork to create child process to execute client in
  child = new Fork(true, true);
  if (child->child())
    {
      std::vector<char*> args;
      // Split 'value' into command and arguments for execvp
      int start = 0, index = 0;
      value.push_back('\0');
      while ( (index = value.find(' ', index)) != std::string::npos)
	{
	  value[index] = '\0';
	  args.push_back(value.begin() + start);
	  start = index + 1;
	}
      args.push_back(value.begin() + start);
      args.push_back(NULL);

      // Execute command
      execvp(args[0], args.begin());

      // Should not get here
      perror("client execvp");
      exit(1);
    }
  // Attempt to kill client on these signals
  child->suicide_on_signal(Signal::interrupt);
  child->suicide_on_signal(Signal::quit);
  child->suicide_on_signal(Signal::abort);
  child->suicide_on_signal(Signal::segv);
}

int main(int argc, char **argv)
{
  /*
   * start with some administrative stuff...
   */
  Dump *dump = new Dump;
  Signal::set(Signal::usr2, dump);
  Signal::set(Signal::abort, dump);
  Signal::set(Signal::segv, dump);
  Signal::set(Signal::hangup, dump);
  if (~prefix.empty()) RCManager::read(prefix + "/share/berlin/berlinrc");

  const char *rcfile = getenv("BERLINRC");
  if (rcfile) RCManager::read(Prague::Path::expand_user(rcfile));
  else RCManager::read(std::string(User().home()) + "/.berlin");
  GetOpt getopt(argv[0], "a berlin display server");
  getopt.add('h', "help", GetOpt::novalue, "help message");
  getopt.add('v', "version", GetOpt::novalue, "version number");
  getopt.add('l', "logging", GetOpt::novalue, "switch logging on");
  getopt.add('p', "profiling", GetOpt::novalue, "switch profiling on");
  getopt.add('d', "drawing", GetOpt::mandatory, "the DrawingKit to choose");
  getopt.add('r', "resource", GetOpt::mandatory, "the resource file to load");
  getopt.add('e', "execute", GetOpt::mandatory, "the command to execute upon startup");
  size_t argo = getopt.parse(argc, argv);
  argc -= argo;
  argv += argo;
  std::string value;
  getopt.get("version", &value);
  if (value == "true") { cout << "version is " << version << endl; return 0;}
  value = "";
  getopt.get("help", &value);
  if (value == "true") { getopt.usage(); return 0;}
  value = "";
  getopt.get("resource", &value);
  if (!value.empty()) RCManager::read(Prague::Path::expand_user(value));
  value = "";
  getopt.get("logging", &value);
  if (value == "true")
    {
      Logger::set(Logger::corba);
      Logger::set(Logger::focus);
      Logger::set(Logger::image);
      Logger::set(Logger::loader);
      Logger::set(Logger::subject);
      Logger::set(Logger::layout);
      Logger::set(Logger::picking);
      Logger::set(Logger::drawing);
      Logger::set(Logger::traversal);
      Logger::set(Logger::widget);
      Logger::set(Logger::text);
      Tracer::logging(true);
    }

#ifdef JPROF
  value = "";
  getopt.get("profiling", &value);
  if (value == "true") setupProfilingStuff();
#endif

  /*
   * ...then start the ORB...
   */
  omniORB::maxTcpConnectionPerServer = 10;
  CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "omniORB3");
  PortableServer::POA_var poa = resolve_init<PortableServer::POA>(orb, "RootPOA");
  PortableServer::POAManager_var pman = poa->the_POAManager();
  pman->activate();

  Logger::log(Logger::corba) << "root POA is activated" << std::endl;

  Console::open(argc, argv, poa);

  Logger::log(Logger::main) << "console is initialized" << std::endl;

  /*
   * ...and finally construct the server.
   */
  ServerImpl *server = ServerImpl::instance();

  Prague::Path path = RCManager::get_path("modulepath");
  for (Prague::Path::iterator i = path.begin(); i != path.end(); ++i)
    server->scan(*i);

  Logger::log(Logger::loader) << "modules are loaded" << std::endl;

  Kit::PropertySeq props;
  props.length(1);
  props[0].name = CORBA::string_dup("implementation");
  value = "";
  getopt.get("drawing", &value);
  if (!value.empty()) props[0].value = CORBA::string_dup(value.c_str());
  else props[0].value = CORBA::string_dup("LibArtDrawingKit");
  DrawingKit_var drawing = server->resolve<DrawingKit>("IDL:Warsaw/DrawingKit:1.0", props, poa);
  if (CORBA::is_nil(drawing))
    {
      std::cerr << "unable to open " << "IDL:Warsaw/DrawingKit:1.0" << " with attribute "
		<< props[0].name << '=' << props[0].value << std::endl;
      return -1;
    }

  Logger::log(Logger::drawing) << "drawing system is built" << std::endl;

  // make a Screen graphic to hold this server's scene graph
  ScreenImpl *screen = new ScreenImpl();
  EventManager *emanager = new EventManager(Controller_var(screen->_this()), screen->allocation());
  ScreenManager *smanager = new ScreenManager(Graphic_var(screen->_this()), emanager, drawing);
  screen->bind_managers(emanager, smanager);
  props.length(0);
  ToolKit_var tools = server->resolve<ToolKit>("IDL:Warsaw/ToolKit:1.0", props, poa);
  LayoutKit_var layout = server->resolve<LayoutKit>("IDL:Warsaw/LayoutKit:1.0", props, poa);
  Layout::Stage_var stage = layout->create_stage();
  DesktopImpl *desktop = new DesktopImpl(stage);
  screen->body(Desktop_var(desktop->_this()));
  screen->append_controller(Desktop_var(desktop->_this()));

  Logger::log(Logger::layout) << "desktop is created" << std::endl;

  // initialize the client listener
  server->set_singleton("IDL:Warsaw/Desktop:1.0", Desktop_var(desktop->_this()));
  server->set_singleton("IDL:Warsaw/DrawingKit:1.0", drawing);
  server->start();

  Logger::log(Logger::layout) << "started server" << std::endl;
  bind_name(orb, Server_var(server->_this()), "IDL:Warsaw/Server:1.0");

  Logger::log(Logger::corba) << "listening for clients" << std::endl;
  // initialize the event distributor and draw thread
  Logger::log(Logger::corba) << "event manager is constructed" << std::endl;

  // Start client via --execute argument
  Fork *child = NULL;
  value = "";
  getopt.get("execute", &value);
  if (!value.empty())
    exec_child(child, value);

  try
    {
      smanager->run();
    }
  catch (CORBA::SystemException &se)
    {
      std::cout << "system exception " << std::endl;
    }
  catch(omniORB::fatalException &fe)
    {
      std::cerr << "fatal exception at " << fe.file() << " " << fe.line() << ":" << fe.errmsg() << std::endl;
    }
  catch (...)
    {
      std::cout << "unknown exception caught" << std::endl;
    };

  if (child) delete child;
  orb->destroy();
  return 0;
}
<|endoftext|>