Bump version to 6.4-15
[LibreOffice.git] / include / tools / gen.hxx
blob2603070589e83c18f0e33d6b7f05d03c67fc7c75
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #ifndef INCLUDED_TOOLS_GEN_HXX
20 #define INCLUDED_TOOLS_GEN_HXX
22 #include <tools/toolsdllapi.h>
24 #include <limits.h>
25 #include <algorithm>
26 #include <ostream>
28 class SvStream;
29 namespace rtl
31 class OString;
34 enum TriState { TRISTATE_FALSE, TRISTATE_TRUE, TRISTATE_INDET };
36 // Pair
38 class SAL_WARN_UNUSED Pair
40 public:
41 Pair() : nA(0), nB(0) {}
42 Pair( long _nA, long _nB ) : nA(_nA), nB(_nB) {}
44 long A() const { return nA; }
45 long B() const { return nB; }
47 long& A() { return nA; }
48 long& B() { return nB; }
50 TOOLS_DLLPUBLIC rtl::OString toString() const;
52 protected:
53 long nA;
54 long nB;
57 namespace tools { namespace detail {
59 // Used to implement operator == for subclasses of Pair:
60 inline bool equal(Pair const & p1, Pair const & p2)
62 return p1.A() == p2.A() && p1.B() == p2.B();
65 } }
67 // Point
69 class Size;
70 class SAL_WARN_UNUSED SAL_DLLPUBLIC_EXPORT Point final : protected Pair
72 public:
73 Point() {}
74 Point( long nX, long nY ) : Pair( nX, nY ) {}
76 long X() const { return nA; }
77 long Y() const { return nB; }
79 void Move( long nHorzMove, long nVertMove );
80 void Move( Size const & s );
81 long AdjustX( long nHorzMove ) { nA += nHorzMove; return nA; }
82 long AdjustY( long nVertMove ) { nB += nVertMove; return nB; }
84 void RotateAround( long& rX, long& rY, short nOrientation ) const;
85 void RotateAround( Point&, short nOrientation ) const;
87 Point& operator += ( const Point& rPoint );
88 Point& operator -= ( const Point& rPoint );
89 Point& operator *= ( const long nVal );
90 Point& operator /= ( const long nVal );
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 );
97 long getX() const { return X(); }
98 long getY() const { return Y(); }
99 void setX(long nX) { nA = nX; }
100 void setY(long nY) { nB = nY; }
102 Pair const & toPair() const { return *this; }
103 Pair & toPair() { return *this; }
105 using Pair::toString;
108 inline void Point::Move( long nHorzMove, long nVertMove )
110 nA += nHorzMove;
111 nB += nVertMove;
114 inline Point& Point::operator += ( const Point& rPoint )
116 nA += rPoint.nA;
117 nB += rPoint.nB;
118 return *this;
121 inline Point& Point::operator -= ( const Point& rPoint )
123 nA -= rPoint.nA;
124 nB -= rPoint.nB;
125 return *this;
128 inline Point& Point::operator *= ( const long nVal )
130 nA *= nVal;
131 nB *= nVal;
132 return *this;
135 inline Point& Point::operator /= ( const long nVal )
137 nA /= nVal;
138 nB /= nVal;
139 return *this;
142 inline Point operator+( const Point &rVal1, const Point &rVal2 )
144 return Point( rVal1.nA+rVal2.nA, rVal1.nB+rVal2.nB );
147 inline Point operator-( const Point &rVal1, const Point &rVal2 )
149 return Point( rVal1.nA-rVal2.nA, rVal1.nB-rVal2.nB );
152 inline Point operator*( const Point &rVal1, const long nVal2 )
154 return Point( rVal1.nA*nVal2, rVal1.nB*nVal2 );
157 inline Point operator/( const Point &rVal1, const long nVal2 )
159 return Point( rVal1.nA/nVal2, rVal1.nB/nVal2 );
162 inline bool operator ==(Point const & p1, Point const & p2)
164 return tools::detail::equal(p1.toPair(), p2.toPair());
167 inline bool operator !=(Point const & p1, Point const & p2)
169 return !(p1 == p2);
172 template< typename charT, typename traits >
173 inline std::basic_ostream<charT, traits> & operator <<(
174 std::basic_ostream<charT, traits> & stream, const Point& point )
176 return stream << point.X() << ',' << point.Y();
179 // Size
181 class SAL_WARN_UNUSED Size final : protected Pair
183 public:
184 Size() {}
185 Size( long nWidth, long nHeight ) : Pair( nWidth, nHeight ) {}
187 long Width() const { return nA; }
188 long Height() const { return nB; }
190 long AdjustWidth( long n ) { nA += n; return nA; }
191 long AdjustHeight( long n ) { nB += n; return nB; }
193 long getWidth() const { return Width(); }
194 long getHeight() const { return Height(); }
195 void setWidth(long nWidth) { nA = nWidth; }
196 void setHeight(long nHeight) { nB = nHeight; }
198 void extendBy(long x, long y)
200 nA += x;
201 nB += y;
204 Pair const & toPair() const { return *this; }
205 Pair & toPair() { return *this; }
207 using Pair::toString;
210 inline bool operator ==(Size const & s1, Size const & s2)
212 return tools::detail::equal(s1.toPair(), s2.toPair());
215 inline bool operator !=(Size const & s1, Size const & s2)
217 return !(s1 == s2);
220 template< typename charT, typename traits >
221 inline std::basic_ostream<charT, traits> & operator <<(
222 std::basic_ostream<charT, traits> & stream, const Size& size )
224 return stream << size.Width() << 'x' << size.Height();
227 inline void Point::Move( Size const & s )
229 AdjustX(s.Width());
230 AdjustY(s.Height());
233 // Range
235 #define RANGE_MAX LONG_MAX
237 class SAL_WARN_UNUSED Range final : protected Pair
239 public:
240 Range() {}
241 Range( long nMin, long nMax ) : Pair( nMin, nMax ) {}
243 long Min() const { return nA; }
244 long Max() const { return nB; }
245 long Len() const { return nB - nA + 1; }
247 long& Min() { return nA; }
248 long& Max() { return nB; }
250 bool IsInside( long nIs ) const;
252 void Justify();
254 Pair const & toPair() const { return *this; }
255 Pair & toPair() { return *this; }
257 using Pair::toString;
260 inline bool Range::IsInside( long nIs ) const
262 return ((nA <= nIs) && (nIs <= nB ));
265 inline void Range::Justify()
267 if ( nA > nB )
269 long nHelp = nA;
270 nA = nB;
271 nB = nHelp;
275 inline bool operator ==(Range const & r1, Range const & r2)
277 return tools::detail::equal(r1.toPair(), r2.toPair());
280 inline bool operator !=(Range const & r1, Range const & r2)
282 return !(r1 == r2);
285 template< typename charT, typename traits >
286 inline std::basic_ostream<charT, traits> & operator <<(
287 std::basic_ostream<charT, traits> & stream, const Range& range )
289 return stream << range.Min() << '-' << range.Max();
292 // Selection
294 #define SELECTION_MIN LONG_MIN
295 #define SELECTION_MAX LONG_MAX
297 class SAL_WARN_UNUSED Selection final : protected Pair
299 public:
300 Selection() {}
301 Selection( long nPos ) : Pair( nPos, nPos ) {}
302 Selection( long nMin, long nMax ) : Pair( nMin, nMax ) {}
304 long Min() const { return nA; }
305 long Max() const { return nB; }
306 long Len() const { return nB - nA; }
308 long& Min() { return nA; }
309 long& Max() { return nB; }
311 bool IsInside( long nIs ) const;
313 void Justify();
315 bool operator !() const { return !Len(); }
317 long getMin() const { return Min(); }
318 void setMin(long nMin) { Min() = nMin; }
319 void setMax(long nMax) { Max() = nMax; }
321 Pair const & toPair() const { return *this; }
322 Pair & toPair() { return *this; }
324 using Pair::toString;
327 inline bool Selection::IsInside( long nIs ) const
329 return ((nA <= nIs) && (nIs < nB ));
332 inline void Selection::Justify()
334 if ( nA > nB )
336 long nHelp = nA;
337 nA = nB;
338 nB = nHelp;
342 inline bool operator ==(Selection const & s1, Selection const & s2)
344 return tools::detail::equal(s1.toPair(), s2.toPair());
347 inline bool operator !=(Selection const & s1, Selection const & s2)
349 return !(s1 == s2);
352 template< typename charT, typename traits >
353 inline std::basic_ostream<charT, traits> & operator <<(
354 std::basic_ostream<charT, traits> & stream, const Selection& selection )
356 return stream << selection.Min() << '-' << selection.Max();
358 // Rectangle
360 #define RECT_MAX LONG_MAX
361 #define RECT_MIN LONG_MIN
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!
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
374 class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Rectangle final
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 );
386 long Left() const { return nLeft; }
387 long Right() const;
388 long Top() const { return nTop; }
389 long Bottom() const;
391 void SetLeft(long v) { nLeft = v; }
392 void SetRight(long v) { nRight = v; }
393 void SetTop(long v) { nTop = v; }
394 void SetBottom(long v) { nBottom = v; }
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;
406 /// Move the top and left edges by a delta, preserving width and height
407 inline void Move( long nHorzMoveDelta, long nVertMoveDelta );
408 void Move( Size const & s ) { Move(s.Width(), s.Height()); }
409 long AdjustLeft( long nHorzMoveDelta ) { nLeft += nHorzMoveDelta; return nLeft; }
410 long AdjustRight( long nHorzMoveDelta );
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;
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;
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;
427 void Justify();
429 bool IsInside( const Point& rPOINT ) const;
430 bool IsInside( const tools::Rectangle& rRect ) const;
431 bool IsOver( const tools::Rectangle& rRect ) const;
433 void SetEmpty() { nRight = nBottom = RECT_EMPTY; }
434 void SetWidthEmpty() { nRight = RECT_EMPTY; }
435 void SetHeightEmpty() { nBottom = RECT_EMPTY; }
436 inline bool IsEmpty() const;
437 bool IsWidthEmpty() const { return nRight == RECT_EMPTY; }
438 bool IsHeightEmpty() const { return nBottom == RECT_EMPTY; }
440 inline bool operator == ( const tools::Rectangle& rRect ) const;
441 inline bool operator != ( const tools::Rectangle& rRect ) const;
443 inline tools::Rectangle& operator += ( const Point& rPt );
444 inline tools::Rectangle& operator -= ( const Point& rPt );
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 );
449 // ONE
450 long getX() const { return nLeft; }
451 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 );
460 void setWidth( long n ) { nRight = nLeft + 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;
466 * Expands the rectangle in all directions by the input value.
468 void expand(long nExpandBy);
469 void shrink(long nShrinkBy);
472 * Sanitizing variants for handling data from the outside
474 void SaturatingSetSize(const Size& rSize);
475 void SaturatingSetX(long x);
476 void SaturatingSetY(long y);
478 private:
479 long nLeft;
480 long nTop;
481 long nRight;
482 long nBottom;
486 inline tools::Rectangle::Rectangle()
488 nLeft = nTop = 0;
489 nRight = nBottom = RECT_EMPTY;
492 inline tools::Rectangle::Rectangle( const Point& rLT, const Point& rRB )
494 nLeft = rLT.X();
495 nTop = rLT.Y();
496 nRight = rRB.X();
497 nBottom = rRB.Y();
500 inline tools::Rectangle::Rectangle( long _nLeft, long _nTop,
501 long _nRight, long _nBottom )
503 nLeft = _nLeft;
504 nTop = _nTop;
505 nRight = _nRight;
506 nBottom = _nBottom;
509 inline tools::Rectangle::Rectangle( long _nLeft, long _nTop )
511 nLeft = _nLeft;
512 nTop = _nTop;
513 nRight = nBottom = RECT_EMPTY;
516 inline tools::Rectangle::Rectangle( const Point& rLT, const Size& rSize )
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;
524 inline bool tools::Rectangle::IsEmpty() const
526 return (nRight == RECT_EMPTY) || (nBottom == RECT_EMPTY);
529 inline Point tools::Rectangle::TopLeft() const
531 return Point( nLeft, nTop );
534 inline Point tools::Rectangle::TopRight() const
536 return Point( (nRight == RECT_EMPTY) ? nLeft : nRight, nTop );
539 inline Point tools::Rectangle::BottomLeft() const
541 return Point( nLeft, (nBottom == RECT_EMPTY) ? nTop : nBottom );
544 inline Point tools::Rectangle::BottomRight() const
546 return Point( (nRight == RECT_EMPTY) ? nLeft : nRight,
547 (nBottom == RECT_EMPTY) ? nTop : nBottom );
550 inline Point tools::Rectangle::TopCenter() const
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) );
559 inline Point tools::Rectangle::BottomCenter() const
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) );
568 inline Point tools::Rectangle::LeftCenter() const
570 if ( IsEmpty() )
571 return Point( nLeft, nTop );
572 else
573 return Point( std::min( nLeft, nRight ), nTop + (nBottom - nTop)/2 );
576 inline Point tools::Rectangle::RightCenter() const
578 if ( IsEmpty() )
579 return Point( nLeft, nTop );
580 else
581 return Point( std::max( nLeft, nRight ), nTop + (nBottom - nTop)/2 );
584 inline Point tools::Rectangle::Center() const
586 if ( IsEmpty() )
587 return Point( nLeft, nTop );
588 else
589 return Point( nLeft+(nRight-nLeft)/2 , nTop+(nBottom-nTop)/2 );
592 inline void tools::Rectangle::Move( long nHorzMove, long nVertMove )
594 nLeft += nHorzMove;
595 nTop += nVertMove;
596 if ( nRight != RECT_EMPTY )
597 nRight += nHorzMove;
598 if ( nBottom != RECT_EMPTY )
599 nBottom += nVertMove;
602 inline void tools::Rectangle::SetPos( const Point& rPoint )
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();
612 inline long tools::Rectangle::GetWidth() const
614 long n;
615 if ( nRight == RECT_EMPTY )
616 n = 0;
617 else
619 n = nRight - nLeft;
620 if( n < 0 )
621 n--;
622 else
623 n++;
626 return n;
629 inline long tools::Rectangle::GetHeight() const
631 long n;
632 if ( nBottom == RECT_EMPTY )
633 n = 0;
634 else
636 n = nBottom - nTop;
637 if ( n < 0 )
638 n--;
639 else
640 n++;
643 return n;
646 inline Size tools::Rectangle::GetSize() const
648 return Size( GetWidth(), GetHeight() );
651 inline tools::Rectangle tools::Rectangle::GetUnion( const tools::Rectangle& rRect ) const
653 tools::Rectangle aTmpRect( *this );
654 return aTmpRect.Union( rRect );
657 inline tools::Rectangle tools::Rectangle::GetIntersection( const tools::Rectangle& rRect ) const
659 tools::Rectangle aTmpRect( *this );
660 return aTmpRect.Intersection( rRect );
663 inline bool tools::Rectangle::operator == ( const tools::Rectangle& rRect ) const
665 return (nLeft == rRect.nLeft ) &&
666 (nTop == rRect.nTop ) &&
667 (nRight == rRect.nRight ) &&
668 (nBottom == rRect.nBottom );
671 inline bool tools::Rectangle::operator != ( const tools::Rectangle& rRect ) const
673 return (nLeft != rRect.nLeft ) ||
674 (nTop != rRect.nTop ) ||
675 (nRight != rRect.nRight ) ||
676 (nBottom != rRect.nBottom );
679 inline tools::Rectangle& tools::Rectangle::operator +=( const Point& rPt )
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;
690 inline tools::Rectangle& tools::Rectangle::operator -= ( const Point& rPt )
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;
701 namespace tools
703 inline Rectangle operator + ( const Rectangle& rRect, const Point& rPt )
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() );
711 inline Rectangle operator - ( const Rectangle& rRect, const Point& rPt )
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() );
720 template< typename charT, typename traits >
721 inline std::basic_ostream<charT, traits> & operator <<(
722 std::basic_ostream<charT, traits> & stream, const tools::Rectangle& rectangle )
724 if (rectangle.IsEmpty())
725 return stream << "EMPTY";
726 else
727 return stream << rectangle.getWidth() << 'x' << rectangle.getHeight()
728 << "@(" << rectangle.getX() << ',' << rectangle.getY() << ")";
731 #endif
733 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */