diff options
author | Dimitri John Ledkov <dimitri.ledkov@canonical.com> | 2014-02-20 16:10:52 +0000 |
---|---|---|
committer | Dimitri John Ledkov <dimitri.ledkov@canonical.com> | 2014-02-20 19:15:57 +0000 |
commit | d20f4a64eba38690337ac914a04a113de7caf125 (patch) | |
tree | 6828990e93ca5d8847b8cde2f2febb6566b0d53f /src/base | |
parent | 28161e9209f21be1a600f637565ecede94855a36 (diff) |
New upstream release. Closes: #721047debian/1.8.0-1
Drop all patches, none are needed with this new upstream release.
Port to dh.
Specify foreign in configure.ac.
Diffstat (limited to 'src/base')
94 files changed, 5738 insertions, 1936 deletions
diff --git a/src/base/Backtrace.cpp b/src/base/Backtrace.cpp index f6d1d77..2b85cde 100644 --- a/src/base/Backtrace.cpp +++ b/src/base/Backtrace.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,6 +21,8 @@ #include "Backtrace.h" +#include "StringHelper.h" + #ifndef _WIN32 #include <execinfo.h> #include <cxxabi.h> @@ -28,6 +30,7 @@ #include <stdlib.h> #include <iostream> +#include <stdio.h> using namespace std; @@ -38,12 +41,10 @@ void dumpBacktrace() #ifndef _WIN32 vector<string> sFuncs; getBacktrace(sFuncs); - int i=0; vector<string>::iterator it = sFuncs.begin(); ++it; for (; it != sFuncs.end(); ++it) { - cerr << " " << i << ": " << *it << endl; - i++; + cerr << " " << *it << endl; } #endif } @@ -67,7 +68,15 @@ string funcNameFromLine(const string& sLine) } } -void getBacktrace(std::vector<std::string>& sFuncs) +void consolidateRepeatedLines(vector<string>& sFuncs, unsigned& i, unsigned numSameLines) +{ + unsigned firstSameLine = i - numSameLines; + sFuncs[firstSameLine+1] = " [...]"; + sFuncs.erase(sFuncs.begin()+firstSameLine+2, sFuncs.begin()+i-1); + i = firstSameLine + 3; +} + +void getBacktrace(vector<string>& sFuncs) { #ifndef _WIN32 void* callstack[128]; @@ -83,9 +92,27 @@ void getBacktrace(std::vector<std::string>& sFuncs) sFuncName = pszDemangledFuncName; free(pszDemangledFuncName); } - sFuncs.push_back(sFuncName); + char szLineNum[10]; + sprintf(szLineNum, "%3d", i); + sFuncs.push_back(string(szLineNum)+" "+sFuncName); } free(ppszLines); + + unsigned numSameLines = 1; + unsigned i = 1; + for (i = 1; i < sFuncs.size(); ++i) { + if (sFuncs[i].substr(4, string::npos) == sFuncs[i-1].substr(4, string::npos)) { + numSameLines++; + } else { + if (numSameLines > 3) { + consolidateRepeatedLines(sFuncs, i, numSameLines); + } + numSameLines = 1; + } + } + if (numSameLines > 2) { + consolidateRepeatedLines(sFuncs, i, numSameLines); + } #endif } diff --git a/src/base/Backtrace.h b/src/base/Backtrace.h index cc49964..2eee387 100644 --- a/src/base/Backtrace.h +++ b/src/base/Backtrace.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/BezierCurve.cpp b/src/base/BezierCurve.cpp index 3d1ea72..7e5fb8e 100644 --- a/src/base/BezierCurve.cpp +++ b/src/base/BezierCurve.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,14 +21,16 @@ #include "BezierCurve.h" +#include "GLMHelper.h" + #include <iostream> using namespace std; namespace avg { -BezierCurve::BezierCurve(const DPoint& p0, const DPoint& p1, const DPoint& p2, - const DPoint& p3) +BezierCurve::BezierCurve(const glm::vec2& p0, const glm::vec2& p1, const glm::vec2& p2, + const glm::vec2& p3) : m_P0(p0), m_P1(p1), m_P2(p2), @@ -36,18 +38,19 @@ BezierCurve::BezierCurve(const DPoint& p0, const DPoint& p1, const DPoint& p2, { } -DPoint BezierCurve::interpolate(double t) const +glm::vec2 BezierCurve::interpolate(float t) const { - return (1-t)*(1-t)*(1-t)*m_P0+ - 3*t*(1-t)*(1-t) *m_P1+ - 3*t*t*(1-t) *m_P2+ - t*t*t *m_P3; + return (1.f-t)*(1.f-t)*(1.f-t)*m_P0+ + 3.f*t*(1.f-t)*(1.f-t) *m_P1+ + 3.f*t*t*(1.f-t) *m_P2+ + t*t*t *m_P3; } -DPoint BezierCurve::getDeriv(double t) const + +glm::vec2 BezierCurve::getDeriv(float t) const { - return 3*(m_P1-m_P0)*(1-t)*(1-t)+ - 6*(m_P2-m_P1)*(1-t)*t+ - 3*(m_P3-m_P2)*t*t; + return 3.f*(m_P1-m_P0)*(1.f-t)*(1.f-t)+ + 6.f*(m_P2-m_P1)*(1.f-t)*t+ + 3.f*(m_P3-m_P2)*t*t; } } diff --git a/src/base/BezierCurve.h b/src/base/BezierCurve.h index b7e00f4..b2ec1dc 100644 --- a/src/base/BezierCurve.h +++ b/src/base/BezierCurve.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,7 +23,8 @@ #define _BezierCurve_H_ #include "../api.h" -#include "Point.h" + +#include "../glm/glm.hpp" #include <boost/shared_ptr.hpp> #include <vector> @@ -32,16 +33,17 @@ namespace avg { class AVG_API BezierCurve { public: - BezierCurve(const DPoint& p0, const DPoint& p1, const DPoint& p2, const DPoint& p3); + BezierCurve(const glm::vec2& p0, const glm::vec2& p1, const glm::vec2& p2, + const glm::vec2& p3); - DPoint interpolate(double t) const; - DPoint getDeriv(double t) const; + glm::vec2 interpolate(float t) const; + glm::vec2 getDeriv(float t) const; private: - DPoint m_P0; - DPoint m_P1; - DPoint m_P2; - DPoint m_P3; + glm::vec2 m_P0; + glm::vec2 m_P1; + glm::vec2 m_P2; + glm::vec2 m_P3; }; typedef boost::shared_ptr<BezierCurve> BezierCurvePtr; diff --git a/src/base/CmdLine.cpp b/src/base/CmdLine.cpp deleted file mode 100644 index d081ec5..0000000 --- a/src/base/CmdLine.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// -// libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow -// -// 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 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// Current versions can be found at www.libavg.de -// - -#include "CmdLine.h" - -#include <iostream> - -using namespace std; - -namespace avg { - -CmdLine::CmdLine(int argc, char **argv) -{ - for (int i = 1; i < argc; ++i) { - string sArg(argv[i]); - if (sArg.substr(0, 2) == "--") { - string::size_type DelimPos = sArg.find('='); - string sOptName; - string sOptVal; - if (DelimPos == sArg.npos) { - sOptName = sArg.substr(2); - sOptVal = ""; - } else { - sOptName = sArg.substr(2, DelimPos-2); - sOptVal = sArg.substr(DelimPos+1); - } - m_Options[sOptName] = sOptVal; - } else { - m_Args.push_back(sArg); - } - } -} - -const OptionMap& CmdLine::getOptions() const -{ - return m_Options; -} - -const string* CmdLine::getOption(const string& sName) const -{ - OptionMap::const_iterator it = m_Options.find(sName); - if (it == m_Options.end()) { - return 0; - } else { - return &(*it).second; - } -} - -int CmdLine::getNumArgs() const -{ - return int(m_Args.size()); -} - -const string* CmdLine::getArg(unsigned int i) const -{ - if (i>=m_Args.size()) { - return 0; - } else { - return &m_Args[i]; - } -} - -} - diff --git a/src/base/CmdQueue.h b/src/base/CmdQueue.h index a2dc6a3..9d38f37 100644 --- a/src/base/CmdQueue.h +++ b/src/base/CmdQueue.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -33,12 +33,19 @@ template<class RECEIVER> class AVG_TEMPLATE_API CmdQueue: public Queue<Command<RECEIVER> > { public: + CmdQueue(int maxSize=-1); typedef typename Queue<Command<RECEIVER> >::QElementPtr CmdPtr; void pushCmd(typename Command<RECEIVER>::CmdFunc func); }; template<class RECEIVER> +CmdQueue<RECEIVER>::CmdQueue(int maxSize) + : Queue<Command<RECEIVER> >(maxSize) +{ +} + +template<class RECEIVER> void CmdQueue<RECEIVER>::pushCmd(typename Command<RECEIVER>::CmdFunc func) { this->push(CmdPtr(new Command<RECEIVER>(func))); diff --git a/src/base/Command.h b/src/base/Command.h index 79c48a6..fe18171 100644 --- a/src/base/Command.h +++ b/src/base/Command.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/ConfigMgr.cpp b/src/base/ConfigMgr.cpp index 04b756d..0414037 100644 --- a/src/base/ConfigMgr.cpp +++ b/src/base/ConfigMgr.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -66,29 +66,45 @@ ConfigMgr* ConfigMgr::get() ConfigMgr::ConfigMgr() { addSubsys("scr"); + addOption("scr", "gles", "false"); addOption("scr", "bpp", "24"); addOption("scr", "fullscreen", "false"); addOption("scr", "windowwidth", "0"); addOption("scr", "windowheight", "0"); addOption("scr", "dotspermm", "0"); addOption("scr", "usepow2textures", "false"); - addOption("scr", "useshaders", "true"); addOption("scr", "usepixelbuffers", "true"); - addOption("scr", "multisamplesamples", "1"); + addOption("scr", "multisamplesamples", "8"); + addOption("scr", "shaderusage", "auto"); addOption("scr", "gamma", "-1,-1,-1"); addOption("scr", "vsyncmode", "auto"); + addOption("scr", "videoaccel", "true"); addSubsys("aud"); addOption("aud", "channels", "2"); addOption("aud", "samplerate", "44100"); addOption("aud", "outputbuffersamples", "1024"); + addSubsys("gesture"); + addOption("gesture", "maxtapdist", "15"); + addOption("gesture", "maxdoubletaptime", "300"); + addOption("gesture", "minswipedist", "50"); + addOption("gesture", "swipedirectiontolerance", "0.393"); // pi/8 + addOption("gesture", "maxswipecontactdist", "100"); + addOption("gesture", "holddelay", "500"); + addOption("gesture", "mindragdist", "5"); + addOption("gesture", "filtermincutoff", "0.1"); + addOption("gesture", "filterbeta", "0.03"); + addOption("gesture", "friction", "-1"); + + addSubsys("touch"); + addOption("touch", "area", "0, 0"); + addOption("touch", "offset", "0, 0"); + m_sFName = "avgrc"; loadFile(getGlobalConfigDir()+m_sFName); char * pHome = getenv("HOME"); - if (!pHome) { - AVG_TRACE(Logger::WARNING, "No home directory set."); - } else { + if (pHome) { loadFile(string(pHome)+"/."+m_sFName); } } @@ -131,8 +147,8 @@ const string* ConfigMgr::getOption(const string& sSubsys, } } -bool ConfigMgr::getBoolOption(const std::string& sSubsys, - const std::string& sName, bool bDefault) const +bool ConfigMgr::getBoolOption(const string& sSubsys, + const string& sName, bool bDefault) const { const string * psOption = getOption(sSubsys, sName); if (psOption == 0) { @@ -143,15 +159,14 @@ bool ConfigMgr::getBoolOption(const std::string& sSubsys, } else if (*psOption == "false") { return false; } else { - AVG_TRACE(Logger::ERROR, - m_sFName << ": Unrecognized value for option "<<sName<<": " + AVG_LOG_ERROR(m_sFName << ": Unrecognized value for option " << sName << ": " << *psOption << ". Must be true or false. Aborting."); exit(-1); } } -int ConfigMgr::getIntOption(const std::string& sSubsys, - const std::string& sName, int Default) const +int ConfigMgr::getIntOption(const string& sSubsys, + const string& sName, int Default) const { errno = 0; const string * psOption = getOption(sSubsys, sName); @@ -161,30 +176,57 @@ int ConfigMgr::getIntOption(const std::string& sSubsys, int Result = strtol(psOption->c_str(), 0, 10); int rc = errno; if (rc == EINVAL || rc == ERANGE) { - AVG_TRACE(Logger::ERROR, - m_sFName << ": Unrecognized value for option "<<sName<<": " + AVG_LOG_ERROR(m_sFName << ": Unrecognized value for option "<<sName<<": " << *psOption << ". Must be an integer. Aborting."); exit(-1); } return Result; } -void ConfigMgr::getGammaOption(const std::string& sSubsys, - const std::string& sName, double* Val) const +void ConfigMgr::getGammaOption(const string& sSubsys, + const string& sName, float* Val) const { const string * psOption = getOption(sSubsys, sName); if (psOption == 0) { return; } - int rc = sscanf(psOption->c_str(), "%lf,%lf,%lf", Val, Val+1, Val+2); + int rc = sscanf(psOption->c_str(), "%f,%f,%f", Val, Val+1, Val+2); if (rc < 3) { - AVG_TRACE(Logger::ERROR, - m_sFName << ": Unrecognized value for option "<<sName<<": " + AVG_LOG_ERROR(m_sFName << ": Unrecognized value for option "<<sName<<": " << *psOption << ". Must be three comma-separated numbers. Aborting."); exit(-1); } } +glm::vec2 ConfigMgr::getSizeOption(const string& sSubsys, + const string& sName) const +{ + const string * psOption = getOption(sSubsys, sName); + if (psOption == 0) { + return glm::vec2(0, 0); + } + float val[2]; + int rc = sscanf(psOption->c_str(), "%f,%f", val, val+1); + if (rc < 2) { + AVG_LOG_ERROR(m_sFName << ": Unrecognized value for option " << sName << ": " + << *psOption << ". Must be 2 comma-separated numbers(x, y). Aborting."); + exit(-1); + } + return glm::vec2(val[0], val[1]); +} + +void ConfigMgr::getStringOption(const string& sSubsys, + const string& sName, const string& sDefault, string& sVal) const +{ + const string * psOption = getOption(sSubsys, sName); + if (psOption == 0) { + sVal = sDefault; + } else { + sVal = *psOption; + } +} + + bool ConfigMgr::loadFile(const std::string& sPath) { string sSubsys; @@ -194,8 +236,8 @@ bool ConfigMgr::loadFile(const std::string& sPath) int err = access(sPath.c_str(), R_OK); if (err == -1) { if (errno == EACCES) { - AVG_TRACE(Logger::WARNING, - sPath+": File exists, but process doesn't have read permissions!"); + AVG_LOG_WARNING(sPath+ + ": File exists, but process doesn't have read permissions!"); } return false; } @@ -215,8 +257,7 @@ bool ConfigMgr::loadFile(const std::string& sPath) } xmlNodePtr pRoot = xmlDocGetRootElement(doc); if (xmlStrcmp(pRoot->name, (const xmlChar *)(m_sFName.c_str()))) { - AVG_TRACE(Logger::ERROR, - sPath+": Root node must be <"+m_sFName+">, found " + AVG_LOG_ERROR(sPath+": Root node must be <"+m_sFName+">, found " << pRoot->name << ". Aborting."); exit(255); } @@ -228,8 +269,7 @@ bool ConfigMgr::loadFile(const std::string& sPath) sSubsys = ((const char *)pSubsysNode->name); xmlNodePtr pOptionNode = pSubsysNode->xmlChildrenNode; if (!pOptionNode) { - AVG_TRACE(Logger::ERROR, - sPath << ": Option " << sSubsys + AVG_LOG_ERROR(sPath << ": Option " << sSubsys << " has no value. Ignoring."); } else { ConfigOptionVector& CurSubsys = getSubsys(sSubsys); @@ -249,13 +289,12 @@ bool ConfigMgr::loadFile(const std::string& sPath) } catch (Exception& e) { switch (e.getCode()) { case AVG_ERR_OPTION_SUBSYS_UNKNOWN: - AVG_TRACE(Logger::ERROR, "While parsing " << sPath - << ": Option group " << e.getStr() << " unknown. Aborting."); + AVG_LOG_ERROR("While parsing " << sPath << ": Option group " << + e.getStr() << " unknown. Aborting."); exit(255); case AVG_ERR_OPTION_UNKNOWN: - AVG_TRACE(Logger::ERROR, "While parsing " << sPath - << ": Option " << sSubsys << ":" << e.getStr() - << " unknown. Aborting."); + AVG_LOG_ERROR("While parsing " << sPath << ": Option " << sSubsys << + ":" << e.getStr() << " unknown. Aborting."); exit(255); default: throw; diff --git a/src/base/ConfigMgr.h b/src/base/ConfigMgr.h index 421c399..e2af8f1 100644 --- a/src/base/ConfigMgr.h +++ b/src/base/ConfigMgr.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,8 +23,8 @@ #define _ConfigMgr_H_ #include "../api.h" -#include "CmdLine.h" +#include "GLMHelper.h" #include <libxml/parser.h> #include <string> @@ -49,9 +49,8 @@ public: void addSubsys(const std::string& sName); void addOption(const std::string& sSubsys, const std::string& sName, const std::string& sDefault); - - const ConfigOptionVector* getOptions(const std::string& sSubsys) - const; + + const ConfigOptionVector* getOptions(const std::string& sSubsys) const; const std::string* getOption(const std::string& sSubsys, const std::string& sName) const; bool getBoolOption(const std::string& sSubsys, @@ -59,7 +58,12 @@ public: int getIntOption(const std::string& sSubsys, const std::string& sName, int Default) const; void getGammaOption(const std::string& sSubsys, - const std::string& sName, double* Val) const; + const std::string& sName, float* Val) const; + glm::vec2 getSizeOption(const std::string& sSubsys, + const std::string& sName) const; + void getStringOption(const std::string& sSubsys, + const std::string& sName, const std::string& sDefault, std::string& sVal) + const; void dump() const; diff --git a/src/base/CubicSpline.cpp b/src/base/CubicSpline.cpp index f03f7f5..105563d 100644 --- a/src/base/CubicSpline.cpp +++ b/src/base/CubicSpline.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,6 +21,7 @@ #include "CubicSpline.h" #include "Exception.h" +#include "MathHelper.h" #include <iostream> @@ -28,61 +29,75 @@ using namespace std; namespace avg { -CubicSpline::CubicSpline(const vector<double>& x, const vector<double>& y) - : m_X(x), - m_Y(y) +CubicSpline::CubicSpline(const vector<float>& x, const vector<float>& y, bool bLoop) { AVG_ASSERT(x.size() == y.size()); - // Add fake points before the first and after the last point so all derivatives - // are defined. - double edgeX = 2*m_X[0]-m_X[1]; - double edgeY = 2*m_Y[0]-m_Y[1]; - m_X.insert(m_X.begin(), edgeX); - m_Y.insert(m_Y.begin(), edgeY); + for (unsigned i=0; i<x.size(); ++i) { + m_Pts.push_back(glm::vec2(x[i], y[i])); + } + init(); +} - int len = m_X.size(); - edgeX = 2*m_X[len-1]-m_X[len-2]; - edgeY = 2*m_Y[len-1]-m_Y[len-2]; - m_X.push_back(edgeX); - m_Y.push_back(edgeY); +CubicSpline::CubicSpline(const vector<glm::vec2>& pts, bool bLoop) + : m_Pts(pts) +{ + init(); } CubicSpline::~CubicSpline() { } -double normedInterpolate(double y0, double y1, double y2, double y3, double mu) +float CubicSpline::interpolate(float orig) { - double mu2 = mu*mu; - double a0 = y3 - y2 - y0 + y1; - double a1 = y0 - y1 - a0; - double a2 = y2 - y0; - double a3 = y1; - - return(a0*mu*mu2+a1*mu2+a2*mu+a3); + int len = m_Pts.size(); + int low = 0; + int high = len-1; + // Binary search. + while (high - low > 1) { + int avg = (high+low) / 2; + if (m_Pts[avg].x > orig) { + high = avg; + } else { + low = avg; + } + } + float h = m_Pts[high].x - m_Pts[low].x; + float a = (m_Pts[high].x-orig)/h; + float b = (orig-m_Pts[low].x)/h; + + float y = a*m_Pts[low].y + b*m_Pts[high].y + + ((a*a*a-a)*m_Y2[low] + (b*b*b-b)*m_Y2[high])*(h*h)/6.f; + return y; } - -double CubicSpline::interpolate(double orig) +void CubicSpline::init() { - unsigned i = 0; - if (m_X[m_X.size()-1] <= orig) { - i = m_X.size(); - } else { - while (m_X[i] < orig) { - i++; + int len = m_Pts.size(); + for (int i=1; i<len; ++i) { + if (m_Pts[i].x <= m_Pts[i-1].x) { + throw Exception(AVG_ERR_INVALID_ARGS, + "CubicSplines must have increasing x coordinates."); } } - if (i < 2) { - double dxdy = (m_X[1]-m_X[0])/(m_Y[1]-m_Y[0]); - return m_Y[1]+(orig-m_X[1])/dxdy; - } else if (i > m_X.size()-2) { - unsigned len = m_X.size(); - double dxdy = (m_X[len-1]-m_X[len-2])/(m_Y[len-1]-m_Y[len-2]); - return m_Y[len-2]+(orig-m_X[len-2])/dxdy; - } else { - double ratio = (orig-m_X[i-1])/(m_X[i]-m_X[i-1]); - return normedInterpolate(m_Y[i-2], m_Y[i-1], m_Y[i], m_Y[i+1], ratio); + vector<float> u(len-1,0); + m_Y2.push_back(0.f); + u[0] = 0.f; + for (int i=1; i<len-1; ++i) { + float sig = (m_Pts[i].x-m_Pts[i-1].x) / (m_Pts[i+1].x-m_Pts[i-1].x); + float p = sig * m_Y2[i-1]+2.0f; + m_Y2.push_back((sig-1.0f)/p); + u[i] = (m_Pts[i+1].y-m_Pts[i].y) / (m_Pts[i+1].x-m_Pts[i].x) - + (m_Pts[i].y - m_Pts[i-1].y) / (m_Pts[i].x-m_Pts[i-1].x); + u[i] = (6.f*u[i]/(m_Pts[i+1].x-m_Pts[i-1].x) - sig*u[i-1]) / p; + } + float qn = 0.f; + float un = 0.f; + + m_Y2.push_back((un-qn*u[len-2]) / (qn*m_Y2[len-2]-1.0f)); + + for (int i=len-2; i>=0; i--) { + m_Y2[i] = m_Y2[i]*m_Y2[i+1]+u[i]; } } diff --git a/src/base/CubicSpline.h b/src/base/CubicSpline.h index 276f41c..a275413 100644 --- a/src/base/CubicSpline.h +++ b/src/base/CubicSpline.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,6 +23,8 @@ #define _CubicSpline_H_ #include "../api.h" +#include "../glm/glm.hpp" + #include <boost/shared_ptr.hpp> #include <vector> @@ -30,14 +32,18 @@ namespace avg { class AVG_API CubicSpline { public: - CubicSpline(const std::vector<double>& x, const std::vector<double>& y); + CubicSpline(const std::vector<float>& x, const std::vector<float>& y, + bool bLoop=false); + CubicSpline(const std::vector<glm::vec2>& pts, bool bLoop=false); virtual ~CubicSpline(); - double interpolate(double orig); + float interpolate(float orig); private: - std::vector<double> m_X; - std::vector<double> m_Y; + void init(); + + std::vector<glm::vec2> m_Pts; + std::vector<float> m_Y2; // Second derivatives }; typedef boost::shared_ptr<CubicSpline> CubicSplinePtr; diff --git a/src/base/DAG.cpp b/src/base/DAG.cpp new file mode 100644 index 0000000..85ab8bb --- /dev/null +++ b/src/base/DAG.cpp @@ -0,0 +1,130 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "DAG.h" + +#include "Exception.h" + +#include <boost/enable_shared_from_this.hpp> + +using namespace std; + +namespace avg { + +class AVG_API DAGNode: public boost::enable_shared_from_this<DAGNode> +{ +public: + DAGNode(long vertexID, const std::set<long>& outgoingIDs); + void resolveIDs(DAG* pDAG); + + long m_VertexID; + std::set<long> m_OutgoingIDs; + std::set<DAGNodePtr> m_pOutgoingNodes; + std::set<DAGNodePtr> m_pIncomingNodes; +}; + + +DAGNode::DAGNode(long vertexID, const set<long>& outgoingIDs) +{ + m_VertexID = vertexID; + m_OutgoingIDs = outgoingIDs; +} + +void DAGNode::resolveIDs(DAG* pDAG) +{ + set<long>::iterator it; + for (it=m_OutgoingIDs.begin(); it!=m_OutgoingIDs.end(); ++it) { + long outgoingID = *it; + DAGNodePtr pDestNode = pDAG->findNode(outgoingID); + m_pOutgoingNodes.insert(pDestNode); + pDestNode->m_pIncomingNodes.insert(shared_from_this()); + } + m_OutgoingIDs.clear(); +} + + +DAG::DAG() +{ +} + +DAG::~DAG() +{ +} + +void DAG::addNode(long vertexID, const set<long>& outgoingIDs) +{ + DAGNode* pNode = new DAGNode(vertexID, outgoingIDs); + m_pNodes.insert(DAGNodePtr(pNode)); +} + +void DAG::sort(vector<long>& pResults) +{ + resolveIDs(); + while (!m_pNodes.empty()) { + DAGNodePtr pCurNode = findStartNode(*m_pNodes.begin()); + removeNode(pCurNode); + pResults.push_back(pCurNode->m_VertexID); + } +} + +void DAG::resolveIDs() +{ + set<DAGNodePtr>::iterator it; + for (it=m_pNodes.begin(); it!=m_pNodes.end(); ++it) { + (*it)->resolveIDs(this); + } +} + +DAGNodePtr DAG::findNode(long id) +{ + set<DAGNodePtr>::iterator it; + for (it=m_pNodes.begin(); it!=m_pNodes.end(); ++it) { + if ((*it)->m_VertexID == id) { + return (*it); + } + } + AVG_ASSERT(false); + return DAGNodePtr(); +} + +void DAG::removeNode(DAGNodePtr pNode) +{ + set<DAGNodePtr>::iterator it; + for (it=pNode->m_pOutgoingNodes.begin(); it!=pNode->m_pOutgoingNodes.end(); ++it) { + DAGNodePtr pDestNode = *it; + pDestNode->m_pIncomingNodes.erase(pNode); + } + m_pNodes.erase(pNode); +} + +DAGNodePtr DAG::findStartNode(DAGNodePtr pNode, unsigned depth) +{ + if (pNode->m_pIncomingNodes.empty()) { + return pNode; + } else { + if (depth > m_pNodes.size()) { + throw Exception(AVG_ERR_INVALID_ARGS, "cyclic graph"); + } + return findStartNode(*pNode->m_pIncomingNodes.begin(), depth+1); + } +} + +} diff --git a/src/base/Triple.h b/src/base/DAG.h index 879a809..929ecd2 100644 --- a/src/base/Triple.h +++ b/src/base/DAG.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -19,48 +19,46 @@ // Current versions can be found at www.libavg.de // -#ifndef _Triple_H_ -#define _Triple_H_ +#ifndef _DAG_H_ +#define _DAG_H_ #include "../api.h" -#include <ostream> -#include <istream> +#include <set> #include <vector> - -// Fix for non-C99 win compilers up to MSVC++2008 -#if defined _MSC_VER && _MSC_VER <= 1500 -#define isinf(x) (!_finite(x)) -#define isnan(x) (_isnan(x)) -#endif +#include <boost/shared_ptr.hpp> namespace avg { -template<class NUM> -class AVG_TEMPLATE_API Triple +class DAG; +class DAGNode; +typedef boost::shared_ptr<DAGNode> DAGNodePtr; + +// Directed Acyclic Graph class. +// Only useful for sorting. The process of sorting destroys the DAG. +class AVG_API DAG { public: - NUM x; - NUM y; - NUM z; + DAG(); + virtual ~DAG(); - Triple(); - Triple(NUM X, NUM Y, NUM Z); - Triple(const Triple<NUM> & p); - Triple(const std::vector<NUM>& v); - ~Triple(); - -}; + void addNode(long vertexID, const std::set<long>& outgoingIDs); + void sort(std::vector<long>& pResults); -template<class NUM> -std::ostream& operator<<(std::ostream& os, const Triple<NUM> &p); +private: + friend class DAGNode; -template<class NUM> -std::istream& operator>>(std::istream& is, Triple<NUM>& p); + void resolveIDs(); + DAGNodePtr findNode(long pID); + void removeNode(DAGNodePtr pNode); + DAGNodePtr findStartNode(DAGNodePtr pNode, unsigned depth=0); -typedef Triple<double> DTriple; -typedef Triple<int> IntTriple; + std::set<DAGNodePtr> m_pNodes; +}; } -#endif +#endif + + + diff --git a/src/base/DirEntry.cpp b/src/base/DirEntry.cpp index 7da4edb..c654e50 100644 --- a/src/base/DirEntry.cpp +++ b/src/base/DirEntry.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/DirEntry.h b/src/base/DirEntry.h index d23388d..ac2fca9 100644 --- a/src/base/DirEntry.h +++ b/src/base/DirEntry.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/Directory.cpp b/src/base/Directory.cpp index dda1e8d..bc40ecc 100644 --- a/src/base/Directory.cpp +++ b/src/base/Directory.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/Directory.h b/src/base/Directory.h index 1edb139..f75107d 100644 --- a/src/base/Directory.h +++ b/src/base/Directory.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/DlfcnWrapper.cpp b/src/base/DlfcnWrapper.cpp index 8dfbfbc..f8011b1 100644 --- a/src/base/DlfcnWrapper.cpp +++ b/src/base/DlfcnWrapper.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/DlfcnWrapper.h b/src/base/DlfcnWrapper.h index 4cc0e98..883fb37 100644 --- a/src/base/DlfcnWrapper.h +++ b/src/base/DlfcnWrapper.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/Exception.cpp b/src/base/Exception.cpp index e694320..eb4f03c 100644 --- a/src/base/Exception.cpp +++ b/src/base/Exception.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -27,23 +27,29 @@ #include <cstdlib> #include <sstream> +#ifdef WIN32 +#include <intrin.h> +#endif + using namespace std; namespace avg { Exception::Exception(int code, const string& sErr) - : m_Code (code), + : std::exception(), + m_Code (code), m_sErr (sErr) { } Exception::Exception(const Exception& ex) - : m_Code (ex.getCode()), + : std::exception(), + m_Code (ex.getCode()), m_sErr (ex.getStr()) { } -Exception::~Exception() +Exception::~Exception() throw() { } @@ -57,23 +63,17 @@ const string& Exception::getStr() const return m_sErr; } -void fatalError(const string& sMsg) +const char* Exception::what() const throw() { - AVG_TRACE(Logger::ERROR, "Internal error: "+sMsg+" Aborting."); - exit(-1); + return m_sErr.c_str(); } void debugBreak() { #ifdef _WIN32 - __asm int 3; -#elseifdef __x86_64 - asm("int $3"); -#elseifdef __i386__ - asm("int $3"); + __debugbreak(); #else - //deliberately dereferencing a null pointer should break in most debuggers - *((char *)0) = 0; + __builtin_trap(); #endif } diff --git a/src/base/Exception.h b/src/base/Exception.h index 1524cb5..b28dc1a 100644 --- a/src/base/Exception.h +++ b/src/base/Exception.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,7 @@ #include "../api.h" #include <string> +#include <exception> #define AVG_ERR_UNKNOWN -1 #define AVG_ERR_XML_PARSE 1 @@ -57,24 +58,25 @@ #define AVG_ERR_DEPRECATED 31 #define AVG_ERR_ASSERT_FAILED 32 #define AVG_ERR_MT_INIT 33 +#define AVG_ERR_DEBUG_CONTEXT_FAILED 34 namespace avg { -class AVG_API Exception +class AVG_API Exception: public std::exception { public: Exception(int code, const std::string& sErr = ""); Exception(const Exception& ex); - virtual ~Exception(); + virtual ~Exception() throw(); virtual int getCode() const; virtual const std::string& getStr() const; + virtual const char* what() const throw(); private: int m_Code; std::string m_sErr; }; -void AVG_API fatalError(const std::string& sMsg); void AVG_API debugBreak(); void AVG_API avgAssert(bool b, const char * pszFile, int line, const char * pszReason=0); diff --git a/src/base/FileHelper.cpp b/src/base/FileHelper.cpp index 9e38e51..d9221c4 100644 --- a/src/base/FileHelper.cpp +++ b/src/base/FileHelper.cpp @@ -1,6 +1,6 @@ // -// libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -20,7 +20,6 @@ // #include "FileHelper.h" -#include "ConfigMgr.h" #include "Exception.h" #ifndef _WIN32 @@ -32,7 +31,9 @@ #include <sys/stat.h> #include <string.h> #include <unistd.h> +#include <stdlib.h> +#include <vector> #include <map> #include <cstring> #include <iostream> @@ -113,7 +114,7 @@ bool isAbsPath(const std::string& path) #else return path[0] == '/'; #endif - + } bool fileExists(const string& sFilename) @@ -155,7 +156,7 @@ void writeWholeFile(const string& sFilename, const string& sContent) void copyFile(const string& sSourceFile, const string& sDestFile) { string sData; - + readWholeFile(sSourceFile, sData); writeWholeFile(sDestFile, sData); } diff --git a/src/base/FileHelper.h b/src/base/FileHelper.h index c5724f5..f367d0b 100644 --- a/src/base/FileHelper.h +++ b/src/base/FileHelper.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -27,20 +27,20 @@ namespace avg { -std::string getPath(const std::string& sFilename); -std::string getFilenamePart(const std::string& sFilename); -std::string getExtension(const std::string& sFilename); -std::string getCWD(); +std::string AVG_API getPath(const std::string& sFilename); +std::string AVG_API getFilenamePart(const std::string& sFilename); +std::string AVG_API getExtension(const std::string& sFilename); +std::string AVG_API getCWD(); -bool isAbsPath(const std::string& path); +bool AVG_API isAbsPath(const std::string& path); -bool fileExists(const std::string& sFilename); +bool AVG_API fileExists(const std::string& sFilename); -void readWholeFile(const std::string& sFilename, std::string& sContents); +void AVG_API readWholeFile(const std::string& sFilename, std::string& sContents); -void writeWholeFile(const std::string& sFilename, const std::string& sContent); +void AVG_API writeWholeFile(const std::string& sFilename, const std::string& sContent); -void copyFile(const std::string& sSourceFile, const std::string& sDestFile); +void AVG_API copyFile(const std::string& sSourceFile, const std::string& sDestFile); #ifdef WIN32 diff --git a/src/base/GLMHelper.cpp b/src/base/GLMHelper.cpp new file mode 100644 index 0000000..e4b0f43 --- /dev/null +++ b/src/base/GLMHelper.cpp @@ -0,0 +1,183 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "GLMHelper.h" +#include "StringHelper.h" +#include "MathHelper.h" + +#include "../glm/gtx/rotate_vector.hpp" + +using namespace std; + +namespace avg { + +glm::vec2 getRotated(const glm::vec2& vec, float angle) +{ + return glm::rotate(vec, angle*180/PI); +} + +glm::vec2 getRotatedPivot(const glm::vec2& vec, float angle, const glm::vec2& pivot) +{ + // translate pivot to origin + glm::vec2 translated = vec - pivot; + + // calculate rotated coordinates about the origin + glm::vec2 rotated = glm::rotate(translated, angle*180/PI); + + // re-translate pivot to original position + rotated += pivot; + + return rotated; +} + +float getAngle(const glm::vec2& vec) +{ + return float(atan2(double(vec.y), double(vec.x))); +} + +glm::vec2 fromPolar(float angle, float radius) +{ + return glm::vec2(cos(angle)*radius, sin(angle)*radius); +} + +template<class NUM> +bool almostEqual(const glm::detail::tvec2<NUM>& v1, const glm::detail::tvec2<NUM>& v2) +{ + return (fabs(v1.x-v2.x)+fabs(v1.y-v2.y)) < 0.0001; +} + +template<class NUM> +bool almostEqual(const glm::detail::tvec4<NUM>& v1, const glm::detail::tvec4<NUM>& v2) +{ + return (fabs(v1.x-v2.x)+fabs(v1.y-v2.y)+fabs(v1.z-v2.z)+fabs(v1.w-v2.w)) < 0.0001; +} + +template<class NUM> +std::ostream& operator<<( std::ostream& os, const glm::detail::tvec2<NUM> &v) +{ + os << "(" << v.x << "," << v.y << ")"; + return os; +} + +template<class NUM> +std::ostream& operator<<( std::ostream& os, const glm::detail::tvec3<NUM> &v) +{ + os << "(" << v.x << "," << v.y << "," << v.z << ")"; + return os; +} + +template<class NUM> +std::ostream& operator<<( std::ostream& os, const glm::detail::tvec4<NUM> &v) +{ + os << "(" << v.x << "," << v.y << "," << v.z << ", " << v.a << ")"; + return os; +} + +template<class NUM> +std::ostream& operator<<( std::ostream& os, const glm::detail::tmat4x4<NUM> &m) +{ + os << "(" << m[0] << ", " << endl << + m[1] << ", " << endl << + m[2] << ", " << endl << + m[3] << ", " << endl << ")"; + return os; +} + +template<class NUM> +std::istream& operator>>(std::istream& is, glm::detail::tvec2<NUM>& p) +{ + skipToken(is, '('); + is >> p.x; + skipToken(is, ','); + is >> p.y; + skipToken(is, ')'); + return is; +} + +template<class NUM> +std::istream& operator>>(std::istream& is, glm::detail::tvec3<NUM>& p) +{ + skipToken(is, '('); + is >> p.x; + skipToken(is, ','); + is >> p.y; + skipToken(is, ','); + is >> p.z; + skipToken(is, ')'); + return is; +} + +glm::vec2 stringToVec2(const std::string& s) +{ + glm::vec2 pt; + fromString(s, pt); + return pt; +} + +glm::vec3 stringToVec3(const std::string& s) +{ + glm::vec3 pt; + fromString(s, pt); + return pt; +} + +glm::ivec3 stringToIVec3(const std::string& s) +{ + glm::ivec3 pt; + fromString(s, pt); + return pt; +} + + +template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec2<int> &p); +template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec2<float> &p); +template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec2<double> &p); + +template AVG_TEMPLATE_API std::istream& operator>>(std::istream& is, glm::detail::tvec2<int>& p); +template AVG_TEMPLATE_API std::istream& operator>>(std::istream& is, glm::detail::tvec2<float>& p); +template AVG_TEMPLATE_API std::istream& operator>>(std::istream& is, glm::detail::tvec2<double>& p); + +template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec3<int> &p); +template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec3<float> &p); +template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec3<double> &p); + +template AVG_TEMPLATE_API std::istream& operator>>(std::istream& is, glm::detail::tvec3<int>& p); +template AVG_TEMPLATE_API std::istream& operator>>(std::istream& is, glm::detail::tvec3<float>& p); +template AVG_TEMPLATE_API std::istream& operator>>(std::istream& is, glm::detail::tvec3<double>& p); + +template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec4<int> &p); +template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec4<float> &p); +template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec4<double> &p); + +template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tmat4x4<float> &p); +template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, + const glm::detail::tmat4x4<double> &p); + +template AVG_TEMPLATE_API bool almostEqual(const glm::detail::tvec2<float>& v1, + const glm::detail::tvec2<float>& v2); +template AVG_TEMPLATE_API bool almostEqual(const glm::detail::tvec2<double>& v1, + const glm::detail::tvec2<double>& v2); +template AVG_TEMPLATE_API bool almostEqual(const glm::detail::tvec4<float>& v1, + const glm::detail::tvec4<float>& v2); +template AVG_TEMPLATE_API bool almostEqual(const glm::detail::tvec4<double>& v1, + const glm::detail::tvec4<double>& v2); +} + diff --git a/src/base/GLMHelper.h b/src/base/GLMHelper.h new file mode 100644 index 0000000..4af8991 --- /dev/null +++ b/src/base/GLMHelper.h @@ -0,0 +1,70 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _GLMHelper_H_ +#define _GLMHelper_H_ + +#include "../api.h" + +#include "../glm/glm.hpp" +#include "../glm/gtc/matrix_transform.hpp" +#include "../glm/gtc/type_ptr.hpp" + +#include <iostream> +#include <vector> + +namespace avg { + +glm::vec2 getRotated(const glm::vec2& vec, float angle); +glm::vec2 getRotatedPivot(const glm::vec2& vec, float angle, + const glm::vec2& pivot=glm::vec2(0,0)); +float getAngle(const glm::vec2& vec); +glm::vec2 fromPolar(float angle, float radius); + +template<class NUM> +bool almostEqual(const glm::detail::tvec2<NUM>& v1, const glm::detail::tvec2<NUM>& v2); +template<class NUM> +bool almostEqual(const glm::detail::tvec4<NUM>& v1, const glm::detail::tvec4<NUM>& v2); + +template<class NUM> +std::ostream& operator<<(std::ostream& os, const glm::detail::tvec2<NUM> &v); +template<class NUM> +std::ostream& operator<<(std::ostream& os, const glm::detail::tvec3<NUM> &v); +template<class NUM> +std::ostream& operator<<(std::ostream& os, const glm::detail::tvec4<NUM> &v); +template<class NUM> +std::ostream& operator<<(std::ostream& os, const glm::detail::tmat4x4<NUM> &v); + +template<class NUM> +std::istream& operator>>(std::istream& is, glm::detail::tvec2<NUM>& p); +template<class NUM> +std::istream& operator>>(std::istream& is, glm::detail::tvec3<NUM>& p); + +typedef glm::ivec2 IntPoint; +typedef std::vector<glm::vec2> Vec2Vector; + +glm::vec2 stringToVec2(const std::string& s); +glm::vec3 stringToVec3(const std::string& s); +glm::ivec3 stringToIVec3(const std::string& s); + +} + +#endif diff --git a/src/base/GeomHelper.cpp b/src/base/GeomHelper.cpp index c1fa7a8..da167ad 100644 --- a/src/base/GeomHelper.cpp +++ b/src/base/GeomHelper.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -28,31 +28,31 @@ using namespace std; namespace avg { -DLineSegment::DLineSegment(const DPoint& pt0, const DPoint& pt1) +LineSegment::LineSegment(const glm::vec2& pt0, const glm::vec2& pt1) : p0(pt0), p1(pt1) { } -bool DLineSegment::isPointOver(const DPoint& pt) +bool LineSegment::isPointOver(const glm::vec2& pt) { - DPoint c = pt - p0; // DPoint from a to Point - DPoint v = (p1 - p0); - double d = v.getNorm(); // Length of the line segment - v /= d; // Unit DPoint from a to b - double t = dotProduct(v, c); // Intersection point Distance from a + glm::vec2 c = pt - p0; + glm::vec2 v = (p1 - p0); + float d = glm::length(v); + v /= d; + float t = glm::dot(v, c); return (t >= 0 && t <= d); } // Code adapted from Antonio, Franklin, "Faster Line Segment Intersection," // Graphics Gems III (David Kirk, ed.), Academic Press, pp. 199-202, 1992. -bool lineSegmentsIntersect(const DLineSegment& l0, const DLineSegment& l1) +bool lineSegmentsIntersect(const LineSegment& l0, const LineSegment& l1) { - double xdiff0 = l0.p1.x-l0.p0.x; - double xdiff1 = l1.p0.x-l1.p1.x; + float xdiff0 = l0.p1.x-l0.p0.x; + float xdiff1 = l1.p0.x-l1.p1.x; - double x1lo, x1hi; + float x1lo, x1hi; /* X bound box test*/ if (xdiff0 < 0) { @@ -72,10 +72,10 @@ bool lineSegmentsIntersect(const DLineSegment& l0, const DLineSegment& l1) } } - double ydiff0 = l0.p1.y-l0.p0.y; - double ydiff1 = l1.p0.y-l1.p1.y; + float ydiff0 = l0.p1.y-l0.p0.y; + float ydiff1 = l1.p0.y-l1.p1.y; - double y1lo, y1hi; + float y1lo, y1hi; /* Y bound box test*/ if (ydiff0 < 0) { @@ -95,10 +95,10 @@ bool lineSegmentsIntersect(const DLineSegment& l0, const DLineSegment& l1) } } - double Cx = l0.p0.x-l1.p0.x; - double Cy = l0.p0.y-l1.p0.y; - double d = ydiff1*Cx - xdiff1*Cy; /* alpha numerator*/ - double f = ydiff0*xdiff1 - xdiff0*ydiff1; /* both denominator*/ + float Cx = l0.p0.x-l1.p0.x; + float Cy = l0.p0.y-l1.p0.y; + float d = ydiff1*Cx - xdiff1*Cy; /* alpha numerator*/ + float f = ydiff0*xdiff1 - xdiff0*ydiff1; /* both denominator*/ if (f > 0) { /* alpha tests*/ if (d < 0 || d > f) { return false; @@ -109,7 +109,7 @@ bool lineSegmentsIntersect(const DLineSegment& l0, const DLineSegment& l1) } } - double e = xdiff0*Cy - ydiff0*Cx; /* beta numerator*/ + float e = xdiff0*Cy - ydiff0*Cx; /* beta numerator*/ if(f > 0) { /* beta tests*/ if (e < 0 || e > f) { return false; @@ -127,7 +127,7 @@ bool lineSegmentsIntersect(const DLineSegment& l0, const DLineSegment& l1) } // /*compute intersection coordinates*/ -// double num = d*xdiff0; /* numerator */ +// float num = d*xdiff0; /* numerator */ // offset = SAME_SIGNS(num,f) ? f/2 : -f/2; /* round direction*/ // *x = x1 + (num+offset) / f; /* intersection x */ // @@ -142,7 +142,7 @@ bool lineSegmentsIntersect(const DLineSegment& l0, const DLineSegment& l1) // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html. // Precomputing a bounding box for the polygon would speed this up a lot, // but the function hasn't shown up on any profiles so far. -bool pointInPolygon(const DPoint& pt, const vector<DPoint>& poly) +bool pointInPolygon(const glm::vec2& pt, const vector<glm::vec2>& poly) { if (poly.size() < 3) { return false; @@ -159,16 +159,16 @@ bool pointInPolygon(const DPoint& pt, const vector<DPoint>& poly) return bPtInPoly; } -DPoint getLineLineIntersection(const DPoint& p1, const DPoint& v1, const DPoint& p2, - const DPoint& v2) +glm::vec2 getLineLineIntersection(const glm::vec2& p1, const glm::vec2& v1, + const glm::vec2& p2, const glm::vec2& v2) { - double denom = v2.y*v1.x-v2.x*v1.y; + float denom = v2.y*v1.x-v2.x*v1.y; if (fabs(denom) < 0.0000001) { // If the lines are parallel or coincident, we just return p2! return p2; } - double numer = v2.x*(p1.y-p2.y) - v2.y*(p1.x-p2.x); - double ua = numer/denom; + float numer = v2.x*(p1.y-p2.y) - v2.y*(p1.x-p2.x); + float ua = numer/denom; return p1+ua*v1; diff --git a/src/base/GeomHelper.h b/src/base/GeomHelper.h index 272a8ef..5774231 100644 --- a/src/base/GeomHelper.h +++ b/src/base/GeomHelper.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,27 +23,28 @@ #define _GeomHelper_H_ #include "../api.h" -#include "Point.h" + +#include "../glm/glm.hpp" #include <vector> namespace avg { -struct AVG_API DLineSegment { +struct AVG_API LineSegment { public: - DLineSegment(const DPoint& pt0, const DPoint& pt1); - DPoint p0; - DPoint p1; + LineSegment(const glm::vec2& pt0, const glm::vec2& pt1); + glm::vec2 p0; + glm::vec2 p1; - bool isPointOver(const DPoint& pt); + bool isPointOver(const glm::vec2& pt); }; -bool AVG_API lineSegmentsIntersect(const DLineSegment& l0, const DLineSegment& l1); +bool AVG_API lineSegmentsIntersect(const LineSegment& l0, const LineSegment& l1); -bool AVG_API pointInPolygon(const DPoint& pt, const std::vector<DPoint>& poly); +bool AVG_API pointInPolygon(const glm::vec2& pt, const std::vector<glm::vec2>& poly); -DPoint AVG_API getLineLineIntersection(const DPoint& p1, const DPoint& v1, const DPoint& p2, - const DPoint& v2); +glm::vec2 AVG_API getLineLineIntersection(const glm::vec2& p1, const glm::vec2& v1, + const glm::vec2& p2, const glm::vec2& v2); } #endif diff --git a/src/base/IFrameEndListener.h b/src/base/IFrameEndListener.h index 5f172d2..6147dbe 100644 --- a/src/base/IFrameEndListener.h +++ b/src/base/IFrameEndListener.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/Matrix3x4.h b/src/base/ILogSink.h index 62a0222..de4c1da 100644 --- a/src/base/Matrix3x4.h +++ b/src/base/ILogSink.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -17,39 +17,36 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // Current versions can be found at www.libavg.de -// -#ifndef _Matrix3x4_H_ -#define _Matrix3x4_H_ +#ifndef _ILOGHANDLER_H_ +#define _ILOGHANDLER_H_ + +#include "UTF8String.h" + +#ifdef _WIN32 +#include <time.h> +#else +#include <sys/time.h> +#endif -#include "../api.h" +#include <boost/shared_ptr.hpp> -#include "Triple.h" +using namespace std; -#include <iostream> +namespace avg{ -namespace avg { - -class AVG_API Matrix3x4 { +typedef unsigned severity_t; +typedef UTF8String category_t; + +class AVG_API ILogSink +{ public: - float val[3][4]; - - Matrix3x4(); - Matrix3x4(const float *); - static Matrix3x4 createTranslate(float x, float y, float z); - static Matrix3x4 createTranslate(const DTriple& tr); - static Matrix3x4 createScale(float x, float y, float z); - static Matrix3x4 createScale(const DTriple& tr); + virtual void logMessage(const tm* pTime, unsigned millis, const category_t& category, + severity_t severity, const UTF8String& sMsg) = 0; - const Matrix3x4& operator *=(const Matrix3x4& mat); - -private: - void setIdent(); }; -bool almostEqual(const Matrix3x4& mat1, const Matrix3x4& mat2); - -std::ostream& operator<<(std::ostream& os, const Matrix3x4& mat); +typedef boost::shared_ptr<ILogSink> LogSinkPtr; } diff --git a/src/base/IPlaybackEndListener.h b/src/base/IPlaybackEndListener.h index 08d8c41..f505177 100644 --- a/src/base/IPlaybackEndListener.h +++ b/src/base/IPlaybackEndListener.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/IPreRenderListener.h b/src/base/IPreRenderListener.h index 5fe4d82..32c244e 100644 --- a/src/base/IPreRenderListener.h +++ b/src/base/IPreRenderListener.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/Logger.cpp b/src/base/Logger.cpp index 286f76c..dd7efe1 100644 --- a/src/base/Logger.cpp +++ b/src/base/Logger.cpp @@ -1,6 +1,6 @@ // -// libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -20,77 +20,104 @@ // #include "Logger.h" - -#include "OSHelper.h" #include "Exception.h" +#include "StandardLogSink.h" +#include "OSHelper.h" + +#include <boost/algorithm/string.hpp> #ifdef _WIN32 #include <Winsock2.h> -#undef ERROR -#undef WARNING #include <time.h> #include <Mmsystem.h> +#undef ERROR #else #include <sys/time.h> #include <syslog.h> #endif #include <iostream> #include <iomanip> -#include <boost/thread.hpp> using namespace std; +namespace ba = boost::algorithm; namespace avg { + const severity_t Logger::severity::CRITICAL = 50; + const severity_t Logger::severity::ERROR = 40; + const severity_t Logger::severity::WARNING = 30; + const severity_t Logger::severity::INFO = 20; + const severity_t Logger::severity::DEBUG = 10; + const severity_t Logger::severity::NONE = 0; -const long Logger::NONE=0; -const long Logger::BLTS=1; -const long Logger::PROFILE=2; -const long Logger::PROFILE_LATEFRAMES=4; -const long Logger::PROFILE_VIDEO=8; -const long Logger::EVENTS=16; -const long Logger::EVENTS2=32; -const long Logger::CONFIG=64; -const long Logger::WARNING=128; -const long Logger::ERROR=256; -const long Logger::MEMORY=512; -const long Logger::APP=1024; -const long Logger::PLUGIN=2048; -const long Logger::PLAYER=4096; - -Logger* Logger::m_pLogger = 0; -boost::mutex log_Mutex; + const category_t Logger::category::NONE = UTF8String("NONE"); + const category_t Logger::category::PROFILE = UTF8String("PROFILE"); + const category_t Logger::category::PROFILE_VIDEO = UTF8String("PROFILE_V"); + const category_t Logger::category::EVENTS = UTF8String("EVENTS"); + const category_t Logger::category::CONFIG = UTF8String("CONFIG"); + const category_t Logger::category::MEMORY = UTF8String("MEMORY"); + const category_t Logger::category::APP = UTF8String("APP"); + const category_t Logger::category::PLUGIN = UTF8String("PLUGIN"); + const category_t Logger::category::PLAYER = UTF8String("PLAYER"); + const category_t Logger::category::SHADER = UTF8String("SHADER"); + const category_t Logger::category::DEPRECATION = UTF8String("DEPREC"); + +namespace { + Logger* s_pLogger = 0; + boost::mutex s_logMutex; + boost::mutex s_traceMutex; + boost::mutex s_sinkMutex; + boost::mutex s_removeStdSinkMutex; +} + +boost::mutex Logger::m_CategoryMutex; Logger * Logger::get() { - - if (!m_pLogger) { - boost::mutex::scoped_lock Lock(log_Mutex); - m_pLogger = new Logger; + lock_guard lock(s_logMutex); + if (!s_pLogger) { + s_pLogger = new Logger; } - return m_pLogger; + return s_pLogger; } Logger::Logger() { - m_Flags = ERROR | WARNING | APP; + m_Severity = severity::WARNING; + string sEnvSeverity; + bool bEnvSeveritySet = getEnv("AVG_LOG_SEVERITY", sEnvSeverity); + if(bEnvSeveritySet) { + m_Severity = Logger::stringToSeverity(sEnvSeverity); + } + setupCategory(); + string sEnvCategories; bool bEnvSet = getEnv("AVG_LOG_CATEGORIES", sEnvCategories); if (bEnvSet) { - m_Flags = ERROR | APP; - bool bDone = false; - string sCategory; - do { - string::size_type pos = sEnvCategories.find(":"); - if (pos == string::npos) { - sCategory = sEnvCategories; - bDone = true; + vector<string> sCategories; + ba::split(sCategories, sEnvCategories, ba::is_any_of(" "), ba::token_compress_on); + vector<string>::iterator it; + for(it=sCategories.begin(); it!=sCategories.end(); it++) { + string::size_type pos = (*it).find(":"); + string sCategory; + string sSeverity = "NONE"; + if(pos == string::npos) { + sCategory = *it; } else { - sCategory = sEnvCategories.substr(0, pos); - sEnvCategories = sEnvCategories.substr(pos+1); + vector<string> tmpValues; + ba::split( tmpValues, *it, ba::is_any_of(":"), ba::token_compress_on); + sCategory = tmpValues.at(0); + sSeverity = tmpValues.at(1); } - long category = stringToCategory(sCategory); - m_Flags |= category; - } while (!bDone); + severity_t severity = stringToSeverity(sSeverity); + configureCategory(sCategory, severity); + } + } + + string sDummy; + bool bEnvOmitStdErr = getEnv("AVG_LOG_OMIT_STDERR", sDummy); + if (!bEnvOmitStdErr) { + m_pStdSink = LogSinkPtr(new StandardLogSink); + addLogSink(m_pStdSink); } } @@ -98,116 +125,156 @@ Logger::~Logger() { } -void Logger::setCategories(int flags) +void Logger::addLogSink(const LogSinkPtr& logSink) { - boost::mutex::scoped_lock Lock(log_Mutex); - m_Flags = flags | ERROR | WARNING; + lock_guard lock(s_sinkMutex); + m_pSinks.push_back(logSink); } - -void Logger::pushCategories() + +void Logger::removeLogSink(const LogSinkPtr& logSink) { - m_FlagStack.push_back(m_Flags); + lock_guard lock(s_sinkMutex); + std::vector<LogSinkPtr>::iterator it; + it = find(m_pSinks.begin(), m_pSinks.end(), logSink); + if ( it != m_pSinks.end() ) { + m_pSinks.erase(it); + } } -void Logger::popCategories() +void Logger::removeStdLogSink() { - if (m_FlagStack.empty()) { - throw Exception(AVG_ERR_OUT_OF_RANGE, "popCategories: Nothing to pop."); + lock_guard lock(s_removeStdSinkMutex); + if ( m_pStdSink.get()) { + removeLogSink(m_pStdSink); + m_pStdSink = LogSinkPtr(); } - m_Flags = m_FlagStack.back(); - m_FlagStack.pop_back(); } -void Logger::trace(int category, const UTF8String& sMsg) +category_t Logger::configureCategory(category_t category, severity_t severity) { - boost::mutex::scoped_lock Lock(log_Mutex); - if (category & m_Flags) { - struct tm* pTime; -#ifdef _WIN32 - __int64 now; - _time64(&now); - pTime = _localtime64(&now); - DWORD tms = timeGetTime(); - unsigned millis = unsigned(tms % 1000); -#else - struct timeval time; - gettimeofday(&time, NULL); - pTime = localtime(&time.tv_sec); - unsigned millis = time.tv_usec/1000; -#endif - char timeString[256]; - strftime(timeString, sizeof(timeString), "%y-%m-%d %H:%M:%S", pTime); - cerr << "[" << timeString << "." << - setw(3) << setfill('0') << millis << setw(0) << "] "; - cerr << categoryToString(category) << ": "; - cerr << sMsg << endl; - cerr.flush(); + lock_guard lock(m_CategoryMutex); + severity = (severity == Logger::severity::NONE) ? m_Severity : severity; + UTF8String sCategory = boost::to_upper_copy(string(category)); + CatToSeverityMap::iterator it; + it = m_CategorySeverities.find(sCategory); + if ( it != m_CategorySeverities.end()) { + m_CategorySeverities.erase(sCategory); + } + pair<const category_t, const severity_t> element(sCategory, severity); + m_CategorySeverities.insert(element); + return sCategory; +} + +CatToSeverityMap Logger::getCategories() +{ + return m_CategorySeverities; +} + +void Logger::trace(const UTF8String& sMsg, const category_t& category, + severity_t severity) const +{ + lock_guard lock(s_traceMutex); + struct tm* pTime; + #ifdef _WIN32 + __int64 now; + _time64(&now); + pTime = _localtime64(&now); + DWORD tms = timeGetTime(); + unsigned millis = unsigned(tms % 1000); + #else + struct timeval time; + gettimeofday(&time, NULL); + pTime = localtime(&time.tv_sec); + unsigned millis = time.tv_usec/1000; + #endif + lock_guard lockHandler(s_sinkMutex); + std::vector<LogSinkPtr>::const_iterator it; + for(it=m_pSinks.begin(); it!=m_pSinks.end(); ++it){ + (*it)->logMessage(pTime, millis, category, severity, sMsg); } } -const char * Logger::categoryToString(int category) -{ - switch(category) { - case BLTS: - return "BLTS"; - case PROFILE: - case PROFILE_LATEFRAMES: - case PROFILE_VIDEO: - return "PROFILE"; - case EVENTS: - case EVENTS2: - return "EVENTS"; - case CONFIG: - return "CONFIG"; - case WARNING: - return "WARNING"; - case ERROR: - return "ERROR"; - case MEMORY: - return "MEMORY"; - case APP: - return "APP"; - case PLUGIN: - return "PLUGIN"; - case PLAYER: - return "PLAYER"; - default: - return "UNKNOWN"; +void Logger::logDebug(const UTF8String& msg, const category_t& category) const +{ + log(msg, category, Logger::severity::DEBUG); +} + +void Logger::logInfo(const UTF8String& msg, const category_t& category) const +{ + log(msg, category, Logger::severity::INFO); +} + +void Logger::logWarning(const UTF8String& msg, const category_t& category) const +{ + log(msg, category, Logger::severity::WARNING); +} + +void Logger::logError(const UTF8String& msg, const category_t& category) const +{ + log(msg, category, Logger::severity::ERROR); +} + +void Logger::logCritical(const UTF8String& msg, const category_t& category) const +{ + log(msg, category, Logger::severity::CRITICAL); +} + +void Logger::log(const UTF8String& msg, const category_t& category, + severity_t severity) const +{ + if(shouldLog(category, severity)) { + Logger::trace(msg, category, severity); + } +} + +void Logger::setupCategory() +{ + configureCategory(category::NONE); + configureCategory(category::PROFILE); + configureCategory(category::PROFILE_VIDEO); + configureCategory(category::EVENTS); + configureCategory(category::CONFIG); + configureCategory(category::MEMORY); + configureCategory(category::APP); + configureCategory(category::PLUGIN); + configureCategory(category::PLAYER); + configureCategory(category::SHADER); + configureCategory(category::DEPRECATION); +} + +severity_t Logger::stringToSeverity(const string& sSeverity) +{ + string severity = boost::to_upper_copy(string(sSeverity)); + if (severity == "CRIT") { + return Logger::severity::CRITICAL; + } else if (severity == "ERR") { + return Logger::severity::ERROR; + } else if (severity == "WARN") { + return Logger::severity::WARNING; + } else if (severity == "INFO") { + return Logger::severity::INFO; + } else if (severity == "DBG") { + return Logger::severity::DEBUG; + } else if (severity == "NONE") { + return Logger::severity::NONE; } + throw Exception(AVG_ERR_INVALID_ARGS, severity + " is an invalid log severity"); } -int Logger::stringToCategory(const string& sCategory) -{ - if (sCategory == "BLTS") { - return BLTS; - } else if (sCategory == "PROFILE") { - return PROFILE; - } else if (sCategory == "PROFILE_LATEFRAMES") { - return PROFILE_LATEFRAMES; - } else if (sCategory == "PROFILE_VIDEO") { - return PROFILE_VIDEO; - } else if (sCategory == "EVENTS") { - return EVENTS; - } else if (sCategory == "EVENTS2") { - return EVENTS2; - } else if (sCategory == "CONFIG") { - return CONFIG; - } else if (sCategory == "WARNING") { - return WARNING; - } else if (sCategory == "ERROR") { - return ERROR; - } else if (sCategory == "MEMORY") { - return MEMORY; - } else if (sCategory == "APP") { - return APP; - } else if (sCategory == "PLUGIN") { - return PLUGIN; - } else if (sCategory == "PLAYER") { - return PLAYER; - } else { - throw Exception (AVG_ERR_INVALID_ARGS, "Unknown logger category " + sCategory - + " set using AVG_LOG_CATEGORIES."); +const char * Logger::severityToString(severity_t severity) +{ + if(severity == Logger::severity::CRITICAL) { + return "CRIT"; + } else if(severity == Logger::severity::ERROR) { + return "ERR"; + } else if(severity == Logger::severity::WARNING) { + return "WARN"; + } else if(severity == Logger::severity::INFO) { + return "INFO"; + } else if(severity == Logger::severity::DEBUG) { + return "DBG"; } + throw Exception(AVG_ERR_UNKNOWN, "Unkown log severity"); } } diff --git a/src/base/Logger.h b/src/base/Logger.h index 34be8b8..197c0c2 100644 --- a/src/base/Logger.h +++ b/src/base/Logger.h @@ -1,6 +1,6 @@ // -// libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -19,68 +19,136 @@ // Current versions can be found at www.libavg.de // -#ifndef _Logger_H_ +#ifndef _Logger_H_ #define _Logger_H_ -#include "../api.h" +#include "Exception.h" +#include "ILogSink.h" #include "UTF8String.h" +#include "ThreadHelper.h" +#include "../api.h" + +#include <boost/noncopyable.hpp> +#include <boost/functional/hash.hpp> +#include <boost/unordered_map.hpp> #include <string> #include <vector> #include <sstream> -namespace avg { - #ifdef ERROR #undef ERROR #endif -class AVG_API Logger { +namespace avg { + +typedef boost::unordered_map< const category_t, const severity_t > CatToSeverityMap; + +#ifdef _WIN32 +// non dll-interface class used as base for dll-interface class +#pragma warning(disable:4275) +#endif +class AVG_API Logger: private boost::noncopyable { public: + struct AVG_API severity + { + static const severity_t CRITICAL; + static const severity_t ERROR; + static const severity_t WARNING; + static const severity_t INFO; + static const severity_t DEBUG; + static const severity_t NONE; + }; + + struct AVG_API category + { + static const category_t NONE; + static const category_t PROFILE; + static const category_t PROFILE_VIDEO; + static const category_t EVENTS; + static const category_t CONFIG; + static const category_t MEMORY; + static const category_t APP; + static const category_t PLUGIN; + static const category_t PLAYER; + static const category_t SHADER; + static const category_t DEPRECATION; + }; + static Logger* get(); virtual ~Logger(); - - void setCategories(int flags); - void pushCategories(); - void popCategories(); - void trace(int category, const UTF8String& sMsg); - inline bool isFlagSet(int category) { - return (category & m_Flags) != 0; - } - static const long NONE; - static const long BLTS; - static const long PROFILE; - static const long PROFILE_LATEFRAMES; - static const long PROFILE_VIDEO; - static const long EVENTS; - static const long EVENTS2; - static const long CONFIG; - static const long WARNING; - static const long ERROR; - static const long MEMORY; - static const long APP; - static const long PLUGIN; - static const long PLAYER; + static severity_t stringToSeverity(const string& sSeverity); + static const char * severityToString(const severity_t severity); + + void addLogSink(const LogSinkPtr& logSink); + void removeLogSink(const LogSinkPtr& logSink); + void removeStdLogSink(); + + category_t configureCategory(category_t category, + severity_t severity=severity::NONE); + CatToSeverityMap getCategories(); + + void trace(const UTF8String& sMsg, const category_t& category, + severity_t severity) const; + void logDebug(const UTF8String& msg, + const category_t& category=category::APP) const; + void logInfo(const UTF8String& msg, + const category_t& category=category::APP) const; + void logWarning(const UTF8String& msg, + const category_t& category=category::APP) const; + void logError(const UTF8String& msg, + const category_t& category=category::APP) const; + void logCritical(const UTF8String& msg, + const category_t& category=category::APP) const; + void log(const UTF8String& msg, const category_t& category=category::APP, + severity_t severity=severity::INFO) const; + + inline bool shouldLog(const category_t& category, severity_t severity) const { + lock_guard lock(m_CategoryMutex); + try { + severity_t targetSeverity = m_CategorySeverities.at(category); + return (targetSeverity <= severity); + } catch (out_of_range e){ + string msg("Unknown category: " + category); + throw Exception(AVG_ERR_INVALID_ARGS, msg); + } + } private: Logger(); - static const char * categoryToString(int category); - int stringToCategory(const std::string& sCategory); - - static Logger* m_pLogger; + void setupCategory(); - int m_Flags; - std::vector<int> m_FlagStack; + std::vector<LogSinkPtr> m_pSinks; + LogSinkPtr m_pStdSink; + CatToSeverityMap m_CategorySeverities; + severity_t m_Severity; + static boost::mutex m_CategoryMutex; }; -#define AVG_TRACE(category, sMsg) { \ - if (Logger::get()->isFlagSet(category)) { \ - std::stringstream tmp(std::stringstream::in | std::stringstream::out); \ - tmp << sMsg; \ - Logger::get()->trace(category, tmp.str()); \ +#define AVG_TRACE(category, severity, sMsg) { \ +if (Logger::get()->shouldLog(category, severity)) { \ + std::stringstream tmp(std::stringstream::in | std::stringstream::out); \ + tmp << sMsg; \ + Logger::get()->trace(tmp.str(), category, severity); \ }\ -} +}\ + +#define AVG_LOG_ERROR(sMsg){ \ + AVG_TRACE(Logger::category::NONE, Logger::severity::ERROR, sMsg); \ +}\ + +#define AVG_LOG_WARNING(sMsg){ \ + AVG_TRACE(Logger::category::NONE, Logger::severity::WARNING, sMsg); \ +}\ + +#define AVG_LOG_INFO(sMsg){ \ + AVG_TRACE(Logger::category::NONE, Logger::severity::INFO, sMsg); \ +}\ + +#define AVG_LOG_DEBUG(sMsg){ \ + AVG_TRACE(Logger::category::NONE, Logger::severity::DEBUG, sMsg); \ +}\ } #endif diff --git a/src/base/Makefile.am b/src/base/Makefile.am index 5fe4c94..ce995f2 100644 --- a/src/base/Makefile.am +++ b/src/base/Makefile.am @@ -1,31 +1,35 @@ +SUBDIRS = triangulate -INCLUDES = -I.. @XML2_CFLAGS@ @PTHREAD_CFLAGS@ -ALL_H = FileHelper.h CmdLine.h Exception.h Logger.h ConfigMgr.h ObjectCounter.h \ +AM_CPPFLAGS = -I.. @XML2_CFLAGS@ @PTHREAD_CFLAGS@ +ALL_H = FileHelper.h Exception.h Logger.h ConfigMgr.h ObjectCounter.h \ XMLHelper.h TimeSource.h ProfilingZone.h ThreadProfiler.h \ ScopeTimer.h IFrameEndListener.h IPreRenderListener.h IPlaybackEndListener.h \ Test.h TestSuite.h OSHelper.h Queue.h WorkerThread.h Command.h ObjectCounter.h \ - Point.h Rect.h Directory.h DirEntry.h StringHelper.h MathHelper.h GeomHelper.h \ - CubicSpline.h BezierCurve.h UTF8String.h Triangle.h \ - Triangulate.h WideLine.h Triple.h DlfcnWrapper.h Signal.h Backtrace.h \ - CmdQueue.h Matrix3x4.h ProfilingZoneID.h + Rect.h Directory.h DirEntry.h StringHelper.h MathHelper.h GeomHelper.h \ + CubicSpline.h BezierCurve.h UTF8String.h Triangle.h DAG.h \ + WideLine.h DlfcnWrapper.h Signal.h Backtrace.h \ + CmdQueue.h ProfilingZoneID.h GLMHelper.h StandardLogSink.h ILogSink.h \ + ThreadHelper.h -TESTS=testbase +TESTS = testbase EXTRA_DIST = DlfcnWrapper.cpp noinst_LTLIBRARIES = libbase.la -libbase_la_SOURCES = FileHelper.cpp CmdLine.cpp Exception.cpp Logger.cpp \ +libbase_la_SOURCES = FileHelper.cpp Exception.cpp Logger.cpp \ ConfigMgr.cpp XMLHelper.cpp TimeSource.cpp OSHelper.cpp \ ProfilingZone.cpp ThreadProfiler.cpp ScopeTimer.cpp Test.cpp \ - TestSuite.cpp ObjectCounter.cpp Point.cpp Directory.cpp DirEntry.cpp \ + TestSuite.cpp ObjectCounter.cpp Directory.cpp DirEntry.cpp \ StringHelper.cpp MathHelper.cpp GeomHelper.cpp CubicSpline.cpp \ - BezierCurve.cpp UTF8String.cpp Triangle.cpp Triangulate.cpp WideLine.cpp \ - Triple.cpp Backtrace.cpp Matrix3x4.cpp ProfilingZoneID.cpp \ + BezierCurve.cpp UTF8String.cpp Triangle.cpp DAG.cpp WideLine.cpp \ + Backtrace.cpp ProfilingZoneID.cpp GLMHelper.cpp \ + WorkerThread.cpp StandardLogSink.cpp ThreadHelper.cpp \ $(ALL_H) libbase_a_CXXFLAGS = -Wno-format-y2k -noinst_PROGRAMS=testbase -testbase_SOURCES=testbase.cpp $(ALL_H) -testbase_LDADD = ./libbase.la -l@BOOST_THREAD_LIB@ -lboost_system @PTHREAD_LIBS@ +noinst_PROGRAMS = testbase +testbase_SOURCES = testbase.cpp $(ALL_H) +testbase_LDADD = ./libbase.la ./triangulate/libtriangulate.la \ + @BOOST_THREAD_LIBS@ @XML2_LIBS@ @PTHREAD_LIBS@ # -rdynamic needed only for testBacktrace to work under linux. testbase_LDFLAGS = -rdynamic diff --git a/src/base/Makefile.in b/src/base/Makefile.in index cc935b7..2383ebb 100644 --- a/src/base/Makefile.in +++ b/src/base/Makefile.in @@ -1,9 +1,9 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11.3 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -44,11 +44,12 @@ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_cxx_namespaces.m4 \ $(top_srcdir)/m4/ac_path_generic.m4 \ $(top_srcdir)/m4/ax_boost_thread.m4 \ - $(top_srcdir)/m4/ax_check_gl.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/python_dev.m4 \ - $(top_srcdir)/configure.in + $(top_srcdir)/m4/ax_check_gl.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/avg_version.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -58,22 +59,22 @@ CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libbase_la_LIBADD = am__objects_1 = -am_libbase_la_OBJECTS = FileHelper.lo CmdLine.lo Exception.lo \ - Logger.lo ConfigMgr.lo XMLHelper.lo TimeSource.lo OSHelper.lo \ +am_libbase_la_OBJECTS = FileHelper.lo Exception.lo Logger.lo \ + ConfigMgr.lo XMLHelper.lo TimeSource.lo OSHelper.lo \ ProfilingZone.lo ThreadProfiler.lo ScopeTimer.lo Test.lo \ - TestSuite.lo ObjectCounter.lo Point.lo Directory.lo \ - DirEntry.lo StringHelper.lo MathHelper.lo GeomHelper.lo \ - CubicSpline.lo BezierCurve.lo UTF8String.lo Triangle.lo \ - Triangulate.lo WideLine.lo Triple.lo Backtrace.lo Matrix3x4.lo \ - ProfilingZoneID.lo $(am__objects_1) + TestSuite.lo ObjectCounter.lo Directory.lo DirEntry.lo \ + StringHelper.lo MathHelper.lo GeomHelper.lo CubicSpline.lo \ + BezierCurve.lo UTF8String.lo Triangle.lo DAG.lo WideLine.lo \ + Backtrace.lo ProfilingZoneID.lo GLMHelper.lo WorkerThread.lo \ + StandardLogSink.lo ThreadHelper.lo $(am__objects_1) libbase_la_OBJECTS = $(am_libbase_la_OBJECTS) -AM_V_lt = $(am__v_lt_$(V)) -am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent PROGRAMS = $(noinst_PROGRAMS) am_testbase_OBJECTS = testbase.$(OBJEXT) $(am__objects_1) testbase_OBJECTS = $(am_testbase_OBJECTS) -testbase_DEPENDENCIES = ./libbase.la +testbase_DEPENDENCIES = ./libbase.la ./triangulate/libtriangulate.la testbase_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(testbase_LDFLAGS) $(LDFLAGS) -o $@ @@ -87,18 +88,18 @@ LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) -AM_V_CXX = $(am__v_CXX_$(V)) -am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY)) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CXXLD = $(am__v_CXXLD_$(V)) -am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY)) +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -106,26 +107,64 @@ LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_$(V)) -am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_$(V)) -am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libbase_la_SOURCES) $(testbase_SOURCES) DIST_SOURCES = $(libbase_la_SOURCES) $(testbase_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir ETAGS = etags CTAGS = ctags am__tty_colors = \ red=; grn=; lgn=; blu=; std= +DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ @@ -135,7 +174,7 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BOOST_PYTHON_LIBS = @BOOST_PYTHON_LIBS@ -BOOST_THREAD_LIB = @BOOST_THREAD_LIB@ +BOOST_THREAD_LIBS = @BOOST_THREAD_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ @@ -150,6 +189,7 @@ DC1394_2_CFLAGS = @DC1394_2_CFLAGS@ DC1394_2_LIBS = @DC1394_2_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -190,6 +230,7 @@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MTDEV_CFLAGS = @MTDEV_CFLAGS@ MTDEV_LIBS = @MTDEV_LIBS@ @@ -219,11 +260,13 @@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PYTHON = @PYTHON@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_INCLUDES = @PYTHON_INCLUDES@ -PYTHON_LIBS = @PYTHON_LIBS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SDL_CFLAGS = @SDL_CFLAGS@ @@ -246,6 +289,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ @@ -280,7 +324,6 @@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ @@ -304,33 +347,38 @@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -INCLUDES = -I.. @XML2_CFLAGS@ @PTHREAD_CFLAGS@ -ALL_H = FileHelper.h CmdLine.h Exception.h Logger.h ConfigMgr.h ObjectCounter.h \ +SUBDIRS = triangulate +AM_CPPFLAGS = -I.. @XML2_CFLAGS@ @PTHREAD_CFLAGS@ +ALL_H = FileHelper.h Exception.h Logger.h ConfigMgr.h ObjectCounter.h \ XMLHelper.h TimeSource.h ProfilingZone.h ThreadProfiler.h \ ScopeTimer.h IFrameEndListener.h IPreRenderListener.h IPlaybackEndListener.h \ Test.h TestSuite.h OSHelper.h Queue.h WorkerThread.h Command.h ObjectCounter.h \ - Point.h Rect.h Directory.h DirEntry.h StringHelper.h MathHelper.h GeomHelper.h \ - CubicSpline.h BezierCurve.h UTF8String.h Triangle.h \ - Triangulate.h WideLine.h Triple.h DlfcnWrapper.h Signal.h Backtrace.h \ - CmdQueue.h Matrix3x4.h ProfilingZoneID.h + Rect.h Directory.h DirEntry.h StringHelper.h MathHelper.h GeomHelper.h \ + CubicSpline.h BezierCurve.h UTF8String.h Triangle.h DAG.h \ + WideLine.h DlfcnWrapper.h Signal.h Backtrace.h \ + CmdQueue.h ProfilingZoneID.h GLMHelper.h StandardLogSink.h ILogSink.h \ + ThreadHelper.h EXTRA_DIST = DlfcnWrapper.cpp noinst_LTLIBRARIES = libbase.la -libbase_la_SOURCES = FileHelper.cpp CmdLine.cpp Exception.cpp Logger.cpp \ +libbase_la_SOURCES = FileHelper.cpp Exception.cpp Logger.cpp \ ConfigMgr.cpp XMLHelper.cpp TimeSource.cpp OSHelper.cpp \ ProfilingZone.cpp ThreadProfiler.cpp ScopeTimer.cpp Test.cpp \ - TestSuite.cpp ObjectCounter.cpp Point.cpp Directory.cpp DirEntry.cpp \ + TestSuite.cpp ObjectCounter.cpp Directory.cpp DirEntry.cpp \ StringHelper.cpp MathHelper.cpp GeomHelper.cpp CubicSpline.cpp \ - BezierCurve.cpp UTF8String.cpp Triangle.cpp Triangulate.cpp WideLine.cpp \ - Triple.cpp Backtrace.cpp Matrix3x4.cpp ProfilingZoneID.cpp \ + BezierCurve.cpp UTF8String.cpp Triangle.cpp DAG.cpp WideLine.cpp \ + Backtrace.cpp ProfilingZoneID.cpp GLMHelper.cpp \ + WorkerThread.cpp StandardLogSink.cpp ThreadHelper.cpp \ $(ALL_H) libbase_a_CXXFLAGS = -Wno-format-y2k testbase_SOURCES = testbase.cpp $(ALL_H) -testbase_LDADD = ./libbase.la -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@ +testbase_LDADD = ./libbase.la ./triangulate/libtriangulate.la \ + @BOOST_THREAD_LIBS@ @XML2_LIBS@ @PTHREAD_LIBS@ + # -rdynamic needed only for testBacktrace to work under linux. testbase_LDFLAGS = -rdynamic -all: all-am +all: all-recursive .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj @@ -373,7 +421,7 @@ clean-noinstLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libbase.la: $(libbase_la_OBJECTS) $(libbase_la_DEPENDENCIES) +libbase.la: $(libbase_la_OBJECTS) $(libbase_la_DEPENDENCIES) $(EXTRA_libbase_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libbase_la_OBJECTS) $(libbase_la_LIBADD) $(LIBS) clean-noinstPROGRAMS: @@ -384,7 +432,7 @@ clean-noinstPROGRAMS: list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list -testbase$(EXEEXT): $(testbase_OBJECTS) $(testbase_DEPENDENCIES) +testbase$(EXEEXT): $(testbase_OBJECTS) $(testbase_DEPENDENCIES) $(EXTRA_testbase_DEPENDENCIES) @rm -f testbase$(EXEEXT) $(AM_V_CXXLD)$(testbase_LINK) $(testbase_OBJECTS) $(testbase_LDADD) $(LIBS) @@ -396,59 +444,56 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Backtrace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BezierCurve.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CmdLine.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConfigMgr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CubicSpline.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DAG.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DirEntry.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Directory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Exception.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileHelper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GLMHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GeomHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Logger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MathHelper.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Matrix3x4.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OSHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ObjectCounter.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Point.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ProfilingZone.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ProfilingZoneID.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ScopeTimer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StandardLogSink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StringHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Test.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TestSuite.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ThreadHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ThreadProfiler.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeSource.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Triangle.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Triangulate.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Triple.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UTF8String.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/WideLine.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/WorkerThread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLHelper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbase.Po@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo @@ -456,6 +501,76 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ @@ -466,10 +581,23 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) mkid -fID $$unique tags: TAGS -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ @@ -488,7 +616,7 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ fi; \ fi ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ @@ -589,14 +717,15 @@ check-TESTS: $(TESTS) fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ - echo "$$grn$$dashes"; \ + col="$$grn"; \ else \ - echo "$$red$$dashes"; \ + col="$$red"; \ fi; \ - echo "$$banner"; \ - test -z "$$skipped" || echo "$$skipped"; \ - test -z "$$report" || echo "$$report"; \ - echo "$$dashes$$std"; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ test "$$failed" -eq 0; \ else :; fi @@ -630,25 +759,59 @@ distdir: $(DISTFILES) || exit 1; \ fi; \ done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-TESTS -check: check-am +check: check-recursive all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) -installdirs: -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -installcheck: installcheck-am +installcheck: installcheck-recursive install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: @@ -660,92 +823,94 @@ distclean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -clean: clean-am +clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ clean-noinstPROGRAMS mostlyclean-am -distclean: distclean-am +distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags -dvi: dvi-am +dvi: dvi-recursive dvi-am: -html: html-am +html: html-recursive html-am: -info: info-am +info: info-recursive info-am: install-data-am: -install-dvi: install-dvi-am +install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: -install-html: install-html-am +install-html: install-html-recursive install-html-am: -install-info: install-info-am +install-info: install-info-recursive install-info-am: install-man: -install-pdf: install-pdf-am +install-pdf: install-pdf-recursive install-pdf-am: -install-ps: install-ps-am +install-ps: install-ps-recursive install-ps-am: installcheck-am: -maintainer-clean: maintainer-clean-am +maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic -mostlyclean: mostlyclean-am +mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool -pdf: pdf-am +pdf: pdf-recursive pdf-am: -ps: ps-am +ps: ps-recursive ps-am: uninstall-am: -.MAKE: check-am install-am install-strip +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) check-am \ + ctags-recursive install-am install-strip tags-recursive -.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ - clean-generic clean-libtool clean-noinstLTLIBRARIES \ - clean-noinstPROGRAMS ctags distclean distclean-compile \ +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-TESTS check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + ctags ctags-recursive distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ - installcheck installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/src/base/MathHelper.cpp b/src/base/MathHelper.cpp index ea7093e..388859d 100644 --- a/src/base/MathHelper.cpp +++ b/src/base/MathHelper.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -35,27 +35,17 @@ bool ispow2(int n) int nextpow2(int n) { - int ret=1; - while (ret < n) { - ret *= 2; - } - return ret; -/* TODO: Fix this fast version :-). - int RetVal = 1; - __asm__ __volatile__( - "xorl %%ecx, %%ecx\n\t" - "bsrl %1, %%ecx\n\t" - "incl %%ecx\n\t" - "shlb %%cl, %0\n\t" - : "=m" (RetVal) - : "m" (n) - : "cc", "ecx" - ); - return RetVal; -*/ + n--; + n |= n >> 1; // handle 2 bit numbers + n |= n >> 2; // handle 4 bit numbers + n |= n >> 4; // handle 8 bit numbers + n |= n >> 8; // handle 16 bit numbers + n |= n >> 16; // handle 32 bit numbers + n++; + return n; } -int safeCeil(double d) +int safeCeil(float d) { if (fabs(d-int(d)) < EPSILON) { return int(d); @@ -80,7 +70,7 @@ float invSqrt(float x) return 1/sqrt(x); } -bool almostEqual(double d1, double d2, double epsilon) +bool almostEqual(float d1, float d2, float epsilon) { return (fabs(d1-d2)<epsilon); } diff --git a/src/base/MathHelper.h b/src/base/MathHelper.h index 16132c4..587ff2c 100644 --- a/src/base/MathHelper.h +++ b/src/base/MathHelper.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,7 @@ #include "../api.h" #include <vector> +#include <set> #include <math.h> #ifndef M_PI @@ -32,15 +33,16 @@ namespace avg { -static const double EPSILON = 0.00001; +static const float PI = 3.14159265358979323846f; +static const float EPSILON = 0.00001f; bool ispow2(int n); int nextpow2(int n); -int safeCeil(double d); +int safeCeil(float d); -bool almostEqual(double d1, double d2, double epsilon=EPSILON); +bool almostEqual(float d1, float d2, float epsilon=EPSILON); float invSqrt(float x); @@ -82,7 +84,7 @@ std::vector<std::vector<T> > vector2DFromCArray(int n, int m, T* pData) template<class T> T round(T d) { - return floor( d + 0.5 ); + return floor(d + 0.5f); } #endif diff --git a/src/base/Matrix3x4.cpp b/src/base/Matrix3x4.cpp deleted file mode 100644 index e065d2b..0000000 --- a/src/base/Matrix3x4.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// -// libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow -// -// 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 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// Current versions can be found at www.libavg.de -// - -#include "Matrix3x4.h" -#include "MathHelper.h" - -#include <math.h> - -using namespace std; - -namespace avg { - -Matrix3x4::Matrix3x4() -{ - setIdent(); -} - -Matrix3x4::Matrix3x4(const float *v) -{ - for (int x=0; x<3; ++x) { - for (int y=0; y<4; ++y) { - val[x][y] = v[x*4+y]; - } - } -} - -Matrix3x4 Matrix3x4::createTranslate(float x, float y, float z) -{ - Matrix3x4 mat; - mat.val[0][3] = x; - mat.val[1][3] = y; - mat.val[2][3] = z; - return mat; -} - -Matrix3x4 Matrix3x4::createTranslate(const DTriple& tr) -{ - return createTranslate(float(tr.x), float(tr.y), float(tr.z)); -} - -Matrix3x4 Matrix3x4::createScale(float x, float y, float z) -{ - Matrix3x4 mat; - mat.val[0][0] = x; - mat.val[1][1] = y; - mat.val[2][2] = z; - return mat; -} - -Matrix3x4 Matrix3x4::createScale(const DTriple& tr) -{ - return createScale(float(tr.x), float(tr.y), float(tr.z)); -} - -const Matrix3x4& Matrix3x4::operator *=(const Matrix3x4& mat) -{ - for (int x=0; x<3; ++x) { - float t0 = val[x][0] * mat.val[0][0] + val[x][1] * mat.val[1][0] - + val[x][2] * mat.val[2][0]; - float t1 = val[x][0] * mat.val[0][1] + val[x][1] * mat.val[1][1] - + val[x][2] * mat.val[2][1]; - float t2 = val[x][0] * mat.val[0][2] + val[x][1] * mat.val[1][2] - + val[x][2] * mat.val[2][2]; - val[x][3] = val[x][0] * mat.val[0][3] + val[x][1] * mat.val[1][3] - + val[x][2] * mat.val[2][3] + val[x][3]; - val[x][0] = t0; - val[x][1] = t1; - val[x][2] = t2; - } - return *this; -} - -void Matrix3x4::setIdent() -{ - for (int x=0; x<3; ++x) { - for (int y=0; y<4; ++y) { - val[x][y] = 0.0; - } - } - val[0][0] = 1.0; - val[1][1] = 1.0; - val[2][2] = 1.0; -} - -bool almostEqual(const Matrix3x4& mat1, const Matrix3x4& mat2) -{ - for (int x=0; x<3; ++x) { - for (int y=0; y<4; ++y) { - if (!almostEqual(mat1.val[x][y], mat2.val[x][y])) { - return false; - } - } - } - return true; -} - -std::ostream& operator<<(ostream& os, const Matrix3x4& mat) -{ - os << "{" << endl; - for (int y=0; y<4; ++y) { - os << " {" << mat.val[0][y] << "," << mat.val[1][y] << "," << mat.val[2][y] - << "}" << endl; - } - os << "}" << endl; - return os; -} - - -} - diff --git a/src/base/OSHelper.cpp b/src/base/OSHelper.cpp index 852a7f0..377e725 100644 --- a/src/base/OSHelper.cpp +++ b/src/base/OSHelper.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -33,12 +33,15 @@ #elif defined(__APPLE__) #include <mach-o/dyld.h> #include <mach/mach.h> +#include <sys/utsname.h> #elif defined(__linux) #include <fstream> #include <unistd.h> +#include <string.h> #endif #include <stdlib.h> +#include <iostream> #include <cstdlib> using namespace std; @@ -59,6 +62,107 @@ string getWinErrMsg(unsigned err) } #endif +#if defined(__linux) +// Adapted from binreloc +static char * +_br_find_exe_for_symbol (const void *symbol) +{ + #define SIZE 1024 + FILE *f; + size_t address_string_len; + char *address_string, line[SIZE], *found; + + if (symbol == NULL) + return (char *) NULL; + + f = fopen ("/proc/self/maps", "r"); + if (f == NULL) + return (char *) NULL; + + address_string_len = 4; + address_string = (char *) malloc(address_string_len); + found = (char *) NULL; + + + while (!feof (f)) { + char *start_addr, *end_addr, *end_addr_end, *file; + void *start_addr_p, *end_addr_p; + size_t len; + + if (fgets (line, SIZE, f) == NULL) + break; + + /* Sanity check. */ + if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL) + continue; + + /* Parse line. */ + start_addr = line; + end_addr = strchr (line, '-'); + file = strchr (line, '/'); + + /* More sanity check. */ + if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-')) + continue; + + end_addr[0] = '\0'; + end_addr++; + end_addr_end = strchr (end_addr, ' '); + if (end_addr_end == NULL) + continue; + + end_addr_end[0] = '\0'; + len = strlen (file); + if (len == 0) + continue; + if (file[len - 1] == '\n') + file[len - 1] = '\0'; + + /* Get rid of "(deleted)" from the filename. */ + len = strlen (file); + if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0) + file[len - 10] = '\0'; + + /* I don't know whether this can happen but better safe than sorry. */ + len = strlen (start_addr); + if (len != strlen (end_addr)) + continue; + + + /* Transform the addresses into a string in the form of 0xdeadbeef, + * then transform that into a pointer. */ + if (address_string_len < len + 3) { + address_string_len = len + 3; + address_string = (char *) realloc (address_string, address_string_len); + } + + memcpy (address_string, "0x", 2); + memcpy (address_string + 2, start_addr, len); + address_string[2 + len] = '\0'; + sscanf (address_string, "%p", &start_addr_p); + + memcpy (address_string, "0x", 2); + memcpy (address_string + 2, end_addr, len); + address_string[2 + len] = '\0'; + sscanf (address_string, "%p", &end_addr_p); + + + if (symbol >= start_addr_p && symbol < end_addr_p) { + found = file; + break; + } + } + + free (address_string); + fclose (f); + + if (found == NULL) + return (char *) NULL; + else + return strdup (found); +} +#endif + string getAvgLibPath() { #if defined(_WIN32) @@ -66,7 +170,7 @@ string getAvgLibPath() char szFilename[1024]; DWORD ok = GetModuleFileName(hModule, szFilename, sizeof(szFilename)); if (ok == 0) { - AVG_TRACE(Logger::ERROR, "getAvgLibPath(): " << getWinErrMsg(GetLastError())); + AVG_LOG_ERROR("getAvgLibPath(): " << getWinErrMsg(GetLastError())); exit(5); } string sPath=getPath(szFilename); @@ -89,8 +193,9 @@ string getAvgLibPath() _NSGetExecutablePath(path, &pathLen); return getPath(path); #else - // For a linux solution, see http://www.autopackage.org/docs/binreloc/ - return ""; + char* pszFilename; + pszFilename = _br_find_exe_for_symbol((const void *)""); + return pszFilename; #endif } @@ -154,8 +259,7 @@ std::string convertUTF8ToFilename(const std::string & sName) int err1 = MultiByteToWideChar(CP_UTF8, 0, sName.c_str(), sName.size()+1, wideString, 2048); if (err1 == 0) { - AVG_TRACE(Logger::WARNING, - "Error in unicode conversion (MultiByteToWideChar): " << + AVG_LOG_WARNING("Error in unicode conversion (MultiByteToWideChar): " << getWinErrMsg(GetLastError())); return sName; } @@ -166,8 +270,7 @@ std::string convertUTF8ToFilename(const std::string & sName) err1 = WideCharToMultiByte(CP_UTF8, 0, wideShortFName, -1, pShortName, 1024, 0, 0); if (err1 == 0) { - AVG_TRACE(Logger::WARNING, - "Error in unicode conversion (MultiByteToWideChar): " << + AVG_LOG_WARNING("Error in unicode conversion (MultiByteToWideChar): " << getWinErrMsg(GetLastError())); } return pShortName; @@ -179,4 +282,27 @@ std::string convertUTF8ToFilename(const std::string & sName) #endif } +#ifdef __APPLE__ +int reallyGetOSXMajorVersion() +{ + utsname sysInfo; + int rc = uname(&sysInfo); + AVG_ASSERT(rc == 0); +// cerr << sysInfo.sysname << ", " << sysInfo.nodename << ", " << sysInfo.release << +// ", " << sysInfo.version << ", " << sysInfo.machine << endl; + istringstream ss(sysInfo.release); + int major; + int minor; + int dot; + char c; + ss >> major >> c >> minor >> c >> dot; + return major; +} + +int getOSXMajorVersion() +{ + static int major = reallyGetOSXMajorVersion(); // only called once for speed reasons. + return major; +} +#endif } diff --git a/src/base/OSHelper.h b/src/base/OSHelper.h index de6924b..6abda5a 100644 --- a/src/base/OSHelper.h +++ b/src/base/OSHelper.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -42,6 +42,10 @@ size_t getMemoryUsage(); // Under other operating systems, returns the input string. AVG_API std::string convertUTF8ToFilename(const std::string & sName); +#ifdef __APPLE__ +int getOSXMajorVersion(); +#endif + } #endif diff --git a/src/base/ObjectCounter.cpp b/src/base/ObjectCounter.cpp index 00015aa..e8136b7 100644 --- a/src/base/ObjectCounter.cpp +++ b/src/base/ObjectCounter.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,6 +21,7 @@ #include "ObjectCounter.h" #include "Exception.h" +#include "Logger.h" #include <boost/thread/mutex.hpp> @@ -80,7 +81,7 @@ ObjectCounter * ObjectCounter::get() void ObjectCounter::incRef(const std::type_info* pType) { #ifdef DEBUG_ALLOC - boost::mutex::scoped_lock Lock(*pCounterMutex); + lock_guard Lock(*pCounterMutex); TypeMap::iterator MapEntry = m_TypeMap.find(pType); if (MapEntry == m_TypeMap.end()) { m_TypeMap[pType] = 1; @@ -99,7 +100,7 @@ void ObjectCounter::decRef(const std::type_info* pType) // s_pObjectCounter has been deleted. return; } - boost::mutex::scoped_lock Lock(*pCounterMutex); + lock_guard Lock(*pCounterMutex); TypeMap::iterator MapEntry = m_TypeMap.find(pType); if (MapEntry == m_TypeMap.end()) { cerr << "ObjectCounter for " << demangle(pType->name()) @@ -179,4 +180,8 @@ string ObjectCounter::demangle(string s) return sResult; } +TypeMap ObjectCounter::getObjectCount(){ + return m_TypeMap; +} + } diff --git a/src/base/ObjectCounter.h b/src/base/ObjectCounter.h index 506a3c9..e370723 100644 --- a/src/base/ObjectCounter.h +++ b/src/base/ObjectCounter.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -29,6 +29,8 @@ namespace avg { +typedef std::map<const std::type_info *, int> TypeMap; + class AVG_API ObjectCounter { public: static ObjectCounter* get(); @@ -38,14 +40,15 @@ public: void decRef(const std::type_info* pType); int getCount(const std::type_info* pType); + + std::string demangle(std::string s); std::string dump(); + TypeMap getObjectCount(); private: ObjectCounter(); - std::string demangle(std::string s); static void deleteSingleton(); - typedef std::map<const std::type_info *, int> TypeMap; TypeMap m_TypeMap; static ObjectCounter* s_pObjectCounter; diff --git a/src/base/Point.cpp b/src/base/Point.cpp deleted file mode 100644 index 24208ca..0000000 --- a/src/base/Point.cpp +++ /dev/null @@ -1,325 +0,0 @@ -// -// libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow -// -// 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 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// Current versions can be found at www.libavg.de -// - -#include "Point.h" - -#include "MathHelper.h" -#include "Exception.h" - -#if defined(__SSE__) || defined(_WIN32) -#include <xmmintrin.h> -#endif - -#include <math.h> -#include <float.h> - -#include <string> - -namespace avg { - -template<class NUM> -Point<NUM>::Point() -{ -// ObjectCounter::get()->incRef(&typeid(*this)); -} - -template<class NUM> -Point<NUM>::Point(NUM X, NUM Y) -{ -// ObjectCounter::get()->incRef(&typeid(*this)); - x = X; - y = Y; -} - -template<class NUM> -Point<NUM>::Point(const Point<NUM>& p) -{ -// ObjectCounter::get()->incRef(&typeid(*this)); - x = p.x; - y = p.y; -} - -template<class NUM> -Point<NUM>::Point(const std::vector<NUM>& v) -{ - AVG_ASSERT_MSG(v.size() == 2, - "Point can only be constructed from 2-component vector"); - x = v[0]; - y = v[1]; -} - -template<class NUM> -Point<NUM>::~Point() -{ -// ObjectCounter::get()->decRef(&typeid(*this)); -} - -template<class NUM> -double Point<NUM>::getNorm() const -{ - return sqrt(double(x*x+y*y)); -} - -template<class NUM> -bool Point<NUM>::isNaN() const -{ - return isnan(x) || isnan(y); -} - -template<class NUM> -bool Point<NUM>::isInf() const -{ - return isinf(x) || isinf(y); -} - -template<class NUM> -Point<NUM> Point<NUM>::getRotated(double angle) const -{ - double cosVal = cos(angle); - double sinVal = sin(angle); - return Point<NUM>(NUM(x*cosVal - y*sinVal), NUM(x*sinVal + y*cosVal)); -} - -template<class NUM> -Point<NUM> Point<NUM>::getRotatedPivot(double angle, const Point<NUM>& pivot) const -{ - // translate pivot to origin - Point<NUM> translated = *this - pivot; - - // calculate rotated coordinates about the origin - Point<NUM> rotated = translated.getRotated(angle); - - // re-translate pivot to original position - rotated += pivot; - - return rotated; -} - -template<class NUM> -Point<NUM>& Point<NUM>::operator =(const Point<NUM>& p) -{ - x = p.x; - y = p.y; - return *this; -} - -template<class NUM> -bool Point<NUM>::operator ==(const Point<NUM> & pt) const -{ - return (x == pt.x && y == pt.y); -} - -template<class NUM> -bool Point<NUM>::operator !=(const Point<NUM> & pt) const -{ - return (x != pt.x || y != pt.y); -} - -template<class NUM> -void Point<NUM>::operator +=(const Point<NUM>& pt) -{ - x += pt.x; - y += pt.y; -} - -template<class NUM> -void Point<NUM>::operator -=(const Point<NUM> & pt) -{ - x -= pt.x; - y -= pt.y; -} - -template<class NUM> -void Point<NUM>::operator *=(NUM f) -{ - x *= f; - y *= f; -} - -template<class NUM> -void Point<NUM>::operator /=(NUM f) -{ - x /= f; - y /= f; -} - -template<class NUM> -Point<NUM> Point<NUM>::operator -() const -{ - return Point<NUM>(-x, -y); -} - -template<class NUM> -Point<NUM> Point<NUM>::operator +(const Point<NUM> & pt) const -{ - return Point<NUM>(x + pt.x, y + pt.y); -} - -template<class NUM> -Point<NUM> Point<NUM>::operator -(const Point<NUM> & pt) const -{ - return Point<NUM>(x - pt.x, y - pt.y); -} - -template<class NUM> -Point<NUM> Point<NUM>::operator /(double f) const -{ - return Point<NUM> (NUM(x/f), NUM(y/f)); -} - -template<class NUM> -Point<NUM> Point<NUM>::operator *(double f) const -{ - return Point<NUM> (NUM(x*f), NUM(y*f)); -} - -template<class NUM> -Point<NUM> Point<NUM>::operator *(const Point<NUM>& pt) const -{ - return Point<NUM> (x*pt.x, y*pt.y); -} - -template<> -Point<int> Point<int>::fromPolar(double angle, double radius) -{ - AVG_ASSERT_MSG(false, "fromPolar undefined for IntPoint"); - return Point<int>(0,0); -} - -template<> -Point<double> Point<double>::fromPolar(double angle, double radius) -{ - return Point<double>(cos(angle)*radius, sin(angle)*radius); -} - -template<class NUM> -double Point<NUM>::getAngle() const -{ - return atan2(double(y), double(x)); -} - -template<> -Point<int> Point<int>::getNormalized() const -{ - AVG_ASSERT_MSG(false, "getNormalized undefined for IntPoint"); - return Point<int>(0,0); -} - -template<> -Point<double> Point<double>::getNormalized() const -{ - // This is imprecise but fast -#if defined(__SSE__) || defined(_WIN32) -#pragma pack(16) - float result[4]; - float normSqr = float(x*x+y*y); - __m128 src = _mm_setr_ps(float(x), float(y), 0, 0); - __m128 normSqrVec = _mm_set_ps1(normSqr); - __m128 invSqrt = _mm_rsqrt_ps(normSqrVec); - __m128 resultVec = _mm_mul_ps(src, invSqrt); - _mm_storeu_ps(result, resultVec); - return Point<double>(result[0], result[1]); -#pragma pack() -#else - double invNorm = invSqrt(float(x*x+y*y)); - if (invNorm != 0) { - return Point<double>(x*invNorm, y*invNorm); - } else { - return *this; - } -#endif -} - -template<> -Point<double> Point<double>::safeGetNormalized() const -{ - // This is precise but slower, and the version exported to python - if (x==0 && y==0) { - throw Exception(AVG_ERR_OUT_OF_RANGE, "Can't normalize (0,0)."); - } else { - double invNorm = 1/sqrt(x*x+y*y); - return Point<double>(x*invNorm, y*invNorm); - } -} - -template<> -Point<int> Point<int>::safeGetNormalized() const -{ - // Not implemented - done to silence compiler warnings. - AVG_ASSERT(false); - return Point<int>(0,0); -} - -template<class NUM> -std::ostream& operator<<( std::ostream& os, const Point<NUM> &p) -{ - os << "(" << p.x << "," << p.y << ")"; - return os; -} - -template<class NUM> -Point<NUM> operator *(double f, const Point<NUM>& pt) -{ - return pt*f; -} - -template<class NUM> -Point<NUM> operator /(double f, const Point<NUM>& pt) -{ - return pt/f; -} - -bool almostEqual(const DPoint& pt1, const DPoint& pt2) -{ - return (fabs(pt1.x-pt2.x)+fabs(pt1.y-pt2.y)) < 0.0001; -} - -double vecAngle(const DPoint& pt1, const DPoint pt2) -{ - double angle = fmod((atan2(pt1.y, pt1.x) - atan2(pt2.y, pt2.x)), 2*M_PI); - if (angle < 0) { - angle += 2*M_PI; - } - return angle; -} - -template<class NUM> -double calcDist(const Point<NUM>& pt1, const Point<NUM>& pt2) -{ - return sqrt(double(sqr(pt1.x-pt2.x)+sqr(pt1.y-pt2.y))); -} - -// Explicit instantiations. -template class Point<double>; -template std::ostream& operator<<( std::ostream& os, const Point<double> &p); -template Point<double> operator *(double f, const Point<double>& pt); -template Point<double> operator /(double f, const Point<double>& pt); -template double calcDist(const Point<double>& pt1, const Point<double>& pt2); -template double calcDistSquared(const Point<double>& pt1, const Point<double>& pt2); - -template class Point<int>; -template std::ostream& operator<<( std::ostream& os, const Point<int> &p); -template Point<int> operator *(double f, const Point<int>& pt); -template Point<int> operator /(double f, const Point<int>& pt); -template double calcDist(const Point<int>& pt1, const Point<int>& pt2); -template double calcDistSquared(const Point<int>& pt1, const Point<int>& pt2); - -} diff --git a/src/base/Point.h b/src/base/Point.h deleted file mode 100644 index 3156aed..0000000 --- a/src/base/Point.h +++ /dev/null @@ -1,124 +0,0 @@ -// -// libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow -// -// 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 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// Current versions can be found at www.libavg.de -// - -#ifndef _Point_H_ -#define _Point_H_ - -#include "../api.h" -#include "MathHelper.h" - -#include <ostream> -#include <vector> - -// Fix for non-C99 win compilers up to MSVC++2008 -#if defined _MSC_VER -#define isinf(x) (!_finite(x)) -#define isnan(x) (_isnan(x)) -#endif - -namespace avg { - -template<class NUM> -class AVG_TEMPLATE_API Point -{ -public: - NUM x; - NUM y; - - Point (); - template<class ORIGNUM> explicit Point(const Point<ORIGNUM>& p); - Point(NUM X, NUM Y); - Point(const Point<NUM>& p); - Point(const std::vector<NUM>& v); - ~Point(); - - Point<NUM> getNormalized() const; - Point<NUM> safeGetNormalized() const; - double getNorm() const; - bool isNaN() const; - bool isInf() const; - Point getRotated(double angle) const; - Point getRotatedPivot(double angle, const Point& pivot = Point(0,0)) const; - - Point<NUM> & operator =(const Point<NUM>& p); - - bool operator ==(const Point<NUM> & pt) const; - bool operator !=(const Point<NUM> & pt) const; - void operator +=(const Point<NUM> & pt); - void operator -=(const Point<NUM> & pt); - void operator *=(NUM f); - void operator /=(NUM f); - Point<NUM> operator -() const; - Point<NUM> operator +(const Point<NUM> & pt) const; - Point<NUM> operator -(const Point<NUM> & pt) const; - Point<NUM> operator /(double f) const; - Point<NUM> operator *(double f) const; - Point<NUM> operator *(const Point<NUM> & pt) const; - - static Point<NUM> fromPolar(double angle, double radius); - double getAngle() const; -}; - -template<class NUM> -std::ostream& operator<<( std::ostream& os, const Point<NUM> &p); - -template<class NUM> -Point<NUM> operator *(double f, const Point<NUM>& pt); - -template<class NUM> -Point<NUM> operator /(double f, const Point<NUM>& pt); - -template<class NUM> -template<class ORIGNUM> -Point<NUM>::Point(const Point<ORIGNUM>& p) - : x(NUM(p.x)), - y(NUM(p.y)) -{ -// ObjectCounter::get()->incRef(&typeid(*this)); -} - -template<class NUM> -double calcDist(const Point<NUM>& pt1, const Point<NUM>& pt2); - -template<class NUM> -double calcDistSquared(const Point<NUM>& pt1, const Point<NUM>& pt2) -{ - return sqr(pt1.x-pt2.x)+sqr(pt1.y-pt2.y); -} - -typedef Point<double> DPoint; -typedef Point<int> IntPoint; - -bool almostEqual(const DPoint& pt1, const DPoint& pt2); - -inline -double dotProduct(const DPoint& pt1, const DPoint pt2) -{ - return pt1.x*pt2.x+pt1.y*pt2.y; -} - -double vecAngle(const DPoint& pt1, const DPoint pt2); - -typedef std::vector<DPoint> DPointVector; - -} - -#endif diff --git a/src/base/ProfilingZone.cpp b/src/base/ProfilingZone.cpp index a12f5e3..9cdbbfe 100644 --- a/src/base/ProfilingZone.cpp +++ b/src/base/ProfilingZone.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -30,12 +30,11 @@ using namespace std; namespace avg { ProfilingZone::ProfilingZone(const ProfilingZoneID& zoneID) - : m_ZoneID(zoneID), - m_TimeSum(0), + : m_TimeSum(0), m_AvgTime(0), m_NumFrames(0), m_Indent(0), - m_bIsRegistered(false) + m_ZoneID(zoneID) { ObjectCounter::get()->incRef(&typeid(*this)); } @@ -45,6 +44,13 @@ ProfilingZone::~ProfilingZone() ObjectCounter::get()->decRef(&typeid(*this)); } +void ProfilingZone::restart() +{ + m_NumFrames = 0; + m_AvgTime = 0; + m_TimeSum = 0; +} + void ProfilingZone::reset() { m_NumFrames++; diff --git a/src/base/ProfilingZone.h b/src/base/ProfilingZone.h index f226d59..0d0ee42 100644 --- a/src/base/ProfilingZone.h +++ b/src/base/ProfilingZone.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -35,6 +35,7 @@ class AVG_API ProfilingZone public: ProfilingZone(const ProfilingZoneID& zoneID); virtual ~ProfilingZone(); + void restart(); void start() { @@ -53,13 +54,12 @@ public: const std::string& getName() const; private: - const ProfilingZoneID& m_ZoneID; long long m_TimeSum; long long m_AvgTime; long long m_StartTime; int m_NumFrames; int m_Indent; - bool m_bIsRegistered; + const ProfilingZoneID& m_ZoneID; }; typedef boost::shared_ptr<ProfilingZone> ProfilingZonePtr; diff --git a/src/base/ProfilingZoneID.cpp b/src/base/ProfilingZoneID.cpp index 025be66..7256887 100644 --- a/src/base/ProfilingZoneID.cpp +++ b/src/base/ProfilingZoneID.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -20,13 +20,16 @@ // #include "ProfilingZoneID.h" +#include "ThreadProfiler.h" using namespace std; namespace avg { -ProfilingZoneID::ProfilingZoneID(const string& sName) - : m_sName(sName) +ProfilingZoneID::ProfilingZoneID(const string& sName, bool bMultithreaded) + : m_sName(sName), + m_bMultithreaded(bMultithreaded), + m_pProfiler(0) { } @@ -39,4 +42,16 @@ const string& ProfilingZoneID::getName() const return m_sName; } +ThreadProfiler* ProfilingZoneID::getProfiler() +{ + if (!m_pProfiler) { + if (m_bMultithreaded) { + return ThreadProfiler::get(); + } else { + m_pProfiler = ThreadProfiler::get(); + } + } + return m_pProfiler; +} + } diff --git a/src/base/ProfilingZoneID.h b/src/base/ProfilingZoneID.h index c590b3d..ca4d637 100644 --- a/src/base/ProfilingZoneID.h +++ b/src/base/ProfilingZoneID.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -28,16 +28,21 @@ namespace avg { +class ThreadProfiler; + class AVG_API ProfilingZoneID { public: - ProfilingZoneID(const std::string& sName); - virtual ~ProfilingZoneID(); + ProfilingZoneID(const std::string& sName, bool bMultithreaded=false); + ~ProfilingZoneID(); const std::string& getName() const; + ThreadProfiler* getProfiler(); private: std::string m_sName; + bool m_bMultithreaded; + ThreadProfiler* m_pProfiler; }; } diff --git a/src/base/Queue.h b/src/base/Queue.h index 35c8d92..36a0eba 100644 --- a/src/base/Queue.h +++ b/src/base/Queue.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -34,7 +34,7 @@ namespace avg { -typedef boost::mutex::scoped_lock scoped_lock; +typedef boost::unique_lock<boost::mutex> unique_lock; template<class QElement> class AVG_TEMPLATE_API Queue @@ -42,18 +42,19 @@ class AVG_TEMPLATE_API Queue public: typedef boost::shared_ptr<QElement> QElementPtr; - Queue(int MaxSize=-1); + Queue(int maxSize=-1); virtual ~Queue(); bool empty() const; QElementPtr pop(bool bBlock = true); - void push(const QElementPtr& Elem); + void clear(); + void push(const QElementPtr& pElem); QElementPtr peek(bool bBlock = true) const; int size() const; int getMaxSize() const; private: - QElementPtr getFrontElement(bool bBlock, scoped_lock& Lock) const; + QElementPtr getFrontElement(bool bBlock, unique_lock& Lock) const; std::deque<QElementPtr> m_pElements; mutable boost::mutex m_Mutex; @@ -62,8 +63,8 @@ private: }; template<class QElement> -Queue<QElement>::Queue(int MaxSize) - : m_MaxSize(MaxSize) +Queue<QElement>::Queue(int maxSize) + : m_MaxSize(maxSize) { } @@ -75,15 +76,15 @@ Queue<QElement>::~Queue() template<class QElement> bool Queue<QElement>::empty() const { - scoped_lock Lock(m_Mutex); + unique_lock Lock(m_Mutex); return m_pElements.empty(); } template<class QElement> typename Queue<QElement>::QElementPtr Queue<QElement>::pop(bool bBlock) { - scoped_lock Lock(m_Mutex); - QElementPtr pElem = getFrontElement(bBlock, Lock); + unique_lock lock(m_Mutex); + QElementPtr pElem = getFrontElement(bBlock, lock); if (pElem) { m_pElements.pop_front(); m_Cond.notify_one(); @@ -92,10 +93,19 @@ typename Queue<QElement>::QElementPtr Queue<QElement>::pop(bool bBlock) } template<class QElement> +void Queue<QElement>::clear() +{ + QElementPtr pElem; + do { + pElem = pop(false); + } while (pElem); +} + +template<class QElement> typename Queue<QElement>::QElementPtr Queue<QElement>::peek(bool bBlock) const { - scoped_lock Lock(m_Mutex); - QElementPtr pElem = getFrontElement(bBlock, Lock); + unique_lock lock(m_Mutex); + QElementPtr pElem = getFrontElement(bBlock, lock); if (pElem) { m_Cond.notify_one(); } @@ -106,10 +116,10 @@ template<class QElement> void Queue<QElement>::push(const QElementPtr& pElem) { assert(pElem); - scoped_lock Lock(m_Mutex); + unique_lock lock(m_Mutex); if (m_pElements.size() == (unsigned)m_MaxSize) { while (m_pElements.size() == (unsigned)m_MaxSize) { - m_Cond.wait(Lock); + m_Cond.wait(lock); } } m_pElements.push_back(pElem); @@ -119,25 +129,25 @@ void Queue<QElement>::push(const QElementPtr& pElem) template<class QElement> int Queue<QElement>::size() const { - scoped_lock Lock(m_Mutex); + unique_lock lock(m_Mutex); return int(m_pElements.size()); } template<class QElement> int Queue<QElement>::getMaxSize() const { - scoped_lock Lock(m_Mutex); + unique_lock lock(m_Mutex); return m_MaxSize; } template<class QElement> typename Queue<QElement>::QElementPtr - Queue<QElement>::getFrontElement(bool bBlock, scoped_lock& Lock) const + Queue<QElement>::getFrontElement(bool bBlock, unique_lock& lock) const { if (m_pElements.empty()) { if (bBlock) { while (m_pElements.empty()) { - m_Cond.wait(Lock); + m_Cond.wait(lock); } } else { return QElementPtr(); diff --git a/src/base/Rect.h b/src/base/Rect.h index 25756de..d668338 100644 --- a/src/base/Rect.h +++ b/src/base/Rect.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,7 +23,9 @@ #define _Rect_H_ #include "../api.h" -#include "Point.h" + +#include "../base/GLMHelper.h" +#include "../glm/glm.hpp" #include <algorithm> @@ -36,29 +38,30 @@ template<class NUM> class AVG_TEMPLATE_API Rect { public: - Point<NUM> tl; - Point<NUM> br; + typedef glm::detail::tvec2<NUM> Vec2; + Vec2 tl; + Vec2 br; Rect(); Rect(NUM left, NUM top, NUM right, NUM bottom); - Rect(const Point<NUM>& TL, const Point<NUM>& BR); + Rect(const Vec2& TL, const Vec2& BR); template<class ORIGNUM> Rect(const Rect<ORIGNUM>& rc); bool operator ==(const Rect<NUM>& rect) const; bool operator !=(const Rect<NUM> & rect) const; NUM width() const; NUM height() const; - Point<NUM> center() const; + Vec2 center() const; void setWidth(NUM width); void setHeight(NUM height); - void setSize(const Point<NUM>& size); - bool contains(const Point<NUM>& pt) const; + void setSize(const Vec2& size); + bool contains(const Vec2& pt) const; bool contains(const Rect<NUM>& rect) const; bool intersects(const Rect<NUM>& rect) const; void expand(const Rect<NUM>& rect); void intersect(const Rect<NUM>& rect); - Point<NUM> size() const; - Point<NUM> cropPoint(const Point<NUM>& pt) const; + Vec2 size() const; + Vec2 cropPoint(const Vec2& pt) const; }; template<class NUM> @@ -69,7 +72,7 @@ std::ostream& operator<<( std::ostream& os, const Rect<NUM> &r) } -typedef Rect<double> DRect; +typedef Rect<float> FRect; typedef Rect<int> IntRect; template<class NUM> @@ -77,7 +80,7 @@ Rect<NUM>::Rect() {} template<class NUM> -Rect<NUM>::Rect(const Point<NUM>& TL, const Point<NUM>& BR) +Rect<NUM>::Rect(const Vec2& TL, const Vec2& BR) : tl(TL), br(BR) {} @@ -120,9 +123,9 @@ NUM Rect<NUM>::height() const } template<class NUM> -Point<NUM> Rect<NUM>::center() const +glm::detail::tvec2<NUM> Rect<NUM>::center() const { - return Point<NUM>(tl+br)/2; + return Vec2(tl+br)/2; } template<class NUM> @@ -138,14 +141,14 @@ void Rect<NUM>::setHeight(NUM height) } template<class NUM> -void Rect<NUM>::setSize(const Point<NUM>& size) +void Rect<NUM>::setSize(const Vec2& size) { setWidth(size.x); setHeight(size.y); } template<class NUM> -bool Rect<NUM>::contains(const Point<NUM>& pt) const +bool Rect<NUM>::contains(const Vec2& pt) const { return (pt.x >= tl.x && pt.x < br.x && pt.y >= tl.y && pt.y < br.y); @@ -154,7 +157,7 @@ bool Rect<NUM>::contains(const Point<NUM>& pt) const template<class NUM> bool Rect<NUM>::contains(const Rect<NUM>& rect) const { - Point<NUM> brpt (rect.br.x-1, rect.br.y-1); + Vec2 brpt (rect.br.x-1, rect.br.y-1); return Contains(rect.tl) && Contains(brpt); } @@ -171,31 +174,31 @@ bool Rect<NUM>::intersects(const Rect<NUM>& rect) const template<class NUM> void Rect<NUM>::expand(const Rect<NUM>& rect) { - tl.x = std::min(tl.x, rect.tl.x); - tl.y = std::min(tl.y, rect.tl.y); - br.x = std::max(br.x, rect.br.x); - br.y = std::max(br.y, rect.br.y); + tl.x = glm::min(tl.x, rect.tl.x); + tl.y = glm::min(tl.y, rect.tl.y); + br.x = glm::max(br.x, rect.br.x); + br.y = glm::max(br.y, rect.br.y); } template<class NUM> void Rect<NUM>::intersect(const Rect<NUM>& rect) { - tl.x = std::max(tl.x, rect.tl.x); - tl.y = std::max(tl.y, rect.tl.y); - br.x = std::min(br.x, rect.br.x); - br.y = std::min(br.y, rect.br.y); + tl.x = glm::max(tl.x, rect.tl.x); + tl.y = glm::max(tl.y, rect.tl.y); + br.x = glm::min(br.x, rect.br.x); + br.y = glm::min(br.y, rect.br.y); } template<class NUM> -Point<NUM> Rect<NUM>::size() const +glm::detail::tvec2<NUM> Rect<NUM>::size() const { - return Point<NUM>(width(), height()); + return Vec2(width(), height()); } template<class NUM> -Point<NUM> Rect<NUM>::cropPoint(const Point<NUM>& pt) const +glm::detail::tvec2<NUM> Rect<NUM>::cropPoint(const Vec2& pt) const { - Point<NUM> Result; + Vec2 Result; Result.x = std::min(std::max(pt.x, tl.x), br.x-1); Result.y = std::min(std::max(pt.y, tl.y), br.y-1); return Result; diff --git a/src/base/ScopeTimer.cpp b/src/base/ScopeTimer.cpp index 1a353e8..eb95736 100644 --- a/src/base/ScopeTimer.cpp +++ b/src/base/ScopeTimer.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -20,21 +20,16 @@ // #include "ScopeTimer.h" -#include "ThreadProfiler.h" using namespace std; namespace avg { -ScopeTimer::ScopeTimer(ProfilingZoneID& zoneID) - : m_ZoneID(zoneID) -{ - ThreadProfiler::get()->startZone(zoneID); -} +bool ScopeTimer::s_bTimersEnabled = false; -ScopeTimer::~ScopeTimer() +void ScopeTimer::enableTimers(bool bEnable) { - ThreadProfiler::get()->stopZone(m_ZoneID); + s_bTimersEnabled = bEnable; } } diff --git a/src/base/ScopeTimer.h b/src/base/ScopeTimer.h index de62eb2..a87263f 100644 --- a/src/base/ScopeTimer.h +++ b/src/base/ScopeTimer.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,16 +24,35 @@ #include "../api.h" #include "ProfilingZoneID.h" +#include "ThreadProfiler.h" namespace avg { - + class AVG_API ScopeTimer { public: - ScopeTimer(ProfilingZoneID& zoneID); - virtual ~ScopeTimer(); - + ScopeTimer(ProfilingZoneID& zoneID) + { + if (s_bTimersEnabled) { + m_pZoneID = &zoneID; + m_pZoneID->getProfiler()->startZone(zoneID); + } else { + m_pZoneID = 0; + } + }; + + ~ScopeTimer() + { + if (m_pZoneID) { + m_pZoneID->getProfiler()->stopZone(*m_pZoneID); + } + }; + + static void enableTimers(bool bEnable); + private: - ProfilingZoneID& m_ZoneID; + ProfilingZoneID* m_pZoneID; + + static bool s_bTimersEnabled; }; } diff --git a/src/base/Signal.h b/src/base/Signal.h index 0e6beb2..b670822 100644 --- a/src/base/Signal.h +++ b/src/base/Signal.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/StandardLogSink.cpp b/src/base/StandardLogSink.cpp new file mode 100644 index 0000000..510aa0b --- /dev/null +++ b/src/base/StandardLogSink.cpp @@ -0,0 +1,54 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de + +#include "StandardLogSink.h" +#include "Logger.h" + +#include <iostream> +#include <iomanip> + +using namespace std; + +namespace avg +{ + +StandardLogSink::StandardLogSink() +{ + +} + +StandardLogSink::~StandardLogSink() +{ + +} + +void StandardLogSink::logMessage(const tm* pTime, unsigned millis, + const category_t& category, severity_t severity, const UTF8String& sMsg) +{ + char timeString[256]; + strftime(timeString, sizeof(timeString), "%y-%m-%d %H:%M:%S", pTime); + cerr << "[" << timeString << "." << + setw(3) << setfill('0') << millis << setw(0) << "]["; + cerr << setw(4) << setfill('.') << Logger::severityToString(severity) << "]["; + cerr << setw(9) << setfill('.') << category << "] : " << sMsg << endl; + cerr.flush(); +} + +} diff --git a/src/base/CmdLine.h b/src/base/StandardLogSink.h index db57104..7cbfe2c 100644 --- a/src/base/CmdLine.h +++ b/src/base/StandardLogSink.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -17,34 +17,23 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // Current versions can be found at www.libavg.de -// - -#ifndef _CmdLine_H_ -#define _CmdLine_H_ -#include "../api.h" -#include <string> -#include <vector> -#include <map> +#ifndef _StandardLogSink_H_ +#define _StandardLogSink_H_ -namespace avg { +#include "ILogSink.h" -typedef std::map<std::string, std::string> OptionMap; +namespace avg{ -class AVG_API CmdLine { +class StandardLogSink: public ILogSink +{ public: - CmdLine(int argc, char **argv); + StandardLogSink(); + virtual ~StandardLogSink (); - const OptionMap& getOptions() const; - const std::string* getOption(const std::string& sName) const; - int getNumArgs() const; - const std::string* getArg(unsigned int i) const; - -private: - OptionMap m_Options; - std::vector<std::string> m_Args; + virtual void logMessage(const tm* pTime, unsigned millis, const category_t& category, + severity_t severity, const UTF8String& sMsg); }; } -#endif - +#endif diff --git a/src/base/StringHelper.cpp b/src/base/StringHelper.cpp index ba02038..6155859 100644 --- a/src/base/StringHelper.cpp +++ b/src/base/StringHelper.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -71,9 +71,9 @@ int stringToInt(const string& s) return i; } -double stringToDouble(const string& s) +float stringToFloat(const string& s) { - double d; + float d; fromString(s, d); return d; } @@ -92,28 +92,17 @@ bool stringToBool(const string& s) throw (Exception(AVG_ERR_TYPE, string("Could not convert ")+s+" to bool.")); } -DPoint stringToDPoint(const std::string& s) -{ - DPoint pt; - fromString(s, pt); - return pt; -} - -IntTriple stringToIntTriple(const std::string& s) -{ - IntTriple pt; - fromString(s, pt); - return pt; -} - std::string removeStartEndSpaces(const string& s) { string sResult = s; - while (sResult[0] == ' ' || sResult[0] == '\n' || sResult[0] == '\r' - || sResult[0] == '\t') + while (sResult.size() > 0 && (sResult[0] == ' ' || sResult[0] == '\n' + || sResult[0] == '\r' || sResult[0] == '\t')) { sResult.erase(0, 1); } + if (sResult.size() == 0) { + return sResult; + } char c = sResult[sResult.length()-1]; while (c == ' ' || c == '\n' || c == '\r' || c == '\t') { sResult.erase(sResult.length()-1, 1); @@ -143,5 +132,14 @@ bool equalIgnoreCase(const string& s1, const string& s2) return sUpper1 == sUpper2; } +string toString(const bool& b) +{ + if (b) { + return "true"; + } else { + return "false"; + } +} + } diff --git a/src/base/StringHelper.h b/src/base/StringHelper.h index 154a5f0..82713eb 100644 --- a/src/base/StringHelper.h +++ b/src/base/StringHelper.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,13 +24,12 @@ #include "../api.h" #include "Exception.h" -#include "Point.h" -#include "Triple.h" #include <string> #include <sstream> #include <typeinfo> #include <iostream> +#include <vector> #ifdef __GNUC__ #include <cxxabi.h> @@ -38,20 +37,9 @@ namespace avg { -bool isWhitespace(const std::string& s); -void skipWhitespace(std::istream& is); -void skipToken(std::istream& is, char token); - -template<class NUM> -std::istream& operator>>(std::istream& is, Point<NUM>& p) -{ - skipToken(is, '('); - is >> p.x; - skipToken(is, ','); - is >> p.y; - skipToken(is, ')'); - return is; -} +bool AVG_API isWhitespace(const std::string& s); +void AVG_API skipWhitespace(std::istream& is); +void AVG_API skipToken(std::istream& is, char token); template<class T> std::istream& operator >>(std::istream& is, std::vector<T>& v) @@ -86,17 +74,15 @@ std::istream& operator >>(std::istream& is, std::vector<T>& v) return is; } -int stringToInt(const std::string& s); -double stringToDouble(const std::string& s); -bool stringToBool(const std::string& s); -DPoint stringToDPoint(const std::string& s); -IntTriple stringToIntTriple(const std::string& s); +int AVG_API stringToInt(const std::string& s); +float AVG_API stringToFloat(const std::string& s); +bool AVG_API stringToBool(const std::string& s); -std::string removeStartEndSpaces(const std::string& s); +std::string AVG_API removeStartEndSpaces(const std::string& s); -std::string toLowerCase(const std::string& s); +std::string AVG_API toLowerCase(const std::string& s); -bool equalIgnoreCase(const std::string& s1, const std::string& s2); +bool AVG_API equalIgnoreCase(const std::string& s1, const std::string& s2); template<class T> std::string toString(const T& i) @@ -106,6 +92,8 @@ std::string toString(const T& i) return stream.str(); } +std::string AVG_API toString(const bool& b); + template<class T> std::string getFriendlyTypeName(const T& dummy) { diff --git a/src/base/Test.cpp b/src/base/Test.cpp index 8825d45..b2c0b12 100644 --- a/src/base/Test.cpp +++ b/src/base/Test.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -44,7 +44,7 @@ Test::~Test() { } -void Test::test (bool b, const char * pszFile, int line) +void Test::test(bool b, const char * pszFile, int line) { if (b) { m_NumSucceeded++; diff --git a/src/base/Test.h b/src/base/Test.h index ef39bc5..0cc20ba 100644 --- a/src/base/Test.h +++ b/src/base/Test.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -56,7 +56,6 @@ protected: int m_IndentLevel; private: - bool m_bOk; int m_NumSucceeded; int m_NumFailed; std::string m_sName; diff --git a/src/base/TestSuite.cpp b/src/base/TestSuite.cpp index 87130da..16a254c 100644 --- a/src/base/TestSuite.cpp +++ b/src/base/TestSuite.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -53,6 +53,10 @@ void TestSuite::runTests() } catch (Exception& ex) { cerr << string(m_IndentLevel, ' ') << ex.getStr() << endl; setFailed(); + } catch (std::exception& ex) { + cerr << string(m_IndentLevel, ' ') << " ---->> failed, std::exception: " + << ex.what() << endl; + setFailed(); } catch (...) { cerr << string(m_IndentLevel, ' ') << " ---->> failed, exception caught" << endl; diff --git a/src/base/TestSuite.h b/src/base/TestSuite.h index d85eef8..124bbc2 100644 --- a/src/base/TestSuite.h +++ b/src/base/TestSuite.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/ThreadHelper.cpp b/src/base/ThreadHelper.cpp new file mode 100644 index 0000000..105e116 --- /dev/null +++ b/src/base/ThreadHelper.cpp @@ -0,0 +1,94 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "ThreadHelper.h" +#include "OSHelper.h" + +#ifdef _WIN32 +#include <Windows.h> +#endif + +namespace avg { + +void setAffinityMask(bool bIsMainThread) +{ + // The main thread gets the first processor to itself. All other threads share the + // rest of the processors available, unless, of course, there is only one processor + // in the machine. +#ifdef linux + static cpu_set_t allProcessors; + static bool bInitialized = false; + if (!bInitialized) { + int rc = sched_getaffinity(0, sizeof(allProcessors), &allProcessors); + AVG_ASSERT(rc == 0); +// cerr << "All processors: "; +// printAffinityMask(allProcessors); + bInitialized = true; + } + cpu_set_t mask; + if (bIsMainThread) { + CPU_ZERO(&mask); + CPU_SET(0, &mask); +// cerr << "Main Thread: "; + } else { + mask = allProcessors; + if (CPU_COUNT(&mask) > 1) { + CPU_CLR(0, &mask); + } +// cerr << "Aux Thread: "; + } +// printAffinityMask(mask); + int rc = sched_setaffinity(0, sizeof(mask), &mask); + AVG_ASSERT(rc == 0); +#elif defined _WIN32 + DWORD processAffinityMask; + DWORD systemAffinityMask; + BOOL rc = GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, + &systemAffinityMask); + AVG_ASSERT(rc == TRUE); + DWORD mainThreadMask = 1 << getLowestBitSet(processAffinityMask); + DWORD mask; + if (bIsMainThread) { + mask = mainThreadMask; + } else { + mask = processAffinityMask & ~mainThreadMask; + if (mask == 0) { + mask = processAffinityMask; + } + } + DWORD_PTR pPrevMask = SetThreadAffinityMask(GetCurrentThread(), mask); + AVG_ASSERT_MSG(pPrevMask != 0, getWinErrMsg(GetLastError()).c_str()); +#endif +} + +unsigned getLowestBitSet(unsigned val) +{ + AVG_ASSERT(val != 0); // Doh + + unsigned pos = 0; + while (!(val & 1)) { + val >>= 1; + ++pos; + } + return pos; +} + +} diff --git a/src/base/ThreadHelper.h b/src/base/ThreadHelper.h new file mode 100644 index 0000000..7acf640 --- /dev/null +++ b/src/base/ThreadHelper.h @@ -0,0 +1,37 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef _ThreadHelper_H_ +#define _ThreadHelper_H_ + +#include "Exception.h" +#include <boost/thread.hpp> +#include <boost/thread/locks.hpp> + +namespace avg { + +void AVG_API setAffinityMask(bool bIsMainThread); +typedef boost::lock_guard<boost::mutex> lock_guard; +unsigned getLowestBitSet(unsigned val); + +} + +#endif diff --git a/src/base/ThreadProfiler.cpp b/src/base/ThreadProfiler.cpp index 12715c7..1f1a354 100644 --- a/src/base/ThreadProfiler.cpp +++ b/src/base/ThreadProfiler.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -20,8 +20,11 @@ // #include "ThreadProfiler.h" + #include "Logger.h" #include "Exception.h" +#include "ProfilingZone.h" +#include "ScopeTimer.h" #include <sstream> #include <iomanip> @@ -32,33 +35,37 @@ using namespace boost; namespace avg { -thread_specific_ptr<ThreadProfilerPtr> ThreadProfiler::s_pInstance; +thread_specific_ptr<ThreadProfiler*> ThreadProfiler::s_pInstance; -ThreadProfilerPtr& ThreadProfiler::get() +ThreadProfiler* ThreadProfiler::get() { if (s_pInstance.get() == 0) { - s_pInstance.reset(new ThreadProfilerPtr(new ThreadProfiler())); + s_pInstance.reset(new (ThreadProfiler*)); + *s_pInstance = new ThreadProfiler(); } return *s_pInstance; } void ThreadProfiler::kill() { + delete *s_pInstance; s_pInstance.reset(); } ThreadProfiler::ThreadProfiler() : m_sName(""), - m_LogCategory(Logger::PROFILE) + m_LogCategory(Logger::category::PROFILE) { m_bRunning = false; + ScopeTimer::enableTimers(Logger::get()->shouldLog(m_LogCategory, + Logger::severity::INFO)); } ThreadProfiler::~ThreadProfiler() { } -void ThreadProfiler::setLogCategory(long category) +void ThreadProfiler::setLogCategory(category_t category) { AVG_ASSERT(!m_bRunning); m_LogCategory = category; @@ -69,9 +76,12 @@ void ThreadProfiler::start() m_bRunning = true; } -bool ThreadProfiler::isRunning() +void ThreadProfiler::restart() { - return m_bRunning; + ZoneVector::iterator it; + for (it = m_Zones.begin(); it != m_Zones.end(); ++it) { + (*it)->restart(); + } } void ThreadProfiler::startZone(const ProfilingZoneID& zoneID) @@ -93,47 +103,34 @@ void ThreadProfiler::startZone(const ProfilingZoneID& zoneID) void ThreadProfiler::stopZone(const ProfilingZoneID& zoneID) { ZoneMap::iterator it = m_ZoneMap.find(&zoneID); - AVG_ASSERT(it != m_ZoneMap.end()); ProfilingZonePtr& pZone = it->second; - AVG_ASSERT(m_ActiveZones.back() == pZone); pZone->stop(); m_ActiveZones.pop_back(); } -void ThreadProfiler::dumpFrame() -{ - AVG_TRACE(Logger::PROFILE_LATEFRAMES, "Frame Profile:"); - ZoneList::iterator it; - for (it = m_Zones.begin(); it != m_Zones.end(); ++it) { - AVG_TRACE(Logger::PROFILE_LATEFRAMES, - std::setw(35) << std::left - << ((*it)->getIndentString() + (*it)->getName()) - << std::setw(9) << std::right << (*it)->getUSecs()); - } - AVG_TRACE(Logger::PROFILE_LATEFRAMES, ""); -} - void ThreadProfiler::dumpStatistics() { if (!m_Zones.empty()) { - AVG_TRACE(m_LogCategory, "Thread " << m_sName); - AVG_TRACE(m_LogCategory, "Zone name Avg. time"); - AVG_TRACE(m_LogCategory, "--------- ---------"); + AVG_TRACE(m_LogCategory, Logger::severity::INFO, "Thread " << m_sName); + AVG_TRACE(m_LogCategory, Logger::severity::INFO, + "Zone name Avg. time"); + AVG_TRACE(m_LogCategory, Logger::severity::INFO, + "--------- ---------"); - ZoneList::iterator it; + ZoneVector::iterator it; for (it = m_Zones.begin(); it != m_Zones.end(); ++it) { - AVG_TRACE(m_LogCategory, + AVG_TRACE(m_LogCategory, Logger::severity::INFO, std::setw(35) << std::left << ((*it)->getIndentString()+(*it)->getName()) << std::setw(9) << std::right << (*it)->getAvgUSecs()); } - AVG_TRACE(m_LogCategory, ""); + AVG_TRACE(m_LogCategory, Logger::severity::INFO, ""); } } void ThreadProfiler::reset() { - ZoneList::iterator it; + ZoneVector::iterator it; for (it = m_Zones.begin(); it != m_Zones.end(); ++it) { (*it)->reset(); } @@ -159,7 +156,7 @@ ProfilingZonePtr ThreadProfiler::addZone(const ProfilingZoneID& zoneID) { ProfilingZonePtr pZone(new ProfilingZone(zoneID)); m_ZoneMap[&zoneID] = pZone; - ZoneList::iterator it; + ZoneVector::iterator it; int parentIndent = -2; if (m_ActiveZones.empty()) { it = m_Zones.end(); @@ -176,7 +173,7 @@ ProfilingZonePtr ThreadProfiler::addZone(const ProfilingZoneID& zoneID) AVG_ASSERT(bParentFound); parentIndent = pActiveZone->getIndentLevel(); ++it; - for (; it != m_Zones.end() && (*it)->getIndentLevel() > parentIndent; ++it); + for (; it != m_Zones.end() && (*it)->getIndentLevel() > parentIndent; ++it) {}; } m_Zones.insert(it, pZone); pZone->setIndentLevel(parentIndent+2); diff --git a/src/base/ThreadProfiler.h b/src/base/ThreadProfiler.h index a571220..a581271 100644 --- a/src/base/ThreadProfiler.h +++ b/src/base/ThreadProfiler.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,34 +23,40 @@ #define _ThreadProfiler_H_ #include "../api.h" -#include "ProfilingZone.h" +#include "ILogSink.h" #include <boost/thread.hpp> #include <boost/shared_ptr.hpp> #include <boost/thread/tss.hpp> -#include <list> +#include <vector> #include <map> - +#if defined(_WIN32) || defined(_LIBCPP_VERSION) +#include <unordered_map> +#else +#include <tr1/unordered_map> +#endif namespace avg { class ThreadProfiler; typedef boost::shared_ptr<ThreadProfiler> ThreadProfilerPtr; +class ProfilingZone; +typedef boost::shared_ptr<ProfilingZone> ProfilingZonePtr; +class ProfilingZoneID; class AVG_API ThreadProfiler { public: - static ThreadProfilerPtr& get(); + static ThreadProfiler* get(); static void kill(); ThreadProfiler(); virtual ~ThreadProfiler(); - void setLogCategory(long category); + void setLogCategory(category_t category); void start(); - bool isRunning(); + void restart(); void startZone(const ProfilingZoneID& zoneID); void stopZone(const ProfilingZoneID& zoneID); - void dumpFrame(); void dumpStatistics(); void reset(); int getNumZones(); @@ -62,15 +68,19 @@ private: ProfilingZonePtr addZone(const ProfilingZoneID& zoneID); std::string m_sName; - typedef std::map<const ProfilingZoneID*, ProfilingZonePtr> ZoneMap; - typedef std::list<ProfilingZonePtr> ZoneList; +#if defined(_WIN32) || defined(_LIBCPP_VERSION) + typedef std::unordered_map<const ProfilingZoneID*, ProfilingZonePtr> ZoneMap; +#else + typedef std::tr1::unordered_map<const ProfilingZoneID*, ProfilingZonePtr> ZoneMap; +#endif + typedef std::vector<ProfilingZonePtr> ZoneVector; ZoneMap m_ZoneMap; - ZoneList m_ActiveZones; - ZoneList m_Zones; + ZoneVector m_ActiveZones; + ZoneVector m_Zones; bool m_bRunning; - long m_LogCategory; + category_t m_LogCategory; - static boost::thread_specific_ptr<ThreadProfilerPtr> s_pInstance; + static boost::thread_specific_ptr<ThreadProfiler*> s_pInstance; }; } diff --git a/src/base/TimeSource.cpp b/src/base/TimeSource.cpp index 320b3ff..e90575d 100644 --- a/src/base/TimeSource.cpp +++ b/src/base/TimeSource.cpp @@ -1,6 +1,6 @@ // -// libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -34,12 +34,12 @@ #endif #include <sys/stat.h> #include <sys/types.h> -#include <unistd.h> #include <errno.h> #include <assert.h> #include <iostream> #include <sstream> +#include <unistd.h> using namespace std; @@ -56,8 +56,8 @@ TimeSource * TimeSource::get() MMRESULT err = timeGetDevCaps(&tc, sizeof(TIMECAPS)); AVG_ASSERT(err == TIMERR_NOERROR); wTimerRes = max(tc.wPeriodMin, 1); - timeBeginPeriod(wTimerRes); -#endif + timeBeginPeriod(wTimerRes); +#endif m_pTimeSource = new TimeSource; } return m_pTimeSource; @@ -92,15 +92,15 @@ long long TimeSource::getCurrentMicrosecs() int rc = clock_gettime(CLOCK_MONOTONIC, &now); assert(rc == 0); return ((long long)now.tv_sec)*1000000+now.tv_nsec/1000; -#endif -#endif +#endif +#endif } void TimeSource::sleepUntil(long long targetTime) { long long now = getCurrentMillisecs(); #ifdef __APPLE__ - if (targetTime > now) { + if (targetTime > now) { msleep(targetTime-now); } #else @@ -114,7 +114,7 @@ void TimeSource::sleepUntil(long long targetTime) } #endif } - + void msleep(int millisecs) { #if _WIN32 diff --git a/src/base/TimeSource.h b/src/base/TimeSource.h index 63679fe..a4ca9ae 100644 --- a/src/base/TimeSource.h +++ b/src/base/TimeSource.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/src/base/Triangle.cpp b/src/base/Triangle.cpp index 039c643..7efe9f7 100644 --- a/src/base/Triangle.cpp +++ b/src/base/Triangle.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,11 +21,13 @@ #include "Triangle.h" +#include "GLMHelper.h" + #include <math.h> namespace avg { -Triangle::Triangle(const DPoint& P0, const DPoint& P1, const DPoint& P2) +Triangle::Triangle(const glm::vec2& P0, const glm::vec2& P1, const glm::vec2& P2) : p0(P0), p1(P1), p2(P2) @@ -41,48 +43,48 @@ bool Triangle::operator ==(const Triangle & tri) const return (p0 == tri.p0 && p1 == tri.p1 && p2 == tri.p2); } -bool Triangle::isInside(const DPoint& pt) const +bool Triangle::isInside(const glm::vec2& pt) const { /* Slower func that only works for cw triangles. - DPoint a = p2-p1; - DPoint bp = pt-p1; - double aCROSSbp = a.x*bp.y - a.y*bp.x; + glm::vec2 a = p2-p1; + glm::vec2 bp = pt-p1; + float aCROSSbp = a.x*bp.y - a.y*bp.x; if (aCROSSbp < 0.0) { return false; } - DPoint b = p0-p2; - DPoint cp = pt-p2; - double bCROSScp = b.x*cp.y - b.y*cp.x; + glm::vec2 b = p0-p2; + glm::vec2 cp = pt-p2; + float bCROSScp = b.x*cp.y - b.y*cp.x; if (bCROSScp < 0.0) { return false; } - DPoint c = p1-p0; - DPoint ap = pt-p0; - double cCROSSap = c.x*ap.y - c.y*ap.x; + glm::vec2 c = p1-p0; + glm::vec2 ap = pt-p0; + float cCROSSap = c.x*ap.y - c.y*ap.x; return cCROSSap >= 0.0; */ - DPoint v0 = p2 - p0; - DPoint v1 = p1 - p0; - DPoint v2 = pt - p0; + glm::vec2 v0 = p2 - p0; + glm::vec2 v1 = p1 - p0; + glm::vec2 v2 = pt - p0; - double dot00 = dotProduct(v0, v0); - double dot01 = dotProduct(v0, v1); - double dot02 = dotProduct(v0, v2); - double dot11 = dotProduct(v1, v1); - double dot12 = dotProduct(v1, v2); + float dot00 = glm::dot(v0, v0); + float dot01 = glm::dot(v0, v1); + float dot02 = glm::dot(v0, v2); + float dot11 = glm::dot(v1, v1); + float dot12 = glm::dot(v1, v2); - double invDenom = 1 / (dot00 * dot11 - dot01 * dot01); - double u = (dot11 * dot02 - dot01 * dot12) * invDenom; - double v = (dot00 * dot12 - dot01 * dot02) * invDenom; + float invDenom = 1 / (dot00 * dot11 - dot01 * dot01); + float u = (dot11 * dot02 - dot01 * dot12) * invDenom; + float v = (dot00 * dot12 - dot01 * dot02) * invDenom; return (u > 0) && (v > 0) && (u + v < 1); } -double Triangle::getArea() const +float Triangle::getArea() const { return fabs((((p1.x-p0.x)*(p2.y-p0.y)) - ((p1.y-p0.y)*(p2.x-p0.x)))/2); } diff --git a/src/base/Triangle.h b/src/base/Triangle.h index a9722fb..21ad35f 100644 --- a/src/base/Triangle.h +++ b/src/base/Triangle.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,22 +24,24 @@ #include "../api.h" -#include "Point.h" +#include "../glm/glm.hpp" + +#include <iostream> namespace avg { struct AVG_API Triangle { public: - DPoint p0; - DPoint p1; - DPoint p2; + glm::vec2 p0; + glm::vec2 p1; + glm::vec2 p2; - Triangle(const DPoint& P0, const DPoint& P1, const DPoint& P2); + Triangle(const glm::vec2& P0, const glm::vec2& P1, const glm::vec2& P2); Triangle(); bool operator ==(const Triangle & tri) const; - bool isInside(const DPoint& pt) const; - double getArea() const; + bool isInside(const glm::vec2& pt) const; + float getArea() const; bool isClockwise() const; }; diff --git a/src/base/Triangulate.cpp b/src/base/Triangulate.cpp deleted file mode 100644 index bbd9ef5..0000000 --- a/src/base/Triangulate.cpp +++ /dev/null @@ -1,139 +0,0 @@ -// Original code by John W. Ratcliff presumed to be in the public domain. Found -// at http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml. - -#include "Triangulate.h" -#include "Exception.h" - -#include "../base/Exception.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <iostream> - -namespace avg { - -using namespace std; - -double getPolygonArea(const DPointVector &contour) -{ - int n = contour.size(); - - double A=0.0; - - for (int p=n-1,q=0; q<n; p=q++) { - A += contour[p].x*contour[q].y - contour[q].x*contour[p].y; - } - return A*0.5; -} - - -bool snip(const DPointVector &contour,int u,int v,int w,int n,int *V) -{ - int p; - Triangle tri; - tri.p0 = contour[V[u]]; - tri.p1 = contour[V[v]]; - tri.p2 = contour[V[w]]; - -// double area = tri.getArea(); - - if (tri.isClockwise()) { - return false; - } - - for (p=0; p<n; p++) { - if( (p == u) || (p == v) || (p == w) ) { - continue; - } - if (tri.isInside(contour[V[p]])) { - return false; - } - } - - return true; -} - - -// TODO: There's code that's probably faster in Graphics Gems V: -// http://tog.acm.org/resources/GraphicsGems/gemsv/ch7-5/ -void triangulatePolygon(const DPointVector &contour, vector<int> &resultIndexes) -{ - /* allocate and initialize list of Vertices in polygon */ - - int n = contour.size(); - AVG_ASSERT(n>2); - - int *V = new int[n]; - - // we want a counter-clockwise polygon in V. - if (0.0 < getPolygonArea(contour)) { - for (int v=0; v<n; v++) { - V[v] = v; - } - } else { - for(int v=0; v<n; v++) { - V[v] = (n-1)-v; - } - } - - int nv = n; - - /* remove nv-2 Vertices, creating 1 triangle every time */ - int count = 2*nv; /* error detection */ - - for(int m=0, v=nv-1; nv>2; ) - { - if (count <= 0) { - delete V; - throw Exception(AVG_ERR_INVALID_ARGS, - "Non-simple polygon: Self-intersecting polygons or degenerate polygons are not supported."); - } - count--; - - /* three consecutive vertices in current polygon, <u,v,w> */ - int u = v; - if (nv <= u) { - u = 0; /* previous */ - } - v = u+1; - if (nv <= v) { - v = 0; - } - int w = v+1; - if (nv <= w) { - w = 0; - } - - if (snip(contour,u,v,w,nv,V)) - { - int a,b,c,s,t; - - /* true names of the vertices */ - a = V[u]; b = V[v]; c = V[w]; - - /* output Triangle */ - - resultIndexes.push_back(a); - resultIndexes.push_back(b); - resultIndexes.push_back(c); - - m++; - - /* remove v from remaining polygon */ - for(s=v,t=v+1; t<nv; s++,t++) { - V[s] = V[t]; - } - nv--; - - /* resest error detection counter */ - count = 2*nv; - - } - } - - delete[] V; -} - -} - diff --git a/src/base/Triangulate.h b/src/base/Triangulate.h deleted file mode 100644 index d2b4ef6..0000000 --- a/src/base/Triangulate.h +++ /dev/null @@ -1,22 +0,0 @@ -// Original code by John W. Ratcliff presumed to be in the public domain. Found -// at http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml. - -#ifndef _Triangulate_H_ -#define _Triangulate_H_ - -#include "Point.h" -#include "Triangle.h" - -#include <vector> - -namespace avg { - -// Result type is suitable for use in a Triangle Vertex Array. -void triangulatePolygon(const DPointVector &contour, std::vector<int> &resultIndexes); - -double getPolygonArea(const DPointVector &contour); - -} - -#endif - diff --git a/src/base/Triple.cpp b/src/base/Triple.cpp deleted file mode 100644 index 8249f72..0000000 --- a/src/base/Triple.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow -// -// 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 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// Current versions can be found at www.libavg.de -// - -#include "Triple.h" - -#include "MathHelper.h" -#include "StringHelper.h" -#include "Exception.h" - -#if defined(__SSE__) || defined(_WIN32) -#include <xmmintrin.h> -#endif - -#include <math.h> -#include <float.h> - -#include <string> - -namespace avg { - -template<class NUM> -Triple<NUM>::Triple() -{ - x = 0; - y = 0; - z = 0; -} - -template<class NUM> -Triple<NUM>::Triple(NUM X, NUM Y, NUM Z) -{ - x = X; - y = Y; - z = Z; -} - -template<class NUM> -Triple<NUM>::Triple(const Triple<NUM>& p) -{ - x = p.x; - y = p.y; - z = p.z; -} - - -template<class NUM> -Triple<NUM>::Triple(const std::vector<NUM>& v) -{ - AVG_ASSERT(v.size() == 3); - x = v[0]; - y = v[1]; - z = v[2]; -} - -template<class NUM> -Triple<NUM>::~Triple() -{ -} - -template<class NUM> -std::ostream& operator<<(std::ostream& os, const Triple<NUM> &p) -{ - os << "(" << p.x << "," << p.y << "," << p.z << ")"; - return os; -} - -template<class NUM> -std::istream& operator>>(std::istream& is, Triple<NUM>& p) -{ - skipToken(is, '('); - is >> p.x; - skipToken(is, ','); - is >> p.y; - skipToken(is, ','); - is >> p.z; - skipToken(is, ')'); - return is; -} - -// Explicit instantiations. -template class Triple<double>; -template std::ostream& operator<<(std::ostream& os, const Triple<double> &p); -template std::istream& operator>>(std::istream& is, Triple<double>& p); - -template class Triple<int>; -template std::ostream& operator<<(std::ostream& os, const Triple<int> &p); -template std::istream& operator>>(std::istream& is, Triple<int>& p); - -} diff --git a/src/base/UTF8String.cpp b/src/base/UTF8String.cpp index 214901b..4855364 100644 --- a/src/base/UTF8String.cpp +++ b/src/base/UTF8String.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -54,4 +54,9 @@ UTF8String& UTF8String::operator =(const char* psz) return *this; } +std::size_t hash_value(const avg::UTF8String& x) +{ + boost::hash<std::string> hasher; + return hasher(x); +}; } diff --git a/src/base/UTF8String.h b/src/base/UTF8String.h index 2c0f1be..3cee69d 100644 --- a/src/base/UTF8String.h +++ b/src/base/UTF8String.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,6 +23,7 @@ #define _UTF8String_H_ #include "../api.h" +#include <boost/functional/hash.hpp> #include <string> namespace avg { @@ -39,5 +40,7 @@ public: }; +std::size_t hash_value(const avg::UTF8String& x); + } #endif diff --git a/src/base/WideLine.cpp b/src/base/WideLine.cpp index 04e3162..84f4096 100644 --- a/src/base/WideLine.cpp +++ b/src/base/WideLine.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -21,24 +21,26 @@ #include "WideLine.h" +#include "GLMHelper.h" + namespace avg { -WideLine::WideLine(const DPoint& p0, const DPoint& p1, double width) +WideLine::WideLine(const glm::vec2& p0, const glm::vec2& p1, float width) : pt0(p0), pt1(p1) { - DPoint m = (pt1-pt0).getNormalized(); - DPoint w = DPoint(m.y, -m.x)*width/2; + glm::vec2 m = glm::normalize(pt1-pt0); + glm::vec2 w = glm::vec2(m.y, -m.x)*(width/2); pl0 = p0-w; pr0 = p0+w; pl1 = p1-w; pr1 = p1+w; - dir = DPoint(w.y, -w.x); + dir = glm::vec2(w.y, -w.x); } -double WideLine::getLen() const +float WideLine::getLen() const { - return calcDist(pt0, pt1); + return glm::length(pt1-pt0); } std::ostream& operator<<(std::ostream& os, const WideLine& line) diff --git a/src/base/WideLine.h b/src/base/WideLine.h index 0235c20..28584ef 100644 --- a/src/base/WideLine.h +++ b/src/base/WideLine.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -24,21 +24,21 @@ #include "../api.h" -#include "Point.h" +#include "../glm/glm.hpp" #include <iostream> namespace avg { struct AVG_API WideLine { - WideLine(const DPoint& p0, const DPoint& p1, double width); + WideLine(const glm::vec2& p0, const glm::vec2& p1, float width); - double getLen() const; + float getLen() const; - DPoint pt0, pt1; - DPoint pl0, pl1; - DPoint pr0, pr1; - DPoint dir; + glm::vec2 pt0, pt1; + glm::vec2 pl0, pl1; + glm::vec2 pr0, pr1; + glm::vec2 dir; }; std::ostream& operator<<(std::ostream& os, const WideLine& line); diff --git a/src/base/WorkerThread.cpp b/src/base/WorkerThread.cpp new file mode 100644 index 0000000..f2efb0a --- /dev/null +++ b/src/base/WorkerThread.cpp @@ -0,0 +1,41 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#include "WorkerThread.h" + +#include "OSHelper.h" + +namespace avg { + +using namespace std; + +#ifdef linux +void printAffinityMask(cpu_set_t& mask) +{ + for (int i=0; i<32; ++i) { + cerr << int(CPU_ISSET(i, &mask)); + } + cerr << endl; +} +#endif + +} + diff --git a/src/base/WorkerThread.h b/src/base/WorkerThread.h index 6e5dba0..c4cc3c4 100644 --- a/src/base/WorkerThread.h +++ b/src/base/WorkerThread.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -27,8 +27,8 @@ #include "Exception.h" #include "Logger.h" #include "Queue.h" +#include "ThreadHelper.h" #include "ThreadProfiler.h" -#include "ObjectCounter.h" #include "CmdQueue.h" #include <boost/shared_ptr.hpp> @@ -47,7 +47,7 @@ public: typedef typename boost::shared_ptr<CQueue> CQueuePtr; WorkerThread(const std::string& sName, CQueue& CmdQ, - long logCategory=Logger::PROFILE); + category_t logCategory=Logger::category::PROFILE); WorkerThread(WorkerThread const& other); virtual ~WorkerThread(); void operator()(); @@ -55,6 +55,9 @@ public: void waitForCommand(); void stop(); +protected: + int getNumCmdsInQueue() const; + private: virtual bool init(); virtual bool work() = 0; @@ -65,18 +68,17 @@ private: std::string m_sName; bool m_bShouldStop; CQueue& m_CmdQ; - long m_LogCategory; + category_t m_LogCategory; }; template<class DERIVED_THREAD> WorkerThread<DERIVED_THREAD>::WorkerThread(const std::string& sName, CQueue& CmdQ, - long logCategory) + category_t logCategory) : m_sName(sName), m_bShouldStop(false), m_CmdQ(CmdQ), m_LogCategory(logCategory) { - ObjectCounter::get()->incRef(&typeid(*this)); } template<class DERIVED_THREAD> @@ -86,20 +88,19 @@ WorkerThread<DERIVED_THREAD>::WorkerThread(WorkerThread const& other) m_sName = other.m_sName; m_bShouldStop = other.m_bShouldStop; m_LogCategory = other.m_LogCategory; - ObjectCounter::get()->incRef(&typeid(*this)); } template<class DERIVED_THREAD> WorkerThread<DERIVED_THREAD>::~WorkerThread() { - ObjectCounter::get()->decRef(&typeid(*this)); } template<class DERIVED_THREAD> void WorkerThread<DERIVED_THREAD>::operator()() { try { - ThreadProfilerPtr pProfiler = ThreadProfiler::get(); + setAffinityMask(false); + ThreadProfiler* pProfiler = ThreadProfiler::get(); pProfiler->setName(m_sName); pProfiler->setLogCategory(m_LogCategory); bool bOK; @@ -112,7 +113,8 @@ void WorkerThread<DERIVED_THREAD>::operator()() bOK = work(); if (!bOK) { m_bShouldStop = true; - } else { + } + if (!m_bShouldStop) { processCommands(); } } @@ -120,8 +122,7 @@ void WorkerThread<DERIVED_THREAD>::operator()() pProfiler->dumpStatistics(); pProfiler->kill(); } catch (const Exception& e) { - AVG_TRACE(Logger::ERROR, "Uncaught exception in thread " << m_sName << ": " - << e.getStr()); + AVG_LOG_ERROR("Uncaught exception in thread " << m_sName << ": " << e.getStr()); throw; } } @@ -140,6 +141,12 @@ void WorkerThread<DERIVED_THREAD>::stop() } template<class DERIVED_THREAD> +int WorkerThread<DERIVED_THREAD>::getNumCmdsInQueue() const +{ + return m_CmdQ.size(); +} + +template<class DERIVED_THREAD> bool WorkerThread<DERIVED_THREAD>::init() { return true; @@ -148,17 +155,13 @@ bool WorkerThread<DERIVED_THREAD>::init() template<class DERIVED_THREAD> void WorkerThread<DERIVED_THREAD>::processCommands() { - try { - CmdPtr pCmd = m_CmdQ.pop(false); - while (pCmd) { - pCmd->execute(dynamic_cast<DERIVED_THREAD*>(this)); + CmdPtr pCmd = m_CmdQ.pop(false); + while (pCmd && !m_bShouldStop) { + pCmd->execute(dynamic_cast<DERIVED_THREAD*>(this)); + if (!m_bShouldStop) { pCmd = m_CmdQ.pop(false); } - } catch (const Exception& e) { - AVG_TRACE(Logger::ERROR, "Uncaught exception in thread " - << m_sName << ": " << e.getStr()); } - } } diff --git a/src/base/XMLHelper.cpp b/src/base/XMLHelper.cpp index 0fa6bdf..6f362e8 100644 --- a/src/base/XMLHelper.cpp +++ b/src/base/XMLHelper.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -20,6 +20,8 @@ // #include "XMLHelper.h" +#include "Exception.h" +#include "Logger.h" #include <libxml/parserInternals.h> #include <cstring> @@ -75,4 +77,149 @@ void registerDTDEntityLoader(const string& sID, const string& sDTD) xmlSetExternalEntityLoader(DTDExternalEntityLoader); } + +XMLParser::XMLParser() + : m_SchemaParserCtxt(0), + m_Schema(0), + m_SchemaValidCtxt(0), + m_DTD(0), + m_DTDValidCtxt(0), + m_Doc(0) +{ + xmlPedanticParserDefault(1); + xmlSetGenericErrorFunc(this, errorOutputFunc); + xmlDoValidityCheckingDefaultValue = 0; +} + +XMLParser::~XMLParser() +{ + if (m_Schema) { + xmlSchemaFree(m_Schema); + } + if (m_SchemaParserCtxt) { + xmlSchemaFreeParserCtxt(m_SchemaParserCtxt); + } + if (m_SchemaValidCtxt) { + xmlSchemaFreeValidCtxt(m_SchemaValidCtxt); + } + if (m_DTD) { + xmlFreeDtd(m_DTD); + } + if (m_DTDValidCtxt) { + xmlFreeValidCtxt(m_DTDValidCtxt); + } + if (m_Doc) { + xmlFreeDoc(m_Doc); + } + xmlSetGenericErrorFunc(0, 0); +} + +void XMLParser::setSchema(const string& sSchema, const string& sSchemaName) +{ + AVG_ASSERT(!m_SchemaParserCtxt); + AVG_ASSERT(!m_Schema); + AVG_ASSERT(!m_SchemaValidCtxt); + AVG_ASSERT(!m_DTD); + AVG_ASSERT(!m_DTDValidCtxt); + + m_SchemaParserCtxt = xmlSchemaNewMemParserCtxt(sSchema.c_str(), sSchema.length()); + checkError(!m_SchemaParserCtxt, sSchemaName); + + m_Schema = xmlSchemaParse(m_SchemaParserCtxt); + checkError(!m_Schema, sSchemaName); + + m_SchemaValidCtxt = xmlSchemaNewValidCtxt(m_Schema); + checkError(!m_SchemaValidCtxt, sSchemaName); +} + +void XMLParser::setDTD(const std::string& sDTD, const std::string& sDTDName) +{ + AVG_ASSERT(!m_SchemaParserCtxt); + AVG_ASSERT(!m_Schema); + AVG_ASSERT(!m_SchemaValidCtxt); + AVG_ASSERT(!m_DTD); + AVG_ASSERT(!m_DTDValidCtxt); + + registerDTDEntityLoader("memory.dtd", sDTD.c_str()); + string sDTDFName = "memory.dtd"; + m_DTD = xmlParseDTD(NULL, (const xmlChar*) sDTDFName.c_str()); + checkError(!m_DTD, sDTDName); + + m_DTDValidCtxt = xmlNewValidCtxt(); + checkError(!m_DTDValidCtxt, sDTDName); + m_DTDValidCtxt->error = xmlParserValidityError; + m_DTDValidCtxt->warning = xmlParserValidityWarning; +} + +void XMLParser::parse(const string& sXML, const string& sXMLName) +{ + if (m_Doc) { + xmlFreeDoc(m_Doc); + } + m_Doc = xmlParseMemory(sXML.c_str(), int(sXML.length())); + checkError(!m_Doc, sXMLName); + + bool bOK = true; + if (m_SchemaValidCtxt) { + int err = xmlSchemaValidateDoc(m_SchemaValidCtxt, m_Doc); + AVG_ASSERT(err != -1); + bOK = (err == 0); + } + if (m_DTD) { + int err = xmlValidateDtd(m_DTDValidCtxt, m_Doc, m_DTD); + bOK = (err != 0); + } + if (!bOK) { + xmlFreeDoc(m_Doc); + m_Doc = 0; + checkError(true, sXMLName); + } +} + +xmlDocPtr XMLParser::getDoc() +{ + AVG_ASSERT(m_Doc); + return m_Doc; +} + +xmlNodePtr XMLParser::getRootNode() +{ + AVG_ASSERT(m_Doc); + return xmlDocGetRootElement(m_Doc); +} + +void XMLParser::errorOutputFunc(void * ctx, const char * msg, ...) +{ + va_list args; + va_start(args, msg); + ((XMLParser*)ctx)->internalErrorHandler(msg, args); + va_end(args); +} + +void XMLParser::internalErrorHandler(const char * msg, va_list args) +{ + char psz[1024]; + vsnprintf(psz, 1024, msg, args); + m_sError += psz; +} + +void XMLParser::checkError(bool bError, const string& sXMLName) +{ + if (bError) { + string sError = "Error parsing "+sXMLName+".\n"; + sError += m_sError; + m_sError = ""; + throw (Exception(AVG_ERR_XML_PARSE, sError)); + } +} + +void validateXml(const string& sXML, const string& sSchema, const string& sXMLName, + const string& sSchemaName) +{ + XMLParser parser; + parser.setSchema(sSchema, sSchemaName); + + parser.parse(sXML, sXMLName); +} + } diff --git a/src/base/XMLHelper.h b/src/base/XMLHelper.h index 5557faf..e258de2 100644 --- a/src/base/XMLHelper.h +++ b/src/base/XMLHelper.h @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -23,10 +23,10 @@ #define _XMLHelper_H_ #include "../api.h" -#include "Point.h" #include <libxml/parser.h> #include <libxml/xmlwriter.h> +#include <libxml/xmlschemas.h> #include <string> #include <map> @@ -38,7 +38,41 @@ std::string getXmlChildrenAsString(const xmlDocPtr xmlDoc, const xmlNodePtr& xml void registerDTDEntityLoader(const std::string& sID, const std::string& sDTD); +class XMLParser +{ +public: + XMLParser(); + virtual ~XMLParser(); + + void setSchema(const std::string& sSchema, const std::string& sSchemaName); + void setDTD(const std::string& sDTD, const std::string& sDTDName); + void parse(const std::string& sXML, const std::string& sXMLName); + + xmlDocPtr getDoc(); + xmlNodePtr getRootNode(); + +private: + static void errorOutputFunc(void * ctx, const char * msg, ...); + void internalErrorHandler(const char * msg, va_list args); + + void checkError(bool bError, const std::string& sXMLName); + + xmlSchemaParserCtxtPtr m_SchemaParserCtxt; + xmlSchemaPtr m_Schema; + xmlSchemaValidCtxtPtr m_SchemaValidCtxt; + + xmlDtdPtr m_DTD; + xmlValidCtxtPtr m_DTDValidCtxt; + + xmlDocPtr m_Doc; + + std::string m_sError; +}; + +void validateXml(const std::string& sXML, const std::string& sSchema, + const std::string& sXMLName, const std::string& sSchemaName); + } -#endif //_XMLHelper_H_ +#endif diff --git a/src/base/testbase.cpp b/src/base/testbase.cpp index 656714e..57faf36 100644 --- a/src/base/testbase.cpp +++ b/src/base/testbase.cpp @@ -1,6 +1,6 @@ // // libavg - Media Playback Engine. -// Copyright (C) 2003-2011 Ulrich von Zadow +// Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -19,13 +19,13 @@ // Current versions can be found at www.libavg.de // +#include "DAG.h" #include "Queue.h" #include "Command.h" #include "WorkerThread.h" #include "ObjectCounter.h" -#include "Point.h" -#include "Matrix3x4.h" -#include "Triangulate.h" +#include "triangulate/Triangulate.h" +#include "GLMHelper.h" #include "GeomHelper.h" #include "OSHelper.h" #include "FileHelper.h" @@ -35,9 +35,13 @@ #include "BezierCurve.h" #include "Signal.h" #include "Backtrace.h" - +#include "WideLine.h" +#include "Rect.h" +#include "Triangle.h" #include "TestSuite.h" #include "TimeSource.h" +#include "XMLHelper.h" +#include "Logger.h" #include <boost/thread/thread.hpp> @@ -52,6 +56,102 @@ using namespace avg; using namespace std; using namespace boost; +class DAGTest: public Test +{ +public: + DAGTest() + : Test("DAGTest", 2) + { + } + + void runTests() + { + { + DAG dag; + + dag.addNode(1, set<long>()); + long outgoing2[] = {1}; + dag.addNode(0, makeOutgoing(1, outgoing2)); + + long expected[] = {0, 1}; + checkResults(&dag, expected); + } + { + DAG dag; + + dag.addNode(2, set<long>()); + long outgoing2[] = {1}; + dag.addNode(0, makeOutgoing(1, outgoing2)); + long outgoing3[] = {2}; + dag.addNode(1, makeOutgoing(1, outgoing3)); + + long expected[] = {0, 1, 2}; + checkResults(&dag, expected); + } + { + DAG dag; + + long outgoing2[] = {1}; + dag.addNode(0, makeOutgoing(1, outgoing2)); + dag.addNode(2, set<long>()); + long outgoing3[] = {2}; + dag.addNode(1, makeOutgoing(1, outgoing3)); + + long expected[] = {0, 1, 2}; + checkResults(&dag, expected); + } + { + DAG dag; + + dag.addNode(2, set<long>()); + long outgoing2[] = {1, 2}; + dag.addNode(0, makeOutgoing(1, outgoing2)); + long outgoing3[] = {2}; + dag.addNode(1, makeOutgoing(1, outgoing3)); + + long expected[] = {0, 1, 2}; + checkResults(&dag, expected); + } + { + DAG dag; + + long outgoing2[] = {1}; + dag.addNode(0, makeOutgoing(1, outgoing2)); + long outgoing3[] = {0}; + dag.addNode(1, makeOutgoing(1, outgoing3)); + + bool bExceptionThrown = false; + long expected[] = {0, 1, 2}; + try { + checkResults(&dag, expected); + } catch (const Exception&) { + bExceptionThrown = true; + } + TEST(bExceptionThrown); + } + } + +private: + set<long> makeOutgoing(int n, long ids[]) + { + set<long> v; + for (int i=0; i<n; ++i) { + v.insert(ids[i]); + } + return v; + } + + void checkResults(DAG* pDAG, long expected[]) + { + vector<long> results; + pDAG->sort(results); + + for (unsigned i=0; i<results.size(); ++i) { + QUIET_TEST(results[i] == expected[i]); + } + } +}; + class QueueTest: public Test { public: @@ -67,6 +167,8 @@ public: } private: + typedef Queue<int>::QElementPtr ElemPtr; + void runSingleThreadTests() { Queue<string> q; @@ -92,7 +194,7 @@ private: void runMultiThreadTests() { { - Queue<string> q(10); + Queue<int> q(10); thread pusher(boost::bind(&pushThread, &q, 100)); thread popper(boost::bind(&popThread, &q, 100)); pusher.join(); @@ -100,7 +202,7 @@ private: TEST(q.empty()); } { - Queue<string> q(10); + Queue<int> q(10); thread pusher1(boost::bind(&pushThread, &q, 100)); thread pusher2(boost::bind(&pushThread, &q, 100)); thread popper(boost::bind(&popThread, &q, 200)); @@ -109,21 +211,25 @@ private: popper.join(); TEST(q.empty()); } + { + Queue<int> q(10); + thread pusher(boost::bind(&pushClearThread, &q, 100)); + thread popper(boost::bind(&popClearThread, &q)); + pusher.join(); + popper.join(); + TEST(q.empty()); + } } - static void pushThread(Queue<string>* pq, int numPushes) + static void pushThread(Queue<int>* pq, int numPushes) { - typedef Queue<string>::QElementPtr ElemPtr; for (int i=0; i<numPushes; ++i) { - stringstream ss; - ss << i; - string s = ss.str(); - pq->push(ElemPtr(new string(s))); + pq->push(ElemPtr(new int(i))); msleep(1); } } - static void popThread(Queue<string>* pq, int numPops) + static void popThread(Queue<int>* pq, int numPops) { for (int i=0; i<numPops; ++i) { pq->peek(); @@ -131,6 +237,27 @@ private: msleep(3); } } + + static void pushClearThread(Queue<int>* pq, int numPushes) + { + typedef Queue<int>::QElementPtr ElemPtr; + for (int i=0; i<numPushes; ++i) { + pq->push(ElemPtr(new int(i))); + if (i%7 == 0) { + pq->clear(); + } + msleep(1); + } + pq->push(ElemPtr(new int(-1))); + } + + static void popClearThread(Queue<int>* pq) + { + ElemPtr pElem; + do { + pElem = pq->pop(); + } while (*pElem != -1); + } }; class TestWorkerThread: public WorkerThread<TestWorkerThread> @@ -248,103 +375,79 @@ public: #pragma warning(push) #pragma warning(disable:4723) #endif -class PointTest: public Test +class GeomTest: public Test { public: - PointTest() - : Test("PointTest", 2) + GeomTest() + : Test("GeomTest", 2) { } void runTests() { - double one = 1; - double zero = 0; - - TEST(isinf(-one/zero) != 0); - TEST(isinf(one/zero) != 0); - TEST(isinf(one) == 0); - TEST(isnan(sqrt(-one)) != 0); - TEST(isnan(sqrt(one+one)) == 0); - // TODO: Move to a separate math test once we're done here. TEST(almostEqual(invSqrt(1), 1)); TEST(almostEqual(invSqrt(4), 0.5)); - // TODO: The point tests aren't complete! - DPoint pt1(0,0); - DPoint pt2(3,4); - TEST(calcDist(pt1, pt2)-5 < 0.0001); - TEST(!almostEqual(pt1, pt2)); - TEST(almostEqual(pt1, pt1)); - std::vector<double> v; - v.push_back(3); - v.push_back(4); - DPoint pt3(v); - TEST(almostEqual(pt2, pt3)); - TEST(almostEqual(pt3.getNorm(), 5)); - DPoint pt4 = pt3.getNormalized(); - TEST(almostEqual(pt4.getNorm(), 1, 0.0001)); { - DLineSegment l1(DPoint(0,0), DPoint(2,2)); - DLineSegment l2(DPoint(2,0), DPoint(0,2)); + LineSegment l1(glm::vec2(0,0), glm::vec2(2,2)); + LineSegment l2(glm::vec2(2,0), glm::vec2(0,2)); TEST(lineSegmentsIntersect(l1, l2)); TEST(lineSegmentsIntersect(l2, l1)); } { - DLineSegment l1(DPoint(0,0), DPoint(0,2)); - DLineSegment l2(DPoint(2,0), DPoint(2,2)); + LineSegment l1(glm::vec2(0,0), glm::vec2(0,2)); + LineSegment l2(glm::vec2(2,0), glm::vec2(2,2)); TEST(!lineSegmentsIntersect(l1, l2)); } { - DLineSegment l1(DPoint(0,0), DPoint(2,0)); - DLineSegment l2(DPoint(0,2), DPoint(2,2)); + LineSegment l1(glm::vec2(0,0), glm::vec2(2,0)); + LineSegment l2(glm::vec2(0,2), glm::vec2(2,2)); TEST(!lineSegmentsIntersect(l1, l2)); } { - DLineSegment l1(DPoint(0,0), DPoint(2,0)); - TEST(l1.isPointOver(DPoint(1,23))); - TEST(l1.isPointOver(DPoint(1.9,-5))); - TEST(!l1.isPointOver(DPoint(-1,1))); - TEST(!l1.isPointOver(DPoint(3,-1))); + LineSegment l1(glm::vec2(0,0), glm::vec2(2,0)); + TEST(l1.isPointOver(glm::vec2(1,23))); + TEST(l1.isPointOver(glm::vec2(1.9,-5))); + TEST(!l1.isPointOver(glm::vec2(-1,1))); + TEST(!l1.isPointOver(glm::vec2(3,-1))); } { - DPoint pt0(DPoint(1,1)); - DPoint pt1(DPoint(1,3)); - DPoint pt2(DPoint(1,-2)); - vector<DPoint> poly; - poly.push_back(DPoint(0,0)); - poly.push_back(DPoint(2,0)); - poly.push_back(DPoint(2,2)); - poly.push_back(DPoint(0,2)); + glm::vec2 pt0(glm::vec2(1,1)); + glm::vec2 pt1(glm::vec2(1,3)); + glm::vec2 pt2(glm::vec2(1,-2)); + vector<glm::vec2> poly; + poly.push_back(glm::vec2(0,0)); + poly.push_back(glm::vec2(2,0)); + poly.push_back(glm::vec2(2,2)); + poly.push_back(glm::vec2(0,2)); TEST(pointInPolygon(pt0, poly)); TEST(!pointInPolygon(pt1, poly)); TEST(!pointInPolygon(pt2, poly)); - poly.push_back(DPoint(2,1)); + poly.push_back(glm::vec2(2,1)); TEST(!pointInPolygon(pt0, poly)); } { - DPoint p1(DPoint(0,0)); - DPoint v1(DPoint(1,1)); - DPoint p2(DPoint(2,1)); - DPoint v2(DPoint(1,0)); - TEST(getLineLineIntersection(p1, v1, p2, v2) == DPoint(1,1)); - } - TEST(almostEqual(DPoint(10,0).getRotatedPivot(M_PI, DPoint(15,5)), DPoint(20,10))); - TEST(almostEqual(DPoint(10,0).getRotatedPivot(M_PI*0.5, DPoint(15,5)), - DPoint(20,0))); - TEST(almostEqual(DPoint(10,0).getRotatedPivot(M_PI*1.5, DPoint(15,5)), - DPoint(10,10))); - TEST(almostEqual(DPoint(10,0).getRotatedPivot(M_PI*2, DPoint(15,5)), - DPoint(10,0))); - TEST(almostEqual(DPoint(23,0).getRotatedPivot(M_PI*0.5), DPoint(0,23))); - - TEST(almostEqual(DPoint(10,0), DPoint::fromPolar(0, 10))); - TEST(almostEqual(DPoint(0,10), DPoint::fromPolar(M_PI*0.5, 10))); - TEST(almostEqual(DPoint(0,-1), DPoint::fromPolar(M_PI*1.5, 1))); - TEST(almostEqual(vecAngle(DPoint(0,1),DPoint(1,0)), M_PI*0.5)); - TEST(almostEqual(vecAngle(DPoint(0,-1),DPoint(1,0)), M_PI*1.5)); - TEST(almostEqual(vecAngle(DPoint(0,2),DPoint(1,0)), M_PI*0.5)); + glm::vec2 p1(glm::vec2(0,0)); + glm::vec2 v1(glm::vec2(1,1)); + glm::vec2 p2(glm::vec2(2,1)); + glm::vec2 v2(glm::vec2(1,0)); + TEST(getLineLineIntersection(p1, v1, p2, v2) == glm::vec2(1,1)); + } + TEST(almostEqual(getRotatedPivot(glm::vec2(10,0), M_PI, glm::vec2(15,5)), + glm::vec2(20,10))); + TEST(almostEqual(getRotatedPivot(glm::vec2(10,0), M_PI*0.5, glm::vec2(15,5)), + glm::vec2(20,0))); + TEST(almostEqual(getRotatedPivot(glm::vec2(10,0), M_PI*1.5, glm::vec2(15,5)), + glm::vec2(10,10))); + TEST(almostEqual(getRotatedPivot(glm::vec2(10,0), M_PI*2, glm::vec2(15,5)), + glm::vec2(10,0))); + TEST(almostEqual(getRotatedPivot(glm::vec2(23,0), M_PI*0.5), glm::vec2(0,23))); + + { + // TODO: More tests + FRect(0,0,10,10); + } } }; #ifdef _MSC_VER @@ -353,32 +456,6 @@ public: #endif -class Matrix3x4Test: public Test -{ -public: - Matrix3x4Test() - : Test("Matrix3x4Test", 2) - { - } - - void runTests() - { - Matrix3x4 mat1; - Matrix3x4 mat2; - mat1 *= mat2; - TEST(almostEqual(mat1, Matrix3x4())); - - mat2 = Matrix3x4::createTranslate(0,0,0); - mat1 *= mat2; - TEST(almostEqual(mat1, Matrix3x4())); - - mat2 = Matrix3x4::createScale(1,1,1); - mat1 *= mat2; - TEST(almostEqual(mat1, Matrix3x4())); - } -}; - - class TriangleTest: public Test { public: @@ -389,31 +466,30 @@ public: void runTests() { - Triangle tri(DPoint(0,0), DPoint(4,4), DPoint(4,8)); - TEST(tri.isInside(DPoint(3,4))); - TEST(!tri.isInside(DPoint(1,4))); - TEST(!tri.isInside(DPoint(2,1))); - TEST(!tri.isInside(DPoint(-2,5))); - TEST(!tri.isInside(DPoint(5,5))); - tri = Triangle(DPoint(0,0), DPoint(4,8), DPoint(4,4)); - TEST(tri.isInside(DPoint(3,4))); - - DPoint polyArray[] = {DPoint(0,0), DPoint(8,2), DPoint(9,0), DPoint(9,3), - DPoint(1,1), DPoint(0,3)}; - - DPointVector poly = vectorFromCArray(6, polyArray); - - vector<int> triangulation; - triangulatePolygon(poly, triangulation); + Triangle tri(glm::vec2(0,0), glm::vec2(4,4), glm::vec2(4,8)); + TEST(tri.isInside(glm::vec2(3,4))); + TEST(!tri.isInside(glm::vec2(1,4))); + TEST(!tri.isInside(glm::vec2(2,1))); + TEST(!tri.isInside(glm::vec2(-2,5))); + TEST(!tri.isInside(glm::vec2(5,5))); + tri = Triangle(glm::vec2(0,0), glm::vec2(4,8), glm::vec2(4,4)); + TEST(tri.isInside(glm::vec2(3,4))); + + glm::vec2 polyArray[] = {glm::vec2(0,0), glm::vec2(8,2), glm::vec2(9,0), glm::vec2(9,3), + glm::vec2(1,1), glm::vec2(0,3)}; + + Vec2Vector poly = vectorFromCArray(6, polyArray); + vector<unsigned int> triangulation; + triangulatePolygon(triangulation, poly); TEST(triangulation.size() == 4*3); - int baselineIndexes[] = {1,2,3, 4,5,0, 0,1,3, 3,4,0}; + unsigned int baselineIndexes[] = {5,0,4, 1,4,0, 4,1,3, 1,2,3}; TEST(triangulation == vectorFromCArray(12, baselineIndexes)); -/* +/* for (unsigned int i=0; i<triangulation.size(); i++) { cerr << i << ":" << triangulation[i] << endl; } -*/ +*/ } }; @@ -445,9 +521,8 @@ public: void runTests() { -#if defined(__APPLE__) || defined(_WIN32) + cerr << getAvgLibPath() << endl; TEST(getAvgLibPath() != ""); -#endif #ifdef __APPLE__ TEST(getMemoryUsage() != 0); #endif @@ -466,7 +541,7 @@ public: void runTests() { TEST(stringToInt("5") == 5); - TEST(almostEqual(stringToDouble("5.5"), 5.5)); + TEST(almostEqual(stringToFloat("5.5"), 5.5f)); TEST(stringToBool("False") == false); bool bExceptionThrown = false; try { @@ -477,8 +552,8 @@ public: } } TEST(bExceptionThrown); - TEST(stringToDPoint(" ( 3.4 , 2.1 ) ") == DPoint(3.4, 2.1)); - vector<double> v; + TEST(stringToVec2(" ( 3.4 , 2.1 ) ") == glm::vec2(3.4f, 2.1f)); + vector<float> v; fromString("(1,2,3,4,5)", v); TEST(v.size() == 5 && v[0] == 1 && v[4] == 5); v.clear(); @@ -499,10 +574,10 @@ public: void runTests() { { - double xd[] = {0,1,2,3}; - vector<double> x = vectorFromCArray(4, xd); - double yd[] = {3,2,1,0}; - vector<double> y = vectorFromCArray(4, yd); + float xd[] = {0,1,2,3}; + vector<float> x = vectorFromCArray(4, xd); + float yd[] = {3,2,1,0}; + vector<float> y = vectorFromCArray(4, yd); CubicSpline spline(x, y); TEST(almostEqual(spline.interpolate(-1), 4)); TEST(almostEqual(spline.interpolate(0), 3)); @@ -511,19 +586,46 @@ public: TEST(almostEqual(spline.interpolate(3.5), -0.5)); } { - double xd[] = {2,4,6,8}; - vector<double> x = vectorFromCArray(4, xd); - double yd[] = {0,1,3,6}; - vector<double> y = vectorFromCArray(4, yd); + float xd[] = {2,4,6,8}; + vector<float> x = vectorFromCArray(4, xd); + float yd[] = {0,1,3,6}; + vector<float> y = vectorFromCArray(4, yd); CubicSpline spline(x, y); TEST(almostEqual(spline.interpolate(0), -1)); - TEST(almostEqual(spline.interpolate(1), -0.5)); TEST(almostEqual(spline.interpolate(2), 0)); TEST(spline.interpolate(3) < 0.5); + TEST(spline.interpolate(3) > 0); + TEST(spline.interpolate(7) > 4); + TEST(spline.interpolate(7) < 5); TEST(almostEqual(spline.interpolate(8), 6)); - TEST(almostEqual(spline.interpolate(9), 7.5)); TEST(almostEqual(spline.interpolate(10), 9)); } + { + float xd[] = {0,1,1}; + vector<float> x = vectorFromCArray(3, xd); + float yd[] = {1,2,1}; + vector<float> y = vectorFromCArray(3, yd); + bool bExceptionThrown = false; + try { + CubicSpline spline(x, y); + } catch (const Exception&) { + bExceptionThrown = true; + } + TEST(bExceptionThrown); + } +/* + { + float xd[] = {0,1,2}; + vector<float> x = vectorFromCArray(3, xd); + float yd[] = {1,2,1}; + vector<float> y = vectorFromCArray(3, yd); + CubicSpline spline(x, y, true); + TEST(almostEqual(spline.interpolate(0), 1)); + TEST(almostEqual(spline.interpolate(0.5), 1.5)); + TEST(almostEqual(spline.interpolate(2), 1)); + TEST(almostEqual(spline.interpolate(3), 2)); + } +*/ } }; @@ -538,12 +640,28 @@ public: void runTests() { - BezierCurve curve(DPoint(0,0), DPoint(1,0), DPoint(1,1), DPoint(0,1)); - TEST(almostEqual(curve.interpolate(0), DPoint(0,0))); - TEST(almostEqual(curve.getDeriv(0), DPoint(3, 0))); - TEST(almostEqual(curve.interpolate(1), DPoint(0,1))); - TEST(almostEqual(curve.getDeriv(1), DPoint(-3, 0))); - TEST(almostEqual(curve.interpolate(0.5), DPoint(0.75,0.5))); + BezierCurve curve(glm::vec2(0,0), glm::vec2(1,0), glm::vec2(1,1), glm::vec2(0,1)); + TEST(almostEqual(curve.interpolate(0), glm::vec2(0,0))); + TEST(almostEqual(curve.getDeriv(0), glm::vec2(3, 0))); + TEST(almostEqual(curve.interpolate(1), glm::vec2(0,1))); + TEST(almostEqual(curve.getDeriv(1), glm::vec2(-3, 0))); + TEST(almostEqual(curve.interpolate(0.5), glm::vec2(0.75,0.5))); + } +}; + + +class WideLineTest: public Test +{ +public: + WideLineTest() + : Test("WideLineTest", 2) + { + } + + void runTests() + { + WideLine line(glm::vec2(0,0), glm::vec2(4,3), 2); + TEST(almostEqual(line.getLen(), 5)); } }; @@ -731,17 +849,151 @@ public: }; +class PolygonTest: public Test +{ +public: + PolygonTest() + : Test("PolygonTest", 2) + { + } + + void runTests() + { + glm::vec2 polyArray[] = {glm::vec2(30,0), glm::vec2(40,20), glm::vec2(60,30), + glm::vec2(40,40), glm::vec2(30,60), glm::vec2(20,40), glm::vec2(0,30), + glm::vec2(20,20)}; + + Vec2Vector poly = vectorFromCArray(8, polyArray); + vector<unsigned int> triangulation; + triangulatePolygon(triangulation, poly); + + TEST(triangulation.size() == 6*3); + unsigned int baselineIndexes[] = {6,7,5, 5,7,1, 7,0,1, 5,1,3, 3,1,2, 4,5,3}; + TEST(triangulation == vectorFromCArray(18, baselineIndexes)); +/* + for (unsigned int i=0; i<triangulation.size(); i++) { + cerr << i << ":" << triangulation[i] << endl; + }/ +*/ + } + +}; + + +class XmlParserTest: public Test +{ +public: + XmlParserTest() + : Test("XmlParserTest", 2) + { + } + + void runTests() + { + string sXmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<shiporder orderid=\"889923\">" + " <orderperson>John Smith</orderperson>" + "</shiporder>"; + + { + string sSchema = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">" + "<xs:element name=\"shiporder\">" + " <xs:complexType>" + " <xs:sequence>" + " <xs:element name=\"orderperson\" type=\"xs:string\"/>" + " </xs:sequence>" + " <xs:attribute name=\"orderid\" type=\"xs:string\" use=\"required\"/>" + " </xs:complexType>" + "</xs:element>" + "</xs:schema>"; + + XMLParser parser; + parser.setSchema(sSchema, "shiporder.xsd"); + parser.parse(sXmlString, "shiporder.xml"); + } + { + string sDTD = + "<!ELEMENT shiporder (orderperson)* >" + "<!ATTLIST shiporder" + " orderid CDATA #IMPLIED>" + "<!ELEMENT orderperson (#PCDATA) >"; + XMLParser parser; + parser.setDTD(sDTD, "shiporder.dtd"); + parser.parse(sXmlString, "shiporder.xml"); + } + } +}; + + +class StandardLoggerTest: public Test +{ +public: + StandardLoggerTest() + : Test("StandardLoggerTest", 2) + { + } + + void runTests() + { + std::stringstream buffer; + std::streambuf *sbuf = std::cerr.rdbuf(); + Logger *logger = Logger::get(); + { + std::cerr.rdbuf(buffer.rdbuf()); + string msg("Test log message"); + AVG_TRACE(Logger::category::NONE, Logger::severity::WARNING, msg); + std::cerr.rdbuf(sbuf); + TEST(buffer.str().find(msg) != string::npos); + buffer.str(string()); + + std::cerr.rdbuf(buffer.rdbuf()); + AVG_TRACE(Logger::category::NONE, Logger::severity::DEBUG, msg); + std::cerr.rdbuf(sbuf); + std::cout << buffer.str(); + TEST(buffer.str().find(msg) == string::npos); + buffer.str(string()); + } + { + std::cerr.rdbuf(buffer.rdbuf()); + category_t CUSTOM_CAT = logger->configureCategory("CUSTOM_CAT 1"); + string msg("CUSTOM_CAT LOG"); + AVG_TRACE(CUSTOM_CAT, Logger::severity::WARNING, msg); + std::cerr.rdbuf(sbuf); + TEST(buffer.str().find(msg) != string::npos); + buffer.str(string()); + } + { + std::cerr.rdbuf(buffer.rdbuf()); + category_t CUSTOM_CAT = logger->configureCategory("CUSTOM_CAT 1", + Logger::severity::CRITICAL); + string msg_info("CUSTOM_CAT LOG INFO"); + AVG_TRACE(CUSTOM_CAT, Logger::severity::WARNING, msg_info); + std::cerr.rdbuf(sbuf); + TEST(buffer.str().find(msg_info) == string::npos); + buffer.str(string()); + + std::cerr.rdbuf(buffer.rdbuf()); + string msg_critical("CUSTOM_CAT LOG CRITICAL"); + AVG_TRACE(CUSTOM_CAT, Logger::severity::CRITICAL, msg_critical); + std::cerr.rdbuf(sbuf); + TEST(buffer.str().find(msg_critical) != string::npos); + buffer.str(string()); + } + } +}; + class BaseTestSuite: public TestSuite { public: BaseTestSuite() : TestSuite("BaseTestSuite") { + addTest(TestPtr(new DAGTest)); addTest(TestPtr(new QueueTest)); addTest(TestPtr(new WorkerThreadTest)); addTest(TestPtr(new ObjectCounterTest)); - addTest(TestPtr(new PointTest)); - addTest(TestPtr(new Matrix3x4Test)); + addTest(TestPtr(new GeomTest)); addTest(TestPtr(new TriangleTest)); addTest(TestPtr(new FileTest)); addTest(TestPtr(new OSTest)); @@ -750,6 +1002,9 @@ public: addTest(TestPtr(new BezierCurveTest)); addTest(TestPtr(new SignalTest)); addTest(TestPtr(new BacktraceTest)); + addTest(TestPtr(new PolygonTest)); + addTest(TestPtr(new XmlParserTest)); + addTest(TestPtr(new StandardLoggerTest)); } }; diff --git a/src/base/triangulate/AdvancingFront.cpp b/src/base/triangulate/AdvancingFront.cpp new file mode 100644 index 0000000..d14f1d3 --- /dev/null +++ b/src/base/triangulate/AdvancingFront.cpp @@ -0,0 +1,104 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +// +// Based on Poly2Tri algorithm. +// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors +// http://code.google.com/p/poly2tri/ +// + +#include "AdvancingFront.h" + +namespace avg { + +AdvancingFront::AdvancingFront(Node& head, Node& tail) +{ + m_Head = &head; + m_Tail = &tail; + m_SearchNode = &head; +} + +Node* AdvancingFront::locateNode(const double& x) +{ + Node* node = m_SearchNode; + + if (x < node->m_Value) { + while ((node = node->m_Prev) != NULL) { + if (x >= node->m_Value) { + m_SearchNode = node; + return node; + } + } + } else { + while ((node = node->m_Next) != NULL) { + if (x < node->m_Value) { + m_SearchNode = node->m_Prev; + return node->m_Prev; + } + } + } + return NULL; +} + +Node* AdvancingFront::findSearchNode(const double& x) +{ + // TO DO: implement BST index + return m_SearchNode; +} + +Node* AdvancingFront::locatePoint(const Point* point) +{ + const double px = point->m_X; + Node* node = findSearchNode(px); + const double nx = node->m_Point->m_X; + + if (px == nx) { + if (point != node->m_Point) { + // We might have two nodes with same x value for a short time + if (point == node->m_Prev->m_Point) { + node = node->m_Prev; + } else if (point == node->m_Next->m_Point) { + node = node->m_Next; + } else { + assert(0); + } + } + } else if (px < nx) { + while ((node = node->m_Prev) != NULL) { + if (point == node->m_Point) { + break; + } + } + } else { + while ((node = node->m_Next) != NULL) { + if (point == node->m_Point) + break; + } + } + if (node) + m_SearchNode = node; + return node; +} + +AdvancingFront::~AdvancingFront() {} + +} + diff --git a/src/base/triangulate/AdvancingFront.h b/src/base/triangulate/AdvancingFront.h new file mode 100644 index 0000000..3bb0d5b --- /dev/null +++ b/src/base/triangulate/AdvancingFront.h @@ -0,0 +1,118 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +// +// Based on Poly2Tri algorithm. +// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors +// http://code.google.com/p/poly2tri/ +// + +#ifndef ADVANCED_FRONT_H +#define ADVANCED_FRONT_H + +#include "Shapes.h" + +namespace avg { + +struct Node; + +struct Node +{ + Point* m_Point; + TriangulationTriangle* m_Triangle; + + Node* m_Next; + Node* m_Prev; + + double m_Value; + + Node() : m_Point(NULL), m_Triangle(NULL), m_Next(NULL), m_Prev(NULL), m_Value(0) + {} + + Node(Point& p) : m_Point(&p), m_Triangle(NULL), m_Next(NULL), m_Prev(NULL), m_Value(p.m_X) + {} + + Node(Point& p, TriangulationTriangle& t) : m_Point(&p), m_Triangle(&t), m_Next(NULL), m_Prev(NULL), m_Value(p.m_X) + {} + +}; + + +class AdvancingFront +{ + +public: + +AdvancingFront(Node& head, Node& tail); + +~AdvancingFront(); + +Node* head(); +void setHead(Node* node); +Node* tail(); +void setTail(Node* node); +Node* search(); +void setSearch(Node* node); + +/// Locate insertion point along advancing front +Node* locateNode(const double& x); + +Node* locatePoint(const Point* point); + +private: + +Node* m_Head, *m_Tail, *m_SearchNode; + +Node* findSearchNode(const double& x); +}; + + +inline Node* AdvancingFront::head() +{ + return m_Head; +} +inline void AdvancingFront::setHead(Node* node) +{ + m_Head = node; +} + +inline Node* AdvancingFront::tail() +{ + return m_Tail; +} +inline void AdvancingFront::setTail(Node* node) +{ + m_Tail = node; +} + +inline Node* AdvancingFront::search() +{ + return m_SearchNode; +} + +inline void AdvancingFront::setSearch(Node* node) +{ + m_SearchNode = node; +} + +} + +#endif diff --git a/src/base/triangulate/Makefile.am b/src/base/triangulate/Makefile.am new file mode 100644 index 0000000..9381e58 --- /dev/null +++ b/src/base/triangulate/Makefile.am @@ -0,0 +1,8 @@ +AM_CPPFLAGS = -I.. @XML2_CFLAGS@ @PTHREAD_CFLAGS@ +ALL_H = Triangulate.h Shapes.h Utils.h \ + AdvancingFront.h Sweep.h SweepContext.h + +noinst_LTLIBRARIES = libtriangulate.la +libtriangulate_la_SOURCES = Triangulate.cpp Shapes.cpp \ + AdvancingFront.cpp Sweep.cpp SweepContext.cpp \ + $(ALL_H) diff --git a/src/base/triangulate/Makefile.in b/src/base/triangulate/Makefile.in new file mode 100644 index 0000000..4b8384a --- /dev/null +++ b/src/base/triangulate/Makefile.in @@ -0,0 +1,593 @@ +# Makefile.in generated by automake 1.11.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/base/triangulate +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ac_cxx_namespaces.m4 \ + $(top_srcdir)/m4/ac_path_generic.m4 \ + $(top_srcdir)/m4/ax_boost_thread.m4 \ + $(top_srcdir)/m4/ax_check_gl.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/avg_version.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/src/avgconfig.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libtriangulate_la_LIBADD = +am__objects_1 = +am_libtriangulate_la_OBJECTS = Triangulate.lo Shapes.lo \ + AdvancingFront.lo Sweep.lo SweepContext.lo $(am__objects_1) +libtriangulate_la_OBJECTS = $(am_libtriangulate_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libtriangulate_la_SOURCES) +DIST_SOURCES = $(libtriangulate_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_PYTHON_LIBS = @BOOST_PYTHON_LIBS@ +BOOST_THREAD_LIBS = @BOOST_THREAD_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DC1394_2_CFLAGS = @DC1394_2_CFLAGS@ +DC1394_2_LIBS = @DC1394_2_LIBS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FGREP = @FGREP@ +FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ +FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_CONFIG = @FREETYPE_CONFIG@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GLU_CFLAGS = @GLU_CFLAGS@ +GLU_LIBS = @GLU_LIBS@ +GL_CFLAGS = @GL_CFLAGS@ +GL_LIBS = @GL_LIBS@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBFFMPEG = @LIBFFMPEG@ +LIBOBJS = @LIBOBJS@ +LIBRSVG_CFLAGS = @LIBRSVG_CFLAGS@ +LIBRSVG_LIBS = @LIBRSVG_LIBS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBVIDEO_LDADD = @LIBVIDEO_LDADD@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MTDEV_CFLAGS = @MTDEV_CFLAGS@ +MTDEV_LIBS = @MTDEV_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCLDFLAGS = @OBJCLDFLAGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOFT2_CFLAGS = @PANGOFT2_CFLAGS@ +PANGOFT2_LIBS = @PANGOFT2_LIBS@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PREFIX = @PREFIX@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PYTHON = @PYTHON@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XI2_1_CFLAGS = @XI2_1_CFLAGS@ +XI2_1_LIBS = @XI2_1_LIBS@ +XI2_2_CFLAGS = @XI2_2_CFLAGS@ +XI2_2_LIBS = @XI2_2_LIBS@ +XMKMF = @XMKMF@ +XML2_CFLAGS = @XML2_CFLAGS@ +XML2_CONFIG = @XML2_CONFIG@ +XML2_LIBS = @XML2_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +acx_pthread_config = @acx_pthread_config@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -I.. @XML2_CFLAGS@ @PTHREAD_CFLAGS@ +ALL_H = Triangulate.h Shapes.h Utils.h \ + AdvancingFront.h Sweep.h SweepContext.h + +noinst_LTLIBRARIES = libtriangulate.la +libtriangulate_la_SOURCES = Triangulate.cpp Shapes.cpp \ + AdvancingFront.cpp Sweep.cpp SweepContext.cpp \ + $(ALL_H) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/base/triangulate/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/base/triangulate/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libtriangulate.la: $(libtriangulate_la_OBJECTS) $(libtriangulate_la_DEPENDENCIES) $(EXTRA_libtriangulate_la_DEPENDENCIES) + $(AM_V_CXXLD)$(CXXLINK) $(libtriangulate_la_OBJECTS) $(libtriangulate_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AdvancingFront.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Shapes.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Sweep.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SweepContext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Triangulate.Plo@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/base/triangulate/Shapes.cpp b/src/base/triangulate/Shapes.cpp new file mode 100644 index 0000000..08e2e13 --- /dev/null +++ b/src/base/triangulate/Shapes.cpp @@ -0,0 +1,353 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +// +// Based on Poly2Tri algorithm. +// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors +// http://code.google.com/p/poly2tri/ +// + +#include "Shapes.h" +#include <iostream> + +namespace avg { + +TriangulationTriangle::TriangulationTriangle(Point& a, Point& b, Point& c) +{ + m_Points[0] = &a; + m_Points[1] = &b; + m_Points[2] = &c; + m_Neighbors[0] = NULL; + m_Neighbors[1] = NULL; + m_Neighbors[2] = NULL; + m_ConstrainedEdge[0] = m_ConstrainedEdge[1] = m_ConstrainedEdge[2] = false; + m_DelaunayEdge[0] = m_DelaunayEdge[1] = m_DelaunayEdge[2] = false; + m_Interior = false; +} + +// Update neighbor pointers +void TriangulationTriangle::markNeighbor(Point* p1, Point* p2, + TriangulationTriangle* t) +{ + if ((p1 == m_Points[2] && p2 == m_Points[1]) + || (p1 == m_Points[1] && p2 == m_Points[2])) { + m_Neighbors[0] = t; + } else if ((p1 == m_Points[0] && p2 == m_Points[2]) + || (p1 == m_Points[2] && p2 == m_Points[0])) { + m_Neighbors[1] = t; + } else if ((p1 == m_Points[0] && p2 == m_Points[1]) + || (p1 == m_Points[1] && p2 == m_Points[0])) { + m_Neighbors[2] = t; + } else { + assert(0); + } + +} + +// Exhaustive search to update neighbor pointers +void TriangulationTriangle::markNeighbor(TriangulationTriangle& t) +{ + if (t.contains(m_Points[1], m_Points[2])) { + m_Neighbors[0] = &t; + t.markNeighbor(m_Points[1], m_Points[2], this); + } else if (t.contains(m_Points[0], m_Points[2])) { + m_Neighbors[1] = &t; + t.markNeighbor(m_Points[0], m_Points[2], this); + } else if (t.contains(m_Points[0], m_Points[1])) { + m_Neighbors[2] = &t; + t.markNeighbor(m_Points[0], m_Points[1], this); + } +} + +void TriangulationTriangle::clear() +{ + TriangulationTriangle *t; + for (int i = 0; i < 3; i++) { + t = m_Neighbors[i]; + if (t != NULL) { + t->clearNeighbor(this); + } + } + clearNeighbors(); + m_Points[0] = m_Points[1] = m_Points[2] = NULL; +} + +void TriangulationTriangle::clearNeighbor(TriangulationTriangle *triangle) +{ + if (m_Neighbors[0] == triangle) { + m_Neighbors[0] = NULL; + } else if (m_Neighbors[1] == triangle) { + m_Neighbors[1] = NULL; + } else { + m_Neighbors[2] = NULL; + } +} + +void TriangulationTriangle::clearNeighbors() +{ + m_Neighbors[0] = NULL; + m_Neighbors[1] = NULL; + m_Neighbors[2] = NULL; +} + +void TriangulationTriangle::clearDelunayEdges() +{ + m_DelaunayEdge[0] = m_DelaunayEdge[1] = m_DelaunayEdge[2] = false; +} + +Point* TriangulationTriangle::oppositePoint(TriangulationTriangle& t, + Point& p) { + Point *cw = t.pointCW(p); + return pointCW(*cw); +} + +// Legalized triangle by rotating clockwise around point(0) +void TriangulationTriangle::legalize(Point& point) +{ + m_Points[1] = m_Points[0]; + m_Points[0] = m_Points[2]; + m_Points[2] = &point; +} + +// Legalize triagnle by rotating clockwise around oPoint +void TriangulationTriangle::legalize(Point& opoint, Point& npoint) +{ + if (&opoint == m_Points[0]) { + m_Points[1] = m_Points[0]; + m_Points[0] = m_Points[2]; + m_Points[2] = &npoint; + } else if (&opoint == m_Points[1]) { + m_Points[2] = m_Points[1]; + m_Points[1] = m_Points[0]; + m_Points[0] = &npoint; + } else if (&opoint == m_Points[2]) { + m_Points[0] = m_Points[2]; + m_Points[2] = m_Points[1]; + m_Points[1] = &npoint; + } else { + assert(0); + } +} + +unsigned int TriangulationTriangle::index(const Point* p) +{ + if (p == m_Points[0]) { + return 0; + } else if (p == m_Points[1]) { + return 1; + } else if (p == m_Points[2]) { + return 2; + } + assert(0); + return 0; +} + +unsigned int TriangulationTriangle::edgeIndex(const Point* p1, const Point* p2) +{ + if (m_Points[0] == p1) { + if (m_Points[1] == p2) { + return 2; + } else if (m_Points[2] == p2) { + return 1; + } + } else if (m_Points[1] == p1) { + if (m_Points[2] == p2) { + return 0; + } else if (m_Points[0] == p2) { + return 2; + } + } else if (m_Points[2] == p1) { + if (m_Points[0] == p2) { + return 1; + } else if (m_Points[1] == p2) { + return 0; + } + } + return -1; +} + +void TriangulationTriangle::markConstrainedEdge(const int index) +{ + m_ConstrainedEdge[index] = true; +} + +void TriangulationTriangle::markConstrainedEdge(Edge& edge) +{ + markConstrainedEdge(edge.m_P, edge.m_Q); +} + +void TriangulationTriangle::markConstrainedEdge(Point* p, Point* q) +{ + if ((q == m_Points[0] && p == m_Points[1]) + || (q == m_Points[1] && p == m_Points[0])) { + m_ConstrainedEdge[2] = true; + } else if ((q == m_Points[0] && p == m_Points[2]) + || (q == m_Points[2] && p == m_Points[0])) { + m_ConstrainedEdge[1] = true; + } else if ((q == m_Points[1] && p == m_Points[2]) + || (q == m_Points[2] && p == m_Points[1])) { + m_ConstrainedEdge[0] = true; + } +} + +// The point counter-clockwise to given point +Point* TriangulationTriangle::pointCW(Point& point) +{ + if (&point == m_Points[0]) { + return m_Points[2]; + } else if (&point == m_Points[1]) { + return m_Points[0]; + } else if (&point == m_Points[2]) { + return m_Points[1]; + } + assert(0); + return 0; // Silence compiler warning +} + +Point* TriangulationTriangle::pointCCW(Point& point) +{ + if (&point == m_Points[0]) { + return m_Points[1]; + } else if (&point == m_Points[1]) { + return m_Points[2]; + } else if (&point == m_Points[2]) { + return m_Points[0]; + } + assert(0); + return 0; // Silence compiler warning +} + +TriangulationTriangle* TriangulationTriangle::neighborCW(Point& point) +{ + if (&point == m_Points[0]) { + return m_Neighbors[1]; + } else if (&point == m_Points[1]) { + return m_Neighbors[2]; + } + return m_Neighbors[0]; +} + +TriangulationTriangle* TriangulationTriangle::neighborCCW(Point& point) +{ + if (&point == m_Points[0]) { + return m_Neighbors[2]; + } else if (&point == m_Points[1]) { + return m_Neighbors[0]; + } + return m_Neighbors[1]; +} + +bool TriangulationTriangle::getConstrainedEdgeCCW(Point& p) +{ + if (&p == m_Points[0]) { + return m_ConstrainedEdge[2]; + } else if (&p == m_Points[1]) { + return m_ConstrainedEdge[0]; + } + return m_ConstrainedEdge[1]; +} + +bool TriangulationTriangle::getConstrainedEdgeCW(Point& p) +{ + if (&p == m_Points[0]) { + return m_ConstrainedEdge[1]; + } else if (&p == m_Points[1]) { + return m_ConstrainedEdge[2]; + } + return m_ConstrainedEdge[0]; +} + +void TriangulationTriangle::setConstrainedEdgeCCW(Point& p, bool ce) +{ + if (&p == m_Points[0]) { + m_ConstrainedEdge[2] = ce; + } else if (&p == m_Points[1]) { + m_ConstrainedEdge[0] = ce; + } else { + m_ConstrainedEdge[1] = ce; + } +} + +void TriangulationTriangle::setConstrainedEdgeCW(Point& p, bool ce) +{ + if (&p == m_Points[0]) { + m_ConstrainedEdge[1] = ce; + } else if (&p == m_Points[1]) { + m_ConstrainedEdge[2] = ce; + } else { + m_ConstrainedEdge[0] = ce; + } +} + +bool TriangulationTriangle::getDelunayEdgeCCW(Point& p) +{ + if (&p == m_Points[0]) { + return m_DelaunayEdge[2]; + } else if (&p == m_Points[1]) { + return m_DelaunayEdge[0]; + } + return m_DelaunayEdge[1]; +} + +bool TriangulationTriangle::getDelunayEdgeCW(Point& p) +{ + if (&p == m_Points[0]) { + return m_DelaunayEdge[1]; + } else if (&p == m_Points[1]) { + return m_DelaunayEdge[2]; + } + return m_DelaunayEdge[0]; +} + +void TriangulationTriangle::setDelunayEdgeCCW(Point& p, bool e) +{ + if (&p == m_Points[0]) { + m_DelaunayEdge[2] = e; + } else if (&p == m_Points[1]) { + m_DelaunayEdge[0] = e; + } else { + m_DelaunayEdge[1] = e; + } +} + +void TriangulationTriangle::setDelunayEdgeCW(Point& p, bool e) +{ + if (&p == m_Points[0]) { + m_DelaunayEdge[1] = e; + } else if (&p == m_Points[1]) { + m_DelaunayEdge[2] = e; + } else { + m_DelaunayEdge[0] = e; + } +} + +TriangulationTriangle& TriangulationTriangle::neighborAcross(Point& opoint) +{ + if (&opoint == m_Points[0]) { + return *m_Neighbors[0]; + } else if (&opoint == m_Points[1]) { + return *m_Neighbors[1]; + } + return *m_Neighbors[2]; +} + +} + diff --git a/src/base/triangulate/Shapes.h b/src/base/triangulate/Shapes.h new file mode 100644 index 0000000..0417d7c --- /dev/null +++ b/src/base/triangulate/Shapes.h @@ -0,0 +1,296 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +// +// Based on Poly2Tri algorithm. +// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors +// http://code.google.com/p/poly2tri/ +// + +#ifndef SHAPES_H +#define SHAPES_H + +#include <vector> +#include <cstddef> +#include <assert.h> +#include <cmath> + +namespace avg { + +struct Edge; + +struct Point +{ + double m_X, m_Y; + int m_Index; + + /// The edges this point constitutes an upper ending point + std::vector<Edge*> m_EdgeList; + + /// Default constructor does nothing (for performance). + Point() { + m_X = 0.0; + m_Y = 0.0; + m_Index = 0; + } + + Point(double x, double y, int index) : + m_X(x), m_Y(y), m_Index(index) {} + + void set_zero() + { + m_X = 0.0; + m_Y = 0.0; + } + + void set(double x_, double y_) + { + m_X = x_; + m_Y = y_; + } + + Point operator -() const + { + Point v; + v.set(-m_X, -m_Y); + return v; + } + + void operator +=(const Point& v) + { + m_X += v.m_X; + m_Y += v.m_Y; + } + + void operator -=(const Point& v) + { + m_X -= v.m_X; + m_Y -= v.m_Y; + } + + void operator *=(double a) + { + m_X *= a; + m_Y *= a; + } + + double length() const + { + return sqrt(m_X * m_X + m_Y * m_Y); + } + + /// Convert this point into a unit point. Returns the Length. + double normalize() + { + double len = length(); + m_X /= len; + m_Y /= len; + return len; + } + +}; + + +// Represents a simple polygon's edge +struct Edge +{ + Point* m_P, *m_Q; + + Edge(Point& p1, Point& p2) :m_P(&p1), m_Q(&p2) + { + if (p1.m_Y > p2.m_Y) { + m_Q = &p1; + m_P = &p2; + } else if (p1.m_Y == p2.m_Y) { + if (p1.m_X > p2.m_X) { + m_Q = &p1; + m_P = &p2; + } else if (p1.m_X == p2.m_X) { + // Repeat points + assert(false); + } + } + m_Q->m_EdgeList.push_back(this); + } +}; + + +class TriangulationTriangle +{ + +public: + + TriangulationTriangle(Point& a, Point& b, Point& c); + +/// Flags to determine if an edge is a Constrained edge + bool m_ConstrainedEdge[3]; +/// Flags to determine if an edge is a Delauney edge + bool m_DelaunayEdge[3]; + + Point* getPoint(const int& index); + Point* pointCW(Point& point); + Point* pointCCW(Point& point); + Point* oppositePoint(TriangulationTriangle& t, Point& p); + + TriangulationTriangle* getNeighbor(const int& index); + void markNeighbor(Point* p1, Point* p2, TriangulationTriangle* t); + void markNeighbor(TriangulationTriangle& t); + + void markConstrainedEdge(const int index); + void markConstrainedEdge(Edge& edge); + void markConstrainedEdge(Point* p, Point* q); + + unsigned int index(const Point* p); + unsigned int edgeIndex(const Point* p1, const Point* p2); + + TriangulationTriangle* neighborCW(Point& point); + TriangulationTriangle* neighborCCW(Point& point); + bool getConstrainedEdgeCCW(Point& p); + bool getConstrainedEdgeCW(Point& p); + void setConstrainedEdgeCCW(Point& p, bool ce); + void setConstrainedEdgeCW(Point& p, bool ce); + bool getDelunayEdgeCCW(Point& p); + bool getDelunayEdgeCW(Point& p); + void setDelunayEdgeCCW(Point& p, bool e); + void setDelunayEdgeCW(Point& p, bool e); + + bool contains(Point* p); + bool contains(const Edge& e); + bool contains(Point* p, Point* q); + void legalize(Point& point); + void legalize(Point& opoint, Point& npoint); + + void clear(); + void clearNeighbor(TriangulationTriangle *triangle); + void clearNeighbors(); + void clearDelunayEdges(); + + inline bool isInterior(); + inline void isInterior(bool b); + + TriangulationTriangle& neighborAcross(Point& opoint); + +private: + + Point* m_Points[3]; + + TriangulationTriangle* m_Neighbors[3]; + + bool m_Interior; +}; + +inline bool cmp(const Point* a, const Point* b) +{ + if (a->m_Y < b->m_Y) { + return true; + } else if (a->m_Y == b->m_Y) { + // Make sure q is point with greater x value + if (a->m_X < b->m_X) { + return true; + } + } + return false; +} +/* + inline Point operator +(const Point& a, const Point& b) + { + return Point(a.x + b.x, a.y + b.y); + } + + inline Point operator -(const Point& a, const Point& b) + { + return Point(a.x - b.x, a.y - b.y); + } + + inline Point operator *(double s, const Point& a) + { + return Point(s * a.x, s * a.y, a.index); + } */ + +inline bool operator ==(const Point& a, const Point& b) +{ + return a.m_X == b.m_X && a.m_Y == b.m_Y; +} + +inline bool operator !=(const Point& a, const Point& b) +{ + return a.m_X != b.m_X && a.m_Y != b.m_Y; +} + +inline double dot(const Point& a, const Point& b) +{ + return a.m_X * b.m_X + a.m_Y * b.m_Y; +} + +inline double cross(const Point& a, const Point& b) +{ + return a.m_X * b.m_Y - a.m_Y * b.m_X; +} + +inline Point cross(const Point& a, double s) +{ + return Point(s * a.m_Y, -s * a.m_X, a.m_Index); +} + +inline Point cross(const double s, const Point& a) +{ + return Point(-s * a.m_Y, s * a.m_X, a.m_Index); +} + +inline Point* TriangulationTriangle::getPoint(const int& index) +{ + return m_Points[index]; +} + +inline TriangulationTriangle* TriangulationTriangle::getNeighbor( + const int& index) +{ + return m_Neighbors[index]; +} + +inline bool TriangulationTriangle::contains(Point* p) +{ + return p == m_Points[0] || p == m_Points[1] || p == m_Points[2]; +} + +inline bool TriangulationTriangle::contains(const Edge& e) +{ + return contains(e.m_P) && contains(e.m_Q); +} + +inline bool TriangulationTriangle::contains(Point* p, Point* q) +{ + return contains(p) && contains(q); +} + +inline bool TriangulationTriangle::isInterior() +{ + return m_Interior; +} + +inline void TriangulationTriangle::isInterior(bool b) +{ + m_Interior = b; +} + +} + +#endif diff --git a/src/base/triangulate/Sweep.cpp b/src/base/triangulate/Sweep.cpp new file mode 100644 index 0000000..2655cb0 --- /dev/null +++ b/src/base/triangulate/Sweep.cpp @@ -0,0 +1,796 @@ +//
+// libavg - Media Playback Engine.
+// Copyright (C) 2003-2014 Ulrich von Zadow +//
+// 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 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Current versions can be found at www.libavg.de
+//
+
+//
+// Based on Poly2Tri algorithm.
+// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+// http://code.google.com/p/poly2tri/
+//
+
+#include <stdexcept>
+#include "Sweep.h"
+#include "SweepContext.h"
+#include "AdvancingFront.h"
+#include "Utils.h"
+
+namespace avg {
+
+void Sweep::Triangulate(SweepContext& sc)
+{
+ arrayCount = 0;
+ for (unsigned int i = 0; i < (unsigned)sc.pointCount(); i++) {
+ m_Nodes.push_back(new Node());
+ }
+ sc.initTriangulation();
+ sc.createAdvancingFront();
+ // Sweep points; build mesh
+ sweepPoints(sc);
+ // Clean up
+ finalizationPolygon(sc);
+}
+
+void Sweep::sweepPoints(SweepContext& sc)
+{
+ for (int i = 1; i < sc.pointCount(); i++) {
+ Point& point = *sc.getPoint(i);
+ Node* node = &pointEvent(sc, point);
+ for (unsigned int i = 0; i < point.m_EdgeList.size(); i++) {
+ edgeEvent(sc, point.m_EdgeList[i], node);
+ }
+ }
+}
+
+void Sweep::finalizationPolygon(SweepContext& sc)
+{
+ // Get an Internal triangle to start with
+ TriangulationTriangle* t = sc.front()->head()->m_Next->m_Triangle;
+ Point* p = sc.front()->head()->m_Next->m_Point;
+ while (!t->getConstrainedEdgeCW(*p)) {
+ t = t->neighborCCW(*p);
+ }
+
+ // Collect interior triangles constrained by edges
+ sc.meshClean(*t);
+}
+
+Node& Sweep::pointEvent(SweepContext& sc, Point& point)
+{
+ Node& node = sc.locateNode(point);
+ Node& new_node = newFrontTriangle(sc, point, node);
+
+ // Only need to check +epsilon since point never have smaller
+ // x value than node due to how we fetch nodes from the front
+ if (point.m_X <= node.m_Point->m_X + EPSILON) {
+ fill(sc, node);
+ }
+
+ //tcx.AddNode(new_node);
+
+ fillAdvancingFront(sc, new_node);
+ return new_node;
+}
+
+void Sweep::edgeEvent(SweepContext& sc, Edge* edge, Node* node)
+{
+ sc.m_EdgeEvent.m_ConstrainedEdge = edge;
+ sc.m_EdgeEvent.m_Right = (edge->m_P->m_X > edge->m_Q->m_X);
+
+ if (isEdgeSideOfTriangle(*node->m_Triangle, *edge->m_P, *edge->m_Q)) {
+ return;
+ }
+
+ // to do: integrate with flip process might give some better performance
+ // but for now this avoid the issue with cases that needs both flips and fills
+ fillEdgeEvent(sc, edge, node);
+ edgeEvent(sc, *edge->m_P, *edge->m_Q, node->m_Triangle, *edge->m_Q);
+}
+
+void Sweep::edgeEvent(SweepContext& sc, Point& ep, Point& eq,
+ TriangulationTriangle* triangle, Point& point)
+{
+ if (isEdgeSideOfTriangle(*triangle, ep, eq)) {
+ return;
+ }
+
+ Point* p1 = triangle->pointCCW(point);
+ Orientation o1 = orient2d(eq, *p1, ep);
+ if (o1 == COLLINEAR) {
+ if (triangle->contains(&eq, p1)) {
+ triangle->markConstrainedEdge(&eq, p1);
+ // We are modifying the constraint maybe it would be better to
+ // not change the given constraint and just keep a variable for the new constraint
+ sc.m_EdgeEvent.m_ConstrainedEdge->m_Q = p1;
+ triangle = &triangle->neighborAcross(point);
+ edgeEvent(sc, ep, *p1, triangle, *p1);
+ } else {
+ std::runtime_error("EdgeEvent - collinear points not supported");
+ assert(0);
+ }
+ return;
+ }
+
+ Point* p2 = triangle->pointCW(point);
+ Orientation o2 = orient2d(eq, *p2, ep);
+ if (o2 == COLLINEAR) {
+ if (triangle->contains(&eq, p2)) {
+ triangle->markConstrainedEdge(&eq, p2);
+ // We are modifying the constraint maybe it would be better to
+ // not change the given constraint and just keep a variable for the new constraint
+ sc.m_EdgeEvent.m_ConstrainedEdge->m_Q = p2;
+ triangle = &triangle->neighborAcross(point);
+ edgeEvent(sc, ep, *p2, triangle, *p2);
+ } else {
+ std::runtime_error("EdgeEvent - collinear points not supported");
+ assert(0);
+ }
+ return;
+ }
+
+ if (o1 == o2) {
+ // Need to decide if we are rotating CW or CCW to get to a triangle
+ // that will cross edge
+ if (o1 == CW) {
+ triangle = triangle->neighborCCW(point);
+ } else {
+ triangle = triangle->neighborCW(point);
+ }
+ edgeEvent(sc, ep, eq, triangle, point);
+ } else {
+ // This triangle crosses constraint so lets flippin start!
+ flipEdgeEvent(sc, ep, eq, triangle, point);
+ }
+}
+
+bool Sweep::isEdgeSideOfTriangle(TriangulationTriangle& triangle, Point& ep,
+ Point& eq)
+{
+ int index = triangle.edgeIndex(&ep, &eq);
+
+ if (index != -1) {
+ triangle.markConstrainedEdge(index);
+ TriangulationTriangle* t = triangle.getNeighbor(index);
+ if (t) {
+ t->markConstrainedEdge(&ep, &eq);
+ }
+ return true;
+ }
+ return false;
+}
+
+Node& Sweep::newFrontTriangle(SweepContext& sc, Point& point, Node& node)
+{
+ TriangulationTriangle* triangle = new TriangulationTriangle(point,
+ *node.m_Point, *node.m_Next->m_Point);
+
+ triangle->markNeighbor(*node.m_Triangle);
+ sc.addToMap(triangle);
+
+ Node* newNode = m_Nodes[arrayCount++]; //new Node(point);
+ newNode->m_Point = &point;
+ newNode->m_Value = point.m_X;
+// m_Nodes.push_back(newNode);
+
+ newNode->m_Next = node.m_Next;
+ newNode->m_Prev = &node;
+ node.m_Next->m_Prev = newNode;
+ node.m_Next = newNode;
+
+ if (!legalize(sc, *triangle)) {
+ sc.mapTriangleToNodes(*triangle);
+ }
+
+ return *newNode;
+}
+
+void Sweep::fill(SweepContext& sc, Node& node)
+{
+ TriangulationTriangle* triangle = new TriangulationTriangle(
+ *node.m_Prev->m_Point, *node.m_Point, *node.m_Next->m_Point);
+
+ // TO DO: should copy the constrained_edge value from neighbor triangles
+ // for now constrained_edge values are copied during the legalize
+ triangle->markNeighbor(*node.m_Prev->m_Triangle);
+ triangle->markNeighbor(*node.m_Triangle);
+
+ sc.addToMap(triangle);
+
+ // Update the advancing front
+ node.m_Prev->m_Next = node.m_Next;
+ node.m_Next->m_Prev = node.m_Prev;
+
+ // If it was legalized the triangle has already been mapped
+ if (!legalize(sc, *triangle)) {
+ sc.mapTriangleToNodes(*triangle);
+ }
+
+}
+
+void Sweep::fillAdvancingFront(SweepContext& sc, Node& n)
+{
+ Node* node = n.m_Next;
+
+ while (node->m_Next) {
+ double angle = holeAngle(*node);
+ if (angle > M_PI_2 || angle < -M_PI_2)
+ break;
+// ---------- LEAK FIX --------------
+// Fill(tcx, *node);
+// node = node->m_next;
+
+
+ Node *tmp = node;
+ node = node->m_Next;
+ fill(sc, *tmp);
+// ----------------------------------
+ }
+
+ node = n.m_Prev;
+
+ while (node->m_Prev) {
+ double angle = holeAngle(*node);
+ if (angle > M_PI_2 || angle < -M_PI_2)
+ break;
+ fill(sc, *node);
+ node = node->m_Prev;
+ }
+
+ if (n.m_Next && n.m_Next->m_Next) {
+ double angle = basinAngle(n);
+ if (angle < PI_3div4) {
+ fillBasin(sc, n);
+ }
+ }
+}
+
+double Sweep::basinAngle(Node& node)
+{
+ double ax = node.m_Point->m_X - node.m_Next->m_Next->m_Point->m_X;
+ double ay = node.m_Point->m_Y - node.m_Next->m_Next->m_Point->m_Y;
+ return atan2(ay, ax);
+}
+
+double Sweep::holeAngle(Node& node)
+{
+ /* Complex plane
+ * ab = cosA +i*sinA
+ * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
+ * atan2(y,x) computes the principal value of the argument function
+ * applied to the complex number x+iy
+ * Where x = ax*bx + ay*by
+ * y = ax*by - ay*bx
+ */
+ double ax = node.m_Next->m_Point->m_X - node.m_Point->m_X;
+ double ay = node.m_Next->m_Point->m_Y - node.m_Point->m_Y;
+ double bx = node.m_Prev->m_Point->m_X - node.m_Point->m_X;
+ double by = node.m_Prev->m_Point->m_Y - node.m_Point->m_Y;
+ return atan2(ax * by - ay * bx, ax * bx + ay * by);
+}
+
+bool Sweep::legalize(SweepContext& sc, TriangulationTriangle& t)
+{
+ // To legalize a triangle we start by finding if any of the three edges
+ // violate the Delaunay condition
+ for (int i = 0; i < 3; i++) {
+ if (t.m_DelaunayEdge[i])
+ continue;
+
+ TriangulationTriangle* ot = t.getNeighbor(i);
+
+ if (ot) {
+ Point* p = t.getPoint(i);
+ Point* op = ot->oppositePoint(t, *p);
+ int oi = ot->index(op);
+
+ // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization)
+ // then we should not try to legalize
+ if (ot->m_ConstrainedEdge[oi] || ot->m_DelaunayEdge[oi]) {
+ t.m_ConstrainedEdge[i] = ot->m_ConstrainedEdge[oi];
+ continue;
+ }
+
+ bool inside = incircle(*p, *t.pointCCW(*p), *t.pointCW(*p), *op);
+
+ if (inside) {
+ // Lets mark this shared edge as Delaunay
+ t.m_DelaunayEdge[i] = true;
+ ot->m_DelaunayEdge[oi] = true;
+
+ // Lets rotate shared edge one vertex CW to legalize it
+ rotateTrianglePair(t, *p, *ot, *op);
+
+ // We now got one valid Delaunay Edge shared by two triangles
+ // This gives us 4 new edges to check for Delaunay
+
+ // Make sure that triangle to node mapping is done only one time for a specific triangle
+ bool notLegalized = !legalize(sc, t);
+ if (notLegalized) {
+ sc.mapTriangleToNodes(t);
+ }
+
+ notLegalized = !legalize(sc, *ot);
+ if (notLegalized)
+ sc.mapTriangleToNodes(*ot);
+
+ // Reset the Delaunay edges, since they only are valid Delaunay edges
+ // until we add a new triangle or point.
+ // XX X: need to think about this. Can these edges be tried after we
+ // return to previous recursive level?
+ t.m_DelaunayEdge[i] = false;
+ ot->m_DelaunayEdge[oi] = false;
+
+ // If triangle have been legalized no need to check the other edges since
+ // the recursive legalization will handles those so we can end here.
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool Sweep::incircle(Point& pa, Point& pb, Point& pc, Point& pd)
+{
+ double adx = pa.m_X - pd.m_X;
+ double ady = pa.m_Y - pd.m_Y;
+ double bdx = pb.m_X - pd.m_X;
+ double bdy = pb.m_Y - pd.m_Y;
+
+ double adxbdy = adx * bdy;
+ double bdxady = bdx * ady;
+ double oabd = adxbdy - bdxady;
+
+ if (oabd <= 0) {
+ return false;
+ }
+
+ double cdx = pc.m_X - pd.m_X;
+ double cdy = pc.m_Y - pd.m_Y;
+
+ double cdxady = cdx * ady;
+ double adxcdy = adx * cdy;
+ double ocad = cdxady - adxcdy;
+
+ if (ocad <= 0) {
+ return false;
+ }
+
+ double bdxcdy = bdx * cdy;
+ double cdxbdy = cdx * bdy;
+
+ double alift = adx * adx + ady * ady;
+ double blift = bdx * bdx + bdy * bdy;
+ double clift = cdx * cdx + cdy * cdy;
+
+ double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
+
+ return det > 0;
+}
+
+void Sweep::rotateTrianglePair(TriangulationTriangle& t, Point& p,
+ TriangulationTriangle& ot, Point& op)
+{
+ TriangulationTriangle* n1, *n2, *n3, *n4;
+ n1 = t.neighborCCW(p);
+ n2 = t.neighborCW(p);
+ n3 = ot.neighborCCW(op);
+ n4 = ot.neighborCW(op);
+
+ bool ce1, ce2, ce3, ce4;
+ ce1 = t.getConstrainedEdgeCCW(p);
+ ce2 = t.getConstrainedEdgeCW(p);
+ ce3 = ot.getConstrainedEdgeCCW(op);
+ ce4 = ot.getConstrainedEdgeCW(op);
+
+ bool de1, de2, de3, de4;
+ de1 = t.getDelunayEdgeCCW(p);
+ de2 = t.getDelunayEdgeCW(p);
+ de3 = ot.getDelunayEdgeCCW(op);
+ de4 = ot.getDelunayEdgeCW(op);
+
+ t.legalize(p, op);
+ ot.legalize(op, p);
+
+ // Remap delaunay_edge
+ ot.setDelunayEdgeCCW(p, de1);
+ t.setDelunayEdgeCW(p, de2);
+ t.setDelunayEdgeCCW(op, de3);
+ ot.setDelunayEdgeCW(op, de4);
+
+ // Remap constrained_edge
+ ot.setConstrainedEdgeCCW(p, ce1);
+ t.setConstrainedEdgeCW(p, ce2);
+ t.setConstrainedEdgeCCW(op, ce3);
+ ot.setConstrainedEdgeCW(op, ce4);
+
+ // Remap neighbors
+ // XX X: might optimize the markNeighbor by keeping track of
+ // what side should be assigned to what neighbor after the
+ // rotation. Now mark neighbor does lots of testing to find
+ // the right side.
+ t.clearNeighbors();
+ ot.clearNeighbors();
+ if (n1) {
+ ot.markNeighbor(*n1);
+ }
+ if (n2) {
+ t.markNeighbor(*n2);
+ }
+ if (n3) {
+ t.markNeighbor(*n3);
+ }
+ if (n4) {
+ ot.markNeighbor(*n4);
+ }
+ t.markNeighbor(ot);
+}
+
+void Sweep::fillBasin(SweepContext& sc, Node& node)
+{
+ if (orient2d(*node.m_Point, *node.m_Next->m_Point, *node.m_Next->m_Next->m_Point)
+ == CCW) {
+ sc.m_Basin.m_LeftNode = node.m_Next->m_Next;
+ } else {
+ sc.m_Basin.m_LeftNode = node.m_Next;
+ }
+
+ // Find the bottom and right node
+ sc.m_Basin.m_BottomNode = sc.m_Basin.m_LeftNode;
+ while (sc.m_Basin.m_BottomNode->m_Next
+ && sc.m_Basin.m_BottomNode->m_Point->m_Y
+ >= sc.m_Basin.m_BottomNode->m_Next->m_Point->m_Y) {
+ sc.m_Basin.m_BottomNode = sc.m_Basin.m_BottomNode->m_Next;
+ }
+ if (sc.m_Basin.m_BottomNode == sc.m_Basin.m_LeftNode) {
+ // No valid basin
+ return;
+ }
+
+ sc.m_Basin.m_RightNode = sc.m_Basin.m_BottomNode;
+ while (sc.m_Basin.m_RightNode->m_Next
+ && sc.m_Basin.m_RightNode->m_Point->m_Y
+ < sc.m_Basin.m_RightNode->m_Next->m_Point->m_Y) {
+ sc.m_Basin.m_RightNode = sc.m_Basin.m_RightNode->m_Next;
+ }
+ if (sc.m_Basin.m_RightNode == sc.m_Basin.m_BottomNode) {
+ // No valid basins
+ return;
+ }
+
+ sc.m_Basin.m_Width = sc.m_Basin.m_RightNode->m_Point->m_X
+ - sc.m_Basin.m_LeftNode->m_Point->m_X;
+ sc.m_Basin.m_LeftHighest = sc.m_Basin.m_LeftNode->m_Point->m_Y
+ > sc.m_Basin.m_RightNode->m_Point->m_Y;
+
+ fillBasinReq(sc, sc.m_Basin.m_BottomNode);
+}
+
+void Sweep::fillBasinReq(SweepContext& sc, Node* node)
+{
+ // if shallow stop filling
+ if (isShallow(sc, *node)) {
+ return;
+ }
+
+ fill(sc, *node);
+
+ if (node->m_Prev == sc.m_Basin.m_LeftNode
+ && node->m_Next == sc.m_Basin.m_RightNode) {
+ return;
+ } else if (node->m_Prev == sc.m_Basin.m_LeftNode) {
+ Orientation o = orient2d(*node->m_Point, *node->m_Next->m_Point,
+ *node->m_Next->m_Next->m_Point);
+ if (o == CW) {
+ return;
+ }
+ node = node->m_Next;
+ } else if (node->m_Next == sc.m_Basin.m_RightNode) {
+ Orientation o = orient2d(*node->m_Point, *node->m_Prev->m_Point,
+ *node->m_Prev->m_Prev->m_Point);
+ if (o == CCW) {
+ return;
+ }
+ node = node->m_Prev;
+ } else {
+ // Continue with the neighbor node with lowest Y value
+ if (node->m_Prev->m_Point->m_Y < node->m_Next->m_Point->m_Y) {
+ node = node->m_Prev;
+ } else {
+ node = node->m_Next;
+ }
+ }
+
+ fillBasinReq(sc, node);
+}
+
+bool Sweep::isShallow(SweepContext& sc, Node& node)
+{
+ double height;
+
+ if (sc.m_Basin.m_LeftHighest) {
+ height = sc.m_Basin.m_LeftNode->m_Point->m_Y - node.m_Point->m_Y;
+ } else {
+ height = sc.m_Basin.m_RightNode->m_Point->m_Y - node.m_Point->m_Y;
+ }
+
+ // if shallow stop filling
+ if (sc.m_Basin.m_Width > height) {
+ return true;
+ }
+ return false;
+}
+
+void Sweep::fillEdgeEvent(SweepContext& sc, Edge* edge, Node* node)
+{
+ if (sc.m_EdgeEvent.m_Right) {
+ fillRightAboveEdgeEvent(sc, edge, node);
+ } else {
+ fillLeftAboveEdgeEvent(sc, edge, node);
+ }
+}
+
+void Sweep::fillRightAboveEdgeEvent(SweepContext& sc, Edge* edge, Node* node)
+{
+ while (node->m_Next->m_Point->m_X < edge->m_P->m_X) {
+ // Check if next node is below the edge
+ if (orient2d(*edge->m_Q, *node->m_Next->m_Point, *edge->m_P) == CCW) {
+ fillRightBelowEdgeEvent(sc, edge, *node);
+ } else {
+ node = node->m_Next;
+ }
+ }
+}
+
+void Sweep::fillRightBelowEdgeEvent(SweepContext& sc, Edge* edge, Node& node)
+{
+ if (node.m_Point->m_X < edge->m_P->m_X) {
+ if (orient2d(*node.m_Point, *node.m_Next->m_Point, *node.m_Next->m_Next->m_Point)
+ == CCW) {
+ // Concave
+ fillRightConcaveEdgeEvent(sc, edge, node);
+ } else {
+ // Convex
+ fillRightConvexEdgeEvent(sc, edge, node);
+ // Retry this one
+ fillRightBelowEdgeEvent(sc, edge, node);
+ }
+ }
+}
+
+void Sweep::fillRightConcaveEdgeEvent(SweepContext& sc, Edge* edge, Node& node)
+{
+ fill(sc, *node.m_Next);
+ if (node.m_Next->m_Point != edge->m_P) {
+ // Next above or below edge?
+ if (orient2d(*edge->m_Q, *node.m_Next->m_Point, *edge->m_P) == CCW) {
+ // Below
+ if (orient2d(*node.m_Point, *node.m_Next->m_Point,
+ *node.m_Next->m_Next->m_Point) == CCW) {
+ // Next is concave
+ fillRightConcaveEdgeEvent(sc, edge, node);
+ } else {
+ // Next is convex
+ }
+ }
+ }
+
+}
+
+void Sweep::fillRightConvexEdgeEvent(SweepContext& sc, Edge* edge, Node& node)
+{
+ // Next concave or convex?
+ if (orient2d(*node.m_Next->m_Point, *node.m_Next->m_Next->m_Point,
+ *node.m_Next->m_Next->m_Next->m_Point) == CCW) {
+ // Concave
+ fillRightConcaveEdgeEvent(sc, edge, *node.m_Next);
+ } else {
+ // Convex
+ // Next above or below edge?
+ if (orient2d(*edge->m_Q, *node.m_Next->m_Next->m_Point, *edge->m_P) == CCW) {
+ // Below
+ fillRightConvexEdgeEvent(sc, edge, *node.m_Next);
+ } else {
+ // Above
+ }
+ }
+}
+
+void Sweep::fillLeftAboveEdgeEvent(SweepContext& sc, Edge* edge, Node* node)
+{
+ while (node->m_Prev->m_Point->m_X > edge->m_P->m_X) {
+ // Check if next node is below the edge
+ if (orient2d(*edge->m_Q, *node->m_Prev->m_Point, *edge->m_P) == CW) {
+ fillLeftBelowEdgeEvent(sc, edge, *node);
+ } else {
+ node = node->m_Prev;
+ }
+ }
+}
+
+void Sweep::fillLeftBelowEdgeEvent(SweepContext& sc, Edge* edge, Node& node)
+{
+ if (node.m_Point->m_X > edge->m_P->m_X) {
+ if (orient2d(*node.m_Point, *node.m_Prev->m_Point, *node.m_Prev->m_Prev->m_Point)
+ == CW) {
+ // Concave
+ fillLeftConcaveEdgeEvent(sc, edge, node);
+ } else {
+ // Convex
+ fillLeftConvexEdgeEvent(sc, edge, node);
+ // Retry this one
+ fillLeftBelowEdgeEvent(sc, edge, node);
+ }
+ }
+}
+
+void Sweep::fillLeftConvexEdgeEvent(SweepContext& sc, Edge* edge, Node& node)
+{
+ // Next concave or convex?
+ if (orient2d(*node.m_Prev->m_Point, *node.m_Prev->m_Prev->m_Point,
+ *node.m_Prev->m_Prev->m_Prev->m_Point) == CW) {
+ // Concave
+ fillLeftConcaveEdgeEvent(sc, edge, *node.m_Prev);
+ } else {
+ // Convex
+ // Next above or below edge?
+ if (orient2d(*edge->m_Q, *node.m_Prev->m_Prev->m_Point, *edge->m_P) == CW) {
+ // Below
+ fillLeftConvexEdgeEvent(sc, edge, *node.m_Prev);
+ } else {
+ // Above
+ }
+ }
+}
+
+void Sweep::fillLeftConcaveEdgeEvent(SweepContext& sc, Edge* edge, Node& node)
+{
+ fill(sc, *node.m_Prev);
+ if (node.m_Prev->m_Point != edge->m_P) {
+ // Next above or below edge?
+ if (orient2d(*edge->m_Q, *node.m_Prev->m_Point, *edge->m_P) == CW) {
+ // Below
+ if (orient2d(*node.m_Point, *node.m_Prev->m_Point,
+ *node.m_Prev->m_Prev->m_Point) == CW) {
+ // Next is concave
+ fillLeftConcaveEdgeEvent(sc, edge, node);
+ } else {
+ // Next is convex
+ }
+ }
+ }
+
+}
+
+void Sweep::flipEdgeEvent(SweepContext& sc, Point& ep, Point& eq,
+ TriangulationTriangle* t, Point& p)
+{
+ TriangulationTriangle& ot = t->neighborAcross(p);
+ Point& op = *ot.oppositePoint(*t, p);
+
+ if (&ot == NULL) {
+ // If we want to integrate the fillEdgeEvent do it here
+ // With current implementation we should never get here
+ //throw new RuntimeException( "[BUG:FIXM E] FLIP failed due to missing triangle");
+ assert(0);
+ }
+
+ if (inScanArea(p, *t->pointCCW(p), *t->pointCW(p), op)) {
+ // Lets rotate shared edge one vertex CW
+ rotateTrianglePair(*t, p, ot, op);
+ sc.mapTriangleToNodes(*t);
+ sc.mapTriangleToNodes(ot);
+
+ if (p == eq && op == ep) {
+ if (eq == *sc.m_EdgeEvent.m_ConstrainedEdge->m_Q
+ && ep == *sc.m_EdgeEvent.m_ConstrainedEdge->m_P) {
+ t->markConstrainedEdge(&ep, &eq);
+ ot.markConstrainedEdge(&ep, &eq);
+ legalize(sc, *t);
+ legalize(sc, ot);
+ } else {
+ // One of the triangles should be legalized here?
+ }
+ } else {
+ Orientation o = orient2d(eq, op, ep);
+ t = &nextFlipTriangle(sc, (int) o, *t, ot, p, op);
+ flipEdgeEvent(sc, ep, eq, t, p);
+ }
+ } else {
+ Point& newP = nextFlipPoint(ep, eq, ot, op);
+ flipScanEdgeEvent(sc, ep, eq, *t, ot, newP);
+ edgeEvent(sc, ep, eq, t, p);
+ }
+}
+
+TriangulationTriangle& Sweep::nextFlipTriangle(SweepContext& sc, int o,
+ TriangulationTriangle& t, TriangulationTriangle& ot, Point& p, Point& op)
+{
+ if (o == CCW) {
+ // ot is not crossing edge after flip
+ int edgeIndex = ot.edgeIndex(&p, &op);
+ ot.m_DelaunayEdge[edgeIndex] = true;
+ legalize(sc, ot);
+ ot.clearDelunayEdges();
+ return t;
+ }
+
+ // t is not crossing edge after flip
+ int edgeIndex = t.edgeIndex(&p, &op);
+
+ t.m_DelaunayEdge[edgeIndex] = true;
+ legalize(sc, t);
+ t.clearDelunayEdges();
+ return ot;
+}
+
+Point& Sweep::nextFlipPoint(Point& ep, Point& eq, TriangulationTriangle& ot, Point& op)
+{
+ Orientation o2d = orient2d(eq, op, ep);
+ if (o2d == CW) {
+ // Right
+ return *ot.pointCCW(op);
+ } else if (o2d == CCW) {
+ // Left
+ return *ot.pointCW(op);
+ } else {
+ //throw new RuntimeException("[Unsupported] Opposing point on constrained edge");
+ assert(0);
+ return ep; // Silence compiler warning.
+ }
+}
+
+void Sweep::flipScanEdgeEvent(SweepContext& sc, Point& ep, Point& eq,
+ TriangulationTriangle& flipTriangle, TriangulationTriangle& t, Point& p)
+{
+ TriangulationTriangle& ot = t.neighborAcross(p);
+ Point& op = *ot.oppositePoint(t, p);
+
+ if (&t.neighborAcross(p) == NULL) {
+ // If we want to integrate the fillEdgeEvent do it here
+ // With current implementation we should never get here
+ //throw new RuntimeException( "[BUG:FIXM E] FLIP failed due to missing triangle");
+ assert(0);
+ }
+
+ if (inScanArea(eq, *flipTriangle.pointCCW(eq), *flipTriangle.pointCW(eq),
+ op)) {
+ // flip with new edge op->eq
+ flipEdgeEvent(sc, eq, op, &ot, op);
+ // To do: Actually I just figured out that it should be possible to
+ // improve this by getting the next ot and op before the the above
+ // flip and continue the flipScanEdgeEvent here
+ // set new ot and op here and loop back to inScanArea test
+ // also need to set a new flip_triangle first
+ // Turns out at first glance that this is somewhat complicated
+ // so it will have to wait.
+ } else {
+ Point& newP = nextFlipPoint(ep, eq, ot, op);
+ flipScanEdgeEvent(sc, ep, eq, flipTriangle, ot, newP);
+ }
+}
+
+Sweep::~Sweep()
+{
+ for (unsigned int i = 0; i < m_Nodes.size(); i++) {
+ delete m_Nodes[i];
+ }
+
+}
+
+}
diff --git a/src/base/triangulate/Sweep.h b/src/base/triangulate/Sweep.h new file mode 100644 index 0000000..48cd13a --- /dev/null +++ b/src/base/triangulate/Sweep.h @@ -0,0 +1,201 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +// +// Based on Poly2Tri algorithm. +// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors +// http://code.google.com/p/poly2tri/ +// + +#ifndef SWEEP_H +#define SWEEP_H + +#include <vector> + +namespace avg { + +class SweepContext; +struct Node; +struct Point; +struct Edge; +class TriangulationTriangle; + +class Sweep +{ + +public: + + void Triangulate(SweepContext& sc); + + ~Sweep(); + +private: + + void sweepPoints(SweepContext& sc); + + Node& pointEvent(SweepContext& sc, Point& point); + + void edgeEvent(SweepContext& sc, Edge* edge, Node* node); + + void edgeEvent(SweepContext& sc, Point& ep, Point& eq, + TriangulationTriangle* triangle, Point& point); + + Node& newFrontTriangle(SweepContext& sc, Point& point, Node& node); + + void fill(SweepContext& sc, Node& node); + + bool legalize(SweepContext& sc, TriangulationTriangle& t); + + /** + * <b>Requirement</b>:<br> + * 1. a,b and c form a triangle.<br> + * 2. a and d is know to be on opposite side of bc<br> + * <pre> + * a + * + + * / \ + * / \ + * b/ \c + * +-------+ + * / d \ + * / \ + * </pre> + * <b>Fact</b>: d has to be in area B to have a chance to be inside the circle formed by + * a,b and c<br> + * d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW<br> + * This preknowledge gives us a way to optimize the incircle test + * @param a - triangle point, opposite d + * @param b - triangle point + * @param c - triangle point + * @param d - point opposite a + * @return true if d is inside circle, false if on circle edge + */ + bool incircle(Point& pa, Point& pb, Point& pc, Point& pd); + + /** + * Rotates a triangle pair one vertex CW + *<pre> + * n2 n2 + * P +-----+ P +-----+ + * | t /| |\ t | + * | / | | \ | + * n1| / |n3 n1| \ |n3 + * | / | after CW | \ | + * |/ oT | | oT \| + * +-----+ oP +-----+ + * n4 n4 + * </pre> + */ + void rotateTrianglePair(TriangulationTriangle& t, Point& p, TriangulationTriangle& ot, + Point& op); + + void fillAdvancingFront(SweepContext& sc, Node& n); + + double holeAngle(Node& node); + + /** + * The basin angle is decided against the horizontal line [1,0] + */ + double basinAngle(Node& node); + + void fillBasin(SweepContext& sc, Node& node); + + void fillBasinReq(SweepContext& sc, Node* node); + + bool isShallow(SweepContext& sc, Node& node); + + bool isEdgeSideOfTriangle(TriangulationTriangle& triangle, Point& ep, Point& eq); + + void fillEdgeEvent(SweepContext& sc, Edge* edge, Node* node); + + void fillRightAboveEdgeEvent(SweepContext& sc, Edge* edge, Node* node); + + void fillRightBelowEdgeEvent(SweepContext& sc, Edge* edge, Node& node); + + void fillRightConcaveEdgeEvent(SweepContext& sc, Edge* edge, Node& node); + + void fillRightConvexEdgeEvent(SweepContext& sc, Edge* edge, Node& node); + + void fillLeftAboveEdgeEvent(SweepContext& sc, Edge* edge, Node* node); + + void fillLeftBelowEdgeEvent(SweepContext& sc, Edge* edge, Node& node); + + void fillLeftConcaveEdgeEvent(SweepContext& sc, Edge* edge, Node& node); + + void fillLeftConvexEdgeEvent(SweepContext& sc, Edge* edge, Node& node); + + void flipEdgeEvent(SweepContext& sc, Point& ep, Point& eq, TriangulationTriangle* t, + Point& p); + + /** + * After a flip we have two triangles and know that only one will still be + * intersecting the edge. So decide which to contiune with and legalize the other + * + * @param sc + * @param o - should be the result of an orient2d( eq, op, ep ) + * @param t - triangle 1 + * @param ot - triangle 2 + * @param p - a point shared by both triangles + * @param op - another point shared by both triangles + * @return returns the triangle still intersecting the edge + */ + TriangulationTriangle& nextFlipTriangle(SweepContext& sc, int o, + TriangulationTriangle& t, TriangulationTriangle& ot, Point& p, Point& op); + + /** + * When we need to traverse from one triangle to the next we need + * the point in current triangle that is the opposite point to the next + * triangle. + * + * @param ep + * @param eq + * @param ot + * @param op + * @return + */ + Point& nextFlipPoint(Point& ep, Point& eq, TriangulationTriangle& ot, Point& op); + + /** + * Scan part of the FlipScan algorithm<br> + * When a triangle pair isn't flippable we will scan for the next + * point that is inside the flip triangle scan area. When found + * we generate a new flipEdgeEvent + * + * @param sc + * @param ep - last point on the edge we are traversing + * @param eq - first point on the edge we are traversing + * @param flipTriangle - the current triangle sharing the point eq with edge + * @param t + * @param p + */ + void flipScanEdgeEvent(SweepContext& sc, Point& ep, Point& eq, + TriangulationTriangle& flip_triangle, TriangulationTriangle& t, Point& p); + + void finalizationPolygon(SweepContext& sc); + + std::vector<Node*> m_Nodes; + unsigned int arrayCount; + +}; + +} + +#endif diff --git a/src/base/triangulate/SweepContext.cpp b/src/base/triangulate/SweepContext.cpp new file mode 100644 index 0000000..16e642e --- /dev/null +++ b/src/base/triangulate/SweepContext.cpp @@ -0,0 +1,196 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +// +// Based on Poly2Tri algorithm. +// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors +// http://code.google.com/p/poly2tri/ +// + +#include "SweepContext.h" +#include <algorithm> +#include "AdvancingFront.h" + +namespace avg { + +SweepContext::SweepContext(std::vector<Point*> polyline) +{ + m_Basin = Basin(); + m_EdgeEvent = EdgeEvent(); + + m_Points = polyline; + + initEdges(m_Points); +} + +void SweepContext::addHole(std::vector<Point*> polyline) +{ + initEdges(polyline); + for (unsigned int i = 0; i < polyline.size(); i++) { + m_Points.push_back(polyline[i]); + } +} + +void SweepContext::addPoint(Point* point) +{ + m_Points.push_back(point); +} + +std::vector<TriangulationTriangle*>& SweepContext::getTriangles() +{ + return m_Triangles; +} + +void SweepContext::initTriangulation() +{ + double xmax(m_Points[0]->m_X), xmin(m_Points[0]->m_X); + double ymax(m_Points[0]->m_Y), ymin(m_Points[0]->m_Y); + + // Calculate bounds. + for (unsigned int i = 0; i < m_Points.size(); i++) { + Point& p = *m_Points[i]; + if (p.m_X > xmax) { + xmax = p.m_X; + } + if (p.m_X < xmin) { + xmin = p.m_X; + } + if (p.m_Y > ymax) { + ymax = p.m_Y; + } + if (p.m_Y < ymin) { + ymin = p.m_Y; + } + } + + double dx = kAlpha * (xmax - xmin); + double dy = kAlpha * (ymax - ymin); + m_Head = new Point(xmax + dx, ymin - dy, 0); + m_Tail = new Point(xmin - dx, ymin - dy, 0); + + // Sort along y-axis + std::sort(m_Points.begin(), m_Points.end(), cmp); + +} + +void SweepContext::initEdges(std::vector<Point*> polyline) +{ + int numPoints = polyline.size(); + for (int i = 0; i < numPoints; i++) { + int j = i < numPoints - 1 ? i + 1 : 0; + + m_EdgeList.push_back(new Edge(*polyline[i], *polyline[j])); + } +} + +Point* SweepContext::getPoint(const int& index) +{ + return m_Points[index]; +} + +void SweepContext::addToMap(TriangulationTriangle* triangle) +{ + m_Map.push_back(triangle); +} + +Node& SweepContext::locateNode(Point& point) +{ + // TO DO implement search tree + return *m_Front->locateNode(point.m_X); +} + +void SweepContext::createAdvancingFront() +{ + // Initial triangle + TriangulationTriangle* triangle = new TriangulationTriangle(*m_Points[0], *m_Tail, + *m_Head); + + m_Map.push_back(triangle); + + m_AfHead = new Node(*triangle->getPoint(1), *triangle); + m_AfMiddle = new Node(*triangle->getPoint(0), *triangle); + m_AfTail = new Node(*triangle->getPoint(2)); + m_Front = new AdvancingFront(*m_AfHead, *m_AfTail); + + m_AfHead->m_Next = m_AfMiddle; + m_AfMiddle->m_Next = m_AfTail; + m_AfMiddle->m_Prev = m_AfHead; + m_AfTail->m_Prev = m_AfMiddle; +} + +void SweepContext::removeNode(Node* node) +{ + delete node; +} + +void SweepContext::mapTriangleToNodes(TriangulationTriangle& t) +{ + for (int i = 0; i < 3; i++) { + if (!t.getNeighbor(i)) { + Node* n = m_Front->locatePoint(t.pointCW(*t.getPoint(i))); + if (n) { + n->m_Triangle = &t; + } + } + } +} + +void SweepContext::removeFromMap(TriangulationTriangle* triangle) +{ + m_Map.remove(triangle); +} + +void SweepContext::meshClean(TriangulationTriangle& triangle) +{ + if (&triangle != NULL && !triangle.isInterior()) { + triangle.isInterior(true); + m_Triangles.push_back(&triangle); + for (int i = 0; i < 3; i++) { + if (!triangle.m_ConstrainedEdge[i]) + meshClean(*triangle.getNeighbor(i)); + } + } +} + +SweepContext::~SweepContext() +{ + + delete m_Head; + delete m_Tail; + delete m_Front; + delete m_AfHead; + delete m_AfMiddle; + delete m_AfTail; + + typedef std::list<TriangulationTriangle*> type_list; + + for (type_list::iterator iter = m_Map.begin(); iter != m_Map.end(); ++iter) { + TriangulationTriangle* ptr = *iter; + delete ptr; + } + + for (unsigned int i = 0; i < m_EdgeList.size(); i++) { + delete m_EdgeList[i]; + } + +} + +} diff --git a/src/base/triangulate/SweepContext.h b/src/base/triangulate/SweepContext.h new file mode 100644 index 0000000..0b9e51d --- /dev/null +++ b/src/base/triangulate/SweepContext.h @@ -0,0 +1,181 @@ +//
+// libavg - Media Playback Engine.
+// Copyright (C) 2003-2014 Ulrich von Zadow +//
+// 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 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Current versions can be found at www.libavg.de
+//
+
+//
+// Based on Poly2Tri algorithm.
+// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+// http://code.google.com/p/poly2tri/
+//
+
+#ifndef SWEEP_CONTEXT_H
+#define SWEEP_CONTEXT_H
+
+#include <list>
+#include <vector>
+#include <cstddef>
+
+namespace avg {
+
+// Inital triangle factor, seed triangle will extend 30% of
+// PointSet width to both left and right.
+const double kAlpha = 0.3;
+
+struct Point;
+class TriangulationTriangle;
+struct Node;
+struct Edge;
+class AdvancingFront;
+
+class SweepContext
+{
+
+public:
+
+ SweepContext(std::vector<Point*> polyline);
+
+ ~SweepContext();
+
+ void setHead(Point* p1);
+
+ Point* head();
+
+ void setTail(Point* p1);
+
+ Point* tail();
+
+ int pointCount();
+
+ Node& locateNode(Point& point);
+
+ void removeNode(Node* node);
+
+ void createAdvancingFront();
+
+/// Try to map a node to all sides of this triangle that don't have a neighbor
+ void mapTriangleToNodes(TriangulationTriangle& t);
+
+ void addToMap(TriangulationTriangle* triangle);
+
+ Point* getPoint(const int& index);
+
+ Point* GetPoints();
+
+ void removeFromMap(TriangulationTriangle* triangle);
+
+ void addHole(std::vector<Point*> polyline);
+
+ void addPoint(Point* point);
+
+ AdvancingFront* front();
+
+ void meshClean(TriangulationTriangle& triangle);
+
+ std::vector<TriangulationTriangle*>& getTriangles();
+
+ std::vector<Edge*> m_EdgeList;
+
+ struct Basin
+ {
+ Node* m_LeftNode;
+ Node* m_BottomNode;
+ Node* m_RightNode;
+ double m_Width;
+ bool m_LeftHighest;
+
+ Basin()
+ {
+ clear();
+ }
+
+ void clear() {
+ m_LeftNode = NULL;
+ m_BottomNode = NULL;
+ m_RightNode = NULL;
+ m_Width = 0.0;
+ m_LeftHighest = false;
+ }
+ };
+
+ struct EdgeEvent
+ {
+ Edge* m_ConstrainedEdge;
+ bool m_Right;
+
+ EdgeEvent() :
+ m_ConstrainedEdge(NULL), m_Right(false) {
+ }
+ };
+
+ Basin m_Basin;
+ EdgeEvent m_EdgeEvent;
+
+private:
+
+ friend class Sweep;
+
+ std::vector<TriangulationTriangle*> m_Triangles;
+ std::list<TriangulationTriangle*> m_Map;
+ std::vector<Point*> m_Points;
+
+ AdvancingFront* m_Front;
+ Point* m_Head;
+ Point* m_Tail;
+
+ Node *m_AfHead, *m_AfMiddle, *m_AfTail;
+
+ void initTriangulation();
+ void initEdges(std::vector<Point*> polyline);
+
+};
+
+inline AdvancingFront* SweepContext::front()
+{
+ return m_Front;
+}
+
+inline int SweepContext::pointCount()
+{
+ return m_Points.size();
+}
+
+inline void SweepContext::setHead(Point* p1)
+{
+ m_Head = p1;
+}
+
+inline Point* SweepContext::head()
+{
+ return m_Head;
+}
+
+inline void SweepContext::setTail(Point* p1)
+{
+ m_Tail = p1;
+}
+
+inline Point* SweepContext::tail()
+{
+ return m_Tail;
+}
+
+}
+
+#endif
diff --git a/src/base/triangulate/Triangulate.cpp b/src/base/triangulate/Triangulate.cpp new file mode 100644 index 0000000..9206327 --- /dev/null +++ b/src/base/triangulate/Triangulate.cpp @@ -0,0 +1,90 @@ +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +// +// Based on Poly2Tri algorithm. +// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors +// http://code.google.com/p/poly2tri/ +// + +#include "Triangulate.h" +#include "Sweep.h" +#include "SweepContext.h" + +#include "Shapes.h" + +using namespace std; + +namespace avg { + +void triangulatePolygon(std::vector<unsigned int>& dest, const Vec2Vector& points, + const std::vector<unsigned int>& holeIndexes) +{ + std::vector<Point*> polyline; + std::vector<Point*> holeLine; + unsigned int contourEnd; + + if (holeIndexes.size() > 0) { + contourEnd = holeIndexes[0]; + } else { + contourEnd = points.size(); + } + + for (unsigned int i = 0; i < contourEnd; i++) { + polyline.push_back(new Point(points[i].x, points[i].y, i)); + } + + SweepContext* sweepContext = new SweepContext(polyline); + Sweep* sweep = new Sweep; + + if (holeIndexes.size() > 0) { + for (unsigned int i = 0; i < holeIndexes.size(); i++) { + if ( i < holeIndexes.size()-1) { + for (unsigned int j = holeIndexes[i]; j < points.size() && j < + holeIndexes[i+1]; j++) + { + holeLine.push_back(new Point(points[j].x, points[j].y, j)); + } + } else { + for (unsigned int j = holeIndexes[i]; j < points.size(); j++) { + holeLine.push_back(new Point(points[j].x, points[j].y, j)); + } + } + sweepContext->addHole(holeLine); + holeLine.clear(); + } + } + + sweep->Triangulate(*sweepContext); + + std::vector<avg::TriangulationTriangle*>& triangles = sweepContext->getTriangles(); + for (unsigned int i = 0; i < triangles.size(); ++i) { + dest.push_back(triangles[i]->getPoint(0)->m_Index); + dest.push_back(triangles[i]->getPoint(1)->m_Index); + dest.push_back(triangles[i]->getPoint(2)->m_Index); + } + + delete sweep; + delete sweepContext; + + for (unsigned int i = 0; i < polyline.size(); i++) { + delete polyline[i]; + } +} + +} diff --git a/src/base/triangulate/Triangulate.h b/src/base/triangulate/Triangulate.h new file mode 100644 index 0000000..af538a6 --- /dev/null +++ b/src/base/triangulate/Triangulate.h @@ -0,0 +1,33 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// 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 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de +// + +#ifndef TRIANGULATION_H_ +#define TRIANGULATION_H_ + +#include "../GLMHelper.h" +namespace avg { + + void triangulatePolygon(std::vector<unsigned int>& dest, const Vec2Vector& points, + const std::vector<unsigned int>& holeIndexes = std::vector<unsigned int>()); + +} + +#endif /* TRIANGULATION_H_ */ diff --git a/src/base/triangulate/Utils.h b/src/base/triangulate/Utils.h new file mode 100644 index 0000000..5dd6685 --- /dev/null +++ b/src/base/triangulate/Utils.h @@ -0,0 +1,124 @@ +/*
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Poly2Tri nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+// Otherwise #defines like M_PI are undeclared under Visual Studio
+#define _USE_MATH_DEFINES
+
+#include <exception>
+#include <math.h>
+
+namespace avg {
+
+const double PI_3div4 = 3 * M_PI / 4;
+const double EPSILON = 1e-12;
+
+enum Orientation
+{
+ CW, CCW, COLLINEAR
+};
+
+/**
+ * Forumla to calculate signed area<br>
+ * Positive if CCW<br>
+ * Negative if CW<br>
+ * 0 if collinear<br>
+ * <pre>
+ * A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
+ * = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
+ * </pre>
+ */
+Orientation orient2d(Point& pa, Point& pb, Point& pc)
+{
+ double detleft = (pa.m_X - pc.m_X) * (pb.m_Y - pc.m_Y);
+ double detright = (pa.m_Y - pc.m_Y) * (pb.m_X - pc.m_X);
+ double val = detleft - detright;
+ if (val > -EPSILON && val < EPSILON) {
+ return COLLINEAR;
+ } else if (val > 0) {
+ return CCW;
+ }
+ return CW;
+}
+
+/*
+ bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
+ {
+ double pdx = pd.x;
+ double pdy = pd.y;
+ double adx = pa.x - pdx;
+ double ady = pa.y - pdy;
+ double bdx = pb.x - pdx;
+ double bdy = pb.y - pdy;
+
+ double adxbdy = adx * bdy;
+ double bdxady = bdx * ady;
+ double oabd = adxbdy - bdxady;
+
+ if (oabd <= EPSILON) {
+ return false;
+ }
+
+ double cdx = pc.x - pdx;
+ double cdy = pc.y - pdy;
+
+ double cdxady = cdx * ady;
+ double adxcdy = adx * cdy;
+ double ocad = cdxady - adxcdy;
+
+ if (ocad <= EPSILON) {
+ return false;
+ }
+
+ return true;
+ }
+
+ */
+
+bool inScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
+{
+ double oadb = (pa.m_X - pb.m_X) * (pd.m_Y - pb.m_Y) - (pd.m_X - pb.m_X) * (pa.m_Y - pb.m_Y);
+ if (oadb >= -EPSILON) {
+ return false;
+ }
+
+ double oadc = (pa.m_X - pc.m_X) * (pd.m_Y - pc.m_Y) - (pd.m_X - pc.m_X) * (pa.m_Y - pc.m_Y);
+ if (oadc <= EPSILON) {
+ return false;
+ }
+ return true;
+}
+
+}
+
+#endif
|