diff --git a/code/BoostWorkaround/boost/LICENSE_1_0.txt b/code/BoostWorkaround/boost/LICENSE_1_0.txt index 30aac2cf4..127a5bc39 100644 --- a/code/BoostWorkaround/boost/LICENSE_1_0.txt +++ b/code/BoostWorkaround/boost/LICENSE_1_0.txt @@ -1,23 +1,23 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/code/BoostWorkaround/boost/foreach.hpp b/code/BoostWorkaround/boost/foreach.hpp index 5b5df6a36..404d325c6 100644 --- a/code/BoostWorkaround/boost/foreach.hpp +++ b/code/BoostWorkaround/boost/foreach.hpp @@ -1,99 +1,99 @@ - -#ifndef BOOST_FOREACH - -/////////////////////////////////////////////////////////////////////////////// -// A stripped down version of FOREACH for -// illustration purposes. NOT FOR GENERAL USE. -// For a complete implementation, see BOOST_FOREACH at -// http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler -// -// Copyright 2004 Eric Niebler. -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Adapted to Assimp November 29th, 2008 (Alexander Gessler). -// Added code to handle both const and non-const iterators, simplified some -// parts. -/////////////////////////////////////////////////////////////////////////////// - -namespace boost { -namespace foreach_detail { - -/////////////////////////////////////////////////////////////////////////////// -// auto_any - -struct auto_any_base -{ - operator bool() const { return false; } -}; - -template -struct auto_any : auto_any_base -{ - auto_any(T const& t) : item(t) {} - mutable T item; -}; - -template -T& auto_any_cast(auto_any_base const& any) -{ - return static_cast const&>(any).item; -} - -/////////////////////////////////////////////////////////////////////////////// -// FOREACH helper function - -template -auto_any begin(T const& t) -{ - return t.begin(); -} - -template -auto_any end(T const& t) -{ - return t.end(); -} - -// iterator -template -bool done(auto_any_base const& cur, auto_any_base const& end, T&) -{ - typedef typename T::iterator iter_type; - return auto_any_cast(cur) == auto_any_cast(end); -} - -template -void next(auto_any_base const& cur, T&) -{ - ++auto_any_cast(cur); -} - -template -typename T::reference deref(auto_any_base const& cur, T&) -{ - return *auto_any_cast(cur); -} - -template -typename T::const_reference deref(auto_any_base const& cur, const T&) -{ - return *auto_any_cast(cur); -} - -} // end foreach_detail - -/////////////////////////////////////////////////////////////////////////////// -// FOREACH - -#define BOOST_FOREACH(item, container) \ - if(boost::foreach_detail::auto_any_base const& foreach_magic_b = boost::foreach_detail::begin(container)) {} else \ - if(boost::foreach_detail::auto_any_base const& foreach_magic_e = boost::foreach_detail::end(container)) {} else \ - for(;!boost::foreach_detail::done(foreach_magic_b,foreach_magic_e,container); boost::foreach_detail::next(foreach_magic_b,container)) \ - if (bool ugly_and_unique_break = false) {} else \ - for(item = boost::foreach_detail::deref(foreach_magic_b,container); !ugly_and_unique_break; ugly_and_unique_break = true) - -} // end boost - -#endif + +#ifndef BOOST_FOREACH + +/////////////////////////////////////////////////////////////////////////////// +// A stripped down version of FOREACH for +// illustration purposes. NOT FOR GENERAL USE. +// For a complete implementation, see BOOST_FOREACH at +// http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler +// +// Copyright 2004 Eric Niebler. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Adapted to Assimp November 29th, 2008 (Alexander Gessler). +// Added code to handle both const and non-const iterators, simplified some +// parts. +/////////////////////////////////////////////////////////////////////////////// + +namespace boost { +namespace foreach_detail { + +/////////////////////////////////////////////////////////////////////////////// +// auto_any + +struct auto_any_base +{ + operator bool() const { return false; } +}; + +template +struct auto_any : auto_any_base +{ + auto_any(T const& t) : item(t) {} + mutable T item; +}; + +template +T& auto_any_cast(auto_any_base const& any) +{ + return static_cast const&>(any).item; +} + +/////////////////////////////////////////////////////////////////////////////// +// FOREACH helper function + +template +auto_any begin(T const& t) +{ + return t.begin(); +} + +template +auto_any end(T const& t) +{ + return t.end(); +} + +// iterator +template +bool done(auto_any_base const& cur, auto_any_base const& end, T&) +{ + typedef typename T::iterator iter_type; + return auto_any_cast(cur) == auto_any_cast(end); +} + +template +void next(auto_any_base const& cur, T&) +{ + ++auto_any_cast(cur); +} + +template +typename T::reference deref(auto_any_base const& cur, T&) +{ + return *auto_any_cast(cur); +} + +template +typename T::const_reference deref(auto_any_base const& cur, const T&) +{ + return *auto_any_cast(cur); +} + +} // end foreach_detail + +/////////////////////////////////////////////////////////////////////////////// +// FOREACH + +#define BOOST_FOREACH(item, container) \ + if(boost::foreach_detail::auto_any_base const& foreach_magic_b = boost::foreach_detail::begin(container)) {} else \ + if(boost::foreach_detail::auto_any_base const& foreach_magic_e = boost::foreach_detail::end(container)) {} else \ + for(;!boost::foreach_detail::done(foreach_magic_b,foreach_magic_e,container); boost::foreach_detail::next(foreach_magic_b,container)) \ + if (bool ugly_and_unique_break = false) {} else \ + for(item = boost::foreach_detail::deref(foreach_magic_b,container); !ugly_and_unique_break; ugly_and_unique_break = true) + +} // end boost + +#endif diff --git a/code/BoostWorkaround/boost/lexical_cast.hpp b/code/BoostWorkaround/boost/lexical_cast.hpp index 7724e4607..af91b011f 100644 --- a/code/BoostWorkaround/boost/lexical_cast.hpp +++ b/code/BoostWorkaround/boost/lexical_cast.hpp @@ -1,26 +1,26 @@ -/// A quick replacement for boost::lexical_cast for all the Boost haters out there - -#ifndef __AI_BOOST_WORKAROUND_LEXICAL_CAST -#define __AI_BOOST_WORKAROUND_LEXICAL_CAST - -#include - -namespace boost -{ - - /// A quick replacement for boost::lexical_cast - should work for all types a stringstream can handle - template - TargetType lexical_cast( const SourceType& source) - { - std::stringstream stream; - TargetType result; - - stream << source; - stream >> result; - return result; - } - -} // namespace boost - -#endif // __AI_BOOST_WORKAROUND_LEXICAL_CAST - +/// A quick replacement for boost::lexical_cast for all the Boost haters out there + +#ifndef __AI_BOOST_WORKAROUND_LEXICAL_CAST +#define __AI_BOOST_WORKAROUND_LEXICAL_CAST + +#include + +namespace boost +{ + + /// A quick replacement for boost::lexical_cast - should work for all types a stringstream can handle + template + TargetType lexical_cast( const SourceType& source) + { + std::stringstream stream; + TargetType result; + + stream << source; + stream >> result; + return result; + } + +} // namespace boost + +#endif // __AI_BOOST_WORKAROUND_LEXICAL_CAST + diff --git a/code/BoostWorkaround/boost/make_shared.hpp b/code/BoostWorkaround/boost/make_shared.hpp index b7b29caa5..d1abb1be6 100644 --- a/code/BoostWorkaround/boost/make_shared.hpp +++ b/code/BoostWorkaround/boost/make_shared.hpp @@ -1,57 +1,57 @@ - -// please note that this replacement implementation does not -// provide the performance benefit of the original, which -// makes only one allocation as opposed to two allocations -// (smart pointer counter and payload) which are usually -// required if object and smart pointer are constructed -// independently. - -#ifndef INCLUDED_AI_BOOST_MAKE_SHARED -#define INCLUDED_AI_BOOST_MAKE_SHARED - - -namespace boost { - - template - shared_ptr make_shared() { - return shared_ptr(new T()); - } - - template - shared_ptr make_shared(const T0& t0) { - return shared_ptr(new T(t0)); - } - - template - shared_ptr make_shared(const T0& t0, const T1& t1) { - return shared_ptr(new T(t0,t1)); - } - - template - shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2) { - return shared_ptr(new T(t0,t1,t2)); - } - - template - shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3) { - return shared_ptr(new T(t0,t1,t2,t3)); - } - - template - shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4) { - return shared_ptr(new T(t0,t1,t2,t3,t4)); - } - - template - shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) { - return shared_ptr(new T(t0,t1,t2,t3,t4,t5)); - } - - template - shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6) { - return shared_ptr(new T(t0,t1,t2,t3,t4,t5,t6)); - } -} - - -#endif + +// please note that this replacement implementation does not +// provide the performance benefit of the original, which +// makes only one allocation as opposed to two allocations +// (smart pointer counter and payload) which are usually +// required if object and smart pointer are constructed +// independently. + +#ifndef INCLUDED_AI_BOOST_MAKE_SHARED +#define INCLUDED_AI_BOOST_MAKE_SHARED + + +namespace boost { + + template + shared_ptr make_shared() { + return shared_ptr(new T()); + } + + template + shared_ptr make_shared(const T0& t0) { + return shared_ptr(new T(t0)); + } + + template + shared_ptr make_shared(const T0& t0, const T1& t1) { + return shared_ptr(new T(t0,t1)); + } + + template + shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2) { + return shared_ptr(new T(t0,t1,t2)); + } + + template + shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3) { + return shared_ptr(new T(t0,t1,t2,t3)); + } + + template + shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4) { + return shared_ptr(new T(t0,t1,t2,t3,t4)); + } + + template + shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) { + return shared_ptr(new T(t0,t1,t2,t3,t4,t5)); + } + + template + shared_ptr make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6) { + return shared_ptr(new T(t0,t1,t2,t3,t4,t5,t6)); + } +} + + +#endif diff --git a/code/BoostWorkaround/boost/math/common_factor_rt.hpp b/code/BoostWorkaround/boost/math/common_factor_rt.hpp index 46a70a298..f7615f974 100644 --- a/code/BoostWorkaround/boost/math/common_factor_rt.hpp +++ b/code/BoostWorkaround/boost/math/common_factor_rt.hpp @@ -1,37 +1,37 @@ - - -#ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP -#define BOOST_MATH_COMMON_FACTOR_RT_HPP - - -namespace boost { -namespace math { - -// TODO: use binary GCD for unsigned integers .... -template < typename IntegerType > -IntegerType gcd( IntegerType a, IntegerType b ) -{ - const IntegerType zero = (IntegerType)0; - while ( true ) - { - if ( a == zero ) - return b; - b %= a; - - if ( b == zero ) - return a; - a %= b; - } -} - -template < typename IntegerType > -IntegerType lcm( IntegerType a, IntegerType b ) -{ - const IntegerType t = gcd (a,b); - if (!t)return t; - return a / t * b; -} - -}} - -#endif + + +#ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP +#define BOOST_MATH_COMMON_FACTOR_RT_HPP + + +namespace boost { +namespace math { + +// TODO: use binary GCD for unsigned integers .... +template < typename IntegerType > +IntegerType gcd( IntegerType a, IntegerType b ) +{ + const IntegerType zero = (IntegerType)0; + while ( true ) + { + if ( a == zero ) + return b; + b %= a; + + if ( b == zero ) + return a; + a %= b; + } +} + +template < typename IntegerType > +IntegerType lcm( IntegerType a, IntegerType b ) +{ + const IntegerType t = gcd (a,b); + if (!t)return t; + return a / t * b; +} + +}} + +#endif diff --git a/code/BoostWorkaround/boost/noncopyable.hpp b/code/BoostWorkaround/boost/noncopyable.hpp index 7deb935fb..7770bdbd3 100644 --- a/code/BoostWorkaround/boost/noncopyable.hpp +++ b/code/BoostWorkaround/boost/noncopyable.hpp @@ -1,36 +1,36 @@ -// Boost noncopyable.hpp header file --------------------------------------// - -// (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/libs/utility for documentation. - -#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED -#define BOOST_NONCOPYABLE_HPP_INCLUDED - -namespace boost { - -// Private copy constructor and copy assignment ensure classes derived from -// class noncopyable cannot be copied. - -// Contributed by Dave Abrahams - -namespace noncopyable_ // protection from unintended ADL -{ - class noncopyable - { - protected: - noncopyable() {} - ~noncopyable() {} - private: // emphasize the following members are private - noncopyable( const noncopyable& ); - const noncopyable& operator=( const noncopyable& ); - }; -} - -typedef noncopyable_::noncopyable noncopyable; - -} // namespace boost - -#endif // BOOST_NONCOPYABLE_HPP_INCLUDED +// Boost noncopyable.hpp header file --------------------------------------// + +// (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/utility for documentation. + +#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED +#define BOOST_NONCOPYABLE_HPP_INCLUDED + +namespace boost { + +// Private copy constructor and copy assignment ensure classes derived from +// class noncopyable cannot be copied. + +// Contributed by Dave Abrahams + +namespace noncopyable_ // protection from unintended ADL +{ + class noncopyable + { + protected: + noncopyable() {} + ~noncopyable() {} + private: // emphasize the following members are private + noncopyable( const noncopyable& ); + const noncopyable& operator=( const noncopyable& ); + }; +} + +typedef noncopyable_::noncopyable noncopyable; + +} // namespace boost + +#endif // BOOST_NONCOPYABLE_HPP_INCLUDED diff --git a/code/BoostWorkaround/boost/pointer_cast.hpp b/code/BoostWorkaround/boost/pointer_cast.hpp index 1083f599e..6e532ebdd 100644 --- a/code/BoostWorkaround/boost/pointer_cast.hpp +++ b/code/BoostWorkaround/boost/pointer_cast.hpp @@ -1,45 +1,45 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2005. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_POINTER_CAST_HPP -#define BOOST_POINTER_CAST_HPP - -namespace boost { - -//static_pointer_cast overload for raw pointers -template -inline T* static_pointer_cast(U *ptr) -{ - return static_cast(ptr); -} - -//dynamic_pointer_cast overload for raw pointers -template -inline T* dynamic_pointer_cast(U *ptr) -{ - return dynamic_cast(ptr); -} - -//const_pointer_cast overload for raw pointers -template -inline T* const_pointer_cast(U *ptr) -{ - return const_cast(ptr); -} - -//reinterpret_pointer_cast overload for raw pointers -template -inline T* reinterpret_pointer_cast(U *ptr) -{ - return reinterpret_cast(ptr); -} - -} // namespace boost - -#endif //BOOST_POINTER_CAST_HPP +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_POINTER_CAST_HPP +#define BOOST_POINTER_CAST_HPP + +namespace boost { + +//static_pointer_cast overload for raw pointers +template +inline T* static_pointer_cast(U *ptr) +{ + return static_cast(ptr); +} + +//dynamic_pointer_cast overload for raw pointers +template +inline T* dynamic_pointer_cast(U *ptr) +{ + return dynamic_cast(ptr); +} + +//const_pointer_cast overload for raw pointers +template +inline T* const_pointer_cast(U *ptr) +{ + return const_cast(ptr); +} + +//reinterpret_pointer_cast overload for raw pointers +template +inline T* reinterpret_pointer_cast(U *ptr) +{ + return reinterpret_cast(ptr); +} + +} // namespace boost + +#endif //BOOST_POINTER_CAST_HPP diff --git a/code/BoostWorkaround/boost/scoped_array.hpp b/code/BoostWorkaround/boost/scoped_array.hpp index 7b1d8cc42..fb1b11544 100644 --- a/code/BoostWorkaround/boost/scoped_array.hpp +++ b/code/BoostWorkaround/boost/scoped_array.hpp @@ -1,79 +1,79 @@ - -#ifndef __AI_BOOST_SCOPED_ARRAY_INCLUDED -#define __AI_BOOST_SCOPED_ARRAY_INCLUDED - -#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED - -namespace boost { - -// small replacement for boost::scoped_array -template -class scoped_array -{ -public: - - // provide a default construtctor - scoped_array() - : ptr(0) - { - } - - // construction from an existing heap object of type T - scoped_array(T* _ptr) - : ptr(_ptr) - { - } - - // automatic destruction of the wrapped object at the - // end of our lifetime - ~scoped_array() - { - delete[] ptr; - } - - inline T* get() - { - return ptr; - } - - inline T* operator-> () - { - return ptr; - } - - inline void reset (T* t = 0) - { - delete[] ptr; - ptr = t; - } - - T & operator[](std::ptrdiff_t i) const - { - return ptr[i]; - } - - void swap(scoped_array & b) - { - std::swap(ptr, b.ptr); - } - -private: - - // encapsulated object pointer - T* ptr; - -}; - -template -inline void swap(scoped_array & a, scoped_array & b) -{ - a.swap(b); -} - -} // end of namespace boost - -#else -# error "scoped_array.h was already included" -#endif -#endif // __AI_BOOST_SCOPED_ARRAY_INCLUDED - + +#ifndef __AI_BOOST_SCOPED_ARRAY_INCLUDED +#define __AI_BOOST_SCOPED_ARRAY_INCLUDED + +#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED + +namespace boost { + +// small replacement for boost::scoped_array +template +class scoped_array +{ +public: + + // provide a default construtctor + scoped_array() + : ptr(0) + { + } + + // construction from an existing heap object of type T + scoped_array(T* _ptr) + : ptr(_ptr) + { + } + + // automatic destruction of the wrapped object at the + // end of our lifetime + ~scoped_array() + { + delete[] ptr; + } + + inline T* get() + { + return ptr; + } + + inline T* operator-> () + { + return ptr; + } + + inline void reset (T* t = 0) + { + delete[] ptr; + ptr = t; + } + + T & operator[](std::ptrdiff_t i) const + { + return ptr[i]; + } + + void swap(scoped_array & b) + { + std::swap(ptr, b.ptr); + } + +private: + + // encapsulated object pointer + T* ptr; + +}; + +template +inline void swap(scoped_array & a, scoped_array & b) +{ + a.swap(b); +} + +} // end of namespace boost + +#else +# error "scoped_array.h was already included" +#endif +#endif // __AI_BOOST_SCOPED_ARRAY_INCLUDED + diff --git a/code/BoostWorkaround/boost/scoped_ptr.hpp b/code/BoostWorkaround/boost/scoped_ptr.hpp index 615db640d..80c394def 100644 --- a/code/BoostWorkaround/boost/scoped_ptr.hpp +++ b/code/BoostWorkaround/boost/scoped_ptr.hpp @@ -1,79 +1,79 @@ - -#ifndef __AI_BOOST_SCOPED_PTR_INCLUDED -#define __AI_BOOST_SCOPED_PTR_INCLUDED - -#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED - -namespace boost { - -// small replacement for boost::scoped_ptr -template -class scoped_ptr -{ -public: - - // provide a default construtctor - scoped_ptr() - : ptr(0) - { - } - - // construction from an existing heap object of type T - scoped_ptr(T* _ptr) - : ptr(_ptr) - { - } - - // automatic destruction of the wrapped object at the - // end of our lifetime - ~scoped_ptr() - { - delete ptr; - } - - inline T* get() const - { - return ptr; - } - - inline operator T*() - { - return ptr; - } - - inline T* operator-> () - { - return ptr; - } - - inline void reset (T* t = 0) - { - delete ptr; - ptr = t; - } - - void swap(scoped_ptr & b) - { - std::swap(ptr, b.ptr); - } - -private: - - // encapsulated object pointer - T* ptr; - -}; - -template -inline void swap(scoped_ptr & a, scoped_ptr & b) -{ - a.swap(b); -} - -} // end of namespace boost - -#else -# error "scoped_ptr.h was already included" -#endif -#endif // __AI_BOOST_SCOPED_PTR_INCLUDED - + +#ifndef __AI_BOOST_SCOPED_PTR_INCLUDED +#define __AI_BOOST_SCOPED_PTR_INCLUDED + +#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED + +namespace boost { + +// small replacement for boost::scoped_ptr +template +class scoped_ptr +{ +public: + + // provide a default construtctor + scoped_ptr() + : ptr(0) + { + } + + // construction from an existing heap object of type T + scoped_ptr(T* _ptr) + : ptr(_ptr) + { + } + + // automatic destruction of the wrapped object at the + // end of our lifetime + ~scoped_ptr() + { + delete ptr; + } + + inline T* get() const + { + return ptr; + } + + inline operator T*() + { + return ptr; + } + + inline T* operator-> () + { + return ptr; + } + + inline void reset (T* t = 0) + { + delete ptr; + ptr = t; + } + + void swap(scoped_ptr & b) + { + std::swap(ptr, b.ptr); + } + +private: + + // encapsulated object pointer + T* ptr; + +}; + +template +inline void swap(scoped_ptr & a, scoped_ptr & b) +{ + a.swap(b); +} + +} // end of namespace boost + +#else +# error "scoped_ptr.h was already included" +#endif +#endif // __AI_BOOST_SCOPED_PTR_INCLUDED + diff --git a/code/BoostWorkaround/boost/shared_array.hpp b/code/BoostWorkaround/boost/shared_array.hpp index 2d068d556..9847d9f82 100644 --- a/code/BoostWorkaround/boost/shared_array.hpp +++ b/code/BoostWorkaround/boost/shared_array.hpp @@ -1,228 +1,228 @@ - -#ifndef INCLUDED_AI_BOOST_SHARED_ARRAY -#define INCLUDED_AI_BOOST_SHARED_ARRAY - -#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED - -// ------------------------------ -// Internal stub -namespace boost { - namespace array_detail { - class controller { - public: - - controller() - : cnt(1) - {} - - public: - - template - controller* decref(T* pt) { - if (--cnt <= 0) { - delete this; - delete[] pt; - } - return NULL; - } - - controller* incref() { - ++cnt; - return this; - } - - long get() const { - return cnt; - } - - private: - long cnt; - }; - - struct empty {}; - - template - struct is_convertible_stub { - - struct yes {char s[1];}; - struct no {char s[2];}; - - static yes foo(DEST*); - static no foo(...); - - enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)}; - }; - - template struct enable_if {}; - template <> struct enable_if { - typedef empty result; - }; - - template - struct is_convertible : public enable_if::result > { - }; - } - -// ------------------------------ -// Small replacement for boost::shared_array, not threadsafe because no -// atomic reference counter is in use. -// ------------------------------ -template -class shared_array -{ - template friend class shared_array; - - template friend bool operator== (const shared_array& a, const shared_array& b); - template friend bool operator!= (const shared_array& a, const shared_array& b); - template friend bool operator< (const shared_array& a, const shared_array& b); - -public: - - typedef T element_type; - -public: - - // provide a default constructor - shared_array() - : ptr() - , ctr(NULL) - { - } - - // construction from an existing object of type T - explicit shared_array(T* ptr) - : ptr(ptr) - , ctr(ptr ? new array_detail::controller() : NULL) - { - } - - shared_array(const shared_array& r) - : ptr(r.ptr) - , ctr(r.ctr ? r.ctr->incref() : NULL) - { - } - - template - shared_array(const shared_array& r,typename detail::is_convertible::result = detail::empty()) - : ptr(r.ptr) - , ctr(r.ctr ? r.ctr->incref() : NULL) - { - } - - // automatic destruction of the wrapped object when all - // references are freed. - ~shared_array() { - if (ctr) { - ctr = ctr->decref(ptr); - } - } - - shared_array& operator=(const shared_array& r) { - if (this == &r) { - return *this; - } - if (ctr) { - ctr->decref(ptr); - } - ptr = r.ptr; - ctr = ptr?r.ctr->incref():NULL; - return *this; - } - - template - shared_array& operator=(const shared_array& r) { - if (this == &r) { - return *this; - } - if (ctr) { - ctr->decref(ptr); - } - ptr = r.ptr; - ctr = ptr?r.ctr->incref():NULL; - return *this; - } - - // pointer access - inline operator T*() { - return ptr; - } - - inline T* operator-> () const { - return ptr; - } - - // standard semantics - inline T* get() { - return ptr; - } - - T& operator[] (std::ptrdiff_t index) const { - return ptr[index]; - } - - inline const T* get() const { - return ptr; - } - - inline operator bool () const { - return ptr != NULL; - } - - inline bool unique() const { - return use_count() == 1; - } - - inline long use_count() const { - return ctr->get(); - } - - inline void reset (T* t = 0) { - if (ctr) { - ctr->decref(ptr); - } - ptr = t; - ctr = ptr?new array_detail::controller():NULL; - } - - void swap(shared_array & b) { - std::swap(ptr, b.ptr); - std::swap(ctr, b.ctr); - } - - -private: - - // encapsulated object pointer - T* ptr; - - // control block - array_detail::controller* ctr; -}; - -template -inline void swap(shared_array & a, shared_array & b) -{ - a.swap(b); -} - -template -bool operator== (const shared_array& a, const shared_array& b) { - return a.ptr == b.ptr; -} -template -bool operator!= (const shared_array& a, const shared_array& b) { - return a.ptr != b.ptr; -} - -template -bool operator< (const shared_array& a, const shared_array& b) { - return a.ptr < b.ptr; -} - - -} // end of namespace boost - -#else -# error "shared_array.h was already included" -#endif -#endif // INCLUDED_AI_BOOST_SHARED_ARRAY + +#ifndef INCLUDED_AI_BOOST_SHARED_ARRAY +#define INCLUDED_AI_BOOST_SHARED_ARRAY + +#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED + +// ------------------------------ +// Internal stub +namespace boost { + namespace array_detail { + class controller { + public: + + controller() + : cnt(1) + {} + + public: + + template + controller* decref(T* pt) { + if (--cnt <= 0) { + delete this; + delete[] pt; + } + return NULL; + } + + controller* incref() { + ++cnt; + return this; + } + + long get() const { + return cnt; + } + + private: + long cnt; + }; + + struct empty {}; + + template + struct is_convertible_stub { + + struct yes {char s[1];}; + struct no {char s[2];}; + + static yes foo(DEST*); + static no foo(...); + + enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)}; + }; + + template struct enable_if {}; + template <> struct enable_if { + typedef empty result; + }; + + template + struct is_convertible : public enable_if::result > { + }; + } + +// ------------------------------ +// Small replacement for boost::shared_array, not threadsafe because no +// atomic reference counter is in use. +// ------------------------------ +template +class shared_array +{ + template friend class shared_array; + + template friend bool operator== (const shared_array& a, const shared_array& b); + template friend bool operator!= (const shared_array& a, const shared_array& b); + template friend bool operator< (const shared_array& a, const shared_array& b); + +public: + + typedef T element_type; + +public: + + // provide a default constructor + shared_array() + : ptr() + , ctr(NULL) + { + } + + // construction from an existing object of type T + explicit shared_array(T* ptr) + : ptr(ptr) + , ctr(ptr ? new array_detail::controller() : NULL) + { + } + + shared_array(const shared_array& r) + : ptr(r.ptr) + , ctr(r.ctr ? r.ctr->incref() : NULL) + { + } + + template + shared_array(const shared_array& r,typename detail::is_convertible::result = detail::empty()) + : ptr(r.ptr) + , ctr(r.ctr ? r.ctr->incref() : NULL) + { + } + + // automatic destruction of the wrapped object when all + // references are freed. + ~shared_array() { + if (ctr) { + ctr = ctr->decref(ptr); + } + } + + shared_array& operator=(const shared_array& r) { + if (this == &r) { + return *this; + } + if (ctr) { + ctr->decref(ptr); + } + ptr = r.ptr; + ctr = ptr?r.ctr->incref():NULL; + return *this; + } + + template + shared_array& operator=(const shared_array& r) { + if (this == &r) { + return *this; + } + if (ctr) { + ctr->decref(ptr); + } + ptr = r.ptr; + ctr = ptr?r.ctr->incref():NULL; + return *this; + } + + // pointer access + inline operator T*() { + return ptr; + } + + inline T* operator-> () const { + return ptr; + } + + // standard semantics + inline T* get() { + return ptr; + } + + T& operator[] (std::ptrdiff_t index) const { + return ptr[index]; + } + + inline const T* get() const { + return ptr; + } + + inline operator bool () const { + return ptr != NULL; + } + + inline bool unique() const { + return use_count() == 1; + } + + inline long use_count() const { + return ctr->get(); + } + + inline void reset (T* t = 0) { + if (ctr) { + ctr->decref(ptr); + } + ptr = t; + ctr = ptr?new array_detail::controller():NULL; + } + + void swap(shared_array & b) { + std::swap(ptr, b.ptr); + std::swap(ctr, b.ctr); + } + + +private: + + // encapsulated object pointer + T* ptr; + + // control block + array_detail::controller* ctr; +}; + +template +inline void swap(shared_array & a, shared_array & b) +{ + a.swap(b); +} + +template +bool operator== (const shared_array& a, const shared_array& b) { + return a.ptr == b.ptr; +} +template +bool operator!= (const shared_array& a, const shared_array& b) { + return a.ptr != b.ptr; +} + +template +bool operator< (const shared_array& a, const shared_array& b) { + return a.ptr < b.ptr; +} + + +} // end of namespace boost + +#else +# error "shared_array.h was already included" +#endif +#endif // INCLUDED_AI_BOOST_SHARED_ARRAY diff --git a/code/BoostWorkaround/boost/static_assert.hpp b/code/BoostWorkaround/boost/static_assert.hpp index 718157622..a533c6fa9 100644 --- a/code/BoostWorkaround/boost/static_assert.hpp +++ b/code/BoostWorkaround/boost/static_assert.hpp @@ -1,20 +1,20 @@ - -#ifndef AI_BOOST_STATIC_ASSERT_INCLUDED -#define AI_BOOST_STATIC_ASSERT_INCLUDED - -#ifndef BOOST_STATIC_ASSERT - -namespace boost { - namespace detail { - - template class static_assertion_failure; - template <> class static_assertion_failure {}; - } -} - - -#define BOOST_STATIC_ASSERT(eval) \ -{boost::detail::static_assertion_failure<(eval)> assert_dummy;(void)assert_dummy;} - -#endif -#endif // !! AI_BOOST_STATIC_ASSERT_INCLUDED + +#ifndef AI_BOOST_STATIC_ASSERT_INCLUDED +#define AI_BOOST_STATIC_ASSERT_INCLUDED + +#ifndef BOOST_STATIC_ASSERT + +namespace boost { + namespace detail { + + template class static_assertion_failure; + template <> class static_assertion_failure {}; + } +} + + +#define BOOST_STATIC_ASSERT(eval) \ +{boost::detail::static_assertion_failure<(eval)> assert_dummy;(void)assert_dummy;} + +#endif +#endif // !! AI_BOOST_STATIC_ASSERT_INCLUDED diff --git a/code/BoostWorkaround/boost/tuple/tuple.hpp b/code/BoostWorkaround/boost/tuple/tuple.hpp index ed5d11861..d196f297d 100644 --- a/code/BoostWorkaround/boost/tuple/tuple.hpp +++ b/code/BoostWorkaround/boost/tuple/tuple.hpp @@ -1,283 +1,283 @@ -// A very small replacement for boost::tuple -// (c) Alexander Gessler, 2008 [alexander.gessler@gmx.net] - -#ifndef BOOST_TUPLE_INCLUDED -#define BOOST_TUPLE_INCLUDED - -namespace boost { - namespace detail { - - // Represents an empty tuple slot (up to 5 supported) - struct nulltype {}; - - // For readable error messages - struct tuple_component_idx_out_of_bounds; - - // To share some code for the const/nonconst versions of the getters - template - struct ConstIf { - typedef T t; - }; - - template - struct ConstIf { - typedef const T t; - }; - - // Predeclare some stuff - template struct value_getter; - - // Helper to obtain the type of a tuple element - template - struct type_getter { - typedef type_getter next_elem_getter; - typedef typename next_elem_getter::type type; - }; - - template - struct type_getter { - typedef T type; - }; - - // Base class for all explicit specializations of list_elem - template - struct list_elem_base { - - // Store template parameters - typedef TNEXT next_type; - typedef T type; - - static const unsigned nidx = NIDX; - }; - - // Represents an element in the tuple component list - template - struct list_elem : list_elem_base{ - - // Real members - T me; - TNEXT next; - - // Get the value of a specific tuple element - template - typename type_getter::type& get () { - value_getter s; - return s(*this); - } - - // Get the value of a specific tuple element - template - const typename type_getter::type& get () const { - value_getter s; - return s(*this); - } - - // Explicit cast - template - operator list_elem () const { - list_elem ret; - ret.me = (T2)me; - ret.next = next; - return ret; - } - - // Recursively compare two elements (last element returns always true) - bool operator == (const list_elem& s) const { - return (me == s.me && next == s.next); - } - }; - - // Represents a non-used tuple element - the very last element processed - template - struct list_elem : list_elem_base { - template struct value_getter { - /* just dummy members to produce readable error messages */ - tuple_component_idx_out_of_bounds operator () (typename ConstIf::t& me); - }; - template struct type_getter { - /* just dummy members to produce readable error messages */ - typedef tuple_component_idx_out_of_bounds type; - }; - - // dummy - list_elem& operator = (const list_elem& /*other*/) { - return *this; - } - - // dummy - bool operator == (const list_elem& other) { - return true; - } - }; - - // Represents the absolute end of the list - typedef list_elem list_end; - - // Helper obtain to query the value of a tuple element - // NOTE: This can't be a nested class as the compiler won't accept a full or - // partial specialization of a nested class of a non-specialized template - template - struct value_getter { - - // calling list_elem - typedef list_elem outer_elem; - - // typedef for the getter for next element - typedef value_getter next_value_getter; - - typename ConstIf::type>::t& - operator () (typename ConstIf::t& me) { - - next_value_getter s; - return s(me.next); - } - }; - - template - struct value_getter { - typedef list_elem outer_elem; - - typename ConstIf::t& operator () (typename ConstIf::t& me) { - return me.me; - } - }; - } - - // A very minimal implementation for up to 5 elements - template - class tuple { - - template - friend class tuple; - - private: - - typedef detail::list_elem > > > > very_long; - - very_long m; - - public: - - // Get a specific tuple element - template - typename detail::type_getter::type& get () { - return m.template get(); - } - - // ... and the const version - template - const typename detail::type_getter::type& get () const { - return m.template get(); - } - - - // comparison operators - bool operator== (const tuple& other) const { - return m == other.m; - } - - // ... and the other way round - bool operator!= (const tuple& other) const { - return !(m == other.m); - } - - // cast to another tuple - all single elements must be convertible - template - operator tuple () const { - tuple s; - s.m = (typename tuple ::very_long)m; - return s; - } - }; - - // Another way to access an element ... - template - inline typename tuple::very_long::template type_getter::type& get ( - tuple& m) { - return m.template get(); - } - - // ... and the const version - template - inline const typename tuple::very_long::template type_getter::type& get ( - const tuple& m) { - return m.template get(); - } - - // Constructs a tuple with 5 elements - template - inline tuple make_tuple (const T0& t0, - const T1& t1,const T2& t2,const T3& t3,const T4& t4) { - - tuple t; - t.template get<0>() = t0; - t.template get<1>() = t1; - t.template get<2>() = t2; - t.template get<3>() = t3; - t.template get<4>() = t4; - return t; - } - - // Constructs a tuple with 4 elements - template - inline tuple make_tuple (const T0& t0, - const T1& t1,const T2& t2,const T3& t3) { - tuple t; - t.template get<0>() = t0; - t.template get<1>() = t1; - t.template get<2>() = t2; - t.template get<3>() = t3; - return t; - } - - // Constructs a tuple with 3 elements - template - inline tuple make_tuple (const T0& t0, - const T1& t1,const T2& t2) { - tuple t; - t.template get<0>() = t0; - t.template get<1>() = t1; - t.template get<2>() = t2; - return t; - } - - // Constructs a tuple with 2 elements - template - inline tuple make_tuple (const T0& t0, - const T1& t1) { - tuple t; - t.template get<0>() = t0; - t.template get<1>() = t1; - return t; - } - - // Constructs a tuple with 1 elements (well ...) - template - inline tuple make_tuple (const T0& t0) { - tuple t; - t.template get<0>() = t0; - return t; - } - - // Constructs a tuple with 0 elements (well ...) - inline tuple <> make_tuple () { - tuple <> t; - return t; - } -} - -#endif // !! BOOST_TUPLE_INCLUDED +// A very small replacement for boost::tuple +// (c) Alexander Gessler, 2008 [alexander.gessler@gmx.net] + +#ifndef BOOST_TUPLE_INCLUDED +#define BOOST_TUPLE_INCLUDED + +namespace boost { + namespace detail { + + // Represents an empty tuple slot (up to 5 supported) + struct nulltype {}; + + // For readable error messages + struct tuple_component_idx_out_of_bounds; + + // To share some code for the const/nonconst versions of the getters + template + struct ConstIf { + typedef T t; + }; + + template + struct ConstIf { + typedef const T t; + }; + + // Predeclare some stuff + template struct value_getter; + + // Helper to obtain the type of a tuple element + template + struct type_getter { + typedef type_getter next_elem_getter; + typedef typename next_elem_getter::type type; + }; + + template + struct type_getter { + typedef T type; + }; + + // Base class for all explicit specializations of list_elem + template + struct list_elem_base { + + // Store template parameters + typedef TNEXT next_type; + typedef T type; + + static const unsigned nidx = NIDX; + }; + + // Represents an element in the tuple component list + template + struct list_elem : list_elem_base{ + + // Real members + T me; + TNEXT next; + + // Get the value of a specific tuple element + template + typename type_getter::type& get () { + value_getter s; + return s(*this); + } + + // Get the value of a specific tuple element + template + const typename type_getter::type& get () const { + value_getter s; + return s(*this); + } + + // Explicit cast + template + operator list_elem () const { + list_elem ret; + ret.me = (T2)me; + ret.next = next; + return ret; + } + + // Recursively compare two elements (last element returns always true) + bool operator == (const list_elem& s) const { + return (me == s.me && next == s.next); + } + }; + + // Represents a non-used tuple element - the very last element processed + template + struct list_elem : list_elem_base { + template struct value_getter { + /* just dummy members to produce readable error messages */ + tuple_component_idx_out_of_bounds operator () (typename ConstIf::t& me); + }; + template struct type_getter { + /* just dummy members to produce readable error messages */ + typedef tuple_component_idx_out_of_bounds type; + }; + + // dummy + list_elem& operator = (const list_elem& /*other*/) { + return *this; + } + + // dummy + bool operator == (const list_elem& other) { + return true; + } + }; + + // Represents the absolute end of the list + typedef list_elem list_end; + + // Helper obtain to query the value of a tuple element + // NOTE: This can't be a nested class as the compiler won't accept a full or + // partial specialization of a nested class of a non-specialized template + template + struct value_getter { + + // calling list_elem + typedef list_elem outer_elem; + + // typedef for the getter for next element + typedef value_getter next_value_getter; + + typename ConstIf::type>::t& + operator () (typename ConstIf::t& me) { + + next_value_getter s; + return s(me.next); + } + }; + + template + struct value_getter { + typedef list_elem outer_elem; + + typename ConstIf::t& operator () (typename ConstIf::t& me) { + return me.me; + } + }; + } + + // A very minimal implementation for up to 5 elements + template + class tuple { + + template + friend class tuple; + + private: + + typedef detail::list_elem > > > > very_long; + + very_long m; + + public: + + // Get a specific tuple element + template + typename detail::type_getter::type& get () { + return m.template get(); + } + + // ... and the const version + template + const typename detail::type_getter::type& get () const { + return m.template get(); + } + + + // comparison operators + bool operator== (const tuple& other) const { + return m == other.m; + } + + // ... and the other way round + bool operator!= (const tuple& other) const { + return !(m == other.m); + } + + // cast to another tuple - all single elements must be convertible + template + operator tuple () const { + tuple s; + s.m = (typename tuple ::very_long)m; + return s; + } + }; + + // Another way to access an element ... + template + inline typename tuple::very_long::template type_getter::type& get ( + tuple& m) { + return m.template get(); + } + + // ... and the const version + template + inline const typename tuple::very_long::template type_getter::type& get ( + const tuple& m) { + return m.template get(); + } + + // Constructs a tuple with 5 elements + template + inline tuple make_tuple (const T0& t0, + const T1& t1,const T2& t2,const T3& t3,const T4& t4) { + + tuple t; + t.template get<0>() = t0; + t.template get<1>() = t1; + t.template get<2>() = t2; + t.template get<3>() = t3; + t.template get<4>() = t4; + return t; + } + + // Constructs a tuple with 4 elements + template + inline tuple make_tuple (const T0& t0, + const T1& t1,const T2& t2,const T3& t3) { + tuple t; + t.template get<0>() = t0; + t.template get<1>() = t1; + t.template get<2>() = t2; + t.template get<3>() = t3; + return t; + } + + // Constructs a tuple with 3 elements + template + inline tuple make_tuple (const T0& t0, + const T1& t1,const T2& t2) { + tuple t; + t.template get<0>() = t0; + t.template get<1>() = t1; + t.template get<2>() = t2; + return t; + } + + // Constructs a tuple with 2 elements + template + inline tuple make_tuple (const T0& t0, + const T1& t1) { + tuple t; + t.template get<0>() = t0; + t.template get<1>() = t1; + return t; + } + + // Constructs a tuple with 1 elements (well ...) + template + inline tuple make_tuple (const T0& t0) { + tuple t; + t.template get<0>() = t0; + return t; + } + + // Constructs a tuple with 0 elements (well ...) + inline tuple <> make_tuple () { + tuple <> t; + return t; + } +} + +#endif // !! BOOST_TUPLE_INCLUDED diff --git a/code/res/resource.h b/code/res/resource.h index 41ce1c5ee..37d39284f 100644 --- a/code/res/resource.h +++ b/code/res/resource.h @@ -1,14 +1,14 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by assimp.rc - -// Nächste Standardwerte für neue Objekte -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by assimp.rc + +// Nächste Standardwerte für neue Objekte +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/contrib/clipper/License.txt b/contrib/clipper/License.txt index 51acabf74..8e2278cef 100644 --- a/contrib/clipper/License.txt +++ b/contrib/clipper/License.txt @@ -1,29 +1,29 @@ -The Clipper code library, the "Software" (that includes Delphi, C++ & C# -source code, accompanying samples and documentation), has been released -under the following license, terms and conditions: - -Boost Software License - Version 1.0 - August 17th, 2003 -http://www.boost.org/LICENSE_1_0.txt - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - +The Clipper code library, the "Software" (that includes Delphi, C++ & C# +source code, accompanying samples and documentation), has been released +under the following license, terms and conditions: + +Boost Software License - Version 1.0 - August 17th, 2003 +http://www.boost.org/LICENSE_1_0.txt + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + diff --git a/contrib/clipper/clipper.cpp b/contrib/clipper/clipper.cpp index 1efa01df8..b2316ccd5 100644 --- a/contrib/clipper/clipper.cpp +++ b/contrib/clipper/clipper.cpp @@ -1,3448 +1,3448 @@ -/******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 4.8.8 * -* Date : 30 August 2012 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2012 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -* Attributions: * -* The code in this library is an extension of Bala Vatti's clipping algorithm: * -* "A generic solution to polygon clipping" * -* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * -* http://portal.acm.org/citation.cfm?id=129906 * -* * -* Computer graphics and geometric modeling: implementation and algorithms * -* By Max K. Agoston * -* Springer; 1 edition (January 4, 2005) * -* http://books.google.com/books?q=vatti+clipping+agoston * -* * -* See also: * -* "Polygon Offsetting by Computing Winding Numbers" * -* Paper no. DETC2005-85513 pp. 565-575 * -* ASME 2005 International Design Engineering Technical Conferences * -* and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24–28, 2005 , Long Beach, California, USA * -* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * -* * -*******************************************************************************/ - -/******************************************************************************* -* * -* This is a translation of the Delphi Clipper library and the naming style * -* used has retained a Delphi flavour. * -* * -*******************************************************************************/ - -#include "clipper.hpp" -#include -#include -#include -#include -#include -#include -#include - -namespace ClipperLib { - -static long64 const loRange = 0x3FFFFFFF; -static long64 const hiRange = 0x3FFFFFFFFFFFFFFFLL; -static double const pi = 3.141592653589793238; -enum Direction { dRightToLeft, dLeftToRight }; - -#define HORIZONTAL (-1.0E+40) -#define TOLERANCE (1.0e-20) -#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) -#define NEAR_EQUAL(a, b) NEAR_ZERO((a) - (b)) - -inline long64 Abs(long64 val) -{ - return val < 0 ? -val : val; -} -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -// Int128 class (enables safe math on signed 64bit integers) -// eg Int128 val1((long64)9223372036854775807); //ie 2^63 -1 -// Int128 val2((long64)9223372036854775807); -// Int128 val3 = val1 * val2; -// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37) -//------------------------------------------------------------------------------ - -class Int128 -{ - public: - - Int128(long64 _lo = 0) - { - lo = _lo; - if (lo < 0) hi = -1; else hi = 0; - } - - Int128(const Int128 &val): hi(val.hi), lo(val.lo){} - - long64 operator = (const long64 &val) - { - lo = val; - if (lo < 0) hi = -1; else hi = 0; - return val; - } - - bool operator == (const Int128 &val) const - {return (hi == val.hi && lo == val.lo);} - - bool operator != (const Int128 &val) const - { return !(*this == val);} - - bool operator > (const Int128 &val) const - { - if (hi != val.hi) - return hi > val.hi; - else - return lo > val.lo; - } - - bool operator < (const Int128 &val) const - { - if (hi != val.hi) - return hi < val.hi; - else - return lo < val.lo; - } - - bool operator >= (const Int128 &val) const - { return !(*this < val);} - - bool operator <= (const Int128 &val) const - { return !(*this > val);} - - Int128& operator += (const Int128 &rhs) - { - hi += rhs.hi; - lo += rhs.lo; - if (ulong64(lo) < ulong64(rhs.lo)) hi++; - return *this; - } - - Int128 operator + (const Int128 &rhs) const - { - Int128 result(*this); - result+= rhs; - return result; - } - - Int128& operator -= (const Int128 &rhs) - { - Int128 tmp(rhs); - Negate(tmp); - *this += tmp; - return *this; - } - - //Int128 operator -() const - //{ - // Int128 result(*this); - // if (result.lo == 0) { - // if (result.hi != 0) result.hi = -1; - // } - // else { - // result.lo = -result.lo; - // result.hi = ~result.hi; - // } - // return result; - //} - - Int128 operator - (const Int128 &rhs) const - { - Int128 result(*this); - result -= rhs; - return result; - } - - Int128 operator * (const Int128 &rhs) const - { - if ( !(hi == 0 || hi == -1) || !(rhs.hi == 0 || rhs.hi == -1)) - throw "Int128 operator*: overflow error"; - bool negate = (hi < 0) != (rhs.hi < 0); - - Int128 tmp(*this); - if (tmp.hi < 0) Negate(tmp); - ulong64 int1Hi = ulong64(tmp.lo) >> 32; - ulong64 int1Lo = ulong64(tmp.lo & 0xFFFFFFFF); - - tmp = rhs; - if (tmp.hi < 0) Negate(tmp); - ulong64 int2Hi = ulong64(tmp.lo) >> 32; - ulong64 int2Lo = ulong64(tmp.lo & 0xFFFFFFFF); - - //nb: see comments in clipper.pas - ulong64 a = int1Hi * int2Hi; - ulong64 b = int1Lo * int2Lo; - ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; - - tmp.hi = long64(a + (c >> 32)); - tmp.lo = long64(c << 32); - tmp.lo += long64(b); - if (ulong64(tmp.lo) < b) tmp.hi++; - if (negate) Negate(tmp); - return tmp; - } - - Int128 operator/ (const Int128 &rhs) const - { - if (rhs.lo == 0 && rhs.hi == 0) - throw "Int128 operator/: divide by zero"; - bool negate = (rhs.hi < 0) != (hi < 0); - Int128 result(*this), denom(rhs); - if (result.hi < 0) Negate(result); - if (denom.hi < 0) Negate(denom); - if (denom > result) return Int128(0); //result is only a fraction of 1 - Negate(denom); - - Int128 p(0); - for (int i = 0; i < 128; ++i) - { - p.hi = p.hi << 1; - if (p.lo < 0) p.hi++; - p.lo = long64(p.lo) << 1; - if (result.hi < 0) p.lo++; - result.hi = result.hi << 1; - if (result.lo < 0) result.hi++; - result.lo = long64(result.lo) << 1; - Int128 p2(p); - p += denom; - if (p.hi < 0) p = p2; - else result.lo++; - } - if (negate) Negate(result); - return result; - } - - double AsDouble() const - { - const double shift64 = 18446744073709551616.0; //2^64 - const double bit64 = 9223372036854775808.0; - if (hi < 0) - { - Int128 tmp(*this); - Negate(tmp); - if (tmp.lo < 0) - return (double)tmp.lo - bit64 - tmp.hi * shift64; - else - return -(double)tmp.lo - tmp.hi * shift64; - } - else if (lo < 0) - return -(double)lo + bit64 + hi * shift64; - else - return (double)lo + (double)hi * shift64; - } - - //for bug testing ... - //std::string AsString() const - //{ - // std::string result; - // unsigned char r = 0; - // Int128 tmp(0), val(*this); - // if (hi < 0) Negate(val); - // result.resize(50); - // std::string::size_type i = result.size() -1; - // while (val.hi != 0 || val.lo != 0) - // { - // Div10(val, tmp, r); - // result[i--] = char('0' + r); - // val = tmp; - // } - // if (hi < 0) result[i--] = '-'; - // result.erase(0,i+1); - // if (result.size() == 0) result = "0"; - // return result; - //} - -private: - long64 hi; - long64 lo; - - static void Negate(Int128 &val) - { - if (val.lo == 0) { - if (val.hi != 0) val.hi = -val.hi;; - } - else { - val.lo = -val.lo; - val.hi = ~val.hi; - } - } - - //debugging only ... - //void Div10(const Int128 val, Int128& result, unsigned char & remainder) const - //{ - // remainder = 0; - // result = 0; - // for (int i = 63; i >= 0; --i) - // { - // if ((val.hi & ((long64)1 << i)) != 0) - // remainder = char((remainder * 2) + 1); else - // remainder *= char(2); - // if (remainder >= 10) - // { - // result.hi += ((long64)1 << i); - // remainder -= char(10); - // } - // } - // for (int i = 63; i >= 0; --i) - // { - // if ((val.lo & ((long64)1 << i)) != 0) - // remainder = char((remainder * 2) + 1); else - // remainder *= char(2); - // if (remainder >= 10) - // { - // result.lo += ((long64)1 << i); - // remainder -= char(10); - // } - // } - //} -}; - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -bool FullRangeNeeded(const Polygon &pts) -{ - bool result = false; - for (Polygon::size_type i = 0; i < pts.size(); ++i) - { - if (Abs(pts[i].X) > hiRange || Abs(pts[i].Y) > hiRange) - throw "Coordinate exceeds range bounds."; - else if (Abs(pts[i].X) > loRange || Abs(pts[i].Y) > loRange) - result = true; - } - return result; -} -//------------------------------------------------------------------------------ - -bool Orientation(const Polygon &poly) -{ - int highI = (int)poly.size() -1; - if (highI < 2) return false; - - int j = 0, jplus, jminus; - for (int i = 0; i <= highI; ++i) - { - if (poly[i].Y < poly[j].Y) continue; - if ((poly[i].Y > poly[j].Y || poly[i].X < poly[j].X)) j = i; - }; - if (j == highI) jplus = 0; - else jplus = j +1; - if (j == 0) jminus = highI; - else jminus = j -1; - - IntPoint vec1, vec2; - //get cross product of vectors of the edges adjacent to highest point ... - vec1.X = poly[j].X - poly[jminus].X; - vec1.Y = poly[j].Y - poly[jminus].Y; - vec2.X = poly[jplus].X - poly[j].X; - vec2.Y = poly[jplus].Y - poly[j].Y; - - if (Abs(vec1.X) > loRange || Abs(vec1.Y) > loRange || - Abs(vec2.X) > loRange || Abs(vec2.Y) > loRange) - { - if (Abs(vec1.X) > hiRange || Abs(vec1.Y) > hiRange || - Abs(vec2.X) > hiRange || Abs(vec2.Y) > hiRange) - throw "Coordinate exceeds range bounds."; - Int128 cross = Int128(vec1.X) * Int128(vec2.Y) - - Int128(vec2.X) * Int128(vec1.Y); - return cross >= 0; - } - else - return (vec1.X * vec2.Y - vec2.X * vec1.Y) >= 0; -} -//------------------------------------------------------------------------------ - -inline bool PointsEqual( const IntPoint &pt1, const IntPoint &pt2) -{ - return ( pt1.X == pt2.X && pt1.Y == pt2.Y ); -} -//------------------------------------------------------------------------------ - -bool Orientation(OutRec *outRec, bool UseFullInt64Range) -{ - //first make sure bottomPt is correctly assigned ... - OutPt *opBottom = outRec->pts, *op = outRec->pts->next; - while (op != outRec->pts) - { - if (op->pt.Y >= opBottom->pt.Y) - { - if (op->pt.Y > opBottom->pt.Y || op->pt.X < opBottom->pt.X) - opBottom = op; - } - op = op->next; - } - outRec->bottomPt = opBottom; - opBottom->idx = outRec->idx; - - op = opBottom; - //find vertices either side of bottomPt (skipping duplicate points) .... - OutPt *opPrev = op->prev; - OutPt *opNext = op->next; - while (op != opPrev && PointsEqual(op->pt, opPrev->pt)) - opPrev = opPrev->prev; - while (op != opNext && PointsEqual(op->pt, opNext->pt)) - opNext = opNext->next; - - IntPoint ip1, ip2; - ip1.X = op->pt.X - opPrev->pt.X; - ip1.Y = op->pt.Y - opPrev->pt.Y; - ip2.X = opNext->pt.X - op->pt.X; - ip2.Y = opNext->pt.Y - op->pt.Y; - - if (UseFullInt64Range) - return Int128(ip1.X) * Int128(ip2.Y) - Int128(ip2.X) * Int128(ip1.Y) >= 0; - else - return (ip1.X * ip2.Y - ip2.X * ip1.Y) >= 0; -} -//------------------------------------------------------------------------------ - -double Area(const Polygon &poly) -{ - int highI = (int)poly.size() -1; - if (highI < 2) return 0; - - if (FullRangeNeeded(poly)) { - Int128 a; - a = (Int128(poly[highI].X) * Int128(poly[0].Y)) - - Int128(poly[0].X) * Int128(poly[highI].Y); - for (int i = 0; i < highI; ++i) - a += Int128(poly[i].X) * Int128(poly[i+1].Y) - - Int128(poly[i+1].X) * Int128(poly[i].Y); - return a.AsDouble() / 2; - } - else - { - double a; - a = (double)poly[highI].X * poly[0].Y - (double)poly[0].X * poly[highI].Y; - for (int i = 0; i < highI; ++i) - a += (double)poly[i].X * poly[i+1].Y - (double)poly[i+1].X * poly[i].Y; - return a/2; - } -} -//------------------------------------------------------------------------------ - -double Area(const OutRec &outRec, bool UseFullInt64Range) -{ - OutPt *op = outRec.pts; - if (UseFullInt64Range) { - Int128 a(0); - do { - a += (Int128(op->prev->pt.X) * Int128(op->pt.Y)) - - Int128(op->pt.X) * Int128(op->prev->pt.Y); - op = op->next; - } while (op != outRec.pts); - return a.AsDouble() / 2; - } - else - { - double a = 0; - do { - a += (op->prev->pt.X * op->pt.Y) - (op->pt.X * op->prev->pt.Y); - op = op->next; - } while (op != outRec.pts); - return a/2; - } -} -//------------------------------------------------------------------------------ - -bool PointIsVertex(const IntPoint &pt, OutPt *pp) -{ - OutPt *pp2 = pp; - do - { - if (PointsEqual(pp2->pt, pt)) return true; - pp2 = pp2->next; - } - while (pp2 != pp); - return false; -} -//------------------------------------------------------------------------------ - -bool PointInPolygon(const IntPoint &pt, OutPt *pp, bool UseFullInt64Range) -{ - OutPt *pp2 = pp; - bool result = false; - if (UseFullInt64Range) { - do - { - if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || - ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && - Int128(pt.X - pp2->pt.X) < (Int128(pp2->prev->pt.X - pp2->pt.X) * - Int128(pt.Y - pp2->pt.Y)) / Int128(pp2->prev->pt.Y - pp2->pt.Y)) - result = !result; - pp2 = pp2->next; - } - while (pp2 != pp); - } - else - { - do - { - if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || - ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && - (pt.X < (pp2->prev->pt.X - pp2->pt.X) * (pt.Y - pp2->pt.Y) / - (pp2->prev->pt.Y - pp2->pt.Y) + pp2->pt.X )) result = !result; - pp2 = pp2->next; - } - while (pp2 != pp); - } - return result; -} -//------------------------------------------------------------------------------ - -bool SlopesEqual(TEdge &e1, TEdge &e2, bool UseFullInt64Range) -{ - if (UseFullInt64Range) - return Int128(e1.ytop - e1.ybot) * Int128(e2.xtop - e2.xbot) == - Int128(e1.xtop - e1.xbot) * Int128(e2.ytop - e2.ybot); - else return (e1.ytop - e1.ybot)*(e2.xtop - e2.xbot) == - (e1.xtop - e1.xbot)*(e2.ytop - e2.ybot); -} -//------------------------------------------------------------------------------ - -bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, - const IntPoint pt3, bool UseFullInt64Range) -{ - if (UseFullInt64Range) - return Int128(pt1.Y-pt2.Y) * Int128(pt2.X-pt3.X) == - Int128(pt1.X-pt2.X) * Int128(pt2.Y-pt3.Y); - else return (pt1.Y-pt2.Y)*(pt2.X-pt3.X) == (pt1.X-pt2.X)*(pt2.Y-pt3.Y); -} -//------------------------------------------------------------------------------ - -bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, - const IntPoint pt3, const IntPoint pt4, bool UseFullInt64Range) -{ - if (UseFullInt64Range) - return Int128(pt1.Y-pt2.Y) * Int128(pt3.X-pt4.X) == - Int128(pt1.X-pt2.X) * Int128(pt3.Y-pt4.Y); - else return (pt1.Y-pt2.Y)*(pt3.X-pt4.X) == (pt1.X-pt2.X)*(pt3.Y-pt4.Y); -} -//------------------------------------------------------------------------------ - -double GetDx(const IntPoint pt1, const IntPoint pt2) -{ - return (pt1.Y == pt2.Y) ? - HORIZONTAL : (double)(pt2.X - pt1.X) / (double)(pt2.Y - pt1.Y); -} -//--------------------------------------------------------------------------- - -void SetDx(TEdge &e) -{ - if (e.ybot == e.ytop) e.dx = HORIZONTAL; - else e.dx = (double)(e.xtop - e.xbot) / (double)(e.ytop - e.ybot); -} -//--------------------------------------------------------------------------- - -void SwapSides(TEdge &edge1, TEdge &edge2) -{ - EdgeSide side = edge1.side; - edge1.side = edge2.side; - edge2.side = side; -} -//------------------------------------------------------------------------------ - -void SwapPolyIndexes(TEdge &edge1, TEdge &edge2) -{ - int outIdx = edge1.outIdx; - edge1.outIdx = edge2.outIdx; - edge2.outIdx = outIdx; -} -//------------------------------------------------------------------------------ - -inline long64 Round(double val) -{ - return (val < 0) ? - static_cast(val - 0.5) : static_cast(val + 0.5); -} -//------------------------------------------------------------------------------ - -long64 TopX(TEdge &edge, const long64 currentY) -{ - return ( currentY == edge.ytop ) ? - edge.xtop : edge.xbot + Round(edge.dx *(currentY - edge.ybot)); -} -//------------------------------------------------------------------------------ - -long64 TopX(const IntPoint pt1, const IntPoint pt2, const long64 currentY) -{ - //preconditions: pt1.Y <> pt2.Y and pt1.Y > pt2.Y - if (currentY >= pt1.Y) return pt1.X; - else if (currentY == pt2.Y) return pt2.X; - else if (pt1.X == pt2.X) return pt1.X; - else - { - double q = (double)(pt1.X-pt2.X)/(double)(pt1.Y-pt2.Y); - return Round(pt1.X + (currentY - pt1.Y) *q); - } -} -//------------------------------------------------------------------------------ - -bool IntersectPoint(TEdge &edge1, TEdge &edge2, - IntPoint &ip, bool UseFullInt64Range) -{ - double b1, b2; - if (SlopesEqual(edge1, edge2, UseFullInt64Range)) return false; - else if (NEAR_ZERO(edge1.dx)) - { - ip.X = edge1.xbot; - if (NEAR_EQUAL(edge2.dx, HORIZONTAL)) - { - ip.Y = edge2.ybot; - } else - { - b2 = edge2.ybot - (edge2.xbot/edge2.dx); - ip.Y = Round(ip.X/edge2.dx + b2); - } - } - else if (NEAR_ZERO(edge2.dx)) - { - ip.X = edge2.xbot; - if (NEAR_EQUAL(edge1.dx, HORIZONTAL)) - { - ip.Y = edge1.ybot; - } else - { - b1 = edge1.ybot - (edge1.xbot/edge1.dx); - ip.Y = Round(ip.X/edge1.dx + b1); - } - } else - { - b1 = edge1.xbot - edge1.ybot * edge1.dx; - b2 = edge2.xbot - edge2.ybot * edge2.dx; - b2 = (b2-b1)/(edge1.dx - edge2.dx); - ip.Y = Round(b2); - ip.X = Round(edge1.dx * b2 + b1); - } - - return - //can be *so close* to the top of one edge that the rounded Y equals one ytop ... - (ip.Y == edge1.ytop && ip.Y >= edge2.ytop && edge1.tmpX > edge2.tmpX) || - (ip.Y == edge2.ytop && ip.Y >= edge1.ytop && edge1.tmpX > edge2.tmpX) || - (ip.Y > edge1.ytop && ip.Y > edge2.ytop); -} -//------------------------------------------------------------------------------ - -void ReversePolyPtLinks(OutPt &pp) -{ - OutPt *pp1, *pp2; - pp1 = &pp; - do { - pp2 = pp1->next; - pp1->next = pp1->prev; - pp1->prev = pp2; - pp1 = pp2; - } while( pp1 != &pp ); -} -//------------------------------------------------------------------------------ - -void DisposeOutPts(OutPt*& pp) -{ - if (pp == 0) return; - pp->prev->next = 0; - while( pp ) - { - OutPt *tmpPp = pp; - pp = pp->next; - delete tmpPp ; - } -} -//------------------------------------------------------------------------------ - -void InitEdge(TEdge *e, TEdge *eNext, - TEdge *ePrev, const IntPoint &pt, PolyType polyType) -{ - std::memset( e, 0, sizeof( TEdge )); - - e->next = eNext; - e->prev = ePrev; - e->xcurr = pt.X; - e->ycurr = pt.Y; - if (e->ycurr >= e->next->ycurr) - { - e->xbot = e->xcurr; - e->ybot = e->ycurr; - e->xtop = e->next->xcurr; - e->ytop = e->next->ycurr; - e->windDelta = 1; - } else - { - e->xtop = e->xcurr; - e->ytop = e->ycurr; - e->xbot = e->next->xcurr; - e->ybot = e->next->ycurr; - e->windDelta = -1; - } - SetDx(*e); - e->polyType = polyType; - e->outIdx = -1; -} -//------------------------------------------------------------------------------ - -inline void SwapX(TEdge &e) -{ - //swap horizontal edges' top and bottom x's so they follow the natural - //progression of the bounds - ie so their xbots will align with the - //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] - e.xcurr = e.xtop; - e.xtop = e.xbot; - e.xbot = e.xcurr; -} -//------------------------------------------------------------------------------ - -void SwapPoints(IntPoint &pt1, IntPoint &pt2) -{ - IntPoint tmp = pt1; - pt1 = pt2; - pt2 = tmp; -} -//------------------------------------------------------------------------------ - -bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, - IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) -{ - //precondition: segments are colinear. - if ( pt1a.Y == pt1b.Y || Abs((pt1a.X - pt1b.X)/(pt1a.Y - pt1b.Y)) > 1 ) - { - if (pt1a.X > pt1b.X) SwapPoints(pt1a, pt1b); - if (pt2a.X > pt2b.X) SwapPoints(pt2a, pt2b); - if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; - if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; - return pt1.X < pt2.X; - } else - { - if (pt1a.Y < pt1b.Y) SwapPoints(pt1a, pt1b); - if (pt2a.Y < pt2b.Y) SwapPoints(pt2a, pt2b); - if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; - if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; - return pt1.Y > pt2.Y; - } -} -//------------------------------------------------------------------------------ - -bool FirstIsBottomPt(const OutPt* btmPt1, const OutPt* btmPt2) -{ - OutPt *p = btmPt1->prev; - while (PointsEqual(p->pt, btmPt1->pt) && (p != btmPt1)) p = p->prev; - double dx1p = std::fabs(GetDx(btmPt1->pt, p->pt)); - p = btmPt1->next; - while (PointsEqual(p->pt, btmPt1->pt) && (p != btmPt1)) p = p->next; - double dx1n = std::fabs(GetDx(btmPt1->pt, p->pt)); - - p = btmPt2->prev; - while (PointsEqual(p->pt, btmPt2->pt) && (p != btmPt2)) p = p->prev; - double dx2p = std::fabs(GetDx(btmPt2->pt, p->pt)); - p = btmPt2->next; - while (PointsEqual(p->pt, btmPt2->pt) && (p != btmPt2)) p = p->next; - double dx2n = std::fabs(GetDx(btmPt2->pt, p->pt)); - return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); -} -//------------------------------------------------------------------------------ - -OutPt* GetBottomPt(OutPt *pp) -{ - OutPt* dups = 0; - OutPt* p = pp->next; - while (p != pp) - { - if (p->pt.Y > pp->pt.Y) - { - pp = p; - dups = 0; - } - else if (p->pt.Y == pp->pt.Y && p->pt.X <= pp->pt.X) - { - if (p->pt.X < pp->pt.X) - { - dups = 0; - pp = p; - } else - { - if (p->next != pp && p->prev != pp) dups = p; - } - } - p = p->next; - } - if (dups) - { - //there appears to be at least 2 vertices at bottomPt so ... - while (dups != p) - { - if (!FirstIsBottomPt(p, dups)) pp = dups; - dups = dups->next; - while (!PointsEqual(dups->pt, pp->pt)) dups = dups->next; - } - } - return pp; -} -//------------------------------------------------------------------------------ - -bool FindSegment(OutPt* &pp, IntPoint &pt1, IntPoint &pt2) -{ - //outPt1 & outPt2 => the overlap segment (if the function returns true) - if (!pp) return false; - OutPt* pp2 = pp; - IntPoint pt1a = pt1, pt2a = pt2; - do - { - if (SlopesEqual(pt1a, pt2a, pp->pt, pp->prev->pt, true) && - SlopesEqual(pt1a, pt2a, pp->pt, true) && - GetOverlapSegment(pt1a, pt2a, pp->pt, pp->prev->pt, pt1, pt2)) - return true; - pp = pp->next; - } - while (pp != pp2); - return false; -} -//------------------------------------------------------------------------------ - -bool Pt3IsBetweenPt1AndPt2(const IntPoint pt1, - const IntPoint pt2, const IntPoint pt3) -{ - if (PointsEqual(pt1, pt3) || PointsEqual(pt2, pt3)) return true; - else if (pt1.X != pt2.X) return (pt1.X < pt3.X) == (pt3.X < pt2.X); - else return (pt1.Y < pt3.Y) == (pt3.Y < pt2.Y); -} -//------------------------------------------------------------------------------ - -OutPt* InsertPolyPtBetween(OutPt* p1, OutPt* p2, const IntPoint pt) -{ - if (p1 == p2) throw "JoinError"; - OutPt* result = new OutPt; - result->pt = pt; - if (p2 == p1->next) - { - p1->next = result; - p2->prev = result; - result->next = p2; - result->prev = p1; - } else - { - p2->next = result; - p1->prev = result; - result->next = p1; - result->prev = p2; - } - return result; -} - -//------------------------------------------------------------------------------ -// ClipperBase class methods ... -//------------------------------------------------------------------------------ - -ClipperBase::ClipperBase() //constructor -{ - m_MinimaList = 0; - m_CurrentLM = 0; - m_UseFullRange = true; -} -//------------------------------------------------------------------------------ - -ClipperBase::~ClipperBase() //destructor -{ - Clear(); -} -//------------------------------------------------------------------------------ - -bool ClipperBase::AddPolygon( const Polygon &pg, PolyType polyType) -{ - int len = (int)pg.size(); - if (len < 3) return false; - Polygon p(len); - p[0] = pg[0]; - int j = 0; - - long64 maxVal; - if (m_UseFullRange) maxVal = hiRange; else maxVal = loRange; - - for (int i = 0; i < len; ++i) - { - if (Abs(pg[i].X) > maxVal || Abs(pg[i].Y) > maxVal) - { - if (Abs(pg[i].X) > hiRange || Abs(pg[i].Y) > hiRange) - throw "Coordinate exceeds range bounds"; - maxVal = hiRange; - m_UseFullRange = true; - } - - if (i == 0 || PointsEqual(p[j], pg[i])) continue; - else if (j > 0 && SlopesEqual(p[j-1], p[j], pg[i], m_UseFullRange)) - { - if (PointsEqual(p[j-1], pg[i])) j--; - } else j++; - p[j] = pg[i]; - } - if (j < 2) return false; - - len = j+1; - while (len > 2) - { - //nb: test for point equality before testing slopes ... - if (PointsEqual(p[j], p[0])) j--; - else if (PointsEqual(p[0], p[1]) || - SlopesEqual(p[j], p[0], p[1], m_UseFullRange)) - p[0] = p[j--]; - else if (SlopesEqual(p[j-1], p[j], p[0], m_UseFullRange)) j--; - else if (SlopesEqual(p[0], p[1], p[2], m_UseFullRange)) - { - for (int i = 2; i <= j; ++i) p[i-1] = p[i]; - j--; - } - else break; - len--; - } - if (len < 3) return false; - - //create a new edge array ... - TEdge *edges = new TEdge [len]; - m_edges.push_back(edges); - - //convert vertices to a double-linked-list of edges and initialize ... - edges[0].xcurr = p[0].X; - edges[0].ycurr = p[0].Y; - InitEdge(&edges[len-1], &edges[0], &edges[len-2], p[len-1], polyType); - for (int i = len-2; i > 0; --i) - InitEdge(&edges[i], &edges[i+1], &edges[i-1], p[i], polyType); - InitEdge(&edges[0], &edges[1], &edges[len-1], p[0], polyType); - - //reset xcurr & ycurr and find 'eHighest' (given the Y axis coordinates - //increase downward so the 'highest' edge will have the smallest ytop) ... - TEdge *e = &edges[0]; - TEdge *eHighest = e; - do - { - e->xcurr = e->xbot; - e->ycurr = e->ybot; - if (e->ytop < eHighest->ytop) eHighest = e; - e = e->next; - } - while ( e != &edges[0]); - - //make sure eHighest is positioned so the following loop works safely ... - if (eHighest->windDelta > 0) eHighest = eHighest->next; - if (NEAR_EQUAL(eHighest->dx, HORIZONTAL)) eHighest = eHighest->next; - - //finally insert each local minima ... - e = eHighest; - do { - e = AddBoundsToLML(e); - } - while( e != eHighest ); - return true; -} -//------------------------------------------------------------------------------ - -void ClipperBase::InsertLocalMinima(LocalMinima *newLm) -{ - if( ! m_MinimaList ) - { - m_MinimaList = newLm; - } - else if( newLm->Y >= m_MinimaList->Y ) - { - newLm->next = m_MinimaList; - m_MinimaList = newLm; - } else - { - LocalMinima* tmpLm = m_MinimaList; - while( tmpLm->next && ( newLm->Y < tmpLm->next->Y ) ) - tmpLm = tmpLm->next; - newLm->next = tmpLm->next; - tmpLm->next = newLm; - } -} -//------------------------------------------------------------------------------ - -TEdge* ClipperBase::AddBoundsToLML(TEdge *e) -{ - //Starting at the top of one bound we progress to the bottom where there's - //a local minima. We then go to the top of the next bound. These two bounds - //form the left and right (or right and left) bounds of the local minima. - e->nextInLML = 0; - e = e->next; - for (;;) - { - if (NEAR_EQUAL(e->dx, HORIZONTAL)) - { - //nb: proceed through horizontals when approaching from their right, - // but break on horizontal minima if approaching from their left. - // This ensures 'local minima' are always on the left of horizontals. - if (e->next->ytop < e->ytop && e->next->xbot > e->prev->xbot) break; - if (e->xtop != e->prev->xbot) SwapX(*e); - e->nextInLML = e->prev; - } - else if (e->ycurr == e->prev->ycurr) break; - else e->nextInLML = e->prev; - e = e->next; - } - - //e and e.prev are now at a local minima ... - LocalMinima* newLm = new LocalMinima; - newLm->next = 0; - newLm->Y = e->prev->ybot; - - if ( NEAR_EQUAL(e->dx, HORIZONTAL) ) //horizontal edges never start a left bound - { - if (e->xbot != e->prev->xbot) SwapX(*e); - newLm->leftBound = e->prev; - newLm->rightBound = e; - } else if (e->dx < e->prev->dx) - { - newLm->leftBound = e->prev; - newLm->rightBound = e; - } else - { - newLm->leftBound = e; - newLm->rightBound = e->prev; - } - newLm->leftBound->side = esLeft; - newLm->rightBound->side = esRight; - InsertLocalMinima( newLm ); - - for (;;) - { - if ( e->next->ytop == e->ytop && !NEAR_EQUAL(e->next->dx, HORIZONTAL) ) break; - e->nextInLML = e->next; - e = e->next; - if ( NEAR_EQUAL(e->dx, HORIZONTAL) && e->xbot != e->prev->xtop) SwapX(*e); - } - return e->next; -} -//------------------------------------------------------------------------------ - -bool ClipperBase::AddPolygons(const Polygons &ppg, PolyType polyType) -{ - bool result = false; - for (Polygons::size_type i = 0; i < ppg.size(); ++i) - if (AddPolygon(ppg[i], polyType)) result = true; - return result; -} -//------------------------------------------------------------------------------ - -void ClipperBase::Clear() -{ - DisposeLocalMinimaList(); - for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) delete [] m_edges[i]; - m_edges.clear(); - m_UseFullRange = false; -} -//------------------------------------------------------------------------------ - -void ClipperBase::Reset() -{ - m_CurrentLM = m_MinimaList; - if( !m_CurrentLM ) return; //ie nothing to process - - //reset all edges ... - LocalMinima* lm = m_MinimaList; - while( lm ) - { - TEdge* e = lm->leftBound; - while( e ) - { - e->xcurr = e->xbot; - e->ycurr = e->ybot; - e->side = esLeft; - e->outIdx = -1; - e = e->nextInLML; - } - e = lm->rightBound; - while( e ) - { - e->xcurr = e->xbot; - e->ycurr = e->ybot; - e->side = esRight; - e->outIdx = -1; - e = e->nextInLML; - } - lm = lm->next; - } -} -//------------------------------------------------------------------------------ - -void ClipperBase::DisposeLocalMinimaList() -{ - while( m_MinimaList ) - { - LocalMinima* tmpLm = m_MinimaList->next; - delete m_MinimaList; - m_MinimaList = tmpLm; - } - m_CurrentLM = 0; -} -//------------------------------------------------------------------------------ - -void ClipperBase::PopLocalMinima() -{ - if( ! m_CurrentLM ) return; - m_CurrentLM = m_CurrentLM->next; -} -//------------------------------------------------------------------------------ - -IntRect ClipperBase::GetBounds() -{ - IntRect result; - LocalMinima* lm = m_MinimaList; - if (!lm) - { - result.left = result.top = result.right = result.bottom = 0; - return result; - } - result.left = lm->leftBound->xbot; - result.top = lm->leftBound->ybot; - result.right = lm->leftBound->xbot; - result.bottom = lm->leftBound->ybot; - while (lm) - { - if (lm->leftBound->ybot > result.bottom) - result.bottom = lm->leftBound->ybot; - TEdge* e = lm->leftBound; - for (;;) { - TEdge* bottomE = e; - while (e->nextInLML) - { - if (e->xbot < result.left) result.left = e->xbot; - if (e->xbot > result.right) result.right = e->xbot; - e = e->nextInLML; - } - if (e->xbot < result.left) result.left = e->xbot; - if (e->xbot > result.right) result.right = e->xbot; - if (e->xtop < result.left) result.left = e->xtop; - if (e->xtop > result.right) result.right = e->xtop; - if (e->ytop < result.top) result.top = e->ytop; - - if (bottomE == lm->leftBound) e = lm->rightBound; - else break; - } - lm = lm->next; - } - return result; -} - - -//------------------------------------------------------------------------------ -// TClipper methods ... -//------------------------------------------------------------------------------ - -Clipper::Clipper() : ClipperBase() //constructor -{ - m_Scanbeam = 0; - m_ActiveEdges = 0; - m_SortedEdges = 0; - m_IntersectNodes = 0; - m_ExecuteLocked = false; - m_UseFullRange = false; - m_ReverseOutput = false; -} -//------------------------------------------------------------------------------ - -Clipper::~Clipper() //destructor -{ - Clear(); - DisposeScanbeamList(); -} -//------------------------------------------------------------------------------ - -void Clipper::Clear() -{ - if (m_edges.size() == 0) return; //avoids problems with ClipperBase destructor - DisposeAllPolyPts(); - ClipperBase::Clear(); -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeScanbeamList() -{ - while ( m_Scanbeam ) { - Scanbeam* sb2 = m_Scanbeam->next; - delete m_Scanbeam; - m_Scanbeam = sb2; - } -} -//------------------------------------------------------------------------------ - -void Clipper::Reset() -{ - ClipperBase::Reset(); - m_Scanbeam = 0; - m_ActiveEdges = 0; - m_SortedEdges = 0; - DisposeAllPolyPts(); - LocalMinima* lm = m_MinimaList; - while (lm) - { - InsertScanbeam(lm->Y); - InsertScanbeam(lm->leftBound->ytop); - lm = lm->next; - } -} -//------------------------------------------------------------------------------ - -bool Clipper::Execute(ClipType clipType, Polygons &solution, - PolyFillType subjFillType, PolyFillType clipFillType) -{ - if( m_ExecuteLocked ) return false; - m_ExecuteLocked = true; - solution.resize(0); - m_SubjFillType = subjFillType; - m_ClipFillType = clipFillType; - m_ClipType = clipType; - bool succeeded = ExecuteInternal(false); - if (succeeded) BuildResult(solution); - m_ExecuteLocked = false; - return succeeded; -} -//------------------------------------------------------------------------------ - -bool Clipper::Execute(ClipType clipType, ExPolygons &solution, - PolyFillType subjFillType, PolyFillType clipFillType) -{ - if( m_ExecuteLocked ) return false; - m_ExecuteLocked = true; - solution.resize(0); - m_SubjFillType = subjFillType; - m_ClipFillType = clipFillType; - m_ClipType = clipType; - bool succeeded = ExecuteInternal(true); - if (succeeded) BuildResultEx(solution); - m_ExecuteLocked = false; - return succeeded; -} -//------------------------------------------------------------------------------ - -bool PolySort(OutRec *or1, OutRec *or2) -{ - if (or1 == or2) return false; - if (!or1->pts || !or2->pts) - { - if (or1->pts != or2->pts) - { - return or1->pts ? true : false; - } - else return false; - } - int i1, i2; - if (or1->isHole) - i1 = or1->FirstLeft->idx; else - i1 = or1->idx; - if (or2->isHole) - i2 = or2->FirstLeft->idx; else - i2 = or2->idx; - int result = i1 - i2; - if (result == 0 && (or1->isHole != or2->isHole)) - { - return or1->isHole ? false : true; - } - else return result < 0; -} -//------------------------------------------------------------------------------ - -OutRec* FindAppendLinkEnd(OutRec *outRec) -{ - while (outRec->AppendLink) outRec = outRec->AppendLink; - return outRec; -} -//------------------------------------------------------------------------------ - -void Clipper::FixHoleLinkage(OutRec *outRec) -{ - OutRec *tmp; - if (outRec->bottomPt) - tmp = m_PolyOuts[outRec->bottomPt->idx]->FirstLeft; - else - tmp = outRec->FirstLeft; - if (outRec == tmp) throw clipperException("HoleLinkage error"); - - if (tmp) - { - if (tmp->AppendLink) tmp = FindAppendLinkEnd(tmp); - if (tmp == outRec) tmp = 0; - else if (tmp->isHole) - { - FixHoleLinkage(tmp); - tmp = tmp->FirstLeft; - } - } - outRec->FirstLeft = tmp; - if (!tmp) outRec->isHole = false; - outRec->AppendLink = 0; -} -//------------------------------------------------------------------------------ - -bool Clipper::ExecuteInternal(bool fixHoleLinkages) -{ - bool succeeded; - try { - Reset(); - if (!m_CurrentLM ) return true; - long64 botY = PopScanbeam(); - do { - InsertLocalMinimaIntoAEL(botY); - ClearHorzJoins(); - ProcessHorizontals(); - long64 topY = PopScanbeam(); - succeeded = ProcessIntersections(botY, topY); - if (!succeeded) break; - ProcessEdgesAtTopOfScanbeam(topY); - botY = topY; - } while( m_Scanbeam ); - } - catch(...) { - succeeded = false; - } - - if (succeeded) - { - //tidy up output polygons and fix orientations where necessary ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - OutRec *outRec = m_PolyOuts[i]; - if (!outRec->pts) continue; - FixupOutPolygon(*outRec); - if (!outRec->pts) continue; - if (outRec->isHole && fixHoleLinkages) FixHoleLinkage(outRec); - - if (outRec->bottomPt == outRec->bottomFlag && - (Orientation(outRec, m_UseFullRange) != (Area(*outRec, m_UseFullRange) > 0))) - DisposeBottomPt(*outRec); - - if (outRec->isHole == - (m_ReverseOutput ^ Orientation(outRec, m_UseFullRange))) - ReversePolyPtLinks(*outRec->pts); - } - - JoinCommonEdges(fixHoleLinkages); - if (fixHoleLinkages) - std::sort(m_PolyOuts.begin(), m_PolyOuts.end(), PolySort); - } - - ClearJoins(); - ClearHorzJoins(); - return succeeded; -} -//------------------------------------------------------------------------------ - -void Clipper::InsertScanbeam(const long64 Y) -{ - if( !m_Scanbeam ) - { - m_Scanbeam = new Scanbeam; - m_Scanbeam->next = 0; - m_Scanbeam->Y = Y; - } - else if( Y > m_Scanbeam->Y ) - { - Scanbeam* newSb = new Scanbeam; - newSb->Y = Y; - newSb->next = m_Scanbeam; - m_Scanbeam = newSb; - } else - { - Scanbeam* sb2 = m_Scanbeam; - while( sb2->next && ( Y <= sb2->next->Y ) ) sb2 = sb2->next; - if( Y == sb2->Y ) return; //ie ignores duplicates - Scanbeam* newSb = new Scanbeam; - newSb->Y = Y; - newSb->next = sb2->next; - sb2->next = newSb; - } -} -//------------------------------------------------------------------------------ - -long64 Clipper::PopScanbeam() -{ - long64 Y = m_Scanbeam->Y; - Scanbeam* sb2 = m_Scanbeam; - m_Scanbeam = m_Scanbeam->next; - delete sb2; - return Y; -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeAllPolyPts(){ - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - DisposeOutRec(i); - m_PolyOuts.clear(); -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeOutRec(PolyOutList::size_type index) -{ - OutRec *outRec = m_PolyOuts[index]; - if (outRec->pts) DisposeOutPts(outRec->pts); - delete outRec; - m_PolyOuts[index] = 0; -} -//------------------------------------------------------------------------------ - -void Clipper::SetWindingCount(TEdge &edge) -{ - TEdge *e = edge.prevInAEL; - //find the edge of the same polytype that immediately preceeds 'edge' in AEL - while ( e && e->polyType != edge.polyType ) e = e->prevInAEL; - if ( !e ) - { - edge.windCnt = edge.windDelta; - edge.windCnt2 = 0; - e = m_ActiveEdges; //ie get ready to calc windCnt2 - } else if ( IsEvenOddFillType(edge) ) - { - //EvenOdd filling ... - edge.windCnt = 1; - edge.windCnt2 = e->windCnt2; - e = e->nextInAEL; //ie get ready to calc windCnt2 - } else - { - //nonZero, Positive or Negative filling ... - if ( e->windCnt * e->windDelta < 0 ) - { - if (Abs(e->windCnt) > 1) - { - if (e->windDelta * edge.windDelta < 0) edge.windCnt = e->windCnt; - else edge.windCnt = e->windCnt + edge.windDelta; - } else - edge.windCnt = e->windCnt + e->windDelta + edge.windDelta; - } else - { - if ( Abs(e->windCnt) > 1 && e->windDelta * edge.windDelta < 0) - edge.windCnt = e->windCnt; - else if ( e->windCnt + edge.windDelta == 0 ) - edge.windCnt = e->windCnt; - else edge.windCnt = e->windCnt + edge.windDelta; - } - edge.windCnt2 = e->windCnt2; - e = e->nextInAEL; //ie get ready to calc windCnt2 - } - - //update windCnt2 ... - if ( IsEvenOddAltFillType(edge) ) - { - //EvenOdd filling ... - while ( e != &edge ) - { - edge.windCnt2 = (edge.windCnt2 == 0) ? 1 : 0; - e = e->nextInAEL; - } - } else - { - //nonZero, Positive or Negative filling ... - while ( e != &edge ) - { - edge.windCnt2 += e->windDelta; - e = e->nextInAEL; - } - } -} -//------------------------------------------------------------------------------ - -bool Clipper::IsEvenOddFillType(const TEdge& edge) const -{ - if (edge.polyType == ptSubject) - return m_SubjFillType == pftEvenOdd; else - return m_ClipFillType == pftEvenOdd; -} -//------------------------------------------------------------------------------ - -bool Clipper::IsEvenOddAltFillType(const TEdge& edge) const -{ - if (edge.polyType == ptSubject) - return m_ClipFillType == pftEvenOdd; else - return m_SubjFillType == pftEvenOdd; -} -//------------------------------------------------------------------------------ - -bool Clipper::IsContributing(const TEdge& edge) const -{ - PolyFillType pft, pft2; - if (edge.polyType == ptSubject) - { - pft = m_SubjFillType; - pft2 = m_ClipFillType; - } else - { - pft = m_ClipFillType; - pft2 = m_SubjFillType; - } - - switch(pft) - { - case pftEvenOdd: - case pftNonZero: - if (Abs(edge.windCnt) != 1) return false; - break; - case pftPositive: - if (edge.windCnt != 1) return false; - break; - default: //pftNegative - if (edge.windCnt != -1) return false; - } - - switch(m_ClipType) - { - case ctIntersection: - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.windCnt2 != 0); - case pftPositive: - return (edge.windCnt2 > 0); - default: - return (edge.windCnt2 < 0); - } - case ctUnion: - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.windCnt2 == 0); - case pftPositive: - return (edge.windCnt2 <= 0); - default: - return (edge.windCnt2 >= 0); - } - case ctDifference: - if (edge.polyType == ptSubject) - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.windCnt2 == 0); - case pftPositive: - return (edge.windCnt2 <= 0); - default: - return (edge.windCnt2 >= 0); - } - else - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.windCnt2 != 0); - case pftPositive: - return (edge.windCnt2 > 0); - default: - return (edge.windCnt2 < 0); - } - default: - return true; - } -} -//------------------------------------------------------------------------------ - -void Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) -{ - TEdge *e, *prevE; - if( NEAR_EQUAL(e2->dx, HORIZONTAL) || ( e1->dx > e2->dx ) ) - { - AddOutPt( e1, pt ); - e2->outIdx = e1->outIdx; - e1->side = esLeft; - e2->side = esRight; - e = e1; - if (e->prevInAEL == e2) - prevE = e2->prevInAEL; - else - prevE = e->prevInAEL; - } else - { - AddOutPt( e2, pt ); - e1->outIdx = e2->outIdx; - e1->side = esRight; - e2->side = esLeft; - e = e2; - if (e->prevInAEL == e1) - prevE = e1->prevInAEL; - else - prevE = e->prevInAEL; - } - if (prevE && prevE->outIdx >= 0 && - (TopX(*prevE, pt.Y) == TopX(*e, pt.Y)) && - SlopesEqual(*e, *prevE, m_UseFullRange)) - AddJoin(e, prevE, -1, -1); -} -//------------------------------------------------------------------------------ - -void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) -{ - AddOutPt( e1, pt ); - if( e1->outIdx == e2->outIdx ) - { - e1->outIdx = -1; - e2->outIdx = -1; - } - else if (e1->outIdx < e2->outIdx) - AppendPolygon(e1, e2); - else - AppendPolygon(e2, e1); -} -//------------------------------------------------------------------------------ - -void Clipper::AddEdgeToSEL(TEdge *edge) -{ - //SEL pointers in PEdge are reused to build a list of horizontal edges. - //However, we don't need to worry about order with horizontal edge processing. - if( !m_SortedEdges ) - { - m_SortedEdges = edge; - edge->prevInSEL = 0; - edge->nextInSEL = 0; - } - else - { - edge->nextInSEL = m_SortedEdges; - edge->prevInSEL = 0; - m_SortedEdges->prevInSEL = edge; - m_SortedEdges = edge; - } -} -//------------------------------------------------------------------------------ - -void Clipper::CopyAELToSEL() -{ - TEdge* e = m_ActiveEdges; - m_SortedEdges = e; - if (!m_ActiveEdges) return; - m_SortedEdges->prevInSEL = 0; - e = e->nextInAEL; - while ( e ) - { - e->prevInSEL = e->prevInAEL; - e->prevInSEL->nextInSEL = e; - e->nextInSEL = 0; - e = e->nextInAEL; - } -} -//------------------------------------------------------------------------------ - -void Clipper::AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx, int e2OutIdx) -{ - JoinRec* jr = new JoinRec; - if (e1OutIdx >= 0) - jr->poly1Idx = e1OutIdx; else - jr->poly1Idx = e1->outIdx; - jr->pt1a = IntPoint(e1->xcurr, e1->ycurr); - jr->pt1b = IntPoint(e1->xtop, e1->ytop); - if (e2OutIdx >= 0) - jr->poly2Idx = e2OutIdx; else - jr->poly2Idx = e2->outIdx; - jr->pt2a = IntPoint(e2->xcurr, e2->ycurr); - jr->pt2b = IntPoint(e2->xtop, e2->ytop); - m_Joins.push_back(jr); -} -//------------------------------------------------------------------------------ - -void Clipper::ClearJoins() -{ - for (JoinList::size_type i = 0; i < m_Joins.size(); i++) - delete m_Joins[i]; - m_Joins.resize(0); -} -//------------------------------------------------------------------------------ - -void Clipper::AddHorzJoin(TEdge *e, int idx) -{ - HorzJoinRec* hj = new HorzJoinRec; - hj->edge = e; - hj->savedIdx = idx; - m_HorizJoins.push_back(hj); -} -//------------------------------------------------------------------------------ - -void Clipper::ClearHorzJoins() -{ - for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); i++) - delete m_HorizJoins[i]; - m_HorizJoins.resize(0); -} -//------------------------------------------------------------------------------ - -void Clipper::InsertLocalMinimaIntoAEL( const long64 botY) -{ - while( m_CurrentLM && ( m_CurrentLM->Y == botY ) ) - { - TEdge* lb = m_CurrentLM->leftBound; - TEdge* rb = m_CurrentLM->rightBound; - - InsertEdgeIntoAEL( lb ); - InsertScanbeam( lb->ytop ); - InsertEdgeIntoAEL( rb ); - - if (IsEvenOddFillType(*lb)) - { - lb->windDelta = 1; - rb->windDelta = 1; - } - else - { - rb->windDelta = -lb->windDelta; - } - SetWindingCount( *lb ); - rb->windCnt = lb->windCnt; - rb->windCnt2 = lb->windCnt2; - - if( NEAR_EQUAL(rb->dx, HORIZONTAL) ) - { - //nb: only rightbounds can have a horizontal bottom edge - AddEdgeToSEL( rb ); - InsertScanbeam( rb->nextInLML->ytop ); - } - else - InsertScanbeam( rb->ytop ); - - if( IsContributing(*lb) ) - AddLocalMinPoly( lb, rb, IntPoint(lb->xcurr, m_CurrentLM->Y) ); - - //if any output polygons share an edge, they'll need joining later ... - if (rb->outIdx >= 0) - { - if (NEAR_EQUAL(rb->dx, HORIZONTAL)) - { - for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) - { - IntPoint pt, pt2; //returned by GetOverlapSegment() but unused here. - HorzJoinRec* hj = m_HorizJoins[i]; - //if horizontals rb and hj.edge overlap, flag for joining later ... - if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), - IntPoint(hj->edge->xtop, hj->edge->ytop), - IntPoint(rb->xbot, rb->ybot), - IntPoint(rb->xtop, rb->ytop), pt, pt2)) - AddJoin(hj->edge, rb, hj->savedIdx); - } - } - } - - if( lb->nextInAEL != rb ) - { - if (rb->outIdx >= 0 && rb->prevInAEL->outIdx >= 0 && - SlopesEqual(*rb->prevInAEL, *rb, m_UseFullRange)) - AddJoin(rb, rb->prevInAEL); - - TEdge* e = lb->nextInAEL; - IntPoint pt = IntPoint(lb->xcurr, lb->ycurr); - while( e != rb ) - { - if(!e) throw clipperException("InsertLocalMinimaIntoAEL: missing rightbound!"); - //nb: For calculating winding counts etc, IntersectEdges() assumes - //that param1 will be to the right of param2 ABOVE the intersection ... - IntersectEdges( rb , e , pt , ipNone); //order important here - e = e->nextInAEL; - } - } - PopLocalMinima(); - } -} -//------------------------------------------------------------------------------ - -void Clipper::DeleteFromAEL(TEdge *e) -{ - TEdge* AelPrev = e->prevInAEL; - TEdge* AelNext = e->nextInAEL; - if( !AelPrev && !AelNext && (e != m_ActiveEdges) ) return; //already deleted - if( AelPrev ) AelPrev->nextInAEL = AelNext; - else m_ActiveEdges = AelNext; - if( AelNext ) AelNext->prevInAEL = AelPrev; - e->nextInAEL = 0; - e->prevInAEL = 0; -} -//------------------------------------------------------------------------------ - -void Clipper::DeleteFromSEL(TEdge *e) -{ - TEdge* SelPrev = e->prevInSEL; - TEdge* SelNext = e->nextInSEL; - if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted - if( SelPrev ) SelPrev->nextInSEL = SelNext; - else m_SortedEdges = SelNext; - if( SelNext ) SelNext->prevInSEL = SelPrev; - e->nextInSEL = 0; - e->prevInSEL = 0; -} -//------------------------------------------------------------------------------ - -void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, - const IntPoint &pt, IntersectProtects protects) -{ - //e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before - //e2 in AEL except when e1 is being inserted at the intersection point ... - bool e1stops = !(ipLeft & protects) && !e1->nextInLML && - e1->xtop == pt.X && e1->ytop == pt.Y; - bool e2stops = !(ipRight & protects) && !e2->nextInLML && - e2->xtop == pt.X && e2->ytop == pt.Y; - bool e1Contributing = ( e1->outIdx >= 0 ); - bool e2contributing = ( e2->outIdx >= 0 ); - - //update winding counts... - //assumes that e1 will be to the right of e2 ABOVE the intersection - if ( e1->polyType == e2->polyType ) - { - if ( IsEvenOddFillType( *e1) ) - { - int oldE1WindCnt = e1->windCnt; - e1->windCnt = e2->windCnt; - e2->windCnt = oldE1WindCnt; - } else - { - if (e1->windCnt + e2->windDelta == 0 ) e1->windCnt = -e1->windCnt; - else e1->windCnt += e2->windDelta; - if ( e2->windCnt - e1->windDelta == 0 ) e2->windCnt = -e2->windCnt; - else e2->windCnt -= e1->windDelta; - } - } else - { - if (!IsEvenOddFillType(*e2)) e1->windCnt2 += e2->windDelta; - else e1->windCnt2 = ( e1->windCnt2 == 0 ) ? 1 : 0; - if (!IsEvenOddFillType(*e1)) e2->windCnt2 -= e1->windDelta; - else e2->windCnt2 = ( e2->windCnt2 == 0 ) ? 1 : 0; - } - - PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; - if (e1->polyType == ptSubject) - { - e1FillType = m_SubjFillType; - e1FillType2 = m_ClipFillType; - } else - { - e1FillType = m_ClipFillType; - e1FillType2 = m_SubjFillType; - } - if (e2->polyType == ptSubject) - { - e2FillType = m_SubjFillType; - e2FillType2 = m_ClipFillType; - } else - { - e2FillType = m_ClipFillType; - e2FillType2 = m_SubjFillType; - } - - long64 e1Wc, e2Wc; - switch (e1FillType) - { - case pftPositive: e1Wc = e1->windCnt; break; - case pftNegative: e1Wc = -e1->windCnt; break; - default: e1Wc = Abs(e1->windCnt); - } - switch(e2FillType) - { - case pftPositive: e2Wc = e2->windCnt; break; - case pftNegative: e2Wc = -e2->windCnt; break; - default: e2Wc = Abs(e2->windCnt); - } - - if ( e1Contributing && e2contributing ) - { - if ( e1stops || e2stops || - (e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || - (e1->polyType != e2->polyType && m_ClipType != ctXor) ) - AddLocalMaxPoly(e1, e2, pt); - else - DoBothEdges( e1, e2, pt ); - } - else if ( e1Contributing ) - { - if ((e2Wc == 0 || e2Wc == 1) && - (m_ClipType != ctIntersection || - e2->polyType == ptSubject || (e2->windCnt2 != 0))) - DoEdge1(e1, e2, pt); - } - else if ( e2contributing ) - { - if ((e1Wc == 0 || e1Wc == 1) && - (m_ClipType != ctIntersection || - e1->polyType == ptSubject || (e1->windCnt2 != 0))) - DoEdge2(e1, e2, pt); - } - else if ( (e1Wc == 0 || e1Wc == 1) && - (e2Wc == 0 || e2Wc == 1) && !e1stops && !e2stops ) - { - //neither edge is currently contributing ... - - long64 e1Wc2, e2Wc2; - switch (e1FillType2) - { - case pftPositive: e1Wc2 = e1->windCnt2; break; - case pftNegative : e1Wc2 = -e1->windCnt2; break; - default: e1Wc2 = Abs(e1->windCnt2); - } - switch (e2FillType2) - { - case pftPositive: e2Wc2 = e2->windCnt2; break; - case pftNegative: e2Wc2 = -e2->windCnt2; break; - default: e2Wc2 = Abs(e2->windCnt2); - } - - if (e1->polyType != e2->polyType) - AddLocalMinPoly(e1, e2, pt); - else if (e1Wc == 1 && e2Wc == 1) - switch( m_ClipType ) { - case ctIntersection: - if (e1Wc2 > 0 && e2Wc2 > 0) - AddLocalMinPoly(e1, e2, pt); - break; - case ctUnion: - if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) - AddLocalMinPoly(e1, e2, pt); - break; - case ctDifference: - if (((e1->polyType == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || - ((e1->polyType == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) - AddLocalMinPoly(e1, e2, pt); - break; - case ctXor: - AddLocalMinPoly(e1, e2, pt); - } - else - SwapSides( *e1, *e2 ); - } - - if( (e1stops != e2stops) && - ( (e1stops && (e1->outIdx >= 0)) || (e2stops && (e2->outIdx >= 0)) ) ) - { - SwapSides( *e1, *e2 ); - SwapPolyIndexes( *e1, *e2 ); - } - - //finally, delete any non-contributing maxima edges ... - if( e1stops ) DeleteFromAEL( e1 ); - if( e2stops ) DeleteFromAEL( e2 ); -} -//------------------------------------------------------------------------------ - -void Clipper::SetHoleState(TEdge *e, OutRec *outRec) -{ - bool isHole = false; - TEdge *e2 = e->prevInAEL; - while (e2) - { - if (e2->outIdx >= 0) - { - isHole = !isHole; - if (! outRec->FirstLeft) - outRec->FirstLeft = m_PolyOuts[e2->outIdx]; - } - e2 = e2->prevInAEL; - } - if (isHole) outRec->isHole = true; -} -//------------------------------------------------------------------------------ - -OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) -{ - //work out which polygon fragment has the correct hole state ... - OutPt *outPt1 = outRec1->bottomPt; - OutPt *outPt2 = outRec2->bottomPt; - if (outPt1->pt.Y > outPt2->pt.Y) return outRec1; - else if (outPt1->pt.Y < outPt2->pt.Y) return outRec2; - else if (outPt1->pt.X < outPt2->pt.X) return outRec1; - else if (outPt1->pt.X > outPt2->pt.X) return outRec2; - else if (outPt1->next == outPt1) return outRec2; - else if (outPt2->next == outPt2) return outRec1; - else if (FirstIsBottomPt(outPt1, outPt2)) return outRec1; - else return outRec2; -} -//------------------------------------------------------------------------------ - -bool Param1RightOfParam2(OutRec* outRec1, OutRec* outRec2) -{ - do - { - outRec1 = outRec1->FirstLeft; - if (outRec1 == outRec2) return true; - } while (outRec1); - return false; -} -//------------------------------------------------------------------------------ - -void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) -{ - //get the start and ends of both output polygons ... - OutRec *outRec1 = m_PolyOuts[e1->outIdx]; - OutRec *outRec2 = m_PolyOuts[e2->outIdx]; - - OutRec *holeStateRec; - if (Param1RightOfParam2(outRec1, outRec2)) holeStateRec = outRec2; - else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1; - else holeStateRec = GetLowermostRec(outRec1, outRec2); - - OutPt* p1_lft = outRec1->pts; - OutPt* p1_rt = p1_lft->prev; - OutPt* p2_lft = outRec2->pts; - OutPt* p2_rt = p2_lft->prev; - - EdgeSide side; - //join e2 poly onto e1 poly and delete pointers to e2 ... - if( e1->side == esLeft ) - { - if( e2->side == esLeft ) - { - //z y x a b c - ReversePolyPtLinks(*p2_lft); - p2_lft->next = p1_lft; - p1_lft->prev = p2_lft; - p1_rt->next = p2_rt; - p2_rt->prev = p1_rt; - outRec1->pts = p2_rt; - } else - { - //x y z a b c - p2_rt->next = p1_lft; - p1_lft->prev = p2_rt; - p2_lft->prev = p1_rt; - p1_rt->next = p2_lft; - outRec1->pts = p2_lft; - } - side = esLeft; - } else - { - if( e2->side == esRight ) - { - //a b c z y x - ReversePolyPtLinks( *p2_lft ); - p1_rt->next = p2_rt; - p2_rt->prev = p1_rt; - p2_lft->next = p1_lft; - p1_lft->prev = p2_lft; - } else - { - //a b c x y z - p1_rt->next = p2_lft; - p2_lft->prev = p1_rt; - p1_lft->prev = p2_rt; - p2_rt->next = p1_lft; - } - side = esRight; - } - - if (holeStateRec == outRec2) - { - outRec1->bottomPt = outRec2->bottomPt; - outRec1->bottomPt->idx = outRec1->idx; - if (outRec2->FirstLeft != outRec1) - outRec1->FirstLeft = outRec2->FirstLeft; - outRec1->isHole = outRec2->isHole; - } - outRec2->pts = 0; - outRec2->bottomPt = 0; - outRec2->AppendLink = outRec1; - int OKIdx = e1->outIdx; - int ObsoleteIdx = e2->outIdx; - - e1->outIdx = -1; //nb: safe because we only get here via AddLocalMaxPoly - e2->outIdx = -1; - - TEdge* e = m_ActiveEdges; - while( e ) - { - if( e->outIdx == ObsoleteIdx ) - { - e->outIdx = OKIdx; - e->side = side; - break; - } - e = e->nextInAEL; - } - - for (JoinList::size_type i = 0; i < m_Joins.size(); ++i) - { - if (m_Joins[i]->poly1Idx == ObsoleteIdx) m_Joins[i]->poly1Idx = OKIdx; - if (m_Joins[i]->poly2Idx == ObsoleteIdx) m_Joins[i]->poly2Idx = OKIdx; - } - - for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) - { - if (m_HorizJoins[i]->savedIdx == ObsoleteIdx) - m_HorizJoins[i]->savedIdx = OKIdx; - } - -} -//------------------------------------------------------------------------------ - -OutRec* Clipper::CreateOutRec() -{ - OutRec* result = new OutRec; - result->isHole = false; - result->FirstLeft = 0; - result->AppendLink = 0; - result->pts = 0; - result->bottomPt = 0; - result->sides = esNeither; - result->bottomFlag = 0; - - return result; -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeBottomPt(OutRec &outRec) -{ - OutPt* next = outRec.bottomPt->next; - OutPt* prev = outRec.bottomPt->prev; - if (outRec.pts == outRec.bottomPt) outRec.pts = next; - delete outRec.bottomPt; - next->prev = prev; - prev->next = next; - outRec.bottomPt = next; - FixupOutPolygon(outRec); -} -//------------------------------------------------------------------------------ - -void Clipper::AddOutPt(TEdge *e, const IntPoint &pt) -{ - bool ToFront = (e->side == esLeft); - if( e->outIdx < 0 ) - { - OutRec *outRec = CreateOutRec(); - m_PolyOuts.push_back(outRec); - outRec->idx = (int)m_PolyOuts.size()-1; - e->outIdx = outRec->idx; - OutPt* op = new OutPt; - outRec->pts = op; - outRec->bottomPt = op; - op->pt = pt; - op->idx = outRec->idx; - op->next = op; - op->prev = op; - SetHoleState(e, outRec); - } else - { - OutRec *outRec = m_PolyOuts[e->outIdx]; - OutPt* op = outRec->pts; - if ((ToFront && PointsEqual(pt, op->pt)) || - (!ToFront && PointsEqual(pt, op->prev->pt))) return; - - if ((e->side | outRec->sides) != outRec->sides) - { - //check for 'rounding' artefacts ... - if (outRec->sides == esNeither && pt.Y == op->pt.Y) - { - if (ToFront) - { - if (pt.X == op->pt.X +1) return; //ie wrong side of bottomPt - } - else if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt - } - - outRec->sides = (EdgeSide)(outRec->sides | e->side); - if (outRec->sides == esBoth) - { - //A vertex from each side has now been added. - //Vertices of one side of an output polygon are quite commonly close to - //or even 'touching' edges of the other side of the output polygon. - //Very occasionally vertices from one side can 'cross' an edge on the - //the other side. The distance 'crossed' is always less that a unit - //and is purely an artefact of coordinate rounding. Nevertheless, this - //results in very tiny self-intersections. Because of the way - //orientation is calculated, even tiny self-intersections can cause - //the Orientation function to return the wrong result. Therefore, it's - //important to ensure that any self-intersections close to BottomPt are - //detected and removed before orientation is assigned. - - OutPt *opBot, *op2; - if (ToFront) - { - opBot = outRec->pts; - op2 = opBot->next; //op2 == right side - if (opBot->pt.Y != op2->pt.Y && opBot->pt.Y != pt.Y && - ((opBot->pt.X - pt.X)/(opBot->pt.Y - pt.Y) < - (opBot->pt.X - op2->pt.X)/(opBot->pt.Y - op2->pt.Y))) - outRec->bottomFlag = opBot; - } else - { - opBot = outRec->pts->prev; - op2 = opBot->prev; //op2 == left side - if (opBot->pt.Y != op2->pt.Y && opBot->pt.Y != pt.Y && - ((opBot->pt.X - pt.X)/(opBot->pt.Y - pt.Y) > - (opBot->pt.X - op2->pt.X)/(opBot->pt.Y - op2->pt.Y))) - outRec->bottomFlag = opBot; - } - } - } - - OutPt* op2 = new OutPt; - op2->pt = pt; - op2->idx = outRec->idx; - if (op2->pt.Y == outRec->bottomPt->pt.Y && - op2->pt.X < outRec->bottomPt->pt.X) - outRec->bottomPt = op2; - op2->next = op; - op2->prev = op->prev; - op2->prev->next = op2; - op->prev = op2; - if (ToFront) outRec->pts = op2; - } -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessHorizontals() -{ - TEdge* horzEdge = m_SortedEdges; - while( horzEdge ) - { - DeleteFromSEL( horzEdge ); - ProcessHorizontal( horzEdge ); - horzEdge = m_SortedEdges; - } -} -//------------------------------------------------------------------------------ - -bool Clipper::IsTopHorz(const long64 XPos) -{ - TEdge* e = m_SortedEdges; - while( e ) - { - if( ( XPos >= std::min(e->xcurr, e->xtop) ) && - ( XPos <= std::max(e->xcurr, e->xtop) ) ) return false; - e = e->nextInSEL; - } - return true; -} -//------------------------------------------------------------------------------ - -bool IsMinima(TEdge *e) -{ - return e && (e->prev->nextInLML != e) && (e->next->nextInLML != e); -} -//------------------------------------------------------------------------------ - -bool IsMaxima(TEdge *e, const long64 Y) -{ - return e && e->ytop == Y && !e->nextInLML; -} -//------------------------------------------------------------------------------ - -bool IsIntermediate(TEdge *e, const long64 Y) -{ - return e->ytop == Y && e->nextInLML; -} -//------------------------------------------------------------------------------ - -TEdge *GetMaximaPair(TEdge *e) -{ - if( !IsMaxima(e->next, e->ytop) || e->next->xtop != e->xtop ) - return e->prev; else - return e->next; -} -//------------------------------------------------------------------------------ - -void Clipper::SwapPositionsInAEL(TEdge *edge1, TEdge *edge2) -{ - if( !edge1->nextInAEL && !edge1->prevInAEL ) return; - if( !edge2->nextInAEL && !edge2->prevInAEL ) return; - - if( edge1->nextInAEL == edge2 ) - { - TEdge* next = edge2->nextInAEL; - if( next ) next->prevInAEL = edge1; - TEdge* prev = edge1->prevInAEL; - if( prev ) prev->nextInAEL = edge2; - edge2->prevInAEL = prev; - edge2->nextInAEL = edge1; - edge1->prevInAEL = edge2; - edge1->nextInAEL = next; - } - else if( edge2->nextInAEL == edge1 ) - { - TEdge* next = edge1->nextInAEL; - if( next ) next->prevInAEL = edge2; - TEdge* prev = edge2->prevInAEL; - if( prev ) prev->nextInAEL = edge1; - edge1->prevInAEL = prev; - edge1->nextInAEL = edge2; - edge2->prevInAEL = edge1; - edge2->nextInAEL = next; - } - else - { - TEdge* next = edge1->nextInAEL; - TEdge* prev = edge1->prevInAEL; - edge1->nextInAEL = edge2->nextInAEL; - if( edge1->nextInAEL ) edge1->nextInAEL->prevInAEL = edge1; - edge1->prevInAEL = edge2->prevInAEL; - if( edge1->prevInAEL ) edge1->prevInAEL->nextInAEL = edge1; - edge2->nextInAEL = next; - if( edge2->nextInAEL ) edge2->nextInAEL->prevInAEL = edge2; - edge2->prevInAEL = prev; - if( edge2->prevInAEL ) edge2->prevInAEL->nextInAEL = edge2; - } - - if( !edge1->prevInAEL ) m_ActiveEdges = edge1; - else if( !edge2->prevInAEL ) m_ActiveEdges = edge2; -} -//------------------------------------------------------------------------------ - -void Clipper::SwapPositionsInSEL(TEdge *edge1, TEdge *edge2) -{ - if( !( edge1->nextInSEL ) && !( edge1->prevInSEL ) ) return; - if( !( edge2->nextInSEL ) && !( edge2->prevInSEL ) ) return; - - if( edge1->nextInSEL == edge2 ) - { - TEdge* next = edge2->nextInSEL; - if( next ) next->prevInSEL = edge1; - TEdge* prev = edge1->prevInSEL; - if( prev ) prev->nextInSEL = edge2; - edge2->prevInSEL = prev; - edge2->nextInSEL = edge1; - edge1->prevInSEL = edge2; - edge1->nextInSEL = next; - } - else if( edge2->nextInSEL == edge1 ) - { - TEdge* next = edge1->nextInSEL; - if( next ) next->prevInSEL = edge2; - TEdge* prev = edge2->prevInSEL; - if( prev ) prev->nextInSEL = edge1; - edge1->prevInSEL = prev; - edge1->nextInSEL = edge2; - edge2->prevInSEL = edge1; - edge2->nextInSEL = next; - } - else - { - TEdge* next = edge1->nextInSEL; - TEdge* prev = edge1->prevInSEL; - edge1->nextInSEL = edge2->nextInSEL; - if( edge1->nextInSEL ) edge1->nextInSEL->prevInSEL = edge1; - edge1->prevInSEL = edge2->prevInSEL; - if( edge1->prevInSEL ) edge1->prevInSEL->nextInSEL = edge1; - edge2->nextInSEL = next; - if( edge2->nextInSEL ) edge2->nextInSEL->prevInSEL = edge2; - edge2->prevInSEL = prev; - if( edge2->prevInSEL ) edge2->prevInSEL->nextInSEL = edge2; - } - - if( !edge1->prevInSEL ) m_SortedEdges = edge1; - else if( !edge2->prevInSEL ) m_SortedEdges = edge2; -} -//------------------------------------------------------------------------------ - -TEdge* GetNextInAEL(TEdge *e, Direction dir) -{ - return dir == dLeftToRight ? e->nextInAEL : e->prevInAEL; -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessHorizontal(TEdge *horzEdge) -{ - Direction dir; - long64 horzLeft, horzRight; - - if( horzEdge->xcurr < horzEdge->xtop ) - { - horzLeft = horzEdge->xcurr; - horzRight = horzEdge->xtop; - dir = dLeftToRight; - } else - { - horzLeft = horzEdge->xtop; - horzRight = horzEdge->xcurr; - dir = dRightToLeft; - } - - TEdge* eMaxPair; - if( horzEdge->nextInLML ) eMaxPair = 0; - else eMaxPair = GetMaximaPair(horzEdge); - - TEdge* e = GetNextInAEL( horzEdge , dir ); - while( e ) - { - TEdge* eNext = GetNextInAEL( e, dir ); - - if (eMaxPair || - ((dir == dLeftToRight) && (e->xcurr <= horzRight)) || - ((dir == dRightToLeft) && (e->xcurr >= horzLeft))) - { - //ok, so far it looks like we're still in range of the horizontal edge - if ( e->xcurr == horzEdge->xtop && !eMaxPair ) - { - if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange)) - { - //if output polygons share an edge, they'll need joining later ... - if (horzEdge->outIdx >= 0 && e->outIdx >= 0) - AddJoin(horzEdge->nextInLML, e, horzEdge->outIdx); - break; //we've reached the end of the horizontal line - } - else if (e->dx < horzEdge->nextInLML->dx) - //we really have got to the end of the intermediate horz edge so quit. - //nb: More -ve slopes follow more +ve slopes ABOVE the horizontal. - break; - } - - if( e == eMaxPair ) - { - //horzEdge is evidently a maxima horizontal and we've arrived at its end. - if (dir == dLeftToRight) - IntersectEdges(horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); - else - IntersectEdges(e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); - if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); - return; - } - else if( NEAR_EQUAL(e->dx, HORIZONTAL) && !IsMinima(e) && !(e->xcurr > e->xtop) ) - { - //An overlapping horizontal edge. Overlapping horizontal edges are - //processed as if layered with the current horizontal edge (horizEdge) - //being infinitesimally lower that the next (e). Therfore, we - //intersect with e only if e.xcurr is within the bounds of horzEdge ... - if( dir == dLeftToRight ) - IntersectEdges( horzEdge , e, IntPoint(e->xcurr, horzEdge->ycurr), - (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); - else - IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), - (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); - } - else if( dir == dLeftToRight ) - { - IntersectEdges( horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), - (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); - } - else - { - IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), - (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); - } - SwapPositionsInAEL( horzEdge, e ); - } - else if( (dir == dLeftToRight && e->xcurr > horzRight && m_SortedEdges) || - (dir == dRightToLeft && e->xcurr < horzLeft && m_SortedEdges) ) break; - e = eNext; - } //end while - - if( horzEdge->nextInLML ) - { - if( horzEdge->outIdx >= 0 ) - AddOutPt( horzEdge, IntPoint(horzEdge->xtop, horzEdge->ytop)); - UpdateEdgeIntoAEL( horzEdge ); - } - else - { - if ( horzEdge->outIdx >= 0 ) - IntersectEdges( horzEdge, eMaxPair, - IntPoint(horzEdge->xtop, horzEdge->ycurr), ipBoth); - if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); - DeleteFromAEL(eMaxPair); - DeleteFromAEL(horzEdge); - } -} -//------------------------------------------------------------------------------ - -void Clipper::UpdateEdgeIntoAEL(TEdge *&e) -{ - if( !e->nextInLML ) throw - clipperException("UpdateEdgeIntoAEL: invalid call"); - TEdge* AelPrev = e->prevInAEL; - TEdge* AelNext = e->nextInAEL; - e->nextInLML->outIdx = e->outIdx; - if( AelPrev ) AelPrev->nextInAEL = e->nextInLML; - else m_ActiveEdges = e->nextInLML; - if( AelNext ) AelNext->prevInAEL = e->nextInLML; - e->nextInLML->side = e->side; - e->nextInLML->windDelta = e->windDelta; - e->nextInLML->windCnt = e->windCnt; - e->nextInLML->windCnt2 = e->windCnt2; - e = e->nextInLML; - e->prevInAEL = AelPrev; - e->nextInAEL = AelNext; - if( !NEAR_EQUAL(e->dx, HORIZONTAL) ) InsertScanbeam( e->ytop ); -} -//------------------------------------------------------------------------------ - -bool Clipper::ProcessIntersections(const long64 botY, const long64 topY) -{ - if( !m_ActiveEdges ) return true; - try { - BuildIntersectList(botY, topY); - if ( !m_IntersectNodes) return true; - if ( FixupIntersections() ) ProcessIntersectList(); - else return false; - } - catch(...) { - m_SortedEdges = 0; - DisposeIntersectNodes(); - throw clipperException("ProcessIntersections error"); - } - return true; -} -//------------------------------------------------------------------------------ - -void Clipper::DisposeIntersectNodes() -{ - while ( m_IntersectNodes ) - { - IntersectNode* iNode = m_IntersectNodes->next; - delete m_IntersectNodes; - m_IntersectNodes = iNode; - } -} -//------------------------------------------------------------------------------ - -void Clipper::BuildIntersectList(const long64 botY, const long64 topY) -{ - if ( !m_ActiveEdges ) return; - - //prepare for sorting ... - TEdge* e = m_ActiveEdges; - e->tmpX = TopX( *e, topY ); - m_SortedEdges = e; - m_SortedEdges->prevInSEL = 0; - e = e->nextInAEL; - while( e ) - { - e->prevInSEL = e->prevInAEL; - e->prevInSEL->nextInSEL = e; - e->nextInSEL = 0; - e->tmpX = TopX( *e, topY ); - e = e->nextInAEL; - } - - //bubblesort ... - bool isModified = true; - while( isModified && m_SortedEdges ) - { - isModified = false; - e = m_SortedEdges; - while( e->nextInSEL ) - { - TEdge *eNext = e->nextInSEL; - IntPoint pt; - if(e->tmpX > eNext->tmpX && - IntersectPoint(*e, *eNext, pt, m_UseFullRange)) - { - if (pt.Y > botY) - { - pt.Y = botY; - pt.X = TopX(*e, pt.Y); - } - AddIntersectNode( e, eNext, pt ); - SwapPositionsInSEL(e, eNext); - isModified = true; - } - else - e = eNext; - } - if( e->prevInSEL ) e->prevInSEL->nextInSEL = 0; - else break; - } - m_SortedEdges = 0; -} -//------------------------------------------------------------------------------ - -bool ProcessParam1BeforeParam2(IntersectNode &node1, IntersectNode &node2) -{ - bool result; - if (node1.pt.Y == node2.pt.Y) - { - if (node1.edge1 == node2.edge1 || node1.edge2 == node2.edge1) - { - result = node2.pt.X > node1.pt.X; - return node2.edge1->dx > 0 ? !result : result; - } - else if (node1.edge1 == node2.edge2 || node1.edge2 == node2.edge2) - { - result = node2.pt.X > node1.pt.X; - return node2.edge2->dx > 0 ? !result : result; - } - else return node2.pt.X > node1.pt.X; - } - else return node1.pt.Y > node2.pt.Y; -} -//------------------------------------------------------------------------------ - -void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt) -{ - IntersectNode* newNode = new IntersectNode; - newNode->edge1 = e1; - newNode->edge2 = e2; - newNode->pt = pt; - newNode->next = 0; - if( !m_IntersectNodes ) m_IntersectNodes = newNode; - else if( ProcessParam1BeforeParam2(*newNode, *m_IntersectNodes) ) - { - newNode->next = m_IntersectNodes; - m_IntersectNodes = newNode; - } - else - { - IntersectNode* iNode = m_IntersectNodes; - while( iNode->next && ProcessParam1BeforeParam2(*iNode->next, *newNode) ) - iNode = iNode->next; - newNode->next = iNode->next; - iNode->next = newNode; - } -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessIntersectList() -{ - while( m_IntersectNodes ) - { - IntersectNode* iNode = m_IntersectNodes->next; - { - IntersectEdges( m_IntersectNodes->edge1 , - m_IntersectNodes->edge2 , m_IntersectNodes->pt, ipBoth ); - SwapPositionsInAEL( m_IntersectNodes->edge1 , m_IntersectNodes->edge2 ); - } - delete m_IntersectNodes; - m_IntersectNodes = iNode; - } -} -//------------------------------------------------------------------------------ - -void Clipper::DoMaxima(TEdge *e, long64 topY) -{ - TEdge* eMaxPair = GetMaximaPair(e); - long64 X = e->xtop; - TEdge* eNext = e->nextInAEL; - while( eNext != eMaxPair ) - { - if (!eNext) throw clipperException("DoMaxima error"); - IntersectEdges( e, eNext, IntPoint(X, topY), ipBoth ); - eNext = eNext->nextInAEL; - } - if( e->outIdx < 0 && eMaxPair->outIdx < 0 ) - { - DeleteFromAEL( e ); - DeleteFromAEL( eMaxPair ); - } - else if( e->outIdx >= 0 && eMaxPair->outIdx >= 0 ) - { - IntersectEdges( e, eMaxPair, IntPoint(X, topY), ipNone ); - } - else throw clipperException("DoMaxima error"); -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY) -{ - TEdge* e = m_ActiveEdges; - while( e ) - { - //1. process maxima, treating them as if they're 'bent' horizontal edges, - // but exclude maxima with horizontal edges. nb: e can't be a horizontal. - if( IsMaxima(e, topY) && !NEAR_EQUAL(GetMaximaPair(e)->dx, HORIZONTAL) ) - { - //'e' might be removed from AEL, as may any following edges so ... - TEdge* ePrior = e->prevInAEL; - DoMaxima(e, topY); - if( !ePrior ) e = m_ActiveEdges; - else e = ePrior->nextInAEL; - } - else - { - //2. promote horizontal edges, otherwise update xcurr and ycurr ... - if( IsIntermediate(e, topY) && NEAR_EQUAL(e->nextInLML->dx, HORIZONTAL) ) - { - if (e->outIdx >= 0) - { - AddOutPt(e, IntPoint(e->xtop, e->ytop)); - - for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) - { - IntPoint pt, pt2; - HorzJoinRec* hj = m_HorizJoins[i]; - if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), - IntPoint(hj->edge->xtop, hj->edge->ytop), - IntPoint(e->nextInLML->xbot, e->nextInLML->ybot), - IntPoint(e->nextInLML->xtop, e->nextInLML->ytop), pt, pt2)) - AddJoin(hj->edge, e->nextInLML, hj->savedIdx, e->outIdx); - } - - AddHorzJoin(e->nextInLML, e->outIdx); - } - UpdateEdgeIntoAEL(e); - AddEdgeToSEL(e); - } else - { - //this just simplifies horizontal processing ... - e->xcurr = TopX( *e, topY ); - e->ycurr = topY; - } - e = e->nextInAEL; - } - } - - //3. Process horizontals at the top of the scanbeam ... - ProcessHorizontals(); - - //4. Promote intermediate vertices ... - e = m_ActiveEdges; - while( e ) - { - if( IsIntermediate( e, topY ) ) - { - if( e->outIdx >= 0 ) AddOutPt(e, IntPoint(e->xtop,e->ytop)); - UpdateEdgeIntoAEL(e); - - //if output polygons share an edge, they'll need joining later ... - if (e->outIdx >= 0 && e->prevInAEL && e->prevInAEL->outIdx >= 0 && - e->prevInAEL->xcurr == e->xbot && e->prevInAEL->ycurr == e->ybot && - SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), - IntPoint(e->xbot,e->ybot), - IntPoint(e->prevInAEL->xtop, e->prevInAEL->ytop), m_UseFullRange)) - { - AddOutPt(e->prevInAEL, IntPoint(e->xbot, e->ybot)); - AddJoin(e, e->prevInAEL); - } - else if (e->outIdx >= 0 && e->nextInAEL && e->nextInAEL->outIdx >= 0 && - e->nextInAEL->ycurr > e->nextInAEL->ytop && - e->nextInAEL->ycurr <= e->nextInAEL->ybot && - e->nextInAEL->xcurr == e->xbot && e->nextInAEL->ycurr == e->ybot && - SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), - IntPoint(e->xbot,e->ybot), - IntPoint(e->nextInAEL->xtop, e->nextInAEL->ytop), m_UseFullRange)) - { - AddOutPt(e->nextInAEL, IntPoint(e->xbot, e->ybot)); - AddJoin(e, e->nextInAEL); - } - } - e = e->nextInAEL; - } -} -//------------------------------------------------------------------------------ - -void Clipper::FixupOutPolygon(OutRec &outRec) -{ - //FixupOutPolygon() - removes duplicate points and simplifies consecutive - //parallel edges by removing the middle vertex. - OutPt *lastOK = 0; - outRec.pts = outRec.bottomPt; - OutPt *pp = outRec.bottomPt; - - for (;;) - { - if (pp->prev == pp || pp->prev == pp->next ) - { - DisposeOutPts(pp); - outRec.pts = 0; - outRec.bottomPt = 0; - return; - } - //test for duplicate points and for same slope (cross-product) ... - if ( PointsEqual(pp->pt, pp->next->pt) || - SlopesEqual(pp->prev->pt, pp->pt, pp->next->pt, m_UseFullRange) ) - { - lastOK = 0; - OutPt *tmp = pp; - if (pp == outRec.bottomPt) - outRec.bottomPt = 0; //flags need for updating - pp->prev->next = pp->next; - pp->next->prev = pp->prev; - pp = pp->prev; - delete tmp; - } - else if (pp == lastOK) break; - else - { - if (!lastOK) lastOK = pp; - pp = pp->next; - } - } - if (!outRec.bottomPt) { - outRec.bottomPt = GetBottomPt(pp); - outRec.bottomPt->idx = outRec.idx; - outRec.pts = outRec.bottomPt; - } -} -//------------------------------------------------------------------------------ - -void Clipper::BuildResult(Polygons &polys) -{ - int k = 0; - polys.resize(m_PolyOuts.size()); - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - if (m_PolyOuts[i]->pts) - { - Polygon* pg = &polys[k]; - pg->clear(); - OutPt* p = m_PolyOuts[i]->pts; - do - { - pg->push_back(p->pt); - p = p->next; - } while (p != m_PolyOuts[i]->pts); - //make sure each polygon has at least 3 vertices ... - if (pg->size() < 3) pg->clear(); else k++; - } - } - polys.resize(k); -} -//------------------------------------------------------------------------------ - -void Clipper::BuildResultEx(ExPolygons &polys) -{ - PolyOutList::size_type i = 0; - int k = 0; - polys.resize(0); - polys.reserve(m_PolyOuts.size()); - while (i < m_PolyOuts.size() && m_PolyOuts[i]->pts) - { - ExPolygon epg; - OutPt* p = m_PolyOuts[i]->pts; - do { - epg.outer.push_back(p->pt); - p = p->next; - } while (p != m_PolyOuts[i]->pts); - i++; - //make sure polygons have at least 3 vertices ... - if (epg.outer.size() < 3) continue; - while (i < m_PolyOuts.size() - && m_PolyOuts[i]->pts && m_PolyOuts[i]->isHole) - { - Polygon pg; - p = m_PolyOuts[i]->pts; - do { - pg.push_back(p->pt); - p = p->next; - } while (p != m_PolyOuts[i]->pts); - epg.holes.push_back(pg); - i++; - } - polys.push_back(epg); - k++; - } - polys.resize(k); -} -//------------------------------------------------------------------------------ - -void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2) -{ - TEdge *e1 = int1.edge1; - TEdge *e2 = int1.edge2; - IntPoint p = int1.pt; - - int1.edge1 = int2.edge1; - int1.edge2 = int2.edge2; - int1.pt = int2.pt; - - int2.edge1 = e1; - int2.edge2 = e2; - int2.pt = p; -} -//------------------------------------------------------------------------------ - -bool Clipper::FixupIntersections() -{ - if ( !m_IntersectNodes->next ) return true; - - CopyAELToSEL(); - IntersectNode *int1 = m_IntersectNodes; - IntersectNode *int2 = m_IntersectNodes->next; - while (int2) - { - TEdge *e1 = int1->edge1; - TEdge *e2; - if (e1->prevInSEL == int1->edge2) e2 = e1->prevInSEL; - else if (e1->nextInSEL == int1->edge2) e2 = e1->nextInSEL; - else - { - //The current intersection is out of order, so try and swap it with - //a subsequent intersection ... - while (int2) - { - if (int2->edge1->nextInSEL == int2->edge2 || - int2->edge1->prevInSEL == int2->edge2) break; - else int2 = int2->next; - } - if ( !int2 ) return false; //oops!!! - - //found an intersect node that can be swapped ... - SwapIntersectNodes(*int1, *int2); - e1 = int1->edge1; - e2 = int1->edge2; - } - SwapPositionsInSEL(e1, e2); - int1 = int1->next; - int2 = int1->next; - } - - m_SortedEdges = 0; - - //finally, check the last intersection too ... - return (int1->edge1->prevInSEL == int1->edge2 || - int1->edge1->nextInSEL == int1->edge2); -} -//------------------------------------------------------------------------------ - -bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) -{ - return e2.xcurr == e1.xcurr ? e2.dx > e1.dx : e2.xcurr < e1.xcurr; -} -//------------------------------------------------------------------------------ - -void Clipper::InsertEdgeIntoAEL(TEdge *edge) -{ - edge->prevInAEL = 0; - edge->nextInAEL = 0; - if( !m_ActiveEdges ) - { - m_ActiveEdges = edge; - } - else if( E2InsertsBeforeE1(*m_ActiveEdges, *edge) ) - { - edge->nextInAEL = m_ActiveEdges; - m_ActiveEdges->prevInAEL = edge; - m_ActiveEdges = edge; - } else - { - TEdge* e = m_ActiveEdges; - while( e->nextInAEL && !E2InsertsBeforeE1(*e->nextInAEL , *edge) ) - e = e->nextInAEL; - edge->nextInAEL = e->nextInAEL; - if( e->nextInAEL ) e->nextInAEL->prevInAEL = edge; - edge->prevInAEL = e; - e->nextInAEL = edge; - } -} -//---------------------------------------------------------------------- - -void Clipper::DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt) -{ - AddOutPt(edge1, pt); - SwapSides(*edge1, *edge2); - SwapPolyIndexes(*edge1, *edge2); -} -//---------------------------------------------------------------------- - -void Clipper::DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt) -{ - AddOutPt(edge2, pt); - SwapSides(*edge1, *edge2); - SwapPolyIndexes(*edge1, *edge2); -} -//---------------------------------------------------------------------- - -void Clipper::DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt) -{ - AddOutPt(edge1, pt); - AddOutPt(edge2, pt); - SwapSides( *edge1 , *edge2 ); - SwapPolyIndexes( *edge1 , *edge2 ); -} -//---------------------------------------------------------------------- - -void Clipper::CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2) -{ - //when a polygon is split into 2 polygons, make sure any holes the original - //polygon contained link to the correct polygon ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - { - OutRec *orec = m_PolyOuts[i]; - if (orec->isHole && orec->bottomPt && orec->FirstLeft == outRec1 && - !PointInPolygon(orec->bottomPt->pt, outRec1->pts, m_UseFullRange)) - orec->FirstLeft = outRec2; - } -} -//---------------------------------------------------------------------- - -void Clipper::CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2) -{ - //if a hole is owned by outRec2 then make it owned by outRec1 ... - for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) - if (m_PolyOuts[i]->isHole && m_PolyOuts[i]->bottomPt && - m_PolyOuts[i]->FirstLeft == outRec2) - m_PolyOuts[i]->FirstLeft = outRec1; -} -//---------------------------------------------------------------------- - -void Clipper::JoinCommonEdges(bool fixHoleLinkages) -{ - for (JoinList::size_type i = 0; i < m_Joins.size(); i++) - { - JoinRec* j = m_Joins[i]; - OutRec *outRec1 = m_PolyOuts[j->poly1Idx]; - OutPt *pp1a = outRec1->pts; - OutRec *outRec2 = m_PolyOuts[j->poly2Idx]; - OutPt *pp2a = outRec2->pts; - IntPoint pt1 = j->pt2a, pt2 = j->pt2b; - IntPoint pt3 = j->pt1a, pt4 = j->pt1b; - if (!FindSegment(pp1a, pt1, pt2)) continue; - if (j->poly1Idx == j->poly2Idx) - { - //we're searching the same polygon for overlapping segments so - //segment 2 mustn't be the same as segment 1 ... - pp2a = pp1a->next; - if (!FindSegment(pp2a, pt3, pt4) || (pp2a == pp1a)) continue; - } - else if (!FindSegment(pp2a, pt3, pt4)) continue; - - if (!GetOverlapSegment(pt1, pt2, pt3, pt4, pt1, pt2)) continue; - - OutPt *p1, *p2, *p3, *p4; - OutPt *prev = pp1a->prev; - //get p1 & p2 polypts - the overlap start & endpoints on poly1 - if (PointsEqual(pp1a->pt, pt1)) p1 = pp1a; - else if (PointsEqual(prev->pt, pt1)) p1 = prev; - else p1 = InsertPolyPtBetween(pp1a, prev, pt1); - - if (PointsEqual(pp1a->pt, pt2)) p2 = pp1a; - else if (PointsEqual(prev->pt, pt2)) p2 = prev; - else if ((p1 == pp1a) || (p1 == prev)) - p2 = InsertPolyPtBetween(pp1a, prev, pt2); - else if (Pt3IsBetweenPt1AndPt2(pp1a->pt, p1->pt, pt2)) - p2 = InsertPolyPtBetween(pp1a, p1, pt2); else - p2 = InsertPolyPtBetween(p1, prev, pt2); - - //get p3 & p4 polypts - the overlap start & endpoints on poly2 - prev = pp2a->prev; - if (PointsEqual(pp2a->pt, pt1)) p3 = pp2a; - else if (PointsEqual(prev->pt, pt1)) p3 = prev; - else p3 = InsertPolyPtBetween(pp2a, prev, pt1); - - if (PointsEqual(pp2a->pt, pt2)) p4 = pp2a; - else if (PointsEqual(prev->pt, pt2)) p4 = prev; - else if ((p3 == pp2a) || (p3 == prev)) - p4 = InsertPolyPtBetween(pp2a, prev, pt2); - else if (Pt3IsBetweenPt1AndPt2(pp2a->pt, p3->pt, pt2)) - p4 = InsertPolyPtBetween(pp2a, p3, pt2); else - p4 = InsertPolyPtBetween(p3, prev, pt2); - - //p1.pt == p3.pt and p2.pt == p4.pt so join p1 to p3 and p2 to p4 ... - if (p1->next == p2 && p3->prev == p4) - { - p1->next = p3; - p3->prev = p1; - p2->prev = p4; - p4->next = p2; - } - else if (p1->prev == p2 && p3->next == p4) - { - p1->prev = p3; - p3->next = p1; - p2->next = p4; - p4->prev = p2; - } - else - continue; //an orientation is probably wrong - - if (j->poly2Idx == j->poly1Idx) - { - //instead of joining two polygons, we've just created a new one by - //splitting one polygon into two. - outRec1->pts = GetBottomPt(p1); - outRec1->bottomPt = outRec1->pts; - outRec1->bottomPt->idx = outRec1->idx; - outRec2 = CreateOutRec(); - m_PolyOuts.push_back(outRec2); - outRec2->idx = (int)m_PolyOuts.size()-1; - j->poly2Idx = outRec2->idx; - outRec2->pts = GetBottomPt(p2); - outRec2->bottomPt = outRec2->pts; - outRec2->bottomPt->idx = outRec2->idx; - - if (PointInPolygon(outRec2->pts->pt, outRec1->pts, m_UseFullRange)) - { - //outRec2 is contained by outRec1 ... - outRec2->isHole = !outRec1->isHole; - outRec2->FirstLeft = outRec1; - if (outRec2->isHole == - (m_ReverseOutput ^ Orientation(outRec2, m_UseFullRange))) - ReversePolyPtLinks(*outRec2->pts); - } else if (PointInPolygon(outRec1->pts->pt, outRec2->pts, m_UseFullRange)) - { - //outRec1 is contained by outRec2 ... - outRec2->isHole = outRec1->isHole; - outRec1->isHole = !outRec2->isHole; - outRec2->FirstLeft = outRec1->FirstLeft; - outRec1->FirstLeft = outRec2; - if (outRec1->isHole == - (m_ReverseOutput ^ Orientation(outRec1, m_UseFullRange))) - ReversePolyPtLinks(*outRec1->pts); - //make sure any contained holes now link to the correct polygon ... - if (fixHoleLinkages) CheckHoleLinkages1(outRec1, outRec2); - } else - { - outRec2->isHole = outRec1->isHole; - outRec2->FirstLeft = outRec1->FirstLeft; - //make sure any contained holes now link to the correct polygon ... - if (fixHoleLinkages) CheckHoleLinkages1(outRec1, outRec2); - } - - //now fixup any subsequent joins that match this polygon - for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) - { - JoinRec* j2 = m_Joins[k]; - if (j2->poly1Idx == j->poly1Idx && PointIsVertex(j2->pt1a, p2)) - j2->poly1Idx = j->poly2Idx; - if (j2->poly2Idx == j->poly1Idx && PointIsVertex(j2->pt2a, p2)) - j2->poly2Idx = j->poly2Idx; - } - - //now cleanup redundant edges too ... - FixupOutPolygon(*outRec1); - FixupOutPolygon(*outRec2); - - if (Orientation(outRec1, m_UseFullRange) != (Area(*outRec1, m_UseFullRange) > 0)) - DisposeBottomPt(*outRec1); - if (Orientation(outRec2, m_UseFullRange) != (Area(*outRec2, m_UseFullRange) > 0)) - DisposeBottomPt(*outRec2); - - } else - { - //joined 2 polygons together ... - - //make sure any holes contained by outRec2 now link to outRec1 ... - if (fixHoleLinkages) CheckHoleLinkages2(outRec1, outRec2); - - //now cleanup redundant edges too ... - FixupOutPolygon(*outRec1); - - if (outRec1->pts) - { - outRec1->isHole = !Orientation(outRec1, m_UseFullRange); - if (outRec1->isHole && !outRec1->FirstLeft) - outRec1->FirstLeft = outRec2->FirstLeft; - } - - //delete the obsolete pointer ... - int OKIdx = outRec1->idx; - int ObsoleteIdx = outRec2->idx; - outRec2->pts = 0; - outRec2->bottomPt = 0; - outRec2->AppendLink = outRec1; - - //now fixup any subsequent Joins that match this polygon - for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) - { - JoinRec* j2 = m_Joins[k]; - if (j2->poly1Idx == ObsoleteIdx) j2->poly1Idx = OKIdx; - if (j2->poly2Idx == ObsoleteIdx) j2->poly2Idx = OKIdx; - } - } - } -} -//------------------------------------------------------------------------------ - -void ReversePolygon(Polygon& p) -{ - std::reverse(p.begin(), p.end()); -} -//------------------------------------------------------------------------------ - -void ReversePolygons(Polygons& p) -{ - for (Polygons::size_type i = 0; i < p.size(); ++i) - ReversePolygon(p[i]); -} - -//------------------------------------------------------------------------------ -// OffsetPolygon functions ... -//------------------------------------------------------------------------------ - -struct DoublePoint -{ - double X; - double Y; - DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} -}; -//------------------------------------------------------------------------------ - -Polygon BuildArc(const IntPoint &pt, - const double a1, const double a2, const double r) -{ - long64 steps = std::max(6, int(std::sqrt(std::fabs(r)) * std::fabs(a2 - a1))); - if (steps > 0x100000) steps = 0x100000; - int n = (unsigned)steps; - Polygon result(n); - double da = (a2 - a1) / (n -1); - double a = a1; - for (int i = 0; i < n; ++i) - { - result[i].X = pt.X + Round(std::cos(a)*r); - result[i].Y = pt.Y + Round(std::sin(a)*r); - a += da; - } - return result; -} -//------------------------------------------------------------------------------ - -DoublePoint GetUnitNormal( const IntPoint &pt1, const IntPoint &pt2) -{ - if(pt2.X == pt1.X && pt2.Y == pt1.Y) - return DoublePoint(0, 0); - - double dx = (double)(pt2.X - pt1.X); - double dy = (double)(pt2.Y - pt1.Y); - double f = 1 *1.0/ std::sqrt( dx*dx + dy*dy ); - dx *= f; - dy *= f; - return DoublePoint(dy, -dx); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -class PolyOffsetBuilder -{ -private: - Polygons m_p; - Polygon* m_curr_poly; - std::vector normals; - double m_delta, m_RMin, m_R; - size_t m_i, m_j, m_k; - static const int buffLength = 128; - JoinType m_jointype; - -public: - -PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys, - double delta, JoinType jointype, double MiterLimit) -{ - //nb precondition - out_polys != ptsin_polys - if (NEAR_ZERO(delta)) - { - out_polys = in_polys; - return; - } - - this->m_p = in_polys; - this->m_delta = delta; - this->m_jointype = jointype; - if (MiterLimit <= 1) MiterLimit = 1; - m_RMin = 2/(MiterLimit*MiterLimit); - - double deltaSq = delta*delta; - out_polys.clear(); - out_polys.resize(in_polys.size()); - for (m_i = 0; m_i < in_polys.size(); m_i++) - { - m_curr_poly = &out_polys[m_i]; - size_t len = in_polys[m_i].size(); - if (len > 1 && m_p[m_i][0].X == m_p[m_i][len - 1].X && - m_p[m_i][0].Y == m_p[m_i][len-1].Y) len--; - - //when 'shrinking' polygons - to minimize artefacts - //strip those polygons that have an area < pi * delta^2 ... - double a1 = Area(in_polys[m_i]); - if (delta < 0) { if (a1 > 0 && a1 < deltaSq *pi) len = 0; } - else if (a1 < 0 && -a1 < deltaSq *pi) len = 0; //holes have neg. area - - if (len == 0 || (len < 3 && delta <= 0)) - continue; - else if (len == 1) - { - Polygon arc; - arc = BuildArc(in_polys[m_i][len-1], 0, 2 * pi, delta); - out_polys[m_i] = arc; - continue; - } - - //build normals ... - normals.clear(); - normals.resize(len); - normals[len-1] = GetUnitNormal(in_polys[m_i][len-1], in_polys[m_i][0]); - for (m_j = 0; m_j < len -1; ++m_j) - normals[m_j] = GetUnitNormal(in_polys[m_i][m_j], in_polys[m_i][m_j+1]); - - m_k = len -1; - for (m_j = 0; m_j < len; ++m_j) - { - switch (jointype) - { - case jtMiter: - { - m_R = 1 + (normals[m_j].X*normals[m_k].X + - normals[m_j].Y*normals[m_k].Y); - if (m_R >= m_RMin) DoMiter(); else DoSquare(MiterLimit); - break; - } - case jtSquare: DoSquare(); break; - case jtRound: DoRound(); break; - } - m_k = m_j; - } - } - - //finally, clean up untidy corners using Clipper ... - Clipper clpr; - clpr.AddPolygons(out_polys, ptSubject); - if (delta > 0) - { - if (!clpr.Execute(ctUnion, out_polys, pftPositive, pftPositive)) - out_polys.clear(); - } - else - { - IntRect r = clpr.GetBounds(); - Polygon outer(4); - outer[0] = IntPoint(r.left - 10, r.bottom + 10); - outer[1] = IntPoint(r.right + 10, r.bottom + 10); - outer[2] = IntPoint(r.right + 10, r.top - 10); - outer[3] = IntPoint(r.left - 10, r.top - 10); - - clpr.AddPolygon(outer, ptSubject); - if (clpr.Execute(ctUnion, out_polys, pftNegative, pftNegative)) - { - out_polys.erase(out_polys.begin()); - ReversePolygons(out_polys); - - } else - out_polys.clear(); - } -} -//------------------------------------------------------------------------------ - -private: - -void AddPoint(const IntPoint& pt) -{ - Polygon::size_type len = m_curr_poly->size(); - if (len == m_curr_poly->capacity()) - m_curr_poly->reserve(len + buffLength); - m_curr_poly->push_back(pt); -} -//------------------------------------------------------------------------------ - -void DoSquare(double mul = 1.0) -{ - IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), - (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); - IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), - (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); - if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) - { - double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); - double a2 = std::atan2(-normals[m_j].Y, -normals[m_j].X); - a1 = std::fabs(a2 - a1); - if (a1 > pi) a1 = pi * 2 - a1; - double dx = std::tan((pi - a1)/4) * std::fabs(m_delta * mul); - pt1 = IntPoint((long64)(pt1.X -normals[m_k].Y * dx), - (long64)(pt1.Y + normals[m_k].X * dx)); - AddPoint(pt1); - pt2 = IntPoint((long64)(pt2.X + normals[m_j].Y * dx), - (long64)(pt2.Y -normals[m_j].X * dx)); - AddPoint(pt2); - } - else - { - AddPoint(pt1); - AddPoint(m_p[m_i][m_j]); - AddPoint(pt2); - } -} -//------------------------------------------------------------------------------ - -void DoMiter() -{ - if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) - { - double q = m_delta / m_R; - AddPoint(IntPoint((long64)Round(m_p[m_i][m_j].X + - (normals[m_k].X + normals[m_j].X) * q), - (long64)Round(m_p[m_i][m_j].Y + (normals[m_k].Y + normals[m_j].Y) * q))); - } - else - { - IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * - m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); - IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * - m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); - AddPoint(pt1); - AddPoint(m_p[m_i][m_j]); - AddPoint(pt2); - } -} -//------------------------------------------------------------------------------ - -void DoRound() -{ - IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), - (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); - IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), - (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); - AddPoint(pt1); - //round off reflex angles (ie > 180 deg) unless almost flat (ie < ~10deg). - if ((normals[m_k].X*normals[m_j].Y - normals[m_j].X*normals[m_k].Y) * m_delta >= 0) - { - if (normals[m_j].X * normals[m_k].X + normals[m_j].Y * normals[m_k].Y < 0.985) - { - double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); - double a2 = std::atan2(normals[m_j].Y, normals[m_j].X); - if (m_delta > 0 && a2 < a1) a2 += pi *2; - else if (m_delta < 0 && a2 > a1) a2 -= pi *2; - Polygon arc = BuildArc(m_p[m_i][m_j], a1, a2, m_delta); - for (Polygon::size_type m = 0; m < arc.size(); m++) - AddPoint(arc[m]); - } - } - else - AddPoint(m_p[m_i][m_j]); - AddPoint(pt2); -} -//-------------------------------------------------------------------------- - -}; //end PolyOffsetBuilder - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, - double delta, JoinType jointype, double MiterLimit) -{ - if (&out_polys == &in_polys) - { - Polygons poly2(in_polys); - PolyOffsetBuilder(poly2, out_polys, delta, jointype, MiterLimit); - } - else PolyOffsetBuilder(in_polys, out_polys, delta, jointype, MiterLimit); -} -//------------------------------------------------------------------------------ - -void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType) -{ - Clipper c; - c.AddPolygon(in_poly, ptSubject); - c.Execute(ctUnion, out_polys, fillType, fillType); -} -//------------------------------------------------------------------------------ - -void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType) -{ - Clipper c; - c.AddPolygons(in_polys, ptSubject); - c.Execute(ctUnion, out_polys, fillType, fillType); -} -//------------------------------------------------------------------------------ - -void SimplifyPolygons(Polygons &polys, PolyFillType fillType) -{ - SimplifyPolygons(polys, polys, fillType); -} -//------------------------------------------------------------------------------ - -std::ostream& operator <<(std::ostream &s, IntPoint& p) -{ - s << p.X << ' ' << p.Y << "\n"; - return s; -} -//------------------------------------------------------------------------------ - -std::ostream& operator <<(std::ostream &s, Polygon &p) -{ - for (Polygon::size_type i = 0; i < p.size(); i++) - s << p[i]; - s << "\n"; - return s; -} -//------------------------------------------------------------------------------ - -std::ostream& operator <<(std::ostream &s, Polygons &p) -{ - for (Polygons::size_type i = 0; i < p.size(); i++) - s << p[i]; - s << "\n"; - return s; -} -//------------------------------------------------------------------------------ - -} //ClipperLib namespace +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 4.8.8 * +* Date : 30 August 2012 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2012 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24–28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +/******************************************************************************* +* * +* This is a translation of the Delphi Clipper library and the naming style * +* used has retained a Delphi flavour. * +* * +*******************************************************************************/ + +#include "clipper.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace ClipperLib { + +static long64 const loRange = 0x3FFFFFFF; +static long64 const hiRange = 0x3FFFFFFFFFFFFFFFLL; +static double const pi = 3.141592653589793238; +enum Direction { dRightToLeft, dLeftToRight }; + +#define HORIZONTAL (-1.0E+40) +#define TOLERANCE (1.0e-20) +#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) +#define NEAR_EQUAL(a, b) NEAR_ZERO((a) - (b)) + +inline long64 Abs(long64 val) +{ + return val < 0 ? -val : val; +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Int128 class (enables safe math on signed 64bit integers) +// eg Int128 val1((long64)9223372036854775807); //ie 2^63 -1 +// Int128 val2((long64)9223372036854775807); +// Int128 val3 = val1 * val2; +// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37) +//------------------------------------------------------------------------------ + +class Int128 +{ + public: + + Int128(long64 _lo = 0) + { + lo = _lo; + if (lo < 0) hi = -1; else hi = 0; + } + + Int128(const Int128 &val): hi(val.hi), lo(val.lo){} + + long64 operator = (const long64 &val) + { + lo = val; + if (lo < 0) hi = -1; else hi = 0; + return val; + } + + bool operator == (const Int128 &val) const + {return (hi == val.hi && lo == val.lo);} + + bool operator != (const Int128 &val) const + { return !(*this == val);} + + bool operator > (const Int128 &val) const + { + if (hi != val.hi) + return hi > val.hi; + else + return lo > val.lo; + } + + bool operator < (const Int128 &val) const + { + if (hi != val.hi) + return hi < val.hi; + else + return lo < val.lo; + } + + bool operator >= (const Int128 &val) const + { return !(*this < val);} + + bool operator <= (const Int128 &val) const + { return !(*this > val);} + + Int128& operator += (const Int128 &rhs) + { + hi += rhs.hi; + lo += rhs.lo; + if (ulong64(lo) < ulong64(rhs.lo)) hi++; + return *this; + } + + Int128 operator + (const Int128 &rhs) const + { + Int128 result(*this); + result+= rhs; + return result; + } + + Int128& operator -= (const Int128 &rhs) + { + Int128 tmp(rhs); + Negate(tmp); + *this += tmp; + return *this; + } + + //Int128 operator -() const + //{ + // Int128 result(*this); + // if (result.lo == 0) { + // if (result.hi != 0) result.hi = -1; + // } + // else { + // result.lo = -result.lo; + // result.hi = ~result.hi; + // } + // return result; + //} + + Int128 operator - (const Int128 &rhs) const + { + Int128 result(*this); + result -= rhs; + return result; + } + + Int128 operator * (const Int128 &rhs) const + { + if ( !(hi == 0 || hi == -1) || !(rhs.hi == 0 || rhs.hi == -1)) + throw "Int128 operator*: overflow error"; + bool negate = (hi < 0) != (rhs.hi < 0); + + Int128 tmp(*this); + if (tmp.hi < 0) Negate(tmp); + ulong64 int1Hi = ulong64(tmp.lo) >> 32; + ulong64 int1Lo = ulong64(tmp.lo & 0xFFFFFFFF); + + tmp = rhs; + if (tmp.hi < 0) Negate(tmp); + ulong64 int2Hi = ulong64(tmp.lo) >> 32; + ulong64 int2Lo = ulong64(tmp.lo & 0xFFFFFFFF); + + //nb: see comments in clipper.pas + ulong64 a = int1Hi * int2Hi; + ulong64 b = int1Lo * int2Lo; + ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; + + tmp.hi = long64(a + (c >> 32)); + tmp.lo = long64(c << 32); + tmp.lo += long64(b); + if (ulong64(tmp.lo) < b) tmp.hi++; + if (negate) Negate(tmp); + return tmp; + } + + Int128 operator/ (const Int128 &rhs) const + { + if (rhs.lo == 0 && rhs.hi == 0) + throw "Int128 operator/: divide by zero"; + bool negate = (rhs.hi < 0) != (hi < 0); + Int128 result(*this), denom(rhs); + if (result.hi < 0) Negate(result); + if (denom.hi < 0) Negate(denom); + if (denom > result) return Int128(0); //result is only a fraction of 1 + Negate(denom); + + Int128 p(0); + for (int i = 0; i < 128; ++i) + { + p.hi = p.hi << 1; + if (p.lo < 0) p.hi++; + p.lo = long64(p.lo) << 1; + if (result.hi < 0) p.lo++; + result.hi = result.hi << 1; + if (result.lo < 0) result.hi++; + result.lo = long64(result.lo) << 1; + Int128 p2(p); + p += denom; + if (p.hi < 0) p = p2; + else result.lo++; + } + if (negate) Negate(result); + return result; + } + + double AsDouble() const + { + const double shift64 = 18446744073709551616.0; //2^64 + const double bit64 = 9223372036854775808.0; + if (hi < 0) + { + Int128 tmp(*this); + Negate(tmp); + if (tmp.lo < 0) + return (double)tmp.lo - bit64 - tmp.hi * shift64; + else + return -(double)tmp.lo - tmp.hi * shift64; + } + else if (lo < 0) + return -(double)lo + bit64 + hi * shift64; + else + return (double)lo + (double)hi * shift64; + } + + //for bug testing ... + //std::string AsString() const + //{ + // std::string result; + // unsigned char r = 0; + // Int128 tmp(0), val(*this); + // if (hi < 0) Negate(val); + // result.resize(50); + // std::string::size_type i = result.size() -1; + // while (val.hi != 0 || val.lo != 0) + // { + // Div10(val, tmp, r); + // result[i--] = char('0' + r); + // val = tmp; + // } + // if (hi < 0) result[i--] = '-'; + // result.erase(0,i+1); + // if (result.size() == 0) result = "0"; + // return result; + //} + +private: + long64 hi; + long64 lo; + + static void Negate(Int128 &val) + { + if (val.lo == 0) { + if (val.hi != 0) val.hi = -val.hi;; + } + else { + val.lo = -val.lo; + val.hi = ~val.hi; + } + } + + //debugging only ... + //void Div10(const Int128 val, Int128& result, unsigned char & remainder) const + //{ + // remainder = 0; + // result = 0; + // for (int i = 63; i >= 0; --i) + // { + // if ((val.hi & ((long64)1 << i)) != 0) + // remainder = char((remainder * 2) + 1); else + // remainder *= char(2); + // if (remainder >= 10) + // { + // result.hi += ((long64)1 << i); + // remainder -= char(10); + // } + // } + // for (int i = 63; i >= 0; --i) + // { + // if ((val.lo & ((long64)1 << i)) != 0) + // remainder = char((remainder * 2) + 1); else + // remainder *= char(2); + // if (remainder >= 10) + // { + // result.lo += ((long64)1 << i); + // remainder -= char(10); + // } + // } + //} +}; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +bool FullRangeNeeded(const Polygon &pts) +{ + bool result = false; + for (Polygon::size_type i = 0; i < pts.size(); ++i) + { + if (Abs(pts[i].X) > hiRange || Abs(pts[i].Y) > hiRange) + throw "Coordinate exceeds range bounds."; + else if (Abs(pts[i].X) > loRange || Abs(pts[i].Y) > loRange) + result = true; + } + return result; +} +//------------------------------------------------------------------------------ + +bool Orientation(const Polygon &poly) +{ + int highI = (int)poly.size() -1; + if (highI < 2) return false; + + int j = 0, jplus, jminus; + for (int i = 0; i <= highI; ++i) + { + if (poly[i].Y < poly[j].Y) continue; + if ((poly[i].Y > poly[j].Y || poly[i].X < poly[j].X)) j = i; + }; + if (j == highI) jplus = 0; + else jplus = j +1; + if (j == 0) jminus = highI; + else jminus = j -1; + + IntPoint vec1, vec2; + //get cross product of vectors of the edges adjacent to highest point ... + vec1.X = poly[j].X - poly[jminus].X; + vec1.Y = poly[j].Y - poly[jminus].Y; + vec2.X = poly[jplus].X - poly[j].X; + vec2.Y = poly[jplus].Y - poly[j].Y; + + if (Abs(vec1.X) > loRange || Abs(vec1.Y) > loRange || + Abs(vec2.X) > loRange || Abs(vec2.Y) > loRange) + { + if (Abs(vec1.X) > hiRange || Abs(vec1.Y) > hiRange || + Abs(vec2.X) > hiRange || Abs(vec2.Y) > hiRange) + throw "Coordinate exceeds range bounds."; + Int128 cross = Int128(vec1.X) * Int128(vec2.Y) - + Int128(vec2.X) * Int128(vec1.Y); + return cross >= 0; + } + else + return (vec1.X * vec2.Y - vec2.X * vec1.Y) >= 0; +} +//------------------------------------------------------------------------------ + +inline bool PointsEqual( const IntPoint &pt1, const IntPoint &pt2) +{ + return ( pt1.X == pt2.X && pt1.Y == pt2.Y ); +} +//------------------------------------------------------------------------------ + +bool Orientation(OutRec *outRec, bool UseFullInt64Range) +{ + //first make sure bottomPt is correctly assigned ... + OutPt *opBottom = outRec->pts, *op = outRec->pts->next; + while (op != outRec->pts) + { + if (op->pt.Y >= opBottom->pt.Y) + { + if (op->pt.Y > opBottom->pt.Y || op->pt.X < opBottom->pt.X) + opBottom = op; + } + op = op->next; + } + outRec->bottomPt = opBottom; + opBottom->idx = outRec->idx; + + op = opBottom; + //find vertices either side of bottomPt (skipping duplicate points) .... + OutPt *opPrev = op->prev; + OutPt *opNext = op->next; + while (op != opPrev && PointsEqual(op->pt, opPrev->pt)) + opPrev = opPrev->prev; + while (op != opNext && PointsEqual(op->pt, opNext->pt)) + opNext = opNext->next; + + IntPoint ip1, ip2; + ip1.X = op->pt.X - opPrev->pt.X; + ip1.Y = op->pt.Y - opPrev->pt.Y; + ip2.X = opNext->pt.X - op->pt.X; + ip2.Y = opNext->pt.Y - op->pt.Y; + + if (UseFullInt64Range) + return Int128(ip1.X) * Int128(ip2.Y) - Int128(ip2.X) * Int128(ip1.Y) >= 0; + else + return (ip1.X * ip2.Y - ip2.X * ip1.Y) >= 0; +} +//------------------------------------------------------------------------------ + +double Area(const Polygon &poly) +{ + int highI = (int)poly.size() -1; + if (highI < 2) return 0; + + if (FullRangeNeeded(poly)) { + Int128 a; + a = (Int128(poly[highI].X) * Int128(poly[0].Y)) - + Int128(poly[0].X) * Int128(poly[highI].Y); + for (int i = 0; i < highI; ++i) + a += Int128(poly[i].X) * Int128(poly[i+1].Y) - + Int128(poly[i+1].X) * Int128(poly[i].Y); + return a.AsDouble() / 2; + } + else + { + double a; + a = (double)poly[highI].X * poly[0].Y - (double)poly[0].X * poly[highI].Y; + for (int i = 0; i < highI; ++i) + a += (double)poly[i].X * poly[i+1].Y - (double)poly[i+1].X * poly[i].Y; + return a/2; + } +} +//------------------------------------------------------------------------------ + +double Area(const OutRec &outRec, bool UseFullInt64Range) +{ + OutPt *op = outRec.pts; + if (UseFullInt64Range) { + Int128 a(0); + do { + a += (Int128(op->prev->pt.X) * Int128(op->pt.Y)) - + Int128(op->pt.X) * Int128(op->prev->pt.Y); + op = op->next; + } while (op != outRec.pts); + return a.AsDouble() / 2; + } + else + { + double a = 0; + do { + a += (op->prev->pt.X * op->pt.Y) - (op->pt.X * op->prev->pt.Y); + op = op->next; + } while (op != outRec.pts); + return a/2; + } +} +//------------------------------------------------------------------------------ + +bool PointIsVertex(const IntPoint &pt, OutPt *pp) +{ + OutPt *pp2 = pp; + do + { + if (PointsEqual(pp2->pt, pt)) return true; + pp2 = pp2->next; + } + while (pp2 != pp); + return false; +} +//------------------------------------------------------------------------------ + +bool PointInPolygon(const IntPoint &pt, OutPt *pp, bool UseFullInt64Range) +{ + OutPt *pp2 = pp; + bool result = false; + if (UseFullInt64Range) { + do + { + if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || + ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && + Int128(pt.X - pp2->pt.X) < (Int128(pp2->prev->pt.X - pp2->pt.X) * + Int128(pt.Y - pp2->pt.Y)) / Int128(pp2->prev->pt.Y - pp2->pt.Y)) + result = !result; + pp2 = pp2->next; + } + while (pp2 != pp); + } + else + { + do + { + if ((((pp2->pt.Y <= pt.Y) && (pt.Y < pp2->prev->pt.Y)) || + ((pp2->prev->pt.Y <= pt.Y) && (pt.Y < pp2->pt.Y))) && + (pt.X < (pp2->prev->pt.X - pp2->pt.X) * (pt.Y - pp2->pt.Y) / + (pp2->prev->pt.Y - pp2->pt.Y) + pp2->pt.X )) result = !result; + pp2 = pp2->next; + } + while (pp2 != pp); + } + return result; +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(TEdge &e1, TEdge &e2, bool UseFullInt64Range) +{ + if (UseFullInt64Range) + return Int128(e1.ytop - e1.ybot) * Int128(e2.xtop - e2.xbot) == + Int128(e1.xtop - e1.xbot) * Int128(e2.ytop - e2.ybot); + else return (e1.ytop - e1.ybot)*(e2.xtop - e2.xbot) == + (e1.xtop - e1.xbot)*(e2.ytop - e2.ybot); +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, + const IntPoint pt3, bool UseFullInt64Range) +{ + if (UseFullInt64Range) + return Int128(pt1.Y-pt2.Y) * Int128(pt2.X-pt3.X) == + Int128(pt1.X-pt2.X) * Int128(pt2.Y-pt3.Y); + else return (pt1.Y-pt2.Y)*(pt2.X-pt3.X) == (pt1.X-pt2.X)*(pt2.Y-pt3.Y); +} +//------------------------------------------------------------------------------ + +bool SlopesEqual(const IntPoint pt1, const IntPoint pt2, + const IntPoint pt3, const IntPoint pt4, bool UseFullInt64Range) +{ + if (UseFullInt64Range) + return Int128(pt1.Y-pt2.Y) * Int128(pt3.X-pt4.X) == + Int128(pt1.X-pt2.X) * Int128(pt3.Y-pt4.Y); + else return (pt1.Y-pt2.Y)*(pt3.X-pt4.X) == (pt1.X-pt2.X)*(pt3.Y-pt4.Y); +} +//------------------------------------------------------------------------------ + +double GetDx(const IntPoint pt1, const IntPoint pt2) +{ + return (pt1.Y == pt2.Y) ? + HORIZONTAL : (double)(pt2.X - pt1.X) / (double)(pt2.Y - pt1.Y); +} +//--------------------------------------------------------------------------- + +void SetDx(TEdge &e) +{ + if (e.ybot == e.ytop) e.dx = HORIZONTAL; + else e.dx = (double)(e.xtop - e.xbot) / (double)(e.ytop - e.ybot); +} +//--------------------------------------------------------------------------- + +void SwapSides(TEdge &edge1, TEdge &edge2) +{ + EdgeSide side = edge1.side; + edge1.side = edge2.side; + edge2.side = side; +} +//------------------------------------------------------------------------------ + +void SwapPolyIndexes(TEdge &edge1, TEdge &edge2) +{ + int outIdx = edge1.outIdx; + edge1.outIdx = edge2.outIdx; + edge2.outIdx = outIdx; +} +//------------------------------------------------------------------------------ + +inline long64 Round(double val) +{ + return (val < 0) ? + static_cast(val - 0.5) : static_cast(val + 0.5); +} +//------------------------------------------------------------------------------ + +long64 TopX(TEdge &edge, const long64 currentY) +{ + return ( currentY == edge.ytop ) ? + edge.xtop : edge.xbot + Round(edge.dx *(currentY - edge.ybot)); +} +//------------------------------------------------------------------------------ + +long64 TopX(const IntPoint pt1, const IntPoint pt2, const long64 currentY) +{ + //preconditions: pt1.Y <> pt2.Y and pt1.Y > pt2.Y + if (currentY >= pt1.Y) return pt1.X; + else if (currentY == pt2.Y) return pt2.X; + else if (pt1.X == pt2.X) return pt1.X; + else + { + double q = (double)(pt1.X-pt2.X)/(double)(pt1.Y-pt2.Y); + return Round(pt1.X + (currentY - pt1.Y) *q); + } +} +//------------------------------------------------------------------------------ + +bool IntersectPoint(TEdge &edge1, TEdge &edge2, + IntPoint &ip, bool UseFullInt64Range) +{ + double b1, b2; + if (SlopesEqual(edge1, edge2, UseFullInt64Range)) return false; + else if (NEAR_ZERO(edge1.dx)) + { + ip.X = edge1.xbot; + if (NEAR_EQUAL(edge2.dx, HORIZONTAL)) + { + ip.Y = edge2.ybot; + } else + { + b2 = edge2.ybot - (edge2.xbot/edge2.dx); + ip.Y = Round(ip.X/edge2.dx + b2); + } + } + else if (NEAR_ZERO(edge2.dx)) + { + ip.X = edge2.xbot; + if (NEAR_EQUAL(edge1.dx, HORIZONTAL)) + { + ip.Y = edge1.ybot; + } else + { + b1 = edge1.ybot - (edge1.xbot/edge1.dx); + ip.Y = Round(ip.X/edge1.dx + b1); + } + } else + { + b1 = edge1.xbot - edge1.ybot * edge1.dx; + b2 = edge2.xbot - edge2.ybot * edge2.dx; + b2 = (b2-b1)/(edge1.dx - edge2.dx); + ip.Y = Round(b2); + ip.X = Round(edge1.dx * b2 + b1); + } + + return + //can be *so close* to the top of one edge that the rounded Y equals one ytop ... + (ip.Y == edge1.ytop && ip.Y >= edge2.ytop && edge1.tmpX > edge2.tmpX) || + (ip.Y == edge2.ytop && ip.Y >= edge1.ytop && edge1.tmpX > edge2.tmpX) || + (ip.Y > edge1.ytop && ip.Y > edge2.ytop); +} +//------------------------------------------------------------------------------ + +void ReversePolyPtLinks(OutPt &pp) +{ + OutPt *pp1, *pp2; + pp1 = &pp; + do { + pp2 = pp1->next; + pp1->next = pp1->prev; + pp1->prev = pp2; + pp1 = pp2; + } while( pp1 != &pp ); +} +//------------------------------------------------------------------------------ + +void DisposeOutPts(OutPt*& pp) +{ + if (pp == 0) return; + pp->prev->next = 0; + while( pp ) + { + OutPt *tmpPp = pp; + pp = pp->next; + delete tmpPp ; + } +} +//------------------------------------------------------------------------------ + +void InitEdge(TEdge *e, TEdge *eNext, + TEdge *ePrev, const IntPoint &pt, PolyType polyType) +{ + std::memset( e, 0, sizeof( TEdge )); + + e->next = eNext; + e->prev = ePrev; + e->xcurr = pt.X; + e->ycurr = pt.Y; + if (e->ycurr >= e->next->ycurr) + { + e->xbot = e->xcurr; + e->ybot = e->ycurr; + e->xtop = e->next->xcurr; + e->ytop = e->next->ycurr; + e->windDelta = 1; + } else + { + e->xtop = e->xcurr; + e->ytop = e->ycurr; + e->xbot = e->next->xcurr; + e->ybot = e->next->ycurr; + e->windDelta = -1; + } + SetDx(*e); + e->polyType = polyType; + e->outIdx = -1; +} +//------------------------------------------------------------------------------ + +inline void SwapX(TEdge &e) +{ + //swap horizontal edges' top and bottom x's so they follow the natural + //progression of the bounds - ie so their xbots will align with the + //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] + e.xcurr = e.xtop; + e.xtop = e.xbot; + e.xbot = e.xcurr; +} +//------------------------------------------------------------------------------ + +void SwapPoints(IntPoint &pt1, IntPoint &pt2) +{ + IntPoint tmp = pt1; + pt1 = pt2; + pt2 = tmp; +} +//------------------------------------------------------------------------------ + +bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, + IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) +{ + //precondition: segments are colinear. + if ( pt1a.Y == pt1b.Y || Abs((pt1a.X - pt1b.X)/(pt1a.Y - pt1b.Y)) > 1 ) + { + if (pt1a.X > pt1b.X) SwapPoints(pt1a, pt1b); + if (pt2a.X > pt2b.X) SwapPoints(pt2a, pt2b); + if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; + if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; + return pt1.X < pt2.X; + } else + { + if (pt1a.Y < pt1b.Y) SwapPoints(pt1a, pt1b); + if (pt2a.Y < pt2b.Y) SwapPoints(pt2a, pt2b); + if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; + if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; + return pt1.Y > pt2.Y; + } +} +//------------------------------------------------------------------------------ + +bool FirstIsBottomPt(const OutPt* btmPt1, const OutPt* btmPt2) +{ + OutPt *p = btmPt1->prev; + while (PointsEqual(p->pt, btmPt1->pt) && (p != btmPt1)) p = p->prev; + double dx1p = std::fabs(GetDx(btmPt1->pt, p->pt)); + p = btmPt1->next; + while (PointsEqual(p->pt, btmPt1->pt) && (p != btmPt1)) p = p->next; + double dx1n = std::fabs(GetDx(btmPt1->pt, p->pt)); + + p = btmPt2->prev; + while (PointsEqual(p->pt, btmPt2->pt) && (p != btmPt2)) p = p->prev; + double dx2p = std::fabs(GetDx(btmPt2->pt, p->pt)); + p = btmPt2->next; + while (PointsEqual(p->pt, btmPt2->pt) && (p != btmPt2)) p = p->next; + double dx2n = std::fabs(GetDx(btmPt2->pt, p->pt)); + return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); +} +//------------------------------------------------------------------------------ + +OutPt* GetBottomPt(OutPt *pp) +{ + OutPt* dups = 0; + OutPt* p = pp->next; + while (p != pp) + { + if (p->pt.Y > pp->pt.Y) + { + pp = p; + dups = 0; + } + else if (p->pt.Y == pp->pt.Y && p->pt.X <= pp->pt.X) + { + if (p->pt.X < pp->pt.X) + { + dups = 0; + pp = p; + } else + { + if (p->next != pp && p->prev != pp) dups = p; + } + } + p = p->next; + } + if (dups) + { + //there appears to be at least 2 vertices at bottomPt so ... + while (dups != p) + { + if (!FirstIsBottomPt(p, dups)) pp = dups; + dups = dups->next; + while (!PointsEqual(dups->pt, pp->pt)) dups = dups->next; + } + } + return pp; +} +//------------------------------------------------------------------------------ + +bool FindSegment(OutPt* &pp, IntPoint &pt1, IntPoint &pt2) +{ + //outPt1 & outPt2 => the overlap segment (if the function returns true) + if (!pp) return false; + OutPt* pp2 = pp; + IntPoint pt1a = pt1, pt2a = pt2; + do + { + if (SlopesEqual(pt1a, pt2a, pp->pt, pp->prev->pt, true) && + SlopesEqual(pt1a, pt2a, pp->pt, true) && + GetOverlapSegment(pt1a, pt2a, pp->pt, pp->prev->pt, pt1, pt2)) + return true; + pp = pp->next; + } + while (pp != pp2); + return false; +} +//------------------------------------------------------------------------------ + +bool Pt3IsBetweenPt1AndPt2(const IntPoint pt1, + const IntPoint pt2, const IntPoint pt3) +{ + if (PointsEqual(pt1, pt3) || PointsEqual(pt2, pt3)) return true; + else if (pt1.X != pt2.X) return (pt1.X < pt3.X) == (pt3.X < pt2.X); + else return (pt1.Y < pt3.Y) == (pt3.Y < pt2.Y); +} +//------------------------------------------------------------------------------ + +OutPt* InsertPolyPtBetween(OutPt* p1, OutPt* p2, const IntPoint pt) +{ + if (p1 == p2) throw "JoinError"; + OutPt* result = new OutPt; + result->pt = pt; + if (p2 == p1->next) + { + p1->next = result; + p2->prev = result; + result->next = p2; + result->prev = p1; + } else + { + p2->next = result; + p1->prev = result; + result->next = p1; + result->prev = p2; + } + return result; +} + +//------------------------------------------------------------------------------ +// ClipperBase class methods ... +//------------------------------------------------------------------------------ + +ClipperBase::ClipperBase() //constructor +{ + m_MinimaList = 0; + m_CurrentLM = 0; + m_UseFullRange = true; +} +//------------------------------------------------------------------------------ + +ClipperBase::~ClipperBase() //destructor +{ + Clear(); +} +//------------------------------------------------------------------------------ + +bool ClipperBase::AddPolygon( const Polygon &pg, PolyType polyType) +{ + int len = (int)pg.size(); + if (len < 3) return false; + Polygon p(len); + p[0] = pg[0]; + int j = 0; + + long64 maxVal; + if (m_UseFullRange) maxVal = hiRange; else maxVal = loRange; + + for (int i = 0; i < len; ++i) + { + if (Abs(pg[i].X) > maxVal || Abs(pg[i].Y) > maxVal) + { + if (Abs(pg[i].X) > hiRange || Abs(pg[i].Y) > hiRange) + throw "Coordinate exceeds range bounds"; + maxVal = hiRange; + m_UseFullRange = true; + } + + if (i == 0 || PointsEqual(p[j], pg[i])) continue; + else if (j > 0 && SlopesEqual(p[j-1], p[j], pg[i], m_UseFullRange)) + { + if (PointsEqual(p[j-1], pg[i])) j--; + } else j++; + p[j] = pg[i]; + } + if (j < 2) return false; + + len = j+1; + while (len > 2) + { + //nb: test for point equality before testing slopes ... + if (PointsEqual(p[j], p[0])) j--; + else if (PointsEqual(p[0], p[1]) || + SlopesEqual(p[j], p[0], p[1], m_UseFullRange)) + p[0] = p[j--]; + else if (SlopesEqual(p[j-1], p[j], p[0], m_UseFullRange)) j--; + else if (SlopesEqual(p[0], p[1], p[2], m_UseFullRange)) + { + for (int i = 2; i <= j; ++i) p[i-1] = p[i]; + j--; + } + else break; + len--; + } + if (len < 3) return false; + + //create a new edge array ... + TEdge *edges = new TEdge [len]; + m_edges.push_back(edges); + + //convert vertices to a double-linked-list of edges and initialize ... + edges[0].xcurr = p[0].X; + edges[0].ycurr = p[0].Y; + InitEdge(&edges[len-1], &edges[0], &edges[len-2], p[len-1], polyType); + for (int i = len-2; i > 0; --i) + InitEdge(&edges[i], &edges[i+1], &edges[i-1], p[i], polyType); + InitEdge(&edges[0], &edges[1], &edges[len-1], p[0], polyType); + + //reset xcurr & ycurr and find 'eHighest' (given the Y axis coordinates + //increase downward so the 'highest' edge will have the smallest ytop) ... + TEdge *e = &edges[0]; + TEdge *eHighest = e; + do + { + e->xcurr = e->xbot; + e->ycurr = e->ybot; + if (e->ytop < eHighest->ytop) eHighest = e; + e = e->next; + } + while ( e != &edges[0]); + + //make sure eHighest is positioned so the following loop works safely ... + if (eHighest->windDelta > 0) eHighest = eHighest->next; + if (NEAR_EQUAL(eHighest->dx, HORIZONTAL)) eHighest = eHighest->next; + + //finally insert each local minima ... + e = eHighest; + do { + e = AddBoundsToLML(e); + } + while( e != eHighest ); + return true; +} +//------------------------------------------------------------------------------ + +void ClipperBase::InsertLocalMinima(LocalMinima *newLm) +{ + if( ! m_MinimaList ) + { + m_MinimaList = newLm; + } + else if( newLm->Y >= m_MinimaList->Y ) + { + newLm->next = m_MinimaList; + m_MinimaList = newLm; + } else + { + LocalMinima* tmpLm = m_MinimaList; + while( tmpLm->next && ( newLm->Y < tmpLm->next->Y ) ) + tmpLm = tmpLm->next; + newLm->next = tmpLm->next; + tmpLm->next = newLm; + } +} +//------------------------------------------------------------------------------ + +TEdge* ClipperBase::AddBoundsToLML(TEdge *e) +{ + //Starting at the top of one bound we progress to the bottom where there's + //a local minima. We then go to the top of the next bound. These two bounds + //form the left and right (or right and left) bounds of the local minima. + e->nextInLML = 0; + e = e->next; + for (;;) + { + if (NEAR_EQUAL(e->dx, HORIZONTAL)) + { + //nb: proceed through horizontals when approaching from their right, + // but break on horizontal minima if approaching from their left. + // This ensures 'local minima' are always on the left of horizontals. + if (e->next->ytop < e->ytop && e->next->xbot > e->prev->xbot) break; + if (e->xtop != e->prev->xbot) SwapX(*e); + e->nextInLML = e->prev; + } + else if (e->ycurr == e->prev->ycurr) break; + else e->nextInLML = e->prev; + e = e->next; + } + + //e and e.prev are now at a local minima ... + LocalMinima* newLm = new LocalMinima; + newLm->next = 0; + newLm->Y = e->prev->ybot; + + if ( NEAR_EQUAL(e->dx, HORIZONTAL) ) //horizontal edges never start a left bound + { + if (e->xbot != e->prev->xbot) SwapX(*e); + newLm->leftBound = e->prev; + newLm->rightBound = e; + } else if (e->dx < e->prev->dx) + { + newLm->leftBound = e->prev; + newLm->rightBound = e; + } else + { + newLm->leftBound = e; + newLm->rightBound = e->prev; + } + newLm->leftBound->side = esLeft; + newLm->rightBound->side = esRight; + InsertLocalMinima( newLm ); + + for (;;) + { + if ( e->next->ytop == e->ytop && !NEAR_EQUAL(e->next->dx, HORIZONTAL) ) break; + e->nextInLML = e->next; + e = e->next; + if ( NEAR_EQUAL(e->dx, HORIZONTAL) && e->xbot != e->prev->xtop) SwapX(*e); + } + return e->next; +} +//------------------------------------------------------------------------------ + +bool ClipperBase::AddPolygons(const Polygons &ppg, PolyType polyType) +{ + bool result = false; + for (Polygons::size_type i = 0; i < ppg.size(); ++i) + if (AddPolygon(ppg[i], polyType)) result = true; + return result; +} +//------------------------------------------------------------------------------ + +void ClipperBase::Clear() +{ + DisposeLocalMinimaList(); + for (EdgeList::size_type i = 0; i < m_edges.size(); ++i) delete [] m_edges[i]; + m_edges.clear(); + m_UseFullRange = false; +} +//------------------------------------------------------------------------------ + +void ClipperBase::Reset() +{ + m_CurrentLM = m_MinimaList; + if( !m_CurrentLM ) return; //ie nothing to process + + //reset all edges ... + LocalMinima* lm = m_MinimaList; + while( lm ) + { + TEdge* e = lm->leftBound; + while( e ) + { + e->xcurr = e->xbot; + e->ycurr = e->ybot; + e->side = esLeft; + e->outIdx = -1; + e = e->nextInLML; + } + e = lm->rightBound; + while( e ) + { + e->xcurr = e->xbot; + e->ycurr = e->ybot; + e->side = esRight; + e->outIdx = -1; + e = e->nextInLML; + } + lm = lm->next; + } +} +//------------------------------------------------------------------------------ + +void ClipperBase::DisposeLocalMinimaList() +{ + while( m_MinimaList ) + { + LocalMinima* tmpLm = m_MinimaList->next; + delete m_MinimaList; + m_MinimaList = tmpLm; + } + m_CurrentLM = 0; +} +//------------------------------------------------------------------------------ + +void ClipperBase::PopLocalMinima() +{ + if( ! m_CurrentLM ) return; + m_CurrentLM = m_CurrentLM->next; +} +//------------------------------------------------------------------------------ + +IntRect ClipperBase::GetBounds() +{ + IntRect result; + LocalMinima* lm = m_MinimaList; + if (!lm) + { + result.left = result.top = result.right = result.bottom = 0; + return result; + } + result.left = lm->leftBound->xbot; + result.top = lm->leftBound->ybot; + result.right = lm->leftBound->xbot; + result.bottom = lm->leftBound->ybot; + while (lm) + { + if (lm->leftBound->ybot > result.bottom) + result.bottom = lm->leftBound->ybot; + TEdge* e = lm->leftBound; + for (;;) { + TEdge* bottomE = e; + while (e->nextInLML) + { + if (e->xbot < result.left) result.left = e->xbot; + if (e->xbot > result.right) result.right = e->xbot; + e = e->nextInLML; + } + if (e->xbot < result.left) result.left = e->xbot; + if (e->xbot > result.right) result.right = e->xbot; + if (e->xtop < result.left) result.left = e->xtop; + if (e->xtop > result.right) result.right = e->xtop; + if (e->ytop < result.top) result.top = e->ytop; + + if (bottomE == lm->leftBound) e = lm->rightBound; + else break; + } + lm = lm->next; + } + return result; +} + + +//------------------------------------------------------------------------------ +// TClipper methods ... +//------------------------------------------------------------------------------ + +Clipper::Clipper() : ClipperBase() //constructor +{ + m_Scanbeam = 0; + m_ActiveEdges = 0; + m_SortedEdges = 0; + m_IntersectNodes = 0; + m_ExecuteLocked = false; + m_UseFullRange = false; + m_ReverseOutput = false; +} +//------------------------------------------------------------------------------ + +Clipper::~Clipper() //destructor +{ + Clear(); + DisposeScanbeamList(); +} +//------------------------------------------------------------------------------ + +void Clipper::Clear() +{ + if (m_edges.size() == 0) return; //avoids problems with ClipperBase destructor + DisposeAllPolyPts(); + ClipperBase::Clear(); +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeScanbeamList() +{ + while ( m_Scanbeam ) { + Scanbeam* sb2 = m_Scanbeam->next; + delete m_Scanbeam; + m_Scanbeam = sb2; + } +} +//------------------------------------------------------------------------------ + +void Clipper::Reset() +{ + ClipperBase::Reset(); + m_Scanbeam = 0; + m_ActiveEdges = 0; + m_SortedEdges = 0; + DisposeAllPolyPts(); + LocalMinima* lm = m_MinimaList; + while (lm) + { + InsertScanbeam(lm->Y); + InsertScanbeam(lm->leftBound->ytop); + lm = lm->next; + } +} +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, Polygons &solution, + PolyFillType subjFillType, PolyFillType clipFillType) +{ + if( m_ExecuteLocked ) return false; + m_ExecuteLocked = true; + solution.resize(0); + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + bool succeeded = ExecuteInternal(false); + if (succeeded) BuildResult(solution); + m_ExecuteLocked = false; + return succeeded; +} +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, ExPolygons &solution, + PolyFillType subjFillType, PolyFillType clipFillType) +{ + if( m_ExecuteLocked ) return false; + m_ExecuteLocked = true; + solution.resize(0); + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + bool succeeded = ExecuteInternal(true); + if (succeeded) BuildResultEx(solution); + m_ExecuteLocked = false; + return succeeded; +} +//------------------------------------------------------------------------------ + +bool PolySort(OutRec *or1, OutRec *or2) +{ + if (or1 == or2) return false; + if (!or1->pts || !or2->pts) + { + if (or1->pts != or2->pts) + { + return or1->pts ? true : false; + } + else return false; + } + int i1, i2; + if (or1->isHole) + i1 = or1->FirstLeft->idx; else + i1 = or1->idx; + if (or2->isHole) + i2 = or2->FirstLeft->idx; else + i2 = or2->idx; + int result = i1 - i2; + if (result == 0 && (or1->isHole != or2->isHole)) + { + return or1->isHole ? false : true; + } + else return result < 0; +} +//------------------------------------------------------------------------------ + +OutRec* FindAppendLinkEnd(OutRec *outRec) +{ + while (outRec->AppendLink) outRec = outRec->AppendLink; + return outRec; +} +//------------------------------------------------------------------------------ + +void Clipper::FixHoleLinkage(OutRec *outRec) +{ + OutRec *tmp; + if (outRec->bottomPt) + tmp = m_PolyOuts[outRec->bottomPt->idx]->FirstLeft; + else + tmp = outRec->FirstLeft; + if (outRec == tmp) throw clipperException("HoleLinkage error"); + + if (tmp) + { + if (tmp->AppendLink) tmp = FindAppendLinkEnd(tmp); + if (tmp == outRec) tmp = 0; + else if (tmp->isHole) + { + FixHoleLinkage(tmp); + tmp = tmp->FirstLeft; + } + } + outRec->FirstLeft = tmp; + if (!tmp) outRec->isHole = false; + outRec->AppendLink = 0; +} +//------------------------------------------------------------------------------ + +bool Clipper::ExecuteInternal(bool fixHoleLinkages) +{ + bool succeeded; + try { + Reset(); + if (!m_CurrentLM ) return true; + long64 botY = PopScanbeam(); + do { + InsertLocalMinimaIntoAEL(botY); + ClearHorzJoins(); + ProcessHorizontals(); + long64 topY = PopScanbeam(); + succeeded = ProcessIntersections(botY, topY); + if (!succeeded) break; + ProcessEdgesAtTopOfScanbeam(topY); + botY = topY; + } while( m_Scanbeam ); + } + catch(...) { + succeeded = false; + } + + if (succeeded) + { + //tidy up output polygons and fix orientations where necessary ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec *outRec = m_PolyOuts[i]; + if (!outRec->pts) continue; + FixupOutPolygon(*outRec); + if (!outRec->pts) continue; + if (outRec->isHole && fixHoleLinkages) FixHoleLinkage(outRec); + + if (outRec->bottomPt == outRec->bottomFlag && + (Orientation(outRec, m_UseFullRange) != (Area(*outRec, m_UseFullRange) > 0))) + DisposeBottomPt(*outRec); + + if (outRec->isHole == + (m_ReverseOutput ^ Orientation(outRec, m_UseFullRange))) + ReversePolyPtLinks(*outRec->pts); + } + + JoinCommonEdges(fixHoleLinkages); + if (fixHoleLinkages) + std::sort(m_PolyOuts.begin(), m_PolyOuts.end(), PolySort); + } + + ClearJoins(); + ClearHorzJoins(); + return succeeded; +} +//------------------------------------------------------------------------------ + +void Clipper::InsertScanbeam(const long64 Y) +{ + if( !m_Scanbeam ) + { + m_Scanbeam = new Scanbeam; + m_Scanbeam->next = 0; + m_Scanbeam->Y = Y; + } + else if( Y > m_Scanbeam->Y ) + { + Scanbeam* newSb = new Scanbeam; + newSb->Y = Y; + newSb->next = m_Scanbeam; + m_Scanbeam = newSb; + } else + { + Scanbeam* sb2 = m_Scanbeam; + while( sb2->next && ( Y <= sb2->next->Y ) ) sb2 = sb2->next; + if( Y == sb2->Y ) return; //ie ignores duplicates + Scanbeam* newSb = new Scanbeam; + newSb->Y = Y; + newSb->next = sb2->next; + sb2->next = newSb; + } +} +//------------------------------------------------------------------------------ + +long64 Clipper::PopScanbeam() +{ + long64 Y = m_Scanbeam->Y; + Scanbeam* sb2 = m_Scanbeam; + m_Scanbeam = m_Scanbeam->next; + delete sb2; + return Y; +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeAllPolyPts(){ + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + DisposeOutRec(i); + m_PolyOuts.clear(); +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeOutRec(PolyOutList::size_type index) +{ + OutRec *outRec = m_PolyOuts[index]; + if (outRec->pts) DisposeOutPts(outRec->pts); + delete outRec; + m_PolyOuts[index] = 0; +} +//------------------------------------------------------------------------------ + +void Clipper::SetWindingCount(TEdge &edge) +{ + TEdge *e = edge.prevInAEL; + //find the edge of the same polytype that immediately preceeds 'edge' in AEL + while ( e && e->polyType != edge.polyType ) e = e->prevInAEL; + if ( !e ) + { + edge.windCnt = edge.windDelta; + edge.windCnt2 = 0; + e = m_ActiveEdges; //ie get ready to calc windCnt2 + } else if ( IsEvenOddFillType(edge) ) + { + //EvenOdd filling ... + edge.windCnt = 1; + edge.windCnt2 = e->windCnt2; + e = e->nextInAEL; //ie get ready to calc windCnt2 + } else + { + //nonZero, Positive or Negative filling ... + if ( e->windCnt * e->windDelta < 0 ) + { + if (Abs(e->windCnt) > 1) + { + if (e->windDelta * edge.windDelta < 0) edge.windCnt = e->windCnt; + else edge.windCnt = e->windCnt + edge.windDelta; + } else + edge.windCnt = e->windCnt + e->windDelta + edge.windDelta; + } else + { + if ( Abs(e->windCnt) > 1 && e->windDelta * edge.windDelta < 0) + edge.windCnt = e->windCnt; + else if ( e->windCnt + edge.windDelta == 0 ) + edge.windCnt = e->windCnt; + else edge.windCnt = e->windCnt + edge.windDelta; + } + edge.windCnt2 = e->windCnt2; + e = e->nextInAEL; //ie get ready to calc windCnt2 + } + + //update windCnt2 ... + if ( IsEvenOddAltFillType(edge) ) + { + //EvenOdd filling ... + while ( e != &edge ) + { + edge.windCnt2 = (edge.windCnt2 == 0) ? 1 : 0; + e = e->nextInAEL; + } + } else + { + //nonZero, Positive or Negative filling ... + while ( e != &edge ) + { + edge.windCnt2 += e->windDelta; + e = e->nextInAEL; + } + } +} +//------------------------------------------------------------------------------ + +bool Clipper::IsEvenOddFillType(const TEdge& edge) const +{ + if (edge.polyType == ptSubject) + return m_SubjFillType == pftEvenOdd; else + return m_ClipFillType == pftEvenOdd; +} +//------------------------------------------------------------------------------ + +bool Clipper::IsEvenOddAltFillType(const TEdge& edge) const +{ + if (edge.polyType == ptSubject) + return m_ClipFillType == pftEvenOdd; else + return m_SubjFillType == pftEvenOdd; +} +//------------------------------------------------------------------------------ + +bool Clipper::IsContributing(const TEdge& edge) const +{ + PolyFillType pft, pft2; + if (edge.polyType == ptSubject) + { + pft = m_SubjFillType; + pft2 = m_ClipFillType; + } else + { + pft = m_ClipFillType; + pft2 = m_SubjFillType; + } + + switch(pft) + { + case pftEvenOdd: + case pftNonZero: + if (Abs(edge.windCnt) != 1) return false; + break; + case pftPositive: + if (edge.windCnt != 1) return false; + break; + default: //pftNegative + if (edge.windCnt != -1) return false; + } + + switch(m_ClipType) + { + case ctIntersection: + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.windCnt2 != 0); + case pftPositive: + return (edge.windCnt2 > 0); + default: + return (edge.windCnt2 < 0); + } + case ctUnion: + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.windCnt2 == 0); + case pftPositive: + return (edge.windCnt2 <= 0); + default: + return (edge.windCnt2 >= 0); + } + case ctDifference: + if (edge.polyType == ptSubject) + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.windCnt2 == 0); + case pftPositive: + return (edge.windCnt2 <= 0); + default: + return (edge.windCnt2 >= 0); + } + else + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.windCnt2 != 0); + case pftPositive: + return (edge.windCnt2 > 0); + default: + return (edge.windCnt2 < 0); + } + default: + return true; + } +} +//------------------------------------------------------------------------------ + +void Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) +{ + TEdge *e, *prevE; + if( NEAR_EQUAL(e2->dx, HORIZONTAL) || ( e1->dx > e2->dx ) ) + { + AddOutPt( e1, pt ); + e2->outIdx = e1->outIdx; + e1->side = esLeft; + e2->side = esRight; + e = e1; + if (e->prevInAEL == e2) + prevE = e2->prevInAEL; + else + prevE = e->prevInAEL; + } else + { + AddOutPt( e2, pt ); + e1->outIdx = e2->outIdx; + e1->side = esRight; + e2->side = esLeft; + e = e2; + if (e->prevInAEL == e1) + prevE = e1->prevInAEL; + else + prevE = e->prevInAEL; + } + if (prevE && prevE->outIdx >= 0 && + (TopX(*prevE, pt.Y) == TopX(*e, pt.Y)) && + SlopesEqual(*e, *prevE, m_UseFullRange)) + AddJoin(e, prevE, -1, -1); +} +//------------------------------------------------------------------------------ + +void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt) +{ + AddOutPt( e1, pt ); + if( e1->outIdx == e2->outIdx ) + { + e1->outIdx = -1; + e2->outIdx = -1; + } + else if (e1->outIdx < e2->outIdx) + AppendPolygon(e1, e2); + else + AppendPolygon(e2, e1); +} +//------------------------------------------------------------------------------ + +void Clipper::AddEdgeToSEL(TEdge *edge) +{ + //SEL pointers in PEdge are reused to build a list of horizontal edges. + //However, we don't need to worry about order with horizontal edge processing. + if( !m_SortedEdges ) + { + m_SortedEdges = edge; + edge->prevInSEL = 0; + edge->nextInSEL = 0; + } + else + { + edge->nextInSEL = m_SortedEdges; + edge->prevInSEL = 0; + m_SortedEdges->prevInSEL = edge; + m_SortedEdges = edge; + } +} +//------------------------------------------------------------------------------ + +void Clipper::CopyAELToSEL() +{ + TEdge* e = m_ActiveEdges; + m_SortedEdges = e; + if (!m_ActiveEdges) return; + m_SortedEdges->prevInSEL = 0; + e = e->nextInAEL; + while ( e ) + { + e->prevInSEL = e->prevInAEL; + e->prevInSEL->nextInSEL = e; + e->nextInSEL = 0; + e = e->nextInAEL; + } +} +//------------------------------------------------------------------------------ + +void Clipper::AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx, int e2OutIdx) +{ + JoinRec* jr = new JoinRec; + if (e1OutIdx >= 0) + jr->poly1Idx = e1OutIdx; else + jr->poly1Idx = e1->outIdx; + jr->pt1a = IntPoint(e1->xcurr, e1->ycurr); + jr->pt1b = IntPoint(e1->xtop, e1->ytop); + if (e2OutIdx >= 0) + jr->poly2Idx = e2OutIdx; else + jr->poly2Idx = e2->outIdx; + jr->pt2a = IntPoint(e2->xcurr, e2->ycurr); + jr->pt2b = IntPoint(e2->xtop, e2->ytop); + m_Joins.push_back(jr); +} +//------------------------------------------------------------------------------ + +void Clipper::ClearJoins() +{ + for (JoinList::size_type i = 0; i < m_Joins.size(); i++) + delete m_Joins[i]; + m_Joins.resize(0); +} +//------------------------------------------------------------------------------ + +void Clipper::AddHorzJoin(TEdge *e, int idx) +{ + HorzJoinRec* hj = new HorzJoinRec; + hj->edge = e; + hj->savedIdx = idx; + m_HorizJoins.push_back(hj); +} +//------------------------------------------------------------------------------ + +void Clipper::ClearHorzJoins() +{ + for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); i++) + delete m_HorizJoins[i]; + m_HorizJoins.resize(0); +} +//------------------------------------------------------------------------------ + +void Clipper::InsertLocalMinimaIntoAEL( const long64 botY) +{ + while( m_CurrentLM && ( m_CurrentLM->Y == botY ) ) + { + TEdge* lb = m_CurrentLM->leftBound; + TEdge* rb = m_CurrentLM->rightBound; + + InsertEdgeIntoAEL( lb ); + InsertScanbeam( lb->ytop ); + InsertEdgeIntoAEL( rb ); + + if (IsEvenOddFillType(*lb)) + { + lb->windDelta = 1; + rb->windDelta = 1; + } + else + { + rb->windDelta = -lb->windDelta; + } + SetWindingCount( *lb ); + rb->windCnt = lb->windCnt; + rb->windCnt2 = lb->windCnt2; + + if( NEAR_EQUAL(rb->dx, HORIZONTAL) ) + { + //nb: only rightbounds can have a horizontal bottom edge + AddEdgeToSEL( rb ); + InsertScanbeam( rb->nextInLML->ytop ); + } + else + InsertScanbeam( rb->ytop ); + + if( IsContributing(*lb) ) + AddLocalMinPoly( lb, rb, IntPoint(lb->xcurr, m_CurrentLM->Y) ); + + //if any output polygons share an edge, they'll need joining later ... + if (rb->outIdx >= 0) + { + if (NEAR_EQUAL(rb->dx, HORIZONTAL)) + { + for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) + { + IntPoint pt, pt2; //returned by GetOverlapSegment() but unused here. + HorzJoinRec* hj = m_HorizJoins[i]; + //if horizontals rb and hj.edge overlap, flag for joining later ... + if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), + IntPoint(hj->edge->xtop, hj->edge->ytop), + IntPoint(rb->xbot, rb->ybot), + IntPoint(rb->xtop, rb->ytop), pt, pt2)) + AddJoin(hj->edge, rb, hj->savedIdx); + } + } + } + + if( lb->nextInAEL != rb ) + { + if (rb->outIdx >= 0 && rb->prevInAEL->outIdx >= 0 && + SlopesEqual(*rb->prevInAEL, *rb, m_UseFullRange)) + AddJoin(rb, rb->prevInAEL); + + TEdge* e = lb->nextInAEL; + IntPoint pt = IntPoint(lb->xcurr, lb->ycurr); + while( e != rb ) + { + if(!e) throw clipperException("InsertLocalMinimaIntoAEL: missing rightbound!"); + //nb: For calculating winding counts etc, IntersectEdges() assumes + //that param1 will be to the right of param2 ABOVE the intersection ... + IntersectEdges( rb , e , pt , ipNone); //order important here + e = e->nextInAEL; + } + } + PopLocalMinima(); + } +} +//------------------------------------------------------------------------------ + +void Clipper::DeleteFromAEL(TEdge *e) +{ + TEdge* AelPrev = e->prevInAEL; + TEdge* AelNext = e->nextInAEL; + if( !AelPrev && !AelNext && (e != m_ActiveEdges) ) return; //already deleted + if( AelPrev ) AelPrev->nextInAEL = AelNext; + else m_ActiveEdges = AelNext; + if( AelNext ) AelNext->prevInAEL = AelPrev; + e->nextInAEL = 0; + e->prevInAEL = 0; +} +//------------------------------------------------------------------------------ + +void Clipper::DeleteFromSEL(TEdge *e) +{ + TEdge* SelPrev = e->prevInSEL; + TEdge* SelNext = e->nextInSEL; + if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted + if( SelPrev ) SelPrev->nextInSEL = SelNext; + else m_SortedEdges = SelNext; + if( SelNext ) SelNext->prevInSEL = SelPrev; + e->nextInSEL = 0; + e->prevInSEL = 0; +} +//------------------------------------------------------------------------------ + +void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, + const IntPoint &pt, IntersectProtects protects) +{ + //e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before + //e2 in AEL except when e1 is being inserted at the intersection point ... + bool e1stops = !(ipLeft & protects) && !e1->nextInLML && + e1->xtop == pt.X && e1->ytop == pt.Y; + bool e2stops = !(ipRight & protects) && !e2->nextInLML && + e2->xtop == pt.X && e2->ytop == pt.Y; + bool e1Contributing = ( e1->outIdx >= 0 ); + bool e2contributing = ( e2->outIdx >= 0 ); + + //update winding counts... + //assumes that e1 will be to the right of e2 ABOVE the intersection + if ( e1->polyType == e2->polyType ) + { + if ( IsEvenOddFillType( *e1) ) + { + int oldE1WindCnt = e1->windCnt; + e1->windCnt = e2->windCnt; + e2->windCnt = oldE1WindCnt; + } else + { + if (e1->windCnt + e2->windDelta == 0 ) e1->windCnt = -e1->windCnt; + else e1->windCnt += e2->windDelta; + if ( e2->windCnt - e1->windDelta == 0 ) e2->windCnt = -e2->windCnt; + else e2->windCnt -= e1->windDelta; + } + } else + { + if (!IsEvenOddFillType(*e2)) e1->windCnt2 += e2->windDelta; + else e1->windCnt2 = ( e1->windCnt2 == 0 ) ? 1 : 0; + if (!IsEvenOddFillType(*e1)) e2->windCnt2 -= e1->windDelta; + else e2->windCnt2 = ( e2->windCnt2 == 0 ) ? 1 : 0; + } + + PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; + if (e1->polyType == ptSubject) + { + e1FillType = m_SubjFillType; + e1FillType2 = m_ClipFillType; + } else + { + e1FillType = m_ClipFillType; + e1FillType2 = m_SubjFillType; + } + if (e2->polyType == ptSubject) + { + e2FillType = m_SubjFillType; + e2FillType2 = m_ClipFillType; + } else + { + e2FillType = m_ClipFillType; + e2FillType2 = m_SubjFillType; + } + + long64 e1Wc, e2Wc; + switch (e1FillType) + { + case pftPositive: e1Wc = e1->windCnt; break; + case pftNegative: e1Wc = -e1->windCnt; break; + default: e1Wc = Abs(e1->windCnt); + } + switch(e2FillType) + { + case pftPositive: e2Wc = e2->windCnt; break; + case pftNegative: e2Wc = -e2->windCnt; break; + default: e2Wc = Abs(e2->windCnt); + } + + if ( e1Contributing && e2contributing ) + { + if ( e1stops || e2stops || + (e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || + (e1->polyType != e2->polyType && m_ClipType != ctXor) ) + AddLocalMaxPoly(e1, e2, pt); + else + DoBothEdges( e1, e2, pt ); + } + else if ( e1Contributing ) + { + if ((e2Wc == 0 || e2Wc == 1) && + (m_ClipType != ctIntersection || + e2->polyType == ptSubject || (e2->windCnt2 != 0))) + DoEdge1(e1, e2, pt); + } + else if ( e2contributing ) + { + if ((e1Wc == 0 || e1Wc == 1) && + (m_ClipType != ctIntersection || + e1->polyType == ptSubject || (e1->windCnt2 != 0))) + DoEdge2(e1, e2, pt); + } + else if ( (e1Wc == 0 || e1Wc == 1) && + (e2Wc == 0 || e2Wc == 1) && !e1stops && !e2stops ) + { + //neither edge is currently contributing ... + + long64 e1Wc2, e2Wc2; + switch (e1FillType2) + { + case pftPositive: e1Wc2 = e1->windCnt2; break; + case pftNegative : e1Wc2 = -e1->windCnt2; break; + default: e1Wc2 = Abs(e1->windCnt2); + } + switch (e2FillType2) + { + case pftPositive: e2Wc2 = e2->windCnt2; break; + case pftNegative: e2Wc2 = -e2->windCnt2; break; + default: e2Wc2 = Abs(e2->windCnt2); + } + + if (e1->polyType != e2->polyType) + AddLocalMinPoly(e1, e2, pt); + else if (e1Wc == 1 && e2Wc == 1) + switch( m_ClipType ) { + case ctIntersection: + if (e1Wc2 > 0 && e2Wc2 > 0) + AddLocalMinPoly(e1, e2, pt); + break; + case ctUnion: + if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) + AddLocalMinPoly(e1, e2, pt); + break; + case ctDifference: + if (((e1->polyType == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || + ((e1->polyType == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) + AddLocalMinPoly(e1, e2, pt); + break; + case ctXor: + AddLocalMinPoly(e1, e2, pt); + } + else + SwapSides( *e1, *e2 ); + } + + if( (e1stops != e2stops) && + ( (e1stops && (e1->outIdx >= 0)) || (e2stops && (e2->outIdx >= 0)) ) ) + { + SwapSides( *e1, *e2 ); + SwapPolyIndexes( *e1, *e2 ); + } + + //finally, delete any non-contributing maxima edges ... + if( e1stops ) DeleteFromAEL( e1 ); + if( e2stops ) DeleteFromAEL( e2 ); +} +//------------------------------------------------------------------------------ + +void Clipper::SetHoleState(TEdge *e, OutRec *outRec) +{ + bool isHole = false; + TEdge *e2 = e->prevInAEL; + while (e2) + { + if (e2->outIdx >= 0) + { + isHole = !isHole; + if (! outRec->FirstLeft) + outRec->FirstLeft = m_PolyOuts[e2->outIdx]; + } + e2 = e2->prevInAEL; + } + if (isHole) outRec->isHole = true; +} +//------------------------------------------------------------------------------ + +OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) +{ + //work out which polygon fragment has the correct hole state ... + OutPt *outPt1 = outRec1->bottomPt; + OutPt *outPt2 = outRec2->bottomPt; + if (outPt1->pt.Y > outPt2->pt.Y) return outRec1; + else if (outPt1->pt.Y < outPt2->pt.Y) return outRec2; + else if (outPt1->pt.X < outPt2->pt.X) return outRec1; + else if (outPt1->pt.X > outPt2->pt.X) return outRec2; + else if (outPt1->next == outPt1) return outRec2; + else if (outPt2->next == outPt2) return outRec1; + else if (FirstIsBottomPt(outPt1, outPt2)) return outRec1; + else return outRec2; +} +//------------------------------------------------------------------------------ + +bool Param1RightOfParam2(OutRec* outRec1, OutRec* outRec2) +{ + do + { + outRec1 = outRec1->FirstLeft; + if (outRec1 == outRec2) return true; + } while (outRec1); + return false; +} +//------------------------------------------------------------------------------ + +void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) +{ + //get the start and ends of both output polygons ... + OutRec *outRec1 = m_PolyOuts[e1->outIdx]; + OutRec *outRec2 = m_PolyOuts[e2->outIdx]; + + OutRec *holeStateRec; + if (Param1RightOfParam2(outRec1, outRec2)) holeStateRec = outRec2; + else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1; + else holeStateRec = GetLowermostRec(outRec1, outRec2); + + OutPt* p1_lft = outRec1->pts; + OutPt* p1_rt = p1_lft->prev; + OutPt* p2_lft = outRec2->pts; + OutPt* p2_rt = p2_lft->prev; + + EdgeSide side; + //join e2 poly onto e1 poly and delete pointers to e2 ... + if( e1->side == esLeft ) + { + if( e2->side == esLeft ) + { + //z y x a b c + ReversePolyPtLinks(*p2_lft); + p2_lft->next = p1_lft; + p1_lft->prev = p2_lft; + p1_rt->next = p2_rt; + p2_rt->prev = p1_rt; + outRec1->pts = p2_rt; + } else + { + //x y z a b c + p2_rt->next = p1_lft; + p1_lft->prev = p2_rt; + p2_lft->prev = p1_rt; + p1_rt->next = p2_lft; + outRec1->pts = p2_lft; + } + side = esLeft; + } else + { + if( e2->side == esRight ) + { + //a b c z y x + ReversePolyPtLinks( *p2_lft ); + p1_rt->next = p2_rt; + p2_rt->prev = p1_rt; + p2_lft->next = p1_lft; + p1_lft->prev = p2_lft; + } else + { + //a b c x y z + p1_rt->next = p2_lft; + p2_lft->prev = p1_rt; + p1_lft->prev = p2_rt; + p2_rt->next = p1_lft; + } + side = esRight; + } + + if (holeStateRec == outRec2) + { + outRec1->bottomPt = outRec2->bottomPt; + outRec1->bottomPt->idx = outRec1->idx; + if (outRec2->FirstLeft != outRec1) + outRec1->FirstLeft = outRec2->FirstLeft; + outRec1->isHole = outRec2->isHole; + } + outRec2->pts = 0; + outRec2->bottomPt = 0; + outRec2->AppendLink = outRec1; + int OKIdx = e1->outIdx; + int ObsoleteIdx = e2->outIdx; + + e1->outIdx = -1; //nb: safe because we only get here via AddLocalMaxPoly + e2->outIdx = -1; + + TEdge* e = m_ActiveEdges; + while( e ) + { + if( e->outIdx == ObsoleteIdx ) + { + e->outIdx = OKIdx; + e->side = side; + break; + } + e = e->nextInAEL; + } + + for (JoinList::size_type i = 0; i < m_Joins.size(); ++i) + { + if (m_Joins[i]->poly1Idx == ObsoleteIdx) m_Joins[i]->poly1Idx = OKIdx; + if (m_Joins[i]->poly2Idx == ObsoleteIdx) m_Joins[i]->poly2Idx = OKIdx; + } + + for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) + { + if (m_HorizJoins[i]->savedIdx == ObsoleteIdx) + m_HorizJoins[i]->savedIdx = OKIdx; + } + +} +//------------------------------------------------------------------------------ + +OutRec* Clipper::CreateOutRec() +{ + OutRec* result = new OutRec; + result->isHole = false; + result->FirstLeft = 0; + result->AppendLink = 0; + result->pts = 0; + result->bottomPt = 0; + result->sides = esNeither; + result->bottomFlag = 0; + + return result; +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeBottomPt(OutRec &outRec) +{ + OutPt* next = outRec.bottomPt->next; + OutPt* prev = outRec.bottomPt->prev; + if (outRec.pts == outRec.bottomPt) outRec.pts = next; + delete outRec.bottomPt; + next->prev = prev; + prev->next = next; + outRec.bottomPt = next; + FixupOutPolygon(outRec); +} +//------------------------------------------------------------------------------ + +void Clipper::AddOutPt(TEdge *e, const IntPoint &pt) +{ + bool ToFront = (e->side == esLeft); + if( e->outIdx < 0 ) + { + OutRec *outRec = CreateOutRec(); + m_PolyOuts.push_back(outRec); + outRec->idx = (int)m_PolyOuts.size()-1; + e->outIdx = outRec->idx; + OutPt* op = new OutPt; + outRec->pts = op; + outRec->bottomPt = op; + op->pt = pt; + op->idx = outRec->idx; + op->next = op; + op->prev = op; + SetHoleState(e, outRec); + } else + { + OutRec *outRec = m_PolyOuts[e->outIdx]; + OutPt* op = outRec->pts; + if ((ToFront && PointsEqual(pt, op->pt)) || + (!ToFront && PointsEqual(pt, op->prev->pt))) return; + + if ((e->side | outRec->sides) != outRec->sides) + { + //check for 'rounding' artefacts ... + if (outRec->sides == esNeither && pt.Y == op->pt.Y) + { + if (ToFront) + { + if (pt.X == op->pt.X +1) return; //ie wrong side of bottomPt + } + else if (pt.X == op->pt.X -1) return; //ie wrong side of bottomPt + } + + outRec->sides = (EdgeSide)(outRec->sides | e->side); + if (outRec->sides == esBoth) + { + //A vertex from each side has now been added. + //Vertices of one side of an output polygon are quite commonly close to + //or even 'touching' edges of the other side of the output polygon. + //Very occasionally vertices from one side can 'cross' an edge on the + //the other side. The distance 'crossed' is always less that a unit + //and is purely an artefact of coordinate rounding. Nevertheless, this + //results in very tiny self-intersections. Because of the way + //orientation is calculated, even tiny self-intersections can cause + //the Orientation function to return the wrong result. Therefore, it's + //important to ensure that any self-intersections close to BottomPt are + //detected and removed before orientation is assigned. + + OutPt *opBot, *op2; + if (ToFront) + { + opBot = outRec->pts; + op2 = opBot->next; //op2 == right side + if (opBot->pt.Y != op2->pt.Y && opBot->pt.Y != pt.Y && + ((opBot->pt.X - pt.X)/(opBot->pt.Y - pt.Y) < + (opBot->pt.X - op2->pt.X)/(opBot->pt.Y - op2->pt.Y))) + outRec->bottomFlag = opBot; + } else + { + opBot = outRec->pts->prev; + op2 = opBot->prev; //op2 == left side + if (opBot->pt.Y != op2->pt.Y && opBot->pt.Y != pt.Y && + ((opBot->pt.X - pt.X)/(opBot->pt.Y - pt.Y) > + (opBot->pt.X - op2->pt.X)/(opBot->pt.Y - op2->pt.Y))) + outRec->bottomFlag = opBot; + } + } + } + + OutPt* op2 = new OutPt; + op2->pt = pt; + op2->idx = outRec->idx; + if (op2->pt.Y == outRec->bottomPt->pt.Y && + op2->pt.X < outRec->bottomPt->pt.X) + outRec->bottomPt = op2; + op2->next = op; + op2->prev = op->prev; + op2->prev->next = op2; + op->prev = op2; + if (ToFront) outRec->pts = op2; + } +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessHorizontals() +{ + TEdge* horzEdge = m_SortedEdges; + while( horzEdge ) + { + DeleteFromSEL( horzEdge ); + ProcessHorizontal( horzEdge ); + horzEdge = m_SortedEdges; + } +} +//------------------------------------------------------------------------------ + +bool Clipper::IsTopHorz(const long64 XPos) +{ + TEdge* e = m_SortedEdges; + while( e ) + { + if( ( XPos >= std::min(e->xcurr, e->xtop) ) && + ( XPos <= std::max(e->xcurr, e->xtop) ) ) return false; + e = e->nextInSEL; + } + return true; +} +//------------------------------------------------------------------------------ + +bool IsMinima(TEdge *e) +{ + return e && (e->prev->nextInLML != e) && (e->next->nextInLML != e); +} +//------------------------------------------------------------------------------ + +bool IsMaxima(TEdge *e, const long64 Y) +{ + return e && e->ytop == Y && !e->nextInLML; +} +//------------------------------------------------------------------------------ + +bool IsIntermediate(TEdge *e, const long64 Y) +{ + return e->ytop == Y && e->nextInLML; +} +//------------------------------------------------------------------------------ + +TEdge *GetMaximaPair(TEdge *e) +{ + if( !IsMaxima(e->next, e->ytop) || e->next->xtop != e->xtop ) + return e->prev; else + return e->next; +} +//------------------------------------------------------------------------------ + +void Clipper::SwapPositionsInAEL(TEdge *edge1, TEdge *edge2) +{ + if( !edge1->nextInAEL && !edge1->prevInAEL ) return; + if( !edge2->nextInAEL && !edge2->prevInAEL ) return; + + if( edge1->nextInAEL == edge2 ) + { + TEdge* next = edge2->nextInAEL; + if( next ) next->prevInAEL = edge1; + TEdge* prev = edge1->prevInAEL; + if( prev ) prev->nextInAEL = edge2; + edge2->prevInAEL = prev; + edge2->nextInAEL = edge1; + edge1->prevInAEL = edge2; + edge1->nextInAEL = next; + } + else if( edge2->nextInAEL == edge1 ) + { + TEdge* next = edge1->nextInAEL; + if( next ) next->prevInAEL = edge2; + TEdge* prev = edge2->prevInAEL; + if( prev ) prev->nextInAEL = edge1; + edge1->prevInAEL = prev; + edge1->nextInAEL = edge2; + edge2->prevInAEL = edge1; + edge2->nextInAEL = next; + } + else + { + TEdge* next = edge1->nextInAEL; + TEdge* prev = edge1->prevInAEL; + edge1->nextInAEL = edge2->nextInAEL; + if( edge1->nextInAEL ) edge1->nextInAEL->prevInAEL = edge1; + edge1->prevInAEL = edge2->prevInAEL; + if( edge1->prevInAEL ) edge1->prevInAEL->nextInAEL = edge1; + edge2->nextInAEL = next; + if( edge2->nextInAEL ) edge2->nextInAEL->prevInAEL = edge2; + edge2->prevInAEL = prev; + if( edge2->prevInAEL ) edge2->prevInAEL->nextInAEL = edge2; + } + + if( !edge1->prevInAEL ) m_ActiveEdges = edge1; + else if( !edge2->prevInAEL ) m_ActiveEdges = edge2; +} +//------------------------------------------------------------------------------ + +void Clipper::SwapPositionsInSEL(TEdge *edge1, TEdge *edge2) +{ + if( !( edge1->nextInSEL ) && !( edge1->prevInSEL ) ) return; + if( !( edge2->nextInSEL ) && !( edge2->prevInSEL ) ) return; + + if( edge1->nextInSEL == edge2 ) + { + TEdge* next = edge2->nextInSEL; + if( next ) next->prevInSEL = edge1; + TEdge* prev = edge1->prevInSEL; + if( prev ) prev->nextInSEL = edge2; + edge2->prevInSEL = prev; + edge2->nextInSEL = edge1; + edge1->prevInSEL = edge2; + edge1->nextInSEL = next; + } + else if( edge2->nextInSEL == edge1 ) + { + TEdge* next = edge1->nextInSEL; + if( next ) next->prevInSEL = edge2; + TEdge* prev = edge2->prevInSEL; + if( prev ) prev->nextInSEL = edge1; + edge1->prevInSEL = prev; + edge1->nextInSEL = edge2; + edge2->prevInSEL = edge1; + edge2->nextInSEL = next; + } + else + { + TEdge* next = edge1->nextInSEL; + TEdge* prev = edge1->prevInSEL; + edge1->nextInSEL = edge2->nextInSEL; + if( edge1->nextInSEL ) edge1->nextInSEL->prevInSEL = edge1; + edge1->prevInSEL = edge2->prevInSEL; + if( edge1->prevInSEL ) edge1->prevInSEL->nextInSEL = edge1; + edge2->nextInSEL = next; + if( edge2->nextInSEL ) edge2->nextInSEL->prevInSEL = edge2; + edge2->prevInSEL = prev; + if( edge2->prevInSEL ) edge2->prevInSEL->nextInSEL = edge2; + } + + if( !edge1->prevInSEL ) m_SortedEdges = edge1; + else if( !edge2->prevInSEL ) m_SortedEdges = edge2; +} +//------------------------------------------------------------------------------ + +TEdge* GetNextInAEL(TEdge *e, Direction dir) +{ + return dir == dLeftToRight ? e->nextInAEL : e->prevInAEL; +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessHorizontal(TEdge *horzEdge) +{ + Direction dir; + long64 horzLeft, horzRight; + + if( horzEdge->xcurr < horzEdge->xtop ) + { + horzLeft = horzEdge->xcurr; + horzRight = horzEdge->xtop; + dir = dLeftToRight; + } else + { + horzLeft = horzEdge->xtop; + horzRight = horzEdge->xcurr; + dir = dRightToLeft; + } + + TEdge* eMaxPair; + if( horzEdge->nextInLML ) eMaxPair = 0; + else eMaxPair = GetMaximaPair(horzEdge); + + TEdge* e = GetNextInAEL( horzEdge , dir ); + while( e ) + { + TEdge* eNext = GetNextInAEL( e, dir ); + + if (eMaxPair || + ((dir == dLeftToRight) && (e->xcurr <= horzRight)) || + ((dir == dRightToLeft) && (e->xcurr >= horzLeft))) + { + //ok, so far it looks like we're still in range of the horizontal edge + if ( e->xcurr == horzEdge->xtop && !eMaxPair ) + { + if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange)) + { + //if output polygons share an edge, they'll need joining later ... + if (horzEdge->outIdx >= 0 && e->outIdx >= 0) + AddJoin(horzEdge->nextInLML, e, horzEdge->outIdx); + break; //we've reached the end of the horizontal line + } + else if (e->dx < horzEdge->nextInLML->dx) + //we really have got to the end of the intermediate horz edge so quit. + //nb: More -ve slopes follow more +ve slopes ABOVE the horizontal. + break; + } + + if( e == eMaxPair ) + { + //horzEdge is evidently a maxima horizontal and we've arrived at its end. + if (dir == dLeftToRight) + IntersectEdges(horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); + else + IntersectEdges(e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), ipNone); + if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); + return; + } + else if( NEAR_EQUAL(e->dx, HORIZONTAL) && !IsMinima(e) && !(e->xcurr > e->xtop) ) + { + //An overlapping horizontal edge. Overlapping horizontal edges are + //processed as if layered with the current horizontal edge (horizEdge) + //being infinitesimally lower that the next (e). Therfore, we + //intersect with e only if e.xcurr is within the bounds of horzEdge ... + if( dir == dLeftToRight ) + IntersectEdges( horzEdge , e, IntPoint(e->xcurr, horzEdge->ycurr), + (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); + else + IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), + (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); + } + else if( dir == dLeftToRight ) + { + IntersectEdges( horzEdge, e, IntPoint(e->xcurr, horzEdge->ycurr), + (IsTopHorz( e->xcurr ))? ipLeft : ipBoth ); + } + else + { + IntersectEdges( e, horzEdge, IntPoint(e->xcurr, horzEdge->ycurr), + (IsTopHorz( e->xcurr ))? ipRight : ipBoth ); + } + SwapPositionsInAEL( horzEdge, e ); + } + else if( (dir == dLeftToRight && e->xcurr > horzRight && m_SortedEdges) || + (dir == dRightToLeft && e->xcurr < horzLeft && m_SortedEdges) ) break; + e = eNext; + } //end while + + if( horzEdge->nextInLML ) + { + if( horzEdge->outIdx >= 0 ) + AddOutPt( horzEdge, IntPoint(horzEdge->xtop, horzEdge->ytop)); + UpdateEdgeIntoAEL( horzEdge ); + } + else + { + if ( horzEdge->outIdx >= 0 ) + IntersectEdges( horzEdge, eMaxPair, + IntPoint(horzEdge->xtop, horzEdge->ycurr), ipBoth); + if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); + DeleteFromAEL(eMaxPair); + DeleteFromAEL(horzEdge); + } +} +//------------------------------------------------------------------------------ + +void Clipper::UpdateEdgeIntoAEL(TEdge *&e) +{ + if( !e->nextInLML ) throw + clipperException("UpdateEdgeIntoAEL: invalid call"); + TEdge* AelPrev = e->prevInAEL; + TEdge* AelNext = e->nextInAEL; + e->nextInLML->outIdx = e->outIdx; + if( AelPrev ) AelPrev->nextInAEL = e->nextInLML; + else m_ActiveEdges = e->nextInLML; + if( AelNext ) AelNext->prevInAEL = e->nextInLML; + e->nextInLML->side = e->side; + e->nextInLML->windDelta = e->windDelta; + e->nextInLML->windCnt = e->windCnt; + e->nextInLML->windCnt2 = e->windCnt2; + e = e->nextInLML; + e->prevInAEL = AelPrev; + e->nextInAEL = AelNext; + if( !NEAR_EQUAL(e->dx, HORIZONTAL) ) InsertScanbeam( e->ytop ); +} +//------------------------------------------------------------------------------ + +bool Clipper::ProcessIntersections(const long64 botY, const long64 topY) +{ + if( !m_ActiveEdges ) return true; + try { + BuildIntersectList(botY, topY); + if ( !m_IntersectNodes) return true; + if ( FixupIntersections() ) ProcessIntersectList(); + else return false; + } + catch(...) { + m_SortedEdges = 0; + DisposeIntersectNodes(); + throw clipperException("ProcessIntersections error"); + } + return true; +} +//------------------------------------------------------------------------------ + +void Clipper::DisposeIntersectNodes() +{ + while ( m_IntersectNodes ) + { + IntersectNode* iNode = m_IntersectNodes->next; + delete m_IntersectNodes; + m_IntersectNodes = iNode; + } +} +//------------------------------------------------------------------------------ + +void Clipper::BuildIntersectList(const long64 botY, const long64 topY) +{ + if ( !m_ActiveEdges ) return; + + //prepare for sorting ... + TEdge* e = m_ActiveEdges; + e->tmpX = TopX( *e, topY ); + m_SortedEdges = e; + m_SortedEdges->prevInSEL = 0; + e = e->nextInAEL; + while( e ) + { + e->prevInSEL = e->prevInAEL; + e->prevInSEL->nextInSEL = e; + e->nextInSEL = 0; + e->tmpX = TopX( *e, topY ); + e = e->nextInAEL; + } + + //bubblesort ... + bool isModified = true; + while( isModified && m_SortedEdges ) + { + isModified = false; + e = m_SortedEdges; + while( e->nextInSEL ) + { + TEdge *eNext = e->nextInSEL; + IntPoint pt; + if(e->tmpX > eNext->tmpX && + IntersectPoint(*e, *eNext, pt, m_UseFullRange)) + { + if (pt.Y > botY) + { + pt.Y = botY; + pt.X = TopX(*e, pt.Y); + } + AddIntersectNode( e, eNext, pt ); + SwapPositionsInSEL(e, eNext); + isModified = true; + } + else + e = eNext; + } + if( e->prevInSEL ) e->prevInSEL->nextInSEL = 0; + else break; + } + m_SortedEdges = 0; +} +//------------------------------------------------------------------------------ + +bool ProcessParam1BeforeParam2(IntersectNode &node1, IntersectNode &node2) +{ + bool result; + if (node1.pt.Y == node2.pt.Y) + { + if (node1.edge1 == node2.edge1 || node1.edge2 == node2.edge1) + { + result = node2.pt.X > node1.pt.X; + return node2.edge1->dx > 0 ? !result : result; + } + else if (node1.edge1 == node2.edge2 || node1.edge2 == node2.edge2) + { + result = node2.pt.X > node1.pt.X; + return node2.edge2->dx > 0 ? !result : result; + } + else return node2.pt.X > node1.pt.X; + } + else return node1.pt.Y > node2.pt.Y; +} +//------------------------------------------------------------------------------ + +void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt) +{ + IntersectNode* newNode = new IntersectNode; + newNode->edge1 = e1; + newNode->edge2 = e2; + newNode->pt = pt; + newNode->next = 0; + if( !m_IntersectNodes ) m_IntersectNodes = newNode; + else if( ProcessParam1BeforeParam2(*newNode, *m_IntersectNodes) ) + { + newNode->next = m_IntersectNodes; + m_IntersectNodes = newNode; + } + else + { + IntersectNode* iNode = m_IntersectNodes; + while( iNode->next && ProcessParam1BeforeParam2(*iNode->next, *newNode) ) + iNode = iNode->next; + newNode->next = iNode->next; + iNode->next = newNode; + } +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessIntersectList() +{ + while( m_IntersectNodes ) + { + IntersectNode* iNode = m_IntersectNodes->next; + { + IntersectEdges( m_IntersectNodes->edge1 , + m_IntersectNodes->edge2 , m_IntersectNodes->pt, ipBoth ); + SwapPositionsInAEL( m_IntersectNodes->edge1 , m_IntersectNodes->edge2 ); + } + delete m_IntersectNodes; + m_IntersectNodes = iNode; + } +} +//------------------------------------------------------------------------------ + +void Clipper::DoMaxima(TEdge *e, long64 topY) +{ + TEdge* eMaxPair = GetMaximaPair(e); + long64 X = e->xtop; + TEdge* eNext = e->nextInAEL; + while( eNext != eMaxPair ) + { + if (!eNext) throw clipperException("DoMaxima error"); + IntersectEdges( e, eNext, IntPoint(X, topY), ipBoth ); + eNext = eNext->nextInAEL; + } + if( e->outIdx < 0 && eMaxPair->outIdx < 0 ) + { + DeleteFromAEL( e ); + DeleteFromAEL( eMaxPair ); + } + else if( e->outIdx >= 0 && eMaxPair->outIdx >= 0 ) + { + IntersectEdges( e, eMaxPair, IntPoint(X, topY), ipNone ); + } + else throw clipperException("DoMaxima error"); +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY) +{ + TEdge* e = m_ActiveEdges; + while( e ) + { + //1. process maxima, treating them as if they're 'bent' horizontal edges, + // but exclude maxima with horizontal edges. nb: e can't be a horizontal. + if( IsMaxima(e, topY) && !NEAR_EQUAL(GetMaximaPair(e)->dx, HORIZONTAL) ) + { + //'e' might be removed from AEL, as may any following edges so ... + TEdge* ePrior = e->prevInAEL; + DoMaxima(e, topY); + if( !ePrior ) e = m_ActiveEdges; + else e = ePrior->nextInAEL; + } + else + { + //2. promote horizontal edges, otherwise update xcurr and ycurr ... + if( IsIntermediate(e, topY) && NEAR_EQUAL(e->nextInLML->dx, HORIZONTAL) ) + { + if (e->outIdx >= 0) + { + AddOutPt(e, IntPoint(e->xtop, e->ytop)); + + for (HorzJoinList::size_type i = 0; i < m_HorizJoins.size(); ++i) + { + IntPoint pt, pt2; + HorzJoinRec* hj = m_HorizJoins[i]; + if (GetOverlapSegment(IntPoint(hj->edge->xbot, hj->edge->ybot), + IntPoint(hj->edge->xtop, hj->edge->ytop), + IntPoint(e->nextInLML->xbot, e->nextInLML->ybot), + IntPoint(e->nextInLML->xtop, e->nextInLML->ytop), pt, pt2)) + AddJoin(hj->edge, e->nextInLML, hj->savedIdx, e->outIdx); + } + + AddHorzJoin(e->nextInLML, e->outIdx); + } + UpdateEdgeIntoAEL(e); + AddEdgeToSEL(e); + } else + { + //this just simplifies horizontal processing ... + e->xcurr = TopX( *e, topY ); + e->ycurr = topY; + } + e = e->nextInAEL; + } + } + + //3. Process horizontals at the top of the scanbeam ... + ProcessHorizontals(); + + //4. Promote intermediate vertices ... + e = m_ActiveEdges; + while( e ) + { + if( IsIntermediate( e, topY ) ) + { + if( e->outIdx >= 0 ) AddOutPt(e, IntPoint(e->xtop,e->ytop)); + UpdateEdgeIntoAEL(e); + + //if output polygons share an edge, they'll need joining later ... + if (e->outIdx >= 0 && e->prevInAEL && e->prevInAEL->outIdx >= 0 && + e->prevInAEL->xcurr == e->xbot && e->prevInAEL->ycurr == e->ybot && + SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), + IntPoint(e->xbot,e->ybot), + IntPoint(e->prevInAEL->xtop, e->prevInAEL->ytop), m_UseFullRange)) + { + AddOutPt(e->prevInAEL, IntPoint(e->xbot, e->ybot)); + AddJoin(e, e->prevInAEL); + } + else if (e->outIdx >= 0 && e->nextInAEL && e->nextInAEL->outIdx >= 0 && + e->nextInAEL->ycurr > e->nextInAEL->ytop && + e->nextInAEL->ycurr <= e->nextInAEL->ybot && + e->nextInAEL->xcurr == e->xbot && e->nextInAEL->ycurr == e->ybot && + SlopesEqual(IntPoint(e->xbot,e->ybot), IntPoint(e->xtop, e->ytop), + IntPoint(e->xbot,e->ybot), + IntPoint(e->nextInAEL->xtop, e->nextInAEL->ytop), m_UseFullRange)) + { + AddOutPt(e->nextInAEL, IntPoint(e->xbot, e->ybot)); + AddJoin(e, e->nextInAEL); + } + } + e = e->nextInAEL; + } +} +//------------------------------------------------------------------------------ + +void Clipper::FixupOutPolygon(OutRec &outRec) +{ + //FixupOutPolygon() - removes duplicate points and simplifies consecutive + //parallel edges by removing the middle vertex. + OutPt *lastOK = 0; + outRec.pts = outRec.bottomPt; + OutPt *pp = outRec.bottomPt; + + for (;;) + { + if (pp->prev == pp || pp->prev == pp->next ) + { + DisposeOutPts(pp); + outRec.pts = 0; + outRec.bottomPt = 0; + return; + } + //test for duplicate points and for same slope (cross-product) ... + if ( PointsEqual(pp->pt, pp->next->pt) || + SlopesEqual(pp->prev->pt, pp->pt, pp->next->pt, m_UseFullRange) ) + { + lastOK = 0; + OutPt *tmp = pp; + if (pp == outRec.bottomPt) + outRec.bottomPt = 0; //flags need for updating + pp->prev->next = pp->next; + pp->next->prev = pp->prev; + pp = pp->prev; + delete tmp; + } + else if (pp == lastOK) break; + else + { + if (!lastOK) lastOK = pp; + pp = pp->next; + } + } + if (!outRec.bottomPt) { + outRec.bottomPt = GetBottomPt(pp); + outRec.bottomPt->idx = outRec.idx; + outRec.pts = outRec.bottomPt; + } +} +//------------------------------------------------------------------------------ + +void Clipper::BuildResult(Polygons &polys) +{ + int k = 0; + polys.resize(m_PolyOuts.size()); + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + if (m_PolyOuts[i]->pts) + { + Polygon* pg = &polys[k]; + pg->clear(); + OutPt* p = m_PolyOuts[i]->pts; + do + { + pg->push_back(p->pt); + p = p->next; + } while (p != m_PolyOuts[i]->pts); + //make sure each polygon has at least 3 vertices ... + if (pg->size() < 3) pg->clear(); else k++; + } + } + polys.resize(k); +} +//------------------------------------------------------------------------------ + +void Clipper::BuildResultEx(ExPolygons &polys) +{ + PolyOutList::size_type i = 0; + int k = 0; + polys.resize(0); + polys.reserve(m_PolyOuts.size()); + while (i < m_PolyOuts.size() && m_PolyOuts[i]->pts) + { + ExPolygon epg; + OutPt* p = m_PolyOuts[i]->pts; + do { + epg.outer.push_back(p->pt); + p = p->next; + } while (p != m_PolyOuts[i]->pts); + i++; + //make sure polygons have at least 3 vertices ... + if (epg.outer.size() < 3) continue; + while (i < m_PolyOuts.size() + && m_PolyOuts[i]->pts && m_PolyOuts[i]->isHole) + { + Polygon pg; + p = m_PolyOuts[i]->pts; + do { + pg.push_back(p->pt); + p = p->next; + } while (p != m_PolyOuts[i]->pts); + epg.holes.push_back(pg); + i++; + } + polys.push_back(epg); + k++; + } + polys.resize(k); +} +//------------------------------------------------------------------------------ + +void SwapIntersectNodes(IntersectNode &int1, IntersectNode &int2) +{ + TEdge *e1 = int1.edge1; + TEdge *e2 = int1.edge2; + IntPoint p = int1.pt; + + int1.edge1 = int2.edge1; + int1.edge2 = int2.edge2; + int1.pt = int2.pt; + + int2.edge1 = e1; + int2.edge2 = e2; + int2.pt = p; +} +//------------------------------------------------------------------------------ + +bool Clipper::FixupIntersections() +{ + if ( !m_IntersectNodes->next ) return true; + + CopyAELToSEL(); + IntersectNode *int1 = m_IntersectNodes; + IntersectNode *int2 = m_IntersectNodes->next; + while (int2) + { + TEdge *e1 = int1->edge1; + TEdge *e2; + if (e1->prevInSEL == int1->edge2) e2 = e1->prevInSEL; + else if (e1->nextInSEL == int1->edge2) e2 = e1->nextInSEL; + else + { + //The current intersection is out of order, so try and swap it with + //a subsequent intersection ... + while (int2) + { + if (int2->edge1->nextInSEL == int2->edge2 || + int2->edge1->prevInSEL == int2->edge2) break; + else int2 = int2->next; + } + if ( !int2 ) return false; //oops!!! + + //found an intersect node that can be swapped ... + SwapIntersectNodes(*int1, *int2); + e1 = int1->edge1; + e2 = int1->edge2; + } + SwapPositionsInSEL(e1, e2); + int1 = int1->next; + int2 = int1->next; + } + + m_SortedEdges = 0; + + //finally, check the last intersection too ... + return (int1->edge1->prevInSEL == int1->edge2 || + int1->edge1->nextInSEL == int1->edge2); +} +//------------------------------------------------------------------------------ + +bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) +{ + return e2.xcurr == e1.xcurr ? e2.dx > e1.dx : e2.xcurr < e1.xcurr; +} +//------------------------------------------------------------------------------ + +void Clipper::InsertEdgeIntoAEL(TEdge *edge) +{ + edge->prevInAEL = 0; + edge->nextInAEL = 0; + if( !m_ActiveEdges ) + { + m_ActiveEdges = edge; + } + else if( E2InsertsBeforeE1(*m_ActiveEdges, *edge) ) + { + edge->nextInAEL = m_ActiveEdges; + m_ActiveEdges->prevInAEL = edge; + m_ActiveEdges = edge; + } else + { + TEdge* e = m_ActiveEdges; + while( e->nextInAEL && !E2InsertsBeforeE1(*e->nextInAEL , *edge) ) + e = e->nextInAEL; + edge->nextInAEL = e->nextInAEL; + if( e->nextInAEL ) e->nextInAEL->prevInAEL = edge; + edge->prevInAEL = e; + e->nextInAEL = edge; + } +} +//---------------------------------------------------------------------- + +void Clipper::DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt) +{ + AddOutPt(edge1, pt); + SwapSides(*edge1, *edge2); + SwapPolyIndexes(*edge1, *edge2); +} +//---------------------------------------------------------------------- + +void Clipper::DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt) +{ + AddOutPt(edge2, pt); + SwapSides(*edge1, *edge2); + SwapPolyIndexes(*edge1, *edge2); +} +//---------------------------------------------------------------------- + +void Clipper::DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt) +{ + AddOutPt(edge1, pt); + AddOutPt(edge2, pt); + SwapSides( *edge1 , *edge2 ); + SwapPolyIndexes( *edge1 , *edge2 ); +} +//---------------------------------------------------------------------- + +void Clipper::CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2) +{ + //when a polygon is split into 2 polygons, make sure any holes the original + //polygon contained link to the correct polygon ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + { + OutRec *orec = m_PolyOuts[i]; + if (orec->isHole && orec->bottomPt && orec->FirstLeft == outRec1 && + !PointInPolygon(orec->bottomPt->pt, outRec1->pts, m_UseFullRange)) + orec->FirstLeft = outRec2; + } +} +//---------------------------------------------------------------------- + +void Clipper::CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2) +{ + //if a hole is owned by outRec2 then make it owned by outRec1 ... + for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) + if (m_PolyOuts[i]->isHole && m_PolyOuts[i]->bottomPt && + m_PolyOuts[i]->FirstLeft == outRec2) + m_PolyOuts[i]->FirstLeft = outRec1; +} +//---------------------------------------------------------------------- + +void Clipper::JoinCommonEdges(bool fixHoleLinkages) +{ + for (JoinList::size_type i = 0; i < m_Joins.size(); i++) + { + JoinRec* j = m_Joins[i]; + OutRec *outRec1 = m_PolyOuts[j->poly1Idx]; + OutPt *pp1a = outRec1->pts; + OutRec *outRec2 = m_PolyOuts[j->poly2Idx]; + OutPt *pp2a = outRec2->pts; + IntPoint pt1 = j->pt2a, pt2 = j->pt2b; + IntPoint pt3 = j->pt1a, pt4 = j->pt1b; + if (!FindSegment(pp1a, pt1, pt2)) continue; + if (j->poly1Idx == j->poly2Idx) + { + //we're searching the same polygon for overlapping segments so + //segment 2 mustn't be the same as segment 1 ... + pp2a = pp1a->next; + if (!FindSegment(pp2a, pt3, pt4) || (pp2a == pp1a)) continue; + } + else if (!FindSegment(pp2a, pt3, pt4)) continue; + + if (!GetOverlapSegment(pt1, pt2, pt3, pt4, pt1, pt2)) continue; + + OutPt *p1, *p2, *p3, *p4; + OutPt *prev = pp1a->prev; + //get p1 & p2 polypts - the overlap start & endpoints on poly1 + if (PointsEqual(pp1a->pt, pt1)) p1 = pp1a; + else if (PointsEqual(prev->pt, pt1)) p1 = prev; + else p1 = InsertPolyPtBetween(pp1a, prev, pt1); + + if (PointsEqual(pp1a->pt, pt2)) p2 = pp1a; + else if (PointsEqual(prev->pt, pt2)) p2 = prev; + else if ((p1 == pp1a) || (p1 == prev)) + p2 = InsertPolyPtBetween(pp1a, prev, pt2); + else if (Pt3IsBetweenPt1AndPt2(pp1a->pt, p1->pt, pt2)) + p2 = InsertPolyPtBetween(pp1a, p1, pt2); else + p2 = InsertPolyPtBetween(p1, prev, pt2); + + //get p3 & p4 polypts - the overlap start & endpoints on poly2 + prev = pp2a->prev; + if (PointsEqual(pp2a->pt, pt1)) p3 = pp2a; + else if (PointsEqual(prev->pt, pt1)) p3 = prev; + else p3 = InsertPolyPtBetween(pp2a, prev, pt1); + + if (PointsEqual(pp2a->pt, pt2)) p4 = pp2a; + else if (PointsEqual(prev->pt, pt2)) p4 = prev; + else if ((p3 == pp2a) || (p3 == prev)) + p4 = InsertPolyPtBetween(pp2a, prev, pt2); + else if (Pt3IsBetweenPt1AndPt2(pp2a->pt, p3->pt, pt2)) + p4 = InsertPolyPtBetween(pp2a, p3, pt2); else + p4 = InsertPolyPtBetween(p3, prev, pt2); + + //p1.pt == p3.pt and p2.pt == p4.pt so join p1 to p3 and p2 to p4 ... + if (p1->next == p2 && p3->prev == p4) + { + p1->next = p3; + p3->prev = p1; + p2->prev = p4; + p4->next = p2; + } + else if (p1->prev == p2 && p3->next == p4) + { + p1->prev = p3; + p3->next = p1; + p2->next = p4; + p4->prev = p2; + } + else + continue; //an orientation is probably wrong + + if (j->poly2Idx == j->poly1Idx) + { + //instead of joining two polygons, we've just created a new one by + //splitting one polygon into two. + outRec1->pts = GetBottomPt(p1); + outRec1->bottomPt = outRec1->pts; + outRec1->bottomPt->idx = outRec1->idx; + outRec2 = CreateOutRec(); + m_PolyOuts.push_back(outRec2); + outRec2->idx = (int)m_PolyOuts.size()-1; + j->poly2Idx = outRec2->idx; + outRec2->pts = GetBottomPt(p2); + outRec2->bottomPt = outRec2->pts; + outRec2->bottomPt->idx = outRec2->idx; + + if (PointInPolygon(outRec2->pts->pt, outRec1->pts, m_UseFullRange)) + { + //outRec2 is contained by outRec1 ... + outRec2->isHole = !outRec1->isHole; + outRec2->FirstLeft = outRec1; + if (outRec2->isHole == + (m_ReverseOutput ^ Orientation(outRec2, m_UseFullRange))) + ReversePolyPtLinks(*outRec2->pts); + } else if (PointInPolygon(outRec1->pts->pt, outRec2->pts, m_UseFullRange)) + { + //outRec1 is contained by outRec2 ... + outRec2->isHole = outRec1->isHole; + outRec1->isHole = !outRec2->isHole; + outRec2->FirstLeft = outRec1->FirstLeft; + outRec1->FirstLeft = outRec2; + if (outRec1->isHole == + (m_ReverseOutput ^ Orientation(outRec1, m_UseFullRange))) + ReversePolyPtLinks(*outRec1->pts); + //make sure any contained holes now link to the correct polygon ... + if (fixHoleLinkages) CheckHoleLinkages1(outRec1, outRec2); + } else + { + outRec2->isHole = outRec1->isHole; + outRec2->FirstLeft = outRec1->FirstLeft; + //make sure any contained holes now link to the correct polygon ... + if (fixHoleLinkages) CheckHoleLinkages1(outRec1, outRec2); + } + + //now fixup any subsequent joins that match this polygon + for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) + { + JoinRec* j2 = m_Joins[k]; + if (j2->poly1Idx == j->poly1Idx && PointIsVertex(j2->pt1a, p2)) + j2->poly1Idx = j->poly2Idx; + if (j2->poly2Idx == j->poly1Idx && PointIsVertex(j2->pt2a, p2)) + j2->poly2Idx = j->poly2Idx; + } + + //now cleanup redundant edges too ... + FixupOutPolygon(*outRec1); + FixupOutPolygon(*outRec2); + + if (Orientation(outRec1, m_UseFullRange) != (Area(*outRec1, m_UseFullRange) > 0)) + DisposeBottomPt(*outRec1); + if (Orientation(outRec2, m_UseFullRange) != (Area(*outRec2, m_UseFullRange) > 0)) + DisposeBottomPt(*outRec2); + + } else + { + //joined 2 polygons together ... + + //make sure any holes contained by outRec2 now link to outRec1 ... + if (fixHoleLinkages) CheckHoleLinkages2(outRec1, outRec2); + + //now cleanup redundant edges too ... + FixupOutPolygon(*outRec1); + + if (outRec1->pts) + { + outRec1->isHole = !Orientation(outRec1, m_UseFullRange); + if (outRec1->isHole && !outRec1->FirstLeft) + outRec1->FirstLeft = outRec2->FirstLeft; + } + + //delete the obsolete pointer ... + int OKIdx = outRec1->idx; + int ObsoleteIdx = outRec2->idx; + outRec2->pts = 0; + outRec2->bottomPt = 0; + outRec2->AppendLink = outRec1; + + //now fixup any subsequent Joins that match this polygon + for (JoinList::size_type k = i+1; k < m_Joins.size(); k++) + { + JoinRec* j2 = m_Joins[k]; + if (j2->poly1Idx == ObsoleteIdx) j2->poly1Idx = OKIdx; + if (j2->poly2Idx == ObsoleteIdx) j2->poly2Idx = OKIdx; + } + } + } +} +//------------------------------------------------------------------------------ + +void ReversePolygon(Polygon& p) +{ + std::reverse(p.begin(), p.end()); +} +//------------------------------------------------------------------------------ + +void ReversePolygons(Polygons& p) +{ + for (Polygons::size_type i = 0; i < p.size(); ++i) + ReversePolygon(p[i]); +} + +//------------------------------------------------------------------------------ +// OffsetPolygon functions ... +//------------------------------------------------------------------------------ + +struct DoublePoint +{ + double X; + double Y; + DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} +}; +//------------------------------------------------------------------------------ + +Polygon BuildArc(const IntPoint &pt, + const double a1, const double a2, const double r) +{ + long64 steps = std::max(6, int(std::sqrt(std::fabs(r)) * std::fabs(a2 - a1))); + if (steps > 0x100000) steps = 0x100000; + int n = (unsigned)steps; + Polygon result(n); + double da = (a2 - a1) / (n -1); + double a = a1; + for (int i = 0; i < n; ++i) + { + result[i].X = pt.X + Round(std::cos(a)*r); + result[i].Y = pt.Y + Round(std::sin(a)*r); + a += da; + } + return result; +} +//------------------------------------------------------------------------------ + +DoublePoint GetUnitNormal( const IntPoint &pt1, const IntPoint &pt2) +{ + if(pt2.X == pt1.X && pt2.Y == pt1.Y) + return DoublePoint(0, 0); + + double dx = (double)(pt2.X - pt1.X); + double dy = (double)(pt2.Y - pt1.Y); + double f = 1 *1.0/ std::sqrt( dx*dx + dy*dy ); + dx *= f; + dy *= f; + return DoublePoint(dy, -dx); +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +class PolyOffsetBuilder +{ +private: + Polygons m_p; + Polygon* m_curr_poly; + std::vector normals; + double m_delta, m_RMin, m_R; + size_t m_i, m_j, m_k; + static const int buffLength = 128; + JoinType m_jointype; + +public: + +PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys, + double delta, JoinType jointype, double MiterLimit) +{ + //nb precondition - out_polys != ptsin_polys + if (NEAR_ZERO(delta)) + { + out_polys = in_polys; + return; + } + + this->m_p = in_polys; + this->m_delta = delta; + this->m_jointype = jointype; + if (MiterLimit <= 1) MiterLimit = 1; + m_RMin = 2/(MiterLimit*MiterLimit); + + double deltaSq = delta*delta; + out_polys.clear(); + out_polys.resize(in_polys.size()); + for (m_i = 0; m_i < in_polys.size(); m_i++) + { + m_curr_poly = &out_polys[m_i]; + size_t len = in_polys[m_i].size(); + if (len > 1 && m_p[m_i][0].X == m_p[m_i][len - 1].X && + m_p[m_i][0].Y == m_p[m_i][len-1].Y) len--; + + //when 'shrinking' polygons - to minimize artefacts + //strip those polygons that have an area < pi * delta^2 ... + double a1 = Area(in_polys[m_i]); + if (delta < 0) { if (a1 > 0 && a1 < deltaSq *pi) len = 0; } + else if (a1 < 0 && -a1 < deltaSq *pi) len = 0; //holes have neg. area + + if (len == 0 || (len < 3 && delta <= 0)) + continue; + else if (len == 1) + { + Polygon arc; + arc = BuildArc(in_polys[m_i][len-1], 0, 2 * pi, delta); + out_polys[m_i] = arc; + continue; + } + + //build normals ... + normals.clear(); + normals.resize(len); + normals[len-1] = GetUnitNormal(in_polys[m_i][len-1], in_polys[m_i][0]); + for (m_j = 0; m_j < len -1; ++m_j) + normals[m_j] = GetUnitNormal(in_polys[m_i][m_j], in_polys[m_i][m_j+1]); + + m_k = len -1; + for (m_j = 0; m_j < len; ++m_j) + { + switch (jointype) + { + case jtMiter: + { + m_R = 1 + (normals[m_j].X*normals[m_k].X + + normals[m_j].Y*normals[m_k].Y); + if (m_R >= m_RMin) DoMiter(); else DoSquare(MiterLimit); + break; + } + case jtSquare: DoSquare(); break; + case jtRound: DoRound(); break; + } + m_k = m_j; + } + } + + //finally, clean up untidy corners using Clipper ... + Clipper clpr; + clpr.AddPolygons(out_polys, ptSubject); + if (delta > 0) + { + if (!clpr.Execute(ctUnion, out_polys, pftPositive, pftPositive)) + out_polys.clear(); + } + else + { + IntRect r = clpr.GetBounds(); + Polygon outer(4); + outer[0] = IntPoint(r.left - 10, r.bottom + 10); + outer[1] = IntPoint(r.right + 10, r.bottom + 10); + outer[2] = IntPoint(r.right + 10, r.top - 10); + outer[3] = IntPoint(r.left - 10, r.top - 10); + + clpr.AddPolygon(outer, ptSubject); + if (clpr.Execute(ctUnion, out_polys, pftNegative, pftNegative)) + { + out_polys.erase(out_polys.begin()); + ReversePolygons(out_polys); + + } else + out_polys.clear(); + } +} +//------------------------------------------------------------------------------ + +private: + +void AddPoint(const IntPoint& pt) +{ + Polygon::size_type len = m_curr_poly->size(); + if (len == m_curr_poly->capacity()) + m_curr_poly->reserve(len + buffLength); + m_curr_poly->push_back(pt); +} +//------------------------------------------------------------------------------ + +void DoSquare(double mul = 1.0) +{ + IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), + (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); + IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), + (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); + if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) + { + double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); + double a2 = std::atan2(-normals[m_j].Y, -normals[m_j].X); + a1 = std::fabs(a2 - a1); + if (a1 > pi) a1 = pi * 2 - a1; + double dx = std::tan((pi - a1)/4) * std::fabs(m_delta * mul); + pt1 = IntPoint((long64)(pt1.X -normals[m_k].Y * dx), + (long64)(pt1.Y + normals[m_k].X * dx)); + AddPoint(pt1); + pt2 = IntPoint((long64)(pt2.X + normals[m_j].Y * dx), + (long64)(pt2.Y -normals[m_j].X * dx)); + AddPoint(pt2); + } + else + { + AddPoint(pt1); + AddPoint(m_p[m_i][m_j]); + AddPoint(pt2); + } +} +//------------------------------------------------------------------------------ + +void DoMiter() +{ + if ((normals[m_k].X * normals[m_j].Y - normals[m_j].X * normals[m_k].Y) * m_delta >= 0) + { + double q = m_delta / m_R; + AddPoint(IntPoint((long64)Round(m_p[m_i][m_j].X + + (normals[m_k].X + normals[m_j].X) * q), + (long64)Round(m_p[m_i][m_j].Y + (normals[m_k].Y + normals[m_j].Y) * q))); + } + else + { + IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * + m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); + IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * + m_delta), (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); + AddPoint(pt1); + AddPoint(m_p[m_i][m_j]); + AddPoint(pt2); + } +} +//------------------------------------------------------------------------------ + +void DoRound() +{ + IntPoint pt1 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_k].X * m_delta), + (long64)Round(m_p[m_i][m_j].Y + normals[m_k].Y * m_delta)); + IntPoint pt2 = IntPoint((long64)Round(m_p[m_i][m_j].X + normals[m_j].X * m_delta), + (long64)Round(m_p[m_i][m_j].Y + normals[m_j].Y * m_delta)); + AddPoint(pt1); + //round off reflex angles (ie > 180 deg) unless almost flat (ie < ~10deg). + if ((normals[m_k].X*normals[m_j].Y - normals[m_j].X*normals[m_k].Y) * m_delta >= 0) + { + if (normals[m_j].X * normals[m_k].X + normals[m_j].Y * normals[m_k].Y < 0.985) + { + double a1 = std::atan2(normals[m_k].Y, normals[m_k].X); + double a2 = std::atan2(normals[m_j].Y, normals[m_j].X); + if (m_delta > 0 && a2 < a1) a2 += pi *2; + else if (m_delta < 0 && a2 > a1) a2 -= pi *2; + Polygon arc = BuildArc(m_p[m_i][m_j], a1, a2, m_delta); + for (Polygon::size_type m = 0; m < arc.size(); m++) + AddPoint(arc[m]); + } + } + else + AddPoint(m_p[m_i][m_j]); + AddPoint(pt2); +} +//-------------------------------------------------------------------------- + +}; //end PolyOffsetBuilder + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, + double delta, JoinType jointype, double MiterLimit) +{ + if (&out_polys == &in_polys) + { + Polygons poly2(in_polys); + PolyOffsetBuilder(poly2, out_polys, delta, jointype, MiterLimit); + } + else PolyOffsetBuilder(in_polys, out_polys, delta, jointype, MiterLimit); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType) +{ + Clipper c; + c.AddPolygon(in_poly, ptSubject); + c.Execute(ctUnion, out_polys, fillType, fillType); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType) +{ + Clipper c; + c.AddPolygons(in_polys, ptSubject); + c.Execute(ctUnion, out_polys, fillType, fillType); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygons(Polygons &polys, PolyFillType fillType) +{ + SimplifyPolygons(polys, polys, fillType); +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, IntPoint& p) +{ + s << p.X << ' ' << p.Y << "\n"; + return s; +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, Polygon &p) +{ + for (Polygon::size_type i = 0; i < p.size(); i++) + s << p[i]; + s << "\n"; + return s; +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, Polygons &p) +{ + for (Polygons::size_type i = 0; i < p.size(); i++) + s << p[i]; + s << "\n"; + return s; +} +//------------------------------------------------------------------------------ + +} //ClipperLib namespace diff --git a/contrib/clipper/clipper.hpp b/contrib/clipper/clipper.hpp index 7cbe898df..f6f196d0d 100644 --- a/contrib/clipper/clipper.hpp +++ b/contrib/clipper/clipper.hpp @@ -1,306 +1,306 @@ -/******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 4.8.8 * -* Date : 30 August 2012 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2012 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -* Attributions: * -* The code in this library is an extension of Bala Vatti's clipping algorithm: * -* "A generic solution to polygon clipping" * -* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * -* http://portal.acm.org/citation.cfm?id=129906 * -* * -* Computer graphics and geometric modeling: implementation and algorithms * -* By Max K. Agoston * -* Springer; 1 edition (January 4, 2005) * -* http://books.google.com/books?q=vatti+clipping+agoston * -* * -* See also: * -* "Polygon Offsetting by Computing Winding Numbers" * -* Paper no. DETC2005-85513 pp. 565-575 * -* ASME 2005 International Design Engineering Technical Conferences * -* and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24–28, 2005 , Long Beach, California, USA * -* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * -* * -*******************************************************************************/ - -#ifndef clipper_hpp -#define clipper_hpp - -#include -#include -#include -#include -#include - -namespace ClipperLib { - -enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; -enum PolyType { ptSubject, ptClip }; -//By far the most widely used winding rules for polygon filling are -//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) -//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) -//see http://glprogramming.com/red/chapter11.html -enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; - -typedef signed long long long64; -typedef unsigned long long ulong64; - -struct IntPoint { -public: - long64 X; - long64 Y; - IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {}; - friend std::ostream& operator <<(std::ostream &s, IntPoint &p); -}; - -typedef std::vector< IntPoint > Polygon; -typedef std::vector< Polygon > Polygons; - -std::ostream& operator <<(std::ostream &s, Polygon &p); -std::ostream& operator <<(std::ostream &s, Polygons &p); - -struct ExPolygon { - Polygon outer; - Polygons holes; -}; -typedef std::vector< ExPolygon > ExPolygons; - -enum JoinType { jtSquare, jtRound, jtMiter }; - -bool Orientation(const Polygon &poly); -double Area(const Polygon &poly); -void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, - double delta, JoinType jointype = jtSquare, double MiterLimit = 2); -void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd); -void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd); -void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd); - -void ReversePolygon(Polygon& p); -void ReversePolygons(Polygons& p); - -//used internally ... -enum EdgeSide { esNeither = 0, esLeft = 1, esRight = 2, esBoth = 3 }; -enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 }; - -struct TEdge { - long64 xbot; - long64 ybot; - long64 xcurr; - long64 ycurr; - long64 xtop; - long64 ytop; - double dx; - long64 tmpX; - PolyType polyType; - EdgeSide side; - int windDelta; //1 or -1 depending on winding direction - int windCnt; - int windCnt2; //winding count of the opposite polytype - int outIdx; - TEdge *next; - TEdge *prev; - TEdge *nextInLML; - TEdge *nextInAEL; - TEdge *prevInAEL; - TEdge *nextInSEL; - TEdge *prevInSEL; -}; - -struct IntersectNode { - TEdge *edge1; - TEdge *edge2; - IntPoint pt; - IntersectNode *next; -}; - -struct LocalMinima { - long64 Y; - TEdge *leftBound; - TEdge *rightBound; - LocalMinima *next; -}; - -struct Scanbeam { - long64 Y; - Scanbeam *next; -}; - -struct OutPt; //forward declaration - -struct OutRec { - int idx; - bool isHole; - OutRec *FirstLeft; - OutRec *AppendLink; - OutPt *pts; - OutPt *bottomPt; - OutPt *bottomFlag; - EdgeSide sides; -}; - -struct OutPt { - int idx; - IntPoint pt; - OutPt *next; - OutPt *prev; -}; - -struct JoinRec { - IntPoint pt1a; - IntPoint pt1b; - int poly1Idx; - IntPoint pt2a; - IntPoint pt2b; - int poly2Idx; -}; - -struct HorzJoinRec { - TEdge *edge; - int savedIdx; -}; - -struct IntRect { long64 left; long64 top; long64 right; long64 bottom; }; - -typedef std::vector < OutRec* > PolyOutList; -typedef std::vector < TEdge* > EdgeList; -typedef std::vector < JoinRec* > JoinList; -typedef std::vector < HorzJoinRec* > HorzJoinList; - -//ClipperBase is the ancestor to the Clipper class. It should not be -//instantiated directly. This class simply abstracts the conversion of sets of -//polygon coordinates into edge objects that are stored in a LocalMinima list. -class ClipperBase -{ -public: - ClipperBase(); - virtual ~ClipperBase(); - bool AddPolygon(const Polygon &pg, PolyType polyType); - bool AddPolygons( const Polygons &ppg, PolyType polyType); - virtual void Clear(); - IntRect GetBounds(); -protected: - void DisposeLocalMinimaList(); - TEdge* AddBoundsToLML(TEdge *e); - void PopLocalMinima(); - virtual void Reset(); - void InsertLocalMinima(LocalMinima *newLm); - LocalMinima *m_CurrentLM; - LocalMinima *m_MinimaList; - bool m_UseFullRange; - EdgeList m_edges; -}; - -class Clipper : public virtual ClipperBase -{ -public: - Clipper(); - ~Clipper(); - bool Execute(ClipType clipType, - Polygons &solution, - PolyFillType subjFillType = pftEvenOdd, - PolyFillType clipFillType = pftEvenOdd); - bool Execute(ClipType clipType, - ExPolygons &solution, - PolyFillType subjFillType = pftEvenOdd, - PolyFillType clipFillType = pftEvenOdd); - void Clear(); - bool ReverseSolution() {return m_ReverseOutput;}; - void ReverseSolution(bool value) {m_ReverseOutput = value;}; -protected: - void Reset(); - virtual bool ExecuteInternal(bool fixHoleLinkages); -private: - PolyOutList m_PolyOuts; - JoinList m_Joins; - HorzJoinList m_HorizJoins; - ClipType m_ClipType; - Scanbeam *m_Scanbeam; - TEdge *m_ActiveEdges; - TEdge *m_SortedEdges; - IntersectNode *m_IntersectNodes; - bool m_ExecuteLocked; - PolyFillType m_ClipFillType; - PolyFillType m_SubjFillType; - bool m_ReverseOutput; - void DisposeScanbeamList(); - void SetWindingCount(TEdge& edge); - bool IsEvenOddFillType(const TEdge& edge) const; - bool IsEvenOddAltFillType(const TEdge& edge) const; - void InsertScanbeam(const long64 Y); - long64 PopScanbeam(); - void InsertLocalMinimaIntoAEL(const long64 botY); - void InsertEdgeIntoAEL(TEdge *edge); - void AddEdgeToSEL(TEdge *edge); - void CopyAELToSEL(); - void DeleteFromSEL(TEdge *e); - void DeleteFromAEL(TEdge *e); - void UpdateEdgeIntoAEL(TEdge *&e); - void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); - bool IsContributing(const TEdge& edge) const; - bool IsTopHorz(const long64 XPos); - void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); - void DoMaxima(TEdge *e, long64 topY); - void ProcessHorizontals(); - void ProcessHorizontal(TEdge *horzEdge); - void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); - void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); - void AppendPolygon(TEdge *e1, TEdge *e2); - void DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt); - void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt); - void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt); - void IntersectEdges(TEdge *e1, TEdge *e2, - const IntPoint &pt, IntersectProtects protects); - OutRec* CreateOutRec(); - void AddOutPt(TEdge *e, const IntPoint &pt); - void DisposeBottomPt(OutRec &outRec); - void DisposeAllPolyPts(); - void DisposeOutRec(PolyOutList::size_type index); - bool ProcessIntersections(const long64 botY, const long64 topY); - void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt); - void BuildIntersectList(const long64 botY, const long64 topY); - void ProcessIntersectList(); - void ProcessEdgesAtTopOfScanbeam(const long64 topY); - void BuildResult(Polygons& polys); - void BuildResultEx(ExPolygons& polys); - void SetHoleState(TEdge *e, OutRec *OutRec); - void DisposeIntersectNodes(); - bool FixupIntersections(); - void FixupOutPolygon(OutRec &outRec); - bool IsHole(TEdge *e); - void FixHoleLinkage(OutRec *outRec); - void CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2); - void CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2); - void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1); - void ClearJoins(); - void AddHorzJoin(TEdge *e, int idx); - void ClearHorzJoins(); - void JoinCommonEdges(bool fixHoleLinkages); -}; - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ - -class clipperException : public std::exception -{ - public: - clipperException(const char* description): m_descr(description) {} - virtual ~clipperException() throw() {} - virtual const char* what() const throw() {return m_descr.c_str();} - private: - std::string m_descr; -}; -//------------------------------------------------------------------------------ - -} //ClipperLib namespace - -#endif //clipper_hpp - - +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 4.8.8 * +* Date : 30 August 2012 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2012 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24–28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +#ifndef clipper_hpp +#define clipper_hpp + +#include +#include +#include +#include +#include + +namespace ClipperLib { + +enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; +enum PolyType { ptSubject, ptClip }; +//By far the most widely used winding rules for polygon filling are +//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) +//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) +//see http://glprogramming.com/red/chapter11.html +enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; + +typedef signed long long long64; +typedef unsigned long long ulong64; + +struct IntPoint { +public: + long64 X; + long64 Y; + IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {}; + friend std::ostream& operator <<(std::ostream &s, IntPoint &p); +}; + +typedef std::vector< IntPoint > Polygon; +typedef std::vector< Polygon > Polygons; + +std::ostream& operator <<(std::ostream &s, Polygon &p); +std::ostream& operator <<(std::ostream &s, Polygons &p); + +struct ExPolygon { + Polygon outer; + Polygons holes; +}; +typedef std::vector< ExPolygon > ExPolygons; + +enum JoinType { jtSquare, jtRound, jtMiter }; + +bool Orientation(const Polygon &poly); +double Area(const Polygon &poly); +void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, + double delta, JoinType jointype = jtSquare, double MiterLimit = 2); +void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd); + +void ReversePolygon(Polygon& p); +void ReversePolygons(Polygons& p); + +//used internally ... +enum EdgeSide { esNeither = 0, esLeft = 1, esRight = 2, esBoth = 3 }; +enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 }; + +struct TEdge { + long64 xbot; + long64 ybot; + long64 xcurr; + long64 ycurr; + long64 xtop; + long64 ytop; + double dx; + long64 tmpX; + PolyType polyType; + EdgeSide side; + int windDelta; //1 or -1 depending on winding direction + int windCnt; + int windCnt2; //winding count of the opposite polytype + int outIdx; + TEdge *next; + TEdge *prev; + TEdge *nextInLML; + TEdge *nextInAEL; + TEdge *prevInAEL; + TEdge *nextInSEL; + TEdge *prevInSEL; +}; + +struct IntersectNode { + TEdge *edge1; + TEdge *edge2; + IntPoint pt; + IntersectNode *next; +}; + +struct LocalMinima { + long64 Y; + TEdge *leftBound; + TEdge *rightBound; + LocalMinima *next; +}; + +struct Scanbeam { + long64 Y; + Scanbeam *next; +}; + +struct OutPt; //forward declaration + +struct OutRec { + int idx; + bool isHole; + OutRec *FirstLeft; + OutRec *AppendLink; + OutPt *pts; + OutPt *bottomPt; + OutPt *bottomFlag; + EdgeSide sides; +}; + +struct OutPt { + int idx; + IntPoint pt; + OutPt *next; + OutPt *prev; +}; + +struct JoinRec { + IntPoint pt1a; + IntPoint pt1b; + int poly1Idx; + IntPoint pt2a; + IntPoint pt2b; + int poly2Idx; +}; + +struct HorzJoinRec { + TEdge *edge; + int savedIdx; +}; + +struct IntRect { long64 left; long64 top; long64 right; long64 bottom; }; + +typedef std::vector < OutRec* > PolyOutList; +typedef std::vector < TEdge* > EdgeList; +typedef std::vector < JoinRec* > JoinList; +typedef std::vector < HorzJoinRec* > HorzJoinList; + +//ClipperBase is the ancestor to the Clipper class. It should not be +//instantiated directly. This class simply abstracts the conversion of sets of +//polygon coordinates into edge objects that are stored in a LocalMinima list. +class ClipperBase +{ +public: + ClipperBase(); + virtual ~ClipperBase(); + bool AddPolygon(const Polygon &pg, PolyType polyType); + bool AddPolygons( const Polygons &ppg, PolyType polyType); + virtual void Clear(); + IntRect GetBounds(); +protected: + void DisposeLocalMinimaList(); + TEdge* AddBoundsToLML(TEdge *e); + void PopLocalMinima(); + virtual void Reset(); + void InsertLocalMinima(LocalMinima *newLm); + LocalMinima *m_CurrentLM; + LocalMinima *m_MinimaList; + bool m_UseFullRange; + EdgeList m_edges; +}; + +class Clipper : public virtual ClipperBase +{ +public: + Clipper(); + ~Clipper(); + bool Execute(ClipType clipType, + Polygons &solution, + PolyFillType subjFillType = pftEvenOdd, + PolyFillType clipFillType = pftEvenOdd); + bool Execute(ClipType clipType, + ExPolygons &solution, + PolyFillType subjFillType = pftEvenOdd, + PolyFillType clipFillType = pftEvenOdd); + void Clear(); + bool ReverseSolution() {return m_ReverseOutput;}; + void ReverseSolution(bool value) {m_ReverseOutput = value;}; +protected: + void Reset(); + virtual bool ExecuteInternal(bool fixHoleLinkages); +private: + PolyOutList m_PolyOuts; + JoinList m_Joins; + HorzJoinList m_HorizJoins; + ClipType m_ClipType; + Scanbeam *m_Scanbeam; + TEdge *m_ActiveEdges; + TEdge *m_SortedEdges; + IntersectNode *m_IntersectNodes; + bool m_ExecuteLocked; + PolyFillType m_ClipFillType; + PolyFillType m_SubjFillType; + bool m_ReverseOutput; + void DisposeScanbeamList(); + void SetWindingCount(TEdge& edge); + bool IsEvenOddFillType(const TEdge& edge) const; + bool IsEvenOddAltFillType(const TEdge& edge) const; + void InsertScanbeam(const long64 Y); + long64 PopScanbeam(); + void InsertLocalMinimaIntoAEL(const long64 botY); + void InsertEdgeIntoAEL(TEdge *edge); + void AddEdgeToSEL(TEdge *edge); + void CopyAELToSEL(); + void DeleteFromSEL(TEdge *e); + void DeleteFromAEL(TEdge *e); + void UpdateEdgeIntoAEL(TEdge *&e); + void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); + bool IsContributing(const TEdge& edge) const; + bool IsTopHorz(const long64 XPos); + void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); + void DoMaxima(TEdge *e, long64 topY); + void ProcessHorizontals(); + void ProcessHorizontal(TEdge *horzEdge); + void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); + void AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); + void AppendPolygon(TEdge *e1, TEdge *e2); + void DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt); + void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt); + void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt); + void IntersectEdges(TEdge *e1, TEdge *e2, + const IntPoint &pt, IntersectProtects protects); + OutRec* CreateOutRec(); + void AddOutPt(TEdge *e, const IntPoint &pt); + void DisposeBottomPt(OutRec &outRec); + void DisposeAllPolyPts(); + void DisposeOutRec(PolyOutList::size_type index); + bool ProcessIntersections(const long64 botY, const long64 topY); + void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt); + void BuildIntersectList(const long64 botY, const long64 topY); + void ProcessIntersectList(); + void ProcessEdgesAtTopOfScanbeam(const long64 topY); + void BuildResult(Polygons& polys); + void BuildResultEx(ExPolygons& polys); + void SetHoleState(TEdge *e, OutRec *OutRec); + void DisposeIntersectNodes(); + bool FixupIntersections(); + void FixupOutPolygon(OutRec &outRec); + bool IsHole(TEdge *e); + void FixHoleLinkage(OutRec *outRec); + void CheckHoleLinkages1(OutRec *outRec1, OutRec *outRec2); + void CheckHoleLinkages2(OutRec *outRec1, OutRec *outRec2); + void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1); + void ClearJoins(); + void AddHorzJoin(TEdge *e, int idx); + void ClearHorzJoins(); + void JoinCommonEdges(bool fixHoleLinkages); +}; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +class clipperException : public std::exception +{ + public: + clipperException(const char* description): m_descr(description) {} + virtual ~clipperException() throw() {} + virtual const char* what() const throw() {return m_descr.c_str();} + private: + std::string m_descr; +}; +//------------------------------------------------------------------------------ + +} //ClipperLib namespace + +#endif //clipper_hpp + + diff --git a/contrib/irrXML/CXMLReaderImpl.h b/contrib/irrXML/CXMLReaderImpl.h index d2472b28b..63b700dc1 100644 --- a/contrib/irrXML/CXMLReaderImpl.h +++ b/contrib/irrXML/CXMLReaderImpl.h @@ -1,809 +1,809 @@ -// Copyright (C) 2002-2005 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine" and the "irrXML" project. -// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h - -#ifndef __ICXML_READER_IMPL_H_INCLUDED__ -#define __ICXML_READER_IMPL_H_INCLUDED__ - -#include "irrXML.h" -#include "irrString.h" -#include "irrArray.h" - -using namespace Assimp; - -#ifdef _DEBUG -#define IRR_DEBUGPRINT(x) printf((x)); -#else // _DEBUG -#define IRR_DEBUGPRINT(x) -#endif // _DEBUG - - -namespace irr -{ -namespace io -{ - - -//! implementation of the IrrXMLReader -template -class CXMLReaderImpl : public IIrrXMLReader -{ -public: - - //! Constructor - CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) - : TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE), - SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII) - { - if (!callback) - return; - - storeTargetFormat(); - - // read whole xml file - - readFile(callback); - - // clean up - - if (deleteCallBack) - delete callback; - - // create list with special characters - - createSpecialCharacterList(); - - // set pointer to text begin - P = TextBegin; - } - - - //! Destructor - virtual ~CXMLReaderImpl() - { - delete [] TextData; - } - - - //! Reads forward to the next xml node. - //! \return Returns false, if there was no further node. - virtual bool read() - { - // if not end reached, parse the node - if (P && (unsigned int)(P - TextBegin) < TextSize - 1 && *P != 0) - { - parseCurrentNode(); - return true; - } - - _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; - return false; - } - - - //! Returns the type of the current XML node. - virtual EXML_NODE getNodeType() const - { - return CurrentNodeType; - } - - - //! Returns attribute count of the current XML node. - virtual int getAttributeCount() const - { - return Attributes.size(); - } - - - //! Returns name of an attribute. - virtual const char_type* getAttributeName(int idx) const - { - if (idx < 0 || idx >= (int)Attributes.size()) - return 0; - - return Attributes[idx].Name.c_str(); - } - - - //! Returns the value of an attribute. - virtual const char_type* getAttributeValue(int idx) const - { - if (idx < 0 || idx >= (int)Attributes.size()) - return 0; - - return Attributes[idx].Value.c_str(); - } - - - //! Returns the value of an attribute. - virtual const char_type* getAttributeValue(const char_type* name) const - { - const SAttribute* attr = getAttributeByName(name); - if (!attr) - return 0; - - return attr->Value.c_str(); - } - - - //! Returns the value of an attribute - virtual const char_type* getAttributeValueSafe(const char_type* name) const - { - const SAttribute* attr = getAttributeByName(name); - if (!attr) - return EmptyString.c_str(); - - return attr->Value.c_str(); - } - - - - //! Returns the value of an attribute as integer. - int getAttributeValueAsInt(const char_type* name) const - { - return (int)getAttributeValueAsFloat(name); - } - - - //! Returns the value of an attribute as integer. - int getAttributeValueAsInt(int idx) const - { - return (int)getAttributeValueAsFloat(idx); - } - - - //! Returns the value of an attribute as float. - float getAttributeValueAsFloat(const char_type* name) const - { - const SAttribute* attr = getAttributeByName(name); - if (!attr) - return 0; - - core::stringc c = attr->Value.c_str(); - return fast_atof(c.c_str()); - } - - - //! Returns the value of an attribute as float. - float getAttributeValueAsFloat(int idx) const - { - const char_type* attrvalue = getAttributeValue(idx); - if (!attrvalue) - return 0; - - core::stringc c = attrvalue; - return fast_atof(c.c_str()); - } - - - //! Returns the name of the current node. - virtual const char_type* getNodeName() const - { - return NodeName.c_str(); - } - - - //! Returns data of the current node. - virtual const char_type* getNodeData() const - { - return NodeName.c_str(); - } - - - //! Returns if an element is an empty element, like - virtual bool isEmptyElement() const - { - return IsEmptyElement; - } - - //! Returns format of the source xml file. - virtual ETEXT_FORMAT getSourceFormat() const - { - return SourceFormat; - } - - //! Returns format of the strings returned by the parser. - virtual ETEXT_FORMAT getParserFormat() const - { - return TargetFormat; - } - -private: - - // Reads the current xml node - void parseCurrentNode() - { - char_type* start = P; - - // move forward until '<' found - while(*P != L'<' && *P) - ++P; - - if (!*P) - return; - - if (P - start > 0) - { - // we found some text, store it - if (setText(start, P)) - return; - } - - ++P; - - // based on current token, parse and report next element - switch(*P) - { - case L'/': - parseClosingXMLElement(); - break; - case L'?': - ignoreDefinition(); - break; - case L'!': - if (!parseCDATA()) - parseComment(); - break; - default: - parseOpeningXMLElement(); - break; - } - } - - - //! sets the state that text was found. Returns true if set should be set - bool setText(char_type* start, char_type* end) - { - // check if text is more than 2 characters, and if not, check if there is - // only white space, so that this text won't be reported - if (end - start < 3) - { - char_type* p = start; - for(; p != end; ++p) - if (!isWhiteSpace(*p)) - break; - - if (p == end) - return false; - } - - // set current text to the parsed text, and replace xml special characters - core::string s(start, (int)(end - start)); - NodeName = replaceSpecialCharacters(s); - - // current XML node type is text - CurrentNodeType = EXN_TEXT; - - return true; - } - - - - //! ignores an xml definition like - void ignoreDefinition() - { - CurrentNodeType = EXN_UNKNOWN; - - // move until end marked with '>' reached - while(*P != L'>') - ++P; - - ++P; - } - - - //! parses a comment - void parseComment() - { - CurrentNodeType = EXN_COMMENT; - P += 1; - - char_type *pCommentBegin = P; - - int count = 1; - - // move until end of comment reached - while(count) - { - if (*P == L'>') - --count; - else - if (*P == L'<') - ++count; - - ++P; - } - - P -= 3; - NodeName = core::string(pCommentBegin+2, (int)(P - pCommentBegin-2)); - P += 3; - } - - - //! parses an opening xml element and reads attributes - void parseOpeningXMLElement() - { - CurrentNodeType = EXN_ELEMENT; - IsEmptyElement = false; - Attributes.clear(); - - // find name - const char_type* startName = P; - - // find end of element - while(*P != L'>' && !isWhiteSpace(*P)) - ++P; - - const char_type* endName = P; - - // find Attributes - while(*P != L'>') - { - if (isWhiteSpace(*P)) - ++P; - else - { - if (*P != L'/') - { - // we've got an attribute - - // read the attribute names - const char_type* attributeNameBegin = P; - - while(!isWhiteSpace(*P) && *P != L'=') - ++P; - - const char_type* attributeNameEnd = P; - ++P; - - // read the attribute value - // check for quotes and single quotes, thx to murphy - while( (*P != L'\"') && (*P != L'\'') && *P) - ++P; - - if (!*P) // malformatted xml file - return; - - const char_type attributeQuoteChar = *P; - - ++P; - const char_type* attributeValueBegin = P; - - while(*P != attributeQuoteChar && *P) - ++P; - - if (!*P) // malformatted xml file - return; - - const char_type* attributeValueEnd = P; - ++P; - - SAttribute attr; - attr.Name = core::string(attributeNameBegin, - (int)(attributeNameEnd - attributeNameBegin)); - - core::string s(attributeValueBegin, - (int)(attributeValueEnd - attributeValueBegin)); - - attr.Value = replaceSpecialCharacters(s); - Attributes.push_back(attr); - } - else - { - // tag is closed directly - ++P; - IsEmptyElement = true; - break; - } - } - } - - // check if this tag is closing directly - if (endName > startName && *(endName-1) == L'/') - { - // directly closing tag - IsEmptyElement = true; - endName--; - } - - NodeName = core::string(startName, (int)(endName - startName)); - - ++P; - } - - - //! parses an closing xml tag - void parseClosingXMLElement() - { - CurrentNodeType = EXN_ELEMENT_END; - IsEmptyElement = false; - Attributes.clear(); - - ++P; - const char_type* pBeginClose = P; - - while(*P != L'>') - ++P; - - // remove trailing whitespace, if any - while( isspace( P[-1])) - --P; - - NodeName = core::string(pBeginClose, (int)(P - pBeginClose)); - ++P; - } - - //! parses a possible CDATA section, returns false if begin was not a CDATA section - bool parseCDATA() - { - if (*(P+1) != L'[') - return false; - - CurrentNodeType = EXN_CDATA; - - // skip '' && - (*(P-1) == L']') && - (*(P-2) == L']')) - { - cDataEnd = P - 2; - } - - ++P; - } - - if ( cDataEnd ) - NodeName = core::string(cDataBegin, (int)(cDataEnd - cDataBegin)); - else - NodeName = ""; - - return true; - } - - - // structure for storing attribute-name pairs - struct SAttribute - { - core::string Name; - core::string Value; - }; - - // finds a current attribute by name, returns 0 if not found - const SAttribute* getAttributeByName(const char_type* name) const - { - if (!name) - return 0; - - core::string n = name; - - for (int i=0; i<(int)Attributes.size(); ++i) - if (Attributes[i].Name == n) - return &Attributes[i]; - - return 0; - } - - // replaces xml special characters in a string and creates a new one - core::string replaceSpecialCharacters( - core::string& origstr) - { - int pos = origstr.findFirst(L'&'); - int oldPos = 0; - - if (pos == -1) - return origstr; - - core::string newstr; - - while(pos != -1 && pos < origstr.size()-2) - { - // check if it is one of the special characters - - int specialChar = -1; - for (int i=0; i<(int)SpecialCharacters.size(); ++i) - { - const char_type* p = &origstr.c_str()[pos]+1; - - if (equalsn(&SpecialCharacters[i][1], p, SpecialCharacters[i].size()-1)) - { - specialChar = i; - break; - } - } - - if (specialChar != -1) - { - newstr.append(origstr.subString(oldPos, pos - oldPos)); - newstr.append(SpecialCharacters[specialChar][0]); - pos += SpecialCharacters[specialChar].size(); - } - else - { - newstr.append(origstr.subString(oldPos, pos - oldPos + 1)); - pos += 1; - } - - // find next & - oldPos = pos; - pos = origstr.findNext(L'&', pos); - } - - if (oldPos < origstr.size()-1) - newstr.append(origstr.subString(oldPos, origstr.size()-oldPos)); - - return newstr; - } - - - - //! reads the xml file and converts it into the wanted character format. - bool readFile(IFileReadCallBack* callback) - { - int size = callback->getSize(); - size += 4; // We need two terminating 0's at the end. - // For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4. - - char* data8 = new char[size]; - - if (!callback->read(data8, size-4)) - { - delete [] data8; - return false; - } - - // add zeros at end - - data8[size-1] = 0; - data8[size-2] = 0; - data8[size-3] = 0; - data8[size-4] = 0; - - char16* data16 = reinterpret_cast(data8); - char32* data32 = reinterpret_cast(data8); - - // now we need to convert the data to the desired target format - // based on the byte order mark. - - const unsigned char UTF8[] = {0xEF, 0xBB, 0xBF}; // 0xEFBBBF; - const int UTF16_BE = 0xFFFE; - const int UTF16_LE = 0xFEFF; - const int UTF32_BE = 0xFFFE0000; - const int UTF32_LE = 0x0000FEFF; - - // check source for all utf versions and convert to target data format - - if (size >= 4 && data32[0] == (char32)UTF32_BE) - { - // UTF-32, big endian - SourceFormat = ETF_UTF32_BE; - convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header - } - else - if (size >= 4 && data32[0] == (char32)UTF32_LE) - { - // UTF-32, little endian - SourceFormat = ETF_UTF32_LE; - convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header - } - else - if (size >= 2 && data16[0] == UTF16_BE) - { - // UTF-16, big endian - SourceFormat = ETF_UTF16_BE; - convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header - } - else - if (size >= 2 && data16[0] == UTF16_LE) - { - // UTF-16, little endian - SourceFormat = ETF_UTF16_LE; - convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header - } - else - if (size >= 3 && data8[0] == UTF8[0] && data8[1] == UTF8[1] && data8[2] == UTF8[2]) - { - // UTF-8 - SourceFormat = ETF_UTF8; - convertTextData(data8+3, data8, size); // data8+3 because we need to skip the header - } - else - { - // ASCII - SourceFormat = ETF_ASCII; - convertTextData(data8, data8, size); - } - - return true; - } - - - //! converts the text file into the desired format. - //! \param source: begin of the text (without byte order mark) - //! \param pointerToStore: pointer to text data block which can be - //! stored or deleted based on the nesessary conversion. - //! \param sizeWithoutHeader: Text size in characters without header - template - void convertTextData(src_char_type* source, char* pointerToStore, int sizeWithoutHeader) - { - // convert little to big endian if necessary - if (sizeof(src_char_type) > 1 && - isLittleEndian(TargetFormat) != isLittleEndian(SourceFormat)) - convertToLittleEndian(source); - - // check if conversion is necessary: - if (sizeof(src_char_type) == sizeof(char_type)) - { - // no need to convert - TextBegin = (char_type*)source; - TextData = (char_type*)pointerToStore; - TextSize = sizeWithoutHeader; - } - else - { - // convert source into target data format. - // TODO: implement a real conversion. This one just - // copies bytes. This is a problem when there are - // unicode symbols using more than one character. - - TextData = new char_type[sizeWithoutHeader]; - - // MSVC debugger complains here about loss of data ... - - - // FIXME - gcc complains about 'shift width larger than width of type' - // for T == unsigned long. Avoid it by messing around volatile .. - volatile unsigned int c = 3; - const src_char_type cc = (src_char_type)((((uint64_t)1u << (sizeof( char_type)< - void convertToLittleEndian(src_char_type* t) - { - if (sizeof(src_char_type) == 4) - { - // 32 bit - - while(*t) - { - *t = ((*t & 0xff000000) >> 24) | - ((*t & 0x00ff0000) >> 8) | - ((*t & 0x0000ff00) << 8) | - ((*t & 0x000000ff) << 24); - ++t; - } - } - else - { - // 16 bit - - while(*t) - { - *t = (*t >> 8) | (*t << 8); - ++t; - } - } - } - - //! returns if a format is little endian - inline bool isLittleEndian(ETEXT_FORMAT f) - { - return f == ETF_ASCII || - f == ETF_UTF8 || - f == ETF_UTF16_LE || - f == ETF_UTF32_LE; - } - - - //! returns true if a character is whitespace - inline bool isWhiteSpace(char_type c) - { - return (c==' ' || c=='\t' || c=='\n' || c=='\r'); - } - - - //! generates a list with xml special characters - void createSpecialCharacterList() - { - // list of strings containing special symbols, - // the first character is the special character, - // the following is the symbol string without trailing &. - - SpecialCharacters.push_back("&"); - SpecialCharacters.push_back("gt;"); - SpecialCharacters.push_back("\"quot;"); - SpecialCharacters.push_back("'apos;"); - - } - - - //! compares the first n characters of the strings - bool equalsn(const char_type* str1, const char_type* str2, int len) - { - int i; - for(i=0; str1[i] && str2[i] && i < len; ++i) - if (str1[i] != str2[i]) - return false; - - // if one (or both) of the strings was smaller then they - // are only equal if they have the same lenght - return (i == len) || (str1[i] == 0 && str2[i] == 0); - } - - - //! stores the target text format - void storeTargetFormat() - { - // get target format. We could have done this using template specialization, - // but VisualStudio 6 don't like it and we want to support it. - - switch(sizeof(char_type)) - { - case 1: - TargetFormat = ETF_UTF8; - break; - case 2: - TargetFormat = ETF_UTF16_LE; - break; - case 4: - TargetFormat = ETF_UTF32_LE; - break; - default: - TargetFormat = ETF_ASCII; // should never happen. - } - } - - - // instance variables: - - char_type* TextData; // data block of the text file - char_type* P; // current point in text to parse - char_type* TextBegin; // start of text to parse - unsigned int TextSize; // size of text to parse in characters, not bytes - - EXML_NODE CurrentNodeType; // type of the currently parsed node - ETEXT_FORMAT SourceFormat; // source format of the xml file - ETEXT_FORMAT TargetFormat; // output format of this parser - - core::string NodeName; // name of the node currently in - core::string EmptyString; // empty string to be returned by getSafe() methods - - bool IsEmptyElement; // is the currently parsed node empty? - - core::array< core::string > SpecialCharacters; // see createSpecialCharacterList() - - core::array Attributes; // attributes of current element - -}; // end CXMLReaderImpl - - -} // end namespace -} // end namespace - -#endif +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h + +#ifndef __ICXML_READER_IMPL_H_INCLUDED__ +#define __ICXML_READER_IMPL_H_INCLUDED__ + +#include "irrXML.h" +#include "irrString.h" +#include "irrArray.h" + +using namespace Assimp; + +#ifdef _DEBUG +#define IRR_DEBUGPRINT(x) printf((x)); +#else // _DEBUG +#define IRR_DEBUGPRINT(x) +#endif // _DEBUG + + +namespace irr +{ +namespace io +{ + + +//! implementation of the IrrXMLReader +template +class CXMLReaderImpl : public IIrrXMLReader +{ +public: + + //! Constructor + CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) + : TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE), + SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII) + { + if (!callback) + return; + + storeTargetFormat(); + + // read whole xml file + + readFile(callback); + + // clean up + + if (deleteCallBack) + delete callback; + + // create list with special characters + + createSpecialCharacterList(); + + // set pointer to text begin + P = TextBegin; + } + + + //! Destructor + virtual ~CXMLReaderImpl() + { + delete [] TextData; + } + + + //! Reads forward to the next xml node. + //! \return Returns false, if there was no further node. + virtual bool read() + { + // if not end reached, parse the node + if (P && (unsigned int)(P - TextBegin) < TextSize - 1 && *P != 0) + { + parseCurrentNode(); + return true; + } + + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return false; + } + + + //! Returns the type of the current XML node. + virtual EXML_NODE getNodeType() const + { + return CurrentNodeType; + } + + + //! Returns attribute count of the current XML node. + virtual int getAttributeCount() const + { + return Attributes.size(); + } + + + //! Returns name of an attribute. + virtual const char_type* getAttributeName(int idx) const + { + if (idx < 0 || idx >= (int)Attributes.size()) + return 0; + + return Attributes[idx].Name.c_str(); + } + + + //! Returns the value of an attribute. + virtual const char_type* getAttributeValue(int idx) const + { + if (idx < 0 || idx >= (int)Attributes.size()) + return 0; + + return Attributes[idx].Value.c_str(); + } + + + //! Returns the value of an attribute. + virtual const char_type* getAttributeValue(const char_type* name) const + { + const SAttribute* attr = getAttributeByName(name); + if (!attr) + return 0; + + return attr->Value.c_str(); + } + + + //! Returns the value of an attribute + virtual const char_type* getAttributeValueSafe(const char_type* name) const + { + const SAttribute* attr = getAttributeByName(name); + if (!attr) + return EmptyString.c_str(); + + return attr->Value.c_str(); + } + + + + //! Returns the value of an attribute as integer. + int getAttributeValueAsInt(const char_type* name) const + { + return (int)getAttributeValueAsFloat(name); + } + + + //! Returns the value of an attribute as integer. + int getAttributeValueAsInt(int idx) const + { + return (int)getAttributeValueAsFloat(idx); + } + + + //! Returns the value of an attribute as float. + float getAttributeValueAsFloat(const char_type* name) const + { + const SAttribute* attr = getAttributeByName(name); + if (!attr) + return 0; + + core::stringc c = attr->Value.c_str(); + return fast_atof(c.c_str()); + } + + + //! Returns the value of an attribute as float. + float getAttributeValueAsFloat(int idx) const + { + const char_type* attrvalue = getAttributeValue(idx); + if (!attrvalue) + return 0; + + core::stringc c = attrvalue; + return fast_atof(c.c_str()); + } + + + //! Returns the name of the current node. + virtual const char_type* getNodeName() const + { + return NodeName.c_str(); + } + + + //! Returns data of the current node. + virtual const char_type* getNodeData() const + { + return NodeName.c_str(); + } + + + //! Returns if an element is an empty element, like + virtual bool isEmptyElement() const + { + return IsEmptyElement; + } + + //! Returns format of the source xml file. + virtual ETEXT_FORMAT getSourceFormat() const + { + return SourceFormat; + } + + //! Returns format of the strings returned by the parser. + virtual ETEXT_FORMAT getParserFormat() const + { + return TargetFormat; + } + +private: + + // Reads the current xml node + void parseCurrentNode() + { + char_type* start = P; + + // move forward until '<' found + while(*P != L'<' && *P) + ++P; + + if (!*P) + return; + + if (P - start > 0) + { + // we found some text, store it + if (setText(start, P)) + return; + } + + ++P; + + // based on current token, parse and report next element + switch(*P) + { + case L'/': + parseClosingXMLElement(); + break; + case L'?': + ignoreDefinition(); + break; + case L'!': + if (!parseCDATA()) + parseComment(); + break; + default: + parseOpeningXMLElement(); + break; + } + } + + + //! sets the state that text was found. Returns true if set should be set + bool setText(char_type* start, char_type* end) + { + // check if text is more than 2 characters, and if not, check if there is + // only white space, so that this text won't be reported + if (end - start < 3) + { + char_type* p = start; + for(; p != end; ++p) + if (!isWhiteSpace(*p)) + break; + + if (p == end) + return false; + } + + // set current text to the parsed text, and replace xml special characters + core::string s(start, (int)(end - start)); + NodeName = replaceSpecialCharacters(s); + + // current XML node type is text + CurrentNodeType = EXN_TEXT; + + return true; + } + + + + //! ignores an xml definition like + void ignoreDefinition() + { + CurrentNodeType = EXN_UNKNOWN; + + // move until end marked with '>' reached + while(*P != L'>') + ++P; + + ++P; + } + + + //! parses a comment + void parseComment() + { + CurrentNodeType = EXN_COMMENT; + P += 1; + + char_type *pCommentBegin = P; + + int count = 1; + + // move until end of comment reached + while(count) + { + if (*P == L'>') + --count; + else + if (*P == L'<') + ++count; + + ++P; + } + + P -= 3; + NodeName = core::string(pCommentBegin+2, (int)(P - pCommentBegin-2)); + P += 3; + } + + + //! parses an opening xml element and reads attributes + void parseOpeningXMLElement() + { + CurrentNodeType = EXN_ELEMENT; + IsEmptyElement = false; + Attributes.clear(); + + // find name + const char_type* startName = P; + + // find end of element + while(*P != L'>' && !isWhiteSpace(*P)) + ++P; + + const char_type* endName = P; + + // find Attributes + while(*P != L'>') + { + if (isWhiteSpace(*P)) + ++P; + else + { + if (*P != L'/') + { + // we've got an attribute + + // read the attribute names + const char_type* attributeNameBegin = P; + + while(!isWhiteSpace(*P) && *P != L'=') + ++P; + + const char_type* attributeNameEnd = P; + ++P; + + // read the attribute value + // check for quotes and single quotes, thx to murphy + while( (*P != L'\"') && (*P != L'\'') && *P) + ++P; + + if (!*P) // malformatted xml file + return; + + const char_type attributeQuoteChar = *P; + + ++P; + const char_type* attributeValueBegin = P; + + while(*P != attributeQuoteChar && *P) + ++P; + + if (!*P) // malformatted xml file + return; + + const char_type* attributeValueEnd = P; + ++P; + + SAttribute attr; + attr.Name = core::string(attributeNameBegin, + (int)(attributeNameEnd - attributeNameBegin)); + + core::string s(attributeValueBegin, + (int)(attributeValueEnd - attributeValueBegin)); + + attr.Value = replaceSpecialCharacters(s); + Attributes.push_back(attr); + } + else + { + // tag is closed directly + ++P; + IsEmptyElement = true; + break; + } + } + } + + // check if this tag is closing directly + if (endName > startName && *(endName-1) == L'/') + { + // directly closing tag + IsEmptyElement = true; + endName--; + } + + NodeName = core::string(startName, (int)(endName - startName)); + + ++P; + } + + + //! parses an closing xml tag + void parseClosingXMLElement() + { + CurrentNodeType = EXN_ELEMENT_END; + IsEmptyElement = false; + Attributes.clear(); + + ++P; + const char_type* pBeginClose = P; + + while(*P != L'>') + ++P; + + // remove trailing whitespace, if any + while( isspace( P[-1])) + --P; + + NodeName = core::string(pBeginClose, (int)(P - pBeginClose)); + ++P; + } + + //! parses a possible CDATA section, returns false if begin was not a CDATA section + bool parseCDATA() + { + if (*(P+1) != L'[') + return false; + + CurrentNodeType = EXN_CDATA; + + // skip '' && + (*(P-1) == L']') && + (*(P-2) == L']')) + { + cDataEnd = P - 2; + } + + ++P; + } + + if ( cDataEnd ) + NodeName = core::string(cDataBegin, (int)(cDataEnd - cDataBegin)); + else + NodeName = ""; + + return true; + } + + + // structure for storing attribute-name pairs + struct SAttribute + { + core::string Name; + core::string Value; + }; + + // finds a current attribute by name, returns 0 if not found + const SAttribute* getAttributeByName(const char_type* name) const + { + if (!name) + return 0; + + core::string n = name; + + for (int i=0; i<(int)Attributes.size(); ++i) + if (Attributes[i].Name == n) + return &Attributes[i]; + + return 0; + } + + // replaces xml special characters in a string and creates a new one + core::string replaceSpecialCharacters( + core::string& origstr) + { + int pos = origstr.findFirst(L'&'); + int oldPos = 0; + + if (pos == -1) + return origstr; + + core::string newstr; + + while(pos != -1 && pos < origstr.size()-2) + { + // check if it is one of the special characters + + int specialChar = -1; + for (int i=0; i<(int)SpecialCharacters.size(); ++i) + { + const char_type* p = &origstr.c_str()[pos]+1; + + if (equalsn(&SpecialCharacters[i][1], p, SpecialCharacters[i].size()-1)) + { + specialChar = i; + break; + } + } + + if (specialChar != -1) + { + newstr.append(origstr.subString(oldPos, pos - oldPos)); + newstr.append(SpecialCharacters[specialChar][0]); + pos += SpecialCharacters[specialChar].size(); + } + else + { + newstr.append(origstr.subString(oldPos, pos - oldPos + 1)); + pos += 1; + } + + // find next & + oldPos = pos; + pos = origstr.findNext(L'&', pos); + } + + if (oldPos < origstr.size()-1) + newstr.append(origstr.subString(oldPos, origstr.size()-oldPos)); + + return newstr; + } + + + + //! reads the xml file and converts it into the wanted character format. + bool readFile(IFileReadCallBack* callback) + { + int size = callback->getSize(); + size += 4; // We need two terminating 0's at the end. + // For ASCII we need 1 0's, for UTF-16 2, for UTF-32 4. + + char* data8 = new char[size]; + + if (!callback->read(data8, size-4)) + { + delete [] data8; + return false; + } + + // add zeros at end + + data8[size-1] = 0; + data8[size-2] = 0; + data8[size-3] = 0; + data8[size-4] = 0; + + char16* data16 = reinterpret_cast(data8); + char32* data32 = reinterpret_cast(data8); + + // now we need to convert the data to the desired target format + // based on the byte order mark. + + const unsigned char UTF8[] = {0xEF, 0xBB, 0xBF}; // 0xEFBBBF; + const int UTF16_BE = 0xFFFE; + const int UTF16_LE = 0xFEFF; + const int UTF32_BE = 0xFFFE0000; + const int UTF32_LE = 0x0000FEFF; + + // check source for all utf versions and convert to target data format + + if (size >= 4 && data32[0] == (char32)UTF32_BE) + { + // UTF-32, big endian + SourceFormat = ETF_UTF32_BE; + convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header + } + else + if (size >= 4 && data32[0] == (char32)UTF32_LE) + { + // UTF-32, little endian + SourceFormat = ETF_UTF32_LE; + convertTextData(data32+1, data8, (size/4)); // data32+1 because we need to skip the header + } + else + if (size >= 2 && data16[0] == UTF16_BE) + { + // UTF-16, big endian + SourceFormat = ETF_UTF16_BE; + convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header + } + else + if (size >= 2 && data16[0] == UTF16_LE) + { + // UTF-16, little endian + SourceFormat = ETF_UTF16_LE; + convertTextData(data16+1, data8, (size/2)); // data16+1 because we need to skip the header + } + else + if (size >= 3 && data8[0] == UTF8[0] && data8[1] == UTF8[1] && data8[2] == UTF8[2]) + { + // UTF-8 + SourceFormat = ETF_UTF8; + convertTextData(data8+3, data8, size); // data8+3 because we need to skip the header + } + else + { + // ASCII + SourceFormat = ETF_ASCII; + convertTextData(data8, data8, size); + } + + return true; + } + + + //! converts the text file into the desired format. + //! \param source: begin of the text (without byte order mark) + //! \param pointerToStore: pointer to text data block which can be + //! stored or deleted based on the nesessary conversion. + //! \param sizeWithoutHeader: Text size in characters without header + template + void convertTextData(src_char_type* source, char* pointerToStore, int sizeWithoutHeader) + { + // convert little to big endian if necessary + if (sizeof(src_char_type) > 1 && + isLittleEndian(TargetFormat) != isLittleEndian(SourceFormat)) + convertToLittleEndian(source); + + // check if conversion is necessary: + if (sizeof(src_char_type) == sizeof(char_type)) + { + // no need to convert + TextBegin = (char_type*)source; + TextData = (char_type*)pointerToStore; + TextSize = sizeWithoutHeader; + } + else + { + // convert source into target data format. + // TODO: implement a real conversion. This one just + // copies bytes. This is a problem when there are + // unicode symbols using more than one character. + + TextData = new char_type[sizeWithoutHeader]; + + // MSVC debugger complains here about loss of data ... + + + // FIXME - gcc complains about 'shift width larger than width of type' + // for T == unsigned long. Avoid it by messing around volatile .. + volatile unsigned int c = 3; + const src_char_type cc = (src_char_type)((((uint64_t)1u << (sizeof( char_type)< + void convertToLittleEndian(src_char_type* t) + { + if (sizeof(src_char_type) == 4) + { + // 32 bit + + while(*t) + { + *t = ((*t & 0xff000000) >> 24) | + ((*t & 0x00ff0000) >> 8) | + ((*t & 0x0000ff00) << 8) | + ((*t & 0x000000ff) << 24); + ++t; + } + } + else + { + // 16 bit + + while(*t) + { + *t = (*t >> 8) | (*t << 8); + ++t; + } + } + } + + //! returns if a format is little endian + inline bool isLittleEndian(ETEXT_FORMAT f) + { + return f == ETF_ASCII || + f == ETF_UTF8 || + f == ETF_UTF16_LE || + f == ETF_UTF32_LE; + } + + + //! returns true if a character is whitespace + inline bool isWhiteSpace(char_type c) + { + return (c==' ' || c=='\t' || c=='\n' || c=='\r'); + } + + + //! generates a list with xml special characters + void createSpecialCharacterList() + { + // list of strings containing special symbols, + // the first character is the special character, + // the following is the symbol string without trailing &. + + SpecialCharacters.push_back("&"); + SpecialCharacters.push_back("gt;"); + SpecialCharacters.push_back("\"quot;"); + SpecialCharacters.push_back("'apos;"); + + } + + + //! compares the first n characters of the strings + bool equalsn(const char_type* str1, const char_type* str2, int len) + { + int i; + for(i=0; str1[i] && str2[i] && i < len; ++i) + if (str1[i] != str2[i]) + return false; + + // if one (or both) of the strings was smaller then they + // are only equal if they have the same lenght + return (i == len) || (str1[i] == 0 && str2[i] == 0); + } + + + //! stores the target text format + void storeTargetFormat() + { + // get target format. We could have done this using template specialization, + // but VisualStudio 6 don't like it and we want to support it. + + switch(sizeof(char_type)) + { + case 1: + TargetFormat = ETF_UTF8; + break; + case 2: + TargetFormat = ETF_UTF16_LE; + break; + case 4: + TargetFormat = ETF_UTF32_LE; + break; + default: + TargetFormat = ETF_ASCII; // should never happen. + } + } + + + // instance variables: + + char_type* TextData; // data block of the text file + char_type* P; // current point in text to parse + char_type* TextBegin; // start of text to parse + unsigned int TextSize; // size of text to parse in characters, not bytes + + EXML_NODE CurrentNodeType; // type of the currently parsed node + ETEXT_FORMAT SourceFormat; // source format of the xml file + ETEXT_FORMAT TargetFormat; // output format of this parser + + core::string NodeName; // name of the node currently in + core::string EmptyString; // empty string to be returned by getSafe() methods + + bool IsEmptyElement; // is the currently parsed node empty? + + core::array< core::string > SpecialCharacters; // see createSpecialCharacterList() + + core::array Attributes; // attributes of current element + +}; // end CXMLReaderImpl + + +} // end namespace +} // end namespace + +#endif diff --git a/contrib/irrXML/heapsort.h b/contrib/irrXML/heapsort.h index 4395119df..d0db319d0 100644 --- a/contrib/irrXML/heapsort.h +++ b/contrib/irrXML/heapsort.h @@ -1,73 +1,73 @@ -// Copyright (C) 2002-2005 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __IRR_HEAPSORT_H_INCLUDED__ -#define __IRR_HEAPSORT_H_INCLUDED__ - -#include "irrTypes.h" - -namespace irr -{ -namespace core -{ - -//! Sinks an element into the heap. -template -inline void heapsink(T*array, s32 element, s32 max) -{ - while ((element<<1) < max) // there is a left child - { - s32 j = (element<<1); - - if (j+1 < max && array[j] < array[j+1]) - j = j+1; // take right child - - if (array[element] < array[j]) - { - T t = array[j]; // swap elements - array[j] = array[element]; - array[element] = t; - element = j; - } - else - return; - } -} - - -//! Sorts an array with size 'size' using heapsort. -template -inline void heapsort(T* array_, s32 size) -{ - // for heapsink we pretent this is not c++, where - // arrays start with index 0. So we decrease the array pointer, - // the maximum always +2 and the element always +1 - - T* virtualArray = array_ - 1; - s32 virtualSize = size + 2; - s32 i; - - // build heap - - for (i=((size-1)/2); i>=0; --i) - heapsink(virtualArray, i+1, virtualSize-1); - - // sort array - - for (i=size-1; i>=0; --i) - { - T t = array_[0]; - array_[0] = array_[i]; - array_[i] = t; - heapsink(virtualArray, 1, i + 1); - } -} - -} // end namespace core -} // end namespace irr - - - -#endif - +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_HEAPSORT_H_INCLUDED__ +#define __IRR_HEAPSORT_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace core +{ + +//! Sinks an element into the heap. +template +inline void heapsink(T*array, s32 element, s32 max) +{ + while ((element<<1) < max) // there is a left child + { + s32 j = (element<<1); + + if (j+1 < max && array[j] < array[j+1]) + j = j+1; // take right child + + if (array[element] < array[j]) + { + T t = array[j]; // swap elements + array[j] = array[element]; + array[element] = t; + element = j; + } + else + return; + } +} + + +//! Sorts an array with size 'size' using heapsort. +template +inline void heapsort(T* array_, s32 size) +{ + // for heapsink we pretent this is not c++, where + // arrays start with index 0. So we decrease the array pointer, + // the maximum always +2 and the element always +1 + + T* virtualArray = array_ - 1; + s32 virtualSize = size + 2; + s32 i; + + // build heap + + for (i=((size-1)/2); i>=0; --i) + heapsink(virtualArray, i+1, virtualSize-1); + + // sort array + + for (i=size-1; i>=0; --i) + { + T t = array_[0]; + array_[0] = array_[i]; + array_[i] = t; + heapsink(virtualArray, 1, i + 1); + } +} + +} // end namespace core +} // end namespace irr + + + +#endif + diff --git a/contrib/irrXML/irrArray.h b/contrib/irrXML/irrArray.h index 4bcf1fc11..40c822590 100644 --- a/contrib/irrXML/irrArray.h +++ b/contrib/irrXML/irrArray.h @@ -1,444 +1,444 @@ -// Copyright (C) 2002-2005 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine" and the "irrXML" project. -// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h - -#ifndef __IRR_ARRAY_H_INCLUDED__ -#define __IRR_ARRAY_H_INCLUDED__ - -#include "irrTypes.h" -#include "heapsort.h" - -namespace irr -{ -namespace core -{ - -//! Self reallocating template array (like stl vector) with additional features. -/** Some features are: Heap sorting, binary search methods, easier debugging. -*/ -template -class array -{ - -public: - - array() - : data(0), allocated(0), used(0), - free_when_destroyed(true), is_sorted(true) - { - } - - //! Constructs a array and allocates an initial chunk of memory. - //! \param start_count: Amount of elements to allocate. - array(u32 start_count) - : data(0), allocated(0), used(0), - free_when_destroyed(true), is_sorted(true) - { - reallocate(start_count); - } - - - //! Copy constructor - array(const array& other) - : data(0) - { - *this = other; - } - - - - //! Destructor. Frees allocated memory, if set_free_when_destroyed - //! was not set to false by the user before. - ~array() - { - if (free_when_destroyed) - delete [] data; - } - - - - //! Reallocates the array, make it bigger or smaller. - //! \param new_size: New size of array. - void reallocate(u32 new_size) - { - T* old_data = data; - - data = new T[new_size]; - allocated = new_size; - - s32 end = used < new_size ? used : new_size; - for (s32 i=0; i allocated) - { - // reallocate(used * 2 +1); - // this doesn't work if the element is in the same array. So - // we'll copy the element first to be sure we'll get no data - // corruption - - T e; - e = element; // copy element - reallocate(used * 2 +1); // increase data block - data[used++] = e; // push_back - is_sorted = false; - return; - } - - data[used++] = element; - is_sorted = false; - } - - - //! Adds an element at the front of the array. If the array is to small to - //! add this new element, the array is made bigger. Please note that this - //! is slow, because the whole array needs to be copied for this. - //! \param element: Element to add at the back of the array. - void push_front(const T& element) - { - if (used + 1 > allocated) - reallocate(used * 2 +1); - - for (int i=(int)used; i>0; --i) - data[i] = data[i-1]; - - data[0] = element; - is_sorted = false; - ++used; - } - - - //! Insert item into array at specified position. Please use this - //! only if you know what you are doing (possible performance loss). - //! The preferred method of adding elements should be push_back(). - //! \param element: Element to be inserted - //! \param index: Where position to insert the new element. - void insert(const T& element, u32 index=0) - { - _IRR_DEBUG_BREAK_IF(index>used) // access violation - - if (used + 1 > allocated) - reallocate(used * 2 +1); - - for (u32 i=used++; i>index; i--) - data[i] = data[i-1]; - - data[index] = element; - is_sorted = false; - } - - - - - //! Clears the array and deletes all allocated memory. - void clear() - { - delete [] data; - data = 0; - used = 0; - allocated = 0; - is_sorted = true; - } - - - - //! Sets pointer to new array, using this as new workspace. - //! \param newPointer: Pointer to new array of elements. - //! \param size: Size of the new array. - void set_pointer(T* newPointer, u32 size) - { - delete [] data; - data = newPointer; - allocated = size; - used = size; - is_sorted = false; - } - - - - //! Sets if the array should delete the memory it used. - //! \param f: If true, the array frees the allocated memory in its - //! destructor, otherwise not. The default is true. - void set_free_when_destroyed(bool f) - { - free_when_destroyed = f; - } - - - - //! Sets the size of the array. - //! \param usedNow: Amount of elements now used. - void set_used(u32 usedNow) - { - if (allocated < usedNow) - reallocate(usedNow); - - used = usedNow; - } - - - - //! Assignement operator - void operator=(const array& other) - { - if (data) - delete [] data; - - //if (allocated < other.allocated) - if (other.allocated == 0) - data = 0; - else - data = new T[other.allocated]; - - used = other.used; - free_when_destroyed = other.free_when_destroyed; - is_sorted = other.is_sorted; - allocated = other.allocated; - - for (u32 i=0; i=used) // access violation - - return data[index]; - } - - - - //! Direct access operator - const T& operator [](u32 index) const - { - _IRR_DEBUG_BREAK_IF(index>=used) // access violation - - return data[index]; - } - - //! Gets last frame - const T& getLast() const - { - _IRR_DEBUG_BREAK_IF(!used) // access violation - - return data[used-1]; - } - - //! Gets last frame - T& getLast() - { - _IRR_DEBUG_BREAK_IF(!used) // access violation - - return data[used-1]; - } - - - //! Returns a pointer to the array. - //! \return Pointer to the array. - T* pointer() - { - return data; - } - - - - //! Returns a const pointer to the array. - //! \return Pointer to the array. - const T* const_pointer() const - { - return data; - } - - - - //! Returns size of used array. - //! \return Size of elements in the array. - u32 size() const - { - return used; - } - - - - //! Returns amount memory allocated. - //! \return Returns amount of memory allocated. The amount of bytes - //! allocated would be allocated_size() * sizeof(ElementsUsed); - u32 allocated_size() const - { - return allocated; - } - - - - //! Returns true if array is empty - //! \return True if the array is empty, false if not. - bool empty() const - { - return used == 0; - } - - - - //! Sorts the array using heapsort. There is no additional memory waste and - //! the algorithm performs (O) n log n in worst case. - void sort() - { - if (is_sorted || used<2) - return; - - heapsort(data, used); - is_sorted = true; - } - - - - //! Performs a binary search for an element, returns -1 if not found. - //! The array will be sorted before the binary search if it is not - //! already sorted. - //! \param element: Element to search for. - //! \return Returns position of the searched element if it was found, - //! otherwise -1 is returned. - s32 binary_search(const T& element) - { - return binary_search(element, 0, used-1); - } - - - - //! Performs a binary search for an element, returns -1 if not found. - //! The array will be sorted before the binary search if it is not - //! already sorted. - //! \param element: Element to search for. - //! \param left: First left index - //! \param right: Last right index. - //! \return Returns position of the searched element if it was found, - //! otherwise -1 is returned. - s32 binary_search(const T& element, s32 left, s32 right) - { - if (!used) - return -1; - - sort(); - - s32 m; - - do - { - m = (left+right)>>1; - - if (element < data[m]) - right = m - 1; - else - left = m + 1; - - } while((element < data[m] || data[m] < element) && left<=right); - - // this last line equals to: - // " while((element != array[m]) && left<=right);" - // but we only want to use the '<' operator. - // the same in next line, it is "(element == array[m])" - - if (!(element < data[m]) && !(data[m] < element)) - return m; - - return -1; - } - - - //! Finds an element in linear time, which is very slow. Use - //! binary_search for faster finding. Only works if =operator is implemented. - //! \param element: Element to search for. - //! \return Returns position of the searched element if it was found, - //! otherwise -1 is returned. - s32 linear_search(T& element) - { - for (u32 i=0; i=0; --i) - if (data[i] == element) - return (s32)i; - - return -1; - } - - - - //! Erases an element from the array. May be slow, because all elements - //! following after the erased element have to be copied. - //! \param index: Index of element to be erased. - void erase(u32 index) - { - _IRR_DEBUG_BREAK_IF(index>=used || index<0) // access violation - - for (u32 i=index+1; i=used || index<0 || count<1 || index+count>used) // access violation - - for (u32 i=index+count; i +class array +{ + +public: + + array() + : data(0), allocated(0), used(0), + free_when_destroyed(true), is_sorted(true) + { + } + + //! Constructs a array and allocates an initial chunk of memory. + //! \param start_count: Amount of elements to allocate. + array(u32 start_count) + : data(0), allocated(0), used(0), + free_when_destroyed(true), is_sorted(true) + { + reallocate(start_count); + } + + + //! Copy constructor + array(const array& other) + : data(0) + { + *this = other; + } + + + + //! Destructor. Frees allocated memory, if set_free_when_destroyed + //! was not set to false by the user before. + ~array() + { + if (free_when_destroyed) + delete [] data; + } + + + + //! Reallocates the array, make it bigger or smaller. + //! \param new_size: New size of array. + void reallocate(u32 new_size) + { + T* old_data = data; + + data = new T[new_size]; + allocated = new_size; + + s32 end = used < new_size ? used : new_size; + for (s32 i=0; i allocated) + { + // reallocate(used * 2 +1); + // this doesn't work if the element is in the same array. So + // we'll copy the element first to be sure we'll get no data + // corruption + + T e; + e = element; // copy element + reallocate(used * 2 +1); // increase data block + data[used++] = e; // push_back + is_sorted = false; + return; + } + + data[used++] = element; + is_sorted = false; + } + + + //! Adds an element at the front of the array. If the array is to small to + //! add this new element, the array is made bigger. Please note that this + //! is slow, because the whole array needs to be copied for this. + //! \param element: Element to add at the back of the array. + void push_front(const T& element) + { + if (used + 1 > allocated) + reallocate(used * 2 +1); + + for (int i=(int)used; i>0; --i) + data[i] = data[i-1]; + + data[0] = element; + is_sorted = false; + ++used; + } + + + //! Insert item into array at specified position. Please use this + //! only if you know what you are doing (possible performance loss). + //! The preferred method of adding elements should be push_back(). + //! \param element: Element to be inserted + //! \param index: Where position to insert the new element. + void insert(const T& element, u32 index=0) + { + _IRR_DEBUG_BREAK_IF(index>used) // access violation + + if (used + 1 > allocated) + reallocate(used * 2 +1); + + for (u32 i=used++; i>index; i--) + data[i] = data[i-1]; + + data[index] = element; + is_sorted = false; + } + + + + + //! Clears the array and deletes all allocated memory. + void clear() + { + delete [] data; + data = 0; + used = 0; + allocated = 0; + is_sorted = true; + } + + + + //! Sets pointer to new array, using this as new workspace. + //! \param newPointer: Pointer to new array of elements. + //! \param size: Size of the new array. + void set_pointer(T* newPointer, u32 size) + { + delete [] data; + data = newPointer; + allocated = size; + used = size; + is_sorted = false; + } + + + + //! Sets if the array should delete the memory it used. + //! \param f: If true, the array frees the allocated memory in its + //! destructor, otherwise not. The default is true. + void set_free_when_destroyed(bool f) + { + free_when_destroyed = f; + } + + + + //! Sets the size of the array. + //! \param usedNow: Amount of elements now used. + void set_used(u32 usedNow) + { + if (allocated < usedNow) + reallocate(usedNow); + + used = usedNow; + } + + + + //! Assignement operator + void operator=(const array& other) + { + if (data) + delete [] data; + + //if (allocated < other.allocated) + if (other.allocated == 0) + data = 0; + else + data = new T[other.allocated]; + + used = other.used; + free_when_destroyed = other.free_when_destroyed; + is_sorted = other.is_sorted; + allocated = other.allocated; + + for (u32 i=0; i=used) // access violation + + return data[index]; + } + + + + //! Direct access operator + const T& operator [](u32 index) const + { + _IRR_DEBUG_BREAK_IF(index>=used) // access violation + + return data[index]; + } + + //! Gets last frame + const T& getLast() const + { + _IRR_DEBUG_BREAK_IF(!used) // access violation + + return data[used-1]; + } + + //! Gets last frame + T& getLast() + { + _IRR_DEBUG_BREAK_IF(!used) // access violation + + return data[used-1]; + } + + + //! Returns a pointer to the array. + //! \return Pointer to the array. + T* pointer() + { + return data; + } + + + + //! Returns a const pointer to the array. + //! \return Pointer to the array. + const T* const_pointer() const + { + return data; + } + + + + //! Returns size of used array. + //! \return Size of elements in the array. + u32 size() const + { + return used; + } + + + + //! Returns amount memory allocated. + //! \return Returns amount of memory allocated. The amount of bytes + //! allocated would be allocated_size() * sizeof(ElementsUsed); + u32 allocated_size() const + { + return allocated; + } + + + + //! Returns true if array is empty + //! \return True if the array is empty, false if not. + bool empty() const + { + return used == 0; + } + + + + //! Sorts the array using heapsort. There is no additional memory waste and + //! the algorithm performs (O) n log n in worst case. + void sort() + { + if (is_sorted || used<2) + return; + + heapsort(data, used); + is_sorted = true; + } + + + + //! Performs a binary search for an element, returns -1 if not found. + //! The array will be sorted before the binary search if it is not + //! already sorted. + //! \param element: Element to search for. + //! \return Returns position of the searched element if it was found, + //! otherwise -1 is returned. + s32 binary_search(const T& element) + { + return binary_search(element, 0, used-1); + } + + + + //! Performs a binary search for an element, returns -1 if not found. + //! The array will be sorted before the binary search if it is not + //! already sorted. + //! \param element: Element to search for. + //! \param left: First left index + //! \param right: Last right index. + //! \return Returns position of the searched element if it was found, + //! otherwise -1 is returned. + s32 binary_search(const T& element, s32 left, s32 right) + { + if (!used) + return -1; + + sort(); + + s32 m; + + do + { + m = (left+right)>>1; + + if (element < data[m]) + right = m - 1; + else + left = m + 1; + + } while((element < data[m] || data[m] < element) && left<=right); + + // this last line equals to: + // " while((element != array[m]) && left<=right);" + // but we only want to use the '<' operator. + // the same in next line, it is "(element == array[m])" + + if (!(element < data[m]) && !(data[m] < element)) + return m; + + return -1; + } + + + //! Finds an element in linear time, which is very slow. Use + //! binary_search for faster finding. Only works if =operator is implemented. + //! \param element: Element to search for. + //! \return Returns position of the searched element if it was found, + //! otherwise -1 is returned. + s32 linear_search(T& element) + { + for (u32 i=0; i=0; --i) + if (data[i] == element) + return (s32)i; + + return -1; + } + + + + //! Erases an element from the array. May be slow, because all elements + //! following after the erased element have to be copied. + //! \param index: Index of element to be erased. + void erase(u32 index) + { + _IRR_DEBUG_BREAK_IF(index>=used || index<0) // access violation + + for (u32 i=index+1; i=used || index<0 || count<1 || index+count>used) // access violation + + for (u32 i=index+count; i and string work both with unicode AND ascii, -so you can assign unicode to string and ascii to string -(and the other way round) if your ever would want to. -Note that the conversation between both is not done using an encoding. - -Known bugs: -Special characters like 'Ä', 'Ü' and 'Ö' are ignored in the -methods make_upper, make_lower and equals_ignore_case. -*/ -template -class string -{ -public: - - //! Default constructor - string() - : array(0), allocated(1), used(1) - { - array = new T[1]; - array[0] = 0x0; - } - - - - //! Constructor - string(const string& other) - : array(0), allocated(0), used(0) - { - *this = other; - } - - - //! Constructs a string from an int - string(int number) - : array(0), allocated(0), used(0) - { - // store if negative and make positive - - bool negative = false; - if (number < 0) - { - number *= -1; - negative = true; - } - - // temporary buffer for 16 numbers - - c8 tmpbuf[16]; - tmpbuf[15] = 0; - s32 idx = 15; - - // special case '0' - - if (!number) - { - tmpbuf[14] = '0'; - *this = &tmpbuf[14]; - return; - } - - // add numbers - - while(number && idx) - { - idx--; - tmpbuf[idx] = (c8)('0' + (number % 10)); - number = number / 10; - } - - // add sign - - if (negative) - { - idx--; - tmpbuf[idx] = '-'; - } - - *this = &tmpbuf[idx]; - } - - - - //! Constructor for copying a string from a pointer with a given lenght - template - string(const B* c, s32 lenght) - : array(0), allocated(0), used(0) - { - if (!c) - return; - - allocated = used = lenght+1; - array = new T[used]; - - for (s32 l = 0; l - string(const B* c) - : array(0),allocated(0), used(0) - { - *this = c; - } - - - - //! destructor - ~string() - { - delete [] array; - } - - - - //! Assignment operator - string& operator=(const string& other) - { - if (this == &other) - return *this; - - delete [] array; - allocated = used = other.size()+1; - array = new T[used]; - - const T* p = other.c_str(); - for (s32 i=0; i - string& operator=(const B* c) - { - if (!c) - { - if (!array) - { - array = new T[1]; - allocated = 1; - used = 1; - } - array[0] = 0x0; - return *this; - } - - if ((void*)c == (void*)array) - return *this; - - s32 len = 0; - const B* p = c; - while(*p) - { - ++len; - ++p; - } - - // we'll take the old string for a while, because the new string could be - // a part of the current string. - T* oldArray = array; - - allocated = used = len+1; - array = new T[used]; - - for (s32 l = 0; l operator+(const string& other) - { - string str(*this); - str.append(other); - - return str; - } - - //! Add operator for strings, ascii and unicode - template - string operator+(const B* c) - { - string str(*this); - str.append(c); - - return str; - } - - - - //! Direct access operator - T& operator [](const s32 index) const - { - _IRR_DEBUG_BREAK_IF(index>=used) // bad index - - return array[index]; - } - - - //! Comparison operator - bool operator ==(const T* str) const - { - int i; - for(i=0; array[i] && str[i]; ++i) - if (array[i] != str[i]) - return false; - - return !array[i] && !str[i]; - } - - - - //! Comparison operator - bool operator ==(const string& other) const - { - for(s32 i=0; array[i] && other.array[i]; ++i) - if (array[i] != other.array[i]) - return false; - - return used == other.used; - } - - - - //! Is smaller operator - bool operator <(const string& other) const - { - for(s32 i=0; array[i] && other.array[i]; ++i) - if (array[i] != other.array[i]) - return (array[i] < other.array[i]); - - return used < other.used; - } - - - - //! Equals not operator - bool operator !=(const string& other) const - { - return !(*this == other); - } - - - - //! Returns length of string - /** \return Returns length of the string in characters. */ - s32 size() const - { - return used-1; - } - - - - //! Returns character string - /** \return Returns pointer to C-style zero terminated string. */ - const T* c_str() const - { - return array; - } - - - - //! Makes the string lower case. - void make_lower() - { - const T A = (T)'A'; - const T Z = (T)'Z'; - const T diff = (T)'a' - A; - - for (s32 i=0; i=A && array[i]<=Z) - array[i] += diff; - } - } - - - - //! Makes the string upper case. - void make_upper() - { - const T a = (T)'a'; - const T z = (T)'z'; - const T diff = (T)'A' - a; - - for (s32 i=0; i=a && array[i]<=z) - array[i] += diff; - } - } - - - - //! Compares the string ignoring case. - /** \param other: Other string to compare. - \return Returns true if the string are equal ignoring case. */ - bool equals_ignore_case(const string& other) const - { - for(s32 i=0; array[i] && other[i]; ++i) - if (toLower(array[i]) != toLower(other[i])) - return false; - - return used == other.used; - } - - - //! compares the first n characters of the strings - bool equalsn(const string& other, int len) - { - int i; - for(i=0; array[i] && other[i] && i < len; ++i) - if (array[i] != other[i]) - return false; - - // if one (or both) of the strings was smaller then they - // are only equal if they have the same lenght - return (i == len) || (used == other.used); - } - - - //! compares the first n characters of the strings - bool equalsn(const T* str, int len) - { - int i; - for(i=0; array[i] && str[i] && i < len; ++i) - if (array[i] != str[i]) - return false; - - // if one (or both) of the strings was smaller then they - // are only equal if they have the same lenght - return (i == len) || (array[i] == 0 && str[i] == 0); - } - - - //! Appends a character to this string - /** \param character: Character to append. */ - void append(T character) - { - if (used + 1 > allocated) - reallocate((s32)used + 1); - - used += 1; - - array[used-2] = character; - array[used-1] = 0; - } - - //! Appends a string to this string - /** \param other: String to append. */ - void append(const string& other) - { - --used; - - s32 len = other.size(); - - if (used + len + 1 > allocated) - reallocate((s32)used + (s32)len + 1); - - for (s32 l=0; l& other, s32 length) - { - s32 len = other.size(); - - if (len < length) - { - append(other); - return; - } - - len = length; - --used; - - if (used + len > allocated) - reallocate((s32)used + (s32)len); - - for (s32 l=0; l - s32 findFirstCharNotInList(B* c, int count) const - { - for (int i=0; i - s32 findLastCharNotInList(B* c, int count) const - { - for (int i=used-2; i>=0; --i) - { - int j; - for (j=0; j=0; --i) - if (array[i] == c) - return i; - - return -1; - } - - - //! Returns a substring - //! \param begin: Start of substring. - //! \param length: Length of substring. - string subString(s32 begin, s32 length) - { - if (length <= 0) - return string(""); - - string o; - o.reserve(length+1); - - for (s32 i=0; i& other) - { - append(other); - } - - void operator += (int i) - { - append(string(i)); - } - - //! replaces all characters of a special type with another one - void replace(T toReplace, T replaceWith) - { - for (s32 i=0; i=used || index<0) // access violation - - for (int i=index+1; i=(T)'A' && t<=(T)'Z') - return t + ((T)'a' - (T)'A'); - else - return t; - } - - //! Reallocate the array, make it bigger or smaler - void reallocate(s32 new_size) - { - T* old_array = array; - - array = new T[new_size]; - allocated = new_size; - - s32 amount = used < new_size ? used : new_size; - for (s32 i=0; i stringc; - -//! Typedef for wide character strings -typedef string stringw; - -} // end namespace core -} // end namespace irr - -#endif - +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h + +#ifndef __IRR_STRING_H_INCLUDED__ +#define __IRR_STRING_H_INCLUDED__ + +#include "irrTypes.h" + +namespace irr +{ +namespace core +{ + +//! Very simple string class with some useful features. +/** string and string work both with unicode AND ascii, +so you can assign unicode to string and ascii to string +(and the other way round) if your ever would want to. +Note that the conversation between both is not done using an encoding. + +Known bugs: +Special characters like 'Ä', 'Ü' and 'Ö' are ignored in the +methods make_upper, make_lower and equals_ignore_case. +*/ +template +class string +{ +public: + + //! Default constructor + string() + : array(0), allocated(1), used(1) + { + array = new T[1]; + array[0] = 0x0; + } + + + + //! Constructor + string(const string& other) + : array(0), allocated(0), used(0) + { + *this = other; + } + + + //! Constructs a string from an int + string(int number) + : array(0), allocated(0), used(0) + { + // store if negative and make positive + + bool negative = false; + if (number < 0) + { + number *= -1; + negative = true; + } + + // temporary buffer for 16 numbers + + c8 tmpbuf[16]; + tmpbuf[15] = 0; + s32 idx = 15; + + // special case '0' + + if (!number) + { + tmpbuf[14] = '0'; + *this = &tmpbuf[14]; + return; + } + + // add numbers + + while(number && idx) + { + idx--; + tmpbuf[idx] = (c8)('0' + (number % 10)); + number = number / 10; + } + + // add sign + + if (negative) + { + idx--; + tmpbuf[idx] = '-'; + } + + *this = &tmpbuf[idx]; + } + + + + //! Constructor for copying a string from a pointer with a given lenght + template + string(const B* c, s32 lenght) + : array(0), allocated(0), used(0) + { + if (!c) + return; + + allocated = used = lenght+1; + array = new T[used]; + + for (s32 l = 0; l + string(const B* c) + : array(0),allocated(0), used(0) + { + *this = c; + } + + + + //! destructor + ~string() + { + delete [] array; + } + + + + //! Assignment operator + string& operator=(const string& other) + { + if (this == &other) + return *this; + + delete [] array; + allocated = used = other.size()+1; + array = new T[used]; + + const T* p = other.c_str(); + for (s32 i=0; i + string& operator=(const B* c) + { + if (!c) + { + if (!array) + { + array = new T[1]; + allocated = 1; + used = 1; + } + array[0] = 0x0; + return *this; + } + + if ((void*)c == (void*)array) + return *this; + + s32 len = 0; + const B* p = c; + while(*p) + { + ++len; + ++p; + } + + // we'll take the old string for a while, because the new string could be + // a part of the current string. + T* oldArray = array; + + allocated = used = len+1; + array = new T[used]; + + for (s32 l = 0; l operator+(const string& other) + { + string str(*this); + str.append(other); + + return str; + } + + //! Add operator for strings, ascii and unicode + template + string operator+(const B* c) + { + string str(*this); + str.append(c); + + return str; + } + + + + //! Direct access operator + T& operator [](const s32 index) const + { + _IRR_DEBUG_BREAK_IF(index>=used) // bad index + + return array[index]; + } + + + //! Comparison operator + bool operator ==(const T* str) const + { + int i; + for(i=0; array[i] && str[i]; ++i) + if (array[i] != str[i]) + return false; + + return !array[i] && !str[i]; + } + + + + //! Comparison operator + bool operator ==(const string& other) const + { + for(s32 i=0; array[i] && other.array[i]; ++i) + if (array[i] != other.array[i]) + return false; + + return used == other.used; + } + + + + //! Is smaller operator + bool operator <(const string& other) const + { + for(s32 i=0; array[i] && other.array[i]; ++i) + if (array[i] != other.array[i]) + return (array[i] < other.array[i]); + + return used < other.used; + } + + + + //! Equals not operator + bool operator !=(const string& other) const + { + return !(*this == other); + } + + + + //! Returns length of string + /** \return Returns length of the string in characters. */ + s32 size() const + { + return used-1; + } + + + + //! Returns character string + /** \return Returns pointer to C-style zero terminated string. */ + const T* c_str() const + { + return array; + } + + + + //! Makes the string lower case. + void make_lower() + { + const T A = (T)'A'; + const T Z = (T)'Z'; + const T diff = (T)'a' - A; + + for (s32 i=0; i=A && array[i]<=Z) + array[i] += diff; + } + } + + + + //! Makes the string upper case. + void make_upper() + { + const T a = (T)'a'; + const T z = (T)'z'; + const T diff = (T)'A' - a; + + for (s32 i=0; i=a && array[i]<=z) + array[i] += diff; + } + } + + + + //! Compares the string ignoring case. + /** \param other: Other string to compare. + \return Returns true if the string are equal ignoring case. */ + bool equals_ignore_case(const string& other) const + { + for(s32 i=0; array[i] && other[i]; ++i) + if (toLower(array[i]) != toLower(other[i])) + return false; + + return used == other.used; + } + + + //! compares the first n characters of the strings + bool equalsn(const string& other, int len) + { + int i; + for(i=0; array[i] && other[i] && i < len; ++i) + if (array[i] != other[i]) + return false; + + // if one (or both) of the strings was smaller then they + // are only equal if they have the same lenght + return (i == len) || (used == other.used); + } + + + //! compares the first n characters of the strings + bool equalsn(const T* str, int len) + { + int i; + for(i=0; array[i] && str[i] && i < len; ++i) + if (array[i] != str[i]) + return false; + + // if one (or both) of the strings was smaller then they + // are only equal if they have the same lenght + return (i == len) || (array[i] == 0 && str[i] == 0); + } + + + //! Appends a character to this string + /** \param character: Character to append. */ + void append(T character) + { + if (used + 1 > allocated) + reallocate((s32)used + 1); + + used += 1; + + array[used-2] = character; + array[used-1] = 0; + } + + //! Appends a string to this string + /** \param other: String to append. */ + void append(const string& other) + { + --used; + + s32 len = other.size(); + + if (used + len + 1 > allocated) + reallocate((s32)used + (s32)len + 1); + + for (s32 l=0; l& other, s32 length) + { + s32 len = other.size(); + + if (len < length) + { + append(other); + return; + } + + len = length; + --used; + + if (used + len > allocated) + reallocate((s32)used + (s32)len); + + for (s32 l=0; l + s32 findFirstCharNotInList(B* c, int count) const + { + for (int i=0; i + s32 findLastCharNotInList(B* c, int count) const + { + for (int i=used-2; i>=0; --i) + { + int j; + for (j=0; j=0; --i) + if (array[i] == c) + return i; + + return -1; + } + + + //! Returns a substring + //! \param begin: Start of substring. + //! \param length: Length of substring. + string subString(s32 begin, s32 length) + { + if (length <= 0) + return string(""); + + string o; + o.reserve(length+1); + + for (s32 i=0; i& other) + { + append(other); + } + + void operator += (int i) + { + append(string(i)); + } + + //! replaces all characters of a special type with another one + void replace(T toReplace, T replaceWith) + { + for (s32 i=0; i=used || index<0) // access violation + + for (int i=index+1; i=(T)'A' && t<=(T)'Z') + return t + ((T)'a' - (T)'A'); + else + return t; + } + + //! Reallocate the array, make it bigger or smaler + void reallocate(s32 new_size) + { + T* old_array = array; + + array = new T[new_size]; + allocated = new_size; + + s32 amount = used < new_size ? used : new_size; + for (s32 i=0; i stringc; + +//! Typedef for wide character strings +typedef string stringw; + +} // end namespace core +} // end namespace irr + +#endif + diff --git a/contrib/irrXML/irrTypes.h b/contrib/irrXML/irrTypes.h index f67be0657..a7f12ec75 100644 --- a/contrib/irrXML/irrTypes.h +++ b/contrib/irrXML/irrTypes.h @@ -1,108 +1,108 @@ -// Copyright (C) 2002-2005 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#ifndef __IRR_TYPES_H_INCLUDED__ -#define __IRR_TYPES_H_INCLUDED__ - -namespace irr -{ - -//! 8 bit unsigned variable. -/** This is a typedef for unsigned char, it ensures portability of the engine. */ -typedef unsigned char u8; - -//! 8 bit signed variable. -/** This is a typedef for signed char, it ensures portability of the engine. */ -typedef signed char s8; - -//! 8 bit character variable. -/** This is a typedef for char, it ensures portability of the engine. */ -typedef char c8; - - - -//! 16 bit unsigned variable. -/** This is a typedef for unsigned short, it ensures portability of the engine. */ -typedef unsigned short u16; - -//! 16 bit signed variable. -/** This is a typedef for signed short, it ensures portability of the engine. */ -typedef signed short s16; - - - -//! 32 bit unsigned variable. -/** This is a typedef for unsigned int, it ensures portability of the engine. */ -typedef unsigned int u32; - -//! 32 bit signed variable. -/** This is a typedef for signed int, it ensures portability of the engine. */ -typedef signed int s32; - - - -// 64 bit signed variable. -// This is a typedef for __int64, it ensures portability of the engine. -// This type is currently not used by the engine and not supported by compilers -// other than Microsoft Compilers, so it is outcommented. -//typedef __int64 s64; - - - -//! 32 bit floating point variable. -/** This is a typedef for float, it ensures portability of the engine. */ -typedef float f32; - -//! 64 bit floating point variable. -/** This is a typedef for double, it ensures portability of the engine. */ -typedef double f64; - - -} // end namespace - - -// define the wchar_t type if not already built in. -#ifdef _MSC_VER -#ifndef _WCHAR_T_DEFINED -//! A 16 bit wide character type. -/** - Defines the wchar_t-type. - In VS6, its not possible to tell - the standard compiler to treat wchar_t as a built-in type, and - sometimes we just don't want to include the huge stdlib.h or wchar.h, - so we'll use this. -*/ -typedef unsigned short wchar_t; -#define _WCHAR_T_DEFINED -#endif // wchar is not defined -#endif // microsoft compiler - -//! define a break macro for debugging only in Win32 mode. -// WORKAROUND (assimp): remove __asm -#if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) -#if defined(_M_IX86) -#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) /*if (_CONDITION_) {_asm int 3}*/ -#else -#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) -#endif -#else -#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) -#endif - -//! Defines a small statement to work around a microsoft compiler bug. -/** The microsft compiler 7.0 - 7.1 has a bug: -When you call unmanaged code that returns a bool type value of false from managed code, -the return value may appear as true. See -http://support.microsoft.com/default.aspx?kbid=823071 for details. -Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/ - -// WORKAROUND (assimp): remove __asm -#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400) -#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX /*__asm mov eax,100*/ -#else -#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX -#endif // _IRR_MANAGED_MARSHALLING_BUGFIX - -#endif // __IRR_TYPES_H_INCLUDED__ - +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __IRR_TYPES_H_INCLUDED__ +#define __IRR_TYPES_H_INCLUDED__ + +namespace irr +{ + +//! 8 bit unsigned variable. +/** This is a typedef for unsigned char, it ensures portability of the engine. */ +typedef unsigned char u8; + +//! 8 bit signed variable. +/** This is a typedef for signed char, it ensures portability of the engine. */ +typedef signed char s8; + +//! 8 bit character variable. +/** This is a typedef for char, it ensures portability of the engine. */ +typedef char c8; + + + +//! 16 bit unsigned variable. +/** This is a typedef for unsigned short, it ensures portability of the engine. */ +typedef unsigned short u16; + +//! 16 bit signed variable. +/** This is a typedef for signed short, it ensures portability of the engine. */ +typedef signed short s16; + + + +//! 32 bit unsigned variable. +/** This is a typedef for unsigned int, it ensures portability of the engine. */ +typedef unsigned int u32; + +//! 32 bit signed variable. +/** This is a typedef for signed int, it ensures portability of the engine. */ +typedef signed int s32; + + + +// 64 bit signed variable. +// This is a typedef for __int64, it ensures portability of the engine. +// This type is currently not used by the engine and not supported by compilers +// other than Microsoft Compilers, so it is outcommented. +//typedef __int64 s64; + + + +//! 32 bit floating point variable. +/** This is a typedef for float, it ensures portability of the engine. */ +typedef float f32; + +//! 64 bit floating point variable. +/** This is a typedef for double, it ensures portability of the engine. */ +typedef double f64; + + +} // end namespace + + +// define the wchar_t type if not already built in. +#ifdef _MSC_VER +#ifndef _WCHAR_T_DEFINED +//! A 16 bit wide character type. +/** + Defines the wchar_t-type. + In VS6, its not possible to tell + the standard compiler to treat wchar_t as a built-in type, and + sometimes we just don't want to include the huge stdlib.h or wchar.h, + so we'll use this. +*/ +typedef unsigned short wchar_t; +#define _WCHAR_T_DEFINED +#endif // wchar is not defined +#endif // microsoft compiler + +//! define a break macro for debugging only in Win32 mode. +// WORKAROUND (assimp): remove __asm +#if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG) +#if defined(_M_IX86) +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) /*if (_CONDITION_) {_asm int 3}*/ +#else +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) +#endif +#else +#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) +#endif + +//! Defines a small statement to work around a microsoft compiler bug. +/** The microsft compiler 7.0 - 7.1 has a bug: +When you call unmanaged code that returns a bool type value of false from managed code, +the return value may appear as true. See +http://support.microsoft.com/default.aspx?kbid=823071 for details. +Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/ + +// WORKAROUND (assimp): remove __asm +#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400) +#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX /*__asm mov eax,100*/ +#else +#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX +#endif // _IRR_MANAGED_MARSHALLING_BUGFIX + +#endif // __IRR_TYPES_H_INCLUDED__ + diff --git a/contrib/irrXML/irrXML.h b/contrib/irrXML/irrXML.h index f9badbd83..b51ddeb54 100644 --- a/contrib/irrXML/irrXML.h +++ b/contrib/irrXML/irrXML.h @@ -1,540 +1,540 @@ -// Copyright (C) 2002-2005 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine" and the "irrXML" project. -// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h - -#ifndef __IRR_XML_H_INCLUDED__ -#define __IRR_XML_H_INCLUDED__ - -#include - -/** \mainpage irrXML 1.2 API documentation -
- - \section intro Introduction - - Welcome to the irrXML API documentation. - Here you'll find any information you'll need to develop applications with - irrXML. If you look for a tutorial on how to start, take a look at the \ref irrxmlexample, - at the homepage of irrXML at xml.irrlicht3d.org - or into the SDK in the directory \example. - - irrXML is intended to be a high speed and easy-to-use XML Parser for C++, and - this documentation is an important part of it. If you have any questions or - suggestions, just send a email to the author of the engine, Nikolaus Gebhardt - (niko (at) irrlicht3d.org). For more informations about this parser, see \ref history. - - \section features Features - - irrXML provides forward-only, read-only - access to a stream of non validated XML data. It was fully implemented by - Nikolaus Gebhardt. Its current features are: - - - It it fast as lighting and has very low memory usage. It was - developed with the intention of being used in 3D games, as it already has been. - - irrXML is very small: It only consists of 60 KB of code and can be added easily - to your existing project. - - Of course, it is platform independent and works with lots of compilers. - - It is able to parse ASCII, UTF-8, UTF-16 and UTF-32 text files, both in - little and big endian format. - - Independent of the input file format, the parser can return all strings in ASCII, UTF-8, - UTF-16 and UTF-32 format. - - With its optional file access abstraction it has the advantage that it can read not - only from files but from any type of data (memory, network, ...). For example when - used with the Irrlicht Engine, it directly reads from compressed .zip files. - - Just like the Irrlicht Engine for which it was originally created, it is extremely easy - to use. - - It has no external dependencies, it does not even need the STL. - - Although irrXML has some strenghts, it currently also has the following limitations: - - - The input xml file is not validated and assumed to be correct. - - \section irrxmlexample Example - - The following code demonstrates the basic usage of irrXML. A simple xml - file like this is parsed: - \code - - - - - - Welcome to the Mesh Viewer of the "Irrlicht Engine". - - - \endcode - - The code for parsing this file would look like this: - \code - #include - using namespace irr; // irrXML is located in the namespace irr::io - using namespace io; - - #include // we use STL strings to store data in this example - - void main() - { - // create the reader using one of the factory functions - - IrrXMLReader* xml = createIrrXMLReader("config.xml"); - - // strings for storing the data we want to get out of the file - std::string modelFile; - std::string messageText; - std::string caption; - - // parse the file until end reached - - while(xml && xml->read()) - { - switch(xml->getNodeType()) - { - case EXN_TEXT: - // in this xml file, the only text which occurs is the messageText - messageText = xml->getNodeData(); - break; - case EXN_ELEMENT: - { - if (!strcmp("model", xml->getNodeName())) - modelFile = xml->getAttributeValue("file"); - else - if (!strcmp("messageText", xml->getNodeName())) - caption = xml->getAttributeValue("caption"); - } - break; - } - } - - // delete the xml parser after usage - delete xml; - } - \endcode - - \section howto How to use - - Simply add the source files in the /src directory of irrXML to your project. Done. - - \section license License - - The irrXML license is based on the zlib license. Basicly, this means you can do with - irrXML whatever you want: - - Copyright (C) 2002-2005 Nikolaus Gebhardt - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source distribution. - - \section history History - - As lots of references in this documentation and the source show, this xml - parser has originally been a part of the - Irrlicht Engine. But because - the parser has become very useful with the latest release, people asked for a - separate version of it, to be able to use it in non Irrlicht projects. With - irrXML 1.0, this has now been done. -*/ - -namespace irr -{ -namespace io -{ - //! Enumeration of all supported source text file formats - enum ETEXT_FORMAT - { - //! ASCII, file without byte order mark, or not a text file - ETF_ASCII, - - //! UTF-8 format - ETF_UTF8, - - //! UTF-16 format, big endian - ETF_UTF16_BE, - - //! UTF-16 format, little endian - ETF_UTF16_LE, - - //! UTF-32 format, big endian - ETF_UTF32_BE, - - //! UTF-32 format, little endian - ETF_UTF32_LE - }; - - - //! Enumeration for all xml nodes which are parsed by IrrXMLReader - enum EXML_NODE - { - //! No xml node. This is usually the node if you did not read anything yet. - EXN_NONE, - - //! A xml element, like - EXN_ELEMENT, - - //! End of an xml element, like - EXN_ELEMENT_END, - - //! Text within a xml element: this is the text. - EXN_TEXT, - - //! An xml comment like <!-- I am a comment --> or a DTD definition. - EXN_COMMENT, - - //! An xml cdata section like <![CDATA[ this is some CDATA ]]> - EXN_CDATA, - - //! Unknown element. - EXN_UNKNOWN - }; - - //! Callback class for file read abstraction. - /** With this, it is possible to make the xml parser read in other things - than just files. The Irrlicht engine is using this for example to - read xml from compressed .zip files. To make the parser read in - any other data, derive a class from this interface, implement the - two methods to read your data and give a pointer to an instance of - your implementation when calling createIrrXMLReader(), - createIrrXMLReaderUTF16() or createIrrXMLReaderUTF32() */ - class IFileReadCallBack - { - public: - - //! virtual destructor - virtual ~IFileReadCallBack() {}; - - //! Reads an amount of bytes from the file. - /** \param buffer: Pointer to buffer where to read bytes will be written to. - \param sizeToRead: Amount of bytes to read from the file. - \return Returns how much bytes were read. */ - virtual int read(void* buffer, int sizeToRead) = 0; - - //! Returns size of file in bytes - virtual int getSize() = 0; - }; - - //! Empty class to be used as parent class for IrrXMLReader. - /** If you need another class as base class for the xml reader, you can do this by creating - the reader using for example new CXMLReaderImpl(yourcallback); - The Irrlicht Engine for example needs IUnknown as base class for every object to - let it automaticly reference countend, hence it replaces IXMLBase with IUnknown. - See irrXML.cpp on how this can be done in detail. */ - class IXMLBase - { - }; - - //! Interface providing easy read access to a XML file. - /** You can create an instance of this reader using one of the factory functions - createIrrXMLReader(), createIrrXMLReaderUTF16() and createIrrXMLReaderUTF32(). - If using the parser from the Irrlicht Engine, please use IFileSystem::createXMLReader() - instead. - For a detailed intro how to use the parser, see \ref irrxmlexample and \ref features. - - The typical usage of this parser looks like this: - \code - #include - using namespace irr; // irrXML is located in the namespace irr::io - using namespace io; - - void main() - { - // create the reader using one of the factory functions - IrrXMLReader* xml = createIrrXMLReader("config.xml"); - - if (xml == 0) - return; // file could not be opened - - // parse the file until end reached - while(xml->read()) - { - // based on xml->getNodeType(), do something. - } - - // delete the xml parser after usage - delete xml; - } - \endcode - See \ref irrxmlexample for a more detailed example. - */ - template - class IIrrXMLReader : public super_class - { - public: - - //! Destructor - virtual ~IIrrXMLReader() {}; - - //! Reads forward to the next xml node. - /** \return Returns false, if there was no further node. */ - virtual bool read() = 0; - - //! Returns the type of the current XML node. - virtual EXML_NODE getNodeType() const = 0; - - //! Returns attribute count of the current XML node. - /** This is usually - non null if the current node is EXN_ELEMENT, and the element has attributes. - \return Returns amount of attributes of this xml node. */ - virtual int getAttributeCount() const = 0; - - //! Returns name of an attribute. - /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. - \return Name of the attribute, 0 if an attribute with this index does not exist. */ - virtual const char_type* getAttributeName(int idx) const = 0; - - //! Returns the value of an attribute. - /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. - \return Value of the attribute, 0 if an attribute with this index does not exist. */ - virtual const char_type* getAttributeValue(int idx) const = 0; - - //! Returns the value of an attribute. - /** \param name: Name of the attribute. - \return Value of the attribute, 0 if an attribute with this name does not exist. */ - virtual const char_type* getAttributeValue(const char_type* name) const = 0; - - //! Returns the value of an attribute in a safe way. - /** Like getAttributeValue(), but does not - return 0 if the attribute does not exist. An empty string ("") is returned then. - \param name: Name of the attribute. - \return Value of the attribute, and "" if an attribute with this name does not exist */ - virtual const char_type* getAttributeValueSafe(const char_type* name) const = 0; - - //! Returns the value of an attribute as integer. - /** \param name Name of the attribute. - \return Value of the attribute as integer, and 0 if an attribute with this name does not exist or - the value could not be interpreted as integer. */ - virtual int getAttributeValueAsInt(const char_type* name) const = 0; - - //! Returns the value of an attribute as integer. - /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. - \return Value of the attribute as integer, and 0 if an attribute with this index does not exist or - the value could not be interpreted as integer. */ - virtual int getAttributeValueAsInt(int idx) const = 0; - - //! Returns the value of an attribute as float. - /** \param name: Name of the attribute. - \return Value of the attribute as float, and 0 if an attribute with this name does not exist or - the value could not be interpreted as float. */ - virtual float getAttributeValueAsFloat(const char_type* name) const = 0; - - //! Returns the value of an attribute as float. - /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. - \return Value of the attribute as float, and 0 if an attribute with this index does not exist or - the value could not be interpreted as float. */ - virtual float getAttributeValueAsFloat(int idx) const = 0; - - //! Returns the name of the current node. - /** Only non null, if the node type is EXN_ELEMENT. - \return Name of the current node or 0 if the node has no name. */ - virtual const char_type* getNodeName() const = 0; - - //! Returns data of the current node. - /** Only non null if the node has some - data and it is of type EXN_TEXT or EXN_UNKNOWN. */ - virtual const char_type* getNodeData() const = 0; - - //! Returns if an element is an empty element, like - virtual bool isEmptyElement() const = 0; - - //! Returns format of the source xml file. - /** It is not necessary to use - this method because the parser will convert the input file format - to the format wanted by the user when creating the parser. This - method is useful to get/display additional informations. */ - virtual ETEXT_FORMAT getSourceFormat() const = 0; - - //! Returns format of the strings returned by the parser. - /** This will be UTF8 for example when you created a parser with - IrrXMLReaderUTF8() and UTF32 when it has been created using - IrrXMLReaderUTF32. It should not be necessary to call this - method and only exists for informational purposes. */ - virtual ETEXT_FORMAT getParserFormat() const = 0; - }; - - - //! defines the utf-16 type. - /** Not using wchar_t for this because - wchar_t has 16 bit on windows and 32 bit on other operating systems. */ - typedef unsigned short char16; - - //! defines the utf-32 type. - /** Not using wchar_t for this because - wchar_t has 16 bit on windows and 32 bit on other operating systems. */ - typedef unsigned long char32; - - //! A UTF-8 or ASCII character xml parser. - /** This means that all character data will be returned in 8 bit ASCII or UTF-8 by this parser. - The file to read can be in any format, it will be converted to UTF-8 if it is not - in this format. - Create an instance of this with createIrrXMLReader(); - See IIrrXMLReader for description on how to use it. */ - typedef IIrrXMLReader IrrXMLReader; - - //! A UTF-16 xml parser. - /** This means that all character data will be returned in UTF-16 by this parser. - The file to read can be in any format, it will be converted to UTF-16 if it is not - in this format. - Create an instance of this with createIrrXMLReaderUTF16(); - See IIrrXMLReader for description on how to use it. */ - typedef IIrrXMLReader IrrXMLReaderUTF16; - - //! A UTF-32 xml parser. - /** This means that all character data will be returned in UTF-32 by this parser. - The file to read can be in any format, it will be converted to UTF-32 if it is not - in this format. - Create an instance of this with createIrrXMLReaderUTF32(); - See IIrrXMLReader for description on how to use it. */ - typedef IIrrXMLReader IrrXMLReaderUTF32; - - - //! Creates an instance of an UFT-8 or ASCII character xml parser. - /** This means that all character data will be returned in 8 bit ASCII or UTF-8. - The file to read can be in any format, it will be converted to UTF-8 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReaderUTF8() instead. - \param filename: Name of file to be opened. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReader* createIrrXMLReader(const char* filename); - - //! Creates an instance of an UFT-8 or ASCII character xml parser. - /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can - be in any format, it will be converted to UTF-8 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReaderUTF8() instead. - \param file: Pointer to opened file, must have been opened in binary mode, e.g. - using fopen("foo.bar", "wb"); The file will not be closed after it has been read. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReader* createIrrXMLReader(FILE* file); - - //! Creates an instance of an UFT-8 or ASCII character xml parser. - /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can - be in any format, it will be converted to UTF-8 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReaderUTF8() instead. - \param callback: Callback for file read abstraction. Implement your own - callback to make the xml parser read in other things than just files. See - IFileReadCallBack for more information about this. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback); - - //! Creates an instance of an UFT-16 xml parser. - /** This means that - all character data will be returned in UTF-16. The file to read can - be in any format, it will be converted to UTF-16 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReader() instead. - \param filename: Name of file to be opened. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename); - - //! Creates an instance of an UFT-16 xml parser. - /** This means that all character data will be returned in UTF-16. The file to read can - be in any format, it will be converted to UTF-16 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReader() instead. - \param file: Pointer to opened file, must have been opened in binary mode, e.g. - using fopen("foo.bar", "wb"); The file will not be closed after it has been read. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file); - - //! Creates an instance of an UFT-16 xml parser. - /** This means that all character data will be returned in UTF-16. The file to read can - be in any format, it will be converted to UTF-16 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReader() instead. - \param callback: Callback for file read abstraction. Implement your own - callback to make the xml parser read in other things than just files. See - IFileReadCallBack for more information about this. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback); - - - //! Creates an instance of an UFT-32 xml parser. - /** This means that all character data will be returned in UTF-32. The file to read can - be in any format, it will be converted to UTF-32 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReader() instead. - \param filename: Name of file to be opened. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename); - - //! Creates an instance of an UFT-32 xml parser. - /** This means that all character data will be returned in UTF-32. The file to read can - be in any format, it will be converted to UTF-32 if it is not in this format. - if you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReader() instead. - \param file: Pointer to opened file, must have been opened in binary mode, e.g. - using fopen("foo.bar", "wb"); The file will not be closed after it has been read. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file); - - //! Creates an instance of an UFT-32 xml parser. - /** This means that - all character data will be returned in UTF-32. The file to read can - be in any format, it will be converted to UTF-32 if it is not in this format. - If you are using the Irrlicht Engine, it is better not to use this function but - IFileSystem::createXMLReader() instead. - \param callback: Callback for file read abstraction. Implement your own - callback to make the xml parser read in other things than just files. See - IFileReadCallBack for more information about this. - \return Returns a pointer to the created xml parser. This pointer should be - deleted using 'delete' after no longer needed. Returns 0 if an error occured - and the file could not be opened. */ - IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback); - - - /*! \file irrxml.h - \brief Header file of the irrXML, the Irrlicht XML parser. - - This file includes everything needed for using irrXML, - the XML parser of the Irrlicht Engine. To use irrXML, - you only need to include this file in your project: - - \code - #include - \endcode - - It is also common to use the two namespaces in which irrXML is included, - directly after #including irrXML.h: - - \code - #include - using namespace irr; - using namespace io; - \endcode - */ - -} // end namespace io -} // end namespace irr - -#endif // __IRR_XML_H_INCLUDED__ - +// Copyright (C) 2002-2005 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine" and the "irrXML" project. +// For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h + +#ifndef __IRR_XML_H_INCLUDED__ +#define __IRR_XML_H_INCLUDED__ + +#include + +/** \mainpage irrXML 1.2 API documentation +
+ + \section intro Introduction + + Welcome to the irrXML API documentation. + Here you'll find any information you'll need to develop applications with + irrXML. If you look for a tutorial on how to start, take a look at the \ref irrxmlexample, + at the homepage of irrXML at xml.irrlicht3d.org + or into the SDK in the directory \example. + + irrXML is intended to be a high speed and easy-to-use XML Parser for C++, and + this documentation is an important part of it. If you have any questions or + suggestions, just send a email to the author of the engine, Nikolaus Gebhardt + (niko (at) irrlicht3d.org). For more informations about this parser, see \ref history. + + \section features Features + + irrXML provides forward-only, read-only + access to a stream of non validated XML data. It was fully implemented by + Nikolaus Gebhardt. Its current features are: + + - It it fast as lighting and has very low memory usage. It was + developed with the intention of being used in 3D games, as it already has been. + - irrXML is very small: It only consists of 60 KB of code and can be added easily + to your existing project. + - Of course, it is platform independent and works with lots of compilers. + - It is able to parse ASCII, UTF-8, UTF-16 and UTF-32 text files, both in + little and big endian format. + - Independent of the input file format, the parser can return all strings in ASCII, UTF-8, + UTF-16 and UTF-32 format. + - With its optional file access abstraction it has the advantage that it can read not + only from files but from any type of data (memory, network, ...). For example when + used with the Irrlicht Engine, it directly reads from compressed .zip files. + - Just like the Irrlicht Engine for which it was originally created, it is extremely easy + to use. + - It has no external dependencies, it does not even need the STL. + + Although irrXML has some strenghts, it currently also has the following limitations: + + - The input xml file is not validated and assumed to be correct. + + \section irrxmlexample Example + + The following code demonstrates the basic usage of irrXML. A simple xml + file like this is parsed: + \code + + + + + + Welcome to the Mesh Viewer of the "Irrlicht Engine". + + + \endcode + + The code for parsing this file would look like this: + \code + #include + using namespace irr; // irrXML is located in the namespace irr::io + using namespace io; + + #include // we use STL strings to store data in this example + + void main() + { + // create the reader using one of the factory functions + + IrrXMLReader* xml = createIrrXMLReader("config.xml"); + + // strings for storing the data we want to get out of the file + std::string modelFile; + std::string messageText; + std::string caption; + + // parse the file until end reached + + while(xml && xml->read()) + { + switch(xml->getNodeType()) + { + case EXN_TEXT: + // in this xml file, the only text which occurs is the messageText + messageText = xml->getNodeData(); + break; + case EXN_ELEMENT: + { + if (!strcmp("model", xml->getNodeName())) + modelFile = xml->getAttributeValue("file"); + else + if (!strcmp("messageText", xml->getNodeName())) + caption = xml->getAttributeValue("caption"); + } + break; + } + } + + // delete the xml parser after usage + delete xml; + } + \endcode + + \section howto How to use + + Simply add the source files in the /src directory of irrXML to your project. Done. + + \section license License + + The irrXML license is based on the zlib license. Basicly, this means you can do with + irrXML whatever you want: + + Copyright (C) 2002-2005 Nikolaus Gebhardt + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + \section history History + + As lots of references in this documentation and the source show, this xml + parser has originally been a part of the + Irrlicht Engine. But because + the parser has become very useful with the latest release, people asked for a + separate version of it, to be able to use it in non Irrlicht projects. With + irrXML 1.0, this has now been done. +*/ + +namespace irr +{ +namespace io +{ + //! Enumeration of all supported source text file formats + enum ETEXT_FORMAT + { + //! ASCII, file without byte order mark, or not a text file + ETF_ASCII, + + //! UTF-8 format + ETF_UTF8, + + //! UTF-16 format, big endian + ETF_UTF16_BE, + + //! UTF-16 format, little endian + ETF_UTF16_LE, + + //! UTF-32 format, big endian + ETF_UTF32_BE, + + //! UTF-32 format, little endian + ETF_UTF32_LE + }; + + + //! Enumeration for all xml nodes which are parsed by IrrXMLReader + enum EXML_NODE + { + //! No xml node. This is usually the node if you did not read anything yet. + EXN_NONE, + + //! A xml element, like + EXN_ELEMENT, + + //! End of an xml element, like + EXN_ELEMENT_END, + + //! Text within a xml element: this is the text. + EXN_TEXT, + + //! An xml comment like <!-- I am a comment --> or a DTD definition. + EXN_COMMENT, + + //! An xml cdata section like <![CDATA[ this is some CDATA ]]> + EXN_CDATA, + + //! Unknown element. + EXN_UNKNOWN + }; + + //! Callback class for file read abstraction. + /** With this, it is possible to make the xml parser read in other things + than just files. The Irrlicht engine is using this for example to + read xml from compressed .zip files. To make the parser read in + any other data, derive a class from this interface, implement the + two methods to read your data and give a pointer to an instance of + your implementation when calling createIrrXMLReader(), + createIrrXMLReaderUTF16() or createIrrXMLReaderUTF32() */ + class IFileReadCallBack + { + public: + + //! virtual destructor + virtual ~IFileReadCallBack() {}; + + //! Reads an amount of bytes from the file. + /** \param buffer: Pointer to buffer where to read bytes will be written to. + \param sizeToRead: Amount of bytes to read from the file. + \return Returns how much bytes were read. */ + virtual int read(void* buffer, int sizeToRead) = 0; + + //! Returns size of file in bytes + virtual int getSize() = 0; + }; + + //! Empty class to be used as parent class for IrrXMLReader. + /** If you need another class as base class for the xml reader, you can do this by creating + the reader using for example new CXMLReaderImpl(yourcallback); + The Irrlicht Engine for example needs IUnknown as base class for every object to + let it automaticly reference countend, hence it replaces IXMLBase with IUnknown. + See irrXML.cpp on how this can be done in detail. */ + class IXMLBase + { + }; + + //! Interface providing easy read access to a XML file. + /** You can create an instance of this reader using one of the factory functions + createIrrXMLReader(), createIrrXMLReaderUTF16() and createIrrXMLReaderUTF32(). + If using the parser from the Irrlicht Engine, please use IFileSystem::createXMLReader() + instead. + For a detailed intro how to use the parser, see \ref irrxmlexample and \ref features. + + The typical usage of this parser looks like this: + \code + #include + using namespace irr; // irrXML is located in the namespace irr::io + using namespace io; + + void main() + { + // create the reader using one of the factory functions + IrrXMLReader* xml = createIrrXMLReader("config.xml"); + + if (xml == 0) + return; // file could not be opened + + // parse the file until end reached + while(xml->read()) + { + // based on xml->getNodeType(), do something. + } + + // delete the xml parser after usage + delete xml; + } + \endcode + See \ref irrxmlexample for a more detailed example. + */ + template + class IIrrXMLReader : public super_class + { + public: + + //! Destructor + virtual ~IIrrXMLReader() {}; + + //! Reads forward to the next xml node. + /** \return Returns false, if there was no further node. */ + virtual bool read() = 0; + + //! Returns the type of the current XML node. + virtual EXML_NODE getNodeType() const = 0; + + //! Returns attribute count of the current XML node. + /** This is usually + non null if the current node is EXN_ELEMENT, and the element has attributes. + \return Returns amount of attributes of this xml node. */ + virtual int getAttributeCount() const = 0; + + //! Returns name of an attribute. + /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. + \return Name of the attribute, 0 if an attribute with this index does not exist. */ + virtual const char_type* getAttributeName(int idx) const = 0; + + //! Returns the value of an attribute. + /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. + \return Value of the attribute, 0 if an attribute with this index does not exist. */ + virtual const char_type* getAttributeValue(int idx) const = 0; + + //! Returns the value of an attribute. + /** \param name: Name of the attribute. + \return Value of the attribute, 0 if an attribute with this name does not exist. */ + virtual const char_type* getAttributeValue(const char_type* name) const = 0; + + //! Returns the value of an attribute in a safe way. + /** Like getAttributeValue(), but does not + return 0 if the attribute does not exist. An empty string ("") is returned then. + \param name: Name of the attribute. + \return Value of the attribute, and "" if an attribute with this name does not exist */ + virtual const char_type* getAttributeValueSafe(const char_type* name) const = 0; + + //! Returns the value of an attribute as integer. + /** \param name Name of the attribute. + \return Value of the attribute as integer, and 0 if an attribute with this name does not exist or + the value could not be interpreted as integer. */ + virtual int getAttributeValueAsInt(const char_type* name) const = 0; + + //! Returns the value of an attribute as integer. + /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. + \return Value of the attribute as integer, and 0 if an attribute with this index does not exist or + the value could not be interpreted as integer. */ + virtual int getAttributeValueAsInt(int idx) const = 0; + + //! Returns the value of an attribute as float. + /** \param name: Name of the attribute. + \return Value of the attribute as float, and 0 if an attribute with this name does not exist or + the value could not be interpreted as float. */ + virtual float getAttributeValueAsFloat(const char_type* name) const = 0; + + //! Returns the value of an attribute as float. + /** \param idx: Zero based index, should be something between 0 and getAttributeCount()-1. + \return Value of the attribute as float, and 0 if an attribute with this index does not exist or + the value could not be interpreted as float. */ + virtual float getAttributeValueAsFloat(int idx) const = 0; + + //! Returns the name of the current node. + /** Only non null, if the node type is EXN_ELEMENT. + \return Name of the current node or 0 if the node has no name. */ + virtual const char_type* getNodeName() const = 0; + + //! Returns data of the current node. + /** Only non null if the node has some + data and it is of type EXN_TEXT or EXN_UNKNOWN. */ + virtual const char_type* getNodeData() const = 0; + + //! Returns if an element is an empty element, like + virtual bool isEmptyElement() const = 0; + + //! Returns format of the source xml file. + /** It is not necessary to use + this method because the parser will convert the input file format + to the format wanted by the user when creating the parser. This + method is useful to get/display additional informations. */ + virtual ETEXT_FORMAT getSourceFormat() const = 0; + + //! Returns format of the strings returned by the parser. + /** This will be UTF8 for example when you created a parser with + IrrXMLReaderUTF8() and UTF32 when it has been created using + IrrXMLReaderUTF32. It should not be necessary to call this + method and only exists for informational purposes. */ + virtual ETEXT_FORMAT getParserFormat() const = 0; + }; + + + //! defines the utf-16 type. + /** Not using wchar_t for this because + wchar_t has 16 bit on windows and 32 bit on other operating systems. */ + typedef unsigned short char16; + + //! defines the utf-32 type. + /** Not using wchar_t for this because + wchar_t has 16 bit on windows and 32 bit on other operating systems. */ + typedef unsigned long char32; + + //! A UTF-8 or ASCII character xml parser. + /** This means that all character data will be returned in 8 bit ASCII or UTF-8 by this parser. + The file to read can be in any format, it will be converted to UTF-8 if it is not + in this format. + Create an instance of this with createIrrXMLReader(); + See IIrrXMLReader for description on how to use it. */ + typedef IIrrXMLReader IrrXMLReader; + + //! A UTF-16 xml parser. + /** This means that all character data will be returned in UTF-16 by this parser. + The file to read can be in any format, it will be converted to UTF-16 if it is not + in this format. + Create an instance of this with createIrrXMLReaderUTF16(); + See IIrrXMLReader for description on how to use it. */ + typedef IIrrXMLReader IrrXMLReaderUTF16; + + //! A UTF-32 xml parser. + /** This means that all character data will be returned in UTF-32 by this parser. + The file to read can be in any format, it will be converted to UTF-32 if it is not + in this format. + Create an instance of this with createIrrXMLReaderUTF32(); + See IIrrXMLReader for description on how to use it. */ + typedef IIrrXMLReader IrrXMLReaderUTF32; + + + //! Creates an instance of an UFT-8 or ASCII character xml parser. + /** This means that all character data will be returned in 8 bit ASCII or UTF-8. + The file to read can be in any format, it will be converted to UTF-8 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReaderUTF8() instead. + \param filename: Name of file to be opened. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReader* createIrrXMLReader(const char* filename); + + //! Creates an instance of an UFT-8 or ASCII character xml parser. + /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can + be in any format, it will be converted to UTF-8 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReaderUTF8() instead. + \param file: Pointer to opened file, must have been opened in binary mode, e.g. + using fopen("foo.bar", "wb"); The file will not be closed after it has been read. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReader* createIrrXMLReader(FILE* file); + + //! Creates an instance of an UFT-8 or ASCII character xml parser. + /** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can + be in any format, it will be converted to UTF-8 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReaderUTF8() instead. + \param callback: Callback for file read abstraction. Implement your own + callback to make the xml parser read in other things than just files. See + IFileReadCallBack for more information about this. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback); + + //! Creates an instance of an UFT-16 xml parser. + /** This means that + all character data will be returned in UTF-16. The file to read can + be in any format, it will be converted to UTF-16 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param filename: Name of file to be opened. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename); + + //! Creates an instance of an UFT-16 xml parser. + /** This means that all character data will be returned in UTF-16. The file to read can + be in any format, it will be converted to UTF-16 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param file: Pointer to opened file, must have been opened in binary mode, e.g. + using fopen("foo.bar", "wb"); The file will not be closed after it has been read. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file); + + //! Creates an instance of an UFT-16 xml parser. + /** This means that all character data will be returned in UTF-16. The file to read can + be in any format, it will be converted to UTF-16 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param callback: Callback for file read abstraction. Implement your own + callback to make the xml parser read in other things than just files. See + IFileReadCallBack for more information about this. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback); + + + //! Creates an instance of an UFT-32 xml parser. + /** This means that all character data will be returned in UTF-32. The file to read can + be in any format, it will be converted to UTF-32 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param filename: Name of file to be opened. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename); + + //! Creates an instance of an UFT-32 xml parser. + /** This means that all character data will be returned in UTF-32. The file to read can + be in any format, it will be converted to UTF-32 if it is not in this format. + if you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param file: Pointer to opened file, must have been opened in binary mode, e.g. + using fopen("foo.bar", "wb"); The file will not be closed after it has been read. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file); + + //! Creates an instance of an UFT-32 xml parser. + /** This means that + all character data will be returned in UTF-32. The file to read can + be in any format, it will be converted to UTF-32 if it is not in this format. + If you are using the Irrlicht Engine, it is better not to use this function but + IFileSystem::createXMLReader() instead. + \param callback: Callback for file read abstraction. Implement your own + callback to make the xml parser read in other things than just files. See + IFileReadCallBack for more information about this. + \return Returns a pointer to the created xml parser. This pointer should be + deleted using 'delete' after no longer needed. Returns 0 if an error occured + and the file could not be opened. */ + IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback); + + + /*! \file irrxml.h + \brief Header file of the irrXML, the Irrlicht XML parser. + + This file includes everything needed for using irrXML, + the XML parser of the Irrlicht Engine. To use irrXML, + you only need to include this file in your project: + + \code + #include + \endcode + + It is also common to use the two namespaces in which irrXML is included, + directly after #including irrXML.h: + + \code + #include + using namespace irr; + using namespace io; + \endcode + */ + +} // end namespace io +} // end namespace irr + +#endif // __IRR_XML_H_INCLUDED__ + diff --git a/contrib/irrXML_note.txt b/contrib/irrXML_note.txt index 403a0dbc6..ff7897ec2 100644 --- a/contrib/irrXML_note.txt +++ b/contrib/irrXML_note.txt @@ -1,6 +1,6 @@ - -IrrXML -Downloaded September 2008 - -- fixed a minor compiler warning (vs 2005, shift too large) -- fixed an issue regarding wchar_t/unsigned short + +IrrXML +Downloaded September 2008 + +- fixed a minor compiler warning (vs 2005, shift too large) +- fixed an issue regarding wchar_t/unsigned short diff --git a/contrib/poly2tri/poly2tri/common/utils.h b/contrib/poly2tri/poly2tri/common/utils.h index e3ed008f3..cb7a7dc01 100644 --- a/contrib/poly2tri/poly2tri/common/utils.h +++ b/contrib/poly2tri/poly2tri/common/utils.h @@ -1,105 +1,105 @@ -/* - * 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 -#include - -namespace p2t { - -const double PI_3div4 = 3 * M_PI / 4; -const double EPSILON = 1e-15; - -enum Orientation { CW, CCW, COLLINEAR }; - -/** - * Forumla to calculate signed area
- * Positive if CCW
- * Negative if CW
- * 0 if collinear
- *
- * A[P1,P2,P3]  =  (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
- *              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
- * 
- */ -Orientation Orient2d(Point& pa, Point& pb, Point& pc) -{ - double detleft = (pa.x - pc.x) * (pb.y - pc.y); - double detright = (pa.y - pc.y) * (pb.x - pc.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; -} - -} - -#endif - +/* + * 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 +#include + +namespace p2t { + +const double PI_3div4 = 3 * M_PI / 4; +const double EPSILON = 1e-15; + +enum Orientation { CW, CCW, COLLINEAR }; + +/** + * Forumla to calculate signed area
+ * Positive if CCW
+ * Negative if CW
+ * 0 if collinear
+ *
+ * A[P1,P2,P3]  =  (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
+ *              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
+ * 
+ */ +Orientation Orient2d(Point& pa, Point& pb, Point& pc) +{ + double detleft = (pa.x - pc.x) * (pb.y - pc.y); + double detright = (pa.y - pc.y) * (pb.x - pc.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; +} + +} + +#endif + diff --git a/contrib/poly2tri/poly2tri/sweep/cdt.h b/contrib/poly2tri/poly2tri/sweep/cdt.h index baf6ca7dd..3e6f02408 100644 --- a/contrib/poly2tri/poly2tri/sweep/cdt.h +++ b/contrib/poly2tri/poly2tri/sweep/cdt.h @@ -1,105 +1,105 @@ -/* - * 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 CDT_H -#define CDT_H - -#include "advancing_front.h" -#include "sweep_context.h" -#include "sweep.h" - -/** - * - * @author Mason Green - * - */ - -namespace p2t { - -class CDT -{ -public: - - /** - * Constructor - add polyline with non repeating points - * - * @param polyline - */ - CDT(std::vector polyline); - - /** - * Destructor - clean up memory - */ - ~CDT(); - - /** - * Add a hole - * - * @param polyline - */ - void AddHole(std::vector polyline); - - /** - * Add a steiner point - * - * @param point - */ - void AddPoint(Point* point); - - /** - * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points - */ - void Triangulate(); - - /** - * Get CDT triangles - */ - std::vector GetTriangles(); - - /** - * Get triangle map - */ - std::list GetMap(); - - private: - - /** - * Internals - */ - - SweepContext* sweep_context_; - Sweep* sweep_; - -}; - -} - -#endif +/* + * 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 CDT_H +#define CDT_H + +#include "advancing_front.h" +#include "sweep_context.h" +#include "sweep.h" + +/** + * + * @author Mason Green + * + */ + +namespace p2t { + +class CDT +{ +public: + + /** + * Constructor - add polyline with non repeating points + * + * @param polyline + */ + CDT(std::vector polyline); + + /** + * Destructor - clean up memory + */ + ~CDT(); + + /** + * Add a hole + * + * @param polyline + */ + void AddHole(std::vector polyline); + + /** + * Add a steiner point + * + * @param point + */ + void AddPoint(Point* point); + + /** + * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points + */ + void Triangulate(); + + /** + * Get CDT triangles + */ + std::vector GetTriangles(); + + /** + * Get triangle map + */ + std::list GetMap(); + + private: + + /** + * Internals + */ + + SweepContext* sweep_context_; + Sweep* sweep_; + +}; + +} + +#endif diff --git a/contrib/poly2tri/poly2tri/sweep/sweep_context.h b/contrib/poly2tri/poly2tri/sweep/sweep_context.h index 266408dc2..1010c0e8a 100644 --- a/contrib/poly2tri/poly2tri/sweep/sweep_context.h +++ b/contrib/poly2tri/poly2tri/sweep/sweep_context.h @@ -1,186 +1,186 @@ -/* - * 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 SWEEP_CONTEXT_H -#define SWEEP_CONTEXT_H - -#include -#include -#include - -namespace p2t { - -// Inital triangle factor, seed triangle will extend 30% of -// PointSet width to both left and right. -const double kAlpha = 0.3; - -struct Point; -class Triangle; -struct Node; -struct Edge; -class AdvancingFront; - -class SweepContext { -public: - -/// Constructor -SweepContext(std::vector polyline); -/// Destructor -~SweepContext(); - -void set_head(Point* p1); - -Point* head(); - -void set_tail(Point* p1); - -Point* tail(); - -int point_count(); - -Node& LocateNode(Point& point); - -void RemoveNode(Node* node); - -void CreateAdvancingFront(std::vector nodes); - -/// Try to map a node to all sides of this triangle that don't have a neighbor -void MapTriangleToNodes(Triangle& t); - -void AddToMap(Triangle* triangle); - -Point* GetPoint(const int& index); - -Point* GetPoints(); - -void RemoveFromMap(Triangle* triangle); - -void AddHole(std::vector polyline); - -void AddPoint(Point* point); - -AdvancingFront* front(); - -void MeshClean(Triangle& triangle); - -std::vector GetTriangles(); +/* + * 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 SWEEP_CONTEXT_H +#define SWEEP_CONTEXT_H + +#include +#include +#include + +namespace p2t { + +// Inital triangle factor, seed triangle will extend 30% of +// PointSet width to both left and right. +const double kAlpha = 0.3; + +struct Point; +class Triangle; +struct Node; +struct Edge; +class AdvancingFront; + +class SweepContext { +public: + +/// Constructor +SweepContext(std::vector polyline); +/// Destructor +~SweepContext(); + +void set_head(Point* p1); + +Point* head(); + +void set_tail(Point* p1); + +Point* tail(); + +int point_count(); + +Node& LocateNode(Point& point); + +void RemoveNode(Node* node); + +void CreateAdvancingFront(std::vector nodes); + +/// Try to map a node to all sides of this triangle that don't have a neighbor +void MapTriangleToNodes(Triangle& t); + +void AddToMap(Triangle* triangle); + +Point* GetPoint(const int& index); + +Point* GetPoints(); + +void RemoveFromMap(Triangle* triangle); + +void AddHole(std::vector polyline); + +void AddPoint(Point* point); + +AdvancingFront* front(); + +void MeshClean(Triangle& triangle); + +std::vector GetTriangles(); std::list GetMap(); - -std::vector edge_list; - -struct Basin { - Node* left_node; - Node* bottom_node; - Node* right_node; - double width; - bool left_highest; - - Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), width(0.0), left_highest(false) - { - } - - void Clear() - { - left_node = NULL; - bottom_node = NULL; - right_node = NULL; - width = 0.0; - left_highest = false; - } -}; - -struct EdgeEvent { - Edge* constrained_edge; - bool right; - - EdgeEvent() : constrained_edge(NULL), right(false) - { - } -}; - -Basin basin; -EdgeEvent edge_event; - -private: - -friend class Sweep; - -std::vector triangles_; -std::list map_; -std::vector points_; - -// Advancing front -AdvancingFront* front_; -// head point used with advancing front -Point* head_; -// tail point used with advancing front -Point* tail_; - -Node *af_head_, *af_middle_, *af_tail_; - -void InitTriangulation(); -void InitEdges(std::vector polyline); - -}; - -inline AdvancingFront* SweepContext::front() -{ - return front_; -} - -inline int SweepContext::point_count() -{ - return points_.size(); -} - -inline void SweepContext::set_head(Point* p1) -{ - head_ = p1; -} - -inline Point* SweepContext::head() -{ - return head_; -} - -inline void SweepContext::set_tail(Point* p1) -{ - tail_ = p1; -} - -inline Point* SweepContext::tail() -{ - return tail_; -} - -} - -#endif + +std::vector edge_list; + +struct Basin { + Node* left_node; + Node* bottom_node; + Node* right_node; + double width; + bool left_highest; + + Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), width(0.0), left_highest(false) + { + } + + void Clear() + { + left_node = NULL; + bottom_node = NULL; + right_node = NULL; + width = 0.0; + left_highest = false; + } +}; + +struct EdgeEvent { + Edge* constrained_edge; + bool right; + + EdgeEvent() : constrained_edge(NULL), right(false) + { + } +}; + +Basin basin; +EdgeEvent edge_event; + +private: + +friend class Sweep; + +std::vector triangles_; +std::list map_; +std::vector points_; + +// Advancing front +AdvancingFront* front_; +// head point used with advancing front +Point* head_; +// tail point used with advancing front +Point* tail_; + +Node *af_head_, *af_middle_, *af_tail_; + +void InitTriangulation(); +void InitEdges(std::vector polyline); + +}; + +inline AdvancingFront* SweepContext::front() +{ + return front_; +} + +inline int SweepContext::point_count() +{ + return points_.size(); +} + +inline void SweepContext::set_head(Point* p1) +{ + head_ = p1; +} + +inline Point* SweepContext::head() +{ + return head_; +} + +inline void SweepContext::set_tail(Point* p1) +{ + tail_ = p1; +} + +inline Point* SweepContext::tail() +{ + return tail_; +} + +} + +#endif diff --git a/contrib/poly2tri_patch.txt b/contrib/poly2tri_patch.txt index 33e621b20..e9cca4cec 100644 --- a/contrib/poly2tri_patch.txt +++ b/contrib/poly2tri_patch.txt @@ -1,75 +1,75 @@ -diff -r 5de9623d6a50 poly2tri/common/shapes.h ---- a/poly2tri/common/shapes.h Mon Aug 08 22:26:41 2011 -0400 -+++ b/poly2tri/common/shapes.h Tue Jan 17 02:36:52 2012 +0100 -@@ -35,6 +35,7 @@ - - #include - #include -+#include - #include - #include - -@@ -136,7 +137,9 @@ - p = &p2; - } else if (p1.x == p2.x) { - // Repeat points -- assert(false); -+ // ASSIMP_CHANGE (aramis_acg) -+ throw std::runtime_error("repeat points"); -+ //assert(false); - } - } - -diff -r 5de9623d6a50 poly2tri/sweep/sweep.cc ---- a/poly2tri/sweep/sweep.cc Mon Aug 08 22:26:41 2011 -0400 -+++ b/poly2tri/sweep/sweep.cc Tue Jan 17 02:36:52 2012 +0100 -@@ -113,6 +113,8 @@ - Point* p1 = triangle->PointCCW(point); - Orientation o1 = Orient2d(eq, *p1, ep); - if (o1 == COLLINEAR) { -+ // ASSIMP_CHANGE (aramis_acg) -+ throw std::runtime_error("EdgeEvent - collinear points not supported"); - if( triangle->Contains(&eq, p1)) { - triangle->MarkConstrainedEdge(&eq, p1 ); - // We are modifying the constraint maybe it would be better to -@@ -121,8 +123,8 @@ - triangle = &triangle->NeighborAcross(point); - EdgeEvent( tcx, ep, *p1, triangle, *p1 ); - } else { -+ // ASSIMP_CHANGE (aramis_acg) - std::runtime_error("EdgeEvent - collinear points not supported"); -- assert(0); - } - return; - } -@@ -130,6 +132,9 @@ - Point* p2 = triangle->PointCW(point); - Orientation o2 = Orient2d(eq, *p2, ep); - if (o2 == COLLINEAR) { -+ // ASSIMP_CHANGE (aramis_acg) -+ throw std::runtime_error("EdgeEvent - collinear points not supported"); -+ - if( triangle->Contains(&eq, p2)) { - triangle->MarkConstrainedEdge(&eq, p2 ); - // We are modifying the constraint maybe it would be better to -@@ -138,8 +143,8 @@ - triangle = &triangle->NeighborAcross(point); - EdgeEvent( tcx, ep, *p2, triangle, *p2 ); - } else { -- std::runtime_error("EdgeEvent - collinear points not supported"); -- assert(0); -+ // ASSIMP_CHANGE (aramis_acg) -+ throw std::runtime_error("EdgeEvent - collinear points not supported"); - } - return; - } -@@ -712,7 +717,8 @@ - return *ot.PointCW(op); - } else{ - //throw new RuntimeException("[Unsupported] Opposing point on constrained edge"); -- assert(0); -+ // ASSIMP_CHANGE (aramis_acg) -+ throw std::runtime_error("[Unsupported] Opposing point on constrained edge"); - } - } - +diff -r 5de9623d6a50 poly2tri/common/shapes.h +--- a/poly2tri/common/shapes.h Mon Aug 08 22:26:41 2011 -0400 ++++ b/poly2tri/common/shapes.h Tue Jan 17 02:36:52 2012 +0100 +@@ -35,6 +35,7 @@ + + #include + #include ++#include + #include + #include + +@@ -136,7 +137,9 @@ + p = &p2; + } else if (p1.x == p2.x) { + // Repeat points +- assert(false); ++ // ASSIMP_CHANGE (aramis_acg) ++ throw std::runtime_error("repeat points"); ++ //assert(false); + } + } + +diff -r 5de9623d6a50 poly2tri/sweep/sweep.cc +--- a/poly2tri/sweep/sweep.cc Mon Aug 08 22:26:41 2011 -0400 ++++ b/poly2tri/sweep/sweep.cc Tue Jan 17 02:36:52 2012 +0100 +@@ -113,6 +113,8 @@ + Point* p1 = triangle->PointCCW(point); + Orientation o1 = Orient2d(eq, *p1, ep); + if (o1 == COLLINEAR) { ++ // ASSIMP_CHANGE (aramis_acg) ++ throw std::runtime_error("EdgeEvent - collinear points not supported"); + if( triangle->Contains(&eq, p1)) { + triangle->MarkConstrainedEdge(&eq, p1 ); + // We are modifying the constraint maybe it would be better to +@@ -121,8 +123,8 @@ + triangle = &triangle->NeighborAcross(point); + EdgeEvent( tcx, ep, *p1, triangle, *p1 ); + } else { ++ // ASSIMP_CHANGE (aramis_acg) + std::runtime_error("EdgeEvent - collinear points not supported"); +- assert(0); + } + return; + } +@@ -130,6 +132,9 @@ + Point* p2 = triangle->PointCW(point); + Orientation o2 = Orient2d(eq, *p2, ep); + if (o2 == COLLINEAR) { ++ // ASSIMP_CHANGE (aramis_acg) ++ throw std::runtime_error("EdgeEvent - collinear points not supported"); ++ + if( triangle->Contains(&eq, p2)) { + triangle->MarkConstrainedEdge(&eq, p2 ); + // We are modifying the constraint maybe it would be better to +@@ -138,8 +143,8 @@ + triangle = &triangle->NeighborAcross(point); + EdgeEvent( tcx, ep, *p2, triangle, *p2 ); + } else { +- std::runtime_error("EdgeEvent - collinear points not supported"); +- assert(0); ++ // ASSIMP_CHANGE (aramis_acg) ++ throw std::runtime_error("EdgeEvent - collinear points not supported"); + } + return; + } +@@ -712,7 +717,8 @@ + return *ot.PointCW(op); + } else{ + //throw new RuntimeException("[Unsupported] Opposing point on constrained edge"); +- assert(0); ++ // ASSIMP_CHANGE (aramis_acg) ++ throw std::runtime_error("[Unsupported] Opposing point on constrained edge"); + } + } + diff --git a/contrib/unzip/crypt.h b/contrib/unzip/crypt.h index f14a628b4..622f4bc2e 100644 --- a/contrib/unzip/crypt.h +++ b/contrib/unzip/crypt.h @@ -1,132 +1,132 @@ -/* crypt.h -- base code for crypt/uncrypt ZIPfile - - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - This code is a modified version of crypting code in Infozip distribution - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - - If you don't need crypting in your application, just define symbols - NOCRYPT and NOUNCRYPT. - - This code support the "Traditional PKWARE Encryption". - - The new AES encryption added on Zip format by Winzip (see the page - http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong - Encryption is not supported. -*/ - -#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) - -/*********************************************************************** - * Return the next byte in the pseudo-random sequence - */ -static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) -{ - unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an - * unpredictable manner on 16-bit systems; not a problem - * with any known compiler so far, though */ - - temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; - return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); -} - -/*********************************************************************** - * Update the encryption keys with the next byte of plain text - */ -static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) -{ - (*(pkeys+0)) = CRC32((*(pkeys+0)), c); - (*(pkeys+1)) += (*(pkeys+0)) & 0xff; - (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; - { - register int keyshift = (int)((*(pkeys+1)) >> 24); - (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); - } - return c; -} - - -/*********************************************************************** - * Initialize the encryption keys and the random header according to - * the given password. - */ -static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) -{ - *(pkeys+0) = 305419896L; - *(pkeys+1) = 591751049L; - *(pkeys+2) = 878082192L; - while (*passwd != '\0') { - update_keys(pkeys,pcrc_32_tab,(int)*passwd); - passwd++; - } -} - -#define zdecode(pkeys,pcrc_32_tab,c) \ - (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) - -#define zencode(pkeys,pcrc_32_tab,c,t) \ - (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) - -#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED - -#define RAND_HEAD_LEN 12 - /* "last resort" source for second part of crypt seed pattern */ -# ifndef ZCR_SEED2 -# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ -# endif - -static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) - const char *passwd; /* password string */ - unsigned char *buf; /* where to write header */ - int bufSize; - unsigned long* pkeys; - const unsigned long* pcrc_32_tab; - unsigned long crcForCrypting; -{ - int n; /* index in random header */ - int t; /* temporary */ - int c; /* random byte */ - unsigned char header[RAND_HEAD_LEN-2]; /* random header */ - static unsigned calls = 0; /* ensure different random header each time */ - - if (bufSize> 7) & 0xff; - header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); - } - /* Encrypt random header (last two bytes is high word of crc) */ - init_keys(passwd, pkeys, pcrc_32_tab); - for (n = 0; n < RAND_HEAD_LEN-2; n++) - { - buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); - } - buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); - buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); - return n; -} - -#endif +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) + const char *passwd; /* password string */ + unsigned char *buf; /* where to write header */ + int bufSize; + unsigned long* pkeys; + const unsigned long* pcrc_32_tab; + unsigned long crcForCrypting; +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/contrib/unzip/ioapi.c b/contrib/unzip/ioapi.c index 44a9e11a3..b7200df75 100644 --- a/contrib/unzip/ioapi.c +++ b/contrib/unzip/ioapi.c @@ -1,181 +1,181 @@ -/* ioapi.c -- IO base function header for compress/uncompress .zip - files using zlib + zip or unzip API - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant -*/ - -#include -#include -#include - -# ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -# else -# include "../zlib/zlib.h" -# endif -#include "ioapi.h" - - - -/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ - -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -voidpf ZCALLBACK fopen_file_func ( - voidpf opaque, - const char* filename, - int mode); - -uLong ZCALLBACK fread_file_func ( - voidpf opaque, - voidpf stream, - void* buf, - uLong size); - -uLong ZCALLBACK fwrite_file_func ( - voidpf opaque, - voidpf stream, - const void* buf, - uLong size); - -long ZCALLBACK ftell_file_func ( - voidpf opaque, - voidpf stream); - -long ZCALLBACK fseek_file_func ( - voidpf opaque, - voidpf stream, - uLong offset, - int origin); - -int ZCALLBACK fclose_file_func ( - voidpf opaque, - voidpf stream); - -int ZCALLBACK ferror_file_func ( - voidpf opaque, - voidpf stream); - - -voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) - voidpf opaque; - const char* filename; - int mode; -{ - FILE* file = NULL; - const char* mode_fopen = NULL; - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - mode_fopen = "rb"; - else - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - mode_fopen = "r+b"; - else - if (mode & ZLIB_FILEFUNC_MODE_CREATE) - mode_fopen = "wb"; - - if ((filename!=NULL) && (mode_fopen != NULL)) - file = fopen(filename, mode_fopen); - return file; -} - - -uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) - voidpf opaque; - voidpf stream; - void* buf; - uLong size; -{ - uLong ret; - ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - - -uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) - voidpf opaque; - voidpf stream; - const void* buf; - uLong size; -{ - uLong ret; - ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - -long ZCALLBACK ftell_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - long ret; - ret = ftell((FILE *)stream); - return ret; -} - -long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) - voidpf opaque; - voidpf stream; - uLong offset; - int origin; -{ - int fseek_origin=0; - long ret; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - fseek_origin = SEEK_CUR; - break; - case ZLIB_FILEFUNC_SEEK_END : - fseek_origin = SEEK_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - fseek_origin = SEEK_SET; - break; - default: return -1; - } - ret = 0; - fseek((FILE *)stream, offset, fseek_origin); - return ret; -} - -int ZCALLBACK fclose_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - int ret; - ret = fclose((FILE *)stream); - return ret; -} - -int ZCALLBACK ferror_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - int ret; - ret = ferror((FILE *)stream); - return ret; -} - -void fill_fopen_filefunc (pzlib_filefunc_def) - zlib_filefunc_def* pzlib_filefunc_def; -{ - pzlib_filefunc_def->zopen_file = fopen_file_func; - pzlib_filefunc_def->zread_file = fread_file_func; - pzlib_filefunc_def->zwrite_file = fwrite_file_func; - pzlib_filefunc_def->ztell_file = ftell_file_func; - pzlib_filefunc_def->zseek_file = fseek_file_func; - pzlib_filefunc_def->zclose_file = fclose_file_func; - pzlib_filefunc_def->zerror_file = ferror_file_func; - pzlib_filefunc_def->opaque = NULL; -} +/* ioapi.c -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#include +#include +#include + +# ifdef ASSIMP_BUILD_NO_OWN_ZLIB +# include +# else +# include "../zlib/zlib.h" +# endif +#include "ioapi.h" + + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +voidpf ZCALLBACK fopen_file_func ( + voidpf opaque, + const char* filename, + int mode); + +uLong ZCALLBACK fread_file_func ( + voidpf opaque, + voidpf stream, + void* buf, + uLong size); + +uLong ZCALLBACK fwrite_file_func ( + voidpf opaque, + voidpf stream, + const void* buf, + uLong size); + +long ZCALLBACK ftell_file_func ( + voidpf opaque, + voidpf stream); + +long ZCALLBACK fseek_file_func ( + voidpf opaque, + voidpf stream, + uLong offset, + int origin); + +int ZCALLBACK fclose_file_func ( + voidpf opaque, + voidpf stream); + +int ZCALLBACK ferror_file_func ( + voidpf opaque, + voidpf stream); + + +voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) + voidpf opaque; + const char* filename; + int mode; +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + + +uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + void* buf; + uLong size; +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + + +uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + const void* buf; + uLong size; +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +long ZCALLBACK ftell_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + +long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) + voidpf opaque; + voidpf stream; + uLong offset; + int origin; +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + fseek((FILE *)stream, offset, fseek_origin); + return ret; +} + +int ZCALLBACK fclose_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +int ZCALLBACK ferror_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/contrib/unzip/ioapi.h b/contrib/unzip/ioapi.h index b12b6c75a..06fdd15e9 100644 --- a/contrib/unzip/ioapi.h +++ b/contrib/unzip/ioapi.h @@ -1,75 +1,75 @@ -/* ioapi.h -- IO base function header for compress/uncompress .zip - files using zlib + zip or unzip API - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant -*/ - -#ifndef _ZLIBIOAPI_H -#define _ZLIBIOAPI_H - - -#define ZLIB_FILEFUNC_SEEK_CUR (1) -#define ZLIB_FILEFUNC_SEEK_END (2) -#define ZLIB_FILEFUNC_SEEK_SET (0) - -#define ZLIB_FILEFUNC_MODE_READ (1) -#define ZLIB_FILEFUNC_MODE_WRITE (2) -#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) - -#define ZLIB_FILEFUNC_MODE_EXISTING (4) -#define ZLIB_FILEFUNC_MODE_CREATE (8) - - -#ifndef ZCALLBACK - -#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) -#define ZCALLBACK CALLBACK -#else -#define ZCALLBACK -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode); -typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size); -typedef uLong (ZCALLBACK *write_file_func)(voidpf opaque, voidpf stream, const void* buf, uLong size); -typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream); -typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin); -typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream); -typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream); - -typedef struct zlib_filefunc_def_s -{ - open_file_func zopen_file; - read_file_func zread_file; - write_file_func zwrite_file; - tell_file_func ztell_file; - seek_file_func zseek_file; - close_file_func zclose_file; - testerror_file_func zerror_file; - voidpf opaque; -} zlib_filefunc_def; - - - -void fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def); - -#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) -#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) -#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) -#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) -#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) -#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) - - -#ifdef __cplusplus -} -#endif - -#endif - +/* ioapi.h -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#ifndef _ZLIBIOAPI_H +#define _ZLIBIOAPI_H + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + +#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) +#define ZCALLBACK CALLBACK +#else +#define ZCALLBACK +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode); +typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size); +typedef uLong (ZCALLBACK *write_file_func)(voidpf opaque, voidpf stream, const void* buf, uLong size); +typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream); +typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin); +typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream); +typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream); + +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + + + +void fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def); + +#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) +#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) +#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) +#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) +#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/contrib/unzip/unzip.c b/contrib/unzip/unzip.c index e83862a43..af00f7d6f 100644 --- a/contrib/unzip/unzip.c +++ b/contrib/unzip/unzip.c @@ -1,1604 +1,1604 @@ -/* unzip.c -- IO for uncompress .zip files using zlib - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - Read unzip.h for more info -*/ - -/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of -compatibility with older software. The following is from the original crypt.c. Code -woven in by Terry Thorsen 1/2003. -*/ -/* - Copyright (c) 1990-2000 Info-ZIP. All rights reserved. - - See the accompanying file LICENSE, version 2000-Apr-09 or later - (the contents of which are also included in zip.h) for terms of use. - If, for some reason, all these files are missing, the Info-ZIP license - also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html -*/ -/* - crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - */ - -/* - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - */ - - -#include -#include -#include -#include "./unzip.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - - -#ifndef CASESENSITIVITYDEFAULT_NO -# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) -# define CASESENSITIVITYDEFAULT_NO -# endif -#endif - - -#ifndef UNZ_BUFSIZE -#define UNZ_BUFSIZE (16384) -#endif - -#ifndef UNZ_MAXFILENAMEINZIP -#define UNZ_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) - - - - -const char unz_copyright[] = - " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; - -/* unz_file_info_interntal contain internal info about a file in zipfile*/ -typedef struct unz_file_info_internal_s -{ - uLong offset_curfile;/* relative offset of local header 4 bytes */ -} unz_file_info_internal; - - -/* file_in_zip_read_info_s contain internal information about a file in zipfile, - when reading and decompress it */ -typedef struct -{ - char *read_buffer; /* internal buffer for compressed data */ - z_stream stream; /* zLib stream structure for inflate */ - - uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ - uLong stream_initialised; /* flag set if stream structure is initialised*/ - - uLong offset_local_extrafield;/* offset of the local extra field */ - uInt size_local_extrafield;/* size of the local extra field */ - uLong pos_local_extrafield; /* position in the local extra field in read*/ - - uLong crc32; /* crc32 of all data uncompressed */ - uLong crc32_wait; /* crc32 we must obtain after decompress all */ - uLong rest_read_compressed; /* number of byte to be decompressed */ - uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ - zlib_filefunc_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - uLong compression_method; /* compression method (0==store) */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - int raw; -} file_in_zip_read_info_s; - - -/* unz_s contain internal information about the zipfile -*/ -typedef struct -{ - zlib_filefunc_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - unz_global_info gi; /* public global information */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - uLong num_file; /* number of the current file in the zipfile*/ - uLong pos_in_central_dir; /* pos of the current file in the central dir*/ - uLong current_file_ok; /* flag about the usability of the current file*/ - uLong central_pos; /* position of the beginning of the central dir*/ - - uLong size_central_dir; /* size of the central directory */ - uLong offset_central_dir; /* offset of start of central directory with - respect to the starting disk number */ - - unz_file_info cur_file_info; /* public info about the current file in zip*/ - unz_file_info_internal cur_file_info_internal; /* private info about it*/ - file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current - file if we are decompressing it */ - int encrypted; -# ifndef NOUNCRYPT - unsigned long keys[3]; /* keys defining the pseudo-random sequence */ - const unsigned long* pcrc_32_tab; -# endif -} unz_s; - - -#ifndef NOUNCRYPT -#include "crypt.h" -#endif - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ - - -local int unzlocal_getByte ( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - int *pi); - -local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - int *pi; -{ - unsigned char c; - int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) - { - *pi = (int)c; - return UNZ_OK; - } - else - { - if (ZERROR(*pzlib_filefunc_def,filestream)) - return UNZ_ERRNO; - else - return UNZ_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unzlocal_getShort ( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX); - -local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong *pX; -{ - uLong x ; - int i; - int err; - - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unzlocal_getLong ( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX); - -local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong *pX; -{ - uLong x ; - int i; - int err; - - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - - -/* My own strcmpi / strcasecmp */ -local int strcmpcasenosensitive_internal (fileName1,fileName2) - const char* fileName1; - const char* fileName2; -{ - for (;;) - { - char c1=*(fileName1++); - char c2=*(fileName2++); - if ((c1>='a') && (c1<='z')) - c1 -= 0x20; - if ((c2>='a') && (c2<='z')) - c2 -= 0x20; - if (c1=='\0') - return ((c2=='\0') ? 0 : -1); - if (c2=='\0') - return 1; - if (c1c2) - return 1; - } -} - - -#ifdef CASESENSITIVITYDEFAULT_NO -#define CASESENSITIVITYDEFAULTVALUE 2 -#else -#define CASESENSITIVITYDEFAULTVALUE 1 -#endif - -#ifndef STRCMPCASENOSENTIVEFUNCTION -#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal -#endif - -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) - -*/ -extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) - const char* fileName1; - const char* fileName2; - int iCaseSensitivity; -{ - if (iCaseSensitivity==0) - iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; - - if (iCaseSensitivity==1) - return strcmp(fileName1,fileName2); - - return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); -} - -#ifndef BUFREADCOMMENT -#define BUFREADCOMMENT (0x400) -#endif - -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local uLong unzlocal_SearchCentralDir ( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream); - -local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; -{ - unsigned char* buf; - uLong uSizeFile; - uLong uBackRead; - uLong uMaxBack=0xffff; /* maximum size of global comment */ - uLong uPosFound=0; - - if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); - if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} - -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer - "zlib/zlib114.zip". - If the zipfile cannot be opened (file doesn't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ -extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) - const char *path; - zlib_filefunc_def* pzlib_filefunc_def; -{ - unz_s us; - unz_s *s; - uLong central_pos,uL; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - uLong number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - - int err=UNZ_OK; - - if (unz_copyright[0]!=' ') - return NULL; - - if (pzlib_filefunc_def==NULL) - fill_fopen_filefunc(&us.z_filefunc); - else - us.z_filefunc = *pzlib_filefunc_def; - - us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, - path, - ZLIB_FILEFUNC_MODE_READ | - ZLIB_FILEFUNC_MODE_EXISTING); - if (us.filestream==NULL) - return NULL; - - central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); - if (central_pos==0) - err=UNZ_ERRNO; - - if (ZSEEK(us.z_filefunc, us.filestream, - central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir on this disk */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* zipfile comment length */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((central_pospfile_in_zip_read!=NULL) - unzCloseCurrentFile(file); - - ZCLOSE(s->z_filefunc, s->filestream); - TRYFREE(s); - return UNZ_OK; -} - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) - unzFile file; - unz_global_info *pglobal_info; -{ - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - *pglobal_info=s->gi; - return UNZ_OK; -} - - -/* - Translate date/time from Dos format to tm_unz (readable more easilty) -*/ -local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) - uLong ulDosDate; - tm_unz* ptm; -{ - uLong uDate; - uDate = (uLong)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; - - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; -} - -/* - Get Info about the current file in the zipfile, with internal only info -*/ -local int unzlocal_GetCurrentFileInfoInternal (unzFile file, - unz_file_info *pfile_info, - unz_file_info_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize); - -local int unzlocal_GetCurrentFileInfoInternal (file, - pfile_info, - pfile_info_internal, - szFileName, fileNameBufferSize, - extraField, extraFieldBufferSize, - szComment, commentBufferSize) - unzFile file; - unz_file_info *pfile_info; - unz_file_info_internal *pfile_info_internal; - char *szFileName; - uLong fileNameBufferSize; - void *extraField; - uLong extraFieldBufferSize; - char *szComment; - uLong commentBufferSize; -{ - unz_s* s; - unz_file_info file_info; - unz_file_info_internal file_info_internal; - int err=UNZ_OK; - uLong uMagic; - long lSeek=0; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (ZSEEK(s->z_filefunc, s->filestream, - s->pos_in_central_dir+s->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - - /* we check the magic */ - if (err==UNZ_OK) - { - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; - - unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - - lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_filename0) && (fileNameBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } - - - if ((err==UNZ_OK) && (extraField!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek += file_info.size_file_extra - uSizeRead; - } - else - lSeek+=file_info.size_file_extra; - - - if ((err==UNZ_OK) && (szComment!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek+=file_info.size_file_comment - uSizeRead; - } - else - lSeek+=file_info.size_file_comment; - - if ((err==UNZ_OK) && (pfile_info!=NULL)) - *pfile_info=file_info; - - if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) - *pfile_info_internal=file_info_internal; - - return err; -} - - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. -*/ -extern int ZEXPORT unzGetCurrentFileInfo (file, - pfile_info, - szFileName, fileNameBufferSize, - extraField, extraFieldBufferSize, - szComment, commentBufferSize) - unzFile file; - unz_file_info *pfile_info; - char *szFileName; - uLong fileNameBufferSize; - void *extraField; - uLong extraFieldBufferSize; - char *szComment; - uLong commentBufferSize; -{ - return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); -} - -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ -extern int ZEXPORT unzGoToFirstFile (file) - unzFile file; -{ - int err=UNZ_OK; - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - s->pos_in_central_dir=s->offset_central_dir; - s->num_file=0; - err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ -extern int ZEXPORT unzGoToNextFile (file) - unzFile file; -{ - unz_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ - if (s->num_file+1==s->gi.number_entry) - return UNZ_END_OF_LIST_OF_FILE; - - s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + - s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; - s->num_file++; - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzipStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ -extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) - unzFile file; - const char *szFileName; - int iCaseSensitivity; -{ - unz_s* s; - int err; - - /* We remember the 'current' position in the file so that we can jump - * back there if we fail. - */ - unz_file_info cur_file_infoSaved; - unz_file_info_internal cur_file_info_internalSaved; - uLong num_fileSaved; - uLong pos_in_central_dirSaved; - - - if (file==NULL) - return UNZ_PARAMERROR; - - if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) - return UNZ_PARAMERROR; - - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - /* Save the current state */ - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; - cur_file_infoSaved = s->cur_file_info; - cur_file_info_internalSaved = s->cur_file_info_internal; - - err = unzGoToFirstFile(file); - - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - err = unzGetCurrentFileInfo(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (err == UNZ_OK) - { - if (unzStringFileNameCompare(szCurrentFileName, - szFileName,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } - } - - /* We failed, so restore the state of the 'current file' to where we - * were. - */ - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - s->cur_file_info = cur_file_infoSaved; - s->cur_file_info_internal = cur_file_info_internalSaved; - return err; -} - - -/* -/////////////////////////////////////////// -// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) -// I need random access -// -// Further optimization could be realized by adding an ability -// to cache the directory in memory. The goal being a single -// comprehensive file read to put the file I need in a memory. -*/ - -/* -typedef struct unz_file_pos_s -{ - uLong pos_in_zip_directory; // offset in file - uLong num_of_file; // # of file -} unz_file_pos; -*/ - -extern int ZEXPORT unzGetFilePos(file, file_pos) - unzFile file; - unz_file_pos* file_pos; -{ - unz_s* s; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - file_pos->pos_in_zip_directory = s->pos_in_central_dir; - file_pos->num_of_file = s->num_file; - - return UNZ_OK; -} - -extern int ZEXPORT unzGoToFilePos(file, file_pos) - unzFile file; - unz_file_pos* file_pos; -{ - unz_s* s; - int err; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - /* jump to the right spot */ - s->pos_in_central_dir = file_pos->pos_in_zip_directory; - s->num_file = file_pos->num_of_file; - - /* set the current file */ - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - /* return results */ - s->current_file_ok = (err == UNZ_OK); - return err; -} - -/* -// Unzip Helper Functions - should be here? -/////////////////////////////////////////// -*/ - -/* - Read the local header of the current zipfile - Check the coherency of the local header and info in the end of central - directory about this file - store in *piSizeVar the size of extra info in local header - (filename and size of extra field data) -*/ -local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, - poffset_local_extrafield, - psize_local_extrafield) - unz_s* s; - uInt* piSizeVar; - uLong *poffset_local_extrafield; - uInt *psize_local_extrafield; -{ - uLong uMagic,uData,uFlags; - uLong size_filename; - uLong size_extra_field; - int err=UNZ_OK; - - *piSizeVar = 0; - *poffset_local_extrafield = 0; - *psize_local_extrafield = 0; - - if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + - s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - - if (err==UNZ_OK) - { - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; -/* - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) - err=UNZ_BADZIPFILE; -*/ - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) - err=UNZ_BADZIPFILE; - - if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) - err=UNZ_BADZIPFILE; - - *piSizeVar += (uInt)size_filename; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) - err=UNZ_ERRNO; - *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + - SIZEZIPLOCALHEADER + size_filename; - *psize_local_extrafield = (uInt)size_extra_field; - - *piSizeVar += (uInt)size_extra_field; - - return err; -} - -/* - Open for reading data the current file in the zipfile. - If there is no error and the file is opened, the return value is UNZ_OK. -*/ -extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) - unzFile file; - int* method; - int* level; - int raw; - const char* password; -{ - int err=UNZ_OK; - uInt iSizeVar; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uLong offset_local_extrafield; /* offset of the local extra field */ - uInt size_local_extrafield; /* size of the local extra field */ -# ifndef NOUNCRYPT - char source[12]; -# else - if (password != NULL) - return UNZ_PARAMERROR; -# endif - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_PARAMERROR; - - if (s->pfile_in_zip_read != NULL) - unzCloseCurrentFile(file); - - if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, - &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) - return UNZ_BADZIPFILE; - - pfile_in_zip_read_info = (file_in_zip_read_info_s*) - ALLOC(sizeof(file_in_zip_read_info_s)); - if (pfile_in_zip_read_info==NULL) - return UNZ_INTERNALERROR; - - pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); - pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; - pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; - pfile_in_zip_read_info->pos_local_extrafield=0; - pfile_in_zip_read_info->raw=raw; - - if (pfile_in_zip_read_info->read_buffer==NULL) - { - TRYFREE(pfile_in_zip_read_info); - return UNZ_INTERNALERROR; - } - - pfile_in_zip_read_info->stream_initialised=0; - - if (method!=NULL) - *method = (int)s->cur_file_info.compression_method; - - if (level!=NULL) - { - *level = 6; - switch (s->cur_file_info.flag & 0x06) - { - case 6 : *level = 1; break; - case 4 : *level = 2; break; - case 2 : *level = 9; break; - } - } - - if ((s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; - pfile_in_zip_read_info->crc32=0; - pfile_in_zip_read_info->compression_method = - s->cur_file_info.compression_method; - pfile_in_zip_read_info->filestream=s->filestream; - pfile_in_zip_read_info->z_filefunc=s->z_filefunc; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; - - pfile_in_zip_read_info->stream.total_out = 0; - - if ((s->cur_file_info.compression_method==Z_DEFLATED) && - (!raw)) - { - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - pfile_in_zip_read_info->stream.next_in = (voidpf)0; - pfile_in_zip_read_info->stream.avail_in = 0; - - err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=1; - else - { - TRYFREE(pfile_in_zip_read_info); - return err; - } - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - * In unzip, i don't wait absolutely Z_STREAM_END because I known the - * size of both compressed and uncompressed data - */ - } - pfile_in_zip_read_info->rest_read_compressed = - s->cur_file_info.compressed_size ; - pfile_in_zip_read_info->rest_read_uncompressed = - s->cur_file_info.uncompressed_size ; - - - pfile_in_zip_read_info->pos_in_zipfile = - s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + - iSizeVar; - - pfile_in_zip_read_info->stream.avail_in = (uInt)0; - - s->pfile_in_zip_read = pfile_in_zip_read_info; - -# ifndef NOUNCRYPT - if (password != NULL) - { - int i; - s->pcrc_32_tab = get_crc_table(); - init_keys(password,s->keys,s->pcrc_32_tab); - if (ZSEEK(s->z_filefunc, s->filestream, - s->pfile_in_zip_read->pos_in_zipfile + - s->pfile_in_zip_read->byte_before_the_zipfile, - SEEK_SET)!=0) - return UNZ_INTERNALERROR; - if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) - return UNZ_INTERNALERROR; - - for (i = 0; i<12; i++) - zdecode(s->keys,s->pcrc_32_tab,source[i]); - - s->pfile_in_zip_read->pos_in_zipfile+=12; - s->encrypted=1; - } -# endif - - - return UNZ_OK; -} - -extern int ZEXPORT unzOpenCurrentFile (file) - unzFile file; -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); -} - -extern int ZEXPORT unzOpenCurrentFilePassword (file, password) - unzFile file; - const char* password; -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, password); -} - -extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw) - unzFile file; - int* method; - int* level; - int raw; -{ - return unzOpenCurrentFile3(file, method, level, raw, NULL); -} - -/* - Read bytes from the current file. - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ -extern int ZEXPORT unzReadCurrentFile (file, buf, len) - unzFile file; - voidp buf; - unsigned len; -{ - int err=UNZ_OK; - uInt iRead = 0; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if (pfile_in_zip_read_info->read_buffer == NULL) - return UNZ_END_OF_LIST_OF_FILE; - if (len==0) - return 0; - - pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; - - pfile_in_zip_read_info->stream.avail_out = (uInt)len; - - if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && - (!(pfile_in_zip_read_info->raw))) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - - if ((len>pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in) && - (pfile_in_zip_read_info->raw)) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in; - - while (pfile_in_zip_read_info->stream.avail_out>0) - { - if ((pfile_in_zip_read_info->stream.avail_in==0) && - (pfile_in_zip_read_info->rest_read_compressed>0)) - { - uInt uReadThis = UNZ_BUFSIZE; - if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; - if (uReadThis == 0) - return UNZ_EOF; - if (ZSEEK(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - if (ZREAD(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->read_buffer, - uReadThis)!=uReadThis) - return UNZ_ERRNO; - - -# ifndef NOUNCRYPT - if(s->encrypted) - { - uInt i; - for(i=0;iread_buffer[i] = - zdecode(s->keys,s->pcrc_32_tab, - pfile_in_zip_read_info->read_buffer[i]); - } -# endif - - - pfile_in_zip_read_info->pos_in_zipfile += uReadThis; - - pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - - pfile_in_zip_read_info->stream.next_in = - (Bytef*)pfile_in_zip_read_info->read_buffer; - pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; - } - - if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) - { - uInt uDoCopy,i ; - - if ((pfile_in_zip_read_info->stream.avail_in == 0) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - return (iRead==0) ? UNZ_EOF : iRead; - - if (pfile_in_zip_read_info->stream.avail_out < - pfile_in_zip_read_info->stream.avail_in) - uDoCopy = pfile_in_zip_read_info->stream.avail_out ; - else - uDoCopy = pfile_in_zip_read_info->stream.avail_in ; - - for (i=0;istream.next_out+i) = - *(pfile_in_zip_read_info->stream.next_in+i); - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, - pfile_in_zip_read_info->stream.next_out, - uDoCopy); - pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; - pfile_in_zip_read_info->stream.avail_in -= uDoCopy; - pfile_in_zip_read_info->stream.avail_out -= uDoCopy; - pfile_in_zip_read_info->stream.next_out += uDoCopy; - pfile_in_zip_read_info->stream.next_in += uDoCopy; - pfile_in_zip_read_info->stream.total_out += uDoCopy; - iRead += uDoCopy; - } - else - { - uLong uTotalOutBefore,uTotalOutAfter; - const Bytef *bufBefore; - uLong uOutThis; - int flush=Z_SYNC_FLUSH; - - uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; - bufBefore = pfile_in_zip_read_info->stream.next_out; - - /* - if ((pfile_in_zip_read_info->rest_read_uncompressed == - pfile_in_zip_read_info->stream.avail_out) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - flush = Z_FINISH; - */ - err=inflate(&pfile_in_zip_read_info->stream,flush); - - if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) - err = Z_DATA_ERROR; - - uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->crc32 = - crc32(pfile_in_zip_read_info->crc32,bufBefore, - (uInt)(uOutThis)); - - pfile_in_zip_read_info->rest_read_uncompressed -= - uOutThis; - - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - if (err==Z_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=Z_OK) - break; - } - } - - if (err==Z_OK) - return iRead; - return err; -} - - -/* - Give the current position in uncompressed data -*/ -extern z_off_t ZEXPORT unztell (file) - unzFile file; -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - return (z_off_t)pfile_in_zip_read_info->stream.total_out; -} - - -/* - return 1 if the end of file was reached, 0 elsewhere -*/ -extern int ZEXPORT unzeof (file) - unzFile file; -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - return 1; - else - return 0; -} - - - -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field that can be read - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ -extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) - unzFile file; - voidp buf; - unsigned len; -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uInt read_now; - uLong size_to_read; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - size_to_read = (pfile_in_zip_read_info->size_local_extrafield - - pfile_in_zip_read_info->pos_local_extrafield); - - if (buf==NULL) - return (int)size_to_read; - - if (len>size_to_read) - read_now = (uInt)size_to_read; - else - read_now = (uInt)len ; - - if (read_now==0) - return 0; - - if (ZSEEK(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->offset_local_extrafield + - pfile_in_zip_read_info->pos_local_extrafield, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (ZREAD(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - buf,read_now)!=read_now) - return UNZ_ERRNO; - - return (int)read_now; -} - -/* - Close the file in zip opened with unzipOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ -extern int ZEXPORT unzCloseCurrentFile (file) - unzFile file; -{ - int err=UNZ_OK; - - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && - (!pfile_in_zip_read_info->raw)) - { - if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) - err=UNZ_CRCERROR; - } - - - TRYFREE(pfile_in_zip_read_info->read_buffer); - pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised) - inflateEnd(&pfile_in_zip_read_info->stream); - - pfile_in_zip_read_info->stream_initialised = 0; - TRYFREE(pfile_in_zip_read_info); - - s->pfile_in_zip_read=NULL; - - return err; -} - - -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ -extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) - unzFile file; - char *szComment; - uLong uSizeBuf; -{ - unz_s* s; - uLong uReadThis ; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - uReadThis = uSizeBuf; - if (uReadThis>s->gi.size_comment) - uReadThis = s->gi.size_comment; - - if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (uReadThis>0) - { - *szComment='\0'; - if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) - return UNZ_ERRNO; - } - - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) - *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; -} - -/* Additions by RX '2004 */ -extern uLong ZEXPORT unzGetOffset (file) - unzFile file; -{ - unz_s* s; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return 0; - if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) - if (s->num_file==s->gi.number_entry) - return 0; - return s->pos_in_central_dir; -} - -extern int ZEXPORT unzSetOffset (file, pos) - unzFile file; - uLong pos; -{ - unz_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - s->pos_in_central_dir = pos; - s->num_file = s->gi.number_entry; /* hack */ - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + Read unzip.h for more info +*/ + +/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of +compatibility with older software. The following is from the original crypt.c. Code +woven in by Terry Thorsen 1/2003. +*/ +/* + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html +*/ +/* + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + */ + +/* + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + */ + + +#include +#include +#include +#include "./unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; +# endif +} unz_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte ( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi); + +local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + int *pi; +{ + unsigned char c; + int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort ( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX); + +local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong ( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX); + +local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (fileName1,fileName2) + const char* fileName1; + const char* fileName2; +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) + const char* fileName1; + const char* fileName2; + int iCaseSensitivity; +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir ( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream); + +local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) + const char *path; + zlib_filefunc_def* pzlib_filefunc_def; +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + if (pzlib_filefunc_def==NULL) + fill_fopen_filefunc(&us.z_filefunc); + else + us.z_filefunc = *pzlib_filefunc_def; + + us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + if (ZSEEK(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) + unzFile file; + unz_global_info *pglobal_info; +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) + uLong ulDosDate; + tm_unz* ptm; +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal (unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize); + +local int unzlocal_GetCurrentFileInfoInternal (file, + pfile_info, + pfile_info_internal, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + unz_file_info_internal *pfile_info_internal; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (ZSEEK(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + { + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo (file, + pfile_info, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (file) + unzFile file; +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (file) + unzFile file; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) + unzFile file; + const char *szFileName; + int iCaseSensitivity; +{ + unz_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info cur_file_infoSaved; + unz_file_info_internal cur_file_info_internalSaved; + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; // offset in file + uLong num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGoToFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, + poffset_local_extrafield, + psize_local_extrafield) + unz_s* s; + uInt* piSizeVar; + uLong *poffset_local_extrafield; + uInt *psize_local_extrafield; +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + { + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) + unzFile file; + int* method; + int* level; + int raw; + const char* password; +{ + int err=UNZ_OK; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_DEFLATED) && + (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (file) + unzFile file; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (file, password) + unzFile file; + const char* password; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw) + unzFile file; + int* method; + int* level; + int raw; +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (file, buf, len) + unzFile file; + voidp buf; + unsigned len; +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->read_buffer == NULL) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;iread_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) + unzFile file; + voidp buf; + unsigned len; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) + unzFile file; + char *szComment; + uLong uSizeBuf; +{ + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern uLong ZEXPORT unzGetOffset (file) + unzFile file; +{ + unz_s* s; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern int ZEXPORT unzSetOffset (file, pos) + unzFile file; + uLong pos; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} diff --git a/contrib/unzip/unzip.h b/contrib/unzip/unzip.h index 16fd9fd70..e3b7f24ee 100644 --- a/contrib/unzip/unzip.h +++ b/contrib/unzip/unzip.h @@ -1,358 +1,358 @@ -/* unzip.h -- IO for uncompress .zip files using zlib - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g - WinZip, InfoZip tools and compatible. - - Multi volume ZipFile (span) are not supported. - Encryption compatible with pkzip 2.04g only supported - Old compressions used by old PKZip 1.x are not supported - - - I WAIT FEEDBACK at mail info@winimage.com - Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution - - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - -*/ - -/* for more info about .ZIP format, see - http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip - http://www.info-zip.org/pub/infozip/doc/ - PkWare has also a specification at : - ftp://ftp.pkware.com/probdesc.zip -*/ - -#ifndef _unz_H -#define _unz_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -# ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -# else -# include "../zlib/zlib.h" -# endif -#endif - -#ifndef _ZLIBIOAPI_H -#include "ioapi.h" -#endif - -#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagunzFile__ { int unused; } unzFile__; -typedef unzFile__ *unzFile; -#else -typedef voidp unzFile; -#endif - - -#define UNZ_OK (0) -#define UNZ_END_OF_LIST_OF_FILE (-100) -#define UNZ_ERRNO (Z_ERRNO) -#define UNZ_EOF (0) -#define UNZ_PARAMERROR (-102) -#define UNZ_BADZIPFILE (-103) -#define UNZ_INTERNALERROR (-104) -#define UNZ_CRCERROR (-105) - -/* tm_unz contain date/time info */ -typedef struct tm_unz_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_unz; - -/* unz_global_info structure contain global data about the ZIPfile - These data comes from the end of central dir */ -typedef struct unz_global_info_s -{ - uLong number_entry; /* total number of entries in - the central dir on this disk */ - uLong size_comment; /* size of the global comment of the zipfile */ -} unz_global_info; - - -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_info_s -{ - uLong version; /* version made by 2 bytes */ - uLong version_needed; /* version needed to extract 2 bytes */ - uLong flag; /* general purpose bit flag 2 bytes */ - uLong compression_method; /* compression method 2 bytes */ - uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ - uLong crc; /* crc-32 4 bytes */ - uLong compressed_size; /* compressed size 4 bytes */ - uLong uncompressed_size; /* uncompressed size 4 bytes */ - uLong size_filename; /* filename length 2 bytes */ - uLong size_file_extra; /* extra field length 2 bytes */ - uLong size_file_comment; /* file comment length 2 bytes */ - - uLong disk_num_start; /* disk number start 2 bytes */ - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ - - tm_unz tmu_date; -} unz_file_info; - -extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, - const char* fileName2, - int iCaseSensitivity); -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) -*/ - - -extern unzFile ZEXPORT unzOpen (const char *path); -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer - "zlib/zlib113.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ - -extern unzFile ZEXPORT unzOpen2 (const char *path, - zlib_filefunc_def* pzlib_filefunc_def); -/* - Open a Zip file, like unzOpen, but provide a set of file low level API - for read/write the zip file (see ioapi.h) -*/ - -extern int ZEXPORT unzClose (unzFile file); -/* - Close a ZipFile opened with unzipOpen. - If there is files inside the .Zip opened with unzOpenCurrentFile (see later), - these files MUST be closed with unzipCloseCurrentFile before call unzipClose. - return UNZ_OK if there is no problem. */ - -extern int ZEXPORT unzGetGlobalInfo (unzFile file, - unz_global_info *pglobal_info); -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ - - -extern int ZEXPORT unzGetGlobalComment (unzFile file, - char *szComment, - uLong uSizeBuf); -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ - - -/***************************************************************************/ -/* Unzip package allow you browse the directory of the zipfile */ - -extern int ZEXPORT unzGoToFirstFile (unzFile file); -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ - -extern int ZEXPORT unzGoToNextFile (unzFile file); -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ - -extern int ZEXPORT unzLocateFile (unzFile file, - const char *szFileName, - int iCaseSensitivity); -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ - - -/* ****************************************** */ -/* Ryan supplied functions */ -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_pos_s -{ - uLong pos_in_zip_directory; /* offset in zip file directory */ - uLong num_of_file; /* # of file */ -} unz_file_pos; - -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos); - -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos); - -/* ****************************************** */ - -extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize); -/* - Get Info about the current file - if pfile_info!=NULL, the *pfile_info structure will contain somes info about - the current file - if szFileName!=NULL, the filemane string will be copied in szFileName - (fileNameBufferSize is the size of the buffer) - if extraField!=NULL, the extra field information will be copied in extraField - (extraFieldBufferSize is the size of the buffer). - This is the Central-header version of the extra field - if szComment!=NULL, the comment string of the file will be copied in szComment - (commentBufferSize is the size of the buffer) -*/ - -/***************************************************************************/ -/* for reading the content of the current zipfile, you can open it, read data - from it, and close it (you can close it before reading all the file) - */ - -extern int ZEXPORT unzOpenCurrentFile (unzFile file); -/* - Open for reading data the current file in the zipfile. - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, - const char* password); -/* - Open for reading data the current file in the zipfile. - password is a crypting password - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, - int* method, - int* level, - int raw); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - -extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, - int* method, - int* level, - int raw, - const char* password); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - - -extern int ZEXPORT unzCloseCurrentFile (unzFile file); -/* - Close the file in zip opened with unzOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ - -extern int ZEXPORT unzReadCurrentFile (unzFile file, - voidp buf, - unsigned len); -/* - Read bytes from the current file (opened by unzOpenCurrentFile) - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ - -extern z_off_t ZEXPORT unztell (unzFile file); -/* - Give the current position in uncompressed data -*/ - -extern int ZEXPORT unzeof (unzFile file); -/* - return 1 if the end of file was reached, 0 elsewhere -*/ - -extern int ZEXPORT unzGetLocalExtrafield (unzFile file, - voidp buf, - unsigned len); -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ - -/***************************************************************************/ - -/* Get the current file offset */ -extern uLong ZEXPORT unzGetOffset (unzFile file); - -/* Set the current file offset */ -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); - - - -#ifdef __cplusplus -} -#endif - -#endif /* _unz_H */ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +# ifdef ASSIMP_BUILD_NO_OWN_ZLIB +# include +# else +# include "../zlib/zlib.h" +# endif +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, + const char* fileName2, + int iCaseSensitivity); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen (const char *path); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern unzFile ZEXPORT unzOpen2 (const char *path, + zlib_filefunc_def* pzlib_filefunc_def); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose (unzFile file); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo (unzFile file, + unz_global_info *pglobal_info); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment (unzFile file, + char *szComment, + uLong uSizeBuf); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile (unzFile file); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile (unzFile file); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile (unzFile file, + const char *szFileName, + int iCaseSensitivity); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile (unzFile file); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, + const char* password); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, + int* method, + int* level, + int raw); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, + int* method, + int* level, + int raw, + const char* password); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile (unzFile file); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile (unzFile file, + voidp buf, + unsigned len); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell (unzFile file); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof (unzFile file); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield (unzFile file, + voidp buf, + unsigned len); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/contrib/zlib/CMakeLists.txt b/contrib/zlib/CMakeLists.txt index 5a9546038..022d3dfba 100644 --- a/contrib/zlib/CMakeLists.txt +++ b/contrib/zlib/CMakeLists.txt @@ -1,199 +1,199 @@ -cmake_minimum_required(VERSION 2.4.4) -set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) - -# CMake 3.0 changed the project command, setting policy CMP0048 reverts to the old behaviour. -# See http://www.cmake.org/cmake/help/v3.0/policy/CMP0048.html -cmake_policy(PUSH) -if(CMAKE_MAJOR_VERSION GREATER 2) - cmake_policy(SET CMP0048 OLD) -endif() -project(zlib C) -cmake_policy(POP) - -set(VERSION "1.2.8") - -option(ASM686 "Enable building i686 assembly implementation for zlib") -option(AMD64 "Enable building amd64 assembly implementation for zlib") - -#set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") -#set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") -#set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") -#set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") -#set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") - -include(CheckTypeSize) -include(CheckFunctionExists) -include(CheckIncludeFile) -include(CheckCSourceCompiles) -enable_testing() - -check_include_file(sys/types.h HAVE_SYS_TYPES_H) -check_include_file(stdint.h HAVE_STDINT_H) -check_include_file(stddef.h HAVE_STDDEF_H) - -# -# Check to see if we have large file support -# -set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) -# We add these other definitions here because CheckTypeSize.cmake -# in CMake 2.4.x does not automatically do so and we want -# compatibility with CMake 2.4.x. -if(HAVE_SYS_TYPES_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H) -endif() -if(HAVE_STDINT_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H) -endif() -if(HAVE_STDDEF_H) - list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H) -endif() -check_type_size(off64_t OFF64_T) -if(HAVE_OFF64_T) - add_definitions(-D_LARGEFILE64_SOURCE=1) -endif() -set(CMAKE_REQUIRED_DEFINITIONS) # clear variable - -# -# Check for fseeko -# -check_function_exists(fseeko HAVE_FSEEKO) -if(NOT HAVE_FSEEKO) - add_definitions(-DNO_FSEEKO) -endif() - -# -# Check for unistd.h -# -check_include_file(unistd.h Z_HAVE_UNISTD_H) - -if(MSVC) - set(CMAKE_DEBUG_POSTFIX "d") - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) - add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -endif() - -if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) - # If we're doing an out of source build and the user has a zconf.h - # in their source tree... - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) - message(STATUS "Renaming") - message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") - message(STATUS "to 'zconf.h.included' because this file is included with zlib") - message(STATUS "but CMake generates it automatically in the build directory.") - file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) - endif() -endif() - -set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein - ${ZLIB_PC} @ONLY) -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein - ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) - -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) - - -#============================================================================ -# zlib -#============================================================================ - -set(ZLIB_PUBLIC_HDRS - ${CMAKE_CURRENT_BINARY_DIR}/zconf.h - zlib.h -) -set(ZLIB_PRIVATE_HDRS - crc32.h - deflate.h - gzguts.h - inffast.h - inffixed.h - inflate.h - inftrees.h - trees.h - zutil.h -) -set(ZLIB_SRCS - adler32.c - compress.c - crc32.c - deflate.c - gzclose.c - gzlib.c - gzread.c - gzwrite.c - inflate.c - infback.c - inftrees.c - inffast.c - trees.c - uncompr.c - zutil.c -) - -if(NOT MINGW) - set(ZLIB_DLL_SRCS - win32/zlib1.rc # If present will override custom build rule below. - ) -endif() - -if(CMAKE_COMPILER_IS_GNUCC) - if(ASM686) - set(ZLIB_ASMS contrib/asm686/match.S) - elseif (AMD64) - set(ZLIB_ASMS contrib/amd64/amd64-match.S) - endif () - - if(ZLIB_ASMS) - add_definitions(-DASMV) - set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE) - endif() -endif() - -if(MSVC) - if(ASM686) - ENABLE_LANGUAGE(ASM_MASM) - set(ZLIB_ASMS - contrib/masmx86/inffas32.asm - contrib/masmx86/match686.asm - ) - elseif (AMD64) - ENABLE_LANGUAGE(ASM_MASM) - set(ZLIB_ASMS - contrib/masmx64/gvmat64.asm - contrib/masmx64/inffasx64.asm - ) - endif() - - if(ZLIB_ASMS) - add_definitions(-DASMV -DASMINF) - endif() -endif() - -# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION -file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) -string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" - "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) - -if(MINGW) - # This gets us DLL resource information when compiling on MinGW. - if(NOT CMAKE_RC_COMPILER) - set(CMAKE_RC_COMPILER windres.exe) - endif() - - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - COMMAND ${CMAKE_RC_COMPILER} - -D GCC_WINDRES - -I ${CMAKE_CURRENT_SOURCE_DIR} - -I ${CMAKE_CURRENT_BINARY_DIR} - -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) - set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) -endif(MINGW) - -add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -INSTALL( TARGETS zlibstatic - LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} - COMPONENT ${LIBASSIMP_COMPONENT}) +cmake_minimum_required(VERSION 2.4.4) +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) + +# CMake 3.0 changed the project command, setting policy CMP0048 reverts to the old behaviour. +# See http://www.cmake.org/cmake/help/v3.0/policy/CMP0048.html +cmake_policy(PUSH) +if(CMAKE_MAJOR_VERSION GREATER 2) + cmake_policy(SET CMP0048 OLD) +endif() +project(zlib C) +cmake_policy(POP) + +set(VERSION "1.2.8") + +option(ASM686 "Enable building i686 assembly implementation for zlib") +option(AMD64 "Enable building amd64 assembly implementation for zlib") + +#set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") +#set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") +#set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") +#set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") +#set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") + +include(CheckTypeSize) +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CheckCSourceCompiles) +enable_testing() + +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(stddef.h HAVE_STDDEF_H) + +# +# Check to see if we have large file support +# +set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) +# We add these other definitions here because CheckTypeSize.cmake +# in CMake 2.4.x does not automatically do so and we want +# compatibility with CMake 2.4.x. +if(HAVE_SYS_TYPES_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H) +endif() +if(HAVE_STDINT_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H) +endif() +if(HAVE_STDDEF_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H) +endif() +check_type_size(off64_t OFF64_T) +if(HAVE_OFF64_T) + add_definitions(-D_LARGEFILE64_SOURCE=1) +endif() +set(CMAKE_REQUIRED_DEFINITIONS) # clear variable + +# +# Check for fseeko +# +check_function_exists(fseeko HAVE_FSEEKO) +if(NOT HAVE_FSEEKO) + add_definitions(-DNO_FSEEKO) +endif() + +# +# Check for unistd.h +# +check_include_file(unistd.h Z_HAVE_UNISTD_H) + +if(MSVC) + set(CMAKE_DEBUG_POSTFIX "d") + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) + # If we're doing an out of source build and the user has a zconf.h + # in their source tree... + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) + message(STATUS "Renaming") + message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") + message(STATUS "to 'zconf.h.included' because this file is included with zlib") + message(STATUS "but CMake generates it automatically in the build directory.") + file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) + endif() +endif() + +set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein + ${ZLIB_PC} @ONLY) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) + +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) + + +#============================================================================ +# zlib +#============================================================================ + +set(ZLIB_PUBLIC_HDRS + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h + zlib.h +) +set(ZLIB_PRIVATE_HDRS + crc32.h + deflate.h + gzguts.h + inffast.h + inffixed.h + inflate.h + inftrees.h + trees.h + zutil.h +) +set(ZLIB_SRCS + adler32.c + compress.c + crc32.c + deflate.c + gzclose.c + gzlib.c + gzread.c + gzwrite.c + inflate.c + infback.c + inftrees.c + inffast.c + trees.c + uncompr.c + zutil.c +) + +if(NOT MINGW) + set(ZLIB_DLL_SRCS + win32/zlib1.rc # If present will override custom build rule below. + ) +endif() + +if(CMAKE_COMPILER_IS_GNUCC) + if(ASM686) + set(ZLIB_ASMS contrib/asm686/match.S) + elseif (AMD64) + set(ZLIB_ASMS contrib/amd64/amd64-match.S) + endif () + + if(ZLIB_ASMS) + add_definitions(-DASMV) + set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE) + endif() +endif() + +if(MSVC) + if(ASM686) + ENABLE_LANGUAGE(ASM_MASM) + set(ZLIB_ASMS + contrib/masmx86/inffas32.asm + contrib/masmx86/match686.asm + ) + elseif (AMD64) + ENABLE_LANGUAGE(ASM_MASM) + set(ZLIB_ASMS + contrib/masmx64/gvmat64.asm + contrib/masmx64/inffasx64.asm + ) + endif() + + if(ZLIB_ASMS) + add_definitions(-DASMV -DASMINF) + endif() +endif() + +# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) +string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" + "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) + +if(MINGW) + # This gets us DLL resource information when compiling on MinGW. + if(NOT CMAKE_RC_COMPILER) + set(CMAKE_RC_COMPILER windres.exe) + endif() + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + COMMAND ${CMAKE_RC_COMPILER} + -D GCC_WINDRES + -I ${CMAKE_CURRENT_SOURCE_DIR} + -I ${CMAKE_CURRENT_BINARY_DIR} + -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) + set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) +endif(MINGW) + +add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +INSTALL( TARGETS zlibstatic + LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} + COMPONENT ${LIBASSIMP_COMPONENT}) diff --git a/contrib/zlib_note.txt b/contrib/zlib_note.txt index 538f8011f..cc274f0bf 100644 --- a/contrib/zlib_note.txt +++ b/contrib/zlib_note.txt @@ -1,11 +1,11 @@ -This is a heavily modified and shrinked version of zlib 1.2.3 - -- Removed comments from zlib.h -- Removed gzip/zip archive I/O -- Removed infback.c -- Added Assimp #idefs to exclude it if not needed -- Disabled debug macros in zutil.h - -Assimp itself does not use the compression part yet, so -it needn't be compiled (trees.c, deflate.c, compress.c). +This is a heavily modified and shrinked version of zlib 1.2.3 + +- Removed comments from zlib.h +- Removed gzip/zip archive I/O +- Removed infback.c +- Added Assimp #idefs to exclude it if not needed +- Disabled debug macros in zutil.h + +Assimp itself does not use the compression part yet, so +it needn't be compiled (trees.c, deflate.c, compress.c). Currently these units are just used by assimp_cmd. \ No newline at end of file diff --git a/doc/Preamble.txt b/doc/Preamble.txt index 5b2fcaa73..0722a48e1 100644 --- a/doc/Preamble.txt +++ b/doc/Preamble.txt @@ -1,40 +1,40 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp team - -All rights reserved. - -Redistribution and use of this software 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 the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -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. ---------------------------------------------------------------------------- +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp team + +All rights reserved. + +Redistribution and use of this software 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 the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +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. +--------------------------------------------------------------------------- */ \ No newline at end of file diff --git a/doc/dox_cmd.h b/doc/dox_cmd.h index 8ebbcb360..bc2320e1e 100644 --- a/doc/dox_cmd.h +++ b/doc/dox_cmd.h @@ -1,548 +1,548 @@ -/** @file dox_cmd.h - * @brief General documentation for assimp_cmd - */ - - -//---------------------------------------------------------------------------------------------- -// ASSIMP CMD MAINPAGE -/** -@mainpage ASSIMP Command-line tools - - - -@section intro Introduction - -This document describes the usage of assimp's command line tools. -This is *not* the SDK reference and programming-related stuff is not covered here. -

-NOTE: For simplicity, the following sections are written with Windows in mind. However -it's not different for Linux/Mac at all, except there's probably no assimp.exe ... - -@section basic_use Basic use - -Open a command prompt and navigate to the directory where assimp.exe resides. The basic command line is: - -@code -assimp [command] [parameters] -@endcode - -The following commands are available: - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@link version version @endlinkRetrieve the current version of assimp
@link help help @endlinkGet a list of all commands (yes, it's this list ...)
@link dump dump @endlinkGenerate a human-readable text dump of a model
@link extract extract @endlinkExtract an embedded texture image
@link iinfo info @endlinkLoad a model and print basic statistics
@link cmpdump cmpdump @endlinkRegression checking tool
- -If you use assimp's command line frequently, consider adding assimp to your PATH -environment. - - */ - - -/** -@page version 'version'-Command - -Display the version/revision of Assimp used. - */ - -/** -@page help 'help'-Command - -Display a really helpful text. - */ - -//---------------------------------------------------------------------------------------------- -// ASSIMP INFO - -/** -@page iinfo 'info'-Command - -Load a model file and print basic statistics. Full postprocessing is applied unless the -r switch is specified. Sample output (assimp info ./test/models/3DS/mar_rifle.3ds): - -@verbatim -Launching model import ... OK -Validating postprocessing flags ... OK -Importing file ... OK - import took approx. 0.02400 seconds - -Memory consumption: 69444 B -Nodes: 2 -Maximum depth 2 -Meshes: 1 -Animations: 0 -Textures (embed.): 0 -Materials: 1 -Cameras: 0 -Lights: 0 -Vertices: 843 -Faces: 572 -Bones: 0 -Animation Channels: 0 -Primitive Types: triangles -Average faces/mesh 572 -Average verts/mesh 843 -Minimum point (-3.522588 -11.573204 -40.340359) -Maximum point (3.522622 30.196556 75.941292) -Center point (0.000017 9.311676 17.800467) - -Named Materials: - 'mat1' - -Texture Refs: - 'm_rifl.bmp' - -Node hierarchy: -'<3DSRoot>', meshes: 0 --- 'm_rifle', meshes: 1 -<-- -@endverbatim - -

Syntax:

- -@code -assimp info file [-r] -@endcode - - -

Parameters:

- -

- -file

-Required. Input file. -

-

- --r
-Optional. Don't perform any postprocessing. The long form of this parameter is --raw. -

- -*/ -//---------------------------------------------------------------------------------------------- -// ASSIMP CMPDUMP - -/** -@page cmpdump 'cmpdump'-Command - -Used for Assimp's internal regression testing. Compare two mini dumps (produced using assimp dump .. -b -s) and -report any differences. In the regression test suite, this facility is used to build a database of -'known-to-be-fine' mini dumps, which are regularly compared against current results to detect regressions. - -

Syntax:

- -@code -assimp cmpdmp actual expected -@endcode - - -

Parameters:

- -

- -actual

-Required. Mini dump now. -

-

- -expected

-Required. Archived dump from some point in the past. -

- -*/ - - -//---------------------------------------------------------------------------------------------- -// ASSIMP DUMP - -/** -@page dump 'dump'-Command - -Generate a text or binary dump of a model. This is the core component of Assimp's internal -regression test suite but it could also be useful for other developers to quickly -examine the contents of a model. Note that text dumps are not intended to be used as -intermediate format, Assimp is not able to read them again, nor is the file format -stable or well-defined. It may change with every revision without notice. -Binary dumps (*.assbin) are backwards- and forwards-compatible. - -

Syntax:

- -@code -assimp dump [] [-b] [-s] [common parameters] -@endcode - - -

Parameters:

- -

- -model

-Required. Relative or absolute path to the input model. -

-

- -out

-Optional. Relative or absolute path to write the output dump to. If it is omitted, -the dump is written to <model>-dump.txt -

- -

--b
-

-Optional. If this switch is specified, the dumb is written in binary format. -The long form of this parameter is --binary. -

- -

--s<n>
-

-Optional. If this switch is specified, the dumb is shortened to include only -min/max values for all vertex components and animation channels. The resulting -file is much smaller, but the original model can't be reconstructed from it. This is -used by Assimp's regression test suite, comparing those minidumps provides -a fast way to verify whether a loader works correctly or not. -The long form of this parameter is --short. -

- -

- -common parameters

-Optional. Import configuration & postprocessing. -See the @link common common parameters page @endlink for more information. -

- -
- -

Sample:

- -@code -assimp dump test.3ds test.txt -l -cfull -assimp dump test.3ds test.txt -include-log -config=full -@endcode - -Dumps 'test.3ds' to 'test.txt' after executing full post-processing on tehe imported data. -The log output is included with the dump. - - -@code -assimp dump files\*.* -assimp dump files\*.* -@endcode - -Dumps all loadable model files in the 'files' subdir. The output dumps are named --dump.txt. The log is not included. - */ - -//---------------------------------------------------------------------------------------------- -// ASSIMP EXTRACT - -/** -@page extract 'extract'-Command - -Extracts one or more embedded texture images from models. - -

Syntax:

- -@code -assimp extract [] [-t] [-f] [-ba] [-s] [common parameters] -@endcode - - -

Parameters:

- -

- -model

-Required. Relative or absolute path to the input model. -

-

- -out

-Optional. Relative or absolute path to write the output images to. If the file name is -omitted the output images are named
-The suffix _img<n> is appended to the file name if the -s switch is not specified -(where <n> is the zero-based index of the texture in the model file).
- -The output file format is determined from the given file extension. Supported -formats are BMP and TGA. If the file format can't be determined, -the value specified with the -f switch is taken. -
-Format settings are ignored for compressed embedded textures. They're always -written in their native file format (e.g. jpg). -

- -

--t<n>
-

-Optional. Specifies the (zero-based) index of the embedded texture to be extracted from -the model. If this option is *not* specified all textures found are exported. -The long form of this parameter is --texture=<n>. -

- -

--ba<n>
-

-Optional. Specifies whether output BMPs contain an alpha channel or not. -The long form of this parameter is --bmp-with-alpha=<n>. -

- - -

--f<n>
-

-Optional. Specifies the output file format. Supported -formats are BMP and TGA. The default value is BMP (if a full output filename is -specified, the output file format is taken from its extension, not from here). -The long form of this parameter is --format=<n>. -

- -

--s<n>
-

-Optional. Prevents the tool from adding the _img<n> suffix to all filenames. This option -must be specified together with -t to ensure that just one image is written. -The long form of this parameter is --nosuffix. -

- -

- -common parameters

-Optional. Import configuration & postprocessing. Most postprocessing-steps don't affect -embedded texture images, configuring too much is probably senseless here. -See the @link common common parameters page @endlink for more information. -

- -
- -

Sample:

- -@code -assimp extract test.mdl test.bmp --texture=0 --validate-data-structure -assimp extract test.mdl test.bmp -t=0 -vds -@endcode - -Extracts the first embedded texture (if any) from test.mdl after validating the -imported data structure and writes it to test_img0.bmp. - - -@code -assimp extract files\*.mdl *.bmp -assimp extract files\*.mdl *.bmp -@endcode - -Extracts all embedded textures from all loadable .mdl files in the 'files' subdirectory -and writes them to bitmaps which are named _img.bmp - */ - -//---------------------------------------------------------------------------------------------- -// ASSIMP COMMON PARAMETERS -/** -@page common Common parameters - -The parameters described on this page are commonly used by almost every assimp command. They -specify how the library will postprocess the imported data. This is done by several -configurable pipeline stages, called 'post processing steps'. Below you can find a list -of all supported steps along with short descriptions of what they're doing.
Programmers: -more information can be found in the aiPostProcess.h header. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterLong parameterDescription
-ptv--pretransform-verticesMove all vertices into worldspace and collapse the scene graph. Animation data is lost. - This is intended for applications which don't support scenegraph-oriented rendering.
-gsn--gen-smooth-normalsComputes 'smooth' per-vertex normal vectors if necessary. Mutually exclusive with -gn
-gn--gen-normalsComputes 'hard' per-face normal vectors if necessary. Mutually exclusive with -gsn
-cts--calc-tangent-spaceIf one UV channel and normal vectors are given, compute tangents and bitangents
-jiv--join-identical-verticesOptimize the index buffer. If this flag is not specified all vertices are referenced once.
-rrm--remove-redundant-materialsRemove redundant materials from the imported data.
-fd--find-degeneratesFind and process degenerates primitives.
-slm--split-large-meshesSplit large meshes over a specific threshold in smaller sub meshes. The default vertex & face limit is 1000000
-lbw--limit-bone-weightsLimit the number of bones influencing a single vertex. The default limit is 4.
-vds--validate-data-structurePerforms a full validation of the imported data structure. Recommended to avoid crashes if - an import plugin produces rubbish
-icl--improve-cache-localityImprove the cache locality of the vertex buffer by reordering the index buffer - to achieve a lower ACMR (average post-transform vertex cache miss ratio)
-sbpt--sort-by-ptypeSplits meshes which consist of more than one kind of primitives (e.g. lines and triangles mixed up) - in 'clean' submeshes.
-lh--convert-to-lhConverts the imported data to left-handed coordinate space
-fuv--flip-uvFlip UV coordinates from upper-left origin to lower-left origin
-fwo--flip-winding-orderFlip face winding order from CCW to CW
-ett--evaluate-texture-transformEvaluate per-texture UV transformations (e.g scaling, offset) and build pretransformed UV channels
-guv--gen-uvcoordsReplace abstract mapping descriptions, such as 'spherical' or 'cylindrical' with proper UV channels
-fixn--fix-normalsRun a heuristic algorithm to detect meshes with wrong face winding order/normals.
-tri--triangulateTriangulate poylgons with 4 and more points. Lines, points and triangles are not affected.
-fi--find-instancesSearch the data structure for instanced meshes and replace them by references. This can - reduce vertex/face counts but the postprocessing-step takes some time.
-og--optimize-graphSimplify and optimize the scenegraph. Use it with care, all hierarchy information could be lost. - Animations remain untouched.
-om--optimize-meshOptimize mesh usage. Meshes are merged, if possible. Very effective in combination with --optimize-graph
- -For convenience some default postprocessing configurations are provided. -The corresponding command line parameter is -c<name> (or --config=<name>). - - - - - - - - - - - - - - - - - - - - - - - -
NameDescriptionList of steps executed
fastFast post processing config, performs some essential optimizations and computes tangents-cts, -gn, -jiv, -tri, -guv, -sbpt
defaultBalanced post processing config; performs most optimizations-cts, -gsn, -jiv, -icl, -lbw, -rrm, -slm, -tri, -guv, -sbpt, -fd, -fiv
fullFull post processing. May take a while but results in best output quality for most purposes-cts, -gsn, -jiv, -icl, -lbw, -rrm, -slm, -tri, -guv, -sbpt, -fd, -fiv, -fi, -vds -om
- - The -tuv, -ptv, -og flags always need to be enabled manually. - -There are also some common flags to customize Assimp's logging behaviour: - - - - - - - - - - - - - - - - - - - -
NameDescription
-l or --show-logShow log file on console window (stderr)
-lo<file> or --log-out=<file>Streams the log to <file>
-v or --verboseEnables verbose logging. Debug messages will be produced too. This might - decrease loading performance and result in *very* long logs ... use with caution if you experience strange issues.
- */ +/** @file dox_cmd.h + * @brief General documentation for assimp_cmd + */ + + +//---------------------------------------------------------------------------------------------- +// ASSIMP CMD MAINPAGE +/** +@mainpage ASSIMP Command-line tools + + + +@section intro Introduction + +This document describes the usage of assimp's command line tools. +This is *not* the SDK reference and programming-related stuff is not covered here. +

+NOTE: For simplicity, the following sections are written with Windows in mind. However +it's not different for Linux/Mac at all, except there's probably no assimp.exe ... + +@section basic_use Basic use + +Open a command prompt and navigate to the directory where assimp.exe resides. The basic command line is: + +@code +assimp [command] [parameters] +@endcode + +The following commands are available: + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@link version version @endlinkRetrieve the current version of assimp
@link help help @endlinkGet a list of all commands (yes, it's this list ...)
@link dump dump @endlinkGenerate a human-readable text dump of a model
@link extract extract @endlinkExtract an embedded texture image
@link iinfo info @endlinkLoad a model and print basic statistics
@link cmpdump cmpdump @endlinkRegression checking tool
+ +If you use assimp's command line frequently, consider adding assimp to your PATH +environment. + + */ + + +/** +@page version 'version'-Command + +Display the version/revision of Assimp used. + */ + +/** +@page help 'help'-Command + +Display a really helpful text. + */ + +//---------------------------------------------------------------------------------------------- +// ASSIMP INFO + +/** +@page iinfo 'info'-Command + +Load a model file and print basic statistics. Full postprocessing is applied unless the -r switch is specified. Sample output (assimp info ./test/models/3DS/mar_rifle.3ds): + +@verbatim +Launching model import ... OK +Validating postprocessing flags ... OK +Importing file ... OK + import took approx. 0.02400 seconds + +Memory consumption: 69444 B +Nodes: 2 +Maximum depth 2 +Meshes: 1 +Animations: 0 +Textures (embed.): 0 +Materials: 1 +Cameras: 0 +Lights: 0 +Vertices: 843 +Faces: 572 +Bones: 0 +Animation Channels: 0 +Primitive Types: triangles +Average faces/mesh 572 +Average verts/mesh 843 +Minimum point (-3.522588 -11.573204 -40.340359) +Maximum point (3.522622 30.196556 75.941292) +Center point (0.000017 9.311676 17.800467) + +Named Materials: + 'mat1' + +Texture Refs: + 'm_rifl.bmp' + +Node hierarchy: +'<3DSRoot>', meshes: 0 +-- 'm_rifle', meshes: 1 +<-- +@endverbatim + +

Syntax:

+ +@code +assimp info file [-r] +@endcode + + +

Parameters:

+ +

+ +file

+Required. Input file. +

+

+ +-r
+Optional. Don't perform any postprocessing. The long form of this parameter is --raw. +

+ +*/ +//---------------------------------------------------------------------------------------------- +// ASSIMP CMPDUMP + +/** +@page cmpdump 'cmpdump'-Command + +Used for Assimp's internal regression testing. Compare two mini dumps (produced using assimp dump .. -b -s) and +report any differences. In the regression test suite, this facility is used to build a database of +'known-to-be-fine' mini dumps, which are regularly compared against current results to detect regressions. + +

Syntax:

+ +@code +assimp cmpdmp actual expected +@endcode + + +

Parameters:

+ +

+ +actual

+Required. Mini dump now. +

+

+ +expected

+Required. Archived dump from some point in the past. +

+ +*/ + + +//---------------------------------------------------------------------------------------------- +// ASSIMP DUMP + +/** +@page dump 'dump'-Command + +Generate a text or binary dump of a model. This is the core component of Assimp's internal +regression test suite but it could also be useful for other developers to quickly +examine the contents of a model. Note that text dumps are not intended to be used as +intermediate format, Assimp is not able to read them again, nor is the file format +stable or well-defined. It may change with every revision without notice. +Binary dumps (*.assbin) are backwards- and forwards-compatible. + +

Syntax:

+ +@code +assimp dump [] [-b] [-s] [common parameters] +@endcode + + +

Parameters:

+ +

+ +model

+Required. Relative or absolute path to the input model. +

+

+ +out

+Optional. Relative or absolute path to write the output dump to. If it is omitted, +the dump is written to <model>-dump.txt +

+ +

+-b
+

+Optional. If this switch is specified, the dumb is written in binary format. +The long form of this parameter is --binary. +

+ +

+-s<n>
+

+Optional. If this switch is specified, the dumb is shortened to include only +min/max values for all vertex components and animation channels. The resulting +file is much smaller, but the original model can't be reconstructed from it. This is +used by Assimp's regression test suite, comparing those minidumps provides +a fast way to verify whether a loader works correctly or not. +The long form of this parameter is --short. +

+ +

+ +common parameters

+Optional. Import configuration & postprocessing. +See the @link common common parameters page @endlink for more information. +

+ +
+ +

Sample:

+ +@code +assimp dump test.3ds test.txt -l -cfull +assimp dump test.3ds test.txt -include-log -config=full +@endcode + +Dumps 'test.3ds' to 'test.txt' after executing full post-processing on tehe imported data. +The log output is included with the dump. + + +@code +assimp dump files\*.* +assimp dump files\*.* +@endcode + +Dumps all loadable model files in the 'files' subdir. The output dumps are named +-dump.txt. The log is not included. + */ + +//---------------------------------------------------------------------------------------------- +// ASSIMP EXTRACT + +/** +@page extract 'extract'-Command + +Extracts one or more embedded texture images from models. + +

Syntax:

+ +@code +assimp extract [] [-t] [-f] [-ba] [-s] [common parameters] +@endcode + + +

Parameters:

+ +

+ +model

+Required. Relative or absolute path to the input model. +

+

+ +out

+Optional. Relative or absolute path to write the output images to. If the file name is +omitted the output images are named
+The suffix _img<n> is appended to the file name if the -s switch is not specified +(where <n> is the zero-based index of the texture in the model file).
+ +The output file format is determined from the given file extension. Supported +formats are BMP and TGA. If the file format can't be determined, +the value specified with the -f switch is taken. +
+Format settings are ignored for compressed embedded textures. They're always +written in their native file format (e.g. jpg). +

+ +

+-t<n>
+

+Optional. Specifies the (zero-based) index of the embedded texture to be extracted from +the model. If this option is *not* specified all textures found are exported. +The long form of this parameter is --texture=<n>. +

+ +

+-ba<n>
+

+Optional. Specifies whether output BMPs contain an alpha channel or not. +The long form of this parameter is --bmp-with-alpha=<n>. +

+ + +

+-f<n>
+

+Optional. Specifies the output file format. Supported +formats are BMP and TGA. The default value is BMP (if a full output filename is +specified, the output file format is taken from its extension, not from here). +The long form of this parameter is --format=<n>. +

+ +

+-s<n>
+

+Optional. Prevents the tool from adding the _img<n> suffix to all filenames. This option +must be specified together with -t to ensure that just one image is written. +The long form of this parameter is --nosuffix. +

+ +

+ +common parameters

+Optional. Import configuration & postprocessing. Most postprocessing-steps don't affect +embedded texture images, configuring too much is probably senseless here. +See the @link common common parameters page @endlink for more information. +

+ +
+ +

Sample:

+ +@code +assimp extract test.mdl test.bmp --texture=0 --validate-data-structure +assimp extract test.mdl test.bmp -t=0 -vds +@endcode + +Extracts the first embedded texture (if any) from test.mdl after validating the +imported data structure and writes it to test_img0.bmp. + + +@code +assimp extract files\*.mdl *.bmp +assimp extract files\*.mdl *.bmp +@endcode + +Extracts all embedded textures from all loadable .mdl files in the 'files' subdirectory +and writes them to bitmaps which are named _img.bmp + */ + +//---------------------------------------------------------------------------------------------- +// ASSIMP COMMON PARAMETERS +/** +@page common Common parameters + +The parameters described on this page are commonly used by almost every assimp command. They +specify how the library will postprocess the imported data. This is done by several +configurable pipeline stages, called 'post processing steps'. Below you can find a list +of all supported steps along with short descriptions of what they're doing.
Programmers: +more information can be found in the aiPostProcess.h header. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterLong parameterDescription
-ptv--pretransform-verticesMove all vertices into worldspace and collapse the scene graph. Animation data is lost. + This is intended for applications which don't support scenegraph-oriented rendering.
-gsn--gen-smooth-normalsComputes 'smooth' per-vertex normal vectors if necessary. Mutually exclusive with -gn
-gn--gen-normalsComputes 'hard' per-face normal vectors if necessary. Mutually exclusive with -gsn
-cts--calc-tangent-spaceIf one UV channel and normal vectors are given, compute tangents and bitangents
-jiv--join-identical-verticesOptimize the index buffer. If this flag is not specified all vertices are referenced once.
-rrm--remove-redundant-materialsRemove redundant materials from the imported data.
-fd--find-degeneratesFind and process degenerates primitives.
-slm--split-large-meshesSplit large meshes over a specific threshold in smaller sub meshes. The default vertex & face limit is 1000000
-lbw--limit-bone-weightsLimit the number of bones influencing a single vertex. The default limit is 4.
-vds--validate-data-structurePerforms a full validation of the imported data structure. Recommended to avoid crashes if + an import plugin produces rubbish
-icl--improve-cache-localityImprove the cache locality of the vertex buffer by reordering the index buffer + to achieve a lower ACMR (average post-transform vertex cache miss ratio)
-sbpt--sort-by-ptypeSplits meshes which consist of more than one kind of primitives (e.g. lines and triangles mixed up) + in 'clean' submeshes.
-lh--convert-to-lhConverts the imported data to left-handed coordinate space
-fuv--flip-uvFlip UV coordinates from upper-left origin to lower-left origin
-fwo--flip-winding-orderFlip face winding order from CCW to CW
-ett--evaluate-texture-transformEvaluate per-texture UV transformations (e.g scaling, offset) and build pretransformed UV channels
-guv--gen-uvcoordsReplace abstract mapping descriptions, such as 'spherical' or 'cylindrical' with proper UV channels
-fixn--fix-normalsRun a heuristic algorithm to detect meshes with wrong face winding order/normals.
-tri--triangulateTriangulate poylgons with 4 and more points. Lines, points and triangles are not affected.
-fi--find-instancesSearch the data structure for instanced meshes and replace them by references. This can + reduce vertex/face counts but the postprocessing-step takes some time.
-og--optimize-graphSimplify and optimize the scenegraph. Use it with care, all hierarchy information could be lost. + Animations remain untouched.
-om--optimize-meshOptimize mesh usage. Meshes are merged, if possible. Very effective in combination with --optimize-graph
+ +For convenience some default postprocessing configurations are provided. +The corresponding command line parameter is -c<name> (or --config=<name>). + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionList of steps executed
fastFast post processing config, performs some essential optimizations and computes tangents-cts, -gn, -jiv, -tri, -guv, -sbpt
defaultBalanced post processing config; performs most optimizations-cts, -gsn, -jiv, -icl, -lbw, -rrm, -slm, -tri, -guv, -sbpt, -fd, -fiv
fullFull post processing. May take a while but results in best output quality for most purposes-cts, -gsn, -jiv, -icl, -lbw, -rrm, -slm, -tri, -guv, -sbpt, -fd, -fiv, -fi, -vds -om
+ + The -tuv, -ptv, -og flags always need to be enabled manually. + +There are also some common flags to customize Assimp's logging behaviour: + + + + + + + + + + + + + + + + + + + +
NameDescription
-l or --show-logShow log file on console window (stderr)
-lo<file> or --log-out=<file>Streams the log to <file>
-v or --verboseEnables verbose logging. Debug messages will be produced too. This might + decrease loading performance and result in *very* long logs ... use with caution if you experience strange issues.
+ */ diff --git a/include/assimp/Compiler/poppack1.h b/include/assimp/Compiler/poppack1.h index 531707420..e033bc147 100644 --- a/include/assimp/Compiler/poppack1.h +++ b/include/assimp/Compiler/poppack1.h @@ -1,22 +1,22 @@ - -// =============================================================================== -// May be included multiple times - resets structure packing to the defaults -// for all supported compilers. Reverts the changes made by #include -// -// Currently this works on the following compilers: -// MSVC 7,8,9 -// GCC -// BORLAND (complains about 'pack state changed but not reverted', but works) -// =============================================================================== - -#ifndef AI_PUSHPACK_IS_DEFINED -# error pushpack1.h must be included after poppack1.h -#endif - -// reset packing to the original value -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) -# pragma pack( pop ) -#endif -#undef PACK_STRUCT - -#undef AI_PUSHPACK_IS_DEFINED + +// =============================================================================== +// May be included multiple times - resets structure packing to the defaults +// for all supported compilers. Reverts the changes made by #include +// +// Currently this works on the following compilers: +// MSVC 7,8,9 +// GCC +// BORLAND (complains about 'pack state changed but not reverted', but works) +// =============================================================================== + +#ifndef AI_PUSHPACK_IS_DEFINED +# error pushpack1.h must be included after poppack1.h +#endif + +// reset packing to the original value +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) +# pragma pack( pop ) +#endif +#undef PACK_STRUCT + +#undef AI_PUSHPACK_IS_DEFINED diff --git a/include/assimp/Compiler/pstdint.h b/include/assimp/Compiler/pstdint.h index 7d0e2bc58..5bc322fab 100644 --- a/include/assimp/Compiler/pstdint.h +++ b/include/assimp/Compiler/pstdint.h @@ -1,729 +1,729 @@ -/* A portable stdint.h - **************************************************************************** - * BSD License: - **************************************************************************** - * - * Copyright (c) 2005-2007 Paul Hsieh - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - **************************************************************************** - * - * Version 0.1.10 - * - * The ANSI C standard committee, for the C99 standard, specified the - * inclusion of a new standard include file called stdint.h. This is - * a very useful and long desired include file which contains several - * very precise definitions for integer scalar types that is - * critically important for making portable several classes of - * applications including cryptography, hashing, variable length - * integer libraries and so on. But for most developers its likely - * useful just for programming sanity. - * - * The problem is that most compiler vendors have decided not to - * implement the C99 standard, and the next C++ language standard - * (which has a lot more mindshare these days) will be a long time in - * coming and its unknown whether or not it will include stdint.h or - * how much adoption it will have. Either way, it will be a long time - * before all compilers come with a stdint.h and it also does nothing - * for the extremely large number of compilers available today which - * do not include this file, or anything comparable to it. - * - * So that's what this file is all about. Its an attempt to build a - * single universal include file that works on as many platforms as - * possible to deliver what stdint.h is supposed to. A few things - * that should be noted about this file: - * - * 1) It is not guaranteed to be portable and/or present an identical - * interface on all platforms. The extreme variability of the - * ANSI C standard makes this an impossibility right from the - * very get go. Its really only meant to be useful for the vast - * majority of platforms that possess the capability of - * implementing usefully and precisely defined, standard sized - * integer scalars. Systems which are not intrinsically 2s - * complement may produce invalid constants. - * - * 2) There is an unavoidable use of non-reserved symbols. - * - * 3) Other standard include files are invoked. - * - * 4) This file may come in conflict with future platforms that do - * include stdint.h. The hope is that one or the other can be - * used with no real difference. - * - * 5) In the current verison, if your platform can't represent - * int32_t, int16_t and int8_t, it just dumps out with a compiler - * error. - * - * 6) 64 bit integers may or may not be defined. Test for their - * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. - * Note that this is different from the C99 specification which - * requires the existence of 64 bit support in the compiler. If - * this is not defined for your platform, yet it is capable of - * dealing with 64 bits then it is because this file has not yet - * been extended to cover all of your system's capabilities. - * - * 7) (u)intptr_t may or may not be defined. Test for its presence - * with the test: #ifdef PTRDIFF_MAX. If this is not defined - * for your platform, then it is because this file has not yet - * been extended to cover all of your system's capabilities, not - * because its optional. - * - * 8) The following might not been defined even if your platform is - * capable of defining it: - * - * WCHAR_MIN - * WCHAR_MAX - * (u)int64_t - * PTRDIFF_MIN - * PTRDIFF_MAX - * (u)intptr_t - * - * 9) The following have not been defined: - * - * WINT_MIN - * WINT_MAX - * - * 10) The criteria for defining (u)int_least(*)_t isn't clear, - * except for systems which don't have a type that precisely - * defined 8, 16, or 32 bit types (which this include file does - * not support anyways). Default definitions have been given. - * - * 11) The criteria for defining (u)int_fast(*)_t isn't something I - * would trust to any particular compiler vendor or the ANSI C - * committee. It is well known that "compatible systems" are - * commonly created that have very different performance - * characteristics from the systems they are compatible with, - * especially those whose vendors make both the compiler and the - * system. Default definitions have been given, but its strongly - * recommended that users never use these definitions for any - * reason (they do *NOT* deliver any serious guarantee of - * improved performance -- not in this file, nor any vendor's - * stdint.h). - * - * 12) The following macros: - * - * PRINTF_INTMAX_MODIFIER - * PRINTF_INT64_MODIFIER - * PRINTF_INT32_MODIFIER - * PRINTF_INT16_MODIFIER - * PRINTF_LEAST64_MODIFIER - * PRINTF_LEAST32_MODIFIER - * PRINTF_LEAST16_MODIFIER - * PRINTF_INTPTR_MODIFIER - * - * are strings which have been defined as the modifiers required - * for the "d", "u" and "x" printf formats to correctly output - * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, - * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. - * PRINTF_INTPTR_MODIFIER is not defined for some systems which - * provide their own stdint.h. PRINTF_INT64_MODIFIER is not - * defined if INT64_MAX is not defined. These are an extension - * beyond what C99 specifies must be in stdint.h. - * - * In addition, the following macros are defined: - * - * PRINTF_INTMAX_HEX_WIDTH - * PRINTF_INT64_HEX_WIDTH - * PRINTF_INT32_HEX_WIDTH - * PRINTF_INT16_HEX_WIDTH - * PRINTF_INT8_HEX_WIDTH - * PRINTF_INTMAX_DEC_WIDTH - * PRINTF_INT64_DEC_WIDTH - * PRINTF_INT32_DEC_WIDTH - * PRINTF_INT16_DEC_WIDTH - * PRINTF_INT8_DEC_WIDTH - * - * Which specifies the maximum number of characters required to - * print the number of that type in either hexadecimal or decimal. - * These are an extension beyond what C99 specifies must be in - * stdint.h. - * - * Compilers tested (all with 0 warnings at their highest respective - * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 - * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio - * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 - * - * This file should be considered a work in progress. Suggestions for - * improvements, especially those which increase coverage are strongly - * encouraged. - * - * Acknowledgements - * - * The following people have made significant contributions to the - * development and testing of this file: - * - * Chris Howie - * John Steele Scott - * Dave Thorup - * - */ - -#include -#include -#include - -/* - * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and - * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. - */ - -#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)))) && !defined (_PSTDINT_H_INCLUDED) && !defined(_STDINT) -#include -#define _PSTDINT_H_INCLUDED -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -# endif -# ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -# endif -# ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -# endif -# ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -# endif -# ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -# endif -# ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -# endif -# ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -# endif -# ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif - -/* - * Something really weird is going on with Open Watcom. Just pull some of - * these duplicated definitions from Open Watcom's stdint.h file for now. - */ - -# if defined (__WATCOMC__) && __WATCOMC__ >= 1250 -# if !defined (INT64_C) -# define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) -# endif -# if !defined (UINT64_C) -# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) -# endif -# if !defined (INT32_C) -# define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) -# endif -# if !defined (UINT32_C) -# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) -# endif -# if !defined (INT16_C) -# define INT16_C(x) (x) -# endif -# if !defined (UINT16_C) -# define UINT16_C(x) (x) -# endif -# if !defined (INT8_C) -# define INT8_C(x) (x) -# endif -# if !defined (UINT8_C) -# define UINT8_C(x) (x) -# endif -# if !defined (UINT64_MAX) -# define UINT64_MAX 18446744073709551615ULL -# endif -# if !defined (INT64_MAX) -# define INT64_MAX 9223372036854775807LL -# endif -# if !defined (UINT32_MAX) -# define UINT32_MAX 4294967295UL -# endif -# if !defined (INT32_MAX) -# define INT32_MAX 2147483647L -# endif -# if !defined (INTMAX_MAX) -# define INTMAX_MAX INT64_MAX -# endif -# if !defined (INTMAX_MIN) -# define INTMAX_MIN INT64_MIN -# endif -# endif -#endif - -#ifndef _PSTDINT_H_INCLUDED -#define _PSTDINT_H_INCLUDED - -#ifndef SIZE_MAX -# define SIZE_MAX (~(size_t)0) -#endif - -/* - * Deduce the type assignments from limits.h under the assumption that - * integer sizes in bits are powers of 2, and follow the ANSI - * definitions. - */ - -#ifndef UINT8_MAX -# define UINT8_MAX 0xff -#endif -#ifndef uint8_t -# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) - typedef unsigned char uint8_t; -# define UINT8_C(v) ((uint8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef INT8_MAX -# define INT8_MAX 0x7f -#endif -#ifndef INT8_MIN -# define INT8_MIN INT8_C(0x80) -#endif -#ifndef int8_t -# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) - typedef signed char int8_t; -# define INT8_C(v) ((int8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef UINT16_MAX -# define UINT16_MAX 0xffff -#endif -#ifndef uint16_t -#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) - typedef unsigned int uint16_t; -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -# define UINT16_C(v) ((uint16_t) (v)) -#elif (USHRT_MAX == UINT16_MAX) - typedef unsigned short uint16_t; -# define UINT16_C(v) ((uint16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT16_MAX -# define INT16_MAX 0x7fff -#endif -#ifndef INT16_MIN -# define INT16_MIN INT16_C(0x8000) -#endif -#ifndef int16_t -#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) - typedef signed int int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -#elif (SHRT_MAX == INT16_MAX) - typedef signed short int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef UINT32_MAX -# define UINT32_MAX (0xffffffffUL) -#endif -#ifndef uint32_t -#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) - typedef unsigned long uint32_t; -# define UINT32_C(v) v ## UL -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (UINT_MAX == UINT32_MAX) - typedef unsigned int uint32_t; -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -# define UINT32_C(v) v ## U -#elif (USHRT_MAX == UINT32_MAX) - typedef unsigned short uint32_t; -# define UINT32_C(v) ((unsigned short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT32_MAX -# define INT32_MAX (0x7fffffffL) -#endif -#ifndef INT32_MIN -# define INT32_MIN INT32_C(0x80000000) -#endif -#ifndef int32_t -#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) - typedef signed long int32_t; -# define INT32_C(v) v ## L -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (INT_MAX == INT32_MAX) - typedef signed int int32_t; -# define INT32_C(v) v -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#elif (SHRT_MAX == INT32_MAX) - typedef signed short int32_t; -# define INT32_C(v) ((short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -/* - * The macro stdint_int64_defined is temporarily used to record - * whether or not 64 integer support is available. It must be - * defined for any 64 integer extensions for new platforms that are - * added. - */ - -#undef stdint_int64_defined -#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) -# if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# endif -#endif - -#if !defined (stdint_int64_defined) -# if defined(__GNUC__) -# define stdint_int64_defined - __extension__ typedef long long int64_t; - __extension__ typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) -# define stdint_int64_defined - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; -# define UINT64_C(v) v ## UI64 -# define INT64_C(v) v ## I64 -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "I64" -# endif -# endif -#endif - -#if !defined (LONG_LONG_MAX) && defined (INT64_C) -# define LONG_LONG_MAX INT64_C (9223372036854775807) -#endif -#ifndef ULONG_LONG_MAX -# define ULONG_LONG_MAX UINT64_C (18446744073709551615) -#endif - -#if !defined (INT64_MAX) && defined (INT64_C) -# define INT64_MAX INT64_C (9223372036854775807) -#endif -#if !defined (INT64_MIN) && defined (INT64_C) -# define INT64_MIN INT64_C (-9223372036854775808) -#endif -#if !defined (UINT64_MAX) && defined (INT64_C) -# define UINT64_MAX UINT64_C (18446744073709551615) -#endif - -/* - * Width of hexadecimal for number field. - */ - -#ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -#endif -#ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -#endif -#ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -#endif -#ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -#endif - -#ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -#endif -#ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -#endif -#ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -#endif -#ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -#endif - -/* - * Ok, lets not worry about 128 bit integers for now. Moore's law says - * we don't need to worry about that until about 2040 at which point - * we'll have bigger things to worry about. - */ - -#ifdef stdint_int64_defined - typedef int64_t intmax_t; - typedef uint64_t uintmax_t; -# define INTMAX_MAX INT64_MAX -# define INTMAX_MIN INT64_MIN -# define UINTMAX_MAX UINT64_MAX -# define UINTMAX_C(v) UINT64_C(v) -# define INTMAX_C(v) INT64_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif -#else - typedef int32_t intmax_t; - typedef uint32_t uintmax_t; -# define INTMAX_MAX INT32_MAX -# define UINTMAX_MAX UINT32_MAX -# define UINTMAX_C(v) UINT32_C(v) -# define INTMAX_C(v) INT32_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH -# endif -#endif - -/* - * Because this file currently only supports platforms which have - * precise powers of 2 as bit sizes for the default integers, the - * least definitions are all trivial. Its possible that a future - * version of this file could have different definitions. - */ - -#ifndef stdint_least_defined - typedef int8_t int_least8_t; - typedef uint8_t uint_least8_t; - typedef int16_t int_least16_t; - typedef uint16_t uint_least16_t; - typedef int32_t int_least32_t; - typedef uint32_t uint_least32_t; -# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER -# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER -# define UINT_LEAST8_MAX UINT8_MAX -# define INT_LEAST8_MAX INT8_MAX -# define UINT_LEAST16_MAX UINT16_MAX -# define INT_LEAST16_MAX INT16_MAX -# define UINT_LEAST32_MAX UINT32_MAX -# define INT_LEAST32_MAX INT32_MAX -# define INT_LEAST8_MIN INT8_MIN -# define INT_LEAST16_MIN INT16_MIN -# define INT_LEAST32_MIN INT32_MIN -# ifdef stdint_int64_defined - typedef int64_t int_least64_t; - typedef uint64_t uint_least64_t; -# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER -# define UINT_LEAST64_MAX UINT64_MAX -# define INT_LEAST64_MAX INT64_MAX -# define INT_LEAST64_MIN INT64_MIN -# endif -#endif -#undef stdint_least_defined - -/* - * The ANSI C committee pretending to know or specify anything about - * performance is the epitome of misguided arrogance. The mandate of - * this file is to *ONLY* ever support that absolute minimum - * definition of the fast integer types, for compatibility purposes. - * No extensions, and no attempt to suggest what may or may not be a - * faster integer type will ever be made in this file. Developers are - * warned to stay away from these types when using this or any other - * stdint.h. - */ - -typedef int_least8_t int_fast8_t; -typedef uint_least8_t uint_fast8_t; -typedef int_least16_t int_fast16_t; -typedef uint_least16_t uint_fast16_t; -typedef int_least32_t int_fast32_t; -typedef uint_least32_t uint_fast32_t; -#define UINT_FAST8_MAX UINT_LEAST8_MAX -#define INT_FAST8_MAX INT_LEAST8_MAX -#define UINT_FAST16_MAX UINT_LEAST16_MAX -#define INT_FAST16_MAX INT_LEAST16_MAX -#define UINT_FAST32_MAX UINT_LEAST32_MAX -#define INT_FAST32_MAX INT_LEAST32_MAX -#define INT_FAST8_MIN INT_LEAST8_MIN -#define INT_FAST16_MIN INT_LEAST16_MIN -#define INT_FAST32_MIN INT_LEAST32_MIN -#ifdef stdint_int64_defined - typedef int_least64_t int_fast64_t; - typedef uint_least64_t uint_fast64_t; -# define UINT_FAST64_MAX UINT_LEAST64_MAX -# define INT_FAST64_MAX INT_LEAST64_MAX -# define INT_FAST64_MIN INT_LEAST64_MIN -#endif - -#undef stdint_int64_defined - -/* - * Whatever piecemeal, per compiler thing we can do about the wchar_t - * type limits. - */ - -#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) -# include -# ifndef WCHAR_MIN -# define WCHAR_MIN 0 -# endif -# ifndef WCHAR_MAX -# define WCHAR_MAX ((wchar_t)-1) -# endif -#endif - -/* - * Whatever piecemeal, per compiler/platform thing we can do about the - * (u)intptr_t types and limits. - */ - -#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED) -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -#ifndef STDINT_H_UINTPTR_T_DEFINED -# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) -# define stdint_intptr_bits 64 -# elif defined (__WATCOMC__) || defined (__TURBOC__) -# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) -# define stdint_intptr_bits 16 -# else -# define stdint_intptr_bits 32 -# endif -# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) -# define stdint_intptr_bits 32 -# elif defined (__INTEL_COMPILER) -/* TODO -- what will Intel do about x86-64? */ -# endif - -# ifdef stdint_intptr_bits -# define stdint_intptr_glue3_i(a,b,c) a##b##c -# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) -# ifndef PRINTF_INTPTR_MODIFIER -# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) -# endif -# ifndef PTRDIFF_MAX -# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef PTRDIFF_MIN -# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef UINTPTR_MAX -# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MAX -# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MIN -# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef INTPTR_C -# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) -# endif -# ifndef UINTPTR_C -# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) -# endif - typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; - typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; -# else -/* TODO -- This following is likely wrong for some platforms, and does - nothing for the definition of uintptr_t. */ - typedef ptrdiff_t intptr_t; -# endif -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -/* - * Assumes sig_atomic_t is signed and we have a 2s complement machine. - */ - -#ifndef SIG_ATOMIC_MAX -# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) -#endif - -#endif - +/* A portable stdint.h + **************************************************************************** + * BSD License: + **************************************************************************** + * + * Copyright (c) 2005-2007 Paul Hsieh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + **************************************************************************** + * + * Version 0.1.10 + * + * The ANSI C standard committee, for the C99 standard, specified the + * inclusion of a new standard include file called stdint.h. This is + * a very useful and long desired include file which contains several + * very precise definitions for integer scalar types that is + * critically important for making portable several classes of + * applications including cryptography, hashing, variable length + * integer libraries and so on. But for most developers its likely + * useful just for programming sanity. + * + * The problem is that most compiler vendors have decided not to + * implement the C99 standard, and the next C++ language standard + * (which has a lot more mindshare these days) will be a long time in + * coming and its unknown whether or not it will include stdint.h or + * how much adoption it will have. Either way, it will be a long time + * before all compilers come with a stdint.h and it also does nothing + * for the extremely large number of compilers available today which + * do not include this file, or anything comparable to it. + * + * So that's what this file is all about. Its an attempt to build a + * single universal include file that works on as many platforms as + * possible to deliver what stdint.h is supposed to. A few things + * that should be noted about this file: + * + * 1) It is not guaranteed to be portable and/or present an identical + * interface on all platforms. The extreme variability of the + * ANSI C standard makes this an impossibility right from the + * very get go. Its really only meant to be useful for the vast + * majority of platforms that possess the capability of + * implementing usefully and precisely defined, standard sized + * integer scalars. Systems which are not intrinsically 2s + * complement may produce invalid constants. + * + * 2) There is an unavoidable use of non-reserved symbols. + * + * 3) Other standard include files are invoked. + * + * 4) This file may come in conflict with future platforms that do + * include stdint.h. The hope is that one or the other can be + * used with no real difference. + * + * 5) In the current verison, if your platform can't represent + * int32_t, int16_t and int8_t, it just dumps out with a compiler + * error. + * + * 6) 64 bit integers may or may not be defined. Test for their + * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. + * Note that this is different from the C99 specification which + * requires the existence of 64 bit support in the compiler. If + * this is not defined for your platform, yet it is capable of + * dealing with 64 bits then it is because this file has not yet + * been extended to cover all of your system's capabilities. + * + * 7) (u)intptr_t may or may not be defined. Test for its presence + * with the test: #ifdef PTRDIFF_MAX. If this is not defined + * for your platform, then it is because this file has not yet + * been extended to cover all of your system's capabilities, not + * because its optional. + * + * 8) The following might not been defined even if your platform is + * capable of defining it: + * + * WCHAR_MIN + * WCHAR_MAX + * (u)int64_t + * PTRDIFF_MIN + * PTRDIFF_MAX + * (u)intptr_t + * + * 9) The following have not been defined: + * + * WINT_MIN + * WINT_MAX + * + * 10) The criteria for defining (u)int_least(*)_t isn't clear, + * except for systems which don't have a type that precisely + * defined 8, 16, or 32 bit types (which this include file does + * not support anyways). Default definitions have been given. + * + * 11) The criteria for defining (u)int_fast(*)_t isn't something I + * would trust to any particular compiler vendor or the ANSI C + * committee. It is well known that "compatible systems" are + * commonly created that have very different performance + * characteristics from the systems they are compatible with, + * especially those whose vendors make both the compiler and the + * system. Default definitions have been given, but its strongly + * recommended that users never use these definitions for any + * reason (they do *NOT* deliver any serious guarantee of + * improved performance -- not in this file, nor any vendor's + * stdint.h). + * + * 12) The following macros: + * + * PRINTF_INTMAX_MODIFIER + * PRINTF_INT64_MODIFIER + * PRINTF_INT32_MODIFIER + * PRINTF_INT16_MODIFIER + * PRINTF_LEAST64_MODIFIER + * PRINTF_LEAST32_MODIFIER + * PRINTF_LEAST16_MODIFIER + * PRINTF_INTPTR_MODIFIER + * + * are strings which have been defined as the modifiers required + * for the "d", "u" and "x" printf formats to correctly output + * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, + * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. + * PRINTF_INTPTR_MODIFIER is not defined for some systems which + * provide their own stdint.h. PRINTF_INT64_MODIFIER is not + * defined if INT64_MAX is not defined. These are an extension + * beyond what C99 specifies must be in stdint.h. + * + * In addition, the following macros are defined: + * + * PRINTF_INTMAX_HEX_WIDTH + * PRINTF_INT64_HEX_WIDTH + * PRINTF_INT32_HEX_WIDTH + * PRINTF_INT16_HEX_WIDTH + * PRINTF_INT8_HEX_WIDTH + * PRINTF_INTMAX_DEC_WIDTH + * PRINTF_INT64_DEC_WIDTH + * PRINTF_INT32_DEC_WIDTH + * PRINTF_INT16_DEC_WIDTH + * PRINTF_INT8_DEC_WIDTH + * + * Which specifies the maximum number of characters required to + * print the number of that type in either hexadecimal or decimal. + * These are an extension beyond what C99 specifies must be in + * stdint.h. + * + * Compilers tested (all with 0 warnings at their highest respective + * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 + * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio + * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 + * + * This file should be considered a work in progress. Suggestions for + * improvements, especially those which increase coverage are strongly + * encouraged. + * + * Acknowledgements + * + * The following people have made significant contributions to the + * development and testing of this file: + * + * Chris Howie + * John Steele Scott + * Dave Thorup + * + */ + +#include +#include +#include + +/* + * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and + * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. + */ + +#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)))) && !defined (_PSTDINT_H_INCLUDED) && !defined(_STDINT) +#include +#define _PSTDINT_H_INCLUDED +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER +# endif +# ifndef PRINTF_INT64_HEX_WIDTH +# define PRINTF_INT64_HEX_WIDTH "16" +# endif +# ifndef PRINTF_INT32_HEX_WIDTH +# define PRINTF_INT32_HEX_WIDTH "8" +# endif +# ifndef PRINTF_INT16_HEX_WIDTH +# define PRINTF_INT16_HEX_WIDTH "4" +# endif +# ifndef PRINTF_INT8_HEX_WIDTH +# define PRINTF_INT8_HEX_WIDTH "2" +# endif +# ifndef PRINTF_INT64_DEC_WIDTH +# define PRINTF_INT64_DEC_WIDTH "20" +# endif +# ifndef PRINTF_INT32_DEC_WIDTH +# define PRINTF_INT32_DEC_WIDTH "10" +# endif +# ifndef PRINTF_INT16_DEC_WIDTH +# define PRINTF_INT16_DEC_WIDTH "5" +# endif +# ifndef PRINTF_INT8_DEC_WIDTH +# define PRINTF_INT8_DEC_WIDTH "3" +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH +# endif + +/* + * Something really weird is going on with Open Watcom. Just pull some of + * these duplicated definitions from Open Watcom's stdint.h file for now. + */ + +# if defined (__WATCOMC__) && __WATCOMC__ >= 1250 +# if !defined (INT64_C) +# define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) +# endif +# if !defined (UINT64_C) +# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) +# endif +# if !defined (INT32_C) +# define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) +# endif +# if !defined (UINT32_C) +# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) +# endif +# if !defined (INT16_C) +# define INT16_C(x) (x) +# endif +# if !defined (UINT16_C) +# define UINT16_C(x) (x) +# endif +# if !defined (INT8_C) +# define INT8_C(x) (x) +# endif +# if !defined (UINT8_C) +# define UINT8_C(x) (x) +# endif +# if !defined (UINT64_MAX) +# define UINT64_MAX 18446744073709551615ULL +# endif +# if !defined (INT64_MAX) +# define INT64_MAX 9223372036854775807LL +# endif +# if !defined (UINT32_MAX) +# define UINT32_MAX 4294967295UL +# endif +# if !defined (INT32_MAX) +# define INT32_MAX 2147483647L +# endif +# if !defined (INTMAX_MAX) +# define INTMAX_MAX INT64_MAX +# endif +# if !defined (INTMAX_MIN) +# define INTMAX_MIN INT64_MIN +# endif +# endif +#endif + +#ifndef _PSTDINT_H_INCLUDED +#define _PSTDINT_H_INCLUDED + +#ifndef SIZE_MAX +# define SIZE_MAX (~(size_t)0) +#endif + +/* + * Deduce the type assignments from limits.h under the assumption that + * integer sizes in bits are powers of 2, and follow the ANSI + * definitions. + */ + +#ifndef UINT8_MAX +# define UINT8_MAX 0xff +#endif +#ifndef uint8_t +# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) + typedef unsigned char uint8_t; +# define UINT8_C(v) ((uint8_t) v) +# else +# error "Platform not supported" +# endif +#endif + +#ifndef INT8_MAX +# define INT8_MAX 0x7f +#endif +#ifndef INT8_MIN +# define INT8_MIN INT8_C(0x80) +#endif +#ifndef int8_t +# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) + typedef signed char int8_t; +# define INT8_C(v) ((int8_t) v) +# else +# error "Platform not supported" +# endif +#endif + +#ifndef UINT16_MAX +# define UINT16_MAX 0xffff +#endif +#ifndef uint16_t +#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) + typedef unsigned int uint16_t; +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "" +# endif +# define UINT16_C(v) ((uint16_t) (v)) +#elif (USHRT_MAX == UINT16_MAX) + typedef unsigned short uint16_t; +# define UINT16_C(v) ((uint16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef INT16_MAX +# define INT16_MAX 0x7fff +#endif +#ifndef INT16_MIN +# define INT16_MIN INT16_C(0x8000) +#endif +#ifndef int16_t +#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) + typedef signed int int16_t; +# define INT16_C(v) ((int16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "" +# endif +#elif (SHRT_MAX == INT16_MAX) + typedef signed short int16_t; +# define INT16_C(v) ((int16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef UINT32_MAX +# define UINT32_MAX (0xffffffffUL) +#endif +#ifndef uint32_t +#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) + typedef unsigned long uint32_t; +# define UINT32_C(v) v ## UL +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +#elif (UINT_MAX == UINT32_MAX) + typedef unsigned int uint32_t; +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +# define UINT32_C(v) v ## U +#elif (USHRT_MAX == UINT32_MAX) + typedef unsigned short uint32_t; +# define UINT32_C(v) ((unsigned short) (v)) +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef INT32_MAX +# define INT32_MAX (0x7fffffffL) +#endif +#ifndef INT32_MIN +# define INT32_MIN INT32_C(0x80000000) +#endif +#ifndef int32_t +#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) + typedef signed long int32_t; +# define INT32_C(v) v ## L +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +#elif (INT_MAX == INT32_MAX) + typedef signed int int32_t; +# define INT32_C(v) v +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#elif (SHRT_MAX == INT32_MAX) + typedef signed short int32_t; +# define INT32_C(v) ((short) (v)) +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#else +#error "Platform not supported" +#endif +#endif + +/* + * The macro stdint_int64_defined is temporarily used to record + * whether or not 64 integer support is available. It must be + * defined for any 64 integer extensions for new platforms that are + * added. + */ + +#undef stdint_int64_defined +#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) +# if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S) +# define stdint_int64_defined + typedef long long int64_t; + typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# endif +#endif + +#if !defined (stdint_int64_defined) +# if defined(__GNUC__) +# define stdint_int64_defined + __extension__ typedef long long int64_t; + __extension__ typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) +# define stdint_int64_defined + typedef long long int64_t; + typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) +# define stdint_int64_defined + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; +# define UINT64_C(v) v ## UI64 +# define INT64_C(v) v ## I64 +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "I64" +# endif +# endif +#endif + +#if !defined (LONG_LONG_MAX) && defined (INT64_C) +# define LONG_LONG_MAX INT64_C (9223372036854775807) +#endif +#ifndef ULONG_LONG_MAX +# define ULONG_LONG_MAX UINT64_C (18446744073709551615) +#endif + +#if !defined (INT64_MAX) && defined (INT64_C) +# define INT64_MAX INT64_C (9223372036854775807) +#endif +#if !defined (INT64_MIN) && defined (INT64_C) +# define INT64_MIN INT64_C (-9223372036854775808) +#endif +#if !defined (UINT64_MAX) && defined (INT64_C) +# define UINT64_MAX UINT64_C (18446744073709551615) +#endif + +/* + * Width of hexadecimal for number field. + */ + +#ifndef PRINTF_INT64_HEX_WIDTH +# define PRINTF_INT64_HEX_WIDTH "16" +#endif +#ifndef PRINTF_INT32_HEX_WIDTH +# define PRINTF_INT32_HEX_WIDTH "8" +#endif +#ifndef PRINTF_INT16_HEX_WIDTH +# define PRINTF_INT16_HEX_WIDTH "4" +#endif +#ifndef PRINTF_INT8_HEX_WIDTH +# define PRINTF_INT8_HEX_WIDTH "2" +#endif + +#ifndef PRINTF_INT64_DEC_WIDTH +# define PRINTF_INT64_DEC_WIDTH "20" +#endif +#ifndef PRINTF_INT32_DEC_WIDTH +# define PRINTF_INT32_DEC_WIDTH "10" +#endif +#ifndef PRINTF_INT16_DEC_WIDTH +# define PRINTF_INT16_DEC_WIDTH "5" +#endif +#ifndef PRINTF_INT8_DEC_WIDTH +# define PRINTF_INT8_DEC_WIDTH "3" +#endif + +/* + * Ok, lets not worry about 128 bit integers for now. Moore's law says + * we don't need to worry about that until about 2040 at which point + * we'll have bigger things to worry about. + */ + +#ifdef stdint_int64_defined + typedef int64_t intmax_t; + typedef uint64_t uintmax_t; +# define INTMAX_MAX INT64_MAX +# define INTMAX_MIN INT64_MIN +# define UINTMAX_MAX UINT64_MAX +# define UINTMAX_C(v) UINT64_C(v) +# define INTMAX_C(v) INT64_C(v) +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH +# endif +#else + typedef int32_t intmax_t; + typedef uint32_t uintmax_t; +# define INTMAX_MAX INT32_MAX +# define UINTMAX_MAX UINT32_MAX +# define UINTMAX_C(v) UINT32_C(v) +# define INTMAX_C(v) INT32_C(v) +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH +# endif +#endif + +/* + * Because this file currently only supports platforms which have + * precise powers of 2 as bit sizes for the default integers, the + * least definitions are all trivial. Its possible that a future + * version of this file could have different definitions. + */ + +#ifndef stdint_least_defined + typedef int8_t int_least8_t; + typedef uint8_t uint_least8_t; + typedef int16_t int_least16_t; + typedef uint16_t uint_least16_t; + typedef int32_t int_least32_t; + typedef uint32_t uint_least32_t; +# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER +# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER +# define UINT_LEAST8_MAX UINT8_MAX +# define INT_LEAST8_MAX INT8_MAX +# define UINT_LEAST16_MAX UINT16_MAX +# define INT_LEAST16_MAX INT16_MAX +# define UINT_LEAST32_MAX UINT32_MAX +# define INT_LEAST32_MAX INT32_MAX +# define INT_LEAST8_MIN INT8_MIN +# define INT_LEAST16_MIN INT16_MIN +# define INT_LEAST32_MIN INT32_MIN +# ifdef stdint_int64_defined + typedef int64_t int_least64_t; + typedef uint64_t uint_least64_t; +# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER +# define UINT_LEAST64_MAX UINT64_MAX +# define INT_LEAST64_MAX INT64_MAX +# define INT_LEAST64_MIN INT64_MIN +# endif +#endif +#undef stdint_least_defined + +/* + * The ANSI C committee pretending to know or specify anything about + * performance is the epitome of misguided arrogance. The mandate of + * this file is to *ONLY* ever support that absolute minimum + * definition of the fast integer types, for compatibility purposes. + * No extensions, and no attempt to suggest what may or may not be a + * faster integer type will ever be made in this file. Developers are + * warned to stay away from these types when using this or any other + * stdint.h. + */ + +typedef int_least8_t int_fast8_t; +typedef uint_least8_t uint_fast8_t; +typedef int_least16_t int_fast16_t; +typedef uint_least16_t uint_fast16_t; +typedef int_least32_t int_fast32_t; +typedef uint_least32_t uint_fast32_t; +#define UINT_FAST8_MAX UINT_LEAST8_MAX +#define INT_FAST8_MAX INT_LEAST8_MAX +#define UINT_FAST16_MAX UINT_LEAST16_MAX +#define INT_FAST16_MAX INT_LEAST16_MAX +#define UINT_FAST32_MAX UINT_LEAST32_MAX +#define INT_FAST32_MAX INT_LEAST32_MAX +#define INT_FAST8_MIN INT_LEAST8_MIN +#define INT_FAST16_MIN INT_LEAST16_MIN +#define INT_FAST32_MIN INT_LEAST32_MIN +#ifdef stdint_int64_defined + typedef int_least64_t int_fast64_t; + typedef uint_least64_t uint_fast64_t; +# define UINT_FAST64_MAX UINT_LEAST64_MAX +# define INT_FAST64_MAX INT_LEAST64_MAX +# define INT_FAST64_MIN INT_LEAST64_MIN +#endif + +#undef stdint_int64_defined + +/* + * Whatever piecemeal, per compiler thing we can do about the wchar_t + * type limits. + */ + +#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) +# include +# ifndef WCHAR_MIN +# define WCHAR_MIN 0 +# endif +# ifndef WCHAR_MAX +# define WCHAR_MAX ((wchar_t)-1) +# endif +#endif + +/* + * Whatever piecemeal, per compiler/platform thing we can do about the + * (u)intptr_t types and limits. + */ + +#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED) +# define STDINT_H_UINTPTR_T_DEFINED +#endif + +#ifndef STDINT_H_UINTPTR_T_DEFINED +# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) +# define stdint_intptr_bits 64 +# elif defined (__WATCOMC__) || defined (__TURBOC__) +# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) +# define stdint_intptr_bits 16 +# else +# define stdint_intptr_bits 32 +# endif +# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) +# define stdint_intptr_bits 32 +# elif defined (__INTEL_COMPILER) +/* TODO -- what will Intel do about x86-64? */ +# endif + +# ifdef stdint_intptr_bits +# define stdint_intptr_glue3_i(a,b,c) a##b##c +# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) +# ifndef PRINTF_INTPTR_MODIFIER +# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) +# endif +# ifndef PTRDIFF_MAX +# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) +# endif +# ifndef PTRDIFF_MIN +# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) +# endif +# ifndef UINTPTR_MAX +# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) +# endif +# ifndef INTPTR_MAX +# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) +# endif +# ifndef INTPTR_MIN +# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) +# endif +# ifndef INTPTR_C +# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) +# endif +# ifndef UINTPTR_C +# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) +# endif + typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; + typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; +# else +/* TODO -- This following is likely wrong for some platforms, and does + nothing for the definition of uintptr_t. */ + typedef ptrdiff_t intptr_t; +# endif +# define STDINT_H_UINTPTR_T_DEFINED +#endif + +/* + * Assumes sig_atomic_t is signed and we have a 2s complement machine. + */ + +#ifndef SIG_ATOMIC_MAX +# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) +#endif + +#endif + diff --git a/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h b/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h index ad6940253..53aa2b844 100644 --- a/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h +++ b/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h @@ -1,92 +1,92 @@ -/* -Open Asset Import Library (assimp) ----------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp team -All rights reserved. - -Redistribution and use of this software 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 the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -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. - ----------------------------------------------------------------------- -*/ - -/** @file Android implementation of IOSystem using the standard C file functions. - * Aimed to ease the acces to android assets */ - -#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) -#ifndef AI_ANDROIDJNIIOSYSTEM_H_INC -#define AI_ANDROIDJNIIOSYSTEM_H_INC - -#include "../code/DefaultIOSystem.h" -#include -#include -#include - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** Android extension to DefaultIOSystem using the standard C file functions */ -class AndroidJNIIOSystem : public DefaultIOSystem -{ -public: - - /** Initialize android activity data */ - std::string mApkWorkspacePath; - AAssetManager* mApkAssetManager; - - /** Constructor. */ - AndroidJNIIOSystem(ANativeActivity* activity); - - /** Destructor. */ - ~AndroidJNIIOSystem(); - - // ------------------------------------------------------------------- - /** Tests for the existence of a file at the given path. */ - bool Exists( const char* pFile) const; - - // ------------------------------------------------------------------- - /** Opens a file at the given path, with given mode */ - IOStream* Open( const char* strFile, const char* strMode); - - // ------------------------------------------------------------------------------------------------ - // Inits Android extractor - void AndroidActivityInit(ANativeActivity* activity); - - // ------------------------------------------------------------------------------------------------ - // Extracts android asset - bool AndroidExtractAsset(std::string name); - -}; - -} //!ns Assimp - -#endif //AI_ANDROIDJNIIOSYSTEM_H_INC -#endif //__ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp team +All rights reserved. + +Redistribution and use of this software 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 the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +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. + +---------------------------------------------------------------------- +*/ + +/** @file Android implementation of IOSystem using the standard C file functions. + * Aimed to ease the acces to android assets */ + +#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) +#ifndef AI_ANDROIDJNIIOSYSTEM_H_INC +#define AI_ANDROIDJNIIOSYSTEM_H_INC + +#include "../code/DefaultIOSystem.h" +#include +#include +#include + +namespace Assimp { + +// --------------------------------------------------------------------------- +/** Android extension to DefaultIOSystem using the standard C file functions */ +class AndroidJNIIOSystem : public DefaultIOSystem +{ +public: + + /** Initialize android activity data */ + std::string mApkWorkspacePath; + AAssetManager* mApkAssetManager; + + /** Constructor. */ + AndroidJNIIOSystem(ANativeActivity* activity); + + /** Destructor. */ + ~AndroidJNIIOSystem(); + + // ------------------------------------------------------------------- + /** Tests for the existence of a file at the given path. */ + bool Exists( const char* pFile) const; + + // ------------------------------------------------------------------- + /** Opens a file at the given path, with given mode */ + IOStream* Open( const char* strFile, const char* strMode); + + // ------------------------------------------------------------------------------------------------ + // Inits Android extractor + void AndroidActivityInit(ANativeActivity* activity); + + // ------------------------------------------------------------------------------------------------ + // Extracts android asset + bool AndroidExtractAsset(std::string name); + +}; + +} //!ns Assimp + +#endif //AI_ANDROIDJNIIOSYSTEM_H_INC +#endif //__ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) diff --git a/packaging/windows-innosetup/howto-build-setup.txt b/packaging/windows-innosetup/howto-build-setup.txt index 4b16eb4ef..d089c0cb4 100644 --- a/packaging/windows-innosetup/howto-build-setup.txt +++ b/packaging/windows-innosetup/howto-build-setup.txt @@ -1,16 +1,16 @@ - -How to build the Assimp installer using Inno Setup - - -1) Get MS VC 2008 SP1 redist packages for x86 and amd64 and copy 'em right here. - -vcredist_x86.exe -vcredist_x64.exe - -2) Get D3DCompiler_NN.dll and D3DX9_NN.dll from a) your system32 folder and b) your SysWOW64 folder. Copy all 4 here. Rename the 64 bit files to _x64.dll. NN is the D3DX version targeted by your DX SDK. If it is not 42, you need to update the Inno setup script (script.iss) as well. If you don't have a 64 bit Windows, get the DLLs from somebody else. Please don't ask google because many DLL downloads are infected. - -3) Build assimp, assimpcmd and assimpview for the 'release-dll' target and both the Win32 and x64 architectures. - -4) Get Inno Setup -5) Compile, output is written to the 'out' folder. - + +How to build the Assimp installer using Inno Setup + + +1) Get MS VC 2008 SP1 redist packages for x86 and amd64 and copy 'em right here. + +vcredist_x86.exe +vcredist_x64.exe + +2) Get D3DCompiler_NN.dll and D3DX9_NN.dll from a) your system32 folder and b) your SysWOW64 folder. Copy all 4 here. Rename the 64 bit files to _x64.dll. NN is the D3DX version targeted by your DX SDK. If it is not 42, you need to update the Inno setup script (script.iss) as well. If you don't have a 64 bit Windows, get the DLLs from somebody else. Please don't ask google because many DLL downloads are infected. + +3) Build assimp, assimpcmd and assimpview for the 'release-dll' target and both the Win32 and x64 architectures. + +4) Get Inno Setup +5) Compile, output is written to the 'out' folder. + diff --git a/packaging/windows-innosetup/readme_installer.txt b/packaging/windows-innosetup/readme_installer.txt index 397fae3dc..6ea969dc1 100644 --- a/packaging/windows-innosetup/readme_installer.txt +++ b/packaging/windows-innosetup/readme_installer.txt @@ -1,23 +1,23 @@ - ------------------------------------------------------------------------------------- -Open Asset Import Library (Assimp) SDK Installer -Release Notes ------------------------------------------------------------------------------------- - -http://assimp.sf.net - - -Troubleshooting -=============== - -1. Missing d3dx9_(some-number).dll? -Install the latest DirectX runtime or grab the file from somewhere (that's evil but mostly fine). - -2. Application configuration not correct / missing msvcr***.dll? -Reinstall Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) - -3. assimp.exe not in PATH -Add it to PATH. That's not a bug, the installer does not alter the PATH. - -4. Crashes immediately -You CPU lacks SSE2 support. Build Assimp from scratch to suit your CPU, sorry. + +------------------------------------------------------------------------------------ +Open Asset Import Library (Assimp) SDK Installer +Release Notes +------------------------------------------------------------------------------------ + +http://assimp.sf.net + + +Troubleshooting +=============== + +1. Missing d3dx9_(some-number).dll? +Install the latest DirectX runtime or grab the file from somewhere (that's evil but mostly fine). + +2. Application configuration not correct / missing msvcr***.dll? +Reinstall Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) + +3. assimp.exe not in PATH +Add it to PATH. That's not a bug, the installer does not alter the PATH. + +4. Crashes immediately +You CPU lacks SSE2 support. Build Assimp from scratch to suit your CPU, sorry. diff --git a/packaging/windows-innosetup/readme_installer_vieweronly.txt b/packaging/windows-innosetup/readme_installer_vieweronly.txt index c1ff3716a..bfa4f8c9e 100644 --- a/packaging/windows-innosetup/readme_installer_vieweronly.txt +++ b/packaging/windows-innosetup/readme_installer_vieweronly.txt @@ -1,32 +1,32 @@ - ------------------------------------------------------------------------------------- -Open Asset Import Library (Assimp) Viewer Installer -Release Notes ------------------------------------------------------------------------------------- - -http://assimp.sf.net - -Known Bugs & Limitations -======================== - -Viewer - -- Normals appear flipped from time to time when either of the normals-related menu items was hit. -- Alpha-sorting is implemented, but still causes artifacts when models are moved quickly. -- Several important texture file formats (such as GIF) are not supported. -- HUD is blurred on the right side. ATI/AMD hardware only. - -Troubleshooting -=============== - -1. Missing d3dx9_(number).dll? -Install the latest DirectX runtime or grab the file from somewhere (that's evil but mostly fine). - -2. Application configuration not correct / missing msvcr***.dll? -Reinstall Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) - -3. assimp.exe not in PATH -Add it to PATH. That's not a bug, the installer does not alter the PATH. - -4. Crashes immediately + +------------------------------------------------------------------------------------ +Open Asset Import Library (Assimp) Viewer Installer +Release Notes +------------------------------------------------------------------------------------ + +http://assimp.sf.net + +Known Bugs & Limitations +======================== + +Viewer + +- Normals appear flipped from time to time when either of the normals-related menu items was hit. +- Alpha-sorting is implemented, but still causes artifacts when models are moved quickly. +- Several important texture file formats (such as GIF) are not supported. +- HUD is blurred on the right side. ATI/AMD hardware only. + +Troubleshooting +=============== + +1. Missing d3dx9_(number).dll? +Install the latest DirectX runtime or grab the file from somewhere (that's evil but mostly fine). + +2. Application configuration not correct / missing msvcr***.dll? +Reinstall Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) + +3. assimp.exe not in PATH +Add it to PATH. That's not a bug, the installer does not alter the PATH. + +4. Crashes immediately You CPU lacks SSE2 support. Build Assimp from scratch to suit your CPU, sorry. \ No newline at end of file diff --git a/packaging/windows-mkzip/bin_readme.txt b/packaging/windows-mkzip/bin_readme.txt index 3b185cfed..10839a3d9 100644 --- a/packaging/windows-mkzip/bin_readme.txt +++ b/packaging/windows-mkzip/bin_readme.txt @@ -1,29 +1,29 @@ - ------------------------------------------------------------------------------------- -Open Asset Import Library (Assimp) Tools/Binaries for Windows -Release Notes ------------------------------------------------------------------------------------- - - -Known Bugs & Limitations -======================== - -Viewer - -- For files more than one embedded texture, only the first is loaded. -- Normals appear flipped from time to time when either of the normals-related menu items was hit. -- Alpha-sorting is implemented, but still causes artifacts when models are moved quickly. -- Several important texture file formats (such as GIF) are not supported. -- HUD is blurred on the right side. ATI/AMD hardware only. - -Troubleshooting -=============== - -1. Missing d3dx9_42.dll? -Install the latest DirectX runtime or grab the file from somewhere (that's evil but mostly fine). - -2. Application configuration not correct / missing msv*** DLLs? -(Re)install Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) - -3. Crashes immediately + +------------------------------------------------------------------------------------ +Open Asset Import Library (Assimp) Tools/Binaries for Windows +Release Notes +------------------------------------------------------------------------------------ + + +Known Bugs & Limitations +======================== + +Viewer + +- For files more than one embedded texture, only the first is loaded. +- Normals appear flipped from time to time when either of the normals-related menu items was hit. +- Alpha-sorting is implemented, but still causes artifacts when models are moved quickly. +- Several important texture file formats (such as GIF) are not supported. +- HUD is blurred on the right side. ATI/AMD hardware only. + +Troubleshooting +=============== + +1. Missing d3dx9_42.dll? +Install the latest DirectX runtime or grab the file from somewhere (that's evil but mostly fine). + +2. Application configuration not correct / missing msv*** DLLs? +(Re)install Microsoft Visual C++ 2005 SP1 Redistributable (x86 or x64, depending on your system) + +3. Crashes immediately You CPU lacks SSE2 support. Build Assimp from scratch to suit your CPU, sorry. \ No newline at end of file diff --git a/port/AndroidJNI/AndroidJNIIOSystem.cpp b/port/AndroidJNI/AndroidJNIIOSystem.cpp index 4a149e050..f9ba94cb1 100644 --- a/port/AndroidJNI/AndroidJNIIOSystem.cpp +++ b/port/AndroidJNI/AndroidJNIIOSystem.cpp @@ -1,175 +1,175 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2012, assimp team - -All rights reserved. - -Redistribution and use of this software 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 the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -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. ---------------------------------------------------------------------------- -*/ - -/** @file Android extension of DefaultIOSystem using the standard C file functions */ - - -#include -#include -#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor. -AndroidJNIIOSystem::AndroidJNIIOSystem(ANativeActivity* activity) -{ - AndroidActivityInit(activity); -} - -// ------------------------------------------------------------------------------------------------ -// Destructor. -AndroidJNIIOSystem::~AndroidJNIIOSystem() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Tests for the existence of a file at the given path. -bool AndroidJNIIOSystem::Exists( const char* pFile) const -{ - AAsset* asset = AAssetManager_open(mApkAssetManager, pFile, - AASSET_MODE_UNKNOWN); - FILE* file = ::fopen( (mApkWorkspacePath + getOsSeparator() + std::string(pFile)).c_str(), "rb"); - - if (!asset && !file) - { - __android_log_print(ANDROID_LOG_ERROR, "Assimp", "Asset manager can not find: %s", pFile); - return false; - } - - __android_log_print(ANDROID_LOG_ERROR, "Assimp", "Asset exists"); - if (file) - ::fclose( file); - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Inits Android extractor -void AndroidJNIIOSystem::AndroidActivityInit(ANativeActivity* activity) -{ - mApkWorkspacePath = activity->internalDataPath; - mApkAssetManager = activity->assetManager; -} - -// ------------------------------------------------------------------------------------------------ -// Extracts android asset -bool AndroidJNIIOSystem::AndroidExtractAsset(std::string name) -{ - std::string newPath = mApkWorkspacePath + getOsSeparator() + name; - - DefaultIOSystem io; - - // Do not extract if extracted already - if ( io.Exists(newPath.c_str()) ) { - __android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset already extracted"); - return true; - } - // Open file - AAsset* asset = AAssetManager_open(mApkAssetManager, name.c_str(), - AASSET_MODE_UNKNOWN); - std::vector assetContent; - - if (asset != NULL) { - // Find size - off_t assetSize = AAsset_getLength(asset); - - // Prepare input buffer - assetContent.resize(assetSize); - - // Store input buffer - AAsset_read(asset, &assetContent[0], assetSize); - - // Close - AAsset_close(asset); - - // Prepare output buffer - std::ofstream assetExtracted(newPath.c_str(), - std::ios::out | std::ios::binary); - if (!assetExtracted) { - __android_log_print(ANDROID_LOG_ERROR, "assimp", - "Can not open output file"); - } - - // Write output buffer into a file - assetExtracted.write(&assetContent[0], assetContent.size()); - assetExtracted.close(); - - __android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset extracted"); - } else { - __android_log_print(ANDROID_LOG_ERROR, "assimp", "Asset not found: %s", name.c_str()); - return false; - } - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Open a new file with a given path. -IOStream* AndroidJNIIOSystem::Open( const char* strFile, const char* strMode) -{ - ai_assert(NULL != strFile); - ai_assert(NULL != strMode); - - std::string fullPath(mApkWorkspacePath + getOsSeparator() + std::string(strFile)); - if (Exists(strFile)) - AndroidExtractAsset(std::string(strFile)); - - FILE* file = ::fopen( fullPath.c_str(), strMode); - - if( NULL == file) - return NULL; - - __android_log_print(ANDROID_LOG_ERROR, "assimp", "AndroidIOSystem: file %s opened", fullPath.c_str()); - return new DefaultIOStream(file, fullPath); -} - -#undef PATHLIMIT -#endif // __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp team + +All rights reserved. + +Redistribution and use of this software 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 the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +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. +--------------------------------------------------------------------------- +*/ + +/** @file Android extension of DefaultIOSystem using the standard C file functions */ + + +#include +#include +#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Assimp; + +// ------------------------------------------------------------------------------------------------ +// Constructor. +AndroidJNIIOSystem::AndroidJNIIOSystem(ANativeActivity* activity) +{ + AndroidActivityInit(activity); +} + +// ------------------------------------------------------------------------------------------------ +// Destructor. +AndroidJNIIOSystem::~AndroidJNIIOSystem() +{ + // nothing to do here +} + +// ------------------------------------------------------------------------------------------------ +// Tests for the existence of a file at the given path. +bool AndroidJNIIOSystem::Exists( const char* pFile) const +{ + AAsset* asset = AAssetManager_open(mApkAssetManager, pFile, + AASSET_MODE_UNKNOWN); + FILE* file = ::fopen( (mApkWorkspacePath + getOsSeparator() + std::string(pFile)).c_str(), "rb"); + + if (!asset && !file) + { + __android_log_print(ANDROID_LOG_ERROR, "Assimp", "Asset manager can not find: %s", pFile); + return false; + } + + __android_log_print(ANDROID_LOG_ERROR, "Assimp", "Asset exists"); + if (file) + ::fclose( file); + return true; +} + +// ------------------------------------------------------------------------------------------------ +// Inits Android extractor +void AndroidJNIIOSystem::AndroidActivityInit(ANativeActivity* activity) +{ + mApkWorkspacePath = activity->internalDataPath; + mApkAssetManager = activity->assetManager; +} + +// ------------------------------------------------------------------------------------------------ +// Extracts android asset +bool AndroidJNIIOSystem::AndroidExtractAsset(std::string name) +{ + std::string newPath = mApkWorkspacePath + getOsSeparator() + name; + + DefaultIOSystem io; + + // Do not extract if extracted already + if ( io.Exists(newPath.c_str()) ) { + __android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset already extracted"); + return true; + } + // Open file + AAsset* asset = AAssetManager_open(mApkAssetManager, name.c_str(), + AASSET_MODE_UNKNOWN); + std::vector assetContent; + + if (asset != NULL) { + // Find size + off_t assetSize = AAsset_getLength(asset); + + // Prepare input buffer + assetContent.resize(assetSize); + + // Store input buffer + AAsset_read(asset, &assetContent[0], assetSize); + + // Close + AAsset_close(asset); + + // Prepare output buffer + std::ofstream assetExtracted(newPath.c_str(), + std::ios::out | std::ios::binary); + if (!assetExtracted) { + __android_log_print(ANDROID_LOG_ERROR, "assimp", + "Can not open output file"); + } + + // Write output buffer into a file + assetExtracted.write(&assetContent[0], assetContent.size()); + assetExtracted.close(); + + __android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset extracted"); + } else { + __android_log_print(ANDROID_LOG_ERROR, "assimp", "Asset not found: %s", name.c_str()); + return false; + } + return true; +} + +// ------------------------------------------------------------------------------------------------ +// Open a new file with a given path. +IOStream* AndroidJNIIOSystem::Open( const char* strFile, const char* strMode) +{ + ai_assert(NULL != strFile); + ai_assert(NULL != strMode); + + std::string fullPath(mApkWorkspacePath + getOsSeparator() + std::string(strFile)); + if (Exists(strFile)) + AndroidExtractAsset(std::string(strFile)); + + FILE* file = ::fopen( fullPath.c_str(), strMode); + + if( NULL == file) + return NULL; + + __android_log_print(ANDROID_LOG_ERROR, "assimp", "AndroidIOSystem: file %s opened", fullPath.c_str()); + return new DefaultIOStream(file, fullPath); +} + +#undef PATHLIMIT +#endif // __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) diff --git a/port/AssimpDelphi/Readme.txt b/port/AssimpDelphi/Readme.txt index c9aed7b0f..07d6935ae 100644 --- a/port/AssimpDelphi/Readme.txt +++ b/port/AssimpDelphi/Readme.txt @@ -1,6 +1,6 @@ -This is a set of Delphi units for using the Assimp C DLL. This was created for use with Delphi 7, but should be usable as-is or with minimal modifications with later Delphi versions. - -This set of headers is enough to load and display a model with external textures. Since I'm not familiar with animated models and some of the other functionality of the assimp library, I did not convert the headers for those features. - -See http://sourceforge.net/tracker/?func=detail&aid=3212646&group_id=226462&atid=1067634 for the original patch - +This is a set of Delphi units for using the Assimp C DLL. This was created for use with Delphi 7, but should be usable as-is or with minimal modifications with later Delphi versions. + +This set of headers is enough to load and display a model with external textures. Since I'm not familiar with animated models and some of the other functionality of the assimp library, I did not convert the headers for those features. + +See http://sourceforge.net/tracker/?func=detail&aid=3212646&group_id=226462&atid=1067634 for the original patch + diff --git a/samples/DevIL/include/IL/ilut_config.h b/samples/DevIL/include/IL/ilut_config.h index a05da54c1..2b3625b86 100644 --- a/samples/DevIL/include/IL/ilut_config.h +++ b/samples/DevIL/include/IL/ilut_config.h @@ -1,26 +1,26 @@ -#ifndef __ILUT_CONFIG_H__ -#define __ILUT_CONFIG_H__ - -#define IL_USE_PRAGMA_LIBS - -// Supported APIs (ILUT) - -// -// sorry just -// cant get this one to work under windows -// have disabled for the now -// -// will look at it some more later -// -// Kriss -// -#undef ILUT_USE_ALLEGRO - -#undef ILUT_USE_DIRECTX8 -//#define ILUT_USE_DIRECTX9 -//#define ILUT_USE_DIRECTX10 -#define ILUT_USE_OPENGL -//#define ILUT_USE_SDL -#define ILUT_USE_WIN32 - -#endif//__ILUT_CONFIG_H__ +#ifndef __ILUT_CONFIG_H__ +#define __ILUT_CONFIG_H__ + +#define IL_USE_PRAGMA_LIBS + +// Supported APIs (ILUT) + +// +// sorry just +// cant get this one to work under windows +// have disabled for the now +// +// will look at it some more later +// +// Kriss +// +#undef ILUT_USE_ALLEGRO + +#undef ILUT_USE_DIRECTX8 +//#define ILUT_USE_DIRECTX9 +//#define ILUT_USE_DIRECTX10 +#define ILUT_USE_OPENGL +//#define ILUT_USE_SDL +#define ILUT_USE_WIN32 + +#endif//__ILUT_CONFIG_H__ diff --git a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp index 2787fad52..bac800152 100644 --- a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp +++ b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp @@ -1,882 +1,882 @@ -// ---------------------------------------------------------------------------- -// Another Assimp OpenGL sample including texturing. -// Note that it is very basic and will only read and apply the model's diffuse -// textures (by their material ids) -// -// Don't worry about the "Couldn't load Image: ...dwarf2.jpg" Message. -// It's caused by a bad texture reference in the model file (I guess) -// -// If you intend to _use_ this code sample in your app, do yourself a favour -// and replace immediate mode calls with VBOs ... -// -// Thanks to NeHe on whose OpenGL tutorials this one's based on! :) -// http://nehe.gamedev.net/ -// ---------------------------------------------------------------------------- -#include -#include -#include -#include -#include - -#include - -//to map image filenames to textureIds -#include -#include - - -// assimp include files. These three are usually needed. -#include "assimp/Importer.hpp" //OO version Header! -#include "assimp/postprocess.h" -#include "assimp/scene.h" -#include "assimp/DefaultLogger.hpp" -#include "assimp/LogStream.hpp" - - -// The default hard-coded path. Can be overridden by supplying a path through the command line. -static std::string modelpath = "../../test/models/OBJ/spider.obj"; - - -HGLRC hRC=NULL; // Permanent Rendering Context -HDC hDC=NULL; // Private GDI Device Context -HWND hWnd=NULL; // Holds Window Handle -HINSTANCE hInstance; // Holds The Instance Of The Application - -bool keys[256]; // Array used for Keyboard Routine; -bool active=TRUE; // Window Active Flag Set To TRUE by Default -bool fullscreen=TRUE; // full-screen Flag Set To full-screen By Default - -GLfloat xrot; -GLfloat yrot; -GLfloat zrot; - - -LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc -GLboolean abortGLInit(const char*); - -const char* windowTitle = "OpenGL Framework"; - -GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; -GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; -GLfloat LightPosition[]= { 0.0f, 0.0f, 15.0f, 1.0f }; - - - -// the global Assimp scene object -const aiScene* scene = NULL; -GLuint scene_list = 0; -aiVector3D scene_min, scene_max, scene_center; - -// images / texture -std::map textureIdMap; // map image filenames to textureIds -GLuint* textureIds; // pointer to texture Array - -// Create an instance of the Importer class -Assimp::Importer importer; - - -void createAILogger() -{ - // Change this line to normal if you not want to analyse the import process - //Assimp::Logger::LogSeverity severity = Assimp::Logger::NORMAL; - Assimp::Logger::LogSeverity severity = Assimp::Logger::VERBOSE; - - // Create a logger instance for Console Output - Assimp::DefaultLogger::create("",severity, aiDefaultLogStream_STDOUT); - - // Create a logger instance for File Output (found in project folder or near .exe) - Assimp::DefaultLogger::create("assimp_log.txt",severity, aiDefaultLogStream_FILE); - - // Now I am ready for logging my stuff - Assimp::DefaultLogger::get()->info("this is my info-call"); -} - -void destroyAILogger() -{ - // Kill it after the work is done - Assimp::DefaultLogger::kill(); -} - -void logInfo(std::string logString) -{ - // Will add message to File with "info" Tag - Assimp::DefaultLogger::get()->info(logString.c_str()); -} - -void logDebug(const char* logString) -{ - // Will add message to File with "debug" Tag - Assimp::DefaultLogger::get()->debug(logString); -} - - -bool Import3DFromFile( const std::string& pFile) -{ - // Check if file exists - std::ifstream fin(pFile.c_str()); - if(!fin.fail()) - { - fin.close(); - } - else - { - MessageBox(NULL, ("Couldn't open file: " + pFile).c_str() , "ERROR", MB_OK | MB_ICONEXCLAMATION); - logInfo( importer.GetErrorString()); - return false; - } - - scene = importer.ReadFile( pFile, aiProcessPreset_TargetRealtime_Quality); - - // If the import failed, report it - if( !scene) - { - logInfo( importer.GetErrorString()); - return false; - } - - // Now we can access the file's contents. - logInfo("Import of scene " + pFile + " succeeded."); - - // We're done. Everything will be cleaned up by the importer destructor - return true; -} - -// Resize And Initialize The GL Window -void ReSizeGLScene(GLsizei width, GLsizei height) -{ - // Prevent A Divide By Zero By - if (height==0) - { - // Making Height Equal One - height=1; - } - - glViewport(0, 0, width, height); // Reset The Current Viewport - - glMatrixMode(GL_PROJECTION); // Select The Projection Matrix - glLoadIdentity(); // Reset The Projection Matrix - - // Calculate The Aspect Ratio Of The Window - gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); - - glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix - glLoadIdentity(); // Reset The Modelview Matrix -} - - -std::string getBasePath(const std::string& path) -{ - size_t pos = path.find_last_of("\\/"); - return (std::string::npos == pos) ? "" : path.substr(0, pos + 1); -} - -int LoadGLTextures(const aiScene* scene) -{ - ILboolean success; - - /* Before calling ilInit() version should be checked. */ - if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION) - { - /// wrong DevIL version /// - std::string err_msg = "Wrong DevIL version. Old devil.dll in system32/SysWow64?"; - char* cErr_msg = (char *) err_msg.c_str(); - abortGLInit(cErr_msg); - return -1; - } - - ilInit(); /* Initialization of DevIL */ - - if (scene->HasTextures()) abortGLInit("Support for meshes with embedded textures is not implemented"); - - /* getTexture Filenames and Numb of Textures */ - for (unsigned int m=0; mmNumMaterials; m++) - { - int texIndex = 0; - aiReturn texFound = AI_SUCCESS; - - aiString path; // filename - - while (texFound == AI_SUCCESS) - { - texFound = scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path); - textureIdMap[path.data] = NULL; //fill map with textures, pointers still NULL yet - texIndex++; - } - } - - int numTextures = textureIdMap.size(); - - /* array with DevIL image IDs */ - ILuint* imageIds = NULL; - imageIds = new ILuint[numTextures]; - - /* generate DevIL Image IDs */ - ilGenImages(numTextures, imageIds); /* Generation of numTextures image names */ - - /* create and fill array with GL texture ids */ - textureIds = new GLuint[numTextures]; - glGenTextures(numTextures, textureIds); /* Texture name generation */ - - /* get iterator */ - std::map::iterator itr = textureIdMap.begin(); - - std::string basepath = getBasePath(modelpath); - for (int i=0; ir, color->g, color->b, color->a); -} - -void set_float4(float f[4], float a, float b, float c, float d) -{ - f[0] = a; - f[1] = b; - f[2] = c; - f[3] = d; -} - -void color4_to_float4(const aiColor4D *c, float f[4]) -{ - f[0] = c->r; - f[1] = c->g; - f[2] = c->b; - f[3] = c->a; -} - -void apply_material(const aiMaterial *mtl) -{ - float c[4]; - - GLenum fill_mode; - int ret1, ret2; - aiColor4D diffuse; - aiColor4D specular; - aiColor4D ambient; - aiColor4D emission; - float shininess, strength; - int two_sided; - int wireframe; - unsigned int max; // changed: to unsigned - - int texIndex = 0; - aiString texPath; //contains filename of texture - - if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath)) - { - //bind texture - unsigned int texId = *textureIdMap[texPath.data]; - glBindTexture(GL_TEXTURE_2D, texId); - } - - set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f); - if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse)) - color4_to_float4(&diffuse, c); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c); - - set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); - if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular)) - color4_to_float4(&specular, c); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); - - set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f); - if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient)) - color4_to_float4(&ambient, c); - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c); - - set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); - if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission)) - color4_to_float4(&emission, c); - glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c); - - max = 1; - ret1 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max); - max = 1; - ret2 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS_STRENGTH, &strength, &max); - if((ret1 == AI_SUCCESS) && (ret2 == AI_SUCCESS)) - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength); - else { - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f); - set_float4(c, 0.0f, 0.0f, 0.0f, 0.0f); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); - } - - max = 1; - if(AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, &max)) - fill_mode = wireframe ? GL_LINE : GL_FILL; - else - fill_mode = GL_FILL; - glPolygonMode(GL_FRONT_AND_BACK, fill_mode); - - max = 1; - if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided) - glEnable(GL_CULL_FACE); - else - glDisable(GL_CULL_FACE); -} - - -void recursive_render (const struct aiScene *sc, const struct aiNode* nd, float scale) -{ - unsigned int i; - unsigned int n=0, t; - aiMatrix4x4 m = nd->mTransformation; - - aiMatrix4x4 m2; - aiMatrix4x4::Scaling(aiVector3D(scale, scale, scale), m2); - m = m * m2; - - // update transform - m.Transpose(); - glPushMatrix(); - glMultMatrixf((float*)&m); - - // draw all meshes assigned to this node - for (; n < nd->mNumMeshes; ++n) - { - const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]]; - - apply_material(sc->mMaterials[mesh->mMaterialIndex]); - - - if(mesh->mNormals == NULL) - { - glDisable(GL_LIGHTING); - } - else - { - glEnable(GL_LIGHTING); - } - - if(mesh->mColors[0] != NULL) - { - glEnable(GL_COLOR_MATERIAL); - } - else - { - glDisable(GL_COLOR_MATERIAL); - } - - for (t = 0; t < mesh->mNumFaces; ++t) { - const struct aiFace* face = &mesh->mFaces[t]; - GLenum face_mode; - - switch(face->mNumIndices) - { - case 1: face_mode = GL_POINTS; break; - case 2: face_mode = GL_LINES; break; - case 3: face_mode = GL_TRIANGLES; break; - default: face_mode = GL_POLYGON; break; - } - - glBegin(face_mode); - - for(i = 0; i < face->mNumIndices; i++) // go through all vertices in face - { - int vertexIndex = face->mIndices[i]; // get group index for current index - if(mesh->mColors[0] != NULL) - Color4f(&mesh->mColors[0][vertexIndex]); - if(mesh->mNormals != NULL) - - if(mesh->HasTextureCoords(0)) //HasTextureCoords(texture_coordinates_set) - { - glTexCoord2f(mesh->mTextureCoords[0][vertexIndex].x, 1 - mesh->mTextureCoords[0][vertexIndex].y); //mTextureCoords[channel][vertex] - } - - glNormal3fv(&mesh->mNormals[vertexIndex].x); - glVertex3fv(&mesh->mVertices[vertexIndex].x); - } - glEnd(); - } - } - - // draw all children - for (n = 0; n < nd->mNumChildren; ++n) - { - recursive_render(sc, nd->mChildren[n], scale); - } - - glPopMatrix(); -} - - -void drawAiScene(const aiScene* scene) -{ - logInfo("drawing objects"); - - recursive_render(scene, scene->mRootNode, 0.5); - -} - -int DrawGLScene() //Here's where we do all the drawing -{ - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer - glLoadIdentity(); // Reset MV Matrix - - - glTranslatef(0.0f, -10.0f, -40.0f); // Move 40 Units And Into The Screen - - - glRotatef(xrot, 1.0f, 0.0f, 0.0f); - glRotatef(yrot, 0.0f, 1.0f, 0.0f); - glRotatef(zrot, 0.0f, 0.0f, 1.0f); - - drawAiScene(scene); - - //xrot+=0.3f; - yrot+=0.2f; - //zrot+=0.4f; - - return TRUE; // okay -} - - -void KillGLWindow() // Properly Kill The Window -{ - if (fullscreen) // Are We In Fullscreen Mode? - { - ChangeDisplaySettings(NULL, 0); // If So Switch Back To The Desktop - ShowCursor(TRUE); // Show Mouse Pointer - } - - if (hRC) // Do We Have A Rendering Context? - { - if (!wglMakeCurrent(NULL, NULL)) // Are We Able To Release The DC And RC Contexts? - { - MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - } - - if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC? - { - MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - } - hRC = NULL; - } - - if (hDC && !ReleaseDC(hWnd, hDC)) // Are We able to Release The DC? - { - MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - hDC=NULL; - } - - if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window - { - MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - hWnd = NULL; - } - - if (!UnregisterClass("OpenGL", hInstance)) // Are We Able To Unregister Class - { - MessageBox(NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); - hInstance = NULL; - } -} - -GLboolean abortGLInit(const char* abortMessage) -{ - KillGLWindow(); // Reset Display - MessageBox(NULL, abortMessage, "ERROR", MB_OK|MB_ICONEXCLAMATION); - return FALSE; // quit and return False -} - -BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool fullscreenflag) -{ - GLuint PixelFormat; // Hold the result after searching for a match - WNDCLASS wc; // Window Class Structure - DWORD dwExStyle; // Window Extended Style - DWORD dwStyle; // Window Style - RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values - WindowRect.left = (long)0; - WindowRect.right = (long)width; - WindowRect.top = (long)0; - WindowRect.bottom = (long)height; - - fullscreen = fullscreenflag; - - hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window - wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window - wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc handles Messages - wc.cbClsExtra = 0; // No Extra Window Data - wc.cbWndExtra = 0; // No Extra Window Data - wc.hInstance = hInstance; - wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon - wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load the default arrow - wc.hbrBackground= NULL; // No Background required for OpenGL - wc.lpszMenuName = NULL; // No Menu - wc.lpszClassName= "OpenGL"; // Class Name - - if (!RegisterClass(&wc)) - { - MessageBox(NULL, "Failed to register the window class", "ERROR", MB_OK | MB_ICONEXCLAMATION); - return FALSE; //exit and return false - } - - if (fullscreen) // attempt fullscreen mode - { - DEVMODE dmScreenSettings; // Device Mode - memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make Sure Memory's Cleared - dmScreenSettings.dmSize = sizeof(dmScreenSettings); // Size Of the devmode structure - dmScreenSettings.dmPelsWidth = width; // Selected Screen Width - dmScreenSettings.dmPelsHeight = height; // Selected Screen Height - dmScreenSettings.dmBitsPerPel = bits; // bits per pixel - dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; - - // Try To Set Selected Mode and Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. - if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) - { - // If The Mode Fails, Offer Two Options. Quit Or Run In A Window. - if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) - { - fullscreen = FALSE; // Select Windowed Mode (Fullscreen = FALSE) - } - else - { - //Popup Messagebox: Closing - MessageBox(NULL, "Program will close now.", "ERROR", MB_OK|MB_ICONSTOP); - return FALSE; //exit, return false - } - } - } - - if (fullscreen) // when mode really succeeded - { - dwExStyle=WS_EX_APPWINDOW; // Window Extended Style - dwStyle=WS_POPUP; - ShowCursor(FALSE); - } - else - { - dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window extended style - dwStyle=WS_OVERLAPPEDWINDOW; // Windows style - } - - AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requestes Size - - if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window - "OpenGL", // Class Name - title, // Window Title - WS_CLIPSIBLINGS | // Required Window Style - WS_CLIPCHILDREN | // Required Window Style - dwStyle, // Selected WIndow Style - 0, 0, // Window Position - WindowRect.right-WindowRect.left, // Calc adjusted Window Width - WindowRect.bottom-WindowRect.top, // Calc adjustes Window Height - NULL, // No Parent Window - NULL, // No Menu - hInstance, // Instance - NULL ))) // Don't pass anything To WM_CREATE - { - abortGLInit("Window Creation Error."); - return FALSE; - } - - static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be - { - sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor - 1, // Version Number - PFD_DRAW_TO_WINDOW | // Format Must Support Window - PFD_SUPPORT_OPENGL | // Format Must Support OpenGL - PFD_DOUBLEBUFFER, // Must Support Double Buffering - PFD_TYPE_RGBA, // Request An RGBA Format - bits, // Select Our Color Depth - 0, 0, 0, 0, 0, 0, // Color Bits Ignored - 0, // No Alpha Buffer - 0, // Shift Bit Ignored - 0, // No Accumulation Buffer - 0, 0, 0, 0, // Accumulation Bits Ignored - 16, // 16Bit Z-Buffer (Depth Buffer) - 0, // No Stencil Buffer - 0, // No Auxiliary Buffer - PFD_MAIN_PLANE, // Main Drawing Layer - 0, // Reserved - 0, 0, 0 // Layer Masks Ignored - }; - - if (!(hDC=GetDC(hWnd))) // Did we get the Device Context? - { - abortGLInit("Can't Create A GL Device Context."); - return FALSE; - } - - if (!(PixelFormat=ChoosePixelFormat(hDC, &pfd))) // Did We Find a matching pixel Format? - { - abortGLInit("Can't Find Suitable PixelFormat"); - return FALSE; - } - - if (!SetPixelFormat(hDC, PixelFormat, &pfd)) - { - abortGLInit("Can't Set The PixelFormat"); - return FALSE; - } - - if (!(hRC=wglCreateContext(hDC))) - { - abortGLInit("Can't Create A GL Rendering Context."); - return FALSE; - } - - if (!(wglMakeCurrent(hDC,hRC))) // Try to activate the rendering context - { - abortGLInit("Can't Activate The Rendering Context"); - return FALSE; - } - - //// *** everything okay *** - - ShowWindow(hWnd, SW_SHOW); // Show The Window - SetForegroundWindow(hWnd); // Slightly Higher Prio - SetFocus(hWnd); // Sets Keyboard Focus To The Window - ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen - - if (!InitGL()) - { - abortGLInit("Initialization failed"); - return FALSE; - } - - return TRUE; -} - -LRESULT CALLBACK WndProc(HWND hWnd, // Handles for this Window - UINT uMsg, // Message for this Window - WPARAM wParam, // additional message Info - LPARAM lParam) // additional message Info -{ - switch (uMsg) // check for Window Messages - { - case WM_ACTIVATE: // Watch For Window Activate Message - { - if (!HIWORD(wParam)) // Check Minimization State - { - active=TRUE; - } - else - { - active=FALSE; - } - - return 0; // return To The Message Loop - } - - case WM_SYSCOMMAND: // Interrupt System Commands - { - switch (wParam) - { - case SC_SCREENSAVE: // Screen-saver trying to start - case SC_MONITORPOWER: // Monitor trying to enter power-safe - return 0; - } - break; - } - - case WM_CLOSE: // close message received? - { - PostQuitMessage(0); // Send WM_QUIT quit message - return 0; // Jump Back - } - - case WM_KEYDOWN: // Is a key pressed? - { - keys[wParam] = TRUE; // If so, Mark it as true - return 0; - } - - case WM_KEYUP: // Has Key Been released? - { - keys[wParam] = FALSE; // If so, Mark It As FALSE - return 0; - } - - case WM_SIZE: // Resize The OpenGL Window - { - ReSizeGLScene(LOWORD(lParam), HIWORD(lParam)); // LoWord-Width, HiWord-Height - return 0; - } - } - - // Pass All unhandled Messaged To DefWindowProc - return DefWindowProc(hWnd, uMsg, wParam, lParam); -} - -int WINAPI WinMain( HINSTANCE hInstance, // The instance - HINSTANCE hPrevInstance, // Previous instance - LPSTR lpCmdLine, // Command Line Parameters - int nShowCmd ) // Window Show State -{ - MSG msg; - BOOL done=FALSE; - - createAILogger(); - logInfo("App fired!"); - - // Check the command line for an override file path. - int argc; - LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); - if (argv != NULL && argc > 1) - { - std::wstring modelpathW(argv[1]); - modelpath = std::string(modelpathW.begin(), modelpathW.end()); - } - - if (!Import3DFromFile(modelpath)) return 0; - - logInfo("=============== Post Import ===================="); - - if (MessageBox(NULL, "Would You Like To Run In Fullscreen Mode?", "Start Fullscreen?", MB_YESNO|MB_ICONEXCLAMATION)==IDNO) - { - fullscreen=FALSE; - } - - if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen)) - { - return 0; - } - - while(!done) // Game Loop - { - if (PeekMessage(&msg, NULL, 0,0, PM_REMOVE)) - { - if (msg.message==WM_QUIT) - { - done=TRUE; - } - else - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - else - { - // Draw The Scene. Watch For ESC Key And Quit Messaged From DrawGLScene() - if (active) - { - if (keys[VK_ESCAPE]) - { - done=TRUE; - } - else - { - DrawGLScene(); - SwapBuffers(hDC); - } - } - - if (keys[VK_F1]) - { - keys[VK_F1]=FALSE; - KillGLWindow(); - fullscreen=!fullscreen; - if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen)) - { - return 0; - } - } - } - } - - // *** cleanup *** - - textureIdMap.clear(); //no need to delete pointers in it manually here. (Pointers point to textureIds deleted in next step) - - if (textureIds) - { - delete[] textureIds; - textureIds = NULL; - } - - // *** cleanup end *** - - destroyAILogger(); - KillGLWindow(); - return (msg.wParam); -} +// ---------------------------------------------------------------------------- +// Another Assimp OpenGL sample including texturing. +// Note that it is very basic and will only read and apply the model's diffuse +// textures (by their material ids) +// +// Don't worry about the "Couldn't load Image: ...dwarf2.jpg" Message. +// It's caused by a bad texture reference in the model file (I guess) +// +// If you intend to _use_ this code sample in your app, do yourself a favour +// and replace immediate mode calls with VBOs ... +// +// Thanks to NeHe on whose OpenGL tutorials this one's based on! :) +// http://nehe.gamedev.net/ +// ---------------------------------------------------------------------------- +#include +#include +#include +#include +#include + +#include + +//to map image filenames to textureIds +#include +#include + + +// assimp include files. These three are usually needed. +#include "assimp/Importer.hpp" //OO version Header! +#include "assimp/postprocess.h" +#include "assimp/scene.h" +#include "assimp/DefaultLogger.hpp" +#include "assimp/LogStream.hpp" + + +// The default hard-coded path. Can be overridden by supplying a path through the command line. +static std::string modelpath = "../../test/models/OBJ/spider.obj"; + + +HGLRC hRC=NULL; // Permanent Rendering Context +HDC hDC=NULL; // Private GDI Device Context +HWND hWnd=NULL; // Holds Window Handle +HINSTANCE hInstance; // Holds The Instance Of The Application + +bool keys[256]; // Array used for Keyboard Routine; +bool active=TRUE; // Window Active Flag Set To TRUE by Default +bool fullscreen=TRUE; // full-screen Flag Set To full-screen By Default + +GLfloat xrot; +GLfloat yrot; +GLfloat zrot; + + +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc +GLboolean abortGLInit(const char*); + +const char* windowTitle = "OpenGL Framework"; + +GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; +GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; +GLfloat LightPosition[]= { 0.0f, 0.0f, 15.0f, 1.0f }; + + + +// the global Assimp scene object +const aiScene* scene = NULL; +GLuint scene_list = 0; +aiVector3D scene_min, scene_max, scene_center; + +// images / texture +std::map textureIdMap; // map image filenames to textureIds +GLuint* textureIds; // pointer to texture Array + +// Create an instance of the Importer class +Assimp::Importer importer; + + +void createAILogger() +{ + // Change this line to normal if you not want to analyse the import process + //Assimp::Logger::LogSeverity severity = Assimp::Logger::NORMAL; + Assimp::Logger::LogSeverity severity = Assimp::Logger::VERBOSE; + + // Create a logger instance for Console Output + Assimp::DefaultLogger::create("",severity, aiDefaultLogStream_STDOUT); + + // Create a logger instance for File Output (found in project folder or near .exe) + Assimp::DefaultLogger::create("assimp_log.txt",severity, aiDefaultLogStream_FILE); + + // Now I am ready for logging my stuff + Assimp::DefaultLogger::get()->info("this is my info-call"); +} + +void destroyAILogger() +{ + // Kill it after the work is done + Assimp::DefaultLogger::kill(); +} + +void logInfo(std::string logString) +{ + // Will add message to File with "info" Tag + Assimp::DefaultLogger::get()->info(logString.c_str()); +} + +void logDebug(const char* logString) +{ + // Will add message to File with "debug" Tag + Assimp::DefaultLogger::get()->debug(logString); +} + + +bool Import3DFromFile( const std::string& pFile) +{ + // Check if file exists + std::ifstream fin(pFile.c_str()); + if(!fin.fail()) + { + fin.close(); + } + else + { + MessageBox(NULL, ("Couldn't open file: " + pFile).c_str() , "ERROR", MB_OK | MB_ICONEXCLAMATION); + logInfo( importer.GetErrorString()); + return false; + } + + scene = importer.ReadFile( pFile, aiProcessPreset_TargetRealtime_Quality); + + // If the import failed, report it + if( !scene) + { + logInfo( importer.GetErrorString()); + return false; + } + + // Now we can access the file's contents. + logInfo("Import of scene " + pFile + " succeeded."); + + // We're done. Everything will be cleaned up by the importer destructor + return true; +} + +// Resize And Initialize The GL Window +void ReSizeGLScene(GLsizei width, GLsizei height) +{ + // Prevent A Divide By Zero By + if (height==0) + { + // Making Height Equal One + height=1; + } + + glViewport(0, 0, width, height); // Reset The Current Viewport + + glMatrixMode(GL_PROJECTION); // Select The Projection Matrix + glLoadIdentity(); // Reset The Projection Matrix + + // Calculate The Aspect Ratio Of The Window + gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); + + glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix + glLoadIdentity(); // Reset The Modelview Matrix +} + + +std::string getBasePath(const std::string& path) +{ + size_t pos = path.find_last_of("\\/"); + return (std::string::npos == pos) ? "" : path.substr(0, pos + 1); +} + +int LoadGLTextures(const aiScene* scene) +{ + ILboolean success; + + /* Before calling ilInit() version should be checked. */ + if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION) + { + /// wrong DevIL version /// + std::string err_msg = "Wrong DevIL version. Old devil.dll in system32/SysWow64?"; + char* cErr_msg = (char *) err_msg.c_str(); + abortGLInit(cErr_msg); + return -1; + } + + ilInit(); /* Initialization of DevIL */ + + if (scene->HasTextures()) abortGLInit("Support for meshes with embedded textures is not implemented"); + + /* getTexture Filenames and Numb of Textures */ + for (unsigned int m=0; mmNumMaterials; m++) + { + int texIndex = 0; + aiReturn texFound = AI_SUCCESS; + + aiString path; // filename + + while (texFound == AI_SUCCESS) + { + texFound = scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path); + textureIdMap[path.data] = NULL; //fill map with textures, pointers still NULL yet + texIndex++; + } + } + + int numTextures = textureIdMap.size(); + + /* array with DevIL image IDs */ + ILuint* imageIds = NULL; + imageIds = new ILuint[numTextures]; + + /* generate DevIL Image IDs */ + ilGenImages(numTextures, imageIds); /* Generation of numTextures image names */ + + /* create and fill array with GL texture ids */ + textureIds = new GLuint[numTextures]; + glGenTextures(numTextures, textureIds); /* Texture name generation */ + + /* get iterator */ + std::map::iterator itr = textureIdMap.begin(); + + std::string basepath = getBasePath(modelpath); + for (int i=0; ir, color->g, color->b, color->a); +} + +void set_float4(float f[4], float a, float b, float c, float d) +{ + f[0] = a; + f[1] = b; + f[2] = c; + f[3] = d; +} + +void color4_to_float4(const aiColor4D *c, float f[4]) +{ + f[0] = c->r; + f[1] = c->g; + f[2] = c->b; + f[3] = c->a; +} + +void apply_material(const aiMaterial *mtl) +{ + float c[4]; + + GLenum fill_mode; + int ret1, ret2; + aiColor4D diffuse; + aiColor4D specular; + aiColor4D ambient; + aiColor4D emission; + float shininess, strength; + int two_sided; + int wireframe; + unsigned int max; // changed: to unsigned + + int texIndex = 0; + aiString texPath; //contains filename of texture + + if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath)) + { + //bind texture + unsigned int texId = *textureIdMap[texPath.data]; + glBindTexture(GL_TEXTURE_2D, texId); + } + + set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse)) + color4_to_float4(&diffuse, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c); + + set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular)) + color4_to_float4(&specular, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); + + set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient)) + color4_to_float4(&ambient, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c); + + set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f); + if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission)) + color4_to_float4(&emission, c); + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c); + + max = 1; + ret1 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max); + max = 1; + ret2 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS_STRENGTH, &strength, &max); + if((ret1 == AI_SUCCESS) && (ret2 == AI_SUCCESS)) + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength); + else { + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f); + set_float4(c, 0.0f, 0.0f, 0.0f, 0.0f); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c); + } + + max = 1; + if(AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, &max)) + fill_mode = wireframe ? GL_LINE : GL_FILL; + else + fill_mode = GL_FILL; + glPolygonMode(GL_FRONT_AND_BACK, fill_mode); + + max = 1; + if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); +} + + +void recursive_render (const struct aiScene *sc, const struct aiNode* nd, float scale) +{ + unsigned int i; + unsigned int n=0, t; + aiMatrix4x4 m = nd->mTransformation; + + aiMatrix4x4 m2; + aiMatrix4x4::Scaling(aiVector3D(scale, scale, scale), m2); + m = m * m2; + + // update transform + m.Transpose(); + glPushMatrix(); + glMultMatrixf((float*)&m); + + // draw all meshes assigned to this node + for (; n < nd->mNumMeshes; ++n) + { + const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]]; + + apply_material(sc->mMaterials[mesh->mMaterialIndex]); + + + if(mesh->mNormals == NULL) + { + glDisable(GL_LIGHTING); + } + else + { + glEnable(GL_LIGHTING); + } + + if(mesh->mColors[0] != NULL) + { + glEnable(GL_COLOR_MATERIAL); + } + else + { + glDisable(GL_COLOR_MATERIAL); + } + + for (t = 0; t < mesh->mNumFaces; ++t) { + const struct aiFace* face = &mesh->mFaces[t]; + GLenum face_mode; + + switch(face->mNumIndices) + { + case 1: face_mode = GL_POINTS; break; + case 2: face_mode = GL_LINES; break; + case 3: face_mode = GL_TRIANGLES; break; + default: face_mode = GL_POLYGON; break; + } + + glBegin(face_mode); + + for(i = 0; i < face->mNumIndices; i++) // go through all vertices in face + { + int vertexIndex = face->mIndices[i]; // get group index for current index + if(mesh->mColors[0] != NULL) + Color4f(&mesh->mColors[0][vertexIndex]); + if(mesh->mNormals != NULL) + + if(mesh->HasTextureCoords(0)) //HasTextureCoords(texture_coordinates_set) + { + glTexCoord2f(mesh->mTextureCoords[0][vertexIndex].x, 1 - mesh->mTextureCoords[0][vertexIndex].y); //mTextureCoords[channel][vertex] + } + + glNormal3fv(&mesh->mNormals[vertexIndex].x); + glVertex3fv(&mesh->mVertices[vertexIndex].x); + } + glEnd(); + } + } + + // draw all children + for (n = 0; n < nd->mNumChildren; ++n) + { + recursive_render(sc, nd->mChildren[n], scale); + } + + glPopMatrix(); +} + + +void drawAiScene(const aiScene* scene) +{ + logInfo("drawing objects"); + + recursive_render(scene, scene->mRootNode, 0.5); + +} + +int DrawGLScene() //Here's where we do all the drawing +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer + glLoadIdentity(); // Reset MV Matrix + + + glTranslatef(0.0f, -10.0f, -40.0f); // Move 40 Units And Into The Screen + + + glRotatef(xrot, 1.0f, 0.0f, 0.0f); + glRotatef(yrot, 0.0f, 1.0f, 0.0f); + glRotatef(zrot, 0.0f, 0.0f, 1.0f); + + drawAiScene(scene); + + //xrot+=0.3f; + yrot+=0.2f; + //zrot+=0.4f; + + return TRUE; // okay +} + + +void KillGLWindow() // Properly Kill The Window +{ + if (fullscreen) // Are We In Fullscreen Mode? + { + ChangeDisplaySettings(NULL, 0); // If So Switch Back To The Desktop + ShowCursor(TRUE); // Show Mouse Pointer + } + + if (hRC) // Do We Have A Rendering Context? + { + if (!wglMakeCurrent(NULL, NULL)) // Are We Able To Release The DC And RC Contexts? + { + MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + } + + if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC? + { + MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + } + hRC = NULL; + } + + if (hDC && !ReleaseDC(hWnd, hDC)) // Are We able to Release The DC? + { + MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + hDC=NULL; + } + + if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window + { + MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + hWnd = NULL; + } + + if (!UnregisterClass("OpenGL", hInstance)) // Are We Able To Unregister Class + { + MessageBox(NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); + hInstance = NULL; + } +} + +GLboolean abortGLInit(const char* abortMessage) +{ + KillGLWindow(); // Reset Display + MessageBox(NULL, abortMessage, "ERROR", MB_OK|MB_ICONEXCLAMATION); + return FALSE; // quit and return False +} + +BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool fullscreenflag) +{ + GLuint PixelFormat; // Hold the result after searching for a match + WNDCLASS wc; // Window Class Structure + DWORD dwExStyle; // Window Extended Style + DWORD dwStyle; // Window Style + RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values + WindowRect.left = (long)0; + WindowRect.right = (long)width; + WindowRect.top = (long)0; + WindowRect.bottom = (long)height; + + fullscreen = fullscreenflag; + + hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window + wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc handles Messages + wc.cbClsExtra = 0; // No Extra Window Data + wc.cbWndExtra = 0; // No Extra Window Data + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon + wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load the default arrow + wc.hbrBackground= NULL; // No Background required for OpenGL + wc.lpszMenuName = NULL; // No Menu + wc.lpszClassName= "OpenGL"; // Class Name + + if (!RegisterClass(&wc)) + { + MessageBox(NULL, "Failed to register the window class", "ERROR", MB_OK | MB_ICONEXCLAMATION); + return FALSE; //exit and return false + } + + if (fullscreen) // attempt fullscreen mode + { + DEVMODE dmScreenSettings; // Device Mode + memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make Sure Memory's Cleared + dmScreenSettings.dmSize = sizeof(dmScreenSettings); // Size Of the devmode structure + dmScreenSettings.dmPelsWidth = width; // Selected Screen Width + dmScreenSettings.dmPelsHeight = height; // Selected Screen Height + dmScreenSettings.dmBitsPerPel = bits; // bits per pixel + dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; + + // Try To Set Selected Mode and Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. + if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) + { + // If The Mode Fails, Offer Two Options. Quit Or Run In A Window. + if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) + { + fullscreen = FALSE; // Select Windowed Mode (Fullscreen = FALSE) + } + else + { + //Popup Messagebox: Closing + MessageBox(NULL, "Program will close now.", "ERROR", MB_OK|MB_ICONSTOP); + return FALSE; //exit, return false + } + } + } + + if (fullscreen) // when mode really succeeded + { + dwExStyle=WS_EX_APPWINDOW; // Window Extended Style + dwStyle=WS_POPUP; + ShowCursor(FALSE); + } + else + { + dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window extended style + dwStyle=WS_OVERLAPPEDWINDOW; // Windows style + } + + AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requestes Size + + if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window + "OpenGL", // Class Name + title, // Window Title + WS_CLIPSIBLINGS | // Required Window Style + WS_CLIPCHILDREN | // Required Window Style + dwStyle, // Selected WIndow Style + 0, 0, // Window Position + WindowRect.right-WindowRect.left, // Calc adjusted Window Width + WindowRect.bottom-WindowRect.top, // Calc adjustes Window Height + NULL, // No Parent Window + NULL, // No Menu + hInstance, // Instance + NULL ))) // Don't pass anything To WM_CREATE + { + abortGLInit("Window Creation Error."); + return FALSE; + } + + static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be + { + sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor + 1, // Version Number + PFD_DRAW_TO_WINDOW | // Format Must Support Window + PFD_SUPPORT_OPENGL | // Format Must Support OpenGL + PFD_DOUBLEBUFFER, // Must Support Double Buffering + PFD_TYPE_RGBA, // Request An RGBA Format + bits, // Select Our Color Depth + 0, 0, 0, 0, 0, 0, // Color Bits Ignored + 0, // No Alpha Buffer + 0, // Shift Bit Ignored + 0, // No Accumulation Buffer + 0, 0, 0, 0, // Accumulation Bits Ignored + 16, // 16Bit Z-Buffer (Depth Buffer) + 0, // No Stencil Buffer + 0, // No Auxiliary Buffer + PFD_MAIN_PLANE, // Main Drawing Layer + 0, // Reserved + 0, 0, 0 // Layer Masks Ignored + }; + + if (!(hDC=GetDC(hWnd))) // Did we get the Device Context? + { + abortGLInit("Can't Create A GL Device Context."); + return FALSE; + } + + if (!(PixelFormat=ChoosePixelFormat(hDC, &pfd))) // Did We Find a matching pixel Format? + { + abortGLInit("Can't Find Suitable PixelFormat"); + return FALSE; + } + + if (!SetPixelFormat(hDC, PixelFormat, &pfd)) + { + abortGLInit("Can't Set The PixelFormat"); + return FALSE; + } + + if (!(hRC=wglCreateContext(hDC))) + { + abortGLInit("Can't Create A GL Rendering Context."); + return FALSE; + } + + if (!(wglMakeCurrent(hDC,hRC))) // Try to activate the rendering context + { + abortGLInit("Can't Activate The Rendering Context"); + return FALSE; + } + + //// *** everything okay *** + + ShowWindow(hWnd, SW_SHOW); // Show The Window + SetForegroundWindow(hWnd); // Slightly Higher Prio + SetFocus(hWnd); // Sets Keyboard Focus To The Window + ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen + + if (!InitGL()) + { + abortGLInit("Initialization failed"); + return FALSE; + } + + return TRUE; +} + +LRESULT CALLBACK WndProc(HWND hWnd, // Handles for this Window + UINT uMsg, // Message for this Window + WPARAM wParam, // additional message Info + LPARAM lParam) // additional message Info +{ + switch (uMsg) // check for Window Messages + { + case WM_ACTIVATE: // Watch For Window Activate Message + { + if (!HIWORD(wParam)) // Check Minimization State + { + active=TRUE; + } + else + { + active=FALSE; + } + + return 0; // return To The Message Loop + } + + case WM_SYSCOMMAND: // Interrupt System Commands + { + switch (wParam) + { + case SC_SCREENSAVE: // Screen-saver trying to start + case SC_MONITORPOWER: // Monitor trying to enter power-safe + return 0; + } + break; + } + + case WM_CLOSE: // close message received? + { + PostQuitMessage(0); // Send WM_QUIT quit message + return 0; // Jump Back + } + + case WM_KEYDOWN: // Is a key pressed? + { + keys[wParam] = TRUE; // If so, Mark it as true + return 0; + } + + case WM_KEYUP: // Has Key Been released? + { + keys[wParam] = FALSE; // If so, Mark It As FALSE + return 0; + } + + case WM_SIZE: // Resize The OpenGL Window + { + ReSizeGLScene(LOWORD(lParam), HIWORD(lParam)); // LoWord-Width, HiWord-Height + return 0; + } + } + + // Pass All unhandled Messaged To DefWindowProc + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + +int WINAPI WinMain( HINSTANCE hInstance, // The instance + HINSTANCE hPrevInstance, // Previous instance + LPSTR lpCmdLine, // Command Line Parameters + int nShowCmd ) // Window Show State +{ + MSG msg; + BOOL done=FALSE; + + createAILogger(); + logInfo("App fired!"); + + // Check the command line for an override file path. + int argc; + LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); + if (argv != NULL && argc > 1) + { + std::wstring modelpathW(argv[1]); + modelpath = std::string(modelpathW.begin(), modelpathW.end()); + } + + if (!Import3DFromFile(modelpath)) return 0; + + logInfo("=============== Post Import ===================="); + + if (MessageBox(NULL, "Would You Like To Run In Fullscreen Mode?", "Start Fullscreen?", MB_YESNO|MB_ICONEXCLAMATION)==IDNO) + { + fullscreen=FALSE; + } + + if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen)) + { + return 0; + } + + while(!done) // Game Loop + { + if (PeekMessage(&msg, NULL, 0,0, PM_REMOVE)) + { + if (msg.message==WM_QUIT) + { + done=TRUE; + } + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + else + { + // Draw The Scene. Watch For ESC Key And Quit Messaged From DrawGLScene() + if (active) + { + if (keys[VK_ESCAPE]) + { + done=TRUE; + } + else + { + DrawGLScene(); + SwapBuffers(hDC); + } + } + + if (keys[VK_F1]) + { + keys[VK_F1]=FALSE; + KillGLWindow(); + fullscreen=!fullscreen; + if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen)) + { + return 0; + } + } + } + } + + // *** cleanup *** + + textureIdMap.clear(); //no need to delete pointers in it manually here. (Pointers point to textureIds deleted in next step) + + if (textureIds) + { + delete[] textureIds; + textureIds = NULL; + } + + // *** cleanup end *** + + destroyAILogger(); + KillGLWindow(); + return (msg.wParam); +} diff --git a/samples/glut/GL/glut.h b/samples/glut/GL/glut.h index aa7428f36..0e6ddfbfe 100644 --- a/samples/glut/GL/glut.h +++ b/samples/glut/GL/glut.h @@ -1,716 +1,716 @@ -#ifndef __glut_h__ -#define __glut_h__ - -/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998. */ - -/* This program is freely distributable without licensing fees and is - provided without guarantee or warrantee expressed or implied. This - program is -not- in the public domain. */ - -#if defined(_WIN32) - -/* GLUT 3.7 now tries to avoid including - to avoid name space pollution, but Win32's - needs APIENTRY and WINGDIAPI defined properly. */ -# if 0 - /* This would put tons of macros and crap in our clean name space. */ -# define WIN32_LEAN_AND_MEAN -# include -# else - /* XXX This is from Win32's */ -# ifndef APIENTRY -# define GLUT_APIENTRY_DEFINED -# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) || defined(__LCC__) -# define APIENTRY __stdcall -# else -# define APIENTRY -# endif -# endif - /* XXX This is from Win32's */ -# ifndef CALLBACK -# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) || defined(__LCC__) -# define CALLBACK __stdcall -# else -# define CALLBACK -# endif -# endif - /* XXX Hack for lcc compiler. It doesn't support __declspec(dllimport), just __stdcall. */ -# if defined( __LCC__ ) -# undef WINGDIAPI -# define WINGDIAPI __stdcall -# else - /* XXX This is from Win32's and */ -# ifndef WINGDIAPI -# define GLUT_WINGDIAPI_DEFINED -# define WINGDIAPI __declspec(dllimport) -# endif -# endif - /* XXX This is from Win32's */ -# ifndef _WCHAR_T_DEFINED -typedef unsigned short wchar_t; -# define _WCHAR_T_DEFINED -# endif -# endif - -/* To disable automatic library usage for GLUT, define GLUT_NO_LIB_PRAGMA - in your compile preprocessor options. */ -# if !defined(GLUT_BUILDING_LIB) && !defined(GLUT_NO_LIB_PRAGMA) -# pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ -/* To enable automatic SGI OpenGL for Windows library usage for GLUT, - define GLUT_USE_SGI_OPENGL in your compile preprocessor options. */ -# ifdef GLUT_USE_SGI_OPENGL -# pragma comment (lib, "opengl.lib") /* link with SGI OpenGL for Windows lib */ -# pragma comment (lib, "glu.lib") /* link with SGI OpenGL Utility lib */ -# pragma comment (lib, "glut.lib") /* link with Win32 GLUT for SGI OpenGL lib */ -# else -# pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ -# pragma comment (lib, "glu32.lib") /* link with Microsoft OpenGL Utility lib */ -# pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ -# endif -# endif - -/* To disable supression of annoying warnings about floats being promoted - to doubles, define GLUT_NO_WARNING_DISABLE in your compile preprocessor - options. */ -# ifndef GLUT_NO_WARNING_DISABLE -# pragma warning (disable:4244) /* Disable bogus VC++ 4.2 conversion warnings. */ -# pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ -# endif - -/* Win32 has an annoying issue where there are multiple C run-time - libraries (CRTs). If the executable is linked with a different CRT - from the GLUT DLL, the GLUT DLL will not share the same CRT static - data seen by the executable. In particular, atexit callbacks registered - in the executable will not be called if GLUT calls its (different) - exit routine). GLUT is typically built with the - "/MD" option (the CRT with multithreading DLL support), but the Visual - C++ linker default is "/ML" (the single threaded CRT). - - One workaround to this issue is requiring users to always link with - the same CRT as GLUT is compiled with. That requires users supply a - non-standard option. GLUT 3.7 has its own built-in workaround where - the executable's "exit" function pointer is covertly passed to GLUT. - GLUT then calls the executable's exit function pointer to ensure that - any "atexit" calls registered by the application are called if GLUT - needs to exit. - - Note that the __glut*WithExit routines should NEVER be called directly. - To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */ - -/* XXX This is from Win32's */ -# if !defined(_MSC_VER) && !defined(__cdecl) - /* Define __cdecl for non-Microsoft compilers. */ -# define __cdecl -# define GLUT_DEFINED___CDECL -# endif -# ifndef _CRTIMP -# ifdef _NTSDK - /* Definition compatible with NT SDK */ -# define _CRTIMP -# else - /* Current definition */ -# ifdef _DLL -# define _CRTIMP __declspec(dllimport) -# else -# define _CRTIMP -# endif -# endif -# define GLUT_DEFINED__CRTIMP -# endif - -/* GLUT API entry point declarations for Win32. */ -# ifdef GLUT_BUILDING_LIB -# define GLUTAPI __declspec(dllexport) -# else -# ifdef _DLL -# define GLUTAPI __declspec(dllimport) -# else -# define GLUTAPI extern -# endif -# endif - -/* GLUT callback calling convention for Win32. */ -# define GLUTCALLBACK __cdecl - -#endif /* _WIN32 */ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(_WIN32) -# ifndef GLUT_BUILDING_LIB -extern _CRTIMP void __cdecl exit(int); -# endif -#else -/* non-Win32 case. */ -/* Define APIENTRY and CALLBACK to nothing if we aren't on Win32. */ -# define APIENTRY -# define GLUT_APIENTRY_DEFINED -# define CALLBACK -/* Define GLUTAPI and GLUTCALLBACK as below if we aren't on Win32. */ -# define GLUTAPI extern -# define GLUTCALLBACK -/* Prototype exit for the non-Win32 case (see above). */ -extern void exit(int); -#endif - -/** - GLUT API revision history: - - GLUT_API_VERSION is updated to reflect incompatible GLUT - API changes (interface changes, semantic changes, deletions, - or additions). - - GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 - - GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, - extension. Supports new input devices like tablet, dial and button - box, and Spaceball. Easy to query OpenGL extensions. - - GLUT_API_VERSION=3 glutMenuStatus added. - - GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, - glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic - video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, - glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, - glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). -**/ -#ifndef GLUT_API_VERSION /* allow this to be overriden */ -#define GLUT_API_VERSION 3 -#endif - -/** - GLUT implementation revision history: - - GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT - API revisions and implementation revisions (ie, bug fixes). - - GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of - GLUT Xlib-based implementation. 11/29/94 - - GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of - GLUT Xlib-based implementation providing GLUT version 2 - interfaces. - - GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 - - GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 - - GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 - - GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 - - GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner - and video resize. 1/3/97 - - GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. - - GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. - - GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. - - GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 beta with GameGLUT support. - - GLUT_XLIB_IMPLEMENTATION=14 mjk's GLUT 3.7 beta with f90gl friend interface. - - GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa -**/ -#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ -#define GLUT_XLIB_IMPLEMENTATION 15 -#endif - -/* Display mode bit masks. */ -#define GLUT_RGB 0 -#define GLUT_RGBA GLUT_RGB -#define GLUT_INDEX 1 -#define GLUT_SINGLE 0 -#define GLUT_DOUBLE 2 -#define GLUT_ACCUM 4 -#define GLUT_ALPHA 8 -#define GLUT_DEPTH 16 -#define GLUT_STENCIL 32 -#if (GLUT_API_VERSION >= 2) -#define GLUT_MULTISAMPLE 128 -#define GLUT_STEREO 256 -#endif -#if (GLUT_API_VERSION >= 3) -#define GLUT_LUMINANCE 512 -#endif - -/* Mouse buttons. */ -#define GLUT_LEFT_BUTTON 0 -#define GLUT_MIDDLE_BUTTON 1 -#define GLUT_RIGHT_BUTTON 2 - -/* Mouse button state. */ -#define GLUT_DOWN 0 -#define GLUT_UP 1 - -#if (GLUT_API_VERSION >= 2) -/* function keys */ -#define GLUT_KEY_F1 1 -#define GLUT_KEY_F2 2 -#define GLUT_KEY_F3 3 -#define GLUT_KEY_F4 4 -#define GLUT_KEY_F5 5 -#define GLUT_KEY_F6 6 -#define GLUT_KEY_F7 7 -#define GLUT_KEY_F8 8 -#define GLUT_KEY_F9 9 -#define GLUT_KEY_F10 10 -#define GLUT_KEY_F11 11 -#define GLUT_KEY_F12 12 -/* directional keys */ -#define GLUT_KEY_LEFT 100 -#define GLUT_KEY_UP 101 -#define GLUT_KEY_RIGHT 102 -#define GLUT_KEY_DOWN 103 -#define GLUT_KEY_PAGE_UP 104 -#define GLUT_KEY_PAGE_DOWN 105 -#define GLUT_KEY_HOME 106 -#define GLUT_KEY_END 107 -#define GLUT_KEY_INSERT 108 -#endif - -/* Entry/exit state. */ -#define GLUT_LEFT 0 -#define GLUT_ENTERED 1 - -/* Menu usage state. */ -#define GLUT_MENU_NOT_IN_USE 0 -#define GLUT_MENU_IN_USE 1 - -/* Visibility state. */ -#define GLUT_NOT_VISIBLE 0 -#define GLUT_VISIBLE 1 - -/* Window status state. */ -#define GLUT_HIDDEN 0 -#define GLUT_FULLY_RETAINED 1 -#define GLUT_PARTIALLY_RETAINED 2 -#define GLUT_FULLY_COVERED 3 - -/* Color index component selection values. */ -#define GLUT_RED 0 -#define GLUT_GREEN 1 -#define GLUT_BLUE 2 - -#if defined(_WIN32) -/* Stroke font constants (use these in GLUT program). */ -#define GLUT_STROKE_ROMAN ((void*)0) -#define GLUT_STROKE_MONO_ROMAN ((void*)1) - -/* Bitmap font constants (use these in GLUT program). */ -#define GLUT_BITMAP_9_BY_15 ((void*)2) -#define GLUT_BITMAP_8_BY_13 ((void*)3) -#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) -#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) -#if (GLUT_API_VERSION >= 3) -#define GLUT_BITMAP_HELVETICA_10 ((void*)6) -#define GLUT_BITMAP_HELVETICA_12 ((void*)7) -#define GLUT_BITMAP_HELVETICA_18 ((void*)8) -#endif -#else -/* Stroke font opaque addresses (use constants instead in source code). */ -GLUTAPI void *glutStrokeRoman; -GLUTAPI void *glutStrokeMonoRoman; - -/* Stroke font constants (use these in GLUT program). */ -#define GLUT_STROKE_ROMAN (&glutStrokeRoman) -#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) - -/* Bitmap font opaque addresses (use constants instead in source code). */ -GLUTAPI void *glutBitmap9By15; -GLUTAPI void *glutBitmap8By13; -GLUTAPI void *glutBitmapTimesRoman10; -GLUTAPI void *glutBitmapTimesRoman24; -GLUTAPI void *glutBitmapHelvetica10; -GLUTAPI void *glutBitmapHelvetica12; -GLUTAPI void *glutBitmapHelvetica18; - -/* Bitmap font constants (use these in GLUT program). */ -#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) -#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) -#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) -#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) -#if (GLUT_API_VERSION >= 3) -#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) -#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) -#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) -#endif -#endif - -/* glutGet parameters. */ -#define GLUT_WINDOW_X ((GLenum) 100) -#define GLUT_WINDOW_Y ((GLenum) 101) -#define GLUT_WINDOW_WIDTH ((GLenum) 102) -#define GLUT_WINDOW_HEIGHT ((GLenum) 103) -#define GLUT_WINDOW_BUFFER_SIZE ((GLenum) 104) -#define GLUT_WINDOW_STENCIL_SIZE ((GLenum) 105) -#define GLUT_WINDOW_DEPTH_SIZE ((GLenum) 106) -#define GLUT_WINDOW_RED_SIZE ((GLenum) 107) -#define GLUT_WINDOW_GREEN_SIZE ((GLenum) 108) -#define GLUT_WINDOW_BLUE_SIZE ((GLenum) 109) -#define GLUT_WINDOW_ALPHA_SIZE ((GLenum) 110) -#define GLUT_WINDOW_ACCUM_RED_SIZE ((GLenum) 111) -#define GLUT_WINDOW_ACCUM_GREEN_SIZE ((GLenum) 112) -#define GLUT_WINDOW_ACCUM_BLUE_SIZE ((GLenum) 113) -#define GLUT_WINDOW_ACCUM_ALPHA_SIZE ((GLenum) 114) -#define GLUT_WINDOW_DOUBLEBUFFER ((GLenum) 115) -#define GLUT_WINDOW_RGBA ((GLenum) 116) -#define GLUT_WINDOW_PARENT ((GLenum) 117) -#define GLUT_WINDOW_NUM_CHILDREN ((GLenum) 118) -#define GLUT_WINDOW_COLORMAP_SIZE ((GLenum) 119) -#if (GLUT_API_VERSION >= 2) -#define GLUT_WINDOW_NUM_SAMPLES ((GLenum) 120) -#define GLUT_WINDOW_STEREO ((GLenum) 121) -#endif -#if (GLUT_API_VERSION >= 3) -#define GLUT_WINDOW_CURSOR ((GLenum) 122) -#endif -#define GLUT_SCREEN_WIDTH ((GLenum) 200) -#define GLUT_SCREEN_HEIGHT ((GLenum) 201) -#define GLUT_SCREEN_WIDTH_MM ((GLenum) 202) -#define GLUT_SCREEN_HEIGHT_MM ((GLenum) 203) -#define GLUT_MENU_NUM_ITEMS ((GLenum) 300) -#define GLUT_DISPLAY_MODE_POSSIBLE ((GLenum) 400) -#define GLUT_INIT_WINDOW_X ((GLenum) 500) -#define GLUT_INIT_WINDOW_Y ((GLenum) 501) -#define GLUT_INIT_WINDOW_WIDTH ((GLenum) 502) -#define GLUT_INIT_WINDOW_HEIGHT ((GLenum) 503) -#define GLUT_INIT_DISPLAY_MODE ((GLenum) 504) -#if (GLUT_API_VERSION >= 2) -#define GLUT_ELAPSED_TIME ((GLenum) 700) -#endif -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -#define GLUT_WINDOW_FORMAT_ID ((GLenum) 123) -#endif - -#if (GLUT_API_VERSION >= 2) -/* glutDeviceGet parameters. */ -#define GLUT_HAS_KEYBOARD ((GLenum) 600) -#define GLUT_HAS_MOUSE ((GLenum) 601) -#define GLUT_HAS_SPACEBALL ((GLenum) 602) -#define GLUT_HAS_DIAL_AND_BUTTON_BOX ((GLenum) 603) -#define GLUT_HAS_TABLET ((GLenum) 604) -#define GLUT_NUM_MOUSE_BUTTONS ((GLenum) 605) -#define GLUT_NUM_SPACEBALL_BUTTONS ((GLenum) 606) -#define GLUT_NUM_BUTTON_BOX_BUTTONS ((GLenum) 607) -#define GLUT_NUM_DIALS ((GLenum) 608) -#define GLUT_NUM_TABLET_BUTTONS ((GLenum) 609) -#endif -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -#define GLUT_DEVICE_IGNORE_KEY_REPEAT ((GLenum) 610) -#define GLUT_DEVICE_KEY_REPEAT ((GLenum) 611) -#define GLUT_HAS_JOYSTICK ((GLenum) 612) -#define GLUT_OWNS_JOYSTICK ((GLenum) 613) -#define GLUT_JOYSTICK_BUTTONS ((GLenum) 614) -#define GLUT_JOYSTICK_AXES ((GLenum) 615) -#define GLUT_JOYSTICK_POLL_RATE ((GLenum) 616) -#endif - -#if (GLUT_API_VERSION >= 3) -/* glutLayerGet parameters. */ -#define GLUT_OVERLAY_POSSIBLE ((GLenum) 800) -#define GLUT_LAYER_IN_USE ((GLenum) 801) -#define GLUT_HAS_OVERLAY ((GLenum) 802) -#define GLUT_TRANSPARENT_INDEX ((GLenum) 803) -#define GLUT_NORMAL_DAMAGED ((GLenum) 804) -#define GLUT_OVERLAY_DAMAGED ((GLenum) 805) - -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -/* glutVideoResizeGet parameters. */ -#define GLUT_VIDEO_RESIZE_POSSIBLE ((GLenum) 900) -#define GLUT_VIDEO_RESIZE_IN_USE ((GLenum) 901) -#define GLUT_VIDEO_RESIZE_X_DELTA ((GLenum) 902) -#define GLUT_VIDEO_RESIZE_Y_DELTA ((GLenum) 903) -#define GLUT_VIDEO_RESIZE_WIDTH_DELTA ((GLenum) 904) -#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA ((GLenum) 905) -#define GLUT_VIDEO_RESIZE_X ((GLenum) 906) -#define GLUT_VIDEO_RESIZE_Y ((GLenum) 907) -#define GLUT_VIDEO_RESIZE_WIDTH ((GLenum) 908) -#define GLUT_VIDEO_RESIZE_HEIGHT ((GLenum) 909) -#endif - -/* glutUseLayer parameters. */ -#define GLUT_NORMAL ((GLenum) 0) -#define GLUT_OVERLAY ((GLenum) 1) - -/* glutGetModifiers return mask. */ -#define GLUT_ACTIVE_SHIFT 1 -#define GLUT_ACTIVE_CTRL 2 -#define GLUT_ACTIVE_ALT 4 - -/* glutSetCursor parameters. */ -/* Basic arrows. */ -#define GLUT_CURSOR_RIGHT_ARROW 0 -#define GLUT_CURSOR_LEFT_ARROW 1 -/* Symbolic cursor shapes. */ -#define GLUT_CURSOR_INFO 2 -#define GLUT_CURSOR_DESTROY 3 -#define GLUT_CURSOR_HELP 4 -#define GLUT_CURSOR_CYCLE 5 -#define GLUT_CURSOR_SPRAY 6 -#define GLUT_CURSOR_WAIT 7 -#define GLUT_CURSOR_TEXT 8 -#define GLUT_CURSOR_CROSSHAIR 9 -/* Directional cursors. */ -#define GLUT_CURSOR_UP_DOWN 10 -#define GLUT_CURSOR_LEFT_RIGHT 11 -/* Sizing cursors. */ -#define GLUT_CURSOR_TOP_SIDE 12 -#define GLUT_CURSOR_BOTTOM_SIDE 13 -#define GLUT_CURSOR_LEFT_SIDE 14 -#define GLUT_CURSOR_RIGHT_SIDE 15 -#define GLUT_CURSOR_TOP_LEFT_CORNER 16 -#define GLUT_CURSOR_TOP_RIGHT_CORNER 17 -#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 -#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 -/* Inherit from parent window. */ -#define GLUT_CURSOR_INHERIT 100 -/* Blank cursor. */ -#define GLUT_CURSOR_NONE 101 -/* Fullscreen crosshair (if available). */ -#define GLUT_CURSOR_FULL_CROSSHAIR 102 -#endif - -/* GLUT initialization sub-API. */ -GLUTAPI void APIENTRY glutInit(int *argcp, char **argv); -#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) -GLUTAPI void APIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)); -#ifndef GLUT_BUILDING_LIB -static void APIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); } -#define glutInit glutInit_ATEXIT_HACK -#endif -#endif -GLUTAPI void APIENTRY glutInitDisplayMode(unsigned int mode); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -GLUTAPI void APIENTRY glutInitDisplayString(const char *string); -#endif -GLUTAPI void APIENTRY glutInitWindowPosition(int x, int y); -GLUTAPI void APIENTRY glutInitWindowSize(int width, int height); -GLUTAPI void APIENTRY glutMainLoop(void); - -/* GLUT window sub-API. */ -GLUTAPI int APIENTRY glutCreateWindow(const char *title); -#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) -GLUTAPI int APIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int)); -#ifndef GLUT_BUILDING_LIB -static int APIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); } -#define glutCreateWindow glutCreateWindow_ATEXIT_HACK -#endif -#endif -GLUTAPI int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); -GLUTAPI void APIENTRY glutDestroyWindow(int win); -GLUTAPI void APIENTRY glutPostRedisplay(void); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) -GLUTAPI void APIENTRY glutPostWindowRedisplay(int win); -#endif -GLUTAPI void APIENTRY glutSwapBuffers(void); -GLUTAPI int APIENTRY glutGetWindow(void); -GLUTAPI void APIENTRY glutSetWindow(int win); -GLUTAPI void APIENTRY glutSetWindowTitle(const char *title); -GLUTAPI void APIENTRY glutSetIconTitle(const char *title); -GLUTAPI void APIENTRY glutPositionWindow(int x, int y); -GLUTAPI void APIENTRY glutReshapeWindow(int width, int height); -GLUTAPI void APIENTRY glutPopWindow(void); -GLUTAPI void APIENTRY glutPushWindow(void); -GLUTAPI void APIENTRY glutIconifyWindow(void); -GLUTAPI void APIENTRY glutShowWindow(void); -GLUTAPI void APIENTRY glutHideWindow(void); -#if (GLUT_API_VERSION >= 3) -GLUTAPI void APIENTRY glutFullScreen(void); -GLUTAPI void APIENTRY glutSetCursor(int cursor); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -GLUTAPI void APIENTRY glutWarpPointer(int x, int y); -#endif - -/* GLUT overlay sub-API. */ -GLUTAPI void APIENTRY glutEstablishOverlay(void); -GLUTAPI void APIENTRY glutRemoveOverlay(void); -GLUTAPI void APIENTRY glutUseLayer(GLenum layer); -GLUTAPI void APIENTRY glutPostOverlayRedisplay(void); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) -GLUTAPI void APIENTRY glutPostWindowOverlayRedisplay(int win); -#endif -GLUTAPI void APIENTRY glutShowOverlay(void); -GLUTAPI void APIENTRY glutHideOverlay(void); -#endif - -/* GLUT menu sub-API. */ -GLUTAPI int APIENTRY glutCreateMenu(void (GLUTCALLBACK *func)(int)); -#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) -GLUTAPI int APIENTRY __glutCreateMenuWithExit(void (GLUTCALLBACK *func)(int), void (__cdecl *exitfunc)(int)); -#ifndef GLUT_BUILDING_LIB -static int APIENTRY glutCreateMenu_ATEXIT_HACK(void (GLUTCALLBACK *func)(int)) { return __glutCreateMenuWithExit(func, exit); } -#define glutCreateMenu glutCreateMenu_ATEXIT_HACK -#endif -#endif -GLUTAPI void APIENTRY glutDestroyMenu(int menu); -GLUTAPI int APIENTRY glutGetMenu(void); -GLUTAPI void APIENTRY glutSetMenu(int menu); -GLUTAPI void APIENTRY glutAddMenuEntry(const char *label, int value); -GLUTAPI void APIENTRY glutAddSubMenu(const char *label, int submenu); -GLUTAPI void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value); -GLUTAPI void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); -GLUTAPI void APIENTRY glutRemoveMenuItem(int item); -GLUTAPI void APIENTRY glutAttachMenu(int button); -GLUTAPI void APIENTRY glutDetachMenu(int button); - -/* GLUT window callback sub-API. */ -GLUTAPI void APIENTRY glutDisplayFunc(void (GLUTCALLBACK *func)(void)); -GLUTAPI void APIENTRY glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height)); -GLUTAPI void APIENTRY glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); -GLUTAPI void APIENTRY glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); -GLUTAPI void APIENTRY glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); -GLUTAPI void APIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); -GLUTAPI void APIENTRY glutEntryFunc(void (GLUTCALLBACK *func)(int state)); -GLUTAPI void APIENTRY glutVisibilityFunc(void (GLUTCALLBACK *func)(int state)); -GLUTAPI void APIENTRY glutIdleFunc(void (GLUTCALLBACK *func)(void)); -GLUTAPI void APIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value); -GLUTAPI void APIENTRY glutMenuStateFunc(void (GLUTCALLBACK *func)(int state)); -#if (GLUT_API_VERSION >= 2) -GLUTAPI void APIENTRY glutSpecialFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); -GLUTAPI void APIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); -GLUTAPI void APIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); -GLUTAPI void APIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state)); -GLUTAPI void APIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state)); -GLUTAPI void APIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value)); -GLUTAPI void APIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); -GLUTAPI void APIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); -#if (GLUT_API_VERSION >= 3) -GLUTAPI void APIENTRY glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y)); -GLUTAPI void APIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK *func)(void)); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -GLUTAPI void APIENTRY glutWindowStatusFunc(void (GLUTCALLBACK *func)(int state)); -#endif -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -GLUTAPI void APIENTRY glutKeyboardUpFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); -GLUTAPI void APIENTRY glutSpecialUpFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); -GLUTAPI void APIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval); -#endif -#endif -#endif - -/* GLUT color index sub-API. */ -GLUTAPI void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); -GLUTAPI GLfloat APIENTRY glutGetColor(int ndx, int component); -GLUTAPI void APIENTRY glutCopyColormap(int win); - -/* GLUT state retrieval sub-API. */ -GLUTAPI int APIENTRY glutGet(GLenum type); -GLUTAPI int APIENTRY glutDeviceGet(GLenum type); -#if (GLUT_API_VERSION >= 2) -/* GLUT extension support sub-API */ -GLUTAPI int APIENTRY glutExtensionSupported(const char *name); -#endif -#if (GLUT_API_VERSION >= 3) -GLUTAPI int APIENTRY glutGetModifiers(void); -GLUTAPI int APIENTRY glutLayerGet(GLenum type); -#endif - -/* GLUT font sub-API */ -GLUTAPI void APIENTRY glutBitmapCharacter(void *font, int character); -GLUTAPI int APIENTRY glutBitmapWidth(void *font, int character); -GLUTAPI void APIENTRY glutStrokeCharacter(void *font, int character); -GLUTAPI int APIENTRY glutStrokeWidth(void *font, int character); -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -GLUTAPI int APIENTRY glutBitmapLength(void *font, const unsigned char *string); -GLUTAPI int APIENTRY glutStrokeLength(void *font, const unsigned char *string); -#endif - -/* GLUT pre-built models sub-API */ -GLUTAPI void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); -GLUTAPI void APIENTRY glutWireCube(GLdouble size); -GLUTAPI void APIENTRY glutSolidCube(GLdouble size); -GLUTAPI void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); -GLUTAPI void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); -GLUTAPI void APIENTRY glutWireDodecahedron(void); -GLUTAPI void APIENTRY glutSolidDodecahedron(void); -GLUTAPI void APIENTRY glutWireTeapot(GLdouble size); -GLUTAPI void APIENTRY glutSolidTeapot(GLdouble size); -GLUTAPI void APIENTRY glutWireOctahedron(void); -GLUTAPI void APIENTRY glutSolidOctahedron(void); -GLUTAPI void APIENTRY glutWireTetrahedron(void); -GLUTAPI void APIENTRY glutSolidTetrahedron(void); -GLUTAPI void APIENTRY glutWireIcosahedron(void); -GLUTAPI void APIENTRY glutSolidIcosahedron(void); - -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) -/* GLUT video resize sub-API. */ -GLUTAPI int APIENTRY glutVideoResizeGet(GLenum param); -GLUTAPI void APIENTRY glutSetupVideoResizing(void); -GLUTAPI void APIENTRY glutStopVideoResizing(void); -GLUTAPI void APIENTRY glutVideoResize(int x, int y, int width, int height); -GLUTAPI void APIENTRY glutVideoPan(int x, int y, int width, int height); - -/* GLUT debugging sub-API. */ -GLUTAPI void APIENTRY glutReportErrors(void); -#endif - -#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) -/* GLUT device control sub-API. */ -/* glutSetKeyRepeat modes. */ -#define GLUT_KEY_REPEAT_OFF 0 -#define GLUT_KEY_REPEAT_ON 1 -#define GLUT_KEY_REPEAT_DEFAULT 2 - -/* Joystick button masks. */ -#define GLUT_JOYSTICK_BUTTON_A 1 -#define GLUT_JOYSTICK_BUTTON_B 2 -#define GLUT_JOYSTICK_BUTTON_C 4 -#define GLUT_JOYSTICK_BUTTON_D 8 - -GLUTAPI void APIENTRY glutIgnoreKeyRepeat(int ignore); -GLUTAPI void APIENTRY glutSetKeyRepeat(int repeatMode); -GLUTAPI void APIENTRY glutForceJoystickFunc(void); - -/* GLUT game mode sub-API. */ -/* glutGameModeGet. */ -#define GLUT_GAME_MODE_ACTIVE ((GLenum) 0) -#define GLUT_GAME_MODE_POSSIBLE ((GLenum) 1) -#define GLUT_GAME_MODE_WIDTH ((GLenum) 2) -#define GLUT_GAME_MODE_HEIGHT ((GLenum) 3) -#define GLUT_GAME_MODE_PIXEL_DEPTH ((GLenum) 4) -#define GLUT_GAME_MODE_REFRESH_RATE ((GLenum) 5) -#define GLUT_GAME_MODE_DISPLAY_CHANGED ((GLenum) 6) - -GLUTAPI void APIENTRY glutGameModeString(const char *string); -GLUTAPI int APIENTRY glutEnterGameMode(void); -GLUTAPI void APIENTRY glutLeaveGameMode(void); -GLUTAPI int APIENTRY glutGameModeGet(GLenum mode); -#endif - -#ifdef __cplusplus -} - -#endif - -#ifdef GLUT_APIENTRY_DEFINED -# undef GLUT_APIENTRY_DEFINED -# undef APIENTRY -#endif - -#ifdef GLUT_WINGDIAPI_DEFINED -# undef GLUT_WINGDIAPI_DEFINED -# undef WINGDIAPI -#endif - -#ifdef GLUT_DEFINED___CDECL -# undef GLUT_DEFINED___CDECL -# undef __cdecl -#endif - -#ifdef GLUT_DEFINED__CRTIMP -# undef GLUT_DEFINED__CRTIMP -# undef _CRTIMP -#endif - -#endif /* __glut_h__ */ +#ifndef __glut_h__ +#define __glut_h__ + +/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998. */ + +/* This program is freely distributable without licensing fees and is + provided without guarantee or warrantee expressed or implied. This + program is -not- in the public domain. */ + +#if defined(_WIN32) + +/* GLUT 3.7 now tries to avoid including + to avoid name space pollution, but Win32's + needs APIENTRY and WINGDIAPI defined properly. */ +# if 0 + /* This would put tons of macros and crap in our clean name space. */ +# define WIN32_LEAN_AND_MEAN +# include +# else + /* XXX This is from Win32's */ +# ifndef APIENTRY +# define GLUT_APIENTRY_DEFINED +# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) || defined(__LCC__) +# define APIENTRY __stdcall +# else +# define APIENTRY +# endif +# endif + /* XXX This is from Win32's */ +# ifndef CALLBACK +# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) || defined(__LCC__) +# define CALLBACK __stdcall +# else +# define CALLBACK +# endif +# endif + /* XXX Hack for lcc compiler. It doesn't support __declspec(dllimport), just __stdcall. */ +# if defined( __LCC__ ) +# undef WINGDIAPI +# define WINGDIAPI __stdcall +# else + /* XXX This is from Win32's and */ +# ifndef WINGDIAPI +# define GLUT_WINGDIAPI_DEFINED +# define WINGDIAPI __declspec(dllimport) +# endif +# endif + /* XXX This is from Win32's */ +# ifndef _WCHAR_T_DEFINED +typedef unsigned short wchar_t; +# define _WCHAR_T_DEFINED +# endif +# endif + +/* To disable automatic library usage for GLUT, define GLUT_NO_LIB_PRAGMA + in your compile preprocessor options. */ +# if !defined(GLUT_BUILDING_LIB) && !defined(GLUT_NO_LIB_PRAGMA) +# pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ +/* To enable automatic SGI OpenGL for Windows library usage for GLUT, + define GLUT_USE_SGI_OPENGL in your compile preprocessor options. */ +# ifdef GLUT_USE_SGI_OPENGL +# pragma comment (lib, "opengl.lib") /* link with SGI OpenGL for Windows lib */ +# pragma comment (lib, "glu.lib") /* link with SGI OpenGL Utility lib */ +# pragma comment (lib, "glut.lib") /* link with Win32 GLUT for SGI OpenGL lib */ +# else +# pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ +# pragma comment (lib, "glu32.lib") /* link with Microsoft OpenGL Utility lib */ +# pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ +# endif +# endif + +/* To disable supression of annoying warnings about floats being promoted + to doubles, define GLUT_NO_WARNING_DISABLE in your compile preprocessor + options. */ +# ifndef GLUT_NO_WARNING_DISABLE +# pragma warning (disable:4244) /* Disable bogus VC++ 4.2 conversion warnings. */ +# pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ +# endif + +/* Win32 has an annoying issue where there are multiple C run-time + libraries (CRTs). If the executable is linked with a different CRT + from the GLUT DLL, the GLUT DLL will not share the same CRT static + data seen by the executable. In particular, atexit callbacks registered + in the executable will not be called if GLUT calls its (different) + exit routine). GLUT is typically built with the + "/MD" option (the CRT with multithreading DLL support), but the Visual + C++ linker default is "/ML" (the single threaded CRT). + + One workaround to this issue is requiring users to always link with + the same CRT as GLUT is compiled with. That requires users supply a + non-standard option. GLUT 3.7 has its own built-in workaround where + the executable's "exit" function pointer is covertly passed to GLUT. + GLUT then calls the executable's exit function pointer to ensure that + any "atexit" calls registered by the application are called if GLUT + needs to exit. + + Note that the __glut*WithExit routines should NEVER be called directly. + To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */ + +/* XXX This is from Win32's */ +# if !defined(_MSC_VER) && !defined(__cdecl) + /* Define __cdecl for non-Microsoft compilers. */ +# define __cdecl +# define GLUT_DEFINED___CDECL +# endif +# ifndef _CRTIMP +# ifdef _NTSDK + /* Definition compatible with NT SDK */ +# define _CRTIMP +# else + /* Current definition */ +# ifdef _DLL +# define _CRTIMP __declspec(dllimport) +# else +# define _CRTIMP +# endif +# endif +# define GLUT_DEFINED__CRTIMP +# endif + +/* GLUT API entry point declarations for Win32. */ +# ifdef GLUT_BUILDING_LIB +# define GLUTAPI __declspec(dllexport) +# else +# ifdef _DLL +# define GLUTAPI __declspec(dllimport) +# else +# define GLUTAPI extern +# endif +# endif + +/* GLUT callback calling convention for Win32. */ +# define GLUTCALLBACK __cdecl + +#endif /* _WIN32 */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_WIN32) +# ifndef GLUT_BUILDING_LIB +extern _CRTIMP void __cdecl exit(int); +# endif +#else +/* non-Win32 case. */ +/* Define APIENTRY and CALLBACK to nothing if we aren't on Win32. */ +# define APIENTRY +# define GLUT_APIENTRY_DEFINED +# define CALLBACK +/* Define GLUTAPI and GLUTCALLBACK as below if we aren't on Win32. */ +# define GLUTAPI extern +# define GLUTCALLBACK +/* Prototype exit for the non-Win32 case (see above). */ +extern void exit(int); +#endif + +/** + GLUT API revision history: + + GLUT_API_VERSION is updated to reflect incompatible GLUT + API changes (interface changes, semantic changes, deletions, + or additions). + + GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 + + GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, + extension. Supports new input devices like tablet, dial and button + box, and Spaceball. Easy to query OpenGL extensions. + + GLUT_API_VERSION=3 glutMenuStatus added. + + GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, + glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic + video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, + glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, + glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). +**/ +#ifndef GLUT_API_VERSION /* allow this to be overriden */ +#define GLUT_API_VERSION 3 +#endif + +/** + GLUT implementation revision history: + + GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT + API revisions and implementation revisions (ie, bug fixes). + + GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of + GLUT Xlib-based implementation. 11/29/94 + + GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of + GLUT Xlib-based implementation providing GLUT version 2 + interfaces. + + GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 + + GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 + + GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 + + GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 + + GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner + and video resize. 1/3/97 + + GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. + + GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. + + GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. + + GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 beta with GameGLUT support. + + GLUT_XLIB_IMPLEMENTATION=14 mjk's GLUT 3.7 beta with f90gl friend interface. + + GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa +**/ +#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ +#define GLUT_XLIB_IMPLEMENTATION 15 +#endif + +/* Display mode bit masks. */ +#define GLUT_RGB 0 +#define GLUT_RGBA GLUT_RGB +#define GLUT_INDEX 1 +#define GLUT_SINGLE 0 +#define GLUT_DOUBLE 2 +#define GLUT_ACCUM 4 +#define GLUT_ALPHA 8 +#define GLUT_DEPTH 16 +#define GLUT_STENCIL 32 +#if (GLUT_API_VERSION >= 2) +#define GLUT_MULTISAMPLE 128 +#define GLUT_STEREO 256 +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_LUMINANCE 512 +#endif + +/* Mouse buttons. */ +#define GLUT_LEFT_BUTTON 0 +#define GLUT_MIDDLE_BUTTON 1 +#define GLUT_RIGHT_BUTTON 2 + +/* Mouse button state. */ +#define GLUT_DOWN 0 +#define GLUT_UP 1 + +#if (GLUT_API_VERSION >= 2) +/* function keys */ +#define GLUT_KEY_F1 1 +#define GLUT_KEY_F2 2 +#define GLUT_KEY_F3 3 +#define GLUT_KEY_F4 4 +#define GLUT_KEY_F5 5 +#define GLUT_KEY_F6 6 +#define GLUT_KEY_F7 7 +#define GLUT_KEY_F8 8 +#define GLUT_KEY_F9 9 +#define GLUT_KEY_F10 10 +#define GLUT_KEY_F11 11 +#define GLUT_KEY_F12 12 +/* directional keys */ +#define GLUT_KEY_LEFT 100 +#define GLUT_KEY_UP 101 +#define GLUT_KEY_RIGHT 102 +#define GLUT_KEY_DOWN 103 +#define GLUT_KEY_PAGE_UP 104 +#define GLUT_KEY_PAGE_DOWN 105 +#define GLUT_KEY_HOME 106 +#define GLUT_KEY_END 107 +#define GLUT_KEY_INSERT 108 +#endif + +/* Entry/exit state. */ +#define GLUT_LEFT 0 +#define GLUT_ENTERED 1 + +/* Menu usage state. */ +#define GLUT_MENU_NOT_IN_USE 0 +#define GLUT_MENU_IN_USE 1 + +/* Visibility state. */ +#define GLUT_NOT_VISIBLE 0 +#define GLUT_VISIBLE 1 + +/* Window status state. */ +#define GLUT_HIDDEN 0 +#define GLUT_FULLY_RETAINED 1 +#define GLUT_PARTIALLY_RETAINED 2 +#define GLUT_FULLY_COVERED 3 + +/* Color index component selection values. */ +#define GLUT_RED 0 +#define GLUT_GREEN 1 +#define GLUT_BLUE 2 + +#if defined(_WIN32) +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN ((void*)0) +#define GLUT_STROKE_MONO_ROMAN ((void*)1) + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 ((void*)2) +#define GLUT_BITMAP_8_BY_13 ((void*)3) +#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) +#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 ((void*)6) +#define GLUT_BITMAP_HELVETICA_12 ((void*)7) +#define GLUT_BITMAP_HELVETICA_18 ((void*)8) +#endif +#else +/* Stroke font opaque addresses (use constants instead in source code). */ +GLUTAPI void *glutStrokeRoman; +GLUTAPI void *glutStrokeMonoRoman; + +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN (&glutStrokeRoman) +#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) + +/* Bitmap font opaque addresses (use constants instead in source code). */ +GLUTAPI void *glutBitmap9By15; +GLUTAPI void *glutBitmap8By13; +GLUTAPI void *glutBitmapTimesRoman10; +GLUTAPI void *glutBitmapTimesRoman24; +GLUTAPI void *glutBitmapHelvetica10; +GLUTAPI void *glutBitmapHelvetica12; +GLUTAPI void *glutBitmapHelvetica18; + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) +#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) +#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) +#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) +#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) +#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) +#endif +#endif + +/* glutGet parameters. */ +#define GLUT_WINDOW_X ((GLenum) 100) +#define GLUT_WINDOW_Y ((GLenum) 101) +#define GLUT_WINDOW_WIDTH ((GLenum) 102) +#define GLUT_WINDOW_HEIGHT ((GLenum) 103) +#define GLUT_WINDOW_BUFFER_SIZE ((GLenum) 104) +#define GLUT_WINDOW_STENCIL_SIZE ((GLenum) 105) +#define GLUT_WINDOW_DEPTH_SIZE ((GLenum) 106) +#define GLUT_WINDOW_RED_SIZE ((GLenum) 107) +#define GLUT_WINDOW_GREEN_SIZE ((GLenum) 108) +#define GLUT_WINDOW_BLUE_SIZE ((GLenum) 109) +#define GLUT_WINDOW_ALPHA_SIZE ((GLenum) 110) +#define GLUT_WINDOW_ACCUM_RED_SIZE ((GLenum) 111) +#define GLUT_WINDOW_ACCUM_GREEN_SIZE ((GLenum) 112) +#define GLUT_WINDOW_ACCUM_BLUE_SIZE ((GLenum) 113) +#define GLUT_WINDOW_ACCUM_ALPHA_SIZE ((GLenum) 114) +#define GLUT_WINDOW_DOUBLEBUFFER ((GLenum) 115) +#define GLUT_WINDOW_RGBA ((GLenum) 116) +#define GLUT_WINDOW_PARENT ((GLenum) 117) +#define GLUT_WINDOW_NUM_CHILDREN ((GLenum) 118) +#define GLUT_WINDOW_COLORMAP_SIZE ((GLenum) 119) +#if (GLUT_API_VERSION >= 2) +#define GLUT_WINDOW_NUM_SAMPLES ((GLenum) 120) +#define GLUT_WINDOW_STEREO ((GLenum) 121) +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_WINDOW_CURSOR ((GLenum) 122) +#endif +#define GLUT_SCREEN_WIDTH ((GLenum) 200) +#define GLUT_SCREEN_HEIGHT ((GLenum) 201) +#define GLUT_SCREEN_WIDTH_MM ((GLenum) 202) +#define GLUT_SCREEN_HEIGHT_MM ((GLenum) 203) +#define GLUT_MENU_NUM_ITEMS ((GLenum) 300) +#define GLUT_DISPLAY_MODE_POSSIBLE ((GLenum) 400) +#define GLUT_INIT_WINDOW_X ((GLenum) 500) +#define GLUT_INIT_WINDOW_Y ((GLenum) 501) +#define GLUT_INIT_WINDOW_WIDTH ((GLenum) 502) +#define GLUT_INIT_WINDOW_HEIGHT ((GLenum) 503) +#define GLUT_INIT_DISPLAY_MODE ((GLenum) 504) +#if (GLUT_API_VERSION >= 2) +#define GLUT_ELAPSED_TIME ((GLenum) 700) +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_WINDOW_FORMAT_ID ((GLenum) 123) +#endif + +#if (GLUT_API_VERSION >= 2) +/* glutDeviceGet parameters. */ +#define GLUT_HAS_KEYBOARD ((GLenum) 600) +#define GLUT_HAS_MOUSE ((GLenum) 601) +#define GLUT_HAS_SPACEBALL ((GLenum) 602) +#define GLUT_HAS_DIAL_AND_BUTTON_BOX ((GLenum) 603) +#define GLUT_HAS_TABLET ((GLenum) 604) +#define GLUT_NUM_MOUSE_BUTTONS ((GLenum) 605) +#define GLUT_NUM_SPACEBALL_BUTTONS ((GLenum) 606) +#define GLUT_NUM_BUTTON_BOX_BUTTONS ((GLenum) 607) +#define GLUT_NUM_DIALS ((GLenum) 608) +#define GLUT_NUM_TABLET_BUTTONS ((GLenum) 609) +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_DEVICE_IGNORE_KEY_REPEAT ((GLenum) 610) +#define GLUT_DEVICE_KEY_REPEAT ((GLenum) 611) +#define GLUT_HAS_JOYSTICK ((GLenum) 612) +#define GLUT_OWNS_JOYSTICK ((GLenum) 613) +#define GLUT_JOYSTICK_BUTTONS ((GLenum) 614) +#define GLUT_JOYSTICK_AXES ((GLenum) 615) +#define GLUT_JOYSTICK_POLL_RATE ((GLenum) 616) +#endif + +#if (GLUT_API_VERSION >= 3) +/* glutLayerGet parameters. */ +#define GLUT_OVERLAY_POSSIBLE ((GLenum) 800) +#define GLUT_LAYER_IN_USE ((GLenum) 801) +#define GLUT_HAS_OVERLAY ((GLenum) 802) +#define GLUT_TRANSPARENT_INDEX ((GLenum) 803) +#define GLUT_NORMAL_DAMAGED ((GLenum) 804) +#define GLUT_OVERLAY_DAMAGED ((GLenum) 805) + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +/* glutVideoResizeGet parameters. */ +#define GLUT_VIDEO_RESIZE_POSSIBLE ((GLenum) 900) +#define GLUT_VIDEO_RESIZE_IN_USE ((GLenum) 901) +#define GLUT_VIDEO_RESIZE_X_DELTA ((GLenum) 902) +#define GLUT_VIDEO_RESIZE_Y_DELTA ((GLenum) 903) +#define GLUT_VIDEO_RESIZE_WIDTH_DELTA ((GLenum) 904) +#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA ((GLenum) 905) +#define GLUT_VIDEO_RESIZE_X ((GLenum) 906) +#define GLUT_VIDEO_RESIZE_Y ((GLenum) 907) +#define GLUT_VIDEO_RESIZE_WIDTH ((GLenum) 908) +#define GLUT_VIDEO_RESIZE_HEIGHT ((GLenum) 909) +#endif + +/* glutUseLayer parameters. */ +#define GLUT_NORMAL ((GLenum) 0) +#define GLUT_OVERLAY ((GLenum) 1) + +/* glutGetModifiers return mask. */ +#define GLUT_ACTIVE_SHIFT 1 +#define GLUT_ACTIVE_CTRL 2 +#define GLUT_ACTIVE_ALT 4 + +/* glutSetCursor parameters. */ +/* Basic arrows. */ +#define GLUT_CURSOR_RIGHT_ARROW 0 +#define GLUT_CURSOR_LEFT_ARROW 1 +/* Symbolic cursor shapes. */ +#define GLUT_CURSOR_INFO 2 +#define GLUT_CURSOR_DESTROY 3 +#define GLUT_CURSOR_HELP 4 +#define GLUT_CURSOR_CYCLE 5 +#define GLUT_CURSOR_SPRAY 6 +#define GLUT_CURSOR_WAIT 7 +#define GLUT_CURSOR_TEXT 8 +#define GLUT_CURSOR_CROSSHAIR 9 +/* Directional cursors. */ +#define GLUT_CURSOR_UP_DOWN 10 +#define GLUT_CURSOR_LEFT_RIGHT 11 +/* Sizing cursors. */ +#define GLUT_CURSOR_TOP_SIDE 12 +#define GLUT_CURSOR_BOTTOM_SIDE 13 +#define GLUT_CURSOR_LEFT_SIDE 14 +#define GLUT_CURSOR_RIGHT_SIDE 15 +#define GLUT_CURSOR_TOP_LEFT_CORNER 16 +#define GLUT_CURSOR_TOP_RIGHT_CORNER 17 +#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18 +#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19 +/* Inherit from parent window. */ +#define GLUT_CURSOR_INHERIT 100 +/* Blank cursor. */ +#define GLUT_CURSOR_NONE 101 +/* Fullscreen crosshair (if available). */ +#define GLUT_CURSOR_FULL_CROSSHAIR 102 +#endif + +/* GLUT initialization sub-API. */ +GLUTAPI void APIENTRY glutInit(int *argcp, char **argv); +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) +GLUTAPI void APIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)); +#ifndef GLUT_BUILDING_LIB +static void APIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); } +#define glutInit glutInit_ATEXIT_HACK +#endif +#endif +GLUTAPI void APIENTRY glutInitDisplayMode(unsigned int mode); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI void APIENTRY glutInitDisplayString(const char *string); +#endif +GLUTAPI void APIENTRY glutInitWindowPosition(int x, int y); +GLUTAPI void APIENTRY glutInitWindowSize(int width, int height); +GLUTAPI void APIENTRY glutMainLoop(void); + +/* GLUT window sub-API. */ +GLUTAPI int APIENTRY glutCreateWindow(const char *title); +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) +GLUTAPI int APIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int)); +#ifndef GLUT_BUILDING_LIB +static int APIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); } +#define glutCreateWindow glutCreateWindow_ATEXIT_HACK +#endif +#endif +GLUTAPI int APIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height); +GLUTAPI void APIENTRY glutDestroyWindow(int win); +GLUTAPI void APIENTRY glutPostRedisplay(void); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) +GLUTAPI void APIENTRY glutPostWindowRedisplay(int win); +#endif +GLUTAPI void APIENTRY glutSwapBuffers(void); +GLUTAPI int APIENTRY glutGetWindow(void); +GLUTAPI void APIENTRY glutSetWindow(int win); +GLUTAPI void APIENTRY glutSetWindowTitle(const char *title); +GLUTAPI void APIENTRY glutSetIconTitle(const char *title); +GLUTAPI void APIENTRY glutPositionWindow(int x, int y); +GLUTAPI void APIENTRY glutReshapeWindow(int width, int height); +GLUTAPI void APIENTRY glutPopWindow(void); +GLUTAPI void APIENTRY glutPushWindow(void); +GLUTAPI void APIENTRY glutIconifyWindow(void); +GLUTAPI void APIENTRY glutShowWindow(void); +GLUTAPI void APIENTRY glutHideWindow(void); +#if (GLUT_API_VERSION >= 3) +GLUTAPI void APIENTRY glutFullScreen(void); +GLUTAPI void APIENTRY glutSetCursor(int cursor); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI void APIENTRY glutWarpPointer(int x, int y); +#endif + +/* GLUT overlay sub-API. */ +GLUTAPI void APIENTRY glutEstablishOverlay(void); +GLUTAPI void APIENTRY glutRemoveOverlay(void); +GLUTAPI void APIENTRY glutUseLayer(GLenum layer); +GLUTAPI void APIENTRY glutPostOverlayRedisplay(void); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11) +GLUTAPI void APIENTRY glutPostWindowOverlayRedisplay(int win); +#endif +GLUTAPI void APIENTRY glutShowOverlay(void); +GLUTAPI void APIENTRY glutHideOverlay(void); +#endif + +/* GLUT menu sub-API. */ +GLUTAPI int APIENTRY glutCreateMenu(void (GLUTCALLBACK *func)(int)); +#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK) +GLUTAPI int APIENTRY __glutCreateMenuWithExit(void (GLUTCALLBACK *func)(int), void (__cdecl *exitfunc)(int)); +#ifndef GLUT_BUILDING_LIB +static int APIENTRY glutCreateMenu_ATEXIT_HACK(void (GLUTCALLBACK *func)(int)) { return __glutCreateMenuWithExit(func, exit); } +#define glutCreateMenu glutCreateMenu_ATEXIT_HACK +#endif +#endif +GLUTAPI void APIENTRY glutDestroyMenu(int menu); +GLUTAPI int APIENTRY glutGetMenu(void); +GLUTAPI void APIENTRY glutSetMenu(int menu); +GLUTAPI void APIENTRY glutAddMenuEntry(const char *label, int value); +GLUTAPI void APIENTRY glutAddSubMenu(const char *label, int submenu); +GLUTAPI void APIENTRY glutChangeToMenuEntry(int item, const char *label, int value); +GLUTAPI void APIENTRY glutChangeToSubMenu(int item, const char *label, int submenu); +GLUTAPI void APIENTRY glutRemoveMenuItem(int item); +GLUTAPI void APIENTRY glutAttachMenu(int button); +GLUTAPI void APIENTRY glutDetachMenu(int button); + +/* GLUT window callback sub-API. */ +GLUTAPI void APIENTRY glutDisplayFunc(void (GLUTCALLBACK *func)(void)); +GLUTAPI void APIENTRY glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height)); +GLUTAPI void APIENTRY glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); +GLUTAPI void APIENTRY glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); +GLUTAPI void APIENTRY glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); +GLUTAPI void APIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); +GLUTAPI void APIENTRY glutEntryFunc(void (GLUTCALLBACK *func)(int state)); +GLUTAPI void APIENTRY glutVisibilityFunc(void (GLUTCALLBACK *func)(int state)); +GLUTAPI void APIENTRY glutIdleFunc(void (GLUTCALLBACK *func)(void)); +GLUTAPI void APIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value); +GLUTAPI void APIENTRY glutMenuStateFunc(void (GLUTCALLBACK *func)(int state)); +#if (GLUT_API_VERSION >= 2) +GLUTAPI void APIENTRY glutSpecialFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); +GLUTAPI void APIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); +GLUTAPI void APIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z)); +GLUTAPI void APIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state)); +GLUTAPI void APIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state)); +GLUTAPI void APIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value)); +GLUTAPI void APIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y)); +GLUTAPI void APIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y)); +#if (GLUT_API_VERSION >= 3) +GLUTAPI void APIENTRY glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y)); +GLUTAPI void APIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK *func)(void)); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI void APIENTRY glutWindowStatusFunc(void (GLUTCALLBACK *func)(int state)); +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +GLUTAPI void APIENTRY glutKeyboardUpFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y)); +GLUTAPI void APIENTRY glutSpecialUpFunc(void (GLUTCALLBACK *func)(int key, int x, int y)); +GLUTAPI void APIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval); +#endif +#endif +#endif + +/* GLUT color index sub-API. */ +GLUTAPI void APIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue); +GLUTAPI GLfloat APIENTRY glutGetColor(int ndx, int component); +GLUTAPI void APIENTRY glutCopyColormap(int win); + +/* GLUT state retrieval sub-API. */ +GLUTAPI int APIENTRY glutGet(GLenum type); +GLUTAPI int APIENTRY glutDeviceGet(GLenum type); +#if (GLUT_API_VERSION >= 2) +/* GLUT extension support sub-API */ +GLUTAPI int APIENTRY glutExtensionSupported(const char *name); +#endif +#if (GLUT_API_VERSION >= 3) +GLUTAPI int APIENTRY glutGetModifiers(void); +GLUTAPI int APIENTRY glutLayerGet(GLenum type); +#endif + +/* GLUT font sub-API */ +GLUTAPI void APIENTRY glutBitmapCharacter(void *font, int character); +GLUTAPI int APIENTRY glutBitmapWidth(void *font, int character); +GLUTAPI void APIENTRY glutStrokeCharacter(void *font, int character); +GLUTAPI int APIENTRY glutStrokeWidth(void *font, int character); +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +GLUTAPI int APIENTRY glutBitmapLength(void *font, const unsigned char *string); +GLUTAPI int APIENTRY glutStrokeLength(void *font, const unsigned char *string); +#endif + +/* GLUT pre-built models sub-API */ +GLUTAPI void APIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks); +GLUTAPI void APIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); +GLUTAPI void APIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +GLUTAPI void APIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks); +GLUTAPI void APIENTRY glutWireCube(GLdouble size); +GLUTAPI void APIENTRY glutSolidCube(GLdouble size); +GLUTAPI void APIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +GLUTAPI void APIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings); +GLUTAPI void APIENTRY glutWireDodecahedron(void); +GLUTAPI void APIENTRY glutSolidDodecahedron(void); +GLUTAPI void APIENTRY glutWireTeapot(GLdouble size); +GLUTAPI void APIENTRY glutSolidTeapot(GLdouble size); +GLUTAPI void APIENTRY glutWireOctahedron(void); +GLUTAPI void APIENTRY glutSolidOctahedron(void); +GLUTAPI void APIENTRY glutWireTetrahedron(void); +GLUTAPI void APIENTRY glutSolidTetrahedron(void); +GLUTAPI void APIENTRY glutWireIcosahedron(void); +GLUTAPI void APIENTRY glutSolidIcosahedron(void); + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9) +/* GLUT video resize sub-API. */ +GLUTAPI int APIENTRY glutVideoResizeGet(GLenum param); +GLUTAPI void APIENTRY glutSetupVideoResizing(void); +GLUTAPI void APIENTRY glutStopVideoResizing(void); +GLUTAPI void APIENTRY glutVideoResize(int x, int y, int width, int height); +GLUTAPI void APIENTRY glutVideoPan(int x, int y, int width, int height); + +/* GLUT debugging sub-API. */ +GLUTAPI void APIENTRY glutReportErrors(void); +#endif + +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +/* GLUT device control sub-API. */ +/* glutSetKeyRepeat modes. */ +#define GLUT_KEY_REPEAT_OFF 0 +#define GLUT_KEY_REPEAT_ON 1 +#define GLUT_KEY_REPEAT_DEFAULT 2 + +/* Joystick button masks. */ +#define GLUT_JOYSTICK_BUTTON_A 1 +#define GLUT_JOYSTICK_BUTTON_B 2 +#define GLUT_JOYSTICK_BUTTON_C 4 +#define GLUT_JOYSTICK_BUTTON_D 8 + +GLUTAPI void APIENTRY glutIgnoreKeyRepeat(int ignore); +GLUTAPI void APIENTRY glutSetKeyRepeat(int repeatMode); +GLUTAPI void APIENTRY glutForceJoystickFunc(void); + +/* GLUT game mode sub-API. */ +/* glutGameModeGet. */ +#define GLUT_GAME_MODE_ACTIVE ((GLenum) 0) +#define GLUT_GAME_MODE_POSSIBLE ((GLenum) 1) +#define GLUT_GAME_MODE_WIDTH ((GLenum) 2) +#define GLUT_GAME_MODE_HEIGHT ((GLenum) 3) +#define GLUT_GAME_MODE_PIXEL_DEPTH ((GLenum) 4) +#define GLUT_GAME_MODE_REFRESH_RATE ((GLenum) 5) +#define GLUT_GAME_MODE_DISPLAY_CHANGED ((GLenum) 6) + +GLUTAPI void APIENTRY glutGameModeString(const char *string); +GLUTAPI int APIENTRY glutEnterGameMode(void); +GLUTAPI void APIENTRY glutLeaveGameMode(void); +GLUTAPI int APIENTRY glutGameModeGet(GLenum mode); +#endif + +#ifdef __cplusplus +} + +#endif + +#ifdef GLUT_APIENTRY_DEFINED +# undef GLUT_APIENTRY_DEFINED +# undef APIENTRY +#endif + +#ifdef GLUT_WINGDIAPI_DEFINED +# undef GLUT_WINGDIAPI_DEFINED +# undef WINGDIAPI +#endif + +#ifdef GLUT_DEFINED___CDECL +# undef GLUT_DEFINED___CDECL +# undef __cdecl +#endif + +#ifdef GLUT_DEFINED__CRTIMP +# undef GLUT_DEFINED__CRTIMP +# undef _CRTIMP +#endif + +#endif /* __glut_h__ */ diff --git a/samples/glut/README-win32.txt b/samples/glut/README-win32.txt index 5e22e9789..f3c1cbaa5 100644 --- a/samples/glut/README-win32.txt +++ b/samples/glut/README-win32.txt @@ -1,613 +1,613 @@ - - - GLUT for Win32 README - --------------------- - - -VERSION/INFO: - - This is GLUT for Win32 version 3.7.6 as of Nov 8th 2001. - See the COPYRIGHT section for distribution and copyright notices. - Send all bug reports and questions for this version of GLUT to - Nate Robins [nate@pobox.com]. - - For more information about GLUT for Win32, see the web page: - www.pobox.com/~nate/glut.html or subscribe to the GLUT for Win32 - mailing list by sending e-mail to majordomo@perp.com with - "subscribe glut" in the body of the message. - - For general information about GLUT, see the GLUT web page: - http://reality.sgi.com/opengl/glut3/glut3.html and be sure to - check the GLUT FAQ first for any questions that you may have: - http://reality.sgi.com/opengl/glut3/glut-faq.html - - -COMPILING/INSTALLATION: - - o Precompiled versions of the DLL and import library can be - found on the GLUT for Win32 web page mentioned above. - - o Microsoft Developer Studio 6 workspace and project files have - been included in the source code distribution. - - To build the glut dll: - First, open Microsoft Developer Studio. - Then, select File -> Open Workspace and find the glut.dsw file - in the file dialog and double-click on it. - Finally, select Build -> Build glut32.dll. - When the build is finished, it will copy: - glut32.dll to %WinDir%\System, - glut32.lib to $(MSDevDir)\..\..\VC98\lib, and - glut.h to $(MSDevDir)\..\..\VC98\include\GL. - - Additional workspace files have been included in the progs, test - and lib directories to build the progs, tests and libs respectively. - - -BORLAND NOTES: - - From what I understand, Borland supplies a utility that - converts Microsoft Visual C++ .libs into Borland compatible - files. Therefore, the best method for Borland users is - probably to get the precompiled versions of the library and - convert the library. To create an import library for Borland - from the DLLs, use the following command (from a command prompt): - IMPLIB glut32.lib glut32.dll - If IMPLIB crashes when called this way, try - IMPLIB glut32.lib glut32.def - using the glut32.def file in this distribution. - - -FORTRAN NOTES: - - Bill Mitchell [william.mitchell@nist.gov] has put considerable - effort into getting GLUT to work with different compilers for - Fortran 90. He indicates that you should copy the f90glut.h - file to your $(MSDevDir)\..\..\VC98\include\GL directory. - Then, just build GLUT as usual. The Fortran 90 interface, f90gl, - can be obtained at http://math.nist.gov/f90gl and contains - installation instructions and usage examples. - - -MISC NOTES: - - o Overlay support is not implemented, nor are there any plans to - implement it in the near future. - - o To customize the windows icon, you can use the resource name - GLUT_ICON. For example, create an icon named "glut.ico", and - create a file called glut.rc that contains the following: - GLUT_ICON ICON glut.ico - then compile the glut.rc file with the following: - rc /r glut - and link the resulting glut.res file into your executable - (just like you would an object file). - Alternatively, you can simply add the glut.rc file to your - project if you are using Microsoft Developer Studio. - - -IMPLEMENTATION DEPENDENT DIFFERENCES: - - There are a few differences between the Win32 version of GLUT - and the X11 version of GLUT. Those are outlined here. Note - that MOST of these differences are allowed by the GLUT - specification. Bugs and unsupported features are outlined in - the UNSUPPORTED/BUGS section. - - o glutInit: - The following command line options have no meaning (and are - ignored) in GLUT for Win32: - -display, -indirect, -direct, -sync. - - o glutInitWindowPosition, glutPositionWindow: - Win32 has two different coordinate systems for windows. - One is in terms of client space and the other is the whole - window space (including the decorations). If you - glutPositionWindow(0, 0), GLUT for Win32 will place the - window CLIENT area at 0, 0. This will cause the window - decorations (title bar and left edge) to be OFF-SCREEN, but - it gives the user the most flexibility in positioning. - HOWEVER, if the user specifies glutInitWindowPosition(0, 0), - the window is placed relative to window space at 0, 0. - This will cause the window to be opened in the upper left - corner with all the decorations showing. This behaviour is - acceptable under the current GLUT specification. - - o glutSetIconTitle, glutSetWindowTitle: - There is no separation between Icon title and Window title - in Win32. Therefore, setting an icon title in Win32 has - no effect. - - o glutSetCursor: - As indicated in the GLUT specification, cursors may be - different on different platforms. This is the case in GLUT - for Win32. For the most part, the cursors will match the - meaning, but not necessarily the shape. Notable exceptions - are the GLUT_CURSOR_INFO & GLUT_CURSOR_SPRAY which use the - crosshair cursor and the GLUT_CURSOR_CYCLE which uses the - 'no' or 'destroy' cursor in Win32. - - o glutVisibilityFunc: - Win32 seems to be unable to determine if a window is fully - obscured. Therefore, the visibility of a GLUT window is - only reflected by its Iconic, Hidden or Shown state. That - is, even if a window is fully obscured, in GLUT for Win32, - it is still "visible". - - o glutEntryFunc: - Window Focus is handled differently in Win32 and X. - Specifically, the "window manager" in Win32 uses a "click to - focus" policy. That is, in order for a window to receive - focus, a mouse button must be clicked in it. Likewise, in - order for a window to lose focus, a mouse button must be - clicked outside the window (or in another window). - Therefore, the Enter and Leave notification provided by GLUT - may behave differently in the Win32 and in X11 versions. - There is a viable workaround for this. A program called - "Tweak UI" is provided by Microsoft which can be used to - change the focus policy in Win32 to "focus follows mouse". - It is available from the Microsoft Web Pages: - http://www.microsoft.com/windows/software/PowerToy.htm - - o glutCopyColormap: - GLUT for Win32 always copies the colormap. There is never - any sharing of colormaps. This is probably okay, since - Win32 merges the logical palette and the physical palette - anyway, so even if there are two windows with totally - different colors in their colormaps, Win32 will find a - (hopefully) good match between them. - - o glutIdleFunc + menus: - The glut idle function will NOT be called when a menu is - active. This causes all animation to stop when a menu is - active (in general, this is probably okay). Timer - functions will still fire, however. If the timer callback - draws into the rendering context, the drawing will not show - up until after the menu has finished, though. - - -UNSUPPORTED/BUGS: - - o glutAttachMenu: - Win32 only likes to work with left and right mouse buttons. - Especially so with popup menus. Therefore, when attaching - the menu to the middle mouse button, the LEFT mouse button - must be used to select from the menu. - - o glutSpaceball*, glutButtonBox*, glutTablet*, glutDials*: - None of the special input devices are supported at this - time. - - o When resizing or moving a GLUT for Win32 window, no updating - is performed. This causes the window to leave "tracks" on - the screen when getting bigger or when previously obscured - parts are being revealed. I put in a bit of a kludgy - workaround for those that absolutely can't have the weird - lines. The reshape callback is called multiple times for - reshapes. Therefore, in the reshape callback, some drawing - can be done. It should probably be limited to a color buffer - clear. - - o The video resizing capabilities of GLUT 3.3+ for X11 is - currently unimplemented (this is probably ok, since it - really isn't part of the spec until 4.0). I doubt that - this will ever be part of GLUT for Win32, since there is no - hardware to support it. A hack could simply change the - resolution of the desktop. - - -CHANGES/FIXES: - - (Nov 8, '01) - x Released 3.7.6 - - (Nov 8, '01) - x Changed fullscreen mode from TOPMOST back to simply TOP, since - (it turns out) many people use windows atop a GLUT window. - - (Nov 8, '01) - x Added code to prevent CPU spiking when no idle function is - registered. Otherwise, if an idle function is registered, spike - CPU so that the idle function gets all the attention it needs and - if this is a problem on the program side, the user can stick a - sleep() in their idle function. I believe that this strikes the - best balance betweeen GLUT being fast, and also being "nice" to - other processes. Thanks to James Wright for reporting this bug. - - (Nov 8, '01) - x Fixed bug in motion callback handler which wasn't setting the - current window, so multiple window apps (e.g., any GLUI app) - wouldn't get the callback correctly. - - (Oct 4, '01) - x Fixed bug in glutEnterGameMode() that caused new windows to not - be in "fullscreen" mode, so they got window decorations. - - (Oct 4, '01) - x Fixed bug in glutEnterGameMode() that caused new windows to not - be in "fullscreen" mode, so they got window decorations. - - (Oct 3, '01) - x Fixed bug in getVisualInfoFromString(): visuals not reloaded on - display mode change. Reload visuals each time they are queried. - This fixes a problem with Win32 because the list of availabe Visuals - (Pixelformats) changes after a change in displaymode. The problem - occurs when switching to gamemode and back. Thanks to Michael - Wimmer for pointing this out & providing the fix. - - (Oct 3, '01) - x Fixed bug in XGetVisualInfo(): pixelformats enumerated incorrectly. - Passing 0 as a pixelformat index to DescribePixelFormat gives - unpredictible results (e.g., this fails on the Voodoo opengl32.dll - and always reports 0 as the last available pixelformat index). - Thanks to Michael Wimmer for pointing this out & providing the fix. - - (Oct 3, '01) - x Fixed bug in glXGetConfig(): pixelformats enumerated incorrectly. The - test was OpenGL support OR draw to window, but should be AND. Thanks - to Michael Wimmer for pointing this out & providing the fix. - - (Sep 28, '01) - x Fixed glutChangeToSubMenu()/glutChangeToMenuEntry() bug where if you - went back and forth between a submenu and a plain entry, the submenu - wouldn't be updated properly. - - (Sep 28, '01) - x glutSetIconTitle() is now a nop. - - (Sep 28, '01) - x glutFullScreen() now sets the window as TOPMOST, therefore, the - window will always be on top (this essentially disables alt-tabbing). - - (Sep 28, '01) - x The key repeat ignore flag is now honored correctly. - - (Sep 28, '01) - x Key presses are now reported more accurately and fully, in - particular, modified up events (i.e., SHIFT-2) are now reported - correctly. - - (Sep 28, '01) - x Subwindows nested arbitrarily deep get their keyboard callbacks - correctly now. - - (Sep 28, '01) - x Major rewrite of the window procedure code to clean it up and make - way for other bug fixes. - - (Sep 23, '01) - x Fixed noof example program to use RAND_MAX instead of assumed - max of 2147483647.0. (Now it looks _much_ better!) - - (Sep 22, '01) - x Fixed sunlight example program. globe.raw data file was corrupt, - added a new one. - - (Sep 22, '01) - x Fixed zcomposite example program to print message if overlay - support is not found (instead of crashing). - - (Jan 22, '01) - x Fixed malloc(0) bug in Win32 version of XGetVisualInfo. Thanks - to Kekoa Proudfoot for bringing this to my attention. - - (Dec 12, '00) - x Added data files for the advanced & advanced97 programs. - - (Dec 12, '00) - x Added Developer Studio 6 project and workspace files for pretty - much everything (the stuff left out was usually unix specific). - - (Dec 7, '00) - x Fixed several compilation problems & corrupt files. Thanks to - Alexander Stohr for bringing these to my attention and providing - detailed fixes. - - (Dec 6, '00) - x Fixed compiler support for lcc. Thanks to Gordon for bringing - this to my attention and debugging fixes. - - (Nov 8, '00) - x Fixed submenu problem (sometimes the menu callback was not - called for valid items). Thanks to Michael Keeley. - - (Oct 16, '00) - x Corrected corrupt duck.iv file. Thanks to Jon Willeke for finding - this problem. - - (Sept 27, '00) - x Fixed bug in processWorkList that could cause a hang. Thanks to - Bill Volz & Daniel Azuma. - - (Sept 26, '00) - x Added mui DLL project file (thanks to DMWeldy@ugsolutions.com). - - (Sept 9, '00) - x Fixed Delete key bug (crash when no keyboard callback was - registered, but a special key callback was). Thanks to - Kent Bowling (kent_bowling@hotmail.com) for finding this bug. - - (May 18, '00) - x Fixed subwindow keyboard callbacks. - - (May 22, '97) - o Menus don't work under Windows 95 - x Fixed! Added a unique identifier to each menu item, and a - search function to grab a menu item given the unique identifier. - - (May 21, '97) - o A few minor bug fixes here and there. - x Thanks to Bruce Silberman and Chris Vale for their help with - this. We now have a DLL! - - (Apr 25, '97) - o DLL version of the library is coming (as soon as I figure out - how to do it -- if you know, let me know). - x Thanks to Bruce Silberman and Chris Vale for their help with - this. We now have a DLL! - - (Apr 24, '97) - x Added returns to KEY_DOWN etc messages so that the F10 key - doesn't toggle the system menu anymore. - - (Apr 7, '97) - o Palette is incorrect for modes other than TrueColor. - x Fixed this by forcing a default palette in modes that aren't - Truecolor in order to 'simulate' it. The applications - program shouldn't have to do this IMHO, but I guess we - can't argue with Microsoft (well, we can, but what good - will it do?). - - (Apr 2, '97) - x Added glut.ide file for Borland users. - - (Apr 2, '97) - x Fixed a bug in the WM_QUERYNEWPALETTE message. Wasn't - checking for a null colormap, then de-ref'd it. Oops. - - (Mar 13, '97) - o glutTimerFunc: - Currently, GLUT for Win32 programs busy waits when there is - an outstanding timer event (i.e., there is no select() - call). I haven't found this to be a problem, but I plan to - fix it just because I can't bear the thought of a busy wait. - x Added a timer event and a wait in the main loop. This fixes - the CPU spike. - - (Mar 11, '97) - x Fixed subwindow visibility. The visibility callback of - subwindows wasn't being called, now it is. - - (Mar 11, '97) - o glutGetHDC, glutGetHWND: - In order to support additional dialog boxes, wgl fonts, and - a host of other Win32 dependent structures, two functions - have been added that operate on the current window in GLUT. - The first (glutGetHDC) returns a handle to the current - windows device context. The second (glutGetHWND) returns - handle to the current window. - x Took these out to preserve GLUT portability. - - (Mar 11, '97) - x Fixed the glutWarpPointer() coordinates. Were relative to - the screen, now relative to window (client area) origin - (which is what they're supposed to be). - - (Mar 11, '97) - o glutCreateMenu, glutIdleFunc: - Menu's are modal in Win32. That is, they don't allow any - messages to be processed while they are up. Therefore, if - an idle function exists, it will not be called while - processing a menu. - x Fixed! I've put in a timer function that fires every - millisecond while a menu is up. The timer function handles - idle and timer events only (which should be the only - functions that are firing when a menu is up anyway). - - (Mar 7 '97) - x Fixed minor bugs tracked down by the example programs. - - (Mar 6, '97) - x Merged 3.3 GLUT for X11 into 3.2 GLUT for Win32. New code - structure allows for EASY merging! - - o In Win32, the parent gets the right to set the cursor of - any of its children. Therefore, a child windows cursor - will 'blink' between its cursor and its parent. - x Fixed this by checking whether the cursor is in a child - window or not. - - (Feb 28 '97) - o On initial bringup apps are getting 2 display callbacks. - x Fixed by the Fev 28 re-write. - - o Some multiple window (not subwindow) functionality is messed up. - See the sphere.exe program. - x Fixed by the Feb 28 re-write. - - o GLUT for Win32 supports color index mode ONLY in a paletted - display mode (i.e., 256 or 16 color mode). - x Fixed this in the re-write. If you can get a color index - visual (pixel format) you can use color index mode. - - (Feb 28 '97) - o Quite a few bugs (and incompatibilities) were being caused - by the structure that I used in the previous port of GLUT. - Therefore I decided that it would be best to "get back to - the roots". I re-implemented most of glut trying to stick - with the structure layed out by Mark. The result is a much - more stable version that passes ALL (!) (except overlay) - the tests provided by Mark. In addition, this new - structure will allow future enhancements by Mark to be - integrated much more quickly into the Win32 version. Also, - I'm now ordering the bugs in reverse, so that the most - recently fixed appear at the top of the list. - - (9/8/96) - o Changed the glutGetModifiers code to produce an error if not - called in the core input callbacks. - - (9/11/96) - o If the alt key is pressed with more than one other modifier key - it acts as if it is stuck -- it stays selected until pressed - and released again. - x Fixed. - - (9/12/96) - o When a submenu is attached to a menu, sometimes a GPF occurs. - Fixed. Needed to set the submenu before referencing it's members. - - o Kenny: Also, one little problem, I attached the menu to the - right-button, but when the left-button is pressed I detach - it to give the right-button new meaning; if I pop-up the menu and I - don't want to select anything, like most users, I click off of the - menu to make it disappear. When I do this, I get a GLUT error and - the program terminates because I am altering the menu attachment - from within the button press while the menu is active. - x Fixed. Needed to finish the menu when the user presses the button, - not just when a button is released. - - o GLUT for Win32 emulates a middle mouse button by checking if - both mouse buttons are down. This causes a lot of problems with - the menu and other multiple mouse button things. - x Fixed. No more middle mouse button emulation. Perhaps it would - be a good idea to emulate the middle mouse button (if not present) - with a key? - - (9/15/96) - o Added code to accept a user defined icon. If no icon is provided, - a default icon is loaded. - - (9/19/96) - o Shane: Command line options seem to be screwed up. (9/13) - x Fixed. The geometry command line was broken, and so was the - gldebug command line. - - o Fixed a bug in the default glut reshape. It was looking for the - parent of the current window and GPF'ing if there wasn't a parent. - Put in a check for a parent, and if none is there, use the - child. - - o Idle function sucks up all processor cycles. (9/8/96) - x I don't know if this is avoidable. If you have a tight rendering - loop, it may be that the processor time is going to be sucked up - no matter what. You can add a sleep() to the end of your render - loop if you would like to yeild to other processes and you don't - care too much about the speed of your rendering loop. If you have - Hardware that supports OpenGL (like a 3Dpro card, or GLint card) - then this should be less of a problem, since it won't be rendering - in software. (9/11/96) - - o If a window is fully obscured by another window, the visibility - callback is NOT called. As far as I can tell, this is a limitation - of the Win32 api, but a workaround is being searched for. (9/8/96) - x Limitation of the Win32 API - - o Fixed the entry functions. They only work if the keyboard focus - changes. Therefore, in most Win32 systems, the mouse must be - pressed outside of the window to get a GLUT_LEFT message and - then pressed inside the window for a GLUT_ENTERED message. - - o Alt modifier key doesn't work with keyboard callback. (9/8/96) - x Probably okay, because the glut spec says that these keys can - be intercepted by the system (which the alt key is...) (9/11/96) - - (11/17/96) - o glutRemoveMenuItem() not working properly. - x Thanks to Gary (grc@maple.civeng.rutgers.edu) for the fix to - this one. - - o Timer functions are messed up. - x Thanks to Joseph Galbraith for the fix to this one. - - (12/9/96) - o One (minor) difference came up between the X version of glut - and the nt one which you should know about. It is not a new - problem, and it concerns co-ords returned to the pointer - callbacks. (glutMotionFunc, glutMouseFunc) - Under X, you get co-ords in the range 0 +/- 2^15, under NT - you get 0..2^16. This is only really a problem when moving - above or to the left of the window. - eg dragging one pixel ABOVE the window will give :- - under x11 : y = -1 - under nt : y = 2^16 -1 - x Put in fix provided by Shane Clauson. - - (12/17/96) - o Idle functions not working properly for multiple windows. - x Fixed this by posting an idle message to every window in the - window list when idle. - - (12/18/96) - o glutSetCursor() was misbehaving (lthomas@cco.caltech.edu). - x Win32 requires that the hCursor member of the window class - be set to NULL when the class is registered or whenever the - mouse is moved, the original cursor is replaced (go - figure!). Now sets the cursor whenever a WM_MOUSEMOVE message - is received, because the WM_SETCURSOR event resets the cursor - even when in the decoration area. - - o Geometry is not being handled quite right. The numbers don't - take into account the window decorations. That is, if I say - make a window 100x100, then the WHOLE window (not just the - client area) is 100x100. Therefore, the client (opengl) area - is smaller than 100x100. (9/8/96) - x Fixed. Added code to subtract the decoration size on glutGet() - and add the decoration size on glutReshapeWindow(). - - o Multiple glutPostRedisplay() calls are NOT being combined. - To get round the "coalesce" problem on glutPostRedisplay, - the easiest solution is to roll-your-own coalesce by - keeping a global "dirty" flag in the app (eg replace all - calls to glutPostRedisplay with image_dirty=TRUE;), and to - handle image_dirty with a single glutPostRedisplay in the - idle callback when required. (erk - but increases - performance for my particular app (a rendering engine on - the end of a pipleine with a stream of graphics updates) by - a couple of orders of magnitude ! ) (9/8/96) - x Added code to coalesce redisplays. Every idle cycle, a - check is made to see which windows need redisplay, if they - need it, a redisplay is posted. The glutPostRedisplay() - call is just a stub that sets a flag. - - -THANKS: - - Special thanks to the following people for extensive testing, - suggestions, fixes and help: - - Alexander Stohr - Shane Clauson - Kenny Hoff - Richard Readings - Paul McQuesten - Philip Winston - JaeWoo Ahn - Joseph Galbraith - Paula Higgins - Sam Fortin - Chris Vale - Bill Mitchell - - and of course, the original author of GLUT: - Mark Kilgard. - - and many others... - - -COPYRIGHT: - -The OpenGL Utility Toolkit distribution for Win32 (Windows NT & -Windows 95) contains source code modified from the original source -code for GLUT version 3.3 which was developed by Mark J. Kilgard. The -original source code for GLUT is Copyright 1997 by Mark J. Kilgard. -GLUT for Win32 is Copyright 1997 by Nate Robins and is not in the -public domain, but it is freely distributable without licensing fees. -It is provided without guarantee or warrantee expressed or implied. -It was ported with the permission of Mark J. Kilgard by Nate Robins. - -THIS SOURCE CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OR MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -OpenGL (R) is a registered trademark of Silicon Graphics, Inc. + + + GLUT for Win32 README + --------------------- + + +VERSION/INFO: + + This is GLUT for Win32 version 3.7.6 as of Nov 8th 2001. + See the COPYRIGHT section for distribution and copyright notices. + Send all bug reports and questions for this version of GLUT to + Nate Robins [nate@pobox.com]. + + For more information about GLUT for Win32, see the web page: + www.pobox.com/~nate/glut.html or subscribe to the GLUT for Win32 + mailing list by sending e-mail to majordomo@perp.com with + "subscribe glut" in the body of the message. + + For general information about GLUT, see the GLUT web page: + http://reality.sgi.com/opengl/glut3/glut3.html and be sure to + check the GLUT FAQ first for any questions that you may have: + http://reality.sgi.com/opengl/glut3/glut-faq.html + + +COMPILING/INSTALLATION: + + o Precompiled versions of the DLL and import library can be + found on the GLUT for Win32 web page mentioned above. + + o Microsoft Developer Studio 6 workspace and project files have + been included in the source code distribution. + + To build the glut dll: + First, open Microsoft Developer Studio. + Then, select File -> Open Workspace and find the glut.dsw file + in the file dialog and double-click on it. + Finally, select Build -> Build glut32.dll. + When the build is finished, it will copy: + glut32.dll to %WinDir%\System, + glut32.lib to $(MSDevDir)\..\..\VC98\lib, and + glut.h to $(MSDevDir)\..\..\VC98\include\GL. + + Additional workspace files have been included in the progs, test + and lib directories to build the progs, tests and libs respectively. + + +BORLAND NOTES: + + From what I understand, Borland supplies a utility that + converts Microsoft Visual C++ .libs into Borland compatible + files. Therefore, the best method for Borland users is + probably to get the precompiled versions of the library and + convert the library. To create an import library for Borland + from the DLLs, use the following command (from a command prompt): + IMPLIB glut32.lib glut32.dll + If IMPLIB crashes when called this way, try + IMPLIB glut32.lib glut32.def + using the glut32.def file in this distribution. + + +FORTRAN NOTES: + + Bill Mitchell [william.mitchell@nist.gov] has put considerable + effort into getting GLUT to work with different compilers for + Fortran 90. He indicates that you should copy the f90glut.h + file to your $(MSDevDir)\..\..\VC98\include\GL directory. + Then, just build GLUT as usual. The Fortran 90 interface, f90gl, + can be obtained at http://math.nist.gov/f90gl and contains + installation instructions and usage examples. + + +MISC NOTES: + + o Overlay support is not implemented, nor are there any plans to + implement it in the near future. + + o To customize the windows icon, you can use the resource name + GLUT_ICON. For example, create an icon named "glut.ico", and + create a file called glut.rc that contains the following: + GLUT_ICON ICON glut.ico + then compile the glut.rc file with the following: + rc /r glut + and link the resulting glut.res file into your executable + (just like you would an object file). + Alternatively, you can simply add the glut.rc file to your + project if you are using Microsoft Developer Studio. + + +IMPLEMENTATION DEPENDENT DIFFERENCES: + + There are a few differences between the Win32 version of GLUT + and the X11 version of GLUT. Those are outlined here. Note + that MOST of these differences are allowed by the GLUT + specification. Bugs and unsupported features are outlined in + the UNSUPPORTED/BUGS section. + + o glutInit: + The following command line options have no meaning (and are + ignored) in GLUT for Win32: + -display, -indirect, -direct, -sync. + + o glutInitWindowPosition, glutPositionWindow: + Win32 has two different coordinate systems for windows. + One is in terms of client space and the other is the whole + window space (including the decorations). If you + glutPositionWindow(0, 0), GLUT for Win32 will place the + window CLIENT area at 0, 0. This will cause the window + decorations (title bar and left edge) to be OFF-SCREEN, but + it gives the user the most flexibility in positioning. + HOWEVER, if the user specifies glutInitWindowPosition(0, 0), + the window is placed relative to window space at 0, 0. + This will cause the window to be opened in the upper left + corner with all the decorations showing. This behaviour is + acceptable under the current GLUT specification. + + o glutSetIconTitle, glutSetWindowTitle: + There is no separation between Icon title and Window title + in Win32. Therefore, setting an icon title in Win32 has + no effect. + + o glutSetCursor: + As indicated in the GLUT specification, cursors may be + different on different platforms. This is the case in GLUT + for Win32. For the most part, the cursors will match the + meaning, but not necessarily the shape. Notable exceptions + are the GLUT_CURSOR_INFO & GLUT_CURSOR_SPRAY which use the + crosshair cursor and the GLUT_CURSOR_CYCLE which uses the + 'no' or 'destroy' cursor in Win32. + + o glutVisibilityFunc: + Win32 seems to be unable to determine if a window is fully + obscured. Therefore, the visibility of a GLUT window is + only reflected by its Iconic, Hidden or Shown state. That + is, even if a window is fully obscured, in GLUT for Win32, + it is still "visible". + + o glutEntryFunc: + Window Focus is handled differently in Win32 and X. + Specifically, the "window manager" in Win32 uses a "click to + focus" policy. That is, in order for a window to receive + focus, a mouse button must be clicked in it. Likewise, in + order for a window to lose focus, a mouse button must be + clicked outside the window (or in another window). + Therefore, the Enter and Leave notification provided by GLUT + may behave differently in the Win32 and in X11 versions. + There is a viable workaround for this. A program called + "Tweak UI" is provided by Microsoft which can be used to + change the focus policy in Win32 to "focus follows mouse". + It is available from the Microsoft Web Pages: + http://www.microsoft.com/windows/software/PowerToy.htm + + o glutCopyColormap: + GLUT for Win32 always copies the colormap. There is never + any sharing of colormaps. This is probably okay, since + Win32 merges the logical palette and the physical palette + anyway, so even if there are two windows with totally + different colors in their colormaps, Win32 will find a + (hopefully) good match between them. + + o glutIdleFunc + menus: + The glut idle function will NOT be called when a menu is + active. This causes all animation to stop when a menu is + active (in general, this is probably okay). Timer + functions will still fire, however. If the timer callback + draws into the rendering context, the drawing will not show + up until after the menu has finished, though. + + +UNSUPPORTED/BUGS: + + o glutAttachMenu: + Win32 only likes to work with left and right mouse buttons. + Especially so with popup menus. Therefore, when attaching + the menu to the middle mouse button, the LEFT mouse button + must be used to select from the menu. + + o glutSpaceball*, glutButtonBox*, glutTablet*, glutDials*: + None of the special input devices are supported at this + time. + + o When resizing or moving a GLUT for Win32 window, no updating + is performed. This causes the window to leave "tracks" on + the screen when getting bigger or when previously obscured + parts are being revealed. I put in a bit of a kludgy + workaround for those that absolutely can't have the weird + lines. The reshape callback is called multiple times for + reshapes. Therefore, in the reshape callback, some drawing + can be done. It should probably be limited to a color buffer + clear. + + o The video resizing capabilities of GLUT 3.3+ for X11 is + currently unimplemented (this is probably ok, since it + really isn't part of the spec until 4.0). I doubt that + this will ever be part of GLUT for Win32, since there is no + hardware to support it. A hack could simply change the + resolution of the desktop. + + +CHANGES/FIXES: + + (Nov 8, '01) + x Released 3.7.6 + + (Nov 8, '01) + x Changed fullscreen mode from TOPMOST back to simply TOP, since + (it turns out) many people use windows atop a GLUT window. + + (Nov 8, '01) + x Added code to prevent CPU spiking when no idle function is + registered. Otherwise, if an idle function is registered, spike + CPU so that the idle function gets all the attention it needs and + if this is a problem on the program side, the user can stick a + sleep() in their idle function. I believe that this strikes the + best balance betweeen GLUT being fast, and also being "nice" to + other processes. Thanks to James Wright for reporting this bug. + + (Nov 8, '01) + x Fixed bug in motion callback handler which wasn't setting the + current window, so multiple window apps (e.g., any GLUI app) + wouldn't get the callback correctly. + + (Oct 4, '01) + x Fixed bug in glutEnterGameMode() that caused new windows to not + be in "fullscreen" mode, so they got window decorations. + + (Oct 4, '01) + x Fixed bug in glutEnterGameMode() that caused new windows to not + be in "fullscreen" mode, so they got window decorations. + + (Oct 3, '01) + x Fixed bug in getVisualInfoFromString(): visuals not reloaded on + display mode change. Reload visuals each time they are queried. + This fixes a problem with Win32 because the list of availabe Visuals + (Pixelformats) changes after a change in displaymode. The problem + occurs when switching to gamemode and back. Thanks to Michael + Wimmer for pointing this out & providing the fix. + + (Oct 3, '01) + x Fixed bug in XGetVisualInfo(): pixelformats enumerated incorrectly. + Passing 0 as a pixelformat index to DescribePixelFormat gives + unpredictible results (e.g., this fails on the Voodoo opengl32.dll + and always reports 0 as the last available pixelformat index). + Thanks to Michael Wimmer for pointing this out & providing the fix. + + (Oct 3, '01) + x Fixed bug in glXGetConfig(): pixelformats enumerated incorrectly. The + test was OpenGL support OR draw to window, but should be AND. Thanks + to Michael Wimmer for pointing this out & providing the fix. + + (Sep 28, '01) + x Fixed glutChangeToSubMenu()/glutChangeToMenuEntry() bug where if you + went back and forth between a submenu and a plain entry, the submenu + wouldn't be updated properly. + + (Sep 28, '01) + x glutSetIconTitle() is now a nop. + + (Sep 28, '01) + x glutFullScreen() now sets the window as TOPMOST, therefore, the + window will always be on top (this essentially disables alt-tabbing). + + (Sep 28, '01) + x The key repeat ignore flag is now honored correctly. + + (Sep 28, '01) + x Key presses are now reported more accurately and fully, in + particular, modified up events (i.e., SHIFT-2) are now reported + correctly. + + (Sep 28, '01) + x Subwindows nested arbitrarily deep get their keyboard callbacks + correctly now. + + (Sep 28, '01) + x Major rewrite of the window procedure code to clean it up and make + way for other bug fixes. + + (Sep 23, '01) + x Fixed noof example program to use RAND_MAX instead of assumed + max of 2147483647.0. (Now it looks _much_ better!) + + (Sep 22, '01) + x Fixed sunlight example program. globe.raw data file was corrupt, + added a new one. + + (Sep 22, '01) + x Fixed zcomposite example program to print message if overlay + support is not found (instead of crashing). + + (Jan 22, '01) + x Fixed malloc(0) bug in Win32 version of XGetVisualInfo. Thanks + to Kekoa Proudfoot for bringing this to my attention. + + (Dec 12, '00) + x Added data files for the advanced & advanced97 programs. + + (Dec 12, '00) + x Added Developer Studio 6 project and workspace files for pretty + much everything (the stuff left out was usually unix specific). + + (Dec 7, '00) + x Fixed several compilation problems & corrupt files. Thanks to + Alexander Stohr for bringing these to my attention and providing + detailed fixes. + + (Dec 6, '00) + x Fixed compiler support for lcc. Thanks to Gordon for bringing + this to my attention and debugging fixes. + + (Nov 8, '00) + x Fixed submenu problem (sometimes the menu callback was not + called for valid items). Thanks to Michael Keeley. + + (Oct 16, '00) + x Corrected corrupt duck.iv file. Thanks to Jon Willeke for finding + this problem. + + (Sept 27, '00) + x Fixed bug in processWorkList that could cause a hang. Thanks to + Bill Volz & Daniel Azuma. + + (Sept 26, '00) + x Added mui DLL project file (thanks to DMWeldy@ugsolutions.com). + + (Sept 9, '00) + x Fixed Delete key bug (crash when no keyboard callback was + registered, but a special key callback was). Thanks to + Kent Bowling (kent_bowling@hotmail.com) for finding this bug. + + (May 18, '00) + x Fixed subwindow keyboard callbacks. + + (May 22, '97) + o Menus don't work under Windows 95 + x Fixed! Added a unique identifier to each menu item, and a + search function to grab a menu item given the unique identifier. + + (May 21, '97) + o A few minor bug fixes here and there. + x Thanks to Bruce Silberman and Chris Vale for their help with + this. We now have a DLL! + + (Apr 25, '97) + o DLL version of the library is coming (as soon as I figure out + how to do it -- if you know, let me know). + x Thanks to Bruce Silberman and Chris Vale for their help with + this. We now have a DLL! + + (Apr 24, '97) + x Added returns to KEY_DOWN etc messages so that the F10 key + doesn't toggle the system menu anymore. + + (Apr 7, '97) + o Palette is incorrect for modes other than TrueColor. + x Fixed this by forcing a default palette in modes that aren't + Truecolor in order to 'simulate' it. The applications + program shouldn't have to do this IMHO, but I guess we + can't argue with Microsoft (well, we can, but what good + will it do?). + + (Apr 2, '97) + x Added glut.ide file for Borland users. + + (Apr 2, '97) + x Fixed a bug in the WM_QUERYNEWPALETTE message. Wasn't + checking for a null colormap, then de-ref'd it. Oops. + + (Mar 13, '97) + o glutTimerFunc: + Currently, GLUT for Win32 programs busy waits when there is + an outstanding timer event (i.e., there is no select() + call). I haven't found this to be a problem, but I plan to + fix it just because I can't bear the thought of a busy wait. + x Added a timer event and a wait in the main loop. This fixes + the CPU spike. + + (Mar 11, '97) + x Fixed subwindow visibility. The visibility callback of + subwindows wasn't being called, now it is. + + (Mar 11, '97) + o glutGetHDC, glutGetHWND: + In order to support additional dialog boxes, wgl fonts, and + a host of other Win32 dependent structures, two functions + have been added that operate on the current window in GLUT. + The first (glutGetHDC) returns a handle to the current + windows device context. The second (glutGetHWND) returns + handle to the current window. + x Took these out to preserve GLUT portability. + + (Mar 11, '97) + x Fixed the glutWarpPointer() coordinates. Were relative to + the screen, now relative to window (client area) origin + (which is what they're supposed to be). + + (Mar 11, '97) + o glutCreateMenu, glutIdleFunc: + Menu's are modal in Win32. That is, they don't allow any + messages to be processed while they are up. Therefore, if + an idle function exists, it will not be called while + processing a menu. + x Fixed! I've put in a timer function that fires every + millisecond while a menu is up. The timer function handles + idle and timer events only (which should be the only + functions that are firing when a menu is up anyway). + + (Mar 7 '97) + x Fixed minor bugs tracked down by the example programs. + + (Mar 6, '97) + x Merged 3.3 GLUT for X11 into 3.2 GLUT for Win32. New code + structure allows for EASY merging! + + o In Win32, the parent gets the right to set the cursor of + any of its children. Therefore, a child windows cursor + will 'blink' between its cursor and its parent. + x Fixed this by checking whether the cursor is in a child + window or not. + + (Feb 28 '97) + o On initial bringup apps are getting 2 display callbacks. + x Fixed by the Fev 28 re-write. + + o Some multiple window (not subwindow) functionality is messed up. + See the sphere.exe program. + x Fixed by the Feb 28 re-write. + + o GLUT for Win32 supports color index mode ONLY in a paletted + display mode (i.e., 256 or 16 color mode). + x Fixed this in the re-write. If you can get a color index + visual (pixel format) you can use color index mode. + + (Feb 28 '97) + o Quite a few bugs (and incompatibilities) were being caused + by the structure that I used in the previous port of GLUT. + Therefore I decided that it would be best to "get back to + the roots". I re-implemented most of glut trying to stick + with the structure layed out by Mark. The result is a much + more stable version that passes ALL (!) (except overlay) + the tests provided by Mark. In addition, this new + structure will allow future enhancements by Mark to be + integrated much more quickly into the Win32 version. Also, + I'm now ordering the bugs in reverse, so that the most + recently fixed appear at the top of the list. + + (9/8/96) + o Changed the glutGetModifiers code to produce an error if not + called in the core input callbacks. + + (9/11/96) + o If the alt key is pressed with more than one other modifier key + it acts as if it is stuck -- it stays selected until pressed + and released again. + x Fixed. + + (9/12/96) + o When a submenu is attached to a menu, sometimes a GPF occurs. + Fixed. Needed to set the submenu before referencing it's members. + + o Kenny: Also, one little problem, I attached the menu to the + right-button, but when the left-button is pressed I detach + it to give the right-button new meaning; if I pop-up the menu and I + don't want to select anything, like most users, I click off of the + menu to make it disappear. When I do this, I get a GLUT error and + the program terminates because I am altering the menu attachment + from within the button press while the menu is active. + x Fixed. Needed to finish the menu when the user presses the button, + not just when a button is released. + + o GLUT for Win32 emulates a middle mouse button by checking if + both mouse buttons are down. This causes a lot of problems with + the menu and other multiple mouse button things. + x Fixed. No more middle mouse button emulation. Perhaps it would + be a good idea to emulate the middle mouse button (if not present) + with a key? + + (9/15/96) + o Added code to accept a user defined icon. If no icon is provided, + a default icon is loaded. + + (9/19/96) + o Shane: Command line options seem to be screwed up. (9/13) + x Fixed. The geometry command line was broken, and so was the + gldebug command line. + + o Fixed a bug in the default glut reshape. It was looking for the + parent of the current window and GPF'ing if there wasn't a parent. + Put in a check for a parent, and if none is there, use the + child. + + o Idle function sucks up all processor cycles. (9/8/96) + x I don't know if this is avoidable. If you have a tight rendering + loop, it may be that the processor time is going to be sucked up + no matter what. You can add a sleep() to the end of your render + loop if you would like to yeild to other processes and you don't + care too much about the speed of your rendering loop. If you have + Hardware that supports OpenGL (like a 3Dpro card, or GLint card) + then this should be less of a problem, since it won't be rendering + in software. (9/11/96) + + o If a window is fully obscured by another window, the visibility + callback is NOT called. As far as I can tell, this is a limitation + of the Win32 api, but a workaround is being searched for. (9/8/96) + x Limitation of the Win32 API + + o Fixed the entry functions. They only work if the keyboard focus + changes. Therefore, in most Win32 systems, the mouse must be + pressed outside of the window to get a GLUT_LEFT message and + then pressed inside the window for a GLUT_ENTERED message. + + o Alt modifier key doesn't work with keyboard callback. (9/8/96) + x Probably okay, because the glut spec says that these keys can + be intercepted by the system (which the alt key is...) (9/11/96) + + (11/17/96) + o glutRemoveMenuItem() not working properly. + x Thanks to Gary (grc@maple.civeng.rutgers.edu) for the fix to + this one. + + o Timer functions are messed up. + x Thanks to Joseph Galbraith for the fix to this one. + + (12/9/96) + o One (minor) difference came up between the X version of glut + and the nt one which you should know about. It is not a new + problem, and it concerns co-ords returned to the pointer + callbacks. (glutMotionFunc, glutMouseFunc) + Under X, you get co-ords in the range 0 +/- 2^15, under NT + you get 0..2^16. This is only really a problem when moving + above or to the left of the window. + eg dragging one pixel ABOVE the window will give :- + under x11 : y = -1 + under nt : y = 2^16 -1 + x Put in fix provided by Shane Clauson. + + (12/17/96) + o Idle functions not working properly for multiple windows. + x Fixed this by posting an idle message to every window in the + window list when idle. + + (12/18/96) + o glutSetCursor() was misbehaving (lthomas@cco.caltech.edu). + x Win32 requires that the hCursor member of the window class + be set to NULL when the class is registered or whenever the + mouse is moved, the original cursor is replaced (go + figure!). Now sets the cursor whenever a WM_MOUSEMOVE message + is received, because the WM_SETCURSOR event resets the cursor + even when in the decoration area. + + o Geometry is not being handled quite right. The numbers don't + take into account the window decorations. That is, if I say + make a window 100x100, then the WHOLE window (not just the + client area) is 100x100. Therefore, the client (opengl) area + is smaller than 100x100. (9/8/96) + x Fixed. Added code to subtract the decoration size on glutGet() + and add the decoration size on glutReshapeWindow(). + + o Multiple glutPostRedisplay() calls are NOT being combined. + To get round the "coalesce" problem on glutPostRedisplay, + the easiest solution is to roll-your-own coalesce by + keeping a global "dirty" flag in the app (eg replace all + calls to glutPostRedisplay with image_dirty=TRUE;), and to + handle image_dirty with a single glutPostRedisplay in the + idle callback when required. (erk - but increases + performance for my particular app (a rendering engine on + the end of a pipleine with a stream of graphics updates) by + a couple of orders of magnitude ! ) (9/8/96) + x Added code to coalesce redisplays. Every idle cycle, a + check is made to see which windows need redisplay, if they + need it, a redisplay is posted. The glutPostRedisplay() + call is just a stub that sets a flag. + + +THANKS: + + Special thanks to the following people for extensive testing, + suggestions, fixes and help: + + Alexander Stohr + Shane Clauson + Kenny Hoff + Richard Readings + Paul McQuesten + Philip Winston + JaeWoo Ahn + Joseph Galbraith + Paula Higgins + Sam Fortin + Chris Vale + Bill Mitchell + + and of course, the original author of GLUT: + Mark Kilgard. + + and many others... + + +COPYRIGHT: + +The OpenGL Utility Toolkit distribution for Win32 (Windows NT & +Windows 95) contains source code modified from the original source +code for GLUT version 3.3 which was developed by Mark J. Kilgard. The +original source code for GLUT is Copyright 1997 by Mark J. Kilgard. +GLUT for Win32 is Copyright 1997 by Nate Robins and is not in the +public domain, but it is freely distributable without licensing fees. +It is provided without guarantee or warrantee expressed or implied. +It was ported with the permission of Mark J. Kilgard by Nate Robins. + +THIS SOURCE CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OR MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + +OpenGL (R) is a registered trademark of Silicon Graphics, Inc. diff --git a/test/models-nonbsd/3D/mar_rifle.source.txt b/test/models-nonbsd/3D/mar_rifle.source.txt index ac8721d26..c0cd5fe6d 100644 --- a/test/models-nonbsd/3D/mar_rifle.source.txt +++ b/test/models-nonbsd/3D/mar_rifle.source.txt @@ -1,18 +1,18 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008. -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008. +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" diff --git a/test/models-nonbsd/3DS/cart_wheel.source.txt b/test/models-nonbsd/3DS/cart_wheel.source.txt index ab926db96..6f43a3a22 100644 --- a/test/models-nonbsd/3DS/cart_wheel.source.txt +++ b/test/models-nonbsd/3DS/cart_wheel.source.txt @@ -1,18 +1,18 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" diff --git a/test/models-nonbsd/3DS/jeep1.3ds.readme.txt b/test/models-nonbsd/3DS/jeep1.3ds.readme.txt index 14b0bd9eb..d17d5e0e9 100644 --- a/test/models-nonbsd/3DS/jeep1.3ds.readme.txt +++ b/test/models-nonbsd/3DS/jeep1.3ds.readme.txt @@ -1,15 +1,15 @@ -Jeep designed, modelled and skinned by me, Psionic - -FREE for use however you like, credits are appreciated!!! - -It was modelled in Milkshape 3D and includes the MS3D files oriented for X or B3D format (BlitzBasic 3D), its 2032 polys with a 512x512 jpg texture map. There are two skin variations plus a UV template to help out if you want to create your own skin variations. - -I'd love to see a few screenshots of it being used in-game so feel free to stop by my site and maybe drop by my forums and show us all what your doing with it!!!!!!! - -Check out more of my work at:- - -http://xu1productions.com/3dstudio/index.html - 3D Game Resources - -http://www.psionicdesign.com - My Main 2D/3D Digital Art site - +Jeep designed, modelled and skinned by me, Psionic + +FREE for use however you like, credits are appreciated!!! + +It was modelled in Milkshape 3D and includes the MS3D files oriented for X or B3D format (BlitzBasic 3D), its 2032 polys with a 512x512 jpg texture map. There are two skin variations plus a UV template to help out if you want to create your own skin variations. + +I'd love to see a few screenshots of it being used in-game so feel free to stop by my site and maybe drop by my forums and show us all what your doing with it!!!!!!! + +Check out more of my work at:- + +http://xu1productions.com/3dstudio/index.html - 3D Game Resources + +http://www.psionicdesign.com - My Main 2D/3D Digital Art site + Psionic 2002 \ No newline at end of file diff --git a/test/models-nonbsd/3DS/mar_rifle.source.txt b/test/models-nonbsd/3DS/mar_rifle.source.txt index ab926db96..6f43a3a22 100644 --- a/test/models-nonbsd/3DS/mar_rifle.source.txt +++ b/test/models-nonbsd/3DS/mar_rifle.source.txt @@ -1,18 +1,18 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" diff --git a/test/models-nonbsd/3DS/mp5_sil.source.txt b/test/models-nonbsd/3DS/mp5_sil.source.txt index ab926db96..6f43a3a22 100644 --- a/test/models-nonbsd/3DS/mp5_sil.source.txt +++ b/test/models-nonbsd/3DS/mp5_sil.source.txt @@ -1,18 +1,18 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" diff --git a/test/models-nonbsd/3DS/pyramob.3ds.readme.txt b/test/models-nonbsd/3DS/pyramob.3ds.readme.txt index 7f6cf0361..bf1858410 100644 --- a/test/models-nonbsd/3DS/pyramob.3ds.readme.txt +++ b/test/models-nonbsd/3DS/pyramob.3ds.readme.txt @@ -1,12 +1,12 @@ -hello! - -fell free to use the object...so do what U want! -& sent me your pictures...:-) -for commercial use, contact me! - -http://www.elektrobar.com/lux/ - -or mail to: -lux@elektrobar.com - +hello! + +fell free to use the object...so do what U want! +& sent me your pictures...:-) +for commercial use, contact me! + +http://www.elektrobar.com/lux/ + +or mail to: +lux@elektrobar.com + have fun.....VIRLUX \ No newline at end of file diff --git a/test/models-nonbsd/ASE/Rifle.source.txt b/test/models-nonbsd/ASE/Rifle.source.txt index 914c69466..04d40a85d 100644 --- a/test/models-nonbsd/ASE/Rifle.source.txt +++ b/test/models-nonbsd/ASE/Rifle.source.txt @@ -1,25 +1,25 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" - - - -INFO -==== - +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" + + + +INFO +==== + CONVERTED FROM 3DS TO ASE WITH AC3D \ No newline at end of file diff --git a/test/models-nonbsd/ASE/Rifle2.source.txt b/test/models-nonbsd/ASE/Rifle2.source.txt index f0dda0b20..2072ddf13 100644 --- a/test/models-nonbsd/ASE/Rifle2.source.txt +++ b/test/models-nonbsd/ASE/Rifle2.source.txt @@ -1,24 +1,24 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" - - -INFO -==== - +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" + + +INFO +==== + CONVERTED FROM 3DS TO ASE WITH AC3D \ No newline at end of file diff --git a/test/models-nonbsd/B3D/dwarf.source.txt b/test/models-nonbsd/B3D/dwarf.source.txt index c062dcabf..1a0040fba 100644 --- a/test/models-nonbsd/B3D/dwarf.source.txt +++ b/test/models-nonbsd/B3D/dwarf.source.txt @@ -1,51 +1,51 @@ -Dwarf lowpoly model Pack -Copyright 2004, Psionic Design -e-mail: psionic@blueyonder.co.uk -Used with permission. - - -INSTALLATION INSTRUCTIONS: - -To install, simply unzip to your hard drive with the "Use Folder Names" option turned on. And that's it you're ready to go! - - - -USAGE INFORMATION: - -Each zip contains the models, textures and animation info for that particular format! - -Please Read the "animationinfo.txt" file included in each zip for the exact frames of animation to use - -Credits to me "Psionic" are really appreciated but are not essential ;-) - -Any questions, screenshots of him in use etc drop by my site or email me at:- - -website: http://www.psionic3d.co.uk -email: psionic@blueyonder.co.uk - - - - -WHAT'S INCLUDED IN THE ZIP: - -ReadMe.txt - This file -b3d.zip - Blitz 3D Format models and textures -ms3d.zip - Milkshape 3D Format models and textures -x.zip - DarkBasic Direct X 8 Format models and textures - - - -RESTRICTIONS: - -This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- - -**You may not sell/re-sell this model pack or claim it as your own. -***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent. - - -Psi -http://www.psionic3d.co.uk - - - - +Dwarf lowpoly model Pack +Copyright 2004, Psionic Design +e-mail: psionic@blueyonder.co.uk +Used with permission. + + +INSTALLATION INSTRUCTIONS: + +To install, simply unzip to your hard drive with the "Use Folder Names" option turned on. And that's it you're ready to go! + + + +USAGE INFORMATION: + +Each zip contains the models, textures and animation info for that particular format! + +Please Read the "animationinfo.txt" file included in each zip for the exact frames of animation to use + +Credits to me "Psionic" are really appreciated but are not essential ;-) + +Any questions, screenshots of him in use etc drop by my site or email me at:- + +website: http://www.psionic3d.co.uk +email: psionic@blueyonder.co.uk + + + + +WHAT'S INCLUDED IN THE ZIP: + +ReadMe.txt - This file +b3d.zip - Blitz 3D Format models and textures +ms3d.zip - Milkshape 3D Format models and textures +x.zip - DarkBasic Direct X 8 Format models and textures + + + +RESTRICTIONS: + +This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- + +**You may not sell/re-sell this model pack or claim it as your own. +***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent. + + +Psi +http://www.psionic3d.co.uk + + + + diff --git a/test/models-nonbsd/B3D/turtle.source.txt b/test/models-nonbsd/B3D/turtle.source.txt index 187fa95a7..fab387bdc 100644 --- a/test/models-nonbsd/B3D/turtle.source.txt +++ b/test/models-nonbsd/B3D/turtle.source.txt @@ -1,11 +1,11 @@ -turtle1.b3d -Copyright 2004, Psionic Design -e-mail: psionic@blueyonder.co.uk -Used with permission. - -RESTRICTIONS: - -This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- - -**You may not sell/re-sell this model pack or claim it as your own. +turtle1.b3d +Copyright 2004, Psionic Design +e-mail: psionic@blueyonder.co.uk +Used with permission. + +RESTRICTIONS: + +This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- + +**You may not sell/re-sell this model pack or claim it as your own. ***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent. \ No newline at end of file diff --git a/test/models-nonbsd/BLEND/bob.source.txt b/test/models-nonbsd/BLEND/bob.source.txt index ac86757d1..592693550 100644 --- a/test/models-nonbsd/BLEND/bob.source.txt +++ b/test/models-nonbsd/BLEND/bob.source.txt @@ -1,31 +1,31 @@ - ----------------------------------------------------------------------------------------------- -TITLE : Bob, MD5 character source file -AUTHOR : Ken Beyer (kat) -EMAIL ADDRESS : info@katsbits.com -HOMEPAGE URL : http://www.katsbits.com - - -MODEL NAME/s -Zip file contains *.blend source file and TGA texture assets for MD5 format testing. -Files and media are provided "as is" without any explicit or implied warranty of fuctionality. - - -DISTRIBUTION -Copyright © 2009 KatsBits. Distribution MUST include this readme and authorship attribution. -Commercial use is permitted with written licensed permission. ----------------------------------------------------------------------------------------------- - -Files: - - Bob.md5mesh - - Bob.md5anim - - Bob.blend - - ./*.png - -Changes: - - converted all tga's to png, updated .blend and .md5mesh accordingly - - removed absolute texture paths from the md5mesh file - - minor downscaling of all textures to fit in less bytes - - - + +---------------------------------------------------------------------------------------------- +TITLE : Bob, MD5 character source file +AUTHOR : Ken Beyer (kat) +EMAIL ADDRESS : info@katsbits.com +HOMEPAGE URL : http://www.katsbits.com + + +MODEL NAME/s +Zip file contains *.blend source file and TGA texture assets for MD5 format testing. +Files and media are provided "as is" without any explicit or implied warranty of fuctionality. + + +DISTRIBUTION +Copyright © 2009 KatsBits. Distribution MUST include this readme and authorship attribution. +Commercial use is permitted with written licensed permission. +---------------------------------------------------------------------------------------------- + +Files: + - Bob.md5mesh + - Bob.md5anim + - Bob.blend + - ./*.png + +Changes: + - converted all tga's to png, updated .blend and .md5mesh accordingly + - removed absolute texture paths from the md5mesh file + - minor downscaling of all textures to fit in less bytes + + + diff --git a/test/models-nonbsd/DXF/rifle.source.txt b/test/models-nonbsd/DXF/rifle.source.txt index f37e2cf8d..3e88f009f 100644 --- a/test/models-nonbsd/DXF/rifle.source.txt +++ b/test/models-nonbsd/DXF/rifle.source.txt @@ -1,23 +1,23 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" - -INFO -==== - +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" + +INFO +==== + COnverted from 3ds to DXF with Ac3D \ No newline at end of file diff --git a/test/models-nonbsd/IFC/linklist.txt b/test/models-nonbsd/IFC/linklist.txt index 041435c50..06ad3844b 100644 --- a/test/models-nonbsd/IFC/linklist.txt +++ b/test/models-nonbsd/IFC/linklist.txt @@ -1,4 +1,4 @@ -Good IFC test cases -=================== - +Good IFC test cases +=================== + http://www.iai.fzk.de/www-extern/index.php?id=1135 \ No newline at end of file diff --git a/test/models-nonbsd/IRR/skybox/credits.txt b/test/models-nonbsd/IRR/skybox/credits.txt index 0b2135e88..b2b601392 100644 --- a/test/models-nonbsd/IRR/skybox/credits.txt +++ b/test/models-nonbsd/IRR/skybox/credits.txt @@ -1,11 +1,11 @@ -This skybox is basing on a skydome texture from - -http://mikepan.homeip.net/earth - -Downloaded November 22th, 08 -Distribution note: -"These royalty-free skydome textures work best when applied to a sphere or hemisphere" - - - -Thanks for your great work! +This skybox is basing on a skydome texture from + +http://mikepan.homeip.net/earth + +Downloaded November 22th, 08 +Distribution note: +"These royalty-free skydome textures work best when applied to a sphere or hemisphere" + + + +Thanks for your great work! diff --git a/test/models-nonbsd/LWO/LWO2/LWSReferences/QuickDraw.source.txt b/test/models-nonbsd/LWO/LWO2/LWSReferences/QuickDraw.source.txt index 80dc1df4e..bb07f8e24 100644 --- a/test/models-nonbsd/LWO/LWO2/LWSReferences/QuickDraw.source.txt +++ b/test/models-nonbsd/LWO/LWO2/LWSReferences/QuickDraw.source.txt @@ -1,31 +1,31 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -"These 3d models are contributed by John Hoffman and are based on -characters from a cartoon show called "Jayce and the wheel warriors" -(except the marauder) John's site: http://www3.sympatico.ca/john.hoffman" - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" - - - -INFO -==== - - -These files belong to the QuickDraw model in the LWS folder - they are referenced +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +"These 3d models are contributed by John Hoffman and are based on +characters from a cartoon show called "Jayce and the wheel warriors" +(except the marauder) John's site: http://www3.sympatico.ca/john.hoffman" + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" + + + +INFO +==== + + +These files belong to the QuickDraw model in the LWS folder - they are referenced and loaded into the LWS scene. \ No newline at end of file diff --git a/test/models-nonbsd/LWO/LWO2/rifle.source.txt b/test/models-nonbsd/LWO/LWO2/rifle.source.txt index 02680a50a..34576f0ca 100644 --- a/test/models-nonbsd/LWO/LWO2/rifle.source.txt +++ b/test/models-nonbsd/LWO/LWO2/rifle.source.txt @@ -1,24 +1,24 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" - - -INFO -==== - +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" + + +INFO +==== + CONVERTED FROM 3DS TO LWO2 WITH AC3D \ No newline at end of file diff --git a/test/models-nonbsd/LWS/QuickDraw v2.2.source.txt b/test/models-nonbsd/LWS/QuickDraw v2.2.source.txt index a40f330e5..e0c7d0f7c 100644 --- a/test/models-nonbsd/LWS/QuickDraw v2.2.source.txt +++ b/test/models-nonbsd/LWS/QuickDraw v2.2.source.txt @@ -1,15 +1,15 @@ -From http://telias.free.fr - - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, lightwave and md2 format. Also a great collection of textures to use in your favorite modelling and rendering program. -All the content is free for any use. -In the future more 3d formats will be added and some other sections such as wallpapers, 3d screensavers, 3d coding source code and tutorials. -" - - -CHANGES: +From http://telias.free.fr + + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, lightwave and md2 format. Also a great collection of textures to use in your favorite modelling and rendering program. +All the content is free for any use. +In the future more 3d formats will be added and some other sections such as wallpapers, 3d screensavers, 3d coding source code and tutorials. +" + + +CHANGES: Paths have been modified \ No newline at end of file diff --git a/test/models-nonbsd/MD2/source.txt b/test/models-nonbsd/MD2/source.txt index ab926db96..6f43a3a22 100644 --- a/test/models-nonbsd/MD2/source.txt +++ b/test/models-nonbsd/MD2/source.txt @@ -1,18 +1,18 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notice found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notice found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" diff --git a/test/models-nonbsd/MD3/q3root/models/mapobjects/kt_kubalwagon/readme_kubalwagon.txt b/test/models-nonbsd/MD3/q3root/models/mapobjects/kt_kubalwagon/readme_kubalwagon.txt index 9b56b97c4..e0a978ee0 100644 --- a/test/models-nonbsd/MD3/q3root/models/mapobjects/kt_kubalwagon/readme_kubalwagon.txt +++ b/test/models-nonbsd/MD3/q3root/models/mapobjects/kt_kubalwagon/readme_kubalwagon.txt @@ -1,26 +1,26 @@ -------------------------------------------------------------------------- - -TITLE : kt_kubalwagon -AUTHOR : ken 'kat' beyer -EMAIL ADDRESS : cpdt@telinco.co.uk -HOMEPAGE URL : http://www.quake3bits.co.uk -NUMBER OF MODELS : 1 -SHADER SCRIPTS : yes - included - ------------------- -* MODEL NAME/s * -[model details below] -european_fnt_v2.md3 - -euro_rnt_2.tga (alpha'd steering wheel) -european_fnt.tga - - ------------------- - -CREDITS -ID software, eskimo roll, EMSIPE, QkenneyQ -DISTRIBUTION -as long as this readme is included...! - +------------------------------------------------------------------------- + +TITLE : kt_kubalwagon +AUTHOR : ken 'kat' beyer +EMAIL ADDRESS : cpdt@telinco.co.uk +HOMEPAGE URL : http://www.quake3bits.co.uk +NUMBER OF MODELS : 1 +SHADER SCRIPTS : yes - included + +------------------ +* MODEL NAME/s * +[model details below] +european_fnt_v2.md3 + +euro_rnt_2.tga (alpha'd steering wheel) +european_fnt.tga + + +------------------ + +CREDITS +ID software, eskimo roll, EMSIPE, QkenneyQ +DISTRIBUTION +as long as this readme is included...! + -------------------------------------------------------------------------- \ No newline at end of file diff --git a/test/models-nonbsd/MD3/readme_water.txt b/test/models-nonbsd/MD3/readme_water.txt index d80e7eb0e..cdc318ff8 100644 --- a/test/models-nonbsd/MD3/readme_water.txt +++ b/test/models-nonbsd/MD3/readme_water.txt @@ -1,26 +1,26 @@ -------------------------------------------------------------------------- - -TITLE : kt_watercan -AUTHOR : ken 'kat' beyer -EMAIL ADDRESS : cpdt@telinco.co.uk -HOMEPAGE URL : http://www.quake3bits.co.uk -NUMBER OF MODELS : 2 -SHADER SCRIPTS : n/a - ------------------- -* MODEL NAME/s * -[model details below] -watercan.md3 -watercan_dmg.md3 (dmg='damaged') - -water_can.tga 256x128 - - ------------------- - -CREDITS -ID software, eskimo roll, EMSIPE, QkenneyQ -DISTRIBUTION -as long as this readme is included...! - +------------------------------------------------------------------------- + +TITLE : kt_watercan +AUTHOR : ken 'kat' beyer +EMAIL ADDRESS : cpdt@telinco.co.uk +HOMEPAGE URL : http://www.quake3bits.co.uk +NUMBER OF MODELS : 2 +SHADER SCRIPTS : n/a + +------------------ +* MODEL NAME/s * +[model details below] +watercan.md3 +watercan_dmg.md3 (dmg='damaged') + +water_can.tga 256x128 + + +------------------ + +CREDITS +ID software, eskimo roll, EMSIPE, QkenneyQ +DISTRIBUTION +as long as this readme is included...! + -------------------------------------------------------------------------- \ No newline at end of file diff --git a/test/models-nonbsd/MD5/BoarMan.source.txt b/test/models-nonbsd/MD5/BoarMan.source.txt index cbba6edf6..50b2dfb53 100644 --- a/test/models-nonbsd/MD5/BoarMan.source.txt +++ b/test/models-nonbsd/MD5/BoarMan.source.txt @@ -1,8 +1,8 @@ - -License: Creative Commons - - Remix - - Share alike - - Attribution Author: zphr (Christian Lenke) - - - + +License: Creative Commons + - Remix + - Share alike + - Attribution Author: zphr (Christian Lenke) + + + diff --git a/test/models-nonbsd/MD5/bob.source.txt b/test/models-nonbsd/MD5/bob.source.txt index ac86757d1..592693550 100644 --- a/test/models-nonbsd/MD5/bob.source.txt +++ b/test/models-nonbsd/MD5/bob.source.txt @@ -1,31 +1,31 @@ - ----------------------------------------------------------------------------------------------- -TITLE : Bob, MD5 character source file -AUTHOR : Ken Beyer (kat) -EMAIL ADDRESS : info@katsbits.com -HOMEPAGE URL : http://www.katsbits.com - - -MODEL NAME/s -Zip file contains *.blend source file and TGA texture assets for MD5 format testing. -Files and media are provided "as is" without any explicit or implied warranty of fuctionality. - - -DISTRIBUTION -Copyright © 2009 KatsBits. Distribution MUST include this readme and authorship attribution. -Commercial use is permitted with written licensed permission. ----------------------------------------------------------------------------------------------- - -Files: - - Bob.md5mesh - - Bob.md5anim - - Bob.blend - - ./*.png - -Changes: - - converted all tga's to png, updated .blend and .md5mesh accordingly - - removed absolute texture paths from the md5mesh file - - minor downscaling of all textures to fit in less bytes - - - + +---------------------------------------------------------------------------------------------- +TITLE : Bob, MD5 character source file +AUTHOR : Ken Beyer (kat) +EMAIL ADDRESS : info@katsbits.com +HOMEPAGE URL : http://www.katsbits.com + + +MODEL NAME/s +Zip file contains *.blend source file and TGA texture assets for MD5 format testing. +Files and media are provided "as is" without any explicit or implied warranty of fuctionality. + + +DISTRIBUTION +Copyright © 2009 KatsBits. Distribution MUST include this readme and authorship attribution. +Commercial use is permitted with written licensed permission. +---------------------------------------------------------------------------------------------- + +Files: + - Bob.md5mesh + - Bob.md5anim + - Bob.blend + - ./*.png + +Changes: + - converted all tga's to png, updated .blend and .md5mesh accordingly + - removed absolute texture paths from the md5mesh file + - minor downscaling of all textures to fit in less bytes + + + diff --git a/test/models-nonbsd/MDL/IDPO (Quake1)/gijoe-readme.txt b/test/models-nonbsd/MDL/IDPO (Quake1)/gijoe-readme.txt index 93afb7cb1..2febb0583 100644 --- a/test/models-nonbsd/MDL/IDPO (Quake1)/gijoe-readme.txt +++ b/test/models-nonbsd/MDL/IDPO (Quake1)/gijoe-readme.txt @@ -1,73 +1,73 @@ -Title : G.I.Joe Skins -Filename : joemodel.zip -Version : 1 -Date : 11/05/97 -Author : Kenneth Whelan -Email : JWHELAN@pop.prodigy.net -Credits : id software, Larry Hama, Steven Polge, and Rene Post for making Quake ME - - - -Build time: ??? Time??? - -Type of Mod ------------ -Quake C : no -Sound : no -MDL : Yes - - -Format of QuakeC (if a Quake C Mod) ------------------------------------ -unified diff : no -context diff : no -.qc files : no -progs.dat : no - - -Description of the Modification -------------------------------- - -This is a new player.mdl for quake. It's main use is for bots. The Skins are Snake Eyes v4, Duke v3, Low-Light, -Storm Shadow v2, Shockwave, Repeater, Gung-Ho, Shipwreck, Dusty v3, and -Tunnel Rat v2. - - - -Known bugs -None that I know of. - -How to Install the Modification -------------------------------- - -First back up the current player.mdl(copy player.mdl player.bak). Just put -it in the progs dir in the hack your using, if any. - -Technical Details ------------------ - -can't think of any - - -Author Information ------------------- - -This is my first publicly distributed quake graphic change. -I did it to get away from the stress of school. - - -Copyright and Distribution Permissions --------------------------------------- - -You may distribute this Quake modification in any electronic format as long as - all the files in this archive remain intact and unmodified and are distributed - together. - - -Availability ------------- - -This modification is available from the following places: - - http://www.yojoe.com/ - +Title : G.I.Joe Skins +Filename : joemodel.zip +Version : 1 +Date : 11/05/97 +Author : Kenneth Whelan +Email : JWHELAN@pop.prodigy.net +Credits : id software, Larry Hama, Steven Polge, and Rene Post for making Quake ME + + + +Build time: ??? Time??? + +Type of Mod +----------- +Quake C : no +Sound : no +MDL : Yes + + +Format of QuakeC (if a Quake C Mod) +----------------------------------- +unified diff : no +context diff : no +.qc files : no +progs.dat : no + + +Description of the Modification +------------------------------- + +This is a new player.mdl for quake. It's main use is for bots. The Skins are Snake Eyes v4, Duke v3, Low-Light, +Storm Shadow v2, Shockwave, Repeater, Gung-Ho, Shipwreck, Dusty v3, and +Tunnel Rat v2. + + + +Known bugs +None that I know of. + +How to Install the Modification +------------------------------- + +First back up the current player.mdl(copy player.mdl player.bak). Just put +it in the progs dir in the hack your using, if any. + +Technical Details +----------------- + +can't think of any + + +Author Information +------------------ + +This is my first publicly distributed quake graphic change. +I did it to get away from the stress of school. + + +Copyright and Distribution Permissions +-------------------------------------- + +You may distribute this Quake modification in any electronic format as long as + all the files in this archive remain intact and unmodified and are distributed + together. + + +Availability +------------ + +This modification is available from the following places: + + http://www.yojoe.com/ + diff --git a/test/models-nonbsd/MDL/IDPO (Quake1)/steg.txt b/test/models-nonbsd/MDL/IDPO (Quake1)/steg.txt index fb8d5304b..c07c2f126 100644 --- a/test/models-nonbsd/MDL/IDPO (Quake1)/steg.txt +++ b/test/models-nonbsd/MDL/IDPO (Quake1)/steg.txt @@ -1,33 +1,33 @@ -Stegosaur Model -from the Free Models Project -www.oz.net/~simitar/model.html - - -June 3, 1997 - -created by Sirius (Dillon Aumiller) -E-mail: sirius25@hotmail.com - - -June 5, 1997 - -modified by The Serpent Lord (Seth Galbraith) -E-mail: sgalbrai@linknet.kitsap.lib.wa.us -WWW: www.oz.net/~simitar - - -This model can be used or modified for any purpose -as long as this text document is included with it -and all modellers listed in this document are -listed wherever credits are appropriate for that -purpose. - - -Help Wanted: - -The Free Models Project can use help with -models and in other areas, such as legal boilerplate -for models. - -WWW: www.oz.net/~simitar/model.html -E-mail: sgalbrai@linknet.kitsap.lib.wa.us +Stegosaur Model +from the Free Models Project +www.oz.net/~simitar/model.html + + +June 3, 1997 + +created by Sirius (Dillon Aumiller) +E-mail: sirius25@hotmail.com + + +June 5, 1997 + +modified by The Serpent Lord (Seth Galbraith) +E-mail: sgalbrai@linknet.kitsap.lib.wa.us +WWW: www.oz.net/~simitar + + +This model can be used or modified for any purpose +as long as this text document is included with it +and all modellers listed in this document are +listed wherever credits are appropriate for that +purpose. + + +Help Wanted: + +The Free Models Project can use help with +models and in other areas, such as legal boilerplate +for models. + +WWW: www.oz.net/~simitar/model.html +E-mail: sgalbrai@linknet.kitsap.lib.wa.us diff --git a/test/models-nonbsd/MDL/IDPO (Quake1)/tekmechbot.txt b/test/models-nonbsd/MDL/IDPO (Quake1)/tekmechbot.txt index a263d9c8b..dc0149b01 100644 --- a/test/models-nonbsd/MDL/IDPO (Quake1)/tekmechbot.txt +++ b/test/models-nonbsd/MDL/IDPO (Quake1)/tekmechbot.txt @@ -1,33 +1,33 @@ - -+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+) - -teckmechbot animated .mdl - -This model was created for the FMP, because I believe -that the FMP is a great concept !! - -There is some movement in the model. -The legs can be animated for walking, stomping, or running -around ! -Ok, it's my first model, so I will work on less polygony -in the future ;-) - - -Created By: Curiel7 -Contact: ebuy@optelnow.net (E-MAIL) -Date Created: 7/07/2000 -====================================================== - -This model can be used or modified for any purpose -as long as this text document is included with it -and all modelers listed in this document are -listed wherever credits are appropriate for that -purpose. - - -The Free Models Project can use your help with -game-oriented models and other areas - -WWW: http://www.planetquake.com/simitar -E-mail: sgalbrai@linknet.kitsap.lib.wa.us - + ++)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+)+) + +teckmechbot animated .mdl + +This model was created for the FMP, because I believe +that the FMP is a great concept !! + +There is some movement in the model. +The legs can be animated for walking, stomping, or running +around ! +Ok, it's my first model, so I will work on less polygony +in the future ;-) + + +Created By: Curiel7 +Contact: ebuy@optelnow.net (E-MAIL) +Date Created: 7/07/2000 +====================================================== + +This model can be used or modified for any purpose +as long as this text document is included with it +and all modelers listed in this document are +listed wherever credits are appropriate for that +purpose. + + +The Free Models Project can use your help with +game-oriented models and other areas + +WWW: http://www.planetquake.com/simitar +E-mail: sgalbrai@linknet.kitsap.lib.wa.us + diff --git a/test/models-nonbsd/NFF/NFFSense8/credits.txt b/test/models-nonbsd/NFF/NFFSense8/credits.txt index 555721a7d..ff169151d 100644 --- a/test/models-nonbsd/NFF/NFFSense8/credits.txt +++ b/test/models-nonbsd/NFF/NFFSense8/credits.txt @@ -1,4 +1,4 @@ -teapot.nff, home4.nff - http://www.martinreddy.net/ukvrsig/wtk.html - -cokecan.nff -www.vrupl.evl.uic.edu/Eng591_Pages/cokecan.nff +teapot.nff, home4.nff - http://www.martinreddy.net/ukvrsig/wtk.html + +cokecan.nff -www.vrupl.evl.uic.edu/Eng591_Pages/cokecan.nff TODO: License status to be confirmed \ No newline at end of file diff --git a/test/models-nonbsd/OBJ/rifle.source.txt b/test/models-nonbsd/OBJ/rifle.source.txt index 842a9cfc0..b09dcda8c 100644 --- a/test/models-nonbsd/OBJ/rifle.source.txt +++ b/test/models-nonbsd/OBJ/rifle.source.txt @@ -1,27 +1,27 @@ -===================================================================== - -From http://telias.free.fr -Model copyright: Elias Tsiantas - -===================================================================== - -Downloaded 4th November 2008 (Obama ftw!). -Notices found on the page: - -" -Free the models is a site that offers free 3d models in 3ds, bryce, poser, -lightwave and md2 format. Also a great collection of textures to use in -your favorite modelling and rendering program. All the content is free -for any use. In the future more 3d formats will be added and some other -sections such as wallpapers, 3d screensavers, 3d coding source code and -tutorials. -" - -" -'Free the models' is a site dedicated to provide free content for 3d applications and 3d/game engines. The license of the content is that what you download from here is one step away from public domain. So, everything you download from here is free for any use EXCEPT it cannot be included in another free web or cd collection and it cannot be sold. Otherwise you can use it in your commercial game, 3d application or render work. You don't have to provide credit but It would be nice if you do. -" - -INFO -==== - +===================================================================== + +From http://telias.free.fr +Model copyright: Elias Tsiantas + +===================================================================== + +Downloaded 4th November 2008 (Obama ftw!). +Notices found on the page: + +" +Free the models is a site that offers free 3d models in 3ds, bryce, poser, +lightwave and md2 format. Also a great collection of textures to use in +your favorite modelling and rendering program. All the content is free +for any use. In the future more 3d formats will be added and some other +sections such as wallpapers, 3d screensavers, 3d coding source code and +tutorials. +" + +" +'Free the models' is a site dedicated to provide free content for 3d applications and 3d/game engines. The license of the content is that what you download from here is one step away from public domain. So, everything you download from here is free for any use EXCEPT it cannot be included in another free web or cd collection and it cannot be sold. Otherwise you can use it in your commercial game, 3d application or render work. You don't have to provide credit but It would be nice if you do. +" + +INFO +==== + Converted from 3DS to OBJ with AC3D \ No newline at end of file diff --git a/test/models-nonbsd/OBJ/segment.source.txt b/test/models-nonbsd/OBJ/segment.source.txt index 35e13588f..978d72d26 100644 --- a/test/models-nonbsd/OBJ/segment.source.txt +++ b/test/models-nonbsd/OBJ/segment.source.txt @@ -1,4 +1,4 @@ -Obj exported from Blender - -http://toychest.in.tum.de/wiki/projects:kuka_lwr +Obj exported from Blender + +http://toychest.in.tum.de/wiki/projects:kuka_lwr License: Creative-Commons-by-Attribution-3.0 \ No newline at end of file diff --git a/test/models-nonbsd/README.txt b/test/models-nonbsd/README.txt index a6842987b..8b244d2aa 100644 --- a/test/models-nonbsd/README.txt +++ b/test/models-nonbsd/README.txt @@ -1,3 +1,3 @@ -These models are not generally redistributable under the terms of Assimp's BSD license. Usually, an additional requirement on the use of the data is imposed (i.e. no commercial use, need credits, some creative commons variants, ...). - +These models are not generally redistributable under the terms of Assimp's BSD license. Usually, an additional requirement on the use of the data is imposed (i.e. no commercial use, need credits, some creative commons variants, ...). + So, if you re-package Assimp for use in a 'clean' OSS package, consider removing this directory. \ No newline at end of file diff --git a/test/models-nonbsd/X/dwarf-Read-Me.txt b/test/models-nonbsd/X/dwarf-Read-Me.txt index ad1583752..ecf775d0b 100644 --- a/test/models-nonbsd/X/dwarf-Read-Me.txt +++ b/test/models-nonbsd/X/dwarf-Read-Me.txt @@ -1,51 +1,51 @@ -Dwarf lowpoly model Pack -Copyright 2004, Psionic Design -e-mail: psionic@blueyonder.co.uk - - - -INSTALLATION INSTRUCTIONS: - -To install, simply unzip to your hard drive with the "Use Folder Names" option turned on. And that's it you're ready to go! - - - -USAGE INFORMATION: - -Each zip contains the models, textures and animation info for that particular format! - -Please Read the "animationinfo.txt" file included in each zip for the exact frames of animation to use - -Credits to me "Psionic" are really appreciated but are not essential ;-) - -Any questions, screenshots of him in use etc drop by my site or email me at:- - -website: http://www.psionic3d.co.uk -email: psionic@blueyonder.co.uk - - - - -WHAT'S INCLUDED IN THE ZIP: - -ReadMe.txt - This file -b3d.zip - Blitz 3D Format models and textures -ms3d.zip - Milkshape 3D Format models and textures -x.zip - DarkBasic Direct X 8 Format models and textures - - - -RESTRICTIONS: - -This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- - -**You may not sell/re-sell this model pack or claim it as your own. -***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent. - - -Psi -http://www.psionic3d.co.uk - - - - +Dwarf lowpoly model Pack +Copyright 2004, Psionic Design +e-mail: psionic@blueyonder.co.uk + + + +INSTALLATION INSTRUCTIONS: + +To install, simply unzip to your hard drive with the "Use Folder Names" option turned on. And that's it you're ready to go! + + + +USAGE INFORMATION: + +Each zip contains the models, textures and animation info for that particular format! + +Please Read the "animationinfo.txt" file included in each zip for the exact frames of animation to use + +Credits to me "Psionic" are really appreciated but are not essential ;-) + +Any questions, screenshots of him in use etc drop by my site or email me at:- + +website: http://www.psionic3d.co.uk +email: psionic@blueyonder.co.uk + + + + +WHAT'S INCLUDED IN THE ZIP: + +ReadMe.txt - This file +b3d.zip - Blitz 3D Format models and textures +ms3d.zip - Milkshape 3D Format models and textures +x.zip - DarkBasic Direct X 8 Format models and textures + + + +RESTRICTIONS: + +This model pack is available for use in freeware, shareware, commercial games/software with the following restrictions:- + +**You may not sell/re-sell this model pack or claim it as your own. +***You may not redistribute this pack in some other model pack through a website or on a compilation CD of any kind, without my written consent. + + +Psi +http://www.psionic3d.co.uk + + + + diff --git a/test/models/3DS/UVTransformTest/note.txt b/test/models/3DS/UVTransformTest/note.txt index fcb276d28..dc4bd0789 100644 --- a/test/models/3DS/UVTransformTest/note.txt +++ b/test/models/3DS/UVTransformTest/note.txt @@ -1,11 +1,11 @@ -All 'mirror' files are not absolutely correct. That's mainly -because it's difficult convert Max' handling of mirroring to -our's. - -In other words: TO DO, but only if someone REALLY needs it. - -------------------------------------------------------------- - -To see how it should look like - test/ReferenceImages -Note that the viewer has no 'decal' texture mapping mode, so +All 'mirror' files are not absolutely correct. That's mainly +because it's difficult convert Max' handling of mirroring to +our's. + +In other words: TO DO, but only if someone REALLY needs it. + +------------------------------------------------------------- + +To see how it should look like - test/ReferenceImages +Note that the viewer has no 'decal' texture mapping mode, so the usual clamping is used. \ No newline at end of file diff --git a/test/models/ASE/MotionCaptureROM.source.txt b/test/models/ASE/MotionCaptureROM.source.txt index 72542af41..222a3afbb 100644 --- a/test/models/ASE/MotionCaptureROM.source.txt +++ b/test/models/ASE/MotionCaptureROM.source.txt @@ -1,3 +1,3 @@ -"MotionCaptureROM.ase" - Free for any purpose. - +"MotionCaptureROM.ase" - Free for any purpose. + NOTE: The errors in the middle of the animation are caused by problems during recording, it's not an importer issue. \ No newline at end of file diff --git a/test/models/BLEND/HUMAN.source.txt b/test/models/BLEND/HUMAN.source.txt index 4cb20c906..9409b46d3 100644 --- a/test/models/BLEND/HUMAN.source.txt +++ b/test/models/BLEND/HUMAN.source.txt @@ -1,3 +1,3 @@ -HUMAN.blend (c) 2010, Tobias Rittig - +HUMAN.blend (c) 2010, Tobias Rittig + Redistribution and reuse allowed for any purpose, credits appreciated. \ No newline at end of file diff --git a/test/models/BVH/01_nn.bvh.source.txt b/test/models/BVH/01_nn.bvh.source.txt index a68993950..e538020a2 100644 --- a/test/models/BVH/01_nn.bvh.source.txt +++ b/test/models/BVH/01_nn.bvh.source.txt @@ -1,50 +1,50 @@ -http://sites.google.com/a/cgspeed.com/cgspeed/motion-capture/cmu-bvh-conversion - - -ReadmeFirst.txt -================ - - -READMEFIRST v1.00 last update July 20, 2008 by B. Hahne - -This READMEFIRST file accompanies the cgspeed.com "BVH conversion" -release of the Carnegie-Mellon University (CMU) Graphics Lab Motion -Capture Database. See "Where to find stuff" at the bottom of this -file for where to get the BVH conversion and/or the original CMU -dataset. - -The original CMU motion capture database isn't in BVH format - it's -in ASF/AMC format. This BVH conversion release was created by Bruce -Hahne, a hobbyist animator, in the interest of making the data more -available and easily usable by other animators. I presently (2008) -maintain the web site www.cgspeed.com, where this BVH conversion -release will be available or linked. - -The emphasis on this release is to produce BVH files that can rapidly -be used in MotionBuilder for motion retargetting. The files are not -yet particularly Poser-friendly or DazStudio-friendly, due to -incorrect assumptions that those programs have to make about the -underlying joint rotation setup. - - -[...] - - - -USAGE RIGHTS: - -CMU places no restrictions on the use of the original dataset, and I -(Bruce) place no additional restrictions on the use of this particular -BVH conversion. - -Here's the relevant paragraph from mocap.cs.cmu.edu: - - Use this data! This data is free for use in research and commercial - projects worldwide. If you publish results obtained using this data, - we would appreciate it if you would send the citation to your - published paper to jkh+mocap@cs.cmu.edu, and also would add this text - to your acknowledgments section: "The data used in this project was - obtained from mocap.cs.cmu.edu. The database was created with funding - from NSF EIA-0196217." - +http://sites.google.com/a/cgspeed.com/cgspeed/motion-capture/cmu-bvh-conversion + + +ReadmeFirst.txt +================ + + +READMEFIRST v1.00 last update July 20, 2008 by B. Hahne + +This READMEFIRST file accompanies the cgspeed.com "BVH conversion" +release of the Carnegie-Mellon University (CMU) Graphics Lab Motion +Capture Database. See "Where to find stuff" at the bottom of this +file for where to get the BVH conversion and/or the original CMU +dataset. + +The original CMU motion capture database isn't in BVH format - it's +in ASF/AMC format. This BVH conversion release was created by Bruce +Hahne, a hobbyist animator, in the interest of making the data more +available and easily usable by other animators. I presently (2008) +maintain the web site www.cgspeed.com, where this BVH conversion +release will be available or linked. + +The emphasis on this release is to produce BVH files that can rapidly +be used in MotionBuilder for motion retargetting. The files are not +yet particularly Poser-friendly or DazStudio-friendly, due to +incorrect assumptions that those programs have to make about the +underlying joint rotation setup. + + +[...] + + + +USAGE RIGHTS: + +CMU places no restrictions on the use of the original dataset, and I +(Bruce) place no additional restrictions on the use of this particular +BVH conversion. + +Here's the relevant paragraph from mocap.cs.cmu.edu: + + Use this data! This data is free for use in research and commercial + projects worldwide. If you publish results obtained using this data, + we would appreciate it if you would send the citation to your + published paper to jkh+mocap@cs.cmu.edu, and also would add this text + to your acknowledgments section: "The data used in this project was + obtained from mocap.cs.cmu.edu. The database was created with funding + from NSF EIA-0196217." + [...] \ No newline at end of file diff --git a/test/models/Collada/kwxport_test_vcolors.dae.source.txt b/test/models/Collada/kwxport_test_vcolors.dae.source.txt index d173f5a47..94ee48e4a 100644 --- a/test/models/Collada/kwxport_test_vcolors.dae.source.txt +++ b/test/models/Collada/kwxport_test_vcolors.dae.source.txt @@ -1,16 +1,16 @@ -From kwxport -http://www.kwxport.org/ - ->> -The kW Xport plug-in source is released under the MIT license. -Basically, it means "feel free to use it; credit the source; don't sue me -if something goes wrong." ->> - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +From kwxport +http://www.kwxport.org/ + +>> +The kW Xport plug-in source is released under the MIT license. +Basically, it means "feel free to use it; credit the source; don't sue me +if something goes wrong." +>> + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/test/models/IRR/warn_dwarf_scaling_is_intended.txt b/test/models/IRR/warn_dwarf_scaling_is_intended.txt index 1fcb03b9a..f651a8643 100644 --- a/test/models/IRR/warn_dwarf_scaling_is_intended.txt +++ b/test/models/IRR/warn_dwarf_scaling_is_intended.txt @@ -1,3 +1,3 @@ -for dawfInCellar_ChildOfCellar & dawfInCellar_SameHierarchy: - -the strange scalings of cellar and dwarf are intended. +for dawfInCellar_ChildOfCellar & dawfInCellar_SameHierarchy: + +the strange scalings of cellar and dwarf are intended. diff --git a/test/models/IRRMesh/credits.txt b/test/models/IRRMesh/credits.txt index 76ae3cb5d..a12163233 100644 --- a/test/models/IRRMesh/credits.txt +++ b/test/models/IRRMesh/credits.txt @@ -1,2 +1,2 @@ -cellar.irrmesh - From irrlight/irrEdit. Irrlicht/irredit license (which?) +cellar.irrmesh - From irrlight/irrEdit. Irrlicht/irredit license (which?) Textures resized to 400*400, improved JPEG compression to make them smaller \ No newline at end of file diff --git a/test/models/LWO/LWO2/MappingModes/earthCylindric.txt b/test/models/LWO/LWO2/MappingModes/earthCylindric.txt index 329b2f85a..46660a486 100644 --- a/test/models/LWO/LWO2/MappingModes/earthCylindric.txt +++ b/test/models/LWO/LWO2/MappingModes/earthCylindric.txt @@ -1,5 +1,5 @@ -Wikipedia Commons, -downloaded November 25th 08 - - +Wikipedia Commons, +downloaded November 25th 08 + + http://upload.wikimedia.org/wikipedia/commons/0/01/Lambert-cylindrical-equal-area-projection.jpg \ No newline at end of file diff --git a/test/models/LWO/LWO2/MappingModes/earthSpherical.source.txt b/test/models/LWO/LWO2/MappingModes/earthSpherical.source.txt index f47970009..218b339e1 100644 --- a/test/models/LWO/LWO2/MappingModes/earthSpherical.source.txt +++ b/test/models/LWO/LWO2/MappingModes/earthSpherical.source.txt @@ -1,9 +1,9 @@ -Source: - -Nasa, Monthly Global Images - -http://earthobservatory.nasa.gov/Features/BlueMarble/BlueMarble_monthlies.php - - -Downloaded November 24, 08. +Source: + +Nasa, Monthly Global Images + +http://earthobservatory.nasa.gov/Features/BlueMarble/BlueMarble_monthlies.php + + +Downloaded November 24, 08. Rescaled to 2048 * 1024 with GIMP \ No newline at end of file diff --git a/test/models/LWO/LWO2/concrete.source.txt b/test/models/LWO/LWO2/concrete.source.txt index de419f814..792fd1f89 100644 --- a/test/models/LWO/LWO2/concrete.source.txt +++ b/test/models/LWO/LWO2/concrete.source.txt @@ -1,2 +1,2 @@ -cgtextures.com - free, even for commercial use. See the licensing conditions and the FAQ the site for mroe details. +cgtextures.com - free, even for commercial use. See the licensing conditions and the FAQ the site for mroe details. Great source for free textures, btw! \ No newline at end of file diff --git a/test/models/LWO/LWO2/uvtest-source.txt b/test/models/LWO/LWO2/uvtest-source.txt index e534a4608..75e4878a7 100644 --- a/test/models/LWO/LWO2/uvtest-source.txt +++ b/test/models/LWO/LWO2/uvtest-source.txt @@ -1,2 +1,2 @@ -Regression file. +Regression file. by Tom Speed, see http://groups.google.com/group/bmx3d/browse_thread/thread/36db3b191f81be36 \ No newline at end of file diff --git a/test/models/MD2/faerie-source.txt b/test/models/MD2/faerie-source.txt index ea7ed82bb..ef0e4f196 100644 --- a/test/models/MD2/faerie-source.txt +++ b/test/models/MD2/faerie-source.txt @@ -1,24 +1,24 @@ - -From IRRLICHT/media - - -The Irrlicht Engine License - =========================== - - Copyright (C) 2002-2007 Nikolaus Gebhardt - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgement in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be clearly marked as such, and must not be - misrepresented as being the original software. + +From IRRLICHT/media + + +The Irrlicht Engine License + =========================== + + Copyright (C) 2002-2007 Nikolaus Gebhardt + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgement in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be clearly marked as such, and must not be + misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. \ No newline at end of file diff --git a/test/models/MD2/sidney-source.txt b/test/models/MD2/sidney-source.txt index ea7ed82bb..ef0e4f196 100644 --- a/test/models/MD2/sidney-source.txt +++ b/test/models/MD2/sidney-source.txt @@ -1,24 +1,24 @@ - -From IRRLICHT/media - - -The Irrlicht Engine License - =========================== - - Copyright (C) 2002-2007 Nikolaus Gebhardt - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgement in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be clearly marked as such, and must not be - misrepresented as being the original software. + +From IRRLICHT/media + + +The Irrlicht Engine License + =========================== + + Copyright (C) 2002-2007 Nikolaus Gebhardt + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgement in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be clearly marked as such, and must not be + misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. \ No newline at end of file diff --git a/test/models/MDL/MDL3 (3DGS A4)/minigun_readme.txt b/test/models/MDL/MDL3 (3DGS A4)/minigun_readme.txt index db69818e0..c2ca7c696 100644 --- a/test/models/MDL/MDL3 (3DGS A4)/minigun_readme.txt +++ b/test/models/MDL/MDL3 (3DGS A4)/minigun_readme.txt @@ -1,6 +1,6 @@ -My name: Grimmmy -Hi everybody!!! -This is my first published model so it isn't very good,but i'm still learning!.. -This model is free for everybody,but credit will be nice! -You may reach me at rojkov91@mail.ru +My name: Grimmmy +Hi everybody!!! +This is my first published model so it isn't very good,but i'm still learning!.. +This model is free for everybody,but credit will be nice! +You may reach me at rojkov91@mail.ru P.S: Excuse my bad english \ No newline at end of file diff --git a/test/models/MDL/MDL5 (3DGS A5)/minigun_mdl5_readme.txt b/test/models/MDL/MDL5 (3DGS A5)/minigun_mdl5_readme.txt index db69818e0..c2ca7c696 100644 --- a/test/models/MDL/MDL5 (3DGS A5)/minigun_mdl5_readme.txt +++ b/test/models/MDL/MDL5 (3DGS A5)/minigun_mdl5_readme.txt @@ -1,6 +1,6 @@ -My name: Grimmmy -Hi everybody!!! -This is my first published model so it isn't very good,but i'm still learning!.. -This model is free for everybody,but credit will be nice! -You may reach me at rojkov91@mail.ru +My name: Grimmmy +Hi everybody!!! +This is my first published model so it isn't very good,but i'm still learning!.. +This model is free for everybody,but credit will be nice! +You may reach me at rojkov91@mail.ru P.S: Excuse my bad english \ No newline at end of file diff --git a/test/models/MS3D/jeep1.readme.txt b/test/models/MS3D/jeep1.readme.txt index 14b0bd9eb..d17d5e0e9 100644 --- a/test/models/MS3D/jeep1.readme.txt +++ b/test/models/MS3D/jeep1.readme.txt @@ -1,15 +1,15 @@ -Jeep designed, modelled and skinned by me, Psionic - -FREE for use however you like, credits are appreciated!!! - -It was modelled in Milkshape 3D and includes the MS3D files oriented for X or B3D format (BlitzBasic 3D), its 2032 polys with a 512x512 jpg texture map. There are two skin variations plus a UV template to help out if you want to create your own skin variations. - -I'd love to see a few screenshots of it being used in-game so feel free to stop by my site and maybe drop by my forums and show us all what your doing with it!!!!!!! - -Check out more of my work at:- - -http://xu1productions.com/3dstudio/index.html - 3D Game Resources - -http://www.psionicdesign.com - My Main 2D/3D Digital Art site - +Jeep designed, modelled and skinned by me, Psionic + +FREE for use however you like, credits are appreciated!!! + +It was modelled in Milkshape 3D and includes the MS3D files oriented for X or B3D format (BlitzBasic 3D), its 2032 polys with a 512x512 jpg texture map. There are two skin variations plus a UV template to help out if you want to create your own skin variations. + +I'd love to see a few screenshots of it being used in-game so feel free to stop by my site and maybe drop by my forums and show us all what your doing with it!!!!!!! + +Check out more of my work at:- + +http://xu1productions.com/3dstudio/index.html - 3D Game Resources + +http://www.psionicdesign.com - My Main 2D/3D Digital Art site + Psionic 2002 \ No newline at end of file diff --git a/test/models/Q3D/E-AT-AT.source.txt b/test/models/Q3D/E-AT-AT.source.txt index b583e19c0..56a96f7d5 100644 --- a/test/models/Q3D/E-AT-AT.source.txt +++ b/test/models/Q3D/E-AT-AT.source.txt @@ -1,8 +1,8 @@ -Source: the3darchive.com - -Downloaded 4th November 08 (Obama ftw!) - -Copyright notice found on the page: - -Where do the models in the archive come from? +Source: the3darchive.com + +Downloaded 4th November 08 (Obama ftw!) + +Copyright notice found on the page: + +Where do the models in the archive come from? All 3D files available from the3darchive.com are from the public domain. \ No newline at end of file diff --git a/test/models/Q3D/earth.source.txt b/test/models/Q3D/earth.source.txt index b583e19c0..56a96f7d5 100644 --- a/test/models/Q3D/earth.source.txt +++ b/test/models/Q3D/earth.source.txt @@ -1,8 +1,8 @@ -Source: the3darchive.com - -Downloaded 4th November 08 (Obama ftw!) - -Copyright notice found on the page: - -Where do the models in the archive come from? +Source: the3darchive.com + +Downloaded 4th November 08 (Obama ftw!) + +Copyright notice found on the page: + +Where do the models in the archive come from? All 3D files available from the3darchive.com are from the public domain. \ No newline at end of file diff --git a/test/models/WRL/credits.txt b/test/models/WRL/credits.txt index 8024aeb81..055f73734 100644 --- a/test/models/WRL/credits.txt +++ b/test/models/WRL/credits.txt @@ -1,2 +1,2 @@ -"MotionCaptureROM.ase" Recorded using ViconIQ. -Converted to VRML with 3DS Max 2008. +"MotionCaptureROM.ase" Recorded using ViconIQ. +Converted to VRML with 3DS Max 2008. diff --git a/test/models/X/anim_test.txt b/test/models/X/anim_test.txt index ca759fd12..637ea0581 100644 --- a/test/models/X/anim_test.txt +++ b/test/models/X/anim_test.txt @@ -1,9 +1,9 @@ -Zylinder animation: - -Frame 1 - 10: Zylinder knickt ein, so dass der Knick in Richtung z+ zeigt. -Frame 10 - 18: Zylinder-Spitze streckt sich in Richtung z-. -Frame 18 - 24: Zylinder-Spitze bewegt sich zu Position in Richtung x+ - -Remarks: The exporter failed here for some reasons... although the mesh referres to four bones, only two of them are stored in the corresponding node hierarchy. So you have a mesh with 4 bones, a hirarchy with 2 nodes and a animation that affects only those two nodes. - +Zylinder animation: + +Frame 1 - 10: Zylinder knickt ein, so dass der Knick in Richtung z+ zeigt. +Frame 10 - 18: Zylinder-Spitze streckt sich in Richtung z-. +Frame 18 - 24: Zylinder-Spitze bewegt sich zu Position in Richtung x+ + +Remarks: The exporter failed here for some reasons... although the mesh referres to four bones, only two of them are stored in the corresponding node hierarchy. So you have a mesh with 4 bones, a hirarchy with 2 nodes and a animation that affects only those two nodes. + There is no timing given for the animation. You have to scale the animation manually. For this file, the timing seems to be 24 ticks per second. \ No newline at end of file diff --git a/test/models/X/kwxport_test_cubewithvcolors.source.txt b/test/models/X/kwxport_test_cubewithvcolors.source.txt index d173f5a47..94ee48e4a 100644 --- a/test/models/X/kwxport_test_cubewithvcolors.source.txt +++ b/test/models/X/kwxport_test_cubewithvcolors.source.txt @@ -1,16 +1,16 @@ -From kwxport -http://www.kwxport.org/ - ->> -The kW Xport plug-in source is released under the MIT license. -Basically, it means "feel free to use it; credit the source; don't sue me -if something goes wrong." ->> - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +From kwxport +http://www.kwxport.org/ + +>> +The kW Xport plug-in source is released under the MIT license. +Basically, it means "feel free to use it; credit the source; don't sue me +if something goes wrong." +>> + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/test/models/X/test.txt b/test/models/X/test.txt index 1f7698422..7a5e8e74b 100644 --- a/test/models/X/test.txt +++ b/test/models/X/test.txt @@ -1,3 +1,3 @@ -Simple textured test cube exported from Maya. Has a texture that does label each cube side uniquely, but the sides do not match DirectX coordinate space. - +Simple textured test cube exported from Maya. Has a texture that does label each cube side uniquely, but the sides do not match DirectX coordinate space. + Is not readable using D3DXLoadFrameHierarchy, needs custom text parsing. \ No newline at end of file diff --git a/test/models/invalid/readme.txt b/test/models/invalid/readme.txt index 50b5fc1ce..cab740a84 100644 --- a/test/models/invalid/readme.txt +++ b/test/models/invalid/readme.txt @@ -1,31 +1,31 @@ - -********************************************************* -GENERAL -********************************************************* - - -The files in this directory are invalid ... some of them are empty, -others have invalid vertices or faces, others are prepared to make - assimp allocate a few hundreds gigs of memory ... most are -actually regression tests, i.e. there was once a bugfix that -fixed the respective loaders. - -This test case is successful if the library (and the viewer) don't -crash. - - -********************************************************* -FILES -********************************************************* - -OutOfMemory.off - the number of faces is invalid. There won't be - enough memory so std::vector::reserve() will most likely fail. - The exception should be caught in Importer.cpp. - -empty. - These files are completely empty. The corresponding - loaders should not crash. - -malformed.obj - out-of-range vertex indices -malformed2.obj - non-existent material referenced - - + +********************************************************* +GENERAL +********************************************************* + + +The files in this directory are invalid ... some of them are empty, +others have invalid vertices or faces, others are prepared to make + assimp allocate a few hundreds gigs of memory ... most are +actually regression tests, i.e. there was once a bugfix that +fixed the respective loaders. + +This test case is successful if the library (and the viewer) don't +crash. + + +********************************************************* +FILES +********************************************************* + +OutOfMemory.off - the number of faces is invalid. There won't be + enough memory so std::vector::reserve() will most likely fail. + The exception should be caught in Importer.cpp. + +empty. - These files are completely empty. The corresponding + loaders should not crash. + +malformed.obj - out-of-range vertex indices +malformed2.obj - non-existent material referenced + + diff --git a/workspaces/xcode3/info.txt b/workspaces/xcode3/info.txt index 4a623d1ed..d22a76b6f 100644 --- a/workspaces/xcode3/info.txt +++ b/workspaces/xcode3/info.txt @@ -1,6 +1,6 @@ -The xcode project files in this directory are contributed by Andy Maloney and are not continuously updated. -Currently, it's for Assimp r352. If you're using a newer revision, watch out for missing files/includes/... - -See Andy's description at -http://sourceforge.net/tracker/index.php?func=detail&aid=2659135&group_id=226462&atid=1067634 (Tracker item 2659135) -for more information. +The xcode project files in this directory are contributed by Andy Maloney and are not continuously updated. +Currently, it's for Assimp r352. If you're using a newer revision, watch out for missing files/includes/... + +See Andy's description at +http://sourceforge.net/tracker/index.php?func=detail&aid=2659135&group_id=226462&atid=1067634 (Tracker item 2659135) +for more information.