1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <tools/long.hxx>
25 #include <tools/degree.hxx>
29 #include <config_options.h>
30 #include <o3tl/unit_conversion.hxx>
38 enum TriState
{ TRISTATE_FALSE
, TRISTATE_TRUE
, TRISTATE_INDET
};
42 class SAL_WARN_UNUSED Pair
45 constexpr Pair() : nA(0), nB(0) {}
46 constexpr Pair( tools::Long _nA
, tools::Long _nB
) : nA(_nA
), nB(_nB
) {}
48 tools::Long
A() const { return nA
; }
49 tools::Long
B() const { return nB
; }
51 tools::Long
& A() { return nA
; }
52 tools::Long
& B() { return nB
; }
54 TOOLS_DLLPUBLIC
rtl::OString
toString() const;
61 namespace tools::detail
{
63 // Used to implement operator == for subclasses of Pair:
64 inline bool equal(Pair
const & p1
, Pair
const & p2
)
66 return p1
.A() == p2
.A() && p1
.B() == p2
.B();
74 class SAL_WARN_UNUSED
UNLESS_MERGELIBS(SAL_DLLPUBLIC_EXPORT
) Point final
: protected Pair
78 constexpr Point( tools::Long nX
, tools::Long nY
) : Pair( nX
, nY
) {}
80 constexpr tools::Long
X() const { return nA
; }
81 constexpr tools::Long
Y() const { return nB
; }
83 void Move( tools::Long nHorzMove
, tools::Long nVertMove
);
84 void Move( Size
const & s
);
85 tools::Long
AdjustX( tools::Long nHorzMove
) { nA
+= nHorzMove
; return nA
; }
86 tools::Long
AdjustY( tools::Long nVertMove
) { nB
+= nVertMove
; return nB
; }
88 void RotateAround( tools::Long
& rX
, tools::Long
& rY
, Degree10 nOrientation
) const;
89 void RotateAround( Point
&, Degree10 nOrientation
) const;
91 Point
& operator += ( const Point
& rPoint
);
92 Point
& operator -= ( const Point
& rPoint
);
93 Point
& operator *= ( const tools::Long nVal
);
94 Point
& operator /= ( const tools::Long nVal
);
96 friend inline Point
operator+( const Point
&rVal1
, const Point
&rVal2
);
97 friend inline Point
operator-( const Point
&rVal1
, const Point
&rVal2
);
98 friend inline Point
operator*( const Point
&rVal1
, const tools::Long nVal2
);
99 friend inline Point
operator/( const Point
&rVal1
, const tools::Long nVal2
);
101 constexpr tools::Long
getX() const { return X(); }
102 constexpr tools::Long
getY() const { return Y(); }
103 void setX(tools::Long nX
) { nA
= nX
; }
104 void setY(tools::Long nY
) { nB
= nY
; }
106 Pair
const & toPair() const { return *this; }
107 Pair
& toPair() { return *this; }
109 using Pair::toString
;
112 inline void Point::Move( tools::Long nHorzMove
, tools::Long nVertMove
)
118 inline Point
& Point::operator += ( const Point
& rPoint
)
125 inline Point
& Point::operator -= ( const Point
& rPoint
)
132 inline Point
& Point::operator *= ( const tools::Long nVal
)
139 inline Point
& Point::operator /= ( const tools::Long nVal
)
146 inline Point
operator+( const Point
&rVal1
, const Point
&rVal2
)
148 return Point( rVal1
.nA
+rVal2
.nA
, rVal1
.nB
+rVal2
.nB
);
151 inline Point
operator-( const Point
&rVal1
, const Point
&rVal2
)
153 return Point( rVal1
.nA
-rVal2
.nA
, rVal1
.nB
-rVal2
.nB
);
156 inline Point
operator*( const Point
&rVal1
, const tools::Long nVal2
)
158 return Point( rVal1
.nA
*nVal2
, rVal1
.nB
*nVal2
);
161 inline Point
operator/( const Point
&rVal1
, const tools::Long nVal2
)
163 return Point( rVal1
.nA
/nVal2
, rVal1
.nB
/nVal2
);
166 inline bool operator ==(Point
const & p1
, Point
const & p2
)
168 return tools::detail::equal(p1
.toPair(), p2
.toPair());
171 inline bool operator !=(Point
const & p1
, Point
const & p2
)
179 constexpr Point
convert(const Point
& rPoint
, o3tl::Length eFrom
, o3tl::Length eTo
)
182 o3tl::convert(rPoint
.getX(), eFrom
, eTo
),
183 o3tl::convert(rPoint
.getY(), eFrom
, eTo
));
188 template< typename charT
, typename traits
>
189 inline std::basic_ostream
<charT
, traits
> & operator <<(
190 std::basic_ostream
<charT
, traits
> & stream
, const Point
& point
)
192 return stream
<< point
.X() << ',' << point
.Y();
197 class SAL_WARN_UNUSED Size final
: protected Pair
201 constexpr Size( tools::Long nWidth
, tools::Long nHeight
) : Pair( nWidth
, nHeight
) {}
203 constexpr tools::Long
Width() const { return nA
; }
204 constexpr tools::Long
Height() const { return nB
; }
206 tools::Long
AdjustWidth( tools::Long n
) { nA
+= n
; return nA
; }
207 tools::Long
AdjustHeight( tools::Long n
) { nB
+= n
; return nB
; }
209 constexpr tools::Long
getWidth() const { return Width(); }
210 constexpr tools::Long
getHeight() const { return Height(); }
211 void setWidth(tools::Long nWidth
) { nA
= nWidth
; }
212 void setHeight(tools::Long nHeight
) { nB
= nHeight
; }
214 bool IsEmpty() const { return nA
<= 0 || nB
<= 0; }
216 void extendBy(tools::Long x
, tools::Long y
)
222 Pair
const & toPair() const { return *this; }
223 Pair
& toPair() { return *this; }
225 using Pair::toString
;
227 Size
& operator += ( const Size
& rSize
);
228 Size
& operator -= ( const Size
& rSize
);
229 Size
& operator *= ( const tools::Long nVal
);
230 Size
& operator /= ( const tools::Long nVal
);
232 friend inline Size
operator+( const Size
&rVal1
, const Size
&rVal2
);
233 friend inline Size
operator-( const Size
&rVal1
, const Size
&rVal2
);
234 friend inline Size
operator*( const Size
&rVal1
, const tools::Long nVal2
);
235 friend inline Size
operator/( const Size
&rVal1
, const tools::Long nVal2
);
239 inline bool operator ==(Size
const & s1
, Size
const & s2
)
241 return tools::detail::equal(s1
.toPair(), s2
.toPair());
244 inline bool operator !=(Size
const & s1
, Size
const & s2
)
249 inline Size
& Size::operator += ( const Size
& rSize
)
256 inline Size
& Size::operator -= ( const Size
& rSize
)
263 inline Size
& Size::operator *= ( const tools::Long nVal
)
270 inline Size
& Size::operator /= ( const tools::Long nVal
)
277 inline Size
operator+( const Size
&rVal1
, const Size
&rVal2
)
279 return Size( rVal1
.nA
+rVal2
.nA
, rVal1
.nB
+rVal2
.nB
);
282 inline Size
operator-( const Size
&rVal1
, const Size
&rVal2
)
284 return Size( rVal1
.nA
-rVal2
.nA
, rVal1
.nB
-rVal2
.nB
);
287 inline Size
operator*( const Size
&rVal1
, const tools::Long nVal2
)
289 return Size( rVal1
.nA
*nVal2
, rVal1
.nB
*nVal2
);
292 inline Size
operator/( const Size
&rVal1
, const tools::Long nVal2
)
294 return Size( rVal1
.nA
/nVal2
, rVal1
.nB
/nVal2
);
300 constexpr Size
convert(const Size
& rSize
, o3tl::Length eFrom
, o3tl::Length eTo
)
303 o3tl::convert(rSize
.Width(), eFrom
, eTo
),
304 o3tl::convert(rSize
.Height(), eFrom
, eTo
));
309 template< typename charT
, typename traits
>
310 inline std::basic_ostream
<charT
, traits
> & operator <<(
311 std::basic_ostream
<charT
, traits
> & stream
, const Size
& size
)
313 return stream
<< size
.Width() << 'x' << size
.Height();
316 inline void Point::Move( Size
const & s
)
324 #define RANGE_MAX LONG_MAX
326 class SAL_WARN_UNUSED Range final
: protected Pair
330 constexpr Range( tools::Long nMin
, tools::Long nMax
) : Pair( nMin
, nMax
) {}
332 tools::Long
Min() const { return nA
; }
333 tools::Long
Max() const { return nB
; }
334 tools::Long
Len() const { return nB
- nA
+ 1; }
336 tools::Long
& Min() { return nA
; }
337 tools::Long
& Max() { return nB
; }
339 bool IsInside( tools::Long nIs
) const;
343 Pair
const & toPair() const { return *this; }
344 Pair
& toPair() { return *this; }
346 using Pair::toString
;
349 inline bool Range::IsInside( tools::Long nIs
) const
351 return ((nA
<= nIs
) && (nIs
<= nB
));
354 inline void Range::Justify()
358 tools::Long nHelp
= nA
;
364 inline bool operator ==(Range
const & r1
, Range
const & r2
)
366 return tools::detail::equal(r1
.toPair(), r2
.toPair());
369 inline bool operator !=(Range
const & r1
, Range
const & r2
)
374 template< typename charT
, typename traits
>
375 inline std::basic_ostream
<charT
, traits
> & operator <<(
376 std::basic_ostream
<charT
, traits
> & stream
, const Range
& range
)
378 return stream
<< range
.Min() << '-' << range
.Max();
383 #define SELECTION_MIN LONG_MIN
384 #define SELECTION_MAX LONG_MAX
386 class SAL_WARN_UNUSED Selection final
: protected Pair
390 Selection( tools::Long nPos
) : Pair( nPos
, nPos
) {}
391 Selection( tools::Long nMin
, tools::Long nMax
) : Pair( nMin
, nMax
) {}
393 tools::Long
Min() const { return nA
; }
394 tools::Long
Max() const { return nB
; }
395 tools::Long
Len() const { return nB
- nA
; }
397 tools::Long
& Min() { return nA
; }
398 tools::Long
& Max() { return nB
; }
400 bool IsInside( tools::Long nIs
) const;
404 bool operator !() const { return !Len(); }
406 tools::Long
getMin() const { return Min(); }
407 void setMin(tools::Long nMin
) { Min() = nMin
; }
408 void setMax(tools::Long nMax
) { Max() = nMax
; }
410 Pair
const & toPair() const { return *this; }
411 Pair
& toPair() { return *this; }
413 using Pair::toString
;
416 inline bool Selection::IsInside( tools::Long nIs
) const
418 return ((nA
<= nIs
) && (nIs
< nB
));
421 inline void Selection::Justify()
425 tools::Long nHelp
= nA
;
431 inline bool operator ==(Selection
const & s1
, Selection
const & s2
)
433 return tools::detail::equal(s1
.toPair(), s2
.toPair());
436 inline bool operator !=(Selection
const & s1
, Selection
const & s2
)
441 template< typename charT
, typename traits
>
442 inline std::basic_ostream
<charT
, traits
> & operator <<(
443 std::basic_ostream
<charT
, traits
> & stream
, const Selection
& selection
)
445 return stream
<< selection
.Min() << '-' << selection
.Max();
449 #define RECT_MAX LONG_MAX
450 #define RECT_MIN LONG_MIN
452 /// Note: this class is a true marvel of engineering: because the author
453 /// could not decide whether it's better to have a closed or half-open
454 /// interval, they just implemented *both* in the same class!
456 /// If you have the misfortune of having to use this class, don't immediately
457 /// despair but first take note that the uppercase GetWidth() / GetHeight()
458 /// etc. methods interpret the interval as closed, while the lowercase
459 /// getWidth() / getHeight() etc. methods interpret the interval as half-open.
460 /// Ok, now is the time for despair.
463 class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Rectangle final
465 static constexpr short RECT_EMPTY
= -32767;
467 constexpr Rectangle() = default;
468 constexpr Rectangle( const Point
& rLT
, const Point
& rRB
);
469 constexpr Rectangle( tools::Long nLeft
, tools::Long nTop
,
470 tools::Long nRight
, tools::Long nBottom
);
471 /// Constructs an empty Rectangle, with top/left at the specified params
472 constexpr Rectangle( tools::Long nLeft
, tools::Long nTop
);
473 constexpr Rectangle( const Point
& rLT
, const Size
& rSize
);
475 static Rectangle
Justify( const Point
& rLT
, const Point
& rRB
);
477 constexpr tools::Long
Left() const { return nLeft
; }
478 constexpr tools::Long
Right() const { return IsWidthEmpty() ? nLeft
: nRight
; }
479 constexpr tools::Long
Top() const { return nTop
; }
480 constexpr tools::Long
Bottom() const { return IsHeightEmpty() ? nTop
: nBottom
; }
482 constexpr void SetLeft(tools::Long v
) { nLeft
= v
; }
483 constexpr void SetRight(tools::Long v
) { nRight
= v
; }
484 constexpr void SetTop(tools::Long v
) { nTop
= v
; }
485 constexpr void SetBottom(tools::Long v
) { nBottom
= v
; }
487 constexpr Point
TopLeft() const { return { Left(), Top() }; }
488 constexpr Point
TopRight() const { return { Right(), Top() }; }
489 constexpr Point
TopCenter() const { return { (Left() + Right()) / 2, Top() }; }
490 constexpr Point
BottomLeft() const { return { Left(), Bottom() }; }
491 constexpr Point
BottomRight() const { return { Right(), Bottom() }; }
492 constexpr Point
BottomCenter() const { return { (Left() + Right()) / 2, Bottom() }; }
493 constexpr Point
LeftCenter() const { return { Left(), (Top() + Bottom()) / 2 }; }
494 constexpr Point
RightCenter() const { return { Right(), (Top() + Bottom()) / 2 }; }
495 constexpr Point
Center() const { return { (Left() + Right()) / 2, (Top() + Bottom()) / 2 }; }
497 /// Move the top and left edges by a delta, preserving width and height
498 inline void Move( tools::Long nHorzMoveDelta
, tools::Long nVertMoveDelta
);
499 void Move( Size
const & s
) { Move(s
.Width(), s
.Height()); }
500 tools::Long
AdjustLeft( tools::Long nHorzMoveDelta
) { nLeft
+= nHorzMoveDelta
; return nLeft
; }
501 tools::Long
AdjustRight( tools::Long nHorzMoveDelta
);
502 tools::Long
AdjustTop( tools::Long nVertMoveDelta
) { nTop
+= nVertMoveDelta
; return nTop
; }
503 tools::Long
AdjustBottom( tools::Long nVertMoveDelta
);
504 inline void SetPos( const Point
& rPoint
);
505 void SetSize( const Size
& rSize
);
507 constexpr Size
GetSize() const { return { GetWidth(), GetHeight() }; }
509 /// Returns the difference between right and left, assuming the range is inclusive.
510 constexpr tools::Long
GetWidth() const
526 /// Returns the difference between bottom and top, assuming the range is inclusive.
527 constexpr tools::Long
GetHeight() const
531 if (!IsHeightEmpty())
543 tools::Rectangle
& Union( const tools::Rectangle
& rRect
);
544 tools::Rectangle
& Intersection( const tools::Rectangle
& rRect
);
545 inline tools::Rectangle
GetUnion( const tools::Rectangle
& rRect
) const;
546 inline tools::Rectangle
GetIntersection( const tools::Rectangle
& rRect
) const;
550 bool IsInside( const Point
& rPOINT
) const;
551 bool IsInside( const tools::Rectangle
& rRect
) const;
552 bool IsOver( const tools::Rectangle
& rRect
) const;
554 void SetEmpty() { nRight
= nBottom
= RECT_EMPTY
; }
555 void SetWidthEmpty() { nRight
= RECT_EMPTY
; }
556 void SetHeightEmpty() { nBottom
= RECT_EMPTY
; }
557 constexpr bool IsEmpty() const { return IsWidthEmpty() || IsHeightEmpty(); }
558 constexpr bool IsWidthEmpty() const { return nRight
== RECT_EMPTY
; }
559 constexpr bool IsHeightEmpty() const { return nBottom
== RECT_EMPTY
; }
561 inline bool operator == ( const tools::Rectangle
& rRect
) const;
562 inline bool operator != ( const tools::Rectangle
& rRect
) const;
564 inline tools::Rectangle
& operator += ( const Point
& rPt
);
565 inline tools::Rectangle
& operator -= ( const Point
& rPt
);
567 friend inline tools::Rectangle
operator + ( const tools::Rectangle
& rRect
, const Point
& rPt
);
568 friend inline tools::Rectangle
operator - ( const tools::Rectangle
& rRect
, const Point
& rPt
);
571 tools::Long
getX() const { return nLeft
; }
572 tools::Long
getY() const { return nTop
; }
573 /// Returns the difference between right and left, assuming the range includes one end, but not the other.
574 tools::Long
getWidth() const { return Right() - Left(); }
575 /// Returns the difference between bottom and top, assuming the range includes one end, but not the other.
576 tools::Long
getHeight() const { return Bottom() - Top(); }
577 /// Set the left edge of the rectangle to x, preserving the width
578 void setX( tools::Long x
);
579 /// Set the top edge of the rectangle to y, preserving the height
580 void setY( tools::Long y
);
581 void setWidth( tools::Long n
) { nRight
= nLeft
+ n
; }
582 void setHeight( tools::Long n
) { nBottom
= nTop
+ n
; }
583 /// Returns the string representation of the rectangle, format is "x, y, width, height".
584 rtl::OString
toString() const;
587 * Expands the rectangle in all directions by the input value.
589 void expand(tools::Long nExpandBy
);
590 void shrink(tools::Long nShrinkBy
);
593 * Sanitizing variants for handling data from the outside
595 void SaturatingSetSize(const Size
& rSize
);
596 void SaturatingSetX(tools::Long x
);
597 void SaturatingSetY(tools::Long y
);
600 tools::Long nLeft
= 0;
601 tools::Long nTop
= 0;
602 tools::Long nRight
= RECT_EMPTY
;
603 tools::Long nBottom
= RECT_EMPTY
;
607 constexpr inline tools::Rectangle::Rectangle( const Point
& rLT
, const Point
& rRB
)
608 : Rectangle(rLT
.X(), rLT
.Y(), rRB
.X(), rRB
.Y())
611 constexpr inline tools::Rectangle::Rectangle( tools::Long _nLeft
, tools::Long _nTop
,
612 tools::Long _nRight
, tools::Long _nBottom
)
616 , nBottom( _nBottom
)
619 constexpr inline tools::Rectangle::Rectangle( tools::Long _nLeft
, tools::Long _nTop
)
624 constexpr inline tools::Rectangle::Rectangle( const Point
& rLT
, const Size
& rSize
)
627 , nRight( rSize
.Width() ? nLeft
+(rSize
.Width()-1) : RECT_EMPTY
)
628 , nBottom( rSize
.Height() ? nTop
+(rSize
.Height()-1) : RECT_EMPTY
)
631 inline void tools::Rectangle::Move( tools::Long nHorzMove
, tools::Long nVertMove
)
637 if (!IsHeightEmpty())
638 nBottom
+= nVertMove
;
641 inline void tools::Rectangle::SetPos( const Point
& rPoint
)
644 nRight
+= rPoint
.X() - nLeft
;
645 if (!IsHeightEmpty())
646 nBottom
+= rPoint
.Y() - nTop
;
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 Move(rPt
.X(), rPt
.Y());
685 inline tools::Rectangle
& tools::Rectangle::operator -= ( const Point
& rPt
)
687 Move(-rPt
.X(), -rPt
.Y());
693 inline Rectangle
operator + ( const Rectangle
& rRect
, const Point
& rPt
)
695 return Rectangle
{ rRect
}.operator+=(rPt
);
698 inline Rectangle
operator - ( const Rectangle
& rRect
, const Point
& rPt
)
700 return Rectangle
{ rRect
}.operator-=(rPt
);
708 constexpr tools::Rectangle
convert(const tools::Rectangle
& rRectangle
, o3tl::Length eFrom
, o3tl::Length eTo
)
710 return tools::Rectangle(o3tl::convert(rRectangle
.TopLeft(), eFrom
, eTo
),
711 o3tl::convert(rRectangle
.GetSize(), eFrom
, eTo
));
718 template< typename charT
, typename traits
>
719 inline std::basic_ostream
<charT
, traits
> & operator <<(
720 std::basic_ostream
<charT
, traits
> & stream
, const tools::Rectangle
& rectangle
)
722 if (rectangle
.IsEmpty())
723 return stream
<< "EMPTY";
725 return stream
<< rectangle
.GetWidth() << 'x' << rectangle
.GetHeight()
726 << "@(" << rectangle
.getX() << ',' << rectangle
.getY() << ")";
732 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */