<commit_before>#pragma once
/**
	@file
	@brief tiny time class

	Copyright (C) 2008 Cybozu Labs, Inc., all rights reserved.
*/
#include <ctime>
#include <cybozu/exception.hpp>
#include <cybozu/atoi.hpp>
#include <cybozu/itoa.hpp>
#ifdef _WIN32
	#include <sys/timeb.h>
#else
	#include <sys/time.h>
#endif

namespace cybozu {

/**
	time struct with time_t and msec
	@note time MUST be latesr than 1970/1/1
*/
class Time {
	static const uint64_t epochBias = 116444736000000000ull;
	std::time_t time_;
	int msec_;
public:
	Time() {}
	explicit Time(std::time_t time, int msec = 0)
		: time_(time)
		, msec_(msec)
	{
	}
	explicit Time(bool doSet)
	{
		if (doSet) setCurrentTime();
	}
	double getTimeMsec() const { return time_ + msec_ * 0.001; }
	Time& setTime(std::time_t time, int msec = 0)
	{
		time_ = time;
		msec_ = msec;
		return *this;
	}
	/*
		Windows FILETIME is defined as
		struct FILETILME {
			DWORD dwLowDateTime;
			DWORD dwHighDateTime;
		};
		the value represents the number of 100-nanosecond intervals since January 1, 1601 (UTC).
	*/
	void setByFILETIME(uint32_t low, uint32_t high)
	{
		const uint64_t fileTime = (((uint64_t(high) << 32) | low) - epochBias) / 10000;
		time_ = fileTime / 1000;
		msec_ = fileTime % 1000;
	}
	/*
		DWORD is defined as unsigned long in windows
	*/
	template<class dword>
	void getFILETIME(dword& low, dword& high) const
	{
		const uint64_t fileTime = (time_ * 1000 + msec_) * 10000 + epochBias;
		low = dword(fileTime);
		high = dword(fileTime >> 32);
	}
	explicit Time(const std::string& in)
	{
		fromString(in);
	}
	explicit Time(const char *in)
	{
		fromString(in, in + strlen(in));
	}
	const std::time_t& getTime() const { return time_; }
	int getMsec() const { return msec_; }
	void addSec(int sec) { time_ += sec; }
	bool operator<(const Time& rhs) const { return (time_ < rhs.time_) || (time_ == rhs.time_ && msec_ < rhs.msec_); }
//	bool operator<=(const Time& rhs) const { return (*this < rhs) || (*this == rhs); }
//	bool operator>(const Time& rhs) const { return rhs < *this; }
	bool operator==(const Time& rhs) const { return (time_ == rhs.time_) && (msec_ == rhs.msec_); }
	bool operator!=(const Time& rhs) const { return !(*this == rhs); }
	/**
		set time from string such as
		2009-Jan-23T02:53:44Z
		2009-Jan-23T02:53:44.078Z
		2009-01-23T02:53:44Z
		2009-01-23T02:53:44.078Z
		@note 'T' may be ' '. '-' may be '/'. last char 'Z' is omissible
	*/
	void fromString(const std::string& in) { fromString(&in[0], &in[0] + in.size()); }

	void fromString(const char *begin, const char *end)
	{
		const size_t len = end - begin;
		if (len >= 19) {
			const char *p = begin;
			struct tm tm;
			int num;
			bool b;
			tm.tm_year = getNum(&b, p, 4, 1970, 3000) - 1900;
			if (!b) goto ERR;
			p += 4;
			char sep = *p++;
			if (sep != '-' && sep != '/') goto ERR;

			p = getMonth(&num, p);
			if (p == 0) goto ERR;
			tm.tm_mon = num;
			if (*p++ != sep) goto ERR;

			tm.tm_mday = getNum(&b, p, 2, 1, 31);
			if (!b) goto ERR;
			p += 2;
			if (*p != ' ' && *p != 'T') goto ERR;
			p++;

			tm.tm_hour = getNum(&b, p, 2, 0, 23);
			if (!b) goto ERR;
			p += 2;
			if (*p++ != ':') goto ERR;

			tm.tm_min = getNum(&b, p, 2, 0, 59);
			if (!b) goto ERR;
			p += 2;
			if (*p++ != ':') goto ERR;

			tm.tm_sec = getNum(&b, p, 2, 0, 59);
			if (!b) goto ERR;
			p += 2;

			if (p == end) {
				msec_ = 0;
			} else if (p + 1 == end && *p == 'Z') {
				msec_ = 0;
				p++;
			} else if (*p == '.' && (p + 4 == end || (p + 5 == end && *(p + 4) == 'Z'))) {
				msec_ = getNum(&b, p + 1, 3, 0, 999);
				if (!b) goto ERR;
				p += 4;
			} else {
				goto ERR;
			}
#ifdef _WIN32
			time_ = _mkgmtime64(&tm);
			if (time_ == -1) goto ERR;
#else
			time_ = timegm(&tm);
#endif
			return;
		}
	ERR:
		throw cybozu::Exception("time::fromString") << std::string(begin, 24);
	}

	/**
		get current time with format
		@param out [out] output string
		@param format [in] foramt for strftime and append three digits for msec
		@param appendMsec [in] appemd <mmm>
		@param doClear (append to out if false)
		@note ex. "%Y-%b-%d %H:%M:%S." to get 2009-Jan-23 02:53:44.078
	*/
	void toString(std::string& out, const char *format, bool appendMsec = true, bool doClear = true) const
	{
		if (doClear) out.clear();
		char buf[128];
#ifdef _WIN32
		struct tm tm;
		if (_gmtime64_s(&tm, &time_) != 0) {
			throw cybozu::Exception("time::toString") << time_;
		}
		struct tm *ptm = &tm;
#else
		struct tm *ptm = gmtime(&time_);
#endif
		if (std::strftime(buf, sizeof(buf), format, ptm) == 0) {
			throw cybozu::Exception("time::toString::too long") << format << time_;
		}
		out += buf;
		if (appendMsec) {
			out += cybozu::itoaWithZero(msec_, 3);
		}
	}

	/**
		get current time such as 2009-01-23 02:53:44.078
		@param out [out] sink string
	*/
	void toString(std::string& out, bool appendMsec = true, bool doClear = true) const
	{
		const char *format = appendMsec ? "%Y-%m-%d %H:%M:%S." : "%Y-%m-%d %H:%M:%S";
		toString(out, format, appendMsec, doClear);
	}
	std::string toString() const { std::string out; toString(out); return out; }
	/**
		get current time
	*/
	Time& setCurrentTime()
	{
#ifdef _WIN32
		struct _timeb timeb;
		_ftime_s(&timeb);
		time_ = timeb.time;
		msec_ = timeb.millitm;
#else
		struct timeval tv;
		gettimeofday(&tv, 0);
		time_ = tv.tv_sec;
		msec_ = tv.tv_usec / 1000;
#endif
		return *this;
	}
private:

	int getNum(bool *b, const char *in, size_t len, int min, int max) const
	{
		int ret = cybozu::atoi(b, in, len);
		if (min <= ret && ret <= max) {
			return ret;
		} else {
			*b = false;
			return 0;
		}
	}

	/*
		convert month-str to [0, 11]
		@param ret [out] return idx
		@param p [in] month-str
		@retval next pointer or null
	*/
	const char *getMonth(int *ret, const char *p) const
	{
		static const char monthTbl[12][4] = {
			"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
		};

		for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(monthTbl); i++) {
			if (memcmp(p, monthTbl[i], 3) == 0) {
				*ret = (int)i;
				return p + 3;
			}
		}
		bool b;
		*ret = getNum(&b, p, 2, 1, 12) - 1;
		if (b) {
			return p + 2;
		} else {
			return 0;
		}
	}
};

inline std::ostream& operator<<(std::ostream& os, const cybozu::Time& time)
{
	return os << time.toString();
}

} // cybozu
<commit_msg>fix unit<commit_after>#pragma once
/**
	@file
	@brief tiny time class

	Copyright (C) 2008 Cybozu Labs, Inc., all rights reserved.
*/
#include <ctime>
#include <cybozu/exception.hpp>
#include <cybozu/atoi.hpp>
#include <cybozu/itoa.hpp>
#ifdef _WIN32
	#include <sys/timeb.h>
#else
	#include <sys/time.h>
#endif

namespace cybozu {

/**
	time struct with time_t and msec
	@note time MUST be latesr than 1970/1/1
*/
class Time {
	static const uint64_t epochBias = 116444736000000000ull;
	std::time_t time_;
	int msec_;
public:
	Time() {}
	explicit Time(std::time_t time, int msec = 0)
		: time_(time)
		, msec_(msec)
	{
	}
	explicit Time(bool doSet)
	{
		if (doSet) setCurrentTime();
	}
	Time& setTime(std::time_t time, int msec = 0)
	{
		time_ = time;
		msec_ = msec;
		return *this;
	}
	/*
		Windows FILETIME is defined as
		struct FILETILME {
			DWORD dwLowDateTime;
			DWORD dwHighDateTime;
		};
		the value represents the number of 100-nanosecond intervals since January 1, 1601 (UTC).
	*/
	void setByFILETIME(uint32_t low, uint32_t high)
	{
		const uint64_t fileTime = (((uint64_t(high) << 32) | low) - epochBias) / 10000;
		time_ = fileTime / 1000;
		msec_ = fileTime % 1000;
	}
	/*
		DWORD is defined as unsigned long in windows
	*/
	template<class dword>
	void getFILETIME(dword& low, dword& high) const
	{
		const uint64_t fileTime = (time_ * 1000 + msec_) * 10000 + epochBias;
		low = dword(fileTime);
		high = dword(fileTime >> 32);
	}
	explicit Time(const std::string& in)
	{
		fromString(in);
	}
	explicit Time(const char *in)
	{
		fromString(in, in + strlen(in));
	}
	const std::time_t& getTime() const { return time_; }
	int getMsec() const { return msec_; }
	double getTimeSec() const { return time_ + msec_ * 1e-3; }
	void addSec(int sec) { time_ += sec; }
	bool operator<(const Time& rhs) const { return (time_ < rhs.time_) || (time_ == rhs.time_ && msec_ < rhs.msec_); }
//	bool operator<=(const Time& rhs) const { return (*this < rhs) || (*this == rhs); }
//	bool operator>(const Time& rhs) const { return rhs < *this; }
	bool operator==(const Time& rhs) const { return (time_ == rhs.time_) && (msec_ == rhs.msec_); }
	bool operator!=(const Time& rhs) const { return !(*this == rhs); }
	/**
		set time from string such as
		2009-Jan-23T02:53:44Z
		2009-Jan-23T02:53:44.078Z
		2009-01-23T02:53:44Z
		2009-01-23T02:53:44.078Z
		@note 'T' may be ' '. '-' may be '/'. last char 'Z' is omissible
	*/
	void fromString(const std::string& in) { fromString(&in[0], &in[0] + in.size()); }

	void fromString(const char *begin, const char *end)
	{
		const size_t len = end - begin;
		if (len >= 19) {
			const char *p = begin;
			struct tm tm;
			int num;
			bool b;
			tm.tm_year = getNum(&b, p, 4, 1970, 3000) - 1900;
			if (!b) goto ERR;
			p += 4;
			char sep = *p++;
			if (sep != '-' && sep != '/') goto ERR;

			p = getMonth(&num, p);
			if (p == 0) goto ERR;
			tm.tm_mon = num;
			if (*p++ != sep) goto ERR;

			tm.tm_mday = getNum(&b, p, 2, 1, 31);
			if (!b) goto ERR;
			p += 2;
			if (*p != ' ' && *p != 'T') goto ERR;
			p++;

			tm.tm_hour = getNum(&b, p, 2, 0, 23);
			if (!b) goto ERR;
			p += 2;
			if (*p++ != ':') goto ERR;

			tm.tm_min = getNum(&b, p, 2, 0, 59);
			if (!b) goto ERR;
			p += 2;
			if (*p++ != ':') goto ERR;

			tm.tm_sec = getNum(&b, p, 2, 0, 59);
			if (!b) goto ERR;
			p += 2;

			if (p == end) {
				msec_ = 0;
			} else if (p + 1 == end && *p == 'Z') {
				msec_ = 0;
				p++;
			} else if (*p == '.' && (p + 4 == end || (p + 5 == end && *(p + 4) == 'Z'))) {
				msec_ = getNum(&b, p + 1, 3, 0, 999);
				if (!b) goto ERR;
				p += 4;
			} else {
				goto ERR;
			}
#ifdef _WIN32
			time_ = _mkgmtime64(&tm);
			if (time_ == -1) goto ERR;
#else
			time_ = timegm(&tm);
#endif
			return;
		}
	ERR:
		throw cybozu::Exception("time::fromString") << std::string(begin, 24);
	}

	/**
		get current time with format
		@param out [out] output string
		@param format [in] foramt for strftime and append three digits for msec
		@param appendMsec [in] appemd <mmm>
		@param doClear (append to out if false)
		@note ex. "%Y-%b-%d %H:%M:%S." to get 2009-Jan-23 02:53:44.078
	*/
	void toString(std::string& out, const char *format, bool appendMsec = true, bool doClear = true) const
	{
		if (doClear) out.clear();
		char buf[128];
#ifdef _WIN32
		struct tm tm;
		if (_gmtime64_s(&tm, &time_) != 0) {
			throw cybozu::Exception("time::toString") << time_;
		}
		struct tm *ptm = &tm;
#else
		struct tm *ptm = gmtime(&time_);
#endif
		if (std::strftime(buf, sizeof(buf), format, ptm) == 0) {
			throw cybozu::Exception("time::toString::too long") << format << time_;
		}
		out += buf;
		if (appendMsec) {
			out += cybozu::itoaWithZero(msec_, 3);
		}
	}

	/**
		get current time such as 2009-01-23 02:53:44.078
		@param out [out] sink string
	*/
	void toString(std::string& out, bool appendMsec = true, bool doClear = true) const
	{
		const char *format = appendMsec ? "%Y-%m-%d %H:%M:%S." : "%Y-%m-%d %H:%M:%S";
		toString(out, format, appendMsec, doClear);
	}
	std::string toString() const { std::string out; toString(out); return out; }
	/**
		get current time
	*/
	Time& setCurrentTime()
	{
#ifdef _WIN32
		struct _timeb timeb;
		_ftime_s(&timeb);
		time_ = timeb.time;
		msec_ = timeb.millitm;
#else
		struct timeval tv;
		gettimeofday(&tv, 0);
		time_ = tv.tv_sec;
		msec_ = tv.tv_usec / 1000;
#endif
		return *this;
	}
private:

	int getNum(bool *b, const char *in, size_t len, int min, int max) const
	{
		int ret = cybozu::atoi(b, in, len);
		if (min <= ret && ret <= max) {
			return ret;
		} else {
			*b = false;
			return 0;
		}
	}

	/*
		convert month-str to [0, 11]
		@param ret [out] return idx
		@param p [in] month-str
		@retval next pointer or null
	*/
	const char *getMonth(int *ret, const char *p) const
	{
		static const char monthTbl[12][4] = {
			"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
		};

		for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(monthTbl); i++) {
			if (memcmp(p, monthTbl[i], 3) == 0) {
				*ret = (int)i;
				return p + 3;
			}
		}
		bool b;
		*ret = getNum(&b, p, 2, 1, 12) - 1;
		if (b) {
			return p + 2;
		} else {
			return 0;
		}
	}
};

inline std::ostream& operator<<(std::ostream& os, const cybozu::Time& time)
{
	return os << time.toString();
}

} // cybozu
<|endoftext|>


<commit_before>//
//
//    The Laxkit, a windowing toolkit
//    Please consult http://laxkit.sourceforge.net about where to send any
//    correspondence about this software.
//
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Library General Public
//    License as published by the Free Software Foundation; either
//    version 2 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Library General Public License for more details.
//
//    You should have received a copy of the GNU Library General Public
//    License along with this library; if not, write to the Free Software
//    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//    Copyright (C) 2004-2010 by Tom Lechner
//

#include <lax/doublebbox.h>
#include <lax/transformmath.h>

namespace Laxkit {

/*! \class DoubleBBox
 * \brief Class with double minx,maxx,miny,maxy.
 */
/*! \fn	int DoubleBBox::validbounds()
 * \brief Returns maxx>=minx && maxy>=miny.
 */
/*! \fn DoubleBBox::DoubleBBox()
 * \brief Create empty invalid bbox (maxx<minx and maxy<miny).
 */
/*! \fn DoubleBBox::DoubleBBox(flatpoint p)
 * \brief Create box whose bounds are p.
 */
/*! \fn DoubleBBox::DoubleBBox(double mix,double max,double miy,double may)
 * \brief Create box whose bounds are as given.
 */
/*! \fn void DoubleBBox::setbounds(double mix,double max,double miy,double may)
 * \brief Set the bounds to the specified values.
 */
/*! \fn void DoubleBBox::clear()
 * \brief Make box invalid: set minx=miny=0 and maxx=maxy=-1.
 */
/*! \fn double DoubleBBox::boxwidth()
 * Return maxx-minx if maxx>minx. Else return 0.
 */
/*! \fn double DoubleBBox::boxheight()
 * Return maxy-miny if maxy>miny. Else return 0.
 */

//! Just copy over the bounds.
void DoubleBBox::setbounds(DoubleBBox *bbox)
{
	minx=bbox->minx;
	maxx=bbox->maxx;
	miny=bbox->miny;
	maxy=bbox->maxy;
}

//! Make this bbox be the bounds for the given n points. (does not add to previous bounds)
void DoubleBBox::setbounds(flatpoint *pts,int n)
{
	minx=maxx=pts[0].x;
	miny=maxy=pts[0].y;
	for (int c=1; c<n; c++) addtobounds(pts[c]);
}

void DoubleBBox::addtobounds(flatpoint *pts,int n)
{
	for (int c=0; c<n; c++) addtobounds(pts[c]);
}

//! Add bbox to bounds, first transforming it by 6 element transform matrix m.
void DoubleBBox::addtobounds(const double *m, DoubleBBox *bbox)
{
	addtobounds(transform_point(m,flatpoint(bbox->minx,bbox->miny)));
	addtobounds(transform_point(m,flatpoint(bbox->maxx,bbox->miny)));
	addtobounds(transform_point(m,flatpoint(bbox->maxx,bbox->maxy)));
	addtobounds(transform_point(m,flatpoint(bbox->minx,bbox->maxy)));
}

//! Add the bbox to the bounds. Set the bounds if current bounds are invalid.
void DoubleBBox::addtobounds(DoubleBBox *bbox)
{
	if (!bbox) return;
	if (maxx<minx || maxy<miny) { setbounds(bbox); return; }
	addtobounds(flatpoint(bbox->minx,bbox->miny));
	addtobounds(flatpoint(bbox->maxx,bbox->miny));
	addtobounds(flatpoint(bbox->maxx,bbox->maxy));
	addtobounds(flatpoint(bbox->minx,bbox->maxy));
}

//! Expand bounds to contain p. Set the bounds to p if current bounds are invalid.
void DoubleBBox::addtobounds(flatpoint p)
{
	if (maxx<minx || maxy<miny) { minx=maxx=p.x; miny=maxy=p.y; return; }
	if (p.x<minx) minx=p.x;
	else if (p.x>maxx) maxx=p.x;
	if (p.y<miny) miny=p.y;
	else if (p.y>maxy) maxy=p.y;
}

void DoubleBBox::addtobounds(double x,double y)
{ addtobounds(flatpoint(x,y)); }

//! Return whether the transformed box touches. **** incomplete implementation
/*! If settointersection, then set the bounds of *this to the bounding box of the
 * intersection.
 *
 * If touching, then return true if any part touches this.
 * If !touching, then return true only if bbox is totally inside this.
 *
 * \todo *** this is not well implemented, settointersection not implemented.
 * \todo *** this needs some rethinking.. options are confusing, touching is ambiguous
 */
int DoubleBBox::intersect(const double *m,DoubleBBox *bbox, int touching, int settointersection)//s=0
{
	if (!m || !bbox) return 0;
	int n=0;
	flatpoint ul,ur,ll,lr;

	 //this here checks if any of the corners are inside the bounding box.
	ll=transform_point(m,flatpoint(bbox->minx,bbox->miny));
	if (ll.x>=minx && ll.x<=maxx && ll.y>=miny && ll.y<=maxy) n++;

	ul=transform_point(m,flatpoint(bbox->minx,bbox->maxy));
	if (ul.x>=minx && ul.x<=maxx && ul.y>=miny && ul.y<=maxy) n++;

	ur=transform_point(m,flatpoint(bbox->maxx,bbox->maxy));
	if (ur.x>=minx && ur.x<=maxx && ur.y>=miny && ur.y<=maxy) n++;

	lr=transform_point(m,flatpoint(bbox->maxx,bbox->miny));
	if (lr.x>=minx && lr.x<=maxx && lr.y>=miny && lr.y<=maxy) n++;

	if (!n && touching) {
		////flatpoint p1(minx,miny), p2(minx,maxy), p3(maxx,maxy), p4(maxx,miny);
		////if (segmentcross(p1,p2, ul,ur, p)) return 1;
		////if (segmentcross(p1,p2, ur,lr, p)) return 1;
		////if (segmentcross(p1,p2, lr,ll, p)) return 1;
		////if (segmentcross(p1,p2, ll,ul, p)) return 1;
		//
		////if (segmentcross(p2,p3, ul,ur, p)) return 1;
		////if (segmentcross(p2,p3, ur,lr, p)) return 1;
		////if (segmentcross(p2,p3, lr,ll, p)) return 1;
		////if (segmentcross(p2,p3, ll,ul, p)) return 1;
		//
		////if (segmentcross(p3,p4, ul,ur, p)) return 1;
		////if (segmentcross(p3,p4, ur,lr, p)) return 1;
		////if (segmentcross(p3,p4, lr,ll, p)) return 1;
		////if (segmentcross(p3,p4, ll,ul, p)) return 1;
		//
		////if (segmentcross(p4,p1, ul,ur, p)) return 1;
		////if (segmentcross(p4,p1, ur,lr, p)) return 1;
		////if (segmentcross(p4,p1, lr,ll, p)) return 1;
		////if (segmentcross(p4,p1, ll,ul, p)) return 1;
		//
		//------------------
		//flatpoint pts[4];
		//pts[0].x=minx; pts[0].y=miny;
		//pts[1].x=maxx; pts[1].y=miny;
		//pts[2].x=maxx; pts[2].y=maxy;
		//pts[3].x=minx; pts[3].y=maxy;
		//if (intersections(ll,lr, pts,4,true)) return 1;
		//if (intersections(lr,ur, pts,4,true)) return 1;
		//if (intersections(ur,ul, pts,4,true)) return 1;
		//if (intersections(ul,ll, pts,4,true)) return 1;
		return 0;
	}
	if (touching) return n; //true if any corners in bounds
	return n==4; //true when all 4 corners are in bounds
}

//! Just return intersect(bbox.minx,...,settointersection).
int DoubleBBox::intersect(DoubleBBox *bbox, int settointersection)//s=0
{
	return intersect(bbox->minx,bbox->maxx,bbox->miny,bbox->maxy,settointersection);
}

//! Intersect the given bounds with this's bounds. Return 1 for non-empty intersection
/*! If settointersection!=0, then set current bounds to the intersection or invalid bounds
 * if there is no intersection.
 *
 * \todo should me more specific about the kind of intersection: all inside, all outside, or just touching.
 */
int DoubleBBox::intersect(double mix,double max,double miy,double may, int settointersection)//s=0
{
	if (minx>mix) mix=minx;
	if (maxx<max) max=maxx;
	if (miny>miy) miy=miny;
	if (maxy<may) may=maxy;
	if (settointersection) {
		minx=mix;
		maxx=max;
		miny=miy;
		maxy=may;
	}
	return max>=mix && may>=miy;
}

//! Return whether the given point is contained within or on the bounds.
/*! Invalid bounds will always return 0.
 */
int DoubleBBox::boxcontains(double x, double y)
{
	if (maxx>=minx && maxy>=miny && x>=minx && x<=maxx && y>=miny && y<=maxy) return 1;
	return 0;
}

/*! Return the absolute point given bbox points.
 * That is, point (0,0) is returned as (minx,miny)
 * and (1,1) is returned as (maxx, maxy).
 */
flatpoint DoubleBBox::BBoxPoint(double x,double y)
{ return flatpoint(minx+x*(maxx-minx),miny+y*(maxy-miny)); }

} // namespace Laxkit
<commit_msg>Adding check for invalid bbox it addtobounds(DoubleBBox*)<commit_after>//
//
//    The Laxkit, a windowing toolkit
//    Please consult http://laxkit.sourceforge.net about where to send any
//    correspondence about this software.
//
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Library General Public
//    License as published by the Free Software Foundation; either
//    version 2 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Library General Public License for more details.
//
//    You should have received a copy of the GNU Library General Public
//    License along with this library; if not, write to the Free Software
//    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//    Copyright (C) 2004-2010 by Tom Lechner
//

#include <lax/doublebbox.h>
#include <lax/transformmath.h>

namespace Laxkit {

/*! \class DoubleBBox
 * \brief Class with double minx,maxx,miny,maxy.
 */
/*! \fn	int DoubleBBox::validbounds()
 * \brief Returns maxx>=minx && maxy>=miny.
 */
/*! \fn DoubleBBox::DoubleBBox()
 * \brief Create empty invalid bbox (maxx<minx and maxy<miny).
 */
/*! \fn DoubleBBox::DoubleBBox(flatpoint p)
 * \brief Create box whose bounds are p.
 */
/*! \fn DoubleBBox::DoubleBBox(double mix,double max,double miy,double may)
 * \brief Create box whose bounds are as given.
 */
/*! \fn void DoubleBBox::setbounds(double mix,double max,double miy,double may)
 * \brief Set the bounds to the specified values.
 */
/*! \fn void DoubleBBox::clear()
 * \brief Make box invalid: set minx=miny=0 and maxx=maxy=-1.
 */
/*! \fn double DoubleBBox::boxwidth()
 * Return maxx-minx if maxx>minx. Else return 0.
 */
/*! \fn double DoubleBBox::boxheight()
 * Return maxy-miny if maxy>miny. Else return 0.
 */

//! Just copy over the bounds.
void DoubleBBox::setbounds(DoubleBBox *bbox)
{
	minx=bbox->minx;
	maxx=bbox->maxx;
	miny=bbox->miny;
	maxy=bbox->maxy;
}

//! Make this bbox be the bounds for the given n points. (does not add to previous bounds)
void DoubleBBox::setbounds(flatpoint *pts,int n)
{
	minx=maxx=pts[0].x;
	miny=maxy=pts[0].y;
	for (int c=1; c<n; c++) addtobounds(pts[c]);
}

void DoubleBBox::addtobounds(flatpoint *pts,int n)
{
	for (int c=0; c<n; c++) addtobounds(pts[c]);
}

//! Add bbox to bounds, first transforming it by 6 element transform matrix m.
void DoubleBBox::addtobounds(const double *m, DoubleBBox *bbox)
{
	addtobounds(transform_point(m,flatpoint(bbox->minx,bbox->miny)));
	addtobounds(transform_point(m,flatpoint(bbox->maxx,bbox->miny)));
	addtobounds(transform_point(m,flatpoint(bbox->maxx,bbox->maxy)));
	addtobounds(transform_point(m,flatpoint(bbox->minx,bbox->maxy)));
}

//! Add the bbox to the bounds. Set the bounds if current bounds are invalid.
/*! Note if bbox is invalid, nothing is changed about current bbox.
 */
void DoubleBBox::addtobounds(DoubleBBox *bbox)
{
	if (!bbox) return;
	if (bbox->maxx<bbox->minx || bbox->maxy<bbox->miny) return;
	if (maxx<minx || maxy<miny) { setbounds(bbox); return; }
	addtobounds(flatpoint(bbox->minx,bbox->miny));
	addtobounds(flatpoint(bbox->maxx,bbox->miny));
	addtobounds(flatpoint(bbox->maxx,bbox->maxy));
	addtobounds(flatpoint(bbox->minx,bbox->maxy));
}

//! Expand bounds to contain p. Set the bounds to p if current bounds are invalid.
void DoubleBBox::addtobounds(flatpoint p)
{
	if (maxx<minx || maxy<miny) { minx=maxx=p.x; miny=maxy=p.y; return; }
	if (p.x<minx) minx=p.x;
	else if (p.x>maxx) maxx=p.x;
	if (p.y<miny) miny=p.y;
	else if (p.y>maxy) maxy=p.y;
}

void DoubleBBox::addtobounds(double x,double y)
{ addtobounds(flatpoint(x,y)); }

//! Return whether the transformed box touches. **** incomplete implementation
/*! If settointersection, then set the bounds of *this to the bounding box of the
 * intersection.
 *
 * If touching, then return true if any part touches this.
 * If !touching, then return true only if bbox is totally inside this.
 *
 * \todo *** this is not well implemented, settointersection not implemented.
 * \todo *** this needs some rethinking.. options are confusing, touching is ambiguous
 */
int DoubleBBox::intersect(const double *m,DoubleBBox *bbox, int touching, int settointersection)//s=0
{
	if (!m || !bbox) return 0;
	int n=0;
	flatpoint ul,ur,ll,lr;

	 //this here checks if any of the corners are inside the bounding box.
	ll=transform_point(m,flatpoint(bbox->minx,bbox->miny));
	if (ll.x>=minx && ll.x<=maxx && ll.y>=miny && ll.y<=maxy) n++;

	ul=transform_point(m,flatpoint(bbox->minx,bbox->maxy));
	if (ul.x>=minx && ul.x<=maxx && ul.y>=miny && ul.y<=maxy) n++;

	ur=transform_point(m,flatpoint(bbox->maxx,bbox->maxy));
	if (ur.x>=minx && ur.x<=maxx && ur.y>=miny && ur.y<=maxy) n++;

	lr=transform_point(m,flatpoint(bbox->maxx,bbox->miny));
	if (lr.x>=minx && lr.x<=maxx && lr.y>=miny && lr.y<=maxy) n++;

	if (!n && touching) {
		////flatpoint p1(minx,miny), p2(minx,maxy), p3(maxx,maxy), p4(maxx,miny);
		////if (segmentcross(p1,p2, ul,ur, p)) return 1;
		////if (segmentcross(p1,p2, ur,lr, p)) return 1;
		////if (segmentcross(p1,p2, lr,ll, p)) return 1;
		////if (segmentcross(p1,p2, ll,ul, p)) return 1;
		//
		////if (segmentcross(p2,p3, ul,ur, p)) return 1;
		////if (segmentcross(p2,p3, ur,lr, p)) return 1;
		////if (segmentcross(p2,p3, lr,ll, p)) return 1;
		////if (segmentcross(p2,p3, ll,ul, p)) return 1;
		//
		////if (segmentcross(p3,p4, ul,ur, p)) return 1;
		////if (segmentcross(p3,p4, ur,lr, p)) return 1;
		////if (segmentcross(p3,p4, lr,ll, p)) return 1;
		////if (segmentcross(p3,p4, ll,ul, p)) return 1;
		//
		////if (segmentcross(p4,p1, ul,ur, p)) return 1;
		////if (segmentcross(p4,p1, ur,lr, p)) return 1;
		////if (segmentcross(p4,p1, lr,ll, p)) return 1;
		////if (segmentcross(p4,p1, ll,ul, p)) return 1;
		//
		//------------------
		//flatpoint pts[4];
		//pts[0].x=minx; pts[0].y=miny;
		//pts[1].x=maxx; pts[1].y=miny;
		//pts[2].x=maxx; pts[2].y=maxy;
		//pts[3].x=minx; pts[3].y=maxy;
		//if (intersections(ll,lr, pts,4,true)) return 1;
		//if (intersections(lr,ur, pts,4,true)) return 1;
		//if (intersections(ur,ul, pts,4,true)) return 1;
		//if (intersections(ul,ll, pts,4,true)) return 1;
		return 0;
	}
	if (touching) return n; //true if any corners in bounds
	return n==4; //true when all 4 corners are in bounds
}

//! Just return intersect(bbox.minx,...,settointersection).
int DoubleBBox::intersect(DoubleBBox *bbox, int settointersection)//s=0
{
	return intersect(bbox->minx,bbox->maxx,bbox->miny,bbox->maxy,settointersection);
}

//! Intersect the given bounds with this's bounds. Return 1 for non-empty intersection
/*! If settointersection!=0, then set current bounds to the intersection or invalid bounds
 * if there is no intersection.
 *
 * \todo should me more specific about the kind of intersection: all inside, all outside, or just touching.
 */
int DoubleBBox::intersect(double mix,double max,double miy,double may, int settointersection)//s=0
{
	if (minx>mix) mix=minx;
	if (maxx<max) max=maxx;
	if (miny>miy) miy=miny;
	if (maxy<may) may=maxy;
	if (settointersection) {
		minx=mix;
		maxx=max;
		miny=miy;
		maxy=may;
	}
	return max>=mix && may>=miy;
}

//! Return whether the given point is contained within or on the bounds.
/*! Invalid bounds will always return 0.
 */
int DoubleBBox::boxcontains(double x, double y)
{
	if (maxx>=minx && maxy>=miny && x>=minx && x<=maxx && y>=miny && y<=maxy) return 1;
	return 0;
}

/*! Return the absolute point given bbox points.
 * That is, point (0,0) is returned as (minx,miny)
 * and (1,1) is returned as (maxx, maxy).
 */
flatpoint DoubleBBox::BBoxPoint(double x,double y)
{ return flatpoint(minx+x*(maxx-minx),miny+y*(maxy-miny)); }

} // namespace Laxkit
<|endoftext|>


<commit_before>/*
 * expressions.hpp
 * Author: Radu Cotescu (rdc1g10)
 *
 * Part 2: Expression Templates
 * Write C++ templates which allow you to use types to represent arithmetic
 * expressions over the four basic operations (addition, subtraction,
 * multiplication and division), a single variable, and integer exponentiation:
 * (e.g. x^2+(x-2)^3/5). For the purposes of this assignment we refer to the
 * single variable as x.
 *
 * The types representing the expressions should contain a function named "eval"
 * that provides code for evaluating the expression. This function should accept
 * a double parameter that will be used as the value for the single variable x.
 */

#ifndef EXPRESSIONS_HPP_
#define EXPRESSIONS_HPP_

#endif /* EXPRESSIONS_HPP_ */
<commit_msg>temporary edit<commit_after>/*
 * expressions.hpp
 * Author: Radu Cotescu (rdc1g10)
 *
 * Part 2: Expression Templates
 * Write C++ templates which allow you to use types to represent arithmetic
 * expressions over the four basic operations (addition, subtraction,
 * multiplication and division), a single variable, and integer exponentiation:
 * (e.g. x^2+(x-2)^3/5). For the purposes of this assignment we refer to the
 * single variable as x.
 *
 * The types representing the expressions should contain a function named "eval"
 * that provides code for evaluating the expression. This function should accept
 * a double parameter that will be used as the value for the single variable x.
 */
#ifndef EXPRESSIONS_HPP_
#define EXPRESSIONS_HPP_
using namespace std;

/*
 * Class defining Literals.
 */
class Literal {
public:
	Literal(const double v) : value(v) {}
	double eval() const {
		return value;
	}
private:
	const double value;
};

/*
 * Class defining variables.
 */
class Variable {
	Variable(const double v) : value(v) {}
	double eval() const {
		return value;
	}
	;
private:
	double& value;
};

/*
 * Template defining a binary expression.
 */
template <class LHS, class RHS, class BinaryOperation> class BinaryExpression {
public:
	BinaryExpression(
			LHS _lhs,
			RHS _rhs,
			BinaryOperation _operation = BinaryOperation()
	) : lhs(_lhs), rhs(_rhs), operation(_operation) {}
	double eval() const {
		return operation(lhs.eval(), rhs.eval());
	}
private:
	LHS lhs;
	RHS rhs;
	BinaryOperation operation;
};

/*
 * Operator overriding.
 */
template <class LHS, class RHS> BinaryExpression<LHS, RHS, plus<double> > operator+(LHS lhs, RHS, rhs) {
	return BinaryExpression<LHS, RHS, plus<double> >(lhs, rhs);
}
#endif /* EXPRESSIONS_HPP_ */
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/yosys.h"
#include "kernel/sigtools.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct ZinitPass : public Pass {
	ZinitPass() : Pass("zinit", "add inverters so all FF are zero-initialized") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    zinit [options] [selection]\n");
		log("\n");
		log("Add inverters as needed to make all FFs zero-initialized.\n");
		log("\n");
		log("    -all\n");
		log("        also add zero initialization to uninitialized FFs\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		bool all_mode = false;

		log_header(design, "Executing ZINIT pass (make all FFs zero-initialized).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-all") {
				all_mode = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
		{
			SigMap sigmap(module);
			dict<SigBit, std::pair<State,SigBit>> initbits;

			for (auto wire : module->selected_wires())
			{
				if (wire->attributes.count(ID::init) == 0)
					continue;

				SigSpec wirebits = sigmap(wire);
				Const initval = wire->attributes.at(ID::init);

				for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
				{
					SigBit bit = wirebits[i];
					State val = initval[i];

					if (val != State::S0 && val != State::S1 && bit.wire != nullptr)
						continue;

					if (initbits.count(bit)) {
						if (initbits.at(bit).first != val)
							log_error("Conflicting init values for signal %s (%s = %s != %s).\n",
									log_signal(bit), log_signal(SigBit(wire, i)),
									log_signal(val), log_signal(initbits.at(bit).first));
						continue;
					}

					initbits[bit] = std::make_pair(val,SigBit(wire,i));
				}
			}

			pool<IdString> dff_types = {
								// FIXME: It would appear that supporting
								//    $dffsr/$_DFFSR_* would require a new
								//    cell type where S has priority over R
				ID($ff), ID($dff), ID($dffe), /*ID($dffsr),*/ ID($adff),
				ID($_FF_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
				/*ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
				ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),*/
				ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
				ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)
			};

			for (auto cell : module->selected_cells())
			{
				if (!dff_types.count(cell->type))
					continue;

				SigSpec sig_d = sigmap(cell->getPort(ID::D));
				SigSpec sig_q = sigmap(cell->getPort(ID::Q));

				if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
					continue;

				Const initval;

				for (int i = 0; i < GetSize(sig_q); i++) {
					if (initbits.count(sig_q[i])) {
						const auto &d = initbits.at(sig_q[i]);
						initval.bits.push_back(d.first);
						const auto &b = d.second;
						b.wire->attributes.at(ID::init)[b.offset] = State::Sx;
					} else
						initval.bits.push_back(all_mode ? State::S0 : State::Sx);
				}

				Wire *initwire = module->addWire(NEW_ID, GetSize(initval));
				initwire->attributes[ID::init] = initval;

				for (int i = 0; i < GetSize(initwire); i++)
					if (initval[i] == State::S1)
					{
						sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
						module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]);
						initwire->attributes[ID::init][i] = State::S0;
					}
					else
					{
						module->connect(sig_q[i], SigSpec(initwire, i));
					}

				log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type),
						log_signal(sig_q), log_signal(initval));

				cell->setPort(ID::D, sig_d);
				cell->setPort(ID::Q, initwire);

				if (cell->type == ID($adff)) {
					auto val = cell->getParam(ID::ARST_VALUE);
					for (int i = 0; i < GetSize(initwire); i++)
						if (initval[i] == State::S1)
							val[i] = (val[i] == State::S1 ? State::S0 : State::S1);
					cell->setParam(ID::ARST_VALUE, std::move(val));
				}
				else if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
							ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
				{
					if (initval == State::S1) {
						std::string t = cell->type.str();
						t[8] = (t[8] == '0' ? '1' : '0');
						cell->type = t;
					}
				}
			}
		}
	}
} ZinitPass;

PRIVATE_NAMESPACE_END
<commit_msg>zinit: handle $__DFFS?E?_[NP][NP][01] too<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/yosys.h"
#include "kernel/sigtools.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct ZinitPass : public Pass {
	ZinitPass() : Pass("zinit", "add inverters so all FF are zero-initialized") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    zinit [options] [selection]\n");
		log("\n");
		log("Add inverters as needed to make all FFs zero-initialized.\n");
		log("\n");
		log("    -all\n");
		log("        also add zero initialization to uninitialized FFs\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		bool all_mode = false;

		log_header(design, "Executing ZINIT pass (make all FFs zero-initialized).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-all") {
				all_mode = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
		{
			SigMap sigmap(module);
			dict<SigBit, std::pair<State,SigBit>> initbits;

			for (auto wire : module->selected_wires())
			{
				if (wire->attributes.count(ID::init) == 0)
					continue;

				SigSpec wirebits = sigmap(wire);
				Const initval = wire->attributes.at(ID::init);

				for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
				{
					SigBit bit = wirebits[i];
					State val = initval[i];

					if (val != State::S0 && val != State::S1 && bit.wire != nullptr)
						continue;

					if (initbits.count(bit)) {
						if (initbits.at(bit).first != val)
							log_error("Conflicting init values for signal %s (%s = %s != %s).\n",
									log_signal(bit), log_signal(SigBit(wire, i)),
									log_signal(val), log_signal(initbits.at(bit).first));
						continue;
					}

					initbits[bit] = std::make_pair(val,SigBit(wire,i));
				}
			}

			pool<IdString> dff_types = {
								// FIXME: It would appear that supporting
								//    $dffsr/$_DFFSR_* would require a new
								//    cell type where S has priority over R
				ID($ff), ID($dff), ID($dffe), /*ID($dffsr),*/ ID($adff),
				ID($_FF_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
				/*ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
				ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),*/
				ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
				ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
				// Async set/reset
				ID($__DFFE_NN0), ID($__DFFE_NN1), ID($__DFFE_NP0), ID($__DFFE_NP1),
				ID($__DFFE_PN0), ID($__DFFE_PN1), ID($__DFFE_PP0), ID($__DFFE_PP1),
				// Sync set/reset
				ID($__DFFS_NN0_), ID($__DFFS_NN1_), ID($__DFFS_NP0_), ID($__DFFS_NP1_),
				ID($__DFFS_PN0_), ID($__DFFS_PN1_), ID($__DFFS_PP0_), ID($__DFFS_PP1_),
				ID($__DFFSE_NN0), ID($__DFFSE_NN1), ID($__DFFSE_NP0), ID($__DFFSE_NP1),
				ID($__DFFSE_PN0), ID($__DFFSE_PN1), ID($__DFFSE_PP0), ID($__DFFSE_PP1)
			};

			for (auto cell : module->selected_cells())
			{
				if (!dff_types.count(cell->type))
					continue;

				SigSpec sig_d = sigmap(cell->getPort(ID::D));
				SigSpec sig_q = sigmap(cell->getPort(ID::Q));

				if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
					continue;

				Const initval;

				for (int i = 0; i < GetSize(sig_q); i++) {
					if (initbits.count(sig_q[i])) {
						const auto &d = initbits.at(sig_q[i]);
						initval.bits.push_back(d.first);
						const auto &b = d.second;
						b.wire->attributes.at(ID::init)[b.offset] = State::Sx;
					} else
						initval.bits.push_back(all_mode ? State::S0 : State::Sx);
				}

				Wire *initwire = module->addWire(NEW_ID, GetSize(initval));
				initwire->attributes[ID::init] = initval;

				for (int i = 0; i < GetSize(initwire); i++)
					if (initval[i] == State::S1)
					{
						sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
						module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]);
						initwire->attributes[ID::init][i] = State::S0;
					}
					else
					{
						module->connect(sig_q[i], SigSpec(initwire, i));
					}

				log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type),
						log_signal(sig_q), log_signal(initval));

				cell->setPort(ID::D, sig_d);
				cell->setPort(ID::Q, initwire);

				if (cell->type == ID($adff)) {
					auto val = cell->getParam(ID::ARST_VALUE);
					for (int i = 0; i < GetSize(initwire); i++)
						if (initval[i] == State::S1)
							val[i] = (val[i] == State::S1 ? State::S0 : State::S1);
					cell->setParam(ID::ARST_VALUE, std::move(val));
				}
				else if (initval == State::S1) {
					std::string t = cell->type.str();
					if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
								ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
					{
						t[8] = (t[8] == '0' ? '1' : '0');
					}
					else if (cell->type.in(ID($__DFFE_NN0), ID($__DFFE_NN1), ID($__DFFE_NP0), ID($__DFFE_NP1),
								ID($__DFFE_PN0), ID($__DFFE_PN1), ID($__DFFE_PP0), ID($__DFFE_PP1),
								ID($__DFFS_NN0_), ID($__DFFS_NN1_), ID($__DFFS_NP0_), ID($__DFFS_NP1_),
								ID($__DFFS_PN0_), ID($__DFFS_PN1_), ID($__DFFS_PP0_), ID($__DFFS_PP1_)))
					{
						t[10] = (t[10] == '0' ? '1' : '0');
					}
					else if (cell->type.in(ID($__DFFSE_NN0), ID($__DFFSE_NN1), ID($__DFFSE_NP0), ID($__DFFSE_NP1),
								ID($__DFFSE_PN0), ID($__DFFSE_PN1), ID($__DFFSE_PP0), ID($__DFFSE_PP1)))
					{
						t[11] = (t[11] == '0' ? '1' : '0');
					}
					cell->type = t;
				}
			}
		}
	}
} ZinitPass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>/**
 * @file Vector.hpp
 *
 * Vector class.
 *
 * @author James Goppert <james.goppert@gmail.com>
 */

#pragma once

#include "math.hpp"

namespace matrix
{

template <typename Type, size_t M, size_t N>
class Matrix;

template<typename Type, size_t M>
class Vector : public Matrix<Type, M, 1>
{
public:
    typedef Matrix<Type, M, 1> MatrixM1;

    Vector() : MatrixM1()
    {
    }

    Vector(const MatrixM1 & other) :
        MatrixM1(other)
    {
    }

    Vector(const Type *data_) :
        MatrixM1(data_)
    {
    }

    inline Type operator()(size_t i) const
    {
        const MatrixM1 &v = *this;
        return v(i, 0);
    }

    inline Type &operator()(size_t i)
    {
        MatrixM1 &v = *this;
        return v(i, 0);
    }

    Type dot(const MatrixM1 & b) const {
        const Vector &a(*this);
        Type r = 0;
        for (size_t i = 0; i<M; i++) {
            r += a(i)*b(i,0);
        }
        return r;
    }

    inline Type operator*(const MatrixM1 & b) const {
        const Vector &a(*this);
        return a.dot(b);
    }

    inline Vector operator*(float b) const {
        return Vector(MatrixM1::operator*(b));
    }

    Type norm() const {
        const Vector &a(*this);
        return Type(sqrt(a.dot(a)));
    }

    inline Type length() const {
        return norm();
    }

    inline void normalize() {
        (*this) /= norm();
    }

    Vector unit() const {
        return (*this) / norm();
    }

    Vector unit_or_zero(const Type eps = 1e-5f) {
        const Type n = norm();
        if (n > eps) {
            return (*this) / n;
        }
        return Vector();
    }

    inline Vector normalized() const {
        return unit();
    }

    Vector pow(Type v) const {
        const Vector &a(*this);
        Vector r;
        for (size_t i = 0; i<M; i++) {
            r(i) = Type(::pow(a(i), v));
        }
        return r;
    }
};

} // namespace matrix

/* vim: set et fenc=utf-8 ff=unix sts=0 sw=4 ts=4 : */
<commit_msg>Vector: added norm_squared() because sometimes you can safe the sqrt operation<commit_after>/**
 * @file Vector.hpp
 *
 * Vector class.
 *
 * @author James Goppert <james.goppert@gmail.com>
 */

#pragma once

#include "math.hpp"

namespace matrix
{

template <typename Type, size_t M, size_t N>
class Matrix;

template<typename Type, size_t M>
class Vector : public Matrix<Type, M, 1>
{
public:
    typedef Matrix<Type, M, 1> MatrixM1;

    Vector() : MatrixM1()
    {
    }

    Vector(const MatrixM1 & other) :
        MatrixM1(other)
    {
    }

    Vector(const Type *data_) :
        MatrixM1(data_)
    {
    }

    inline Type operator()(size_t i) const
    {
        const MatrixM1 &v = *this;
        return v(i, 0);
    }

    inline Type &operator()(size_t i)
    {
        MatrixM1 &v = *this;
        return v(i, 0);
    }

    Type dot(const MatrixM1 & b) const {
        const Vector &a(*this);
        Type r = 0;
        for (size_t i = 0; i<M; i++) {
            r += a(i)*b(i,0);
        }
        return r;
    }

    inline Type operator*(const MatrixM1 & b) const {
        const Vector &a(*this);
        return a.dot(b);
    }

    inline Vector operator*(float b) const {
        return Vector(MatrixM1::operator*(b));
    }

    Type norm() const {
        const Vector &a(*this);
        return Type(sqrt(a.dot(a)));
    }

    Type norm_squared() const {
        const Vector &a(*this);
        return Type(a.dot(a));
    }

    inline Type length() const {
        return norm();
    }

    inline void normalize() {
        (*this) /= norm();
    }

    Vector unit() const {
        return (*this) / norm();
    }

    Vector unit_or_zero(const Type eps = 1e-5f) {
        const Type n = norm();
        if (n > eps) {
            return (*this) / n;
        }
        return Vector();
    }

    inline Vector normalized() const {
        return unit();
    }

    Vector pow(Type v) const {
        const Vector &a(*this);
        Vector r;
        for (size_t i = 0; i<M; i++) {
            r(i) = Type(::pow(a(i), v));
        }
        return r;
    }
};

} // namespace matrix

/* vim: set et fenc=utf-8 ff=unix sts=0 sw=4 ts=4 : */
<|endoftext|>


<commit_before>#ifndef OCCA_DEFINES_HEADER
#define OCCA_DEFINES_HEADER

#ifndef LINUX_OS
#  define LINUX_OS 1
#endif

#ifndef OSX_OS
#  define OSX_OS 2
#endif

#ifndef WINDOWS_OS
#  define WINDOWS_OS 4
#endif

#ifndef OCCA_OS
#  if defined(WIN32) || defined(WIN64)
#    define OCCA_OS WINDOWS_OS
#  elif __APPLE__
#    define OCCA_OS OSX_OS
#  else
#    define OCCA_OS LINUX_OS
#  endif
#endif

#ifndef __PRETTY_FUNCTION__
#  define __PRETTY_FUNCTION__ __FUNCTION__
#endif

#if defined(__x86_64__) || defined(_M_X64) // 64 Bit
#  define OCCA_64_BIT 1
#  define OCCA_32_BIT 0
#elif defined(__i386) || defined(_M_IX86) // 32 Bit
#  define OCCA_64_BIT 0
#  define OCCA_32_BIT 1
#elif defined(__ia64) || defined(__itanium__) || defined(_A_IA64) // Itanium
#  define OCCA_64_BIT 1
#  define OCCA_32_BIT 0
#endif

//---[ Checks and Info ]----------------
#ifndef OCCA_COMPILED_FOR_JULIA
#  define OCCA_THROW throw 1
#else
#  define OCCA_THROW jl_error("Exiting OCCA\n")
#endif

#define OCCA_EMPTY_FORCE_CHECK2( _expr , file , line , func )           \
  do {                                                                  \
    intptr_t expr = (_expr);                                            \
    if( !expr ){                                                        \
      std::cout << '\n'                                                 \
                << "---[ Error ]--------------------------------------------\n" \
                << "    File     : " << file << '\n'                    \
                << "    Function : " << func << '\n'                    \
                << "    Line     : " << line << '\n'                    \
                << "========================================================\n"; \
      OCCA_THROW;                                                       \
    }                                                                   \
  } while(0)

#define OCCA_FORCE_CHECK2( _expr , _msg , file , line , func )          \
  do {                                                                  \
    intptr_t expr = (_expr);                                            \
    if( !expr ){                                                        \
      std::cout << '\n'                                                 \
                << "---[ Error ]--------------------------------------------\n" \
                << "    File     : " << file << '\n'                    \
                << "    Function : " << func << '\n'                    \
                << "    Line     : " << line << '\n'                    \
                << "    Error    : " << _msg << '\n'                    \
                << "========================================================\n"; \
      OCCA_THROW;                                                       \
    }                                                                   \
  } while(0)

#define OCCA_EMPTY_FORCE_CHECK( _expr )  OCCA_EMPTY_FORCE_CHECK2( _expr , __FILE__ , __LINE__ , __PRETTY_FUNCTION__)
#define OCCA_FORCE_CHECK( _expr , _msg ) OCCA_FORCE_CHECK2( _expr , _msg , __FILE__ , __LINE__ , __PRETTY_FUNCTION__)

#if OCCA_CHECK_ENABLED
#  define OCCA_EMPTY_CHECK( _expr )  OCCA_EMPTY_FORCE_CHECK( _expr )
#  define OCCA_CHECK( _expr , _msg ) OCCA_FORCE_CHECK( _expr , _msg )
#else
#  define OCCA_EMPTY_CHECK( _expr )
#  define OCCA_CHECK( _expr , _msg )
#endif

#if OCCA_OS == OSX_OS
#  define OCCA_MEM_ALIGN 16
#else
#  define OCCA_MEM_ALIGN 64
#endif

#define OCCA_SIMD_WIDTH 8

#define OCCA_MAX_ARGS 50
//======================================

//---[ Base ]---------------------------
#define OCCA_KERNEL_ARG_CONSTRUCTOR(TYPE)         \
  template <>                                     \
  inline kernelArg::kernelArg(const TYPE &arg_){  \
    arg.TYPE##_ = arg_;                           \
    size      = sizeof(TYPE);                     \
                                                  \
    pointer    = false;                           \
    hasTwoArgs = false;                           \
  }

#define OCCA_KERNEL_ARG_CONSTRUCTOR_ALIAS(TYPE, ALIAS)  \
  template <>                                           \
  inline kernelArg::kernelArg(const TYPE &arg_){        \
    arg.ALIAS##_ = arg_;                                \
    size         = sizeof(TYPE);                        \
                                                        \
    pointer    = false;                                 \
    hasTwoArgs = false;                                 \
  }

#define OCCA_EXTRACT_DATA(MODE, CLASS)                          \
  MODE##CLASS##Data_t &data_ = *((MODE##CLASS##Data_t*) data);
//======================================

//---[ Pthreads ]-----------------------
//======================================

//---[ OpenMP ]-------------------------
//======================================

//---[ OpenCL ]-------------------------
#if OCCA_CHECK_ENABLED
;
#  define OCCA_CL_CHECK( _str , _statement ) OCCA_CL_CHECK2( _str , _statement , __FILE__ , __LINE__ )
#  define OCCA_CL_CHECK2( _str , _statement , file , line )             \
  do {                                                                  \
    cl_int _error = _statement;                                         \
    if(_error){                                                         \
      _error = _error < 0  ? _error : -_error;                          \
      _error = _error < 65 ? _error : 15;                               \
                                                                        \
      std::cout << "Error\n"                                            \
                << "    File    : " << file << '\n'                     \
                << "    Line    : " << line << '\n'                     \
                << "    Error   : OpenCL Error [ " << _error << " ]: " << occa::openclError(_error) << '\n' \
                << "    Message : " << _str << '\n';                    \
      OCCA_THROW;                                                       \
    }                                                                   \
  } while(0)

#else
#  define OCCA_CL_CHECK( _str , _statement ) do { _statement; } while(0)
#endif
//======================================

//---[ CUDA ]---------------------------
#if OCCA_CHECK_ENABLED
#  define OCCA_CUDA_CHECK( _str , _statement ) OCCA_CUDA_CHECK2( _str , _statement , __FILE__ , __LINE__ )
#  define OCCA_CUDA_CHECK2( _str , _statement , file , line )           \
  do {                                                                  \
    CUresult errorCode = _statement;                                    \
    if(errorCode){                                                      \
      std::cout << "Error\n"                                            \
                << "    File    : " << file << '\n'                     \
                << "    Line    : " << line << '\n'                     \
                << "    Error   : CUDA Error [ " << errorCode << " ]: " << occa::cudaError(errorCode) << '\n' \
                << "    Message : " << _str << '\n';                    \
      OCCA_THROW;                                                       \
    }                                                                   \
  } while(0)
#else
#  define OCCA_CUDA_CHECK( _str , _statement ) do { _statement; } while(0)
#endif
//======================================

//---[ COI ]----------------------------
#if OCCA_CHECK_ENABLED
#  define OCCA_COI_CHECK( _str , _statement ) OCCA_COI_CHECK2( _str , _statement , __FILE__ , __LINE__ )
#  define OCCA_COI_CHECK2( _str , _statement , file , line )            \
  do {                                                                  \
    COIRESULT errorCode = _statement;                                   \
    if(errorCode != COI_SUCCESS){                                       \
      std::cout << "Error\n"                                            \
                << "    File    : " << file << '\n'                     \
                << "    Line    : " << line << '\n'                     \
                << "    Error   : " << occa::coiError(errorCode) << '\n' \
                << "    Message : " << _str << '\n';                    \
      throw 1;                                                          \
    }                                                                   \
  } while(0);
#else
#  define OCCA_COI_CHECK( _str , _statement ) do { _statement; } while(0);
#endif
//======================================
#endif
<commit_msg>[Core] throw -> abort<commit_after>#ifndef OCCA_DEFINES_HEADER
#define OCCA_DEFINES_HEADER

#ifndef LINUX_OS
#  define LINUX_OS 1
#endif

#ifndef OSX_OS
#  define OSX_OS 2
#endif

#ifndef WINDOWS_OS
#  define WINDOWS_OS 4
#endif

#ifndef OCCA_OS
#  if defined(WIN32) || defined(WIN64)
#    define OCCA_OS WINDOWS_OS
#  elif __APPLE__
#    define OCCA_OS OSX_OS
#  else
#    define OCCA_OS LINUX_OS
#  endif
#endif

#ifndef __PRETTY_FUNCTION__
#  define __PRETTY_FUNCTION__ __FUNCTION__
#endif

#if defined(__x86_64__) || defined(_M_X64) // 64 Bit
#  define OCCA_64_BIT 1
#  define OCCA_32_BIT 0
#elif defined(__i386) || defined(_M_IX86) // 32 Bit
#  define OCCA_64_BIT 0
#  define OCCA_32_BIT 1
#elif defined(__ia64) || defined(__itanium__) || defined(_A_IA64) // Itanium
#  define OCCA_64_BIT 1
#  define OCCA_32_BIT 0
#endif

//---[ Checks and Info ]----------------
#ifndef OCCA_COMPILED_FOR_JULIA
#  define OCCA_THROW abort()
#else
#  define OCCA_THROW jl_error("Exiting OCCA\n")
#endif

#define OCCA_EMPTY_FORCE_CHECK2( _expr , file , line , func )           \
  do {                                                                  \
    intptr_t expr = (_expr);                                            \
    if( !expr ){                                                        \
      std::cout << '\n'                                                 \
                << "---[ Error ]--------------------------------------------\n" \
                << "    File     : " << file << '\n'                    \
                << "    Function : " << func << '\n'                    \
                << "    Line     : " << line << '\n'                    \
                << "========================================================\n"; \
      OCCA_THROW;                                                       \
    }                                                                   \
  } while(0)

#define OCCA_FORCE_CHECK2( _expr , _msg , file , line , func )          \
  do {                                                                  \
    intptr_t expr = (_expr);                                            \
    if( !expr ){                                                        \
      std::cout << '\n'                                                 \
                << "---[ Error ]--------------------------------------------\n" \
                << "    File     : " << file << '\n'                    \
                << "    Function : " << func << '\n'                    \
                << "    Line     : " << line << '\n'                    \
                << "    Error    : " << _msg << '\n'                    \
                << "========================================================\n"; \
      OCCA_THROW;                                                       \
    }                                                                   \
  } while(0)

#define OCCA_EMPTY_FORCE_CHECK( _expr )  OCCA_EMPTY_FORCE_CHECK2( _expr , __FILE__ , __LINE__ , __PRETTY_FUNCTION__)
#define OCCA_FORCE_CHECK( _expr , _msg ) OCCA_FORCE_CHECK2( _expr , _msg , __FILE__ , __LINE__ , __PRETTY_FUNCTION__)

#if OCCA_CHECK_ENABLED
#  define OCCA_EMPTY_CHECK( _expr )  OCCA_EMPTY_FORCE_CHECK( _expr )
#  define OCCA_CHECK( _expr , _msg ) OCCA_FORCE_CHECK( _expr , _msg )
#else
#  define OCCA_EMPTY_CHECK( _expr )
#  define OCCA_CHECK( _expr , _msg )
#endif

#if OCCA_OS == OSX_OS
#  define OCCA_MEM_ALIGN 16
#else
#  define OCCA_MEM_ALIGN 64
#endif

#define OCCA_SIMD_WIDTH 8

#define OCCA_MAX_ARGS 50
//======================================

//---[ Base ]---------------------------
#define OCCA_KERNEL_ARG_CONSTRUCTOR(TYPE)         \
  template <>                                     \
  inline kernelArg::kernelArg(const TYPE &arg_){  \
    arg.TYPE##_ = arg_;                           \
    size      = sizeof(TYPE);                     \
                                                  \
    pointer    = false;                           \
    hasTwoArgs = false;                           \
  }

#define OCCA_KERNEL_ARG_CONSTRUCTOR_ALIAS(TYPE, ALIAS)  \
  template <>                                           \
  inline kernelArg::kernelArg(const TYPE &arg_){        \
    arg.ALIAS##_ = arg_;                                \
    size         = sizeof(TYPE);                        \
                                                        \
    pointer    = false;                                 \
    hasTwoArgs = false;                                 \
  }

#define OCCA_EXTRACT_DATA(MODE, CLASS)                          \
  MODE##CLASS##Data_t &data_ = *((MODE##CLASS##Data_t*) data);
//======================================

//---[ Pthreads ]-----------------------
//======================================

//---[ OpenMP ]-------------------------
//======================================

//---[ OpenCL ]-------------------------
#if OCCA_CHECK_ENABLED
;
#  define OCCA_CL_CHECK( _str , _statement ) OCCA_CL_CHECK2( _str , _statement , __FILE__ , __LINE__ )
#  define OCCA_CL_CHECK2( _str , _statement , file , line )             \
  do {                                                                  \
    cl_int _error = _statement;                                         \
    if(_error){                                                         \
      _error = _error < 0  ? _error : -_error;                          \
      _error = _error < 65 ? _error : 15;                               \
                                                                        \
      std::cout << "Error\n"                                            \
                << "    File    : " << file << '\n'                     \
                << "    Line    : " << line << '\n'                     \
                << "    Error   : OpenCL Error [ " << _error << " ]: " << occa::openclError(_error) << '\n' \
                << "    Message : " << _str << '\n';                    \
      OCCA_THROW;                                                       \
    }                                                                   \
  } while(0)

#else
#  define OCCA_CL_CHECK( _str , _statement ) do { _statement; } while(0)
#endif
//======================================

//---[ CUDA ]---------------------------
#if OCCA_CHECK_ENABLED
#  define OCCA_CUDA_CHECK( _str , _statement ) OCCA_CUDA_CHECK2( _str , _statement , __FILE__ , __LINE__ )
#  define OCCA_CUDA_CHECK2( _str , _statement , file , line )           \
  do {                                                                  \
    CUresult errorCode = _statement;                                    \
    if(errorCode){                                                      \
      std::cout << "Error\n"                                            \
                << "    File    : " << file << '\n'                     \
                << "    Line    : " << line << '\n'                     \
                << "    Error   : CUDA Error [ " << errorCode << " ]: " << occa::cudaError(errorCode) << '\n' \
                << "    Message : " << _str << '\n';                    \
      OCCA_THROW;                                                       \
    }                                                                   \
  } while(0)
#else
#  define OCCA_CUDA_CHECK( _str , _statement ) do { _statement; } while(0)
#endif
//======================================

//---[ COI ]----------------------------
#if OCCA_CHECK_ENABLED
#  define OCCA_COI_CHECK( _str , _statement ) OCCA_COI_CHECK2( _str , _statement , __FILE__ , __LINE__ )
#  define OCCA_COI_CHECK2( _str , _statement , file , line )            \
  do {                                                                  \
    COIRESULT errorCode = _statement;                                   \
    if(errorCode != COI_SUCCESS){                                       \
      std::cout << "Error\n"                                            \
                << "    File    : " << file << '\n'                     \
                << "    Line    : " << line << '\n'                     \
                << "    Error   : " << occa::coiError(errorCode) << '\n' \
                << "    Message : " << _str << '\n';                    \
      throw 1;                                                          \
    }                                                                   \
  } while(0);
#else
#  define OCCA_COI_CHECK( _str , _statement ) do { _statement; } while(0);
#endif
//======================================
#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fourboxwipe.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 08:39:52 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_slideshow.hxx"

#include "canvas/debug.hxx"
#include "fourboxwipe.hxx"
#include "basegfx/matrix/b2dhommatrix.hxx"
#include "basegfx/polygon/b2dpolypolygon.hxx"
#include "basegfx/numeric/ftools.hxx"

namespace presentation {
namespace internal {

::basegfx::B2DPolyPolygon FourBoxWipe::operator () ( double t )
{
    ::basegfx::B2DHomMatrix aTransform;
    const double d = ::basegfx::pruneScaleValue( t / 2.0 );
    if (m_cornersOut) {
        aTransform.translate( -0.5, -0.5 );
        aTransform.scale( d, d );
        aTransform.translate( -0.25, -0.25 );
    } else {
        aTransform.scale( d, d );
        aTransform.translate( -0.5, -0.5 );
    }

    // top left:
    ::basegfx::B2DPolygon square( m_unitRect );
    square.transform( aTransform );
    ::basegfx::B2DPolyPolygon res( square );
    // bottom left, flip on x-axis:
    aTransform.scale( -1.0, 1.0 );
    ::basegfx::B2DPolygon square2( m_unitRect );
    square2.transform( aTransform );
    square2.flip(); // flip direction
    res.append( square2 );
    // bottom right, flip on y-axis:
    aTransform.scale( 1.0, -1.0 );
    ::basegfx::B2DPolygon square3( m_unitRect );
    square3.transform( aTransform );
    res.append( square3 );
    // top right, flip on x-axis:
    aTransform.scale( -1.0, 1.0 );
    ::basegfx::B2DPolygon square4( m_unitRect );
    square4.transform( aTransform );
    square4.flip(); // flip direction
    res.append( square4 );

    aTransform.identity();
    aTransform.translate( 0.5, 0.5 );
    res.transform( aTransform );
    return res;
}

}
}
<commit_msg>INTEGRATION: CWS presfixes09 (1.3.18); FILE MERGED 2006/10/18 19:58:28 thb 1.3.18.3: RESYNC: (1.3-1.4); FILE MERGED 2006/04/24 13:25:32 thb 1.3.18.2: #i53194# Unified include statements (local headers always have double quotes; external headers angle brackets); reverted EventMultiplexer pause events to shared_ptr; removed EventMultiplexer::removeViewHandler(), since the handler is held weakly, anyway. 2006/03/24 18:23:24 thb 1.3.18.1: #i37778# Moved whole slideshow engine from namespace presentation (which conflicts with one of the UNO subnamespaces) to slideshow<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fourboxwipe.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-13 15:42:04 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_slideshow.hxx"

#include <canvas/debug.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/numeric/ftools.hxx>
#include "fourboxwipe.hxx"

namespace slideshow {
namespace internal {

::basegfx::B2DPolyPolygon FourBoxWipe::operator () ( double t )
{
    ::basegfx::B2DHomMatrix aTransform;
    const double d = ::basegfx::pruneScaleValue( t / 2.0 );
    if (m_cornersOut) {
        aTransform.translate( -0.5, -0.5 );
        aTransform.scale( d, d );
        aTransform.translate( -0.25, -0.25 );
    } else {
        aTransform.scale( d, d );
        aTransform.translate( -0.5, -0.5 );
    }

    // top left:
    ::basegfx::B2DPolygon square( m_unitRect );
    square.transform( aTransform );
    ::basegfx::B2DPolyPolygon res( square );
    // bottom left, flip on x-axis:
    aTransform.scale( -1.0, 1.0 );
    ::basegfx::B2DPolygon square2( m_unitRect );
    square2.transform( aTransform );
    square2.flip(); // flip direction
    res.append( square2 );
    // bottom right, flip on y-axis:
    aTransform.scale( 1.0, -1.0 );
    ::basegfx::B2DPolygon square3( m_unitRect );
    square3.transform( aTransform );
    res.append( square3 );
    // top right, flip on x-axis:
    aTransform.scale( -1.0, 1.0 );
    ::basegfx::B2DPolygon square4( m_unitRect );
    square4.transform( aTransform );
    square4.flip(); // flip direction
    res.append( square4 );

    aTransform.identity();
    aTransform.translate( 0.5, 0.5 );
    res.transform( aTransform );
    return res;
}

}
}
<|endoftext|>


<commit_before>/*  This file is part of the KDE project.

    Copyright (C) 2010-2011 Harald Sitter <sitter@kde.org>
    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).

    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 2.1 or 3 of the License.

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

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

#include "phononsrc.h"

#include "streamreader.h"

QT_BEGIN_NAMESPACE

namespace Phonon
{
namespace Gstreamer
{

static GstStaticPadTemplate srctemplate =
       GST_STATIC_PAD_TEMPLATE ("src",
                                GST_PAD_SRC,
                                GST_PAD_ALWAYS,
                                GST_STATIC_CAPS_ANY);

GST_DEBUG_CATEGORY_STATIC (phonon_src_debug);

// PhononSrc args
enum
{
    ARG_0,
    ARG_PHONONSRC
};

static void phonon_src_finalize(GObject *object);

static void phonon_src_set_property(GObject *object, guint prop_id,
                                    const GValue *value, GParamSpec *pspec);
static void phonon_src_get_property(GObject *object, guint prop_id,
                                    GValue *value, GParamSpec *pspec);

static gboolean phonon_src_start(GstBaseSrc *basesrc);
static gboolean phonon_src_stop(GstBaseSrc *basesrc);

static gboolean phonon_src_unlock(GstBaseSrc *basesrc);
static gboolean phonon_src_unlock_stop(GstBaseSrc *basesrc);

static gboolean phonon_src_is_seekable(GstBaseSrc *src);
static gboolean phonon_src_get_size(GstBaseSrc *src, guint64 *size);
static GstFlowReturn phonon_src_create(GstBaseSrc *src, guint64 offset,
                                       guint length, GstBuffer **buffer);

static gboolean register_elements(GstPlugin *plugin)
{
    if (!gst_element_register(plugin, "phononsrc", GST_RANK_NONE, GST_TYPE_PHONON_SRC))
        return FALSE;
    return TRUE;
}

gboolean register_phonon_elements()
{
    gst_plugin_register_static(
        GST_VERSION_MAJOR,
        GST_VERSION_MINOR,
        "phonon-plugins",
        "Private elements of Phonon",
        register_elements,
        PHONON_VERSION_STR,
        "LGPL",
        "phonon",
        "phonon",
        "http://phonon.kde.org");
    return TRUE;
}

static void _do_init(GType filesrc_type)
{
    Q_UNUSED(filesrc_type);
    GST_DEBUG_CATEGORY_INIT (phonon_src_debug, "phononsrc", 0, "QIODevice element");
}

GST_BOILERPLATE_FULL(PhononSrc, phonon_src, GstBaseSrc, GST_TYPE_BASE_SRC, _do_init)

// Register element details
static void phonon_src_base_init(gpointer g_class) {
    GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
    static gchar longname[] = "Phonon Stream Source",
                    klass[] = "Source/File",
              description[] = "Read from a Phonon StreamInterface",
                   author[] = "Nokia Corporation and/or its subsidiary(-ies) <qt-info@nokia.com>";
    GstElementDetails details = GST_ELEMENT_DETAILS (longname,
                                          klass,
                                          description,
                                          author);
    gst_element_class_set_details(gstelement_class, &details);
    gst_element_class_add_pad_template(gstelement_class, gst_static_pad_template_get(&srctemplate));
}

static void phonon_src_class_init (PhononSrcClass *klass)
{
    GObjectClass *gobject_class;
    GstElementClass *gstelement_class;
    GstBaseSrcClass *gstbasesrc_class;

    gobject_class = G_OBJECT_CLASS(klass);
    gstelement_class = GST_ELEMENT_CLASS(klass);
    gstbasesrc_class = GST_BASE_SRC_CLASS(klass);

    gobject_class->set_property = phonon_src_set_property;
    gobject_class->get_property = phonon_src_get_property;

    g_object_class_install_property(gobject_class, ARG_PHONONSRC,
                                    g_param_spec_pointer ("iodevice", "A Phonon StreamReader",
                                                          "A Phonon::GStreamer::StreamReader to read from", GParamFlags(G_PARAM_READWRITE)));

    gobject_class->finalize = GST_DEBUG_FUNCPTR(phonon_src_finalize);

    gstbasesrc_class->start = GST_DEBUG_FUNCPTR(phonon_src_start);
    gstbasesrc_class->stop = GST_DEBUG_FUNCPTR(phonon_src_stop);
    gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR(phonon_src_unlock);
    gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR(phonon_src_unlock_stop);
    gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR(phonon_src_is_seekable);
    gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR(phonon_src_get_size);
    gstbasesrc_class->create = GST_DEBUG_FUNCPTR(phonon_src_create);
}

static void phonon_src_init(PhononSrc *src, PhononSrcClass *g_class)
{
    Q_UNUSED(g_class);
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    src->device = 0;
#endif
}

static void phonon_src_finalize(GObject *object)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    PhononSrc *src;
    src = GST_PHONON_SRC(object);
    delete src->device;
    src->device = 0;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    G_OBJECT_CLASS (parent_class)->finalize(object);
}

#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
static gboolean phonon_src_set_device(PhononSrc *src, StreamReader *device)
{
    GstState state;
    // The element must be stopped in order to do this
    GST_OBJECT_LOCK(src);
    state = GST_STATE(src);

    if (state != GST_STATE_READY && state != GST_STATE_NULL)
        goto wrong_state;

    GST_OBJECT_UNLOCK(src);

    src->device = device;
    g_object_notify(G_OBJECT (src), "iodevice");
    return TRUE;

    // Error
wrong_state:
    {
        //GST_DEBUG_OBJECT (src, "setting location in wrong state");
        GST_OBJECT_UNLOCK (src);
        return FALSE;
    }
}
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM

static void phonon_src_set_property(GObject *object, guint prop_id, const GValue *value,
                                    GParamSpec *pspec)
{
    PhononSrc *src;
    g_return_if_fail(GST_IS_PHONON_SRC(object));
    src = GST_PHONON_SRC(object);

    switch (prop_id) {
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    case ARG_PHONONSRC:
    {
        StreamReader *dev = (StreamReader*)(g_value_get_pointer(value));
        if (dev)
            phonon_src_set_device(src, dev);
        break;
    }
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
   default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
}

static void phonon_src_get_property(GObject *object, guint prop_id, GValue *value,
                                    GParamSpec *pspec)
{
    PhononSrc *src;
    g_return_if_fail (GST_IS_PHONON_SRC (object));
    src = GST_PHONON_SRC (object);

    switch (prop_id) {
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    case ARG_PHONONSRC:
        g_value_set_pointer(value, src->device);
        break;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
}

static GstFlowReturn phonon_src_create_read(PhononSrc *src, guint64 offset, guint length,
                                            GstBuffer **buffer)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    Q_ASSERT(src->device);
    if (!src->device)
        return GST_FLOW_ERROR;

    GstBuffer *buf = gst_buffer_new_and_alloc (length);
    GST_BUFFER_SIZE (buf) = length;
    GST_BUFFER_OFFSET (buf) = offset;
    GST_BUFFER_OFFSET_END (buf) = offset + length;

    GstFlowReturn ret = src->device->read(offset, length, (char*)GST_BUFFER_DATA (buf));
//    GST_LOG_OBJECT (src, "Reading %d bytes", length);

    if (ret == GST_FLOW_OK) {
        *buffer = buf;
        return ret;
    } else if (ret == GST_FLOW_UNEXPECTED) {
        return ret;
    }

    gst_mini_object_unref(GST_MINI_OBJECT(buf));
    return GST_FLOW_ERROR;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return GST_FLOW_ERROR;
}

static GstFlowReturn phonon_src_create(GstBaseSrc *basesrc, guint64 offset, guint length, GstBuffer **buffer)
{
    PhononSrc *src = GST_PHONON_SRC (basesrc);
    return phonon_src_create_read (src, offset, length, buffer);
}

static gboolean phonon_src_is_seekable(GstBaseSrc *basesrc)
{
    PhononSrc *src = GST_PHONON_SRC(basesrc);
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    if (src->device)
        return src->device->streamSeekable();
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

static gboolean phonon_src_get_size(GstBaseSrc *basesrc, guint64 *size)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    if (src->device && src->device->streamSeekable()) {
        *size = src->device->streamSize();
        return true;
    }
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    *size = 0;
    return false;
}

static gboolean phonon_src_unlock(GstBaseSrc *basesrc)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    src->device->unlock();
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

static gboolean phonon_src_unlock_stop(GstBaseSrc *basesrc)
{
    Q_UNUSED(basesrc);
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    // Resource locking and unlocking happens onthefly, unlock just wakes our
    // QWaitConditions.
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

// Necessary to go to READY state
static gboolean phonon_src_start(GstBaseSrc *basesrc)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    // Opening the device is handled by the frontend, still we need to make sure
    // that the streamer is in initial state WRT member variables etc.
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    src->device->start();
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

static gboolean phonon_src_stop(GstBaseSrc *basesrc)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    // Closing the device is handled by the frontend, we just need to ensure
    // the reader is unlocked and send a final enoughData.
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    src->device->stop();
    return TRUE;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

}
} //namespace Phonon::Gstreamer

QT_END_NAMESPACE
<commit_msg>Implement URI handler interface for the phononsrc<commit_after>/*  This file is part of the KDE project.

    Copyright (C) 2010-2011 Harald Sitter <sitter@kde.org>
    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).

    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 2.1 or 3 of the License.

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

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

#define GST_CAT_DEFAULT phononsrc

#include "phononsrc.h"

#include "streamreader.h"

QT_BEGIN_NAMESPACE

namespace Phonon
{
namespace Gstreamer
{

static GstStaticPadTemplate srctemplate =
       GST_STATIC_PAD_TEMPLATE ("src",
                                GST_PAD_SRC,
                                GST_PAD_ALWAYS,
                                GST_STATIC_CAPS_ANY);

GST_DEBUG_CATEGORY_STATIC (phononsrc);

// PhononSrc args
enum
{
    ARG_0,
    ARG_PHONONSRC
};

static void phonon_src_finalize(GObject *object);

static void phonon_src_set_property(GObject *object, guint prop_id,
                                    const GValue *value, GParamSpec *pspec);
static void phonon_src_get_property(GObject *object, guint prop_id,
                                    GValue *value, GParamSpec *pspec);

static gboolean phonon_src_start(GstBaseSrc *basesrc);
static gboolean phonon_src_stop(GstBaseSrc *basesrc);

static gboolean phonon_src_unlock(GstBaseSrc *basesrc);
static gboolean phonon_src_unlock_stop(GstBaseSrc *basesrc);

static gboolean phonon_src_is_seekable(GstBaseSrc *src);
static gboolean phonon_src_get_size(GstBaseSrc *src, guint64 *size);
static GstFlowReturn phonon_src_create(GstBaseSrc *src, guint64 offset,
                                       guint length, GstBuffer **buffer);

static gboolean register_elements(GstPlugin *plugin)
{
    if (!gst_element_register(plugin, "phononsrc", GST_RANK_NONE, GST_TYPE_PHONON_SRC))
        return FALSE;
    return TRUE;
}

gboolean register_phonon_elements()
{
    gst_plugin_register_static(
        GST_VERSION_MAJOR,
        GST_VERSION_MINOR,
        "phonon-plugins",
        "Private elements of Phonon",
        register_elements,
        PHONON_VERSION_STR,
        "LGPL",
        "phonon",
        "phonon",
        "http://phonon.kde.org");
    return TRUE;
}

// Register element details
static void phonon_src_base_init(gpointer g_class) {
    GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
    static gchar longname[] = "Phonon Stream Source",
                    klass[] = "Source/File",
              description[] = "Read from a Phonon StreamInterface",
                   author[] = "Nokia Corporation and/or its subsidiary(-ies) <qt-info@nokia.com>";
    GstElementDetails details = GST_ELEMENT_DETAILS (longname,
                                          klass,
                                          description,
                                          author);
    gst_element_class_set_details(gstelement_class, &details);
    gst_element_class_add_pad_template(gstelement_class, gst_static_pad_template_get(&srctemplate));
}

static void phonon_src_class_init (PhononSrcClass *klass)
{
    GObjectClass *gobject_class;
    GstElementClass *gstelement_class;
    GstBaseSrcClass *gstbasesrc_class;

    gobject_class = G_OBJECT_CLASS(klass);
    gstelement_class = GST_ELEMENT_CLASS(klass);
    gstbasesrc_class = GST_BASE_SRC_CLASS(klass);

    gobject_class->set_property = phonon_src_set_property;
    gobject_class->get_property = phonon_src_get_property;

    g_object_class_install_property(gobject_class, ARG_PHONONSRC,
                                    g_param_spec_pointer ("iodevice", "A Phonon StreamReader",
                                                          "A Phonon::GStreamer::StreamReader to read from", GParamFlags(G_PARAM_READWRITE)));

    gobject_class->finalize = GST_DEBUG_FUNCPTR(phonon_src_finalize);

    gstbasesrc_class->start = GST_DEBUG_FUNCPTR(phonon_src_start);
    gstbasesrc_class->stop = GST_DEBUG_FUNCPTR(phonon_src_stop);
    gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR(phonon_src_unlock);
    gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR(phonon_src_unlock_stop);
    gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR(phonon_src_is_seekable);
    gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR(phonon_src_get_size);
    gstbasesrc_class->create = GST_DEBUG_FUNCPTR(phonon_src_create);
}

static void phonon_src_init(PhononSrc *src, PhononSrcClass *g_class)
{
    Q_UNUSED(g_class);
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    src->device = 0;
#endif
}

GstURIType phonon_src_uri_type()
{
    return GST_URI_SRC;
}

gchar** phonon_src_uri_protocols()
{
    static gchar* protocols[] = {
        "phonon",
        0
    };
    return protocols;
}

G_CONST_RETURN gchar* phonon_src_get_uri(GstURIHandler *handler)
{
    Q_UNUSED(handler);
    return "phonon:/";
}

gboolean phonon_src_set_uri(GstURIHandler *handler, const gchar *uri)
{
    Q_UNUSED(uri);
    Q_UNUSED(handler);
    GST_DEBUG("Setting URI");
    return true;
}

static void phonon_src_urihandler_init(GstURIHandlerInterface *iface)
{
    GST_DEBUG("urihandler init");
    iface->get_type = phonon_src_uri_type;
    iface->get_protocols = phonon_src_uri_protocols;
    iface->get_uri = phonon_src_get_uri;
    iface->set_uri = phonon_src_set_uri;
}

//G_DEFINE_TYPE_WITH_CODE(PhononSrc, phonon_src, GST_TYPE_BASE_SRC,
//        G_IMPLEMENT_INTERFACE(GST_TYPE_URI_HANDLER, phonon_src_urihandler_init));

GType phonon_src_get_type()
{
    static GType phonon_src_type = 0;
    if (!phonon_src_type) {
        static const GTypeInfo phonon_src_info = {
            sizeof(PhononSrcClass),
            (GBaseInitFunc) phonon_src_base_init,
            NULL,
            (GClassInitFunc) phonon_src_class_init,
            NULL,
            NULL,
            sizeof(PhononSrc),
            0,
            (GInstanceInitFunc) phonon_src_init
        };
        static const GInterfaceInfo phonon_iface_info = {
            (GInterfaceInitFunc) phonon_src_urihandler_init,
            NULL,
            NULL
        };
        phonon_src_type = g_type_register_static(GST_TYPE_BASE_SRC,
                "PhononSrc",
                &phonon_src_info,
                (GTypeFlags)0);
        g_type_add_interface_static(phonon_src_type, GST_TYPE_URI_HANDLER,
                &phonon_iface_info);
        GST_DEBUG_CATEGORY_INIT (phononsrc, "phononsrc", 0, "QIODevice element");
    }
    return phonon_src_type;
}

static void phonon_src_finalize(GObject *object)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    GST_DEBUG("finalize");
    PhononSrc *src;
    src = GST_PHONON_SRC(object);
    if (src->device)
        delete src->device;
    src->device = 0;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
}

#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
static gboolean phonon_src_set_device(PhononSrc *src, StreamReader *device)
{
    GstState state;
    GST_DEBUG("Loading io device");
    // The element must be stopped in order to do this
    GST_OBJECT_LOCK(src);
    state = GST_STATE(src);

    if (src->device) {
        GST_DEBUG("Stopping old device");
        src->device->stop();
    }

    GST_OBJECT_UNLOCK(src);

    src->device = device;
    if (state >= GST_STATE_READY)
        src->device->start();
    g_object_notify(G_OBJECT (src), "iodevice");
    return TRUE;
}
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM

static void phonon_src_set_property(GObject *object, guint prop_id, const GValue *value,
                                    GParamSpec *pspec)
{
    PhononSrc *src;
    g_return_if_fail(GST_IS_PHONON_SRC(object));
    src = GST_PHONON_SRC(object);

    switch (prop_id) {
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    case ARG_PHONONSRC:
    {
        StreamReader *dev = (StreamReader*)(g_value_get_pointer(value));
        phonon_src_set_device(src, dev);
        break;
    }
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
   default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
}

static void phonon_src_get_property(GObject *object, guint prop_id, GValue *value,
                                    GParamSpec *pspec)
{
    PhononSrc *src;
    g_return_if_fail (GST_IS_PHONON_SRC (object));
    src = GST_PHONON_SRC (object);

    switch (prop_id) {
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    case ARG_PHONONSRC:
        g_value_set_pointer(value, src->device);
        break;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
}

static GstFlowReturn phonon_src_create_read(PhononSrc *src, guint64 offset, guint length,
                                            GstBuffer **buffer)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    if (!src->device)
        return GST_FLOW_ERROR;

    GstBuffer *buf = gst_buffer_new_and_alloc (length);
    GST_BUFFER_SIZE (buf) = length;
    GST_BUFFER_OFFSET (buf) = offset;
    GST_BUFFER_OFFSET_END (buf) = offset + length;

    GstFlowReturn ret = src->device->read(offset, length, (char*)GST_BUFFER_DATA (buf));
    GST_LOG_OBJECT (src, "Reading %d bytes", length);

    if (ret == GST_FLOW_OK) {
        *buffer = buf;
        return ret;
    } else if (ret == GST_FLOW_UNEXPECTED) {
        return ret;
    }

    gst_mini_object_unref(GST_MINI_OBJECT(buf));
    return GST_FLOW_ERROR;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return GST_FLOW_ERROR;
}

static GstFlowReturn phonon_src_create(GstBaseSrc *basesrc, guint64 offset, guint length, GstBuffer **buffer)
{
    PhononSrc *src = GST_PHONON_SRC (basesrc);
    return phonon_src_create_read (src, offset, length, buffer);
}

static gboolean phonon_src_is_seekable(GstBaseSrc *basesrc)
{
    return false;
    PhononSrc *src = GST_PHONON_SRC(basesrc);
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    if (src->device)
        return src->device->streamSeekable();
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

static gboolean phonon_src_get_size(GstBaseSrc *basesrc, guint64 *size)
{
    GST_DEBUG("get_size");
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    if (src->device && src->device->streamSeekable()) {
        *size = src->device->streamSize();
        GST_DEBUG("Size: %d", *size);
        return true;
    }
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    *size = 0;
    return false;
}

static gboolean phonon_src_unlock(GstBaseSrc *basesrc)
{
    GST_DEBUG("unlock");
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    src->device->unlock();
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

static gboolean phonon_src_unlock_stop(GstBaseSrc *basesrc)
{
    GST_DEBUG("unlock stop");
    Q_UNUSED(basesrc);
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    // Resource locking and unlocking happens onthefly, unlock just wakes our
    // QWaitConditions.
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

// Necessary to go to READY state
static gboolean phonon_src_start(GstBaseSrc *basesrc)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    GST_DEBUG("Stream start");
    // Opening the device is handled by the frontend, still we need to make sure
    // that the streamer is in initial state WRT member variables etc.
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    src->device->start();
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

static gboolean phonon_src_stop(GstBaseSrc *basesrc)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    GST_DEBUG("stop");
    // Closing the device is handled by the frontend, we just need to ensure
    // the reader is unlocked and send a final enoughData.
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    src->device->stop();
    return TRUE;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

}
} //namespace Phonon::Gstreamer

QT_END_NAMESPACE
<|endoftext|>