diff --git a/simgear/canvas/layout/BoxLayout.cxx b/simgear/canvas/layout/BoxLayout.cxx index ec2aee53..3da5d98e 100644 --- a/simgear/canvas/layout/BoxLayout.cxx +++ b/simgear/canvas/layout/BoxLayout.cxx @@ -305,9 +305,9 @@ namespace canvas } // Add sizes of all children in layout direction - safeAdd(min_size.x(), item_data.min_size); - safeAdd(max_size.x(), item_data.max_size); - safeAdd(size_hint.x(), item_data.size_hint); + SGMisc::addClipOverflowInplace(min_size.x(), item_data.min_size); + SGMisc::addClipOverflowInplace(max_size.x(), item_data.max_size); + SGMisc::addClipOverflowInplace(size_hint.x(), item_data.size_hint); // Take maximum in fixed (non-layouted) direction min_size.y() = std::max( min_size.y(), @@ -320,9 +320,9 @@ namespace canvas _layout_data.has_hfw = _layout_data.has_hfw || item.hasHeightForWidth(); } - safeAdd(min_size.x(), _layout_data.padding); - safeAdd(max_size.x(), _layout_data.padding); - safeAdd(size_hint.x(), _layout_data.padding); + SGMisc::addClipOverflowInplace(min_size.x(), _layout_data.padding); + SGMisc::addClipOverflowInplace(max_size.x(), _layout_data.padding); + SGMisc::addClipOverflowInplace(size_hint.x(), _layout_data.padding); _layout_data.min_size = min_size.x(); _layout_data.max_size = max_size.x(); diff --git a/simgear/canvas/layout/Layout.cxx b/simgear/canvas/layout/Layout.cxx index 8ae4e6e8..d3ae3886 100644 --- a/simgear/canvas/layout/Layout.cxx +++ b/simgear/canvas/layout/Layout.cxx @@ -108,15 +108,6 @@ namespace canvas return layout_item->minimumSize().y(); } - //---------------------------------------------------------------------------- - void Layout::safeAdd(int& a, int b) - { - if( SGLimits::max() - b < a ) - a = SGLimits::max(); - else - a += b; - } - //---------------------------------------------------------------------------- void Layout::distribute(std::vector& items, const ItemData& space) { diff --git a/simgear/canvas/layout/Layout.hxx b/simgear/canvas/layout/Layout.hxx index b91767f4..f28763cb 100644 --- a/simgear/canvas/layout/Layout.hxx +++ b/simgear/canvas/layout/Layout.hxx @@ -104,11 +104,6 @@ namespace canvas */ virtual void doLayout(const SGRecti& geom) = 0; - /** - * Add two integers taking care of overflow (limit to INT_MAX) - */ - static void safeAdd(int& a, int b); - /** * Distribute the available @a space to all @a items */ diff --git a/simgear/math/SGMisc.hxx b/simgear/math/SGMisc.hxx index 0f57edf1..abf162d8 100644 --- a/simgear/math/SGMisc.hxx +++ b/simgear/math/SGMisc.hxx @@ -41,6 +41,30 @@ public: static T clip(const T& a, const T& _min, const T& _max) { return max(_min, min(_max, a)); } + + /// Add two (integer) values taking care of overflows. + static T addClipOverflow(T a, T b) + { + if( b > 0 ) + { + if( SGLimits::max() - b < a ) + return SGLimits::max(); + } + else + { + if( SGLimits::min() - b > a ) + return SGLimits::min(); + } + + return a + b; + } + + /// Add two (integer) values in place, taking care of overflows. + static T& addClipOverflowInplace(T& a, T b) + { + return a = addClipOverflow(a, b); + } + /** * Seek a variable towards a target value with given rate and timestep * diff --git a/simgear/math/SGVec2.hxx b/simgear/math/SGVec2.hxx index 0695cded..1ed150d8 100644 --- a/simgear/math/SGVec2.hxx +++ b/simgear/math/SGVec2.hxx @@ -196,6 +196,17 @@ SGVec2 max(S s, const SGVec2& v) { return SGVec2(SGMisc::max(s, v(0)), SGMisc::max(s, v(1))); } +/// Add two vectors taking care of (integer) overflows. The values are limited +/// to the respective minimum and maximum values. +template +SGVec2 addClipOverflow(SGVec2 const& lhs, SGVec2 const& rhs) +{ + return SGVec2( + SGMisc::addClipOverflow(lhs.x(), rhs.x()), + SGMisc::addClipOverflow(lhs.y(), rhs.y()) + ); +} + /// Scalar dot product template inline diff --git a/simgear/math/SGVec3.hxx b/simgear/math/SGVec3.hxx index dbc8af54..b0f6b206 100644 --- a/simgear/math/SGVec3.hxx +++ b/simgear/math/SGVec3.hxx @@ -288,6 +288,18 @@ max(S s, const SGVec3& v) SGMisc::max(s, v(2))); } +/// Add two vectors taking care of (integer) overflows. The values are limited +/// to the respective minimum and maximum values. +template +SGVec3 addClipOverflow(SGVec3 const& lhs, SGVec3 const& rhs) +{ + return SGVec3( + SGMisc::addClipOverflow(lhs.x(), rhs.x()), + SGMisc::addClipOverflow(lhs.y(), rhs.y()), + SGMisc::addClipOverflow(lhs.z(), rhs.z()) + ); +} + /// Scalar dot product template inline diff --git a/simgear/math/SGVec4.hxx b/simgear/math/SGVec4.hxx index 301aaca3..4339dfd9 100644 --- a/simgear/math/SGVec4.hxx +++ b/simgear/math/SGVec4.hxx @@ -244,6 +244,19 @@ max(S s, const SGVec4& v) SGMisc::max(s, v(3))); } +/// Add two vectors taking care of (integer) overflows. The values are limited +/// to the respective minimum and maximum values. +template +SGVec4 addClipOverflow(SGVec4 const& lhs, SGVec4 const& rhs) +{ + return SGVec4( + SGMisc::addClipOverflow(lhs.x(), rhs.x()), + SGMisc::addClipOverflow(lhs.y(), rhs.y()), + SGMisc::addClipOverflow(lhs.z(), rhs.z()), + SGMisc::addClipOverflow(lhs.w(), rhs.w()) + ); +} + /// Scalar dot product template inline