You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
6.0 KiB
309 lines
6.0 KiB
// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
// 02110-1301, USA.
|
|
|
|
#include "rect.h"
|
|
#include "common.h"
|
|
|
|
bool operator==( const Rect& r, const Rect& s )
|
|
{
|
|
return ( r.bottomLeft() == s.bottomLeft()
|
|
&& r.width() == s.width()
|
|
&& r.height() == s.height() );
|
|
}
|
|
|
|
kdbgstream& operator<<( kdbgstream& s, const Rect& t )
|
|
{
|
|
s << "left: " << t.left()
|
|
<< "bottom: " << t.bottom()
|
|
<< "right: " << t.right()
|
|
<< "top: " << t.top()
|
|
<< endl;
|
|
return s;
|
|
}
|
|
|
|
Rect::Rect( const Coordinate bottomLeft, const Coordinate topRight )
|
|
: mBottomLeft(bottomLeft)
|
|
{
|
|
mwidth = topRight.x - bottomLeft.x;
|
|
mheight = topRight.y - bottomLeft.y;
|
|
normalize();
|
|
}
|
|
|
|
Rect::Rect( const Coordinate p, const double width, const double height )
|
|
: mBottomLeft(p),
|
|
mwidth(width),
|
|
mheight(height)
|
|
{
|
|
normalize();
|
|
}
|
|
|
|
Rect::Rect( double xa, double ya, double width, double height )
|
|
: mBottomLeft( xa, ya ),
|
|
mwidth( width ),
|
|
mheight( height )
|
|
{
|
|
normalize();
|
|
}
|
|
|
|
Rect::Rect( const Rect& r )
|
|
: mBottomLeft (r.mBottomLeft),
|
|
mwidth(r.mwidth),
|
|
mheight(r.mheight)
|
|
{
|
|
normalize();
|
|
}
|
|
|
|
Rect::Rect()
|
|
: mwidth(0),
|
|
mheight(0)
|
|
{
|
|
}
|
|
|
|
void Rect::setBottomLeft( const Coordinate p )
|
|
{
|
|
mBottomLeft = p;
|
|
}
|
|
|
|
void Rect::setBottomRight( const Coordinate p )
|
|
{
|
|
mBottomLeft = p - Coordinate(mwidth,0);
|
|
}
|
|
|
|
void Rect::setTopRight( const Coordinate p )
|
|
{
|
|
mBottomLeft = p - Coordinate(mwidth, mheight);
|
|
}
|
|
|
|
void Rect::setCenter( const Coordinate p )
|
|
{
|
|
mBottomLeft = p - Coordinate(mwidth, mheight)/2;
|
|
}
|
|
|
|
void Rect::setLeft( const double p )
|
|
{
|
|
double r = right();
|
|
mBottomLeft.x = p;
|
|
setRight( r );
|
|
}
|
|
|
|
void Rect::setRight( const double p )
|
|
{
|
|
mwidth = p - left();
|
|
}
|
|
|
|
void Rect::setBottom( const double p )
|
|
{
|
|
double t = top();
|
|
mBottomLeft.y = p;
|
|
setTop( t );
|
|
}
|
|
|
|
void Rect::setTop( const double p )
|
|
{
|
|
mheight = p - bottom();
|
|
}
|
|
|
|
void Rect::setWidth( const double w )
|
|
{
|
|
mwidth = w;
|
|
}
|
|
|
|
void Rect::setHeight( const double h )
|
|
{
|
|
mheight = h;
|
|
}
|
|
|
|
void Rect::normalize()
|
|
{
|
|
if ( mwidth < 0 )
|
|
{
|
|
mBottomLeft.x += mwidth;
|
|
mwidth = -mwidth;
|
|
};
|
|
if ( mheight < 0 )
|
|
{
|
|
mBottomLeft.y += mheight;
|
|
mheight = -mheight;
|
|
};
|
|
}
|
|
|
|
void Rect::moveBy( const Coordinate p )
|
|
{
|
|
mBottomLeft += p;
|
|
}
|
|
|
|
void Rect::scale( const double r )
|
|
{
|
|
mwidth *= r;
|
|
mheight *= r;
|
|
}
|
|
|
|
|
|
TQRect Rect::toTQRect() const
|
|
{
|
|
return TQRect(mBottomLeft.toTQPoint(), topRight().toTQPoint());
|
|
}
|
|
|
|
Coordinate Rect::bottomLeft() const
|
|
{
|
|
return mBottomLeft;
|
|
}
|
|
|
|
Coordinate Rect::bottomRight() const
|
|
{
|
|
return mBottomLeft + Coordinate(mwidth, 0);
|
|
}
|
|
|
|
Coordinate Rect::topLeft() const
|
|
{
|
|
return mBottomLeft + Coordinate(0, mheight);
|
|
}
|
|
|
|
Coordinate Rect::topRight() const
|
|
{
|
|
return mBottomLeft + Coordinate(mwidth, mheight);
|
|
}
|
|
|
|
Coordinate Rect::center() const
|
|
{
|
|
return mBottomLeft + Coordinate(mwidth, mheight)/2;
|
|
}
|
|
|
|
double Rect::left() const
|
|
{
|
|
return mBottomLeft.x;
|
|
}
|
|
double Rect::right() const
|
|
{
|
|
return left() + mwidth;
|
|
}
|
|
double Rect::bottom() const
|
|
{
|
|
return mBottomLeft.y;
|
|
}
|
|
|
|
double Rect::top() const
|
|
{
|
|
return bottom() + mheight;
|
|
}
|
|
|
|
double Rect::width() const
|
|
{
|
|
return mwidth;
|
|
}
|
|
|
|
double Rect::height() const
|
|
{
|
|
return mheight;
|
|
}
|
|
|
|
bool Rect::contains( const Coordinate& p, double allowed_miss ) const
|
|
{
|
|
return p.x - left() >= - allowed_miss &&
|
|
p.y - bottom() >= - allowed_miss &&
|
|
p.x - left() - width() <= allowed_miss &&
|
|
p.y - bottom() - height() <= allowed_miss;
|
|
}
|
|
|
|
bool Rect::contains( const Coordinate& p ) const
|
|
{
|
|
return p.x >= left() &&
|
|
p.y >= bottom() &&
|
|
p.x - left() <= width() &&
|
|
p.y - bottom() <= height();
|
|
}
|
|
|
|
bool Rect::intersects( const Rect& p ) const
|
|
{
|
|
// never thought it was this simple :)
|
|
if( p.left() < left() && p.right() < left()) return false;
|
|
if( p.left() > right() && p.right() > right()) return false;
|
|
if( p.bottom() < bottom() && p.top() < bottom()) return false;
|
|
if( p.bottom() > top() && p.top() > top()) return false;
|
|
return true;
|
|
}
|
|
|
|
void Rect::setContains( Coordinate p )
|
|
{
|
|
normalize();
|
|
if( p.x < left() ) setLeft( p.x );
|
|
if( p.x > right() ) setRight(p.x);
|
|
if( p.y < bottom() ) setBottom( p.y );
|
|
if( p.y > top() ) setTop( p.y );
|
|
}
|
|
|
|
Rect Rect::normalized() const
|
|
{
|
|
Rect t = *this;
|
|
(void) t.normalize();
|
|
return t;
|
|
}
|
|
|
|
Rect Rect::fromTQRect( const TQRect& r )
|
|
{
|
|
return Rect( r.left(), r.top(), r.right(), r.bottom() );
|
|
}
|
|
|
|
void Rect::setTopLeft( const Coordinate p )
|
|
{
|
|
Coordinate bl = Coordinate( p.x, p.y - mheight );
|
|
setBottomLeft( bl );
|
|
}
|
|
|
|
Rect operator|( const Rect& lhs, const Rect& rhs )
|
|
{
|
|
Rect r( lhs );
|
|
r |= rhs;
|
|
return r;
|
|
}
|
|
|
|
void Rect::eat( const Rect& r )
|
|
{
|
|
setLeft( kigMin( left(), r.left() ) );
|
|
setRight( kigMax( right(), r.right() ) );
|
|
setBottom( kigMin( bottom(), r.bottom() ) );
|
|
setTop( kigMax( top(), r.top() ) );
|
|
}
|
|
|
|
Rect Rect::matchShape( const Rect& rhs, bool shrink ) const
|
|
{
|
|
Rect ret = *this;
|
|
Coordinate c = center();
|
|
double v = width()/height(); // current ratio
|
|
double w = rhs.width()/rhs.height(); // wanted ratio
|
|
|
|
// we don't show less than r, if the dimensions don't match, we
|
|
// extend r into some dimension...
|
|
if( ( v > w ) ^ shrink )
|
|
ret.setHeight( ret.width() / w );
|
|
else
|
|
ret.setWidth( ret.height() * w );
|
|
|
|
ret.setCenter(c);
|
|
return ret.normalized();
|
|
}
|
|
|
|
bool Rect::valid()
|
|
{
|
|
return mBottomLeft.valid() && mwidth != double_inf && mheight != double_inf;
|
|
}
|
|
|
|
Rect Rect::invalidRect()
|
|
{
|
|
return Rect( Coordinate::invalidCoord(), double_inf, double_inf );
|
|
}
|