1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 #ifndef INCLUDED_TOOLS_GEN_HXX
20 #define INCLUDED_TOOLS_GEN_HXX
21 
22 #include <tools/toolsdllapi.h>
23 
24 #include <limits.h>
25 #include <algorithm>
26 #include <ostream>
27 
28 class SvStream;
29 namespace rtl
30 {
31     class OString;
32 }
33 
34 enum TriState { TRISTATE_FALSE, TRISTATE_TRUE, TRISTATE_INDET };
35 
36 // Pair
37 
38 class SAL_WARN_UNUSED Pair
39 {
40 public:
Pair()41                         Pair() : nA(0), nB(0) {}
Pair(long _nA,long _nB)42                         Pair( long _nA, long _nB ) : nA(_nA), nB(_nB) {}
43 
A() const44     long                A() const { return nA; }
B() const45     long                B() const { return nB; }
46 
A()47     long&               A() { return nA; }
B()48     long&               B() { return nB; }
49 
50     TOOLS_DLLPUBLIC rtl::OString        toString() const;
51 
52 protected:
53     long                nA;
54     long                nB;
55 };
56 
57 namespace tools { namespace detail {
58 
59 // Used to implement operator == for subclasses of Pair:
equal(Pair const & p1,Pair const & p2)60 inline bool equal(Pair const & p1, Pair const & p2)
61 {
62     return p1.A() == p2.A() && p1.B() == p2.B();
63 }
64 
65 } }
66 
67 // Point
68 
69 class Size;
70 class SAL_WARN_UNUSED SAL_DLLPUBLIC_EXPORT Point final : protected Pair
71 {
72 public:
Point()73                         Point() {}
Point(long nX,long nY)74                         Point( long nX, long nY ) : Pair( nX, nY ) {}
75 
X() const76     long                X() const { return nA; }
Y() const77     long                Y() const { return nB; }
78 
79     void                Move( long nHorzMove, long nVertMove );
80     void                Move( Size const & s );
AdjustX(long nHorzMove)81     long                AdjustX( long nHorzMove ) { nA += nHorzMove; return nA; }
AdjustY(long nVertMove)82     long                AdjustY( long nVertMove ) { nB += nVertMove; return nB; }
83 
84     void                RotateAround( long& rX, long& rY, short nOrientation ) const;
85     void                RotateAround( Point&, short nOrientation ) const;
86 
87     Point&              operator += ( const Point& rPoint );
88     Point&              operator -= ( const Point& rPoint );
89     Point&              operator *= ( const long nVal );
90     Point&              operator /= ( const long nVal );
91 
92     friend inline Point operator+( const Point &rVal1, const Point &rVal2 );
93     friend inline Point operator-( const Point &rVal1, const Point &rVal2 );
94     friend inline Point operator*( const Point &rVal1, const long nVal2 );
95     friend inline Point operator/( const Point &rVal1, const long nVal2 );
96 
getX() const97     long                getX() const { return X(); }
getY() const98     long                getY() const { return Y(); }
setX(long nX)99     void                setX(long nX)  { nA = nX; }
setY(long nY)100     void                setY(long nY)  { nB = nY; }
101 
toPair() const102     Pair const &        toPair() const { return *this; }
toPair()103     Pair &              toPair() { return *this; }
104 
105     using Pair::toString;
106 };
107 
Move(long nHorzMove,long nVertMove)108 inline void Point::Move( long nHorzMove, long nVertMove )
109 {
110     nA += nHorzMove;
111     nB += nVertMove;
112 }
113 
operator +=(const Point & rPoint)114 inline Point& Point::operator += ( const Point& rPoint )
115 {
116     nA += rPoint.nA;
117     nB += rPoint.nB;
118     return *this;
119 }
120 
operator -=(const Point & rPoint)121 inline Point& Point::operator -= ( const Point& rPoint )
122 {
123     nA -= rPoint.nA;
124     nB -= rPoint.nB;
125     return *this;
126 }
127 
operator *=(const long nVal)128 inline Point& Point::operator *= ( const long nVal )
129 {
130     nA *= nVal;
131     nB *= nVal;
132     return *this;
133 }
134 
operator /=(const long nVal)135 inline Point& Point::operator /= ( const long nVal )
136 {
137     nA /= nVal;
138     nB /= nVal;
139     return *this;
140 }
141 
operator +(const Point & rVal1,const Point & rVal2)142 inline Point operator+( const Point &rVal1, const Point &rVal2 )
143 {
144     return Point( rVal1.nA+rVal2.nA, rVal1.nB+rVal2.nB );
145 }
146 
operator -(const Point & rVal1,const Point & rVal2)147 inline Point operator-( const Point &rVal1, const Point &rVal2 )
148 {
149     return Point( rVal1.nA-rVal2.nA, rVal1.nB-rVal2.nB );
150 }
151 
operator *(const Point & rVal1,const long nVal2)152 inline Point operator*( const Point &rVal1, const long nVal2 )
153 {
154     return Point( rVal1.nA*nVal2, rVal1.nB*nVal2 );
155 }
156 
operator /(const Point & rVal1,const long nVal2)157 inline Point operator/( const Point &rVal1, const long nVal2 )
158 {
159     return Point( rVal1.nA/nVal2, rVal1.nB/nVal2 );
160 }
161 
operator ==(Point const & p1,Point const & p2)162 inline bool operator ==(Point const & p1, Point const & p2)
163 {
164     return tools::detail::equal(p1.toPair(), p2.toPair());
165 }
166 
operator !=(Point const & p1,Point const & p2)167 inline bool operator !=(Point const & p1, Point const & p2)
168 {
169     return !(p1 == p2);
170 }
171 
172 template< typename charT, typename traits >
operator <<(std::basic_ostream<charT,traits> & stream,const Point & point)173 inline std::basic_ostream<charT, traits> & operator <<(
174     std::basic_ostream<charT, traits> & stream, const Point& point )
175 {
176     return stream << point.X() << ',' << point.Y();
177 }
178 
179 // Size
180 
181 class SAL_WARN_UNUSED Size final : protected Pair
182 {
183 public:
Size()184                     Size() {}
Size(long nWidth,long nHeight)185                     Size( long nWidth, long nHeight ) : Pair( nWidth, nHeight ) {}
186 
Width() const187     long            Width() const  { return nA; }
Height() const188     long            Height() const { return nB; }
189 
AdjustWidth(long n)190     long            AdjustWidth( long n ) { nA += n; return nA; }
AdjustHeight(long n)191     long            AdjustHeight( long n ) { nB += n; return nB; }
192 
getWidth() const193     long            getWidth() const { return Width(); }
getHeight() const194     long            getHeight() const { return Height(); }
setWidth(long nWidth)195     void            setWidth(long nWidth)  { nA = nWidth; }
setHeight(long nHeight)196     void            setHeight(long nHeight)  { nB = nHeight; }
197 
extendBy(long x,long y)198     void extendBy(long x, long y)
199     {
200         nA += x;
201         nB += y;
202     }
203 
toPair() const204     Pair const &    toPair() const { return *this; }
toPair()205     Pair &          toPair() { return *this; }
206 
207     using Pair::toString;
208 };
209 
operator ==(Size const & s1,Size const & s2)210 inline bool operator ==(Size const & s1, Size const & s2)
211 {
212     return tools::detail::equal(s1.toPair(), s2.toPair());
213 }
214 
operator !=(Size const & s1,Size const & s2)215 inline bool operator !=(Size const & s1, Size const & s2)
216 {
217     return !(s1 == s2);
218 }
219 
220 template< typename charT, typename traits >
operator <<(std::basic_ostream<charT,traits> & stream,const Size & size)221 inline std::basic_ostream<charT, traits> & operator <<(
222     std::basic_ostream<charT, traits> & stream, const Size& size )
223 {
224     return stream << size.Width() << 'x' << size.Height();
225 }
226 
Move(Size const & s)227 inline void Point::Move( Size const & s )
228 {
229     AdjustX(s.Width());
230     AdjustY(s.Height());
231 }
232 
233 // Range
234 
235 #define RANGE_MAX   LONG_MAX
236 
237 class SAL_WARN_UNUSED Range final : protected Pair
238 {
239 public:
Range()240                     Range() {}
Range(long nMin,long nMax)241                     Range( long nMin, long nMax ) : Pair( nMin, nMax ) {}
242 
Min() const243     long            Min() const { return nA; }
Max() const244     long            Max() const { return nB; }
Len() const245     long            Len() const { return nB - nA + 1; }
246 
Min()247     long&           Min() { return nA; }
Max()248     long&           Max() { return nB; }
249 
250     bool            IsInside( long nIs ) const;
251 
252     void            Justify();
253 
toPair() const254     Pair const &    toPair() const { return *this; }
toPair()255     Pair &          toPair() { return *this; }
256 
257     using Pair::toString;
258 };
259 
IsInside(long nIs) const260 inline bool Range::IsInside( long nIs ) const
261 {
262     return ((nA <= nIs) && (nIs <= nB ));
263 }
264 
Justify()265 inline void Range::Justify()
266 {
267     if ( nA > nB )
268     {
269         long nHelp = nA;
270         nA = nB;
271         nB = nHelp;
272     }
273 }
274 
operator ==(Range const & r1,Range const & r2)275 inline bool operator ==(Range const & r1, Range const & r2)
276 {
277     return tools::detail::equal(r1.toPair(), r2.toPair());
278 }
279 
operator !=(Range const & r1,Range const & r2)280 inline bool operator !=(Range const & r1, Range const & r2)
281 {
282     return !(r1 == r2);
283 }
284 
285 template< typename charT, typename traits >
operator <<(std::basic_ostream<charT,traits> & stream,const Range & range)286 inline std::basic_ostream<charT, traits> & operator <<(
287     std::basic_ostream<charT, traits> & stream, const Range& range )
288 {
289     return stream << range.Min() << '-' << range.Max();
290 }
291 
292 // Selection
293 
294 #define SELECTION_MIN   LONG_MIN
295 #define SELECTION_MAX   LONG_MAX
296 
297 class SAL_WARN_UNUSED Selection final : protected Pair
298 {
299 public:
Selection()300                     Selection() {}
Selection(long nPos)301                     Selection( long nPos ) : Pair( nPos, nPos ) {}
Selection(long nMin,long nMax)302                     Selection( long nMin, long nMax ) : Pair( nMin, nMax ) {}
303 
Min() const304     long            Min() const { return nA; }
Max() const305     long            Max() const { return nB; }
Len() const306     long            Len() const { return nB - nA; }
307 
Min()308     long&           Min() { return nA; }
Max()309     long&           Max() { return nB; }
310 
311     bool            IsInside( long nIs ) const;
312 
313     void            Justify();
314 
operator !() const315     bool            operator !() const { return !Len(); }
316 
getMin() const317     long            getMin() const { return Min(); }
setMin(long nMin)318     void            setMin(long nMin)  { Min() = nMin; }
setMax(long nMax)319     void            setMax(long nMax)  { Max() = nMax; }
320 
toPair() const321     Pair const &    toPair() const { return *this; }
toPair()322     Pair &          toPair() { return *this; }
323 
324     using Pair::toString;
325 };
326 
IsInside(long nIs) const327 inline bool Selection::IsInside( long nIs ) const
328 {
329     return ((nA <= nIs) && (nIs < nB ));
330 }
331 
Justify()332 inline void Selection::Justify()
333 {
334     if ( nA > nB )
335     {
336         long nHelp = nA;
337         nA = nB;
338         nB = nHelp;
339     }
340 }
341 
operator ==(Selection const & s1,Selection const & s2)342 inline bool operator ==(Selection const & s1, Selection const & s2)
343 {
344     return tools::detail::equal(s1.toPair(), s2.toPair());
345 }
346 
operator !=(Selection const & s1,Selection const & s2)347 inline bool operator !=(Selection const & s1, Selection const & s2)
348 {
349     return !(s1 == s2);
350 }
351 
352 template< typename charT, typename traits >
operator <<(std::basic_ostream<charT,traits> & stream,const Selection & selection)353 inline std::basic_ostream<charT, traits> & operator <<(
354     std::basic_ostream<charT, traits> & stream, const Selection& selection )
355 {
356     return stream << selection.Min() << '-' << selection.Max();
357 }
358 // Rectangle
359 
360 #define RECT_MAX    LONG_MAX
361 #define RECT_MIN    LONG_MIN
362 
363 /// Note: this class is a true marvel of engineering: because the author
364 /// could not decide whether it's better to have a closed or half-open
365 /// interval, they just implemented *both* in the same class!
366 ///
367 /// If you have the misfortune of having to use this class, don't immediately
368 /// despair but first take note that the uppercase GetWidth() / GetHeight()
369 /// etc. methods interpret the interval as closed, while the lowercase
370 /// getWidth() / getHeight() etc. methods interpret the interval as half-open.
371 /// Ok, now is the time for despair.
372 namespace tools
373 {
374 class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Rectangle final
375 {
376     static constexpr short RECT_EMPTY = -32767;
377 public:
378                         Rectangle();
379                         Rectangle( const Point& rLT, const Point& rRB );
380                         Rectangle( long nLeft, long nTop,
381                                    long nRight, long nBottom );
382     /// Constructs an empty Rectangle, with top/left at the specified params
383                         Rectangle( long nLeft, long nTop );
384                         Rectangle( const Point& rLT, const Size& rSize );
385 
Left() const386     long                Left() const    { return nLeft;   }
387     long                Right() const;
Top() const388     long                Top() const     { return nTop;    }
389     long                Bottom() const;
390 
SetLeft(long v)391     void                SetLeft(long v)    { nLeft = v;   }
SetRight(long v)392     void                SetRight(long v)   { nRight = v;  }
SetTop(long v)393     void                SetTop(long v)     { nTop = v;    }
SetBottom(long v)394     void                SetBottom(long v)  { nBottom = v; }
395 
396     inline Point        TopLeft() const;
397     inline Point        TopRight() const;
398     inline Point        TopCenter() const;
399     inline Point        BottomLeft() const;
400     inline Point        BottomRight() const;
401     inline Point        BottomCenter() const;
402     inline Point        LeftCenter() const;
403     inline Point        RightCenter() const;
404     inline Point        Center() const;
405 
406     /// Move the top and left edges by a delta, preserving width and height
407     inline void         Move( long nHorzMoveDelta, long nVertMoveDelta );
Move(Size const & s)408     void                Move( Size const & s ) { Move(s.Width(), s.Height()); }
AdjustLeft(long nHorzMoveDelta)409     long                AdjustLeft( long nHorzMoveDelta ) { nLeft += nHorzMoveDelta; return nLeft; }
410     long                AdjustRight( long nHorzMoveDelta );
AdjustTop(long nVertMoveDelta)411     long                AdjustTop( long nVertMoveDelta ) { nTop += nVertMoveDelta; return nTop; }
412     long                AdjustBottom( long nVertMoveDelta );
413     inline void         SetPos( const Point& rPoint );
414     void                SetSize( const Size& rSize );
415     inline Size         GetSize() const;
416 
417     /// Returns the difference between right and left, assuming the range is inclusive.
418     inline long         GetWidth() const;
419     /// Returns the difference between bottom and top, assuming the range is inclusive.
420     inline long         GetHeight() const;
421 
422     tools::Rectangle&          Union( const tools::Rectangle& rRect );
423     tools::Rectangle&          Intersection( const tools::Rectangle& rRect );
424     inline tools::Rectangle    GetUnion( const tools::Rectangle& rRect ) const;
425     inline tools::Rectangle    GetIntersection( const tools::Rectangle& rRect ) const;
426 
427     void                Justify();
428 
429     bool                IsInside( const Point& rPOINT ) const;
430     bool                IsInside( const tools::Rectangle& rRect ) const;
431     bool                IsOver( const tools::Rectangle& rRect ) const;
432 
SetEmpty()433     void                SetEmpty() { nRight = nBottom = RECT_EMPTY; }
SetWidthEmpty()434     void                SetWidthEmpty() { nRight = RECT_EMPTY; }
SetHeightEmpty()435     void                SetHeightEmpty() { nBottom = RECT_EMPTY; }
436     inline bool         IsEmpty() const;
IsWidthEmpty() const437     bool                IsWidthEmpty() const { return nRight == RECT_EMPTY; }
IsHeightEmpty() const438     bool                IsHeightEmpty() const { return nBottom == RECT_EMPTY; }
439 
440     inline bool         operator == ( const tools::Rectangle& rRect ) const;
441     inline bool         operator != ( const tools::Rectangle& rRect ) const;
442 
443     inline tools::Rectangle&   operator += ( const Point& rPt );
444     inline tools::Rectangle&   operator -= ( const Point& rPt );
445 
446     friend inline tools::Rectangle operator + ( const tools::Rectangle& rRect, const Point& rPt );
447     friend inline tools::Rectangle operator - ( const tools::Rectangle& rRect, const Point& rPt );
448 
449     // ONE
getX() const450     long                getX() const { return nLeft; }
getY() const451     long                getY() const { return nTop; }
452     /// Returns the difference between right and left, assuming the range includes one end, but not the other.
453     long                getWidth() const;
454     /// Returns the difference between bottom and top, assuming the range includes one end, but not the other.
455     long                getHeight() const;
456     /// Set the left edge of the rectangle to x, preserving the width
457     void                setX( long x );
458     /// Set the top edge of the rectangle to y, preserving the height
459     void                setY( long y );
setWidth(long n)460     void                setWidth( long n ) { nRight = nLeft + n; }
setHeight(long n)461     void                setHeight( long n ) { nBottom = nTop + n; }
462     /// Returns the string representation of the rectangle, format is "x, y, width, height".
463     rtl::OString        toString() const;
464 
465     /**
466      * Expands the rectangle in all directions by the input value.
467      */
468     void expand(long nExpandBy);
469     void shrink(long nShrinkBy);
470 
471     /**
472      * Sanitizing variants for handling data from the outside
473      */
474     void                SaturatingSetSize(const Size& rSize);
475     void                SaturatingSetX(long x);
476     void                SaturatingSetY(long y);
477 
478 private:
479     long                nLeft;
480     long                nTop;
481     long                nRight;
482     long                nBottom;
483 };
484 }
485 
Rectangle()486 inline tools::Rectangle::Rectangle()
487 {
488     nLeft = nTop = 0;
489     nRight = nBottom = RECT_EMPTY;
490 }
491 
Rectangle(const Point & rLT,const Point & rRB)492 inline tools::Rectangle::Rectangle( const Point& rLT, const Point& rRB )
493 {
494     nLeft   = rLT.X();
495     nTop    = rLT.Y();
496     nRight  = rRB.X();
497     nBottom = rRB.Y();
498 }
499 
Rectangle(long _nLeft,long _nTop,long _nRight,long _nBottom)500 inline tools::Rectangle::Rectangle( long _nLeft,  long _nTop,
501                              long _nRight, long _nBottom )
502 {
503     nLeft   = _nLeft;
504     nTop    = _nTop;
505     nRight  = _nRight;
506     nBottom = _nBottom;
507 }
508 
Rectangle(long _nLeft,long _nTop)509 inline tools::Rectangle::Rectangle( long _nLeft,  long _nTop )
510 {
511     nLeft   = _nLeft;
512     nTop    = _nTop;
513     nRight = nBottom = RECT_EMPTY;
514 }
515 
Rectangle(const Point & rLT,const Size & rSize)516 inline tools::Rectangle::Rectangle( const Point& rLT, const Size& rSize )
517 {
518     nLeft   = rLT.X();
519     nTop    = rLT.Y();
520     nRight  = rSize.Width()  ? nLeft+(rSize.Width()-1) : RECT_EMPTY;
521     nBottom = rSize.Height() ? nTop+(rSize.Height()-1) : RECT_EMPTY;
522 }
523 
IsEmpty() const524 inline bool tools::Rectangle::IsEmpty() const
525 {
526     return (nRight == RECT_EMPTY) || (nBottom == RECT_EMPTY);
527 }
528 
TopLeft() const529 inline Point tools::Rectangle::TopLeft() const
530 {
531     return Point( nLeft, nTop );
532 }
533 
TopRight() const534 inline Point tools::Rectangle::TopRight() const
535 {
536     return Point( (nRight == RECT_EMPTY) ? nLeft : nRight, nTop );
537 }
538 
BottomLeft() const539 inline Point tools::Rectangle::BottomLeft() const
540 {
541     return Point( nLeft, (nBottom == RECT_EMPTY) ? nTop : nBottom );
542 }
543 
BottomRight() const544 inline Point tools::Rectangle::BottomRight() const
545 {
546     return Point( (nRight  == RECT_EMPTY) ? nLeft : nRight,
547                   (nBottom == RECT_EMPTY) ? nTop  : nBottom );
548 }
549 
TopCenter() const550 inline Point tools::Rectangle::TopCenter() const
551 {
552     if ( IsEmpty() )
553         return Point( nLeft, nTop );
554     else
555         return Point( std::min( nLeft, nRight ) + std::abs( (nRight - nLeft)/2 ),
556                       std::min( nTop,  nBottom) );
557 }
558 
BottomCenter() const559 inline Point tools::Rectangle::BottomCenter() const
560 {
561     if ( IsEmpty() )
562         return Point( nLeft, nTop );
563     else
564         return Point( std::min( nLeft, nRight ) + std::abs( (nRight - nLeft)/2 ),
565                       std::max( nTop,  nBottom) );
566 }
567 
LeftCenter() const568 inline Point tools::Rectangle::LeftCenter() const
569 {
570     if ( IsEmpty() )
571         return Point( nLeft, nTop );
572     else
573         return Point( std::min( nLeft, nRight ), nTop + (nBottom - nTop)/2 );
574 }
575 
RightCenter() const576 inline Point tools::Rectangle::RightCenter() const
577 {
578     if ( IsEmpty() )
579         return Point( nLeft, nTop );
580     else
581         return Point( std::max( nLeft, nRight ), nTop + (nBottom - nTop)/2 );
582 }
583 
Center() const584 inline Point tools::Rectangle::Center() const
585 {
586     if ( IsEmpty() )
587         return Point( nLeft, nTop );
588     else
589         return Point( nLeft+(nRight-nLeft)/2 , nTop+(nBottom-nTop)/2 );
590 }
591 
Move(long nHorzMove,long nVertMove)592 inline void tools::Rectangle::Move( long nHorzMove, long nVertMove )
593 {
594     nLeft += nHorzMove;
595     nTop  += nVertMove;
596     if ( nRight != RECT_EMPTY )
597         nRight += nHorzMove;
598     if ( nBottom != RECT_EMPTY )
599         nBottom += nVertMove;
600 }
601 
SetPos(const Point & rPoint)602 inline void tools::Rectangle::SetPos( const Point& rPoint )
603 {
604     if ( nRight != RECT_EMPTY )
605         nRight += rPoint.X() - nLeft;
606     if ( nBottom != RECT_EMPTY )
607         nBottom += rPoint.Y() - nTop;
608     nLeft = rPoint.X();
609     nTop  = rPoint.Y();
610 }
611 
GetWidth() const612 inline long tools::Rectangle::GetWidth() const
613 {
614     long n;
615     if ( nRight == RECT_EMPTY )
616         n = 0;
617     else
618     {
619         n = nRight - nLeft;
620         if( n < 0 )
621             n--;
622         else
623             n++;
624     }
625 
626     return n;
627 }
628 
GetHeight() const629 inline long tools::Rectangle::GetHeight() const
630 {
631     long n;
632     if ( nBottom == RECT_EMPTY )
633         n = 0;
634     else
635     {
636         n = nBottom - nTop;
637         if ( n < 0 )
638             n--;
639         else
640             n++;
641     }
642 
643     return n;
644 }
645 
GetSize() const646 inline Size tools::Rectangle::GetSize() const
647 {
648     return Size( GetWidth(), GetHeight() );
649 }
650 
GetUnion(const tools::Rectangle & rRect) const651 inline tools::Rectangle tools::Rectangle::GetUnion( const tools::Rectangle& rRect ) const
652 {
653     tools::Rectangle aTmpRect( *this );
654     return aTmpRect.Union( rRect );
655 }
656 
GetIntersection(const tools::Rectangle & rRect) const657 inline tools::Rectangle tools::Rectangle::GetIntersection( const tools::Rectangle& rRect ) const
658 {
659     tools::Rectangle aTmpRect( *this );
660     return aTmpRect.Intersection( rRect );
661 }
662 
operator ==(const tools::Rectangle & rRect) const663 inline bool tools::Rectangle::operator == ( const tools::Rectangle& rRect ) const
664 {
665     return (nLeft   == rRect.nLeft   ) &&
666            (nTop    == rRect.nTop    ) &&
667            (nRight  == rRect.nRight  ) &&
668            (nBottom == rRect.nBottom );
669 }
670 
operator !=(const tools::Rectangle & rRect) const671 inline bool tools::Rectangle::operator != ( const tools::Rectangle& rRect ) const
672 {
673     return (nLeft   != rRect.nLeft   ) ||
674            (nTop    != rRect.nTop    ) ||
675            (nRight  != rRect.nRight  ) ||
676            (nBottom != rRect.nBottom );
677 }
678 
operator +=(const Point & rPt)679 inline tools::Rectangle& tools::Rectangle::operator +=( const Point& rPt )
680 {
681     nLeft += rPt.X();
682     nTop  += rPt.Y();
683     if ( nRight != RECT_EMPTY )
684         nRight += rPt.X();
685     if ( nBottom != RECT_EMPTY )
686         nBottom += rPt.Y();
687     return *this;
688 }
689 
operator -=(const Point & rPt)690 inline tools::Rectangle& tools::Rectangle::operator -= ( const Point& rPt )
691 {
692     nLeft -= rPt.X();
693     nTop  -= rPt.Y();
694     if ( nRight != RECT_EMPTY )
695         nRight -= rPt.X();
696     if ( nBottom != RECT_EMPTY )
697         nBottom -= rPt.Y();
698     return *this;
699 }
700 
701 namespace tools
702 {
operator +(const Rectangle & rRect,const Point & rPt)703 inline Rectangle operator + ( const Rectangle& rRect, const Point& rPt )
704 {
705     return rRect.IsEmpty()
706         ?  Rectangle( rRect.nLeft  + rPt.X(), rRect.nTop    + rPt.Y() )
707         :  Rectangle( rRect.nLeft  + rPt.X(), rRect.nTop    + rPt.Y(),
708                       rRect.nRight + rPt.X(), rRect.nBottom + rPt.Y() );
709 }
710 
operator -(const Rectangle & rRect,const Point & rPt)711 inline Rectangle operator - ( const Rectangle& rRect, const Point& rPt )
712 {
713     return rRect.IsEmpty()
714         ? Rectangle( rRect.nLeft - rPt.X(),  rRect.nTop - rPt.Y() )
715         : Rectangle( rRect.nLeft - rPt.X(),  rRect.nTop - rPt.Y(),
716                      rRect.nRight - rPt.X(), rRect.nBottom - rPt.Y() );
717 }
718 }
719 
720 template< typename charT, typename traits >
operator <<(std::basic_ostream<charT,traits> & stream,const tools::Rectangle & rectangle)721 inline std::basic_ostream<charT, traits> & operator <<(
722     std::basic_ostream<charT, traits> & stream, const tools::Rectangle& rectangle )
723 {
724     if (rectangle.IsEmpty())
725         return stream << "EMPTY";
726     else
727         return stream << rectangle.getWidth() << 'x' << rectangle.getHeight()
728                       << "@(" << rectangle.getX() << ',' << rectangle.getY() << ")";
729 }
730 
731 #endif
732 
733 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
734