<commit_before>#include "boost/filesystem.hpp"
#include "boost/filesystem/fstream.hpp"

#include "soci/soci/src/core/soci.h"
#include "soci/soci/src/backends/sqlite3/soci-sqlite3.h"

#include <algorithm>
#include <cstdlib>
#include <exception>
#include <iostream>
#include <map>
#include <string>
#include <vector>

#include "PlaylistController.h"
#include "SettingsController.h"

using std::cout;
using std::map;
using std::string;
using std::vector;

using namespace soci;

using boost::filesystem::ofstream;
using boost::filesystem::ifstream;
using namespace boost::filesystem;

extern SettingsController sc;

PlaylistController::PlaylistController() {
}

void PlaylistController::addplaylist(Playlist& pl, const int pos) {
	if(pos < 0) {
		playlists.push_back(pl);
		selection = begin() + offset;
		dispoffset = size() - 1;
		dispselection = begin() + dispoffset;
	}
	else if((size_t)pos < playlists.size()) {
		playlists.insert(begin() + pos, pl);
		selection = begin() + offset;
		dispoffset = pos;
		dispselection = begin() + dispoffset;
	}
}

void PlaylistController::autoaddplaylist(path p) {
	if(!exists(p))
		return;
	if(!is_directory(p))
		return;

	string n = p.filename().string();
	if(n.empty())
		return;

	Playlist pl(n);
	map<string,string> shows;

	for(auto i = directory_iterator(p); i != directory_iterator(); ++i) {
		shows[i->path().filename().string()] = i->path().string();
	}

#if __GNUC__ <= 4 && __GNUC_MINOR__ < 6
	size_t size = shows.size();
	for(size_t i = 0; i < size; ++i) {
		Show s(shows[i].second, shows[i].first, EPISODE);
		pl.add(s);
	}
#else
	for(auto &i: shows) {
		Show s(i.second, i.first, EPISODE);
		pl.add(s);
	}
#endif
	addplaylist(pl);
}

auto PlaylistController::begin() -> decltype(playlists.begin()) {
	return playlists.begin();
}

auto PlaylistController::cbegin() -> decltype(playlists.cbegin()) {
	return playlists.cbegin();
}

void deleteselected() {}

auto PlaylistController::end() -> decltype(playlists.end()) {
	return playlists.end();
}

auto PlaylistController::cend() -> decltype(playlists.cend()) {
	return playlists.cend();
}

bool PlaylistController::empty() {
	return playlists.empty();
}

auto PlaylistController::getselection() -> decltype(selection) {
	selection = begin() + offset;
	return selection;
}

auto PlaylistController::getdispselection() -> decltype(selection) {
	dispselection = begin() + dispoffset;
	return dispselection;
}

void PlaylistController::go() {
	offset = dispoffset;
	selection = dispselection;
}

void PlaylistController::go(decltype(selection) pos) {
	//if(pos >= begin() && pos < end())
		selection = pos;
}

void PlaylistController::offsetselection(size_t o) {
	auto s = selection + o;
	if(s >= begin() && s < end()) {
		selection = s;
		offset += o;
	}
	return;
}

void PlaylistController::offsetdispselection(size_t o) {
	auto s = dispselection + o;
	if(s >= begin() && s < end()) {
		dispselection = s;
		dispoffset += o;
	}
	return;
}

/**
	Database loading and saving
*/
bool PlaylistController::loaddb() {
	bool ret = true;

	ifstream db;
	db.open(sc.data);

	size_t played, size;
	unsigned int watched;
	string name, type, file;

	//TODO: Better error checking
	while(db.good()) {
		db >> played >> size;
		db.ignore();
		getline(db, name);
		if(db.fail()) {
			goto cleanup;
		}

		Playlist p(name);
		for(size_t i = 0; i < size; ++i) {
			db >> watched >> type;
			db.ignore(100,'\n');
			getline(db, name);
			getline(db, file);
			// The file was incorrectly formatted
			if(db.fail()) {
				ret = false;
				goto cleanup;
			}

			Show s(file, name, Show::gettype(type), watched);
			p.add(s);
		}

		Playlist pl(p.getname(),p);
		addplaylist(pl);
	}

cleanup:
	selection = dispselection = begin();
	offset = dispoffset = 0;

	std::sort(begin(), end());

	db.close();
	return ret;
}

bool PlaylistController::savedb() {
	ofstream db;
	db.open(sc.data);

	//TODO: Better error checking
#if __GNUC__ <= 4 && __GNUC_MINOR__ < 6
	size_t size = playlists.size();
	for(size_t i = 0; i < size; ++i) {
		playlists[i].printdetail(db);
		db << '\n';
		size_t shows_size = shows.size();
		for(size_t j = 0; j < shows_size; ++j) {
			shows[j].printdetail(db);
			db << '\n';
		}
	}
#else
	for(Playlist& p : playlists) {
		p.printdetail(db);
		db << '\n';
		for(Show& s : p) {
			s.printdetail(db);
			db << '\n';
		}
	}
#endif

	db.close();

	savedb_new();

	return true;
}

bool PlaylistController::db_create(bool exists, session& db) {

	const double version = .2;
	double v = 0;
	indicator ind;
	bool init = true, caught = false;

	// TODO: remove exists once we drop old database stuff
	if(exists) {
		try {
			db << "SELECT Number FROM Version", into(v, ind);
		}
		catch (const std::exception& e) {
			init = true;
			caught = true;
		}

		if(!caught && db.got_data()) {
			switch(ind) {
				case i_ok:
					init = false;
					break;
				case i_null:
					break;
				case i_truncated:
					break;
			}

			if(v < version) {
				init = true;
			}
		}
	}
	else
		init = true;

	if(init) {
		db << "CREATE TABLE IF NOT EXISTS Playlists ("
			"Name TEXT PRIMARY KEY ASC NOT NULL"
			")";
		db << "CREATE TABLE IF NOT EXISTS Version ("
			"Number REAL NOT NULL"
			")";

		db << "CREATE TABLE IF NOT EXISTS Shows ("
			"File TEXT PRIMARY KEY ASC NOT NULL, "
			"Name TEXT, "
			"ID INT NOT NULL, "
			"Watched INT DEFAULT 0, "
			"Type TEXT NOT NULL DEFAULT EPISODE, "
			"Playlist REFERENCES Playlists (Name) ON DELETE CASCADE ON UPDATE CASCADE"
			")";

		if(exists && !caught && v < version) {
			db << "UPDATE Version SET Number = :version", use(version);
		}
		else
			db << "INSERT INTO Version (Number) VALUES(:version)", use(version);

		// TODO: remove this once we drop old database stuff
		if(!exists) {
#if __GNUC__ <= 4 && __GNUC_MINOR__ < 6
			int order = 0;
			for(auto i = playlists.begin(); i < playlists.end(); ++i) {
				db << "INSERT INTO Playlists VALUES(:NAME)", use(playlists[i]);

				for(auto j = playlists[i].begin(); j < playlists[i].end(); ++j) {
					db << "INSERT INTO Shows VALUES(:FILE,:NAME,:WATCHED,:TYPE,:PLAYLIST)",
						 use(*j), use((*j).getname(), "PLAYLIST");

				}
			}
#else
			int order = 0;
			for(Playlist& p : playlists) {
				db << "INSERT INTO Playlists VALUES(:NAME)", use(p);

				for(Show& s : p) {

					db << "INSERT INTO Shows VALUES(:FILE,:NAME,:WATCHED,:TYPE,:PLAYLIST)",
						 use(s), use(p.getname(), "PLAYLIST");

				}
			}
#endif
		}

		db << "SELECT Number FROM Version", into(v, ind);

		if(db.got_data()) {
			switch(ind) {
				case i_ok:
					return true;
					break;
				case i_null:
					return false;
					break;
				case i_truncated:
					break;
			}
		}
	}

	return false;
}

bool PlaylistController::savedb_new() {
	bool exists = boost::filesystem::exists(sc.db);
	session db(sqlite3, sc.db.native());

	// TODO: remove exists once we drop old database stuff
	assert(db_create(exists, db));

#if __GNUC__ <= 4 && __GNUC_MINOR__ < 6
	size_t size = playlists.size();
	for(size_t i = 0; i < size; ++i) {
		if(playlists[i].haschanged()) {
			std::string name;
			indicator ind;
			db << "SELECT Name FROM Playlists WHERE Name == :OLDNAME", use(playlists[i]), into(name, ind);
			if(ind == i_ok && db.got_data()) {
				db << "UPDATE Playlists SET "
					"Name=:NAME "
					"WHERE Name == :OLDNAME", use(playlists[i]);
			}
			else {
				db << "INSERT INTO Playlists VALUES(:NAME)", use(playlists[i]);
			}
		}

		size_t shows_size = p.size();
		for(size_t j = 0; j < shows_size; ++j) {
			//s.printdetail(db);
			//db << '\n';
		}
	}
#else
	for(Playlist& p : playlists) {
		if(p.haschanged()) {
			std::string name;
			indicator ind;
			db << "SELECT Name FROM Playlists WHERE Name == :OLDNAME", use(p), into(name, ind);
			if(ind == i_ok && db.got_data()) {
				db << "UPDATE Playlists SET "
					"Name=:NAME "
					"WHERE Name == :OLDNAME", use(p);
			}
			else {
				db << "INSERT INTO Playlists VALUES(:NAME)", use(p);
			}
		}

		for(Show& s : p) {
			//s.printdetail(db);
			//db << '\n';
		}
	}
#endif

	return true;
}

size_t PlaylistController::size() { return playlists.size(); }
<commit_msg>attempt a fix for boost::filesystem library changes<commit_after>#include "boost/filesystem.hpp"
#include "boost/filesystem/fstream.hpp"

#include "soci/soci/src/core/soci.h"
#include "soci/soci/src/backends/sqlite3/soci-sqlite3.h"

#include <algorithm>
#include <cstdlib>
#include <exception>
#include <iostream>
#include <map>
#include <string>
#include <vector>

#include "PlaylistController.h"
#include "SettingsController.h"

using std::cout;
using std::map;
using std::string;
using std::vector;

using namespace soci;

using boost::filesystem::ofstream;
using boost::filesystem::ifstream;
using namespace boost::filesystem;

extern SettingsController sc;

PlaylistController::PlaylistController() {
}

void PlaylistController::addplaylist(Playlist& pl, const int pos) {
	if(pos < 0) {
		playlists.push_back(pl);
		selection = begin() + offset;
		dispoffset = size() - 1;
		dispselection = begin() + dispoffset;
	}
	else if((size_t)pos < playlists.size()) {
		playlists.insert(begin() + pos, pl);
		selection = begin() + offset;
		dispoffset = pos;
		dispselection = begin() + dispoffset;
	}
}

void PlaylistController::autoaddplaylist(path p) {
	if(!exists(p))
		return;
	if(!is_directory(p))
		return;

#if BOOST_FILESYSTEM_VERSION == 3
	string n = p.filename().string();
#else
	string n = p.filename();
#endif
	if(n.empty())
		return;

	Playlist pl(n);
	map<string,string> shows;

	for(auto i = directory_iterator(p); i != directory_iterator(); ++i) {
#if BOOST_FILESYSTEM_VERSION == 3
		shows[i->path().filename().string()] = i->path().string();
#else
		shows[i->path().filename()] = i->path();
#endif
	}

#if __GNUC__ <= 4 && __GNUC_MINOR__ < 6
	size_t size = shows.size();
	for(size_t i = 0; i < size; ++i) {
		Show s(shows[i].second, shows[i].first, EPISODE);
		pl.add(s);
	}
#else
	for(auto &i: shows) {
		Show s(i.second, i.first, EPISODE);
		pl.add(s);
	}
#endif
	addplaylist(pl);
}

auto PlaylistController::begin() -> decltype(playlists.begin()) {
	return playlists.begin();
}

auto PlaylistController::cbegin() -> decltype(playlists.cbegin()) {
	return playlists.cbegin();
}

void deleteselected() {}

auto PlaylistController::end() -> decltype(playlists.end()) {
	return playlists.end();
}

auto PlaylistController::cend() -> decltype(playlists.cend()) {
	return playlists.cend();
}

bool PlaylistController::empty() {
	return playlists.empty();
}

auto PlaylistController::getselection() -> decltype(selection) {
	selection = begin() + offset;
	return selection;
}

auto PlaylistController::getdispselection() -> decltype(selection) {
	dispselection = begin() + dispoffset;
	return dispselection;
}

void PlaylistController::go() {
	offset = dispoffset;
	selection = dispselection;
}

void PlaylistController::go(decltype(selection) pos) {
	//if(pos >= begin() && pos < end())
		selection = pos;
}

void PlaylistController::offsetselection(size_t o) {
	auto s = selection + o;
	if(s >= begin() && s < end()) {
		selection = s;
		offset += o;
	}
	return;
}

void PlaylistController::offsetdispselection(size_t o) {
	auto s = dispselection + o;
	if(s >= begin() && s < end()) {
		dispselection = s;
		dispoffset += o;
	}
	return;
}

/**
	Database loading and saving
*/
bool PlaylistController::loaddb() {
	bool ret = true;

	ifstream db;
	db.open(sc.data);

	size_t played, size;
	unsigned int watched;
	string name, type, file;

	//TODO: Better error checking
	while(db.good()) {
		db >> played >> size;
		db.ignore();
		getline(db, name);
		if(db.fail()) {
			goto cleanup;
		}

		Playlist p(name);
		for(size_t i = 0; i < size; ++i) {
			db >> watched >> type;
			db.ignore(100,'\n');
			getline(db, name);
			getline(db, file);
			// The file was incorrectly formatted
			if(db.fail()) {
				ret = false;
				goto cleanup;
			}

			Show s(file, name, Show::gettype(type), watched);
			p.add(s);
		}

		Playlist pl(p.getname(),p);
		addplaylist(pl);
	}

cleanup:
	selection = dispselection = begin();
	offset = dispoffset = 0;

	std::sort(begin(), end());

	db.close();
	return ret;
}

bool PlaylistController::savedb() {
	ofstream db;
	db.open(sc.data);

	//TODO: Better error checking
#if __GNUC__ <= 4 && __GNUC_MINOR__ < 6
	size_t size = playlists.size();
	for(size_t i = 0; i < size; ++i) {
		playlists[i].printdetail(db);
		db << '\n';
		size_t shows_size = shows.size();
		for(size_t j = 0; j < shows_size; ++j) {
			shows[j].printdetail(db);
			db << '\n';
		}
	}
#else
	for(Playlist& p : playlists) {
		p.printdetail(db);
		db << '\n';
		for(Show& s : p) {
			s.printdetail(db);
			db << '\n';
		}
	}
#endif

	db.close();

	savedb_new();

	return true;
}

bool PlaylistController::db_create(bool exists, session& db) {

	const double version = .2;
	double v = 0;
	indicator ind;
	bool init = true, caught = false;

	// TODO: remove exists once we drop old database stuff
	if(exists) {
		try {
			db << "SELECT Number FROM Version", into(v, ind);
		}
		catch (const std::exception& e) {
			init = true;
			caught = true;
		}

		if(!caught && db.got_data()) {
			switch(ind) {
				case i_ok:
					init = false;
					break;
				case i_null:
					break;
				case i_truncated:
					break;
			}

			if(v < version) {
				init = true;
			}
		}
	}
	else
		init = true;

	if(init) {
		db << "CREATE TABLE IF NOT EXISTS Playlists ("
			"Name TEXT PRIMARY KEY ASC NOT NULL"
			")";
		db << "CREATE TABLE IF NOT EXISTS Version ("
			"Number REAL NOT NULL"
			")";

		db << "CREATE TABLE IF NOT EXISTS Shows ("
			"File TEXT PRIMARY KEY ASC NOT NULL, "
			"Name TEXT, "
			"ID INT NOT NULL, "
			"Watched INT DEFAULT 0, "
			"Type TEXT NOT NULL DEFAULT EPISODE, "
			"Playlist REFERENCES Playlists (Name) ON DELETE CASCADE ON UPDATE CASCADE"
			")";

		if(exists && !caught && v < version) {
			db << "UPDATE Version SET Number = :version", use(version);
		}
		else
			db << "INSERT INTO Version (Number) VALUES(:version)", use(version);

		// TODO: remove this once we drop old database stuff
		if(!exists) {
#if __GNUC__ <= 4 && __GNUC_MINOR__ < 6
			int order = 0;
			for(auto i = playlists.begin(); i < playlists.end(); ++i) {
				db << "INSERT INTO Playlists VALUES(:NAME)", use(playlists[i]);

				for(auto j = playlists[i].begin(); j < playlists[i].end(); ++j) {
					db << "INSERT INTO Shows VALUES(:FILE,:NAME,:WATCHED,:TYPE,:PLAYLIST)",
						 use(*j), use((*j).getname(), "PLAYLIST");

				}
			}
#else
			int order = 0;
			for(Playlist& p : playlists) {
				db << "INSERT INTO Playlists VALUES(:NAME)", use(p);

				for(Show& s : p) {

					db << "INSERT INTO Shows VALUES(:FILE,:NAME,:WATCHED,:TYPE,:PLAYLIST)",
						 use(s), use(p.getname(), "PLAYLIST");

				}
			}
#endif
		}

		db << "SELECT Number FROM Version", into(v, ind);

		if(db.got_data()) {
			switch(ind) {
				case i_ok:
					return true;
					break;
				case i_null:
					return false;
					break;
				case i_truncated:
					break;
			}
		}
	}

	return false;
}

bool PlaylistController::savedb_new() {
	bool exists = boost::filesystem::exists(sc.db);
	session db(sqlite3, sc.db.native());

	// TODO: remove exists once we drop old database stuff
	assert(db_create(exists, db));

#if __GNUC__ <= 4 && __GNUC_MINOR__ < 6
	size_t size = playlists.size();
	for(size_t i = 0; i < size; ++i) {
		if(playlists[i].haschanged()) {
			std::string name;
			indicator ind;
			db << "SELECT Name FROM Playlists WHERE Name == :OLDNAME", use(playlists[i]), into(name, ind);
			if(ind == i_ok && db.got_data()) {
				db << "UPDATE Playlists SET "
					"Name=:NAME "
					"WHERE Name == :OLDNAME", use(playlists[i]);
			}
			else {
				db << "INSERT INTO Playlists VALUES(:NAME)", use(playlists[i]);
			}
		}

		size_t shows_size = p.size();
		for(size_t j = 0; j < shows_size; ++j) {
			//s.printdetail(db);
			//db << '\n';
		}
	}
#else
	for(Playlist& p : playlists) {
		if(p.haschanged()) {
			std::string name;
			indicator ind;
			db << "SELECT Name FROM Playlists WHERE Name == :OLDNAME", use(p), into(name, ind);
			if(ind == i_ok && db.got_data()) {
				db << "UPDATE Playlists SET "
					"Name=:NAME "
					"WHERE Name == :OLDNAME", use(p);
			}
			else {
				db << "INSERT INTO Playlists VALUES(:NAME)", use(p);
			}
		}

		for(Show& s : p) {
			//s.printdetail(db);
			//db << '\n';
		}
	}
#endif

	return true;
}

size_t PlaylistController::size() { return playlists.size(); }
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * Author: Suat Gedikli (gedikli@willowgarage.com)
 */

#include <pcl/pcl_config.h>
#ifdef HAVE_OPENNI

#include <pcl/io/pcd_grabber.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>

//////////////////////// GrabberImplementation //////////////////////
struct pcl::PCDGrabberBase::PCDGrabberImpl
{
  PCDGrabberImpl (pcl::PCDGrabberBase& grabber, const std::string& pcd_path, float frames_per_second, bool repeat);
  PCDGrabberImpl (pcl::PCDGrabberBase& grabber, const std::vector<std::string>& pcd_files, float frames_per_second, bool repeat);
  void trigger ();
  void readAhead ();
  pcl::PCDGrabberBase& grabber_;
  float frames_per_second_;
  bool repeat_;
  bool running_;
  std::vector<std::string> pcd_files_;
  std::vector<std::string>::iterator pcd_iterator_;
  TimeTrigger time_trigger_;

  sensor_msgs::PointCloud2 next_cloud_;
  bool valid_;
};

pcl::PCDGrabberBase::PCDGrabberImpl::PCDGrabberImpl (pcl::PCDGrabberBase& grabber, const std::string& pcd_path, float frames_per_second, bool repeat)
: grabber_ (grabber)
, frames_per_second_ (frames_per_second)
, repeat_ (repeat)
, running_ (false)
, time_trigger_ (1.0 / (double) std::max(frames_per_second, 0.001f), boost::bind (&PCDGrabberImpl::trigger, this))
, valid_ (false)
{
  pcd_files_.push_back (pcd_path);
  pcd_iterator_ = pcd_files_.begin ();
}

pcl::PCDGrabberBase::PCDGrabberImpl::PCDGrabberImpl (pcl::PCDGrabberBase& grabber, const std::vector<std::string>& pcd_files, float frames_per_second, bool repeat)
: grabber_ (grabber)
, frames_per_second_ (frames_per_second)
, repeat_ (repeat)
, running_ (false)
, time_trigger_ (1.0 / (double) std::max(frames_per_second, 0.001f), boost::bind (&PCDGrabberImpl::trigger, this))
, valid_ (false)
{
  pcd_files_ = pcd_files;
  pcd_iterator_ = pcd_files_.begin ();
}

void pcl::PCDGrabberBase::PCDGrabberImpl::readAhead ()
{
  if (pcd_iterator_ != pcd_files_.end ())
  {
    PCDReader reader;
    int pcd_version;
    Eigen::Vector4f origin;
    Eigen::Quaternionf orientation;
    valid_ = (reader.read (*pcd_iterator_, next_cloud_, origin, orientation, pcd_version) == 0);

    if (++pcd_iterator_ == pcd_files_.end () && repeat_)
      pcd_iterator_ = pcd_files_.begin ();
  }
  else
    valid_ = false;
}

void pcl::PCDGrabberBase::PCDGrabberImpl::trigger ()
{
  if (valid_)
    grabber_.publish (next_cloud_);

  // use remaining time, if there is time left!
  readAhead ();
}

//////////////////////// GrabberBase //////////////////////
pcl::PCDGrabberBase::PCDGrabberBase (const std::string& pcd_path, float frames_per_second, bool repeat)
: impl_( new PCDGrabberImpl (*this, pcd_path, frames_per_second, repeat ) )
{
}

pcl::PCDGrabberBase::PCDGrabberBase (const std::vector<std::string>& pcd_files, float frames_per_second, bool repeat)
: impl_( new PCDGrabberImpl (*this, pcd_files, frames_per_second, repeat) )
{
}

pcl::PCDGrabberBase::~PCDGrabberBase () throw ()
{
  stop ();
  delete impl_;
}

void pcl::PCDGrabberBase::start ()
{
  if (impl_->frames_per_second_ > 0)
  {
    impl_->running_ = true;
    impl_->time_trigger_.start ();
  }
  else // manual trigger
  {
    impl_->trigger ();
  }
}

void pcl::PCDGrabberBase::stop ()
{
  if (impl_->frames_per_second_ > 0)
  {
    impl_->time_trigger_.stop ();
    impl_->running_ = false;
  }
}

bool pcl::PCDGrabberBase::isRunning () const
{
  return impl_->running_;
}

std::string pcl::PCDGrabberBase::getName () const
{
  return "PCDGrabber";
}

void pcl::PCDGrabberBase::rewind ()
{
  impl_->pcd_iterator_ = impl_->pcd_files_.begin ();
}

float pcl::PCDGrabberBase::getFramesPerSecond () const
{
  return impl_->frames_per_second_;
}

bool pcl::PCDGrabberBase::isRepeatOn () const
{
  return impl_->repeat_;
}
#endif
<commit_msg>removed OPENNI ifdefs<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2011, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <pcl/pcl_config.h>
#include <pcl/io/pcd_grabber.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>

///////////////////////////////////////////////////////////////////////////////////////////
//////////////////////// GrabberImplementation //////////////////////
struct pcl::PCDGrabberBase::PCDGrabberImpl
{
  PCDGrabberImpl (pcl::PCDGrabberBase& grabber, const std::string& pcd_path, float frames_per_second, bool repeat);
  PCDGrabberImpl (pcl::PCDGrabberBase& grabber, const std::vector<std::string>& pcd_files, float frames_per_second, bool repeat);
  void trigger ();
  void readAhead ();
  pcl::PCDGrabberBase& grabber_;
  float frames_per_second_;
  bool repeat_;
  bool running_;
  std::vector<std::string> pcd_files_;
  std::vector<std::string>::iterator pcd_iterator_;
  TimeTrigger time_trigger_;

  sensor_msgs::PointCloud2 next_cloud_;
  bool valid_;
};

///////////////////////////////////////////////////////////////////////////////////////////
pcl::PCDGrabberBase::PCDGrabberImpl::PCDGrabberImpl (pcl::PCDGrabberBase& grabber, const std::string& pcd_path, float frames_per_second, bool repeat)
: grabber_ (grabber)
, frames_per_second_ (frames_per_second)
, repeat_ (repeat)
, running_ (false)
, time_trigger_ (1.0 / (double) std::max(frames_per_second, 0.001f), boost::bind (&PCDGrabberImpl::trigger, this))
, valid_ (false)
{
  pcd_files_.push_back (pcd_path);
  pcd_iterator_ = pcd_files_.begin ();
}

///////////////////////////////////////////////////////////////////////////////////////////
pcl::PCDGrabberBase::PCDGrabberImpl::PCDGrabberImpl (pcl::PCDGrabberBase& grabber, const std::vector<std::string>& pcd_files, float frames_per_second, bool repeat)
: grabber_ (grabber)
, frames_per_second_ (frames_per_second)
, repeat_ (repeat)
, running_ (false)
, time_trigger_ (1.0 / (double) std::max(frames_per_second, 0.001f), boost::bind (&PCDGrabberImpl::trigger, this))
, valid_ (false)
{
  pcd_files_ = pcd_files;
  pcd_iterator_ = pcd_files_.begin ();
}

///////////////////////////////////////////////////////////////////////////////////////////
void
pcl::PCDGrabberBase::PCDGrabberImpl::readAhead ()
{
  if (pcd_iterator_ != pcd_files_.end ())
  {
    PCDReader reader;
    int pcd_version;
    Eigen::Vector4f origin;
    Eigen::Quaternionf orientation;
    valid_ = (reader.read (*pcd_iterator_, next_cloud_, origin, orientation, pcd_version) == 0);

    if (++pcd_iterator_ == pcd_files_.end () && repeat_)
      pcd_iterator_ = pcd_files_.begin ();
  }
  else
    valid_ = false;
}

void
pcl::PCDGrabberBase::PCDGrabberImpl::trigger ()
{
  if (valid_)
    grabber_.publish (next_cloud_);

  // use remaining time, if there is time left!
  readAhead ();
}

///////////////////////////////////////////////////////////////////////////////////////////
//////////////////////// GrabberBase //////////////////////
pcl::PCDGrabberBase::PCDGrabberBase (const std::string& pcd_path, float frames_per_second, bool repeat)
: impl_( new PCDGrabberImpl (*this, pcd_path, frames_per_second, repeat ) )
{
}

///////////////////////////////////////////////////////////////////////////////////////////
pcl::PCDGrabberBase::PCDGrabberBase (const std::vector<std::string>& pcd_files, float frames_per_second, bool repeat)
: impl_( new PCDGrabberImpl (*this, pcd_files, frames_per_second, repeat) )
{
}

///////////////////////////////////////////////////////////////////////////////////////////
pcl::PCDGrabberBase::~PCDGrabberBase () throw ()
{
  stop ();
  delete impl_;
}

///////////////////////////////////////////////////////////////////////////////////////////
void
pcl::PCDGrabberBase::start ()
{
  if (impl_->frames_per_second_ > 0)
  {
    impl_->running_ = true;
    impl_->time_trigger_.start ();
  }
  else // manual trigger
    impl_->trigger ();
}

///////////////////////////////////////////////////////////////////////////////////////////
void
pcl::PCDGrabberBase::stop ()
{
  if (impl_->frames_per_second_ > 0)
  {
    impl_->time_trigger_.stop ();
    impl_->running_ = false;
  }
}

///////////////////////////////////////////////////////////////////////////////////////////
bool
pcl::PCDGrabberBase::isRunning () const
{
  return (impl_->running_);
}

///////////////////////////////////////////////////////////////////////////////////////////
std::string
pcl::PCDGrabberBase::getName () const
{
  return ("PCDGrabber");
}

///////////////////////////////////////////////////////////////////////////////////////////
void
pcl::PCDGrabberBase::rewind ()
{
  impl_->pcd_iterator_ = impl_->pcd_files_.begin ();
}

///////////////////////////////////////////////////////////////////////////////////////////
float
pcl::PCDGrabberBase::getFramesPerSecond () const
{
  return (impl_->frames_per_second_);
}

///////////////////////////////////////////////////////////////////////////////////////////
bool
pcl::PCDGrabberBase::isRepeatOn () const
{
  return (impl_->repeat_);
}

<|endoftext|>


<commit_before><commit_msg>gtk: fix display of icons in omnibox popup<commit_after><|endoftext|>


<commit_before>/**
 * @file
 */
#pragma once

/**
 * @def LIBBIRCH_ATOMIC_OPENMP
 *
 * Set to true for libbirch::Atomic use OpenMP, or false to use std::atomic.
 *
 * The advantage of the OpenMP implementation is assured memory model
 * consistency and the organic disabling of atomics when OpenMP, and thus
 * multithreading, is disabled (this can improve performance significantly for
 * single threading). The disadvantage is that OpenMP atomics do not support
 * compare-and-swap/compare-and-exchange, only swap/exchange, which can
 * require some clunkier client code, especially for read-write locks.
 */
#define LIBBIRCH_ATOMIC_OPENMP 1

#if !LIBBIRCH_ATOMIC_OPENMP
#include <atomic>
#endif

namespace libbirch {
/**
 * Atomic value.
 *
 * @tparam Value type.
 */
template<class T>
class Atomic {
public:
  /**
   * Default constructor. Initializes the value, not necessarily atomically.
   */
  Atomic() = default;

  /**
   * Constructor.
   *
   * @param value Initial value.
   *
   * Initializes the value, atomically.
   */
  explicit Atomic(const T& value) {
    store(value);
  }

  /**
   * Load the value, atomically.
   */
  T load() const {
    #if LIBBIRCH_ATOMIC_OPENMP
    T value;
    #pragma omp atomic read
    value = this->value;
    return value;
    #else
    return this->value.load(std::memory_order_relaxed);
    #endif
  }

  /**
   * Store the value, atomically.
   */
  void store(const T& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic write
    this->value = value;
    #else
    this->value.store(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Exchange the value with another, atomically.
   *
   * @param value New value.
   *
   * @return Old value.
   */
  T exchange(const T& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T old;
    #pragma omp atomic capture
    {
      old = this->value;
      this->value = value;
    }
    return old;
    #else
    return this->value.exchange(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Apply a mask, with bitwise `and`, and return the previous value,
   * atomically.
   *
   * @param m Mask.
   *
   * @return Previous value.
   */
  T exchangeAnd(const T& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T old;
    #pragma omp atomic capture
    {
      old = this->value;
      this->value &= value;
    }
    return old;
    #else
    return this->value.fetch_and(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Apply a mask, with bitwise `or`, and return the previous value,
   * atomically.
   *
   * @param m Mask.
   *
   * @return Previous value.
   */
  T exchangeOr(const T& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T old;
    #pragma omp atomic capture
    {
      old = this->value;
      this->value |= value;
    }
    return old;
    #else
    return this->value.fetch_or(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Apply a mask, with bitwise `and`, atomically.
   *
   * @param m Mask.
   */
  void maskAnd(const T& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic update
    this->value &= value;
    #else
    this->value.fetch_and(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Apply a mask, with bitwise `or`, atomically.
   *
   * @param m Mask.
   */
  void maskOr(const T& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic update
    this->value |= value;
    #else
    this->value.fetch_or(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Increment the value by one, atomically, but without capturing the
   * current value.
   */
  void increment() {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic update
    ++value;
    #else
    value.fetch_add(1, std::memory_order_relaxed);
    #endif
  }

  /**
   * Decrement the value by one, atomically, but without capturing the
   * current value.
   */
  void decrement() {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic update
    --value;
    #else
    value.fetch_sub(1, std::memory_order_relaxed);
    #endif
  }

  /**
   * Add to the value, atomically, but without capturing the current value.
   */
  template<class U>
  void add(const U& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic update
    this->value += value;
    #else
    this->value.fetch_add(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Subtract from the value, atomically, but without capturing the current
   * value.
   */
  template<class U>
  void subtract(const U& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic update
    this->value -= value;
    #else
    this->value.fetch_sub(value, std::memory_order_relaxed);
    #endif
  }

  template<class U>
  T operator+=(const U& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T result;
    #pragma omp atomic capture
    {
      this->value += value;
      result = this->value;
    }
    return result;
    #else
    return this->value.fetch_add(value, std::memory_order_relaxed) + value;
    #endif
  }

  template<class U>
  T operator-=(const U& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T result;
    #pragma omp atomic capture
    {
      this->value -= value;
      result = this->value;
    }
    return result;
    #else
    return this->value.fetch_sub(value, std::memory_order_relaxed) - value;
    #endif
  }

  T operator++() {
    #if LIBBIRCH_ATOMIC_OPENMP
    T result;
    #pragma omp atomic capture
    {
      ++this->value;
      result = this->value;
    }
    return result;
    #else
    return this->value.fetch_add(1, std::memory_order_relaxed) + 1;
    #endif
  }

  T operator++(int) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T result;
    #pragma omp atomic capture
    {
      result = this->value;
      ++this->value;
    }
    return result;
    #else
    return this->value.fetch_add(1, std::memory_order_relaxed);
    #endif
  }

  T operator--() {
    #if LIBBIRCH_ATOMIC_OPENMP
    T result;
    #pragma omp atomic capture
    {
      --this->value;
      result = this->value;
    }
    return result;
    #else
    return this->value.fetch_sub(1, std::memory_order_relaxed) - 1;
    #endif
  }

  T operator--(int) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T result;
    #pragma omp atomic capture
    {
      result = this->value;
      --this->value;
    }
    return result;
    #else
    return this->value.fetch_sub(1, std::memory_order_relaxed);
    #endif
  }

private:
  /**
   * Value.
   */
  #if LIBBIRCH_ATOMIC_OPENMP
  T value;
  #else
  std::atomic<T> value;
  #endif
};
}
<commit_msg>Switched back to use of std::atomic instead of OpenMP atomics on Mac.<commit_after>/**
 * @file
 */
#pragma once

/**
 * @def LIBBIRCH_ATOMIC_OPENMP
 *
 * Set to 1 for libbirch::Atomic use OpenMP, or 0 to use std::atomic.
 *
 * The advantage of the OpenMP implementation is assured memory model
 * consistency and the organic disabling of atomics when OpenMP, and thus
 * multithreading, is disabled (this can improve performance significantly for
 * single threading). The disadvantage is that OpenMP atomics do not support
 * compare-and-swap/compare-and-exchange, only swap/exchange, which can
 * require some clunkier client code, especially for read-write locks.
 */
#ifdef __APPLE__
/* on Mac, OpenMP atomics appear to cause crashes when release mode is
 * enabled */
#define LIBBIRCH_ATOMIC_OPENMP 0
#else
#define LIBBIRCH_ATOMIC_OPENMP 1
#endif

#if !LIBBIRCH_ATOMIC_OPENMP
#include <atomic>
#endif

namespace libbirch {
/**
 * Atomic value.
 *
 * @tparam Value type.
 */
template<class T>
class Atomic {
public:
  /**
   * Default constructor. Initializes the value, not necessarily atomically.
   */
  Atomic() = default;

  /**
   * Constructor.
   *
   * @param value Initial value.
   *
   * Initializes the value, atomically.
   */
  explicit Atomic(const T& value) {
    store(value);
  }

  /**
   * Load the value, atomically.
   */
  T load() const {
    #if LIBBIRCH_ATOMIC_OPENMP
    T value;
    #pragma omp atomic read
    value = this->value;
    return value;
    #else
    return this->value.load(std::memory_order_relaxed);
    #endif
  }

  /**
   * Store the value, atomically.
   */
  void store(const T& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic write
    this->value = value;
    #else
    this->value.store(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Exchange the value with another, atomically.
   *
   * @param value New value.
   *
   * @return Old value.
   */
  T exchange(const T& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T old;
    #pragma omp atomic capture
    {
      old = this->value;
      this->value = value;
    }
    return old;
    #else
    return this->value.exchange(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Apply a mask, with bitwise `and`, and return the previous value,
   * atomically.
   *
   * @param m Mask.
   *
   * @return Previous value.
   */
  T exchangeAnd(const T& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T old;
    #pragma omp atomic capture
    {
      old = this->value;
      this->value &= value;
    }
    return old;
    #else
    return this->value.fetch_and(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Apply a mask, with bitwise `or`, and return the previous value,
   * atomically.
   *
   * @param m Mask.
   *
   * @return Previous value.
   */
  T exchangeOr(const T& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T old;
    #pragma omp atomic capture
    {
      old = this->value;
      this->value |= value;
    }
    return old;
    #else
    return this->value.fetch_or(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Apply a mask, with bitwise `and`, atomically.
   *
   * @param m Mask.
   */
  void maskAnd(const T& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic update
    this->value &= value;
    #else
    this->value.fetch_and(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Apply a mask, with bitwise `or`, atomically.
   *
   * @param m Mask.
   */
  void maskOr(const T& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic update
    this->value |= value;
    #else
    this->value.fetch_or(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Increment the value by one, atomically, but without capturing the
   * current value.
   */
  void increment() {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic update
    ++value;
    #else
    value.fetch_add(1, std::memory_order_relaxed);
    #endif
  }

  /**
   * Decrement the value by one, atomically, but without capturing the
   * current value.
   */
  void decrement() {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic update
    --value;
    #else
    value.fetch_sub(1, std::memory_order_relaxed);
    #endif
  }

  /**
   * Add to the value, atomically, but without capturing the current value.
   */
  template<class U>
  void add(const U& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic update
    this->value += value;
    #else
    this->value.fetch_add(value, std::memory_order_relaxed);
    #endif
  }

  /**
   * Subtract from the value, atomically, but without capturing the current
   * value.
   */
  template<class U>
  void subtract(const U& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    #pragma omp atomic update
    this->value -= value;
    #else
    this->value.fetch_sub(value, std::memory_order_relaxed);
    #endif
  }

  template<class U>
  T operator+=(const U& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T result;
    #pragma omp atomic capture
    {
      this->value += value;
      result = this->value;
    }
    return result;
    #else
    return this->value.fetch_add(value, std::memory_order_relaxed) + value;
    #endif
  }

  template<class U>
  T operator-=(const U& value) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T result;
    #pragma omp atomic capture
    {
      this->value -= value;
      result = this->value;
    }
    return result;
    #else
    return this->value.fetch_sub(value, std::memory_order_relaxed) - value;
    #endif
  }

  T operator++() {
    #if LIBBIRCH_ATOMIC_OPENMP
    T result;
    #pragma omp atomic capture
    {
      ++this->value;
      result = this->value;
    }
    return result;
    #else
    return this->value.fetch_add(1, std::memory_order_relaxed) + 1;
    #endif
  }

  T operator++(int) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T result;
    #pragma omp atomic capture
    {
      result = this->value;
      ++this->value;
    }
    return result;
    #else
    return this->value.fetch_add(1, std::memory_order_relaxed);
    #endif
  }

  T operator--() {
    #if LIBBIRCH_ATOMIC_OPENMP
    T result;
    #pragma omp atomic capture
    {
      --this->value;
      result = this->value;
    }
    return result;
    #else
    return this->value.fetch_sub(1, std::memory_order_relaxed) - 1;
    #endif
  }

  T operator--(int) {
    #if LIBBIRCH_ATOMIC_OPENMP
    T result;
    #pragma omp atomic capture
    {
      result = this->value;
      --this->value;
    }
    return result;
    #else
    return this->value.fetch_sub(1, std::memory_order_relaxed);
    #endif
  }

private:
  /**
   * Value.
   */
  #if LIBBIRCH_ATOMIC_OPENMP
  T value;
  #else
  std::atomic<T> value;
  #endif
};
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2014                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_OPTIONAL_HPP
#define CAF_OPTIONAL_HPP

#include <new>
#include <utility>

#include "caf/none.hpp"
#include "caf/unit.hpp"
#include "caf/config.hpp"

#include "caf/detail/safe_equal.hpp"
#include "caf/detail/scope_guard.hpp"

namespace caf {

/// A C++17 compatible `optional` implementation.
template <class T>
class optional {
 public:
  /// Typdef for `T`.
  using type = T;

  /// Creates an instance without value.
  optional(const none_t& = none) : m_valid(false) {
    // nop
  }

  /// Creates an valid instance from `value`.
  template <class U,
            class E = typename std::enable_if<
                        std::is_convertible<U, T>::value
                      >::type>
  optional(U x) : m_valid(false) {
    cr(std::move(x));
  }

  optional(const optional& other) : m_valid(false) {
    if (other.m_valid) {
      cr(other.m_value);
    }
  }

  optional(optional&& other) : m_valid(false) {
    if (other.m_valid) {
      cr(std::move(other.m_value));
    }
  }

  ~optional() {
    destroy();
  }

  optional& operator=(const optional& other) {
    if (m_valid) {
      if (other.m_valid) m_value = other.m_value;
      else destroy();
    }
    else if (other.m_valid) {
      cr(other.m_value);
    }
    return *this;
  }

  optional& operator=(optional&& other) {
    if (m_valid) {
      if (other.m_valid) m_value = std::move(other.m_value);
      else destroy();
    }
    else if (other.m_valid) {
      cr(std::move(other.m_value));
    }
    return *this;
  }

  /// Checks whether this object contains a value.
  explicit operator bool() const {
    return m_valid;
  }

  /// Checks whether this object does not contain a value.
  bool operator!() const {
    return !m_valid;
  }

  /// Returns the value.
  T& operator*() {
    CAF_ASSERT(m_valid);
    return m_value;
  }

  /// Returns the value.
  const T& operator*() const {
    CAF_ASSERT(m_valid);
    return m_value;
  }

  /// Returns the value.
  const T* operator->() const {
    CAF_ASSERT(m_valid);
    return &m_value;
  }

  /// Returns the value.
  T* operator->() {
    CAF_ASSERT(m_valid);
    return &m_value;
  }

  /// Returns the value.
  T& value() {
    CAF_ASSERT(m_valid);
    return m_value;
  }

  /// Returns the value.
  const T& value() const {
    CAF_ASSERT(m_valid);
    return m_value;
  }

  /// Returns the value if `m_valid`, otherwise returns `default_value`.
  const T& value_or(const T& default_value) const {
    return m_valid ? value() : default_value;
  }

 private:
  void destroy() {
    if (m_valid) {
      m_value.~T();
      m_valid = false;
    }
  }

  template <class V>
  void cr(V&& x) {
    CAF_ASSERT(!m_valid);
    m_valid = true;
    new (&m_value) T(std::forward<V>(x));
  }

  bool m_valid;
  union { T m_value; };
};

/// Template specialization to allow `optional` to hold a reference
/// rather than an actual value with minimal overhead.
template <class T>
class optional<T&> {
 public:
  using type = T;

  optional(const none_t& = none) : m_value(nullptr) {
    // nop
  }

  optional(T& x) : m_value(&x) {
    // nop
  }

  optional(T* x) : m_value(x) {
    // nop
  }

  optional(const optional& other) = default;

  optional& operator=(const optional& other) = default;

  explicit operator bool() const {
    return m_value != nullptr;
  }

  bool operator!() const {
    return !m_value;
  }

  T& operator*() {
    CAF_ASSERT(m_value);
    return *m_value;
  }

  const T& operator*() const {
    CAF_ASSERT(m_value);
    return *m_value;
  }

  T* operator->() {
    CAF_ASSERT(m_value);
    return m_value;
  }

  const T* operator->() const {
    CAF_ASSERT(m_value);
    return m_value;
  }

  T& value() {
    CAF_ASSERT(m_value);
    return *m_value;
  }

  const T& value() const {
    CAF_ASSERT(m_value);
    return *m_value;
  }

  const T& value_or(const T& default_value) const {
    if (m_value)
      return value();
    return default_value;
  }

 private:
  T* m_value;
};

template <>
class optional<void> {
 public:
  using type = unit_t;

  optional(none_t = none) : m_value(false) {
    // nop
  }

  optional(unit_t) : m_value(true) {
    // nop
  }

  optional(const optional& other) = default;

  optional& operator=(const optional& other) = default;

  explicit operator bool() const {
    return m_value;
  }

  bool operator!() const {
    return !m_value;
  }

 private:
  bool m_value;
};

template <class Inspector, class T>
typename std::enable_if<Inspector::reads_state,
                        typename Inspector::result_type>::type
inspect(Inspector& f, optional<T>& x) {
  return x ? f(true, *x) : f(false);
}

template <class T>
struct optional_inspect_helper {
  bool& enabled;
  T& storage;
  template <class Inspector>
  friend typename Inspector::result_type inspect(Inspector& f,
                                                 optional_inspect_helper& x) {
    return x.enabled ? f(x.storage) : f();
  }
};

template <class Inspector, class T>
typename std::enable_if<Inspector::writes_state,
                        typename Inspector::result_type>::type
inspect(Inspector& f, optional<T>& x) {
  bool flag;
  typename optional<T>::type tmp;
  optional_inspect_helper<T> helper{flag, tmp};
  auto guard = detail::make_scope_guard([&] {
    if (flag)
      x = std::move(tmp);
    else
      x = none;
  });
  return f(flag, helper);
}

/// @relates optional
template <class T>
auto to_string(const optional<T>& x) -> decltype(to_string(*x)) {
  return x ? "*" + to_string(*x) : "<null>";
}

// -- [X.Y.8] comparison with optional ----------------------------------------

/// @relates optional
template <class T>
bool operator==(const optional<T>& lhs, const optional<T>& rhs) {
  return static_cast<bool>(lhs) == static_cast<bool>(rhs)
      && (!lhs || *lhs == *rhs);
}

/// @relates optional
template <class T>
bool operator!=(const optional<T>& lhs, const optional<T>& rhs) {
  return !(lhs == rhs);
}

/// @relates optional
template <class T>
bool operator<(const optional<T>& lhs, const optional<T>& rhs) {
  return static_cast<bool>(rhs) && (!lhs || *lhs < *rhs);
}

/// @relates optional
template <class T>
bool operator<=(const optional<T>& lhs, const optional<T>& rhs) {
  return !(rhs < lhs);
}

/// @relates optional
template <class T>
bool operator>=(const optional<T>& lhs, const optional<T>& rhs) {
  return !(lhs < rhs);
}

/// @relates optional
template <class T>
bool operator>(const optional<T>& lhs, const optional<T>& rhs) {
  return rhs < lhs;
}

// -- [X.Y.9] comparison with none_t (aka. nullopt_t) -------------------------

/// @relates optional
template <class T>
bool operator==(const optional<T>& lhs, none_t) {
  return !lhs;
}

/// @relates optional
template <class T>
bool operator==(none_t, const optional<T>& rhs) {
  return !rhs;
}

/// @relates optional
template <class T>
bool operator!=(const optional<T>& lhs, none_t) {
  return static_cast<bool>(lhs);
}

/// @relates optional
template <class T>
bool operator!=(none_t, const optional<T>& rhs) {
  return static_cast<bool>(rhs);
}

/// @relates optional
template <class T>
bool operator<(const optional<T>&, none_t) {
  return false;
}

/// @relates optional
template <class T>
bool operator<(none_t, const optional<T>& rhs) {
  return static_cast<bool>(rhs);
}

/// @relates optional
template <class T>
bool operator<=(const optional<T>& lhs, none_t) {
  return !lhs;
}

/// @relates optional
template <class T>
bool operator<=(none_t, const optional<T>&) {
  return true;
}

/// @relates optional
template <class T>
bool operator>(const optional<T>& lhs, none_t) {
  return static_cast<bool>(lhs);
}

/// @relates optional
template <class T>
bool operator>(none_t, const optional<T>&) {
  return false;
}

/// @relates optional
template <class T>
bool operator>=(const optional<T>&, none_t) {
  return true;
}

/// @relates optional
template <class T>
bool operator>=(none_t, const optional<T>&) {
  return true;
}

// -- [X.Y.10] comparison with value type ------------------------------------

/// @relates optional
template <class T>
bool operator==(const optional<T>& lhs, const T& rhs) {
  return lhs && *lhs == rhs;
}

/// @relates optional
template <class T>
bool operator==(const T& lhs, const optional<T>& rhs) {
  return rhs && lhs == *rhs;
}

/// @relates optional
template <class T>
bool operator!=(const optional<T>& lhs, const T& rhs) {
  return !lhs || !(*lhs == rhs);
}

/// @relates optional
template <class T>
bool operator!=(const T& lhs, const optional<T>& rhs) {
  return !rhs || !(lhs == *rhs);
}

/// @relates optional
template <class T>
bool operator<(const optional<T>& lhs, const T& rhs) {
  return !lhs || *lhs < rhs;
}

/// @relates optional
template <class T>
bool operator<(const T& lhs, const optional<T>& rhs) {
  return rhs && lhs < *rhs;
}

/// @relates optional
template <class T>
bool operator<=(const optional<T>& lhs, const T& rhs) {
  return !lhs || !(rhs < *lhs);
}

/// @relates optional
template <class T>
bool operator<=(const T& lhs, const optional<T>& rhs) {
  return rhs && !(rhs < lhs);
}

/// @relates optional
template <class T>
bool operator>(const optional<T>& lhs, const T& rhs) {
  return lhs && rhs < *lhs;
}

/// @relates optional
template <class T>
bool operator>(const T& lhs, const optional<T>& rhs) {
  return !rhs || *rhs < lhs;
}

/// @relates optional
template <class T>
bool operator>=(const optional<T>& lhs, const T& rhs) {
  return lhs && !(*lhs < rhs);
}

/// @relates optional
template <class T>
bool operator>=(const T& lhs, const optional<T>& rhs) {
  return !rhs || !(lhs < *rhs);
}

} // namespace caf

#endif // CAF_OPTIONAL_HPP
<commit_msg>Mark optional<T>'s move ctor/assignment noexcept<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2014                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_OPTIONAL_HPP
#define CAF_OPTIONAL_HPP

#include <new>
#include <utility>

#include "caf/none.hpp"
#include "caf/unit.hpp"
#include "caf/config.hpp"

#include "caf/detail/safe_equal.hpp"
#include "caf/detail/scope_guard.hpp"

namespace caf {

/// A C++17 compatible `optional` implementation.
template <class T>
class optional {
 public:
  /// Typdef for `T`.
  using type = T;

  /// Creates an instance without value.
  optional(const none_t& = none) : m_valid(false) {
    // nop
  }

  /// Creates an valid instance from `value`.
  template <class U,
            class E = typename std::enable_if<
                        std::is_convertible<U, T>::value
                      >::type>
  optional(U x) : m_valid(false) {
    cr(std::move(x));
  }

  optional(const optional& other) : m_valid(false) {
    if (other.m_valid) {
      cr(other.m_value);
    }
  }

  optional(optional&& other)
  noexcept(std::is_nothrow_move_constructible<T>::value)
    : m_valid(false) {
    if (other.m_valid) {
      cr(std::move(other.m_value));
    }
  }

  ~optional() {
    destroy();
  }

  optional& operator=(const optional& other) {
    if (m_valid) {
      if (other.m_valid) m_value = other.m_value;
      else destroy();
    }
    else if (other.m_valid) {
      cr(other.m_value);
    }
    return *this;
  }

  optional& operator=(optional&& other)
  noexcept(std::is_nothrow_destructible<T>::value &&
           std::is_nothrow_move_assignable<T>::value) {
    if (m_valid) {
      if (other.m_valid) m_value = std::move(other.m_value);
      else destroy();
    }
    else if (other.m_valid) {
      cr(std::move(other.m_value));
    }
    return *this;
  }

  /// Checks whether this object contains a value.
  explicit operator bool() const {
    return m_valid;
  }

  /// Checks whether this object does not contain a value.
  bool operator!() const {
    return !m_valid;
  }

  /// Returns the value.
  T& operator*() {
    CAF_ASSERT(m_valid);
    return m_value;
  }

  /// Returns the value.
  const T& operator*() const {
    CAF_ASSERT(m_valid);
    return m_value;
  }

  /// Returns the value.
  const T* operator->() const {
    CAF_ASSERT(m_valid);
    return &m_value;
  }

  /// Returns the value.
  T* operator->() {
    CAF_ASSERT(m_valid);
    return &m_value;
  }

  /// Returns the value.
  T& value() {
    CAF_ASSERT(m_valid);
    return m_value;
  }

  /// Returns the value.
  const T& value() const {
    CAF_ASSERT(m_valid);
    return m_value;
  }

  /// Returns the value if `m_valid`, otherwise returns `default_value`.
  const T& value_or(const T& default_value) const {
    return m_valid ? value() : default_value;
  }

 private:
  void destroy() {
    if (m_valid) {
      m_value.~T();
      m_valid = false;
    }
  }

  template <class V>
  void cr(V&& x) {
    CAF_ASSERT(!m_valid);
    m_valid = true;
    new (&m_value) T(std::forward<V>(x));
  }

  bool m_valid;
  union { T m_value; };
};

/// Template specialization to allow `optional` to hold a reference
/// rather than an actual value with minimal overhead.
template <class T>
class optional<T&> {
 public:
  using type = T;

  optional(const none_t& = none) : m_value(nullptr) {
    // nop
  }

  optional(T& x) : m_value(&x) {
    // nop
  }

  optional(T* x) : m_value(x) {
    // nop
  }

  optional(const optional& other) = default;

  optional& operator=(const optional& other) = default;

  explicit operator bool() const {
    return m_value != nullptr;
  }

  bool operator!() const {
    return !m_value;
  }

  T& operator*() {
    CAF_ASSERT(m_value);
    return *m_value;
  }

  const T& operator*() const {
    CAF_ASSERT(m_value);
    return *m_value;
  }

  T* operator->() {
    CAF_ASSERT(m_value);
    return m_value;
  }

  const T* operator->() const {
    CAF_ASSERT(m_value);
    return m_value;
  }

  T& value() {
    CAF_ASSERT(m_value);
    return *m_value;
  }

  const T& value() const {
    CAF_ASSERT(m_value);
    return *m_value;
  }

  const T& value_or(const T& default_value) const {
    if (m_value)
      return value();
    return default_value;
  }

 private:
  T* m_value;
};

template <>
class optional<void> {
 public:
  using type = unit_t;

  optional(none_t = none) : m_value(false) {
    // nop
  }

  optional(unit_t) : m_value(true) {
    // nop
  }

  optional(const optional& other) = default;

  optional& operator=(const optional& other) = default;

  explicit operator bool() const {
    return m_value;
  }

  bool operator!() const {
    return !m_value;
  }

 private:
  bool m_value;
};

template <class Inspector, class T>
typename std::enable_if<Inspector::reads_state,
                        typename Inspector::result_type>::type
inspect(Inspector& f, optional<T>& x) {
  return x ? f(true, *x) : f(false);
}

template <class T>
struct optional_inspect_helper {
  bool& enabled;
  T& storage;
  template <class Inspector>
  friend typename Inspector::result_type inspect(Inspector& f,
                                                 optional_inspect_helper& x) {
    return x.enabled ? f(x.storage) : f();
  }
};

template <class Inspector, class T>
typename std::enable_if<Inspector::writes_state,
                        typename Inspector::result_type>::type
inspect(Inspector& f, optional<T>& x) {
  bool flag;
  typename optional<T>::type tmp;
  optional_inspect_helper<T> helper{flag, tmp};
  auto guard = detail::make_scope_guard([&] {
    if (flag)
      x = std::move(tmp);
    else
      x = none;
  });
  return f(flag, helper);
}

/// @relates optional
template <class T>
auto to_string(const optional<T>& x) -> decltype(to_string(*x)) {
  return x ? "*" + to_string(*x) : "<null>";
}

// -- [X.Y.8] comparison with optional ----------------------------------------

/// @relates optional
template <class T>
bool operator==(const optional<T>& lhs, const optional<T>& rhs) {
  return static_cast<bool>(lhs) == static_cast<bool>(rhs)
      && (!lhs || *lhs == *rhs);
}

/// @relates optional
template <class T>
bool operator!=(const optional<T>& lhs, const optional<T>& rhs) {
  return !(lhs == rhs);
}

/// @relates optional
template <class T>
bool operator<(const optional<T>& lhs, const optional<T>& rhs) {
  return static_cast<bool>(rhs) && (!lhs || *lhs < *rhs);
}

/// @relates optional
template <class T>
bool operator<=(const optional<T>& lhs, const optional<T>& rhs) {
  return !(rhs < lhs);
}

/// @relates optional
template <class T>
bool operator>=(const optional<T>& lhs, const optional<T>& rhs) {
  return !(lhs < rhs);
}

/// @relates optional
template <class T>
bool operator>(const optional<T>& lhs, const optional<T>& rhs) {
  return rhs < lhs;
}

// -- [X.Y.9] comparison with none_t (aka. nullopt_t) -------------------------

/// @relates optional
template <class T>
bool operator==(const optional<T>& lhs, none_t) {
  return !lhs;
}

/// @relates optional
template <class T>
bool operator==(none_t, const optional<T>& rhs) {
  return !rhs;
}

/// @relates optional
template <class T>
bool operator!=(const optional<T>& lhs, none_t) {
  return static_cast<bool>(lhs);
}

/// @relates optional
template <class T>
bool operator!=(none_t, const optional<T>& rhs) {
  return static_cast<bool>(rhs);
}

/// @relates optional
template <class T>
bool operator<(const optional<T>&, none_t) {
  return false;
}

/// @relates optional
template <class T>
bool operator<(none_t, const optional<T>& rhs) {
  return static_cast<bool>(rhs);
}

/// @relates optional
template <class T>
bool operator<=(const optional<T>& lhs, none_t) {
  return !lhs;
}

/// @relates optional
template <class T>
bool operator<=(none_t, const optional<T>&) {
  return true;
}

/// @relates optional
template <class T>
bool operator>(const optional<T>& lhs, none_t) {
  return static_cast<bool>(lhs);
}

/// @relates optional
template <class T>
bool operator>(none_t, const optional<T>&) {
  return false;
}

/// @relates optional
template <class T>
bool operator>=(const optional<T>&, none_t) {
  return true;
}

/// @relates optional
template <class T>
bool operator>=(none_t, const optional<T>&) {
  return true;
}

// -- [X.Y.10] comparison with value type ------------------------------------

/// @relates optional
template <class T>
bool operator==(const optional<T>& lhs, const T& rhs) {
  return lhs && *lhs == rhs;
}

/// @relates optional
template <class T>
bool operator==(const T& lhs, const optional<T>& rhs) {
  return rhs && lhs == *rhs;
}

/// @relates optional
template <class T>
bool operator!=(const optional<T>& lhs, const T& rhs) {
  return !lhs || !(*lhs == rhs);
}

/// @relates optional
template <class T>
bool operator!=(const T& lhs, const optional<T>& rhs) {
  return !rhs || !(lhs == *rhs);
}

/// @relates optional
template <class T>
bool operator<(const optional<T>& lhs, const T& rhs) {
  return !lhs || *lhs < rhs;
}

/// @relates optional
template <class T>
bool operator<(const T& lhs, const optional<T>& rhs) {
  return rhs && lhs < *rhs;
}

/// @relates optional
template <class T>
bool operator<=(const optional<T>& lhs, const T& rhs) {
  return !lhs || !(rhs < *lhs);
}

/// @relates optional
template <class T>
bool operator<=(const T& lhs, const optional<T>& rhs) {
  return rhs && !(rhs < lhs);
}

/// @relates optional
template <class T>
bool operator>(const optional<T>& lhs, const T& rhs) {
  return lhs && rhs < *lhs;
}

/// @relates optional
template <class T>
bool operator>(const T& lhs, const optional<T>& rhs) {
  return !rhs || *rhs < lhs;
}

/// @relates optional
template <class T>
bool operator>=(const optional<T>& lhs, const T& rhs) {
  return lhs && !(*lhs < rhs);
}

/// @relates optional
template <class T>
bool operator>=(const T& lhs, const optional<T>& rhs) {
  return !rhs || !(lhs < *rhs);
}

} // namespace caf

#endif // CAF_OPTIONAL_HPP
<|endoftext|>


<commit_before>/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "experimental/graphite/src/DrawWriter.h"

#include "experimental/graphite/src/DrawBufferManager.h"
#include "src/gpu/BufferWriter.h"

namespace skgpu {

DrawWriter::DrawWriter(DrawDispatcher* dispatcher, DrawBufferManager* bufferManager)
        : DrawWriter(dispatcher, bufferManager, PrimitiveType::kTriangles, 0, 0) {}

DrawWriter::DrawWriter(DrawDispatcher* dispatcher,
                       DrawBufferManager* bufferManager,
                       PrimitiveType primitiveType,
                       size_t vertexStride,
                       size_t instanceStride)
        : fDispatcher(dispatcher)
        , fManager(bufferManager)
        , fPrimitiveType(primitiveType)
        , fVertexStride(vertexStride)
        , fInstanceStride(instanceStride) {
    SkASSERT(dispatcher && bufferManager);
}

void DrawWriter::setTemplateInternal(BindBufferInfo vertices,
                                     BindBufferInfo indices,
                                     unsigned int count,
                                     bool drawPendingVertices) {
    SkASSERT(!vertices || fVertexStride > 0);
    if (vertices != fFixedVertexBuffer ||
        indices != fFixedIndexBuffer ||
        count != fFixedVertexCount) {
        // Issue any accumulated data that referred to the old template.
        if (drawPendingVertices) {
            this->drawPendingVertices();
        }

        fFixedBuffersDirty = true;

        fFixedVertexBuffer = vertices;
        fFixedIndexBuffer = indices;
        fFixedVertexCount = count;
    }
}

void DrawWriter::drawInternal(BindBufferInfo instances,
                              unsigned int base,
                              unsigned int instanceCount) {
    // Draw calls that are only 1 instance and have no extra instance data get routed to
    // the simpler draw APIs.
    // TODO: Is there any benefit to this? Does it help hint to drivers? Avoid more bugs?
    // Or should we always call drawInstanced and drawIndexedInstanced?
    const bool useNonInstancedDraw =
            !SkToBool(instances) && base == 0 && instanceCount == 1;
    SkASSERT(!useNonInstancedDraw || fInstanceStride == 0);

    // Issue new buffer binds only as necessary
    // TODO: Should this instead be the responsibility of the CB or DrawDispatcher to remember
    // what was last bound?
    if (fFixedBuffersDirty || instances != fLastInstanceBuffer) {
        fDispatcher->bindDrawBuffers(fFixedVertexBuffer, instances, fFixedIndexBuffer);
        fFixedBuffersDirty = false;
        fLastInstanceBuffer = instances;
    }

    if (useNonInstancedDraw) {
        if (fFixedIndexBuffer) {
            // Should only get here from a direct draw, in which case base should be 0 and any
            // offset needs to be embedded in the BindBufferInfo by caller.
            SkASSERT(base == 0);
            fDispatcher->drawIndexed(fPrimitiveType, 0, fFixedVertexCount, 0);
        } else {
            // 'base' offsets accumulated vertex data from another DrawWriter across a state change.
            fDispatcher->draw(fPrimitiveType, base, fFixedVertexCount);
        }
    } else {
        // 'base' offsets accumulated instance data (or is 0 for a direct instanced draw). It is
        // assumed that any base vertex and index have been folded into the BindBufferInfos already.
        if (fFixedIndexBuffer) {
            fDispatcher->drawIndexedInstanced(fPrimitiveType, 0, fFixedVertexCount, 0,
                                              base, instanceCount);
        } else {
            fDispatcher->drawInstanced(fPrimitiveType, 0, fFixedVertexCount, base, instanceCount);
        }
    }
}

void DrawWriter::drawPendingVertices() {
    if (fPendingCount > 0) {
        if (fPendingMode == VertexMode::kInstances) {
            // This uses instanced draws, so 'base' will be interpreted in instance units.
            this->drawInternal(fPendingAttrs, fPendingBaseVertex, fPendingCount);
        } else {
            // This triggers a non-instanced draw call so 'base' passed to drawInternal is
            // interpreted in vertex units.
            this->setTemplateInternal(fPendingAttrs, {}, fPendingCount, /*drawPending=*/false);
            this->drawInternal({}, fPendingBaseVertex, 1);
        }

        fPendingCount = 0;
        fPendingBaseVertex = 0;
        fPendingAttrs = {};
    }
}

VertexWriter DrawWriter::appendData(VertexMode mode, size_t stride, unsigned int count) {
    if (fPendingMode != mode) {
        // Switched between accumulating vertices and instances, so issue draws for the old data.
        this->drawPendingVertices();
        fPendingMode = mode;
    }

    auto [writer, nextChunk] = fManager->getVertexWriter(count * stride);
    // Check if next chunk's data is contiguous with what's previously been appended
    if (nextChunk.fBuffer == fPendingAttrs.fBuffer &&
        fPendingAttrs.fOffset + (fPendingBaseVertex + fPendingCount) * stride
                == nextChunk.fOffset) {
        // It is, so the next chunk's vertices that will be written can be folded into the next draw
        fPendingCount += count;
    } else {
        // Alignment mismatch, or the old buffer filled up
        this->drawPendingVertices();
        fPendingCount = count;
        fPendingBaseVertex = 0;
        fPendingAttrs = nextChunk;
    }

    return std::move(writer);
}

void DrawWriter::newDynamicState() {
    // Remember where we left off after we draw, since drawPendingVertices() resets all pending data
    BindBufferInfo base = fPendingAttrs;
    unsigned int baseVertex = fPendingBaseVertex + fPendingCount;
    // Draw anything that used the previous dynamic state
    this->drawPendingVertices();

    fPendingAttrs = base;
    fPendingBaseVertex = baseVertex;
}

void DrawWriter::newPipelineState(PrimitiveType type,
                                  size_t vertexStride,
                                  size_t instanceStride) {
    // Draw anything that used the previous pipeline
    this->drawPendingVertices();

    // For simplicity, if there's a new pipeline, just forget about any previous buffer bindings,
    // in which case the new writer only needs to use the dispatcher and buffer manager.
    this->setTemplateInternal({}, {}, 0, false);
    fLastInstanceBuffer = {};

    fPrimitiveType = type;
    fVertexStride = vertexStride;
    fInstanceStride = instanceStride;
}

} // namespace skgpu
<commit_msg>[graphite] Fix instance vs. non-instanced detection<commit_after>/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "experimental/graphite/src/DrawWriter.h"

#include "experimental/graphite/src/DrawBufferManager.h"
#include "src/gpu/BufferWriter.h"

namespace skgpu {

DrawWriter::DrawWriter(DrawDispatcher* dispatcher, DrawBufferManager* bufferManager)
        : DrawWriter(dispatcher, bufferManager, PrimitiveType::kTriangles, 0, 0) {}

DrawWriter::DrawWriter(DrawDispatcher* dispatcher,
                       DrawBufferManager* bufferManager,
                       PrimitiveType primitiveType,
                       size_t vertexStride,
                       size_t instanceStride)
        : fDispatcher(dispatcher)
        , fManager(bufferManager)
        , fPrimitiveType(primitiveType)
        , fVertexStride(vertexStride)
        , fInstanceStride(instanceStride) {
    SkASSERT(dispatcher && bufferManager);
}

void DrawWriter::setTemplateInternal(BindBufferInfo vertices,
                                     BindBufferInfo indices,
                                     unsigned int count,
                                     bool drawPendingVertices) {
    SkASSERT(!vertices || fVertexStride > 0);
    if (vertices != fFixedVertexBuffer ||
        indices != fFixedIndexBuffer ||
        count != fFixedVertexCount) {
        // Issue any accumulated data that referred to the old template.
        if (drawPendingVertices) {
            this->drawPendingVertices();
        }

        fFixedBuffersDirty = true;

        fFixedVertexBuffer = vertices;
        fFixedIndexBuffer = indices;
        fFixedVertexCount = count;
    }
}

void DrawWriter::drawInternal(BindBufferInfo instances,
                              unsigned int base,
                              unsigned int instanceCount) {
    // Draw calls that are only 1 instance and have no extra instance data get routed to
    // the simpler draw APIs.
    // TODO: Is there any benefit to this? Does it help hint to drivers? Avoid more bugs?
    // Or should we always call drawInstanced and drawIndexedInstanced?
    const bool useInstancedDraw = fInstanceStride > 0 || instanceCount > 1;
    SkASSERT(useInstancedDraw ||
             (fInstanceStride == 0 && instanceCount == 1 && !SkToBool(instances)));

    // Issue new buffer binds only as necessary
    // TODO: Should this instead be the responsibility of the CB or DrawDispatcher to remember
    // what was last bound?
    if (fFixedBuffersDirty || instances != fLastInstanceBuffer) {
        fDispatcher->bindDrawBuffers(fFixedVertexBuffer, instances, fFixedIndexBuffer);
        fFixedBuffersDirty = false;
        fLastInstanceBuffer = instances;
    }

    if (useInstancedDraw) {
        // 'base' offsets accumulated instance data (or is 0 for a direct instanced draw). It is
        // assumed that any base vertex and index have been folded into the BindBufferInfos already.
        if (fFixedIndexBuffer) {
            fDispatcher->drawIndexedInstanced(fPrimitiveType, 0, fFixedVertexCount, 0,
                                              base, instanceCount);
        } else {
            fDispatcher->drawInstanced(fPrimitiveType, 0, fFixedVertexCount, base, instanceCount);
        }
    } else {
        if (fFixedIndexBuffer) {
            // Should only get here from a direct draw, in which case base should be 0 and any
            // offset needs to be embedded in the BindBufferInfo by caller.
            SkASSERT(base == 0);
            fDispatcher->drawIndexed(fPrimitiveType, 0, fFixedVertexCount, 0);
        } else {
            // 'base' offsets accumulated vertex data from another DrawWriter across a state change.
            fDispatcher->draw(fPrimitiveType, base, fFixedVertexCount);
        }
    }
}

void DrawWriter::drawPendingVertices() {
    if (fPendingCount > 0) {
        if (fPendingMode == VertexMode::kInstances) {
            // This uses instanced draws, so 'base' will be interpreted in instance units.
            this->drawInternal(fPendingAttrs, fPendingBaseVertex, fPendingCount);
        } else {
            // This triggers a non-instanced draw call so 'base' passed to drawInternal is
            // interpreted in vertex units.
            this->setTemplateInternal(fPendingAttrs, {}, fPendingCount, /*drawPending=*/false);
            this->drawInternal({}, fPendingBaseVertex, 1);
        }

        fPendingCount = 0;
        fPendingBaseVertex = 0;
        fPendingAttrs = {};
    }
}

VertexWriter DrawWriter::appendData(VertexMode mode, size_t stride, unsigned int count) {
    if (fPendingMode != mode) {
        // Switched between accumulating vertices and instances, so issue draws for the old data.
        this->drawPendingVertices();
        fPendingMode = mode;
    }

    auto [writer, nextChunk] = fManager->getVertexWriter(count * stride);
    // Check if next chunk's data is contiguous with what's previously been appended
    if (nextChunk.fBuffer == fPendingAttrs.fBuffer &&
        fPendingAttrs.fOffset + (fPendingBaseVertex + fPendingCount) * stride
                == nextChunk.fOffset) {
        // It is, so the next chunk's vertices that will be written can be folded into the next draw
        fPendingCount += count;
    } else {
        // Alignment mismatch, or the old buffer filled up
        this->drawPendingVertices();
        fPendingCount = count;
        fPendingBaseVertex = 0;
        fPendingAttrs = nextChunk;
    }

    return std::move(writer);
}

void DrawWriter::newDynamicState() {
    // Remember where we left off after we draw, since drawPendingVertices() resets all pending data
    BindBufferInfo base = fPendingAttrs;
    unsigned int baseVertex = fPendingBaseVertex + fPendingCount;
    // Draw anything that used the previous dynamic state
    this->drawPendingVertices();

    fPendingAttrs = base;
    fPendingBaseVertex = baseVertex;
}

void DrawWriter::newPipelineState(PrimitiveType type,
                                  size_t vertexStride,
                                  size_t instanceStride) {
    // Draw anything that used the previous pipeline
    this->drawPendingVertices();

    // For simplicity, if there's a new pipeline, just forget about any previous buffer bindings,
    // in which case the new writer only needs to use the dispatcher and buffer manager.
    this->setTemplateInternal({}, {}, 0, false);
    fLastInstanceBuffer = {};

    fPrimitiveType = type;
    fVertexStride = vertexStride;
    fInstanceStride = instanceStride;
}

} // namespace skgpu
<|endoftext|>


<commit_before>#ifndef VIENNAGRID_SEGMENTED_MESH_HPP
#define VIENNAGRID_SEGMENTED_MESH_HPP

#include "viennagrid/mesh/mesh.hpp"
#include "viennagrid/mesh/segmentation.hpp"

namespace viennagrid
{

  template<typename MeshT, typename SegmentationT>
  struct segmented_mesh
  {
    typedef MeshT mesh_type;
    typedef SegmentationT segmentation_type;

    mesh_type mesh;
    segmentation_type segmentation;
  };

  template<typename WrappedMeshConfig, typename WrappedSegmentationConfig>
  struct segmented_mesh< viennagrid::mesh<WrappedMeshConfig>, viennagrid::segmentation<WrappedSegmentationConfig> >
  {
    typedef segmented_mesh< viennagrid::mesh<WrappedMeshConfig>, viennagrid::segmentation<WrappedSegmentationConfig> > SelfType;

    typedef viennagrid::mesh<WrappedMeshConfig> mesh_type;
    typedef viennagrid::segmentation<WrappedSegmentationConfig> segmentation_type;

    segmented_mesh() : segmentation(mesh) {}

    segmented_mesh(SelfType const & other) : segmentation(mesh)
    {
      *this = other;
    }

    SelfType & operator=(SelfType const & other)
    {
      clear();

      viennagrid::vertex_copy_map<mesh_type, mesh_type> vertex_map(mesh);

      typedef typename viennagrid::result_of::cell<mesh_type>::type CellType;
      typedef typename viennagrid::result_of::coord<mesh_type>::type NumericType;

      typedef typename viennagrid::result_of::const_cell_range<mesh_type>::type ConstCellRangeType;
      typedef typename viennagrid::result_of::iterator<ConstCellRangeType>::type ConstCellIteratorType;

      typedef typename viennagrid::result_of::segment_id_range<segmentation_type, CellType>::type SrcSegmentIDRangeType;
      typedef typename viennagrid::result_of::segment_id<segmentation_type>::type DstSegmentIDType;

      typedef typename viennagrid::result_of::cell_handle<mesh_type>::type CellHandleType;

      ConstCellRangeType cells(other.mesh);
      for (ConstCellIteratorType cit = cells.begin(); cit != cells.end(); ++cit)
      {
        CellHandleType cell_handle = vertex_map.copy_element(*cit );
        viennagrid::add( segmentation, cell_handle, viennagrid::segment_ids( other.segmentation, *cit ).begin(), viennagrid::segment_ids( other.segmentation, *cit ).end() );
      }

//       mesh = other.mesh;
//       copy_segmentation( other.mesh, other.segmentation, mesh, segmentation );

      return *this;
    }

    void clear()
    {
      mesh.clear();
      segmentation.clear();
    }

    mesh_type mesh;
    segmentation_type segmentation;

  private:
  };

}

#endif
<commit_msg>fixed depndencies (header)<commit_after>#ifndef VIENNAGRID_SEGMENTED_MESH_HPP
#define VIENNAGRID_SEGMENTED_MESH_HPP

#include "viennagrid/mesh/mesh.hpp"
#include "viennagrid/mesh/segmentation.hpp"
#include "viennagrid/mesh/mesh_operations.hpp"

namespace viennagrid
{

  template<typename MeshT, typename SegmentationT>
  struct segmented_mesh
  {
    typedef MeshT mesh_type;
    typedef SegmentationT segmentation_type;

    mesh_type mesh;
    segmentation_type segmentation;
  };

  template<typename WrappedMeshConfig, typename WrappedSegmentationConfig>
  struct segmented_mesh< viennagrid::mesh<WrappedMeshConfig>, viennagrid::segmentation<WrappedSegmentationConfig> >
  {
    typedef segmented_mesh< viennagrid::mesh<WrappedMeshConfig>, viennagrid::segmentation<WrappedSegmentationConfig> > SelfType;

    typedef viennagrid::mesh<WrappedMeshConfig> mesh_type;
    typedef viennagrid::segmentation<WrappedSegmentationConfig> segmentation_type;

    segmented_mesh() : segmentation(mesh) {}

    segmented_mesh(SelfType const & other) : segmentation(mesh)
    {
      *this = other;
    }

    SelfType & operator=(SelfType const & other)
    {
      clear();

      viennagrid::vertex_copy_map<mesh_type, mesh_type> vertex_map(mesh);

      typedef typename viennagrid::result_of::cell<mesh_type>::type CellType;
      typedef typename viennagrid::result_of::coord<mesh_type>::type NumericType;

      typedef typename viennagrid::result_of::const_cell_range<mesh_type>::type ConstCellRangeType;
      typedef typename viennagrid::result_of::iterator<ConstCellRangeType>::type ConstCellIteratorType;

      typedef typename viennagrid::result_of::segment_id_range<segmentation_type, CellType>::type SrcSegmentIDRangeType;
      typedef typename viennagrid::result_of::segment_id<segmentation_type>::type DstSegmentIDType;

      typedef typename viennagrid::result_of::cell_handle<mesh_type>::type CellHandleType;

      ConstCellRangeType cells(other.mesh);
      for (ConstCellIteratorType cit = cells.begin(); cit != cells.end(); ++cit)
      {
        CellHandleType cell_handle = vertex_map.copy_element(*cit );
        viennagrid::add( segmentation, cell_handle, viennagrid::segment_ids( other.segmentation, *cit ).begin(), viennagrid::segment_ids( other.segmentation, *cit ).end() );
      }

//       mesh = other.mesh;
//       copy_segmentation( other.mesh, other.segmentation, mesh, segmentation );

      return *this;
    }

    void clear()
    {
      mesh.clear();
      segmentation.clear();
    }

    mesh_type mesh;
    segmentation_type segmentation;

  private:
  };

}

#endif
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Name:      test-managedm_Frame.cpp
// Purpose:   Implementation for wxExtension cpp unit testing
// Author:    Anton van Wezenbeek
// Copyright: (c) 2015 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/extension/managedframe.h>
#include <wx/extension/defs.h>
#include <wx/extension/stc.h>
#include <wx/extension/vi.h>
#include "test.h"

// Also test the toolbar (wxExToolBar).
void fixture::testManagedFrame()
{
  CPPUNIT_ASSERT(m_Frame->AllowClose(100, NULL));

  wxExSTC* stc = new wxExSTC(m_Frame, "hello world");
  wxExVi* vi = &stc->GetVi();

  CPPUNIT_ASSERT(!m_Frame->ExecExCommand(":n", NULL));

  m_Frame->GetExCommand(vi, "/");

  m_Frame->HideExBar(wxExManagedFrame::HIDE_BAR);
  m_Frame->HideExBar(wxExManagedFrame::HIDE_BAR_FOCUS_STC);
  m_Frame->HideExBar(wxExManagedFrame::HIDE_BAR_FORCE);
  m_Frame->HideExBar(wxExManagedFrame::HIDE_BAR_FORCE_FOCUS_STC);

  CPPUNIT_ASSERT(!m_Frame->GetManager().GetPane("VIBAR").IsShown());

  m_Frame->SetRecentFile("testing");

  m_Frame->ShowExMessage("hello from m_Frame");

  m_Frame->SyncAll();
  m_Frame->SyncCloseAll(0);

  CPPUNIT_ASSERT( m_Frame->GetToolBar() != NULL);
  CPPUNIT_ASSERT( m_Frame->TogglePane("FINDBAR"));
  CPPUNIT_ASSERT( m_Frame->GetManager().GetPane("FINDBAR").IsShown());
  CPPUNIT_ASSERT( m_Frame->TogglePane("OPTIONSBAR"));
  CPPUNIT_ASSERT( m_Frame->GetManager().GetPane("OPTIONSBAR").IsShown());
  CPPUNIT_ASSERT( m_Frame->TogglePane("TOOLBAR"));
  CPPUNIT_ASSERT(!m_Frame->GetManager().GetPane("TOOLBAR").IsShown());
  CPPUNIT_ASSERT( m_Frame->TogglePane("VIBAR"));
  CPPUNIT_ASSERT( m_Frame->GetManager().GetPane("VIBAR").IsShown());

  CPPUNIT_ASSERT(!m_Frame->TogglePane("XXXXBAR"));
  CPPUNIT_ASSERT(!m_Frame->GetManager().GetPane("XXXXBAR").IsOk());

  for (auto id : std::vector<int> {
    wxID_PREFERENCES, ID_FIND_FIRST,
    ID_VIEW_FINDBAR, ID_VIEW_OPTIONSBAR, ID_VIEW_TOOLBAR})
  {
    wxPostEvent(m_Frame, wxCommandEvent(wxEVT_MENU, id));
  }
}
<commit_msg>fixed compile error<commit_after>////////////////////////////////////////////////////////////////////////////////
// Name:      test-managedm_Frame.cpp
// Purpose:   Implementation for wxExtension cpp unit testing
// Author:    Anton van Wezenbeek
// Copyright: (c) 2015 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/extension/managedframe.h>
#include <wx/extension/defs.h>
#include <wx/extension/stc.h>
#include <wx/extension/vi.h>
#include "test.h"

// Also test the toolbar (wxExToolBar).
void fixture::testManagedFrame()
{
  CPPUNIT_ASSERT(m_Frame->AllowClose(100, NULL));

  wxExSTC* stc = new wxExSTC(m_Frame, "hello world");
  wxExVi* vi = &stc->GetVi();

  wxExSTC* stc2 = NULL;
  CPPUNIT_ASSERT(!m_Frame->ExecExCommand(":n", stc2));
  CPPUNIT_ASSERT( stc2 == NULL);

  m_Frame->GetExCommand(vi, "/");

  m_Frame->HideExBar(wxExManagedFrame::HIDE_BAR);
  m_Frame->HideExBar(wxExManagedFrame::HIDE_BAR_FOCUS_STC);
  m_Frame->HideExBar(wxExManagedFrame::HIDE_BAR_FORCE);
  m_Frame->HideExBar(wxExManagedFrame::HIDE_BAR_FORCE_FOCUS_STC);

  CPPUNIT_ASSERT(!m_Frame->GetManager().GetPane("VIBAR").IsShown());

  m_Frame->SetRecentFile("testing");

  m_Frame->ShowExMessage("hello from m_Frame");

  m_Frame->SyncAll();
  m_Frame->SyncCloseAll(0);

  CPPUNIT_ASSERT( m_Frame->GetToolBar() != NULL);
  CPPUNIT_ASSERT( m_Frame->TogglePane("FINDBAR"));
  CPPUNIT_ASSERT( m_Frame->GetManager().GetPane("FINDBAR").IsShown());
  CPPUNIT_ASSERT( m_Frame->TogglePane("OPTIONSBAR"));
  CPPUNIT_ASSERT( m_Frame->GetManager().GetPane("OPTIONSBAR").IsShown());
  CPPUNIT_ASSERT( m_Frame->TogglePane("TOOLBAR"));
  CPPUNIT_ASSERT(!m_Frame->GetManager().GetPane("TOOLBAR").IsShown());
  CPPUNIT_ASSERT( m_Frame->TogglePane("VIBAR"));
  CPPUNIT_ASSERT( m_Frame->GetManager().GetPane("VIBAR").IsShown());

  CPPUNIT_ASSERT(!m_Frame->TogglePane("XXXXBAR"));
  CPPUNIT_ASSERT(!m_Frame->GetManager().GetPane("XXXXBAR").IsOk());

  for (auto id : std::vector<int> {
    wxID_PREFERENCES, ID_FIND_FIRST,
    ID_VIEW_FINDBAR, ID_VIEW_OPTIONSBAR, ID_VIEW_TOOLBAR})
  {
    wxPostEvent(m_Frame, wxCommandEvent(wxEVT_MENU, id));
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 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 "views/widget/native_widget_view.h"

#include "ui/gfx/canvas.h"
#include "ui/gfx/compositor/layer.h"

namespace views {
namespace internal {

////////////////////////////////////////////////////////////////////////////////
// NativeWidgetView, public:

// static
const char NativeWidgetView::kViewClassName[] = "views/NativeWidgetView";

NativeWidgetView::NativeWidgetView(NativeWidgetViews* native_widget)
    : native_widget_(native_widget),
      sent_create_(false),
      delete_native_widget_(true),
      cursor_(NULL) {
}

NativeWidgetView::~NativeWidgetView() {
  // Don't let NativeWidgetViews delete this again.  This must be outside
  // the |delete_native_widget_| clause so it gets invoked for
  // WIDGET_OWNS_NATIVE_WIDGET.  It is safe because |native_widget_| will
  // still exist in both ways NativeWidgetView can be destroyed: by view
  // hierarchy teardown and from the NativeWidgetViews destructor.
  native_widget_->set_delete_native_view(false);
  if (delete_native_widget_)
    delete native_widget_;
}

Widget* NativeWidgetView::GetAssociatedWidget() {
  return native_widget_->delegate()->AsWidget();
}

////////////////////////////////////////////////////////////////////////////////
// NativeWidgetView, View overrides:

void NativeWidgetView::CalculateOffsetToAncestorWithLayer(
    gfx::Point* offset,
    ui::Layer** layer_parent) {
  View::CalculateOffsetToAncestorWithLayer(offset, layer_parent);
}

#if !defined(NDEBUG)
std::string NativeWidgetView::PrintViewGraph(bool first) {
  return DoPrintViewGraph(first, GetAssociatedWidget()->GetRootView());
}
#endif

void NativeWidgetView::ViewHierarchyChanged(bool is_add,
                                            View* parent,
                                            View* child) {
  if (is_add && child == this)  {
    GetAssociatedWidget()->GetRootView()->UpdateParentLayers();
    if (!sent_create_) {
      sent_create_ = true;
      delegate()->OnNativeWidgetCreated();
    }
  }
}

void NativeWidgetView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
  native_widget_->OnBoundsChanged(bounds(), previous_bounds);
}

void NativeWidgetView::OnPaint(gfx::Canvas* canvas) {
  delegate()->OnNativeWidgetPaint(canvas);
}

gfx::NativeCursor NativeWidgetView::GetCursor(const MouseEvent& event) {
  return cursor_;
}

bool NativeWidgetView::OnMousePressed(const MouseEvent& event) {
  return native_widget_->OnMouseEvent(event);
}

bool NativeWidgetView::OnMouseDragged(const MouseEvent& event) {
  return native_widget_->OnMouseEvent(event);
}

void NativeWidgetView::OnMouseReleased(const MouseEvent& event) {
  native_widget_->OnMouseEvent(event);
}

void NativeWidgetView::OnMouseCaptureLost() {
  delegate()->OnMouseCaptureLost();
}

void NativeWidgetView::OnMouseMoved(const MouseEvent& event) {
  native_widget_->OnMouseEvent(event);
}

void NativeWidgetView::OnMouseEntered(const MouseEvent& event) {
  native_widget_->OnMouseEvent(event);
}

void NativeWidgetView::OnMouseExited(const MouseEvent& event) {
  native_widget_->OnMouseEvent(event);
}

ui::TouchStatus NativeWidgetView::OnTouchEvent(const TouchEvent& event) {
  return delegate()->OnTouchEvent(event);
}

bool NativeWidgetView::OnKeyPressed(const KeyEvent& event) {
  return delegate()->OnKeyEvent(event);
}

bool NativeWidgetView::OnKeyReleased(const KeyEvent& event) {
  return delegate()->OnKeyEvent(event);
}

bool NativeWidgetView::OnMouseWheel(const MouseWheelEvent& event) {
  return native_widget_->OnMouseEvent(event);
}

void NativeWidgetView::VisibilityChanged(View* starting_from,
                                         bool visible) {
  delegate()->OnNativeWidgetVisibilityChanged(visible);
}

void NativeWidgetView::OnFocus() {
  // TODO(beng): check if we have to do this.
  //delegate()->OnNativeFocus(NULL);
}

void NativeWidgetView::OnBlur() {
  // TODO(beng): check if we have to do this.
  //delegate()->OnNativeBlur(NULL);
}

std::string NativeWidgetView::GetClassName() const {
  return kViewClassName;
}

void NativeWidgetView::MoveLayerToParent(ui::Layer* parent_layer,
                                         const gfx::Point& point) {
  View::MoveLayerToParent(parent_layer, point);
  if (!layer() || parent_layer == layer()) {
    gfx::Point new_offset(point);
    if (layer() != parent_layer)
      new_offset.Offset(x(), y());
    GetAssociatedWidget()->GetRootView()->MoveLayerToParent(
        parent_layer, new_offset);
  }
}

void NativeWidgetView::UpdateChildLayerBounds(const gfx::Point& offset) {
  gfx::Point new_offset(offset.x() + x(), offset.y() + y());
  View::UpdateChildLayerBounds(new_offset);
  if (!layer())
    GetAssociatedWidget()->GetRootView()->UpdateChildLayerBounds(new_offset);
}

}  // namespace internal
}  // namespace views
<commit_msg>Don't reapply offset in NativeWidgetView::UpdateChildLayerBounds.<commit_after>// Copyright (c) 2011 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 "views/widget/native_widget_view.h"

#include "ui/gfx/canvas.h"
#include "ui/gfx/compositor/layer.h"

namespace views {
namespace internal {

////////////////////////////////////////////////////////////////////////////////
// NativeWidgetView, public:

// static
const char NativeWidgetView::kViewClassName[] = "views/NativeWidgetView";

NativeWidgetView::NativeWidgetView(NativeWidgetViews* native_widget)
    : native_widget_(native_widget),
      sent_create_(false),
      delete_native_widget_(true),
      cursor_(NULL) {
}

NativeWidgetView::~NativeWidgetView() {
  // Don't let NativeWidgetViews delete this again.  This must be outside
  // the |delete_native_widget_| clause so it gets invoked for
  // WIDGET_OWNS_NATIVE_WIDGET.  It is safe because |native_widget_| will
  // still exist in both ways NativeWidgetView can be destroyed: by view
  // hierarchy teardown and from the NativeWidgetViews destructor.
  native_widget_->set_delete_native_view(false);
  if (delete_native_widget_)
    delete native_widget_;
}

Widget* NativeWidgetView::GetAssociatedWidget() {
  return native_widget_->delegate()->AsWidget();
}

////////////////////////////////////////////////////////////////////////////////
// NativeWidgetView, View overrides:

void NativeWidgetView::CalculateOffsetToAncestorWithLayer(
    gfx::Point* offset,
    ui::Layer** layer_parent) {
  View::CalculateOffsetToAncestorWithLayer(offset, layer_parent);
}

#if !defined(NDEBUG)
std::string NativeWidgetView::PrintViewGraph(bool first) {
  return DoPrintViewGraph(first, GetAssociatedWidget()->GetRootView());
}
#endif

void NativeWidgetView::ViewHierarchyChanged(bool is_add,
                                            View* parent,
                                            View* child) {
  if (is_add && child == this)  {
    GetAssociatedWidget()->GetRootView()->UpdateParentLayers();
    if (!sent_create_) {
      sent_create_ = true;
      delegate()->OnNativeWidgetCreated();
    }
  }
}

void NativeWidgetView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
  native_widget_->OnBoundsChanged(bounds(), previous_bounds);
}

void NativeWidgetView::OnPaint(gfx::Canvas* canvas) {
  delegate()->OnNativeWidgetPaint(canvas);
}

gfx::NativeCursor NativeWidgetView::GetCursor(const MouseEvent& event) {
  return cursor_;
}

bool NativeWidgetView::OnMousePressed(const MouseEvent& event) {
  return native_widget_->OnMouseEvent(event);
}

bool NativeWidgetView::OnMouseDragged(const MouseEvent& event) {
  return native_widget_->OnMouseEvent(event);
}

void NativeWidgetView::OnMouseReleased(const MouseEvent& event) {
  native_widget_->OnMouseEvent(event);
}

void NativeWidgetView::OnMouseCaptureLost() {
  delegate()->OnMouseCaptureLost();
}

void NativeWidgetView::OnMouseMoved(const MouseEvent& event) {
  native_widget_->OnMouseEvent(event);
}

void NativeWidgetView::OnMouseEntered(const MouseEvent& event) {
  native_widget_->OnMouseEvent(event);
}

void NativeWidgetView::OnMouseExited(const MouseEvent& event) {
  native_widget_->OnMouseEvent(event);
}

ui::TouchStatus NativeWidgetView::OnTouchEvent(const TouchEvent& event) {
  return delegate()->OnTouchEvent(event);
}

bool NativeWidgetView::OnKeyPressed(const KeyEvent& event) {
  return delegate()->OnKeyEvent(event);
}

bool NativeWidgetView::OnKeyReleased(const KeyEvent& event) {
  return delegate()->OnKeyEvent(event);
}

bool NativeWidgetView::OnMouseWheel(const MouseWheelEvent& event) {
  return native_widget_->OnMouseEvent(event);
}

void NativeWidgetView::VisibilityChanged(View* starting_from,
                                         bool visible) {
  delegate()->OnNativeWidgetVisibilityChanged(visible);
}

void NativeWidgetView::OnFocus() {
  // TODO(beng): check if we have to do this.
  //delegate()->OnNativeFocus(NULL);
}

void NativeWidgetView::OnBlur() {
  // TODO(beng): check if we have to do this.
  //delegate()->OnNativeBlur(NULL);
}

std::string NativeWidgetView::GetClassName() const {
  return kViewClassName;
}

void NativeWidgetView::MoveLayerToParent(ui::Layer* parent_layer,
                                         const gfx::Point& point) {
  View::MoveLayerToParent(parent_layer, point);
  if (!layer() || parent_layer == layer()) {
    gfx::Point new_offset(point);
    if (layer() != parent_layer)
      new_offset.Offset(x(), y());
    GetAssociatedWidget()->GetRootView()->MoveLayerToParent(
        parent_layer, new_offset);
  }
}

void NativeWidgetView::UpdateChildLayerBounds(const gfx::Point& offset) {
  View::UpdateChildLayerBounds(offset);
  if (!layer()) {
    const gfx::Rect& bounds = GetAssociatedWidget()->GetRootView()->bounds();
    gfx::Point new_offset(offset.x() + bounds.x(), offset.y() + bounds.y());
    GetAssociatedWidget()->GetRootView()->UpdateChildLayerBounds(new_offset);
  }
}

}  // namespace internal
}  // namespace views
<|endoftext|>