1 // Scintilla source code edit control
3 ** Classes and functions for geometric and colour calculations.
5 // Copyright 2020 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
11 namespace Scintilla::Internal
{
13 typedef double XYPOSITION
;
14 typedef double XYACCUMULATOR
;
17 * A geometric point class.
18 * Point is similar to the Win32 POINT and GTK+ GdkPoint types.
25 constexpr explicit Point(XYPOSITION x_
=0, XYPOSITION y_
=0) noexcept
: x(x_
), y(y_
) {
28 static constexpr Point
FromInts(int x_
, int y_
) noexcept
{
29 return Point(static_cast<XYPOSITION
>(x_
), static_cast<XYPOSITION
>(y_
));
32 constexpr bool operator==(Point other
) const noexcept
{
33 return (x
== other
.x
) && (y
== other
.y
);
36 constexpr bool operator!=(Point other
) const noexcept
{
37 return (x
!= other
.x
) || (y
!= other
.y
);
40 constexpr Point
operator+(Point other
) const noexcept
{
41 return Point(x
+ other
.x
, y
+ other
.y
);
44 constexpr Point
operator-(Point other
) const noexcept
{
45 return Point(x
- other
.x
, y
- other
.y
);
48 // Other automatically defined methods (assignment, copy constructor, destructor) are fine
53 * A geometric interval class.
59 constexpr bool operator==(const Interval
&other
) const noexcept
{
60 return (left
== other
.left
) && (right
== other
.right
);
62 constexpr XYPOSITION
Width() const noexcept
{ return right
- left
; }
63 constexpr bool Empty() const noexcept
{
66 constexpr bool Intersects(Interval other
) const noexcept
{
67 return (right
> other
.left
) && (left
< other
.right
);
72 * A geometric rectangle class.
73 * PRectangle is similar to Win32 RECT.
74 * PRectangles contain their top and left sides, but not their right and bottom sides.
83 constexpr explicit PRectangle(XYPOSITION left_
=0, XYPOSITION top_
=0, XYPOSITION right_
=0, XYPOSITION bottom_
= 0) noexcept
:
84 left(left_
), top(top_
), right(right_
), bottom(bottom_
) {
87 static constexpr PRectangle
FromInts(int left_
, int top_
, int right_
, int bottom_
) noexcept
{
88 return PRectangle(static_cast<XYPOSITION
>(left_
), static_cast<XYPOSITION
>(top_
),
89 static_cast<XYPOSITION
>(right_
), static_cast<XYPOSITION
>(bottom_
));
92 // Other automatically defined methods (assignment, copy constructor, destructor) are fine
94 constexpr bool operator==(const PRectangle
&rc
) const noexcept
{
95 return (rc
.left
== left
) && (rc
.right
== right
) &&
96 (rc
.top
== top
) && (rc
.bottom
== bottom
);
98 constexpr bool Contains(Point pt
) const noexcept
{
99 return (pt
.x
>= left
) && (pt
.x
<= right
) &&
100 (pt
.y
>= top
) && (pt
.y
<= bottom
);
102 constexpr bool ContainsWholePixel(Point pt
) const noexcept
{
103 // Does the rectangle contain all of the pixel to left/below the point
104 return (pt
.x
>= left
) && ((pt
.x
+1) <= right
) &&
105 (pt
.y
>= top
) && ((pt
.y
+1) <= bottom
);
107 constexpr bool Contains(PRectangle rc
) const noexcept
{
108 return (rc
.left
>= left
) && (rc
.right
<= right
) &&
109 (rc
.top
>= top
) && (rc
.bottom
<= bottom
);
111 constexpr bool Intersects(PRectangle other
) const noexcept
{
112 return (right
> other
.left
) && (left
< other
.right
) &&
113 (bottom
> other
.top
) && (top
< other
.bottom
);
115 void Move(XYPOSITION xDelta
, XYPOSITION yDelta
) noexcept
{
122 constexpr PRectangle
Inset(XYPOSITION delta
) const noexcept
{
123 return PRectangle(left
+ delta
, top
+ delta
, right
- delta
, bottom
- delta
);
126 constexpr PRectangle
Inset(Point delta
) const noexcept
{
127 return PRectangle(left
+ delta
.x
, top
+ delta
.y
, right
- delta
.x
, bottom
- delta
.y
);
130 constexpr Point
Centre() const noexcept
{
131 return Point((left
+ right
) / 2, (top
+ bottom
) / 2);
134 constexpr XYPOSITION
Width() const noexcept
{ return right
- left
; }
135 constexpr XYPOSITION
Height() const noexcept
{ return bottom
- top
; }
136 constexpr bool Empty() const noexcept
{
137 return (Height() <= 0) || (Width() <= 0);
141 enum class Edge
{ left
, top
, bottom
, right
};
143 PRectangle
Clamp(PRectangle rc
, Edge edge
, XYPOSITION position
) noexcept
;
144 PRectangle
Side(PRectangle rc
, Edge edge
, XYPOSITION size
) noexcept
;
146 Interval
Intersection(Interval a
, Interval b
) noexcept
;
147 PRectangle
Intersection(PRectangle rc
, Interval horizontalBounds
) noexcept
;
148 Interval
HorizontalBounds(PRectangle rc
) noexcept
;
150 XYPOSITION
PixelAlign(XYPOSITION xy
, int pixelDivisions
) noexcept
;
151 XYPOSITION
PixelAlignFloor(XYPOSITION xy
, int pixelDivisions
) noexcept
;
153 Point
PixelAlign(const Point
&pt
, int pixelDivisions
) noexcept
;
155 PRectangle
PixelAlign(const PRectangle
&rc
, int pixelDivisions
) noexcept
;
156 PRectangle
PixelAlignOutside(const PRectangle
&rc
, int pixelDivisions
) noexcept
;
159 * Holds an RGBA colour with 8 bits for each component.
161 constexpr const float componentMaximum
= 255.0f
;
165 constexpr explicit ColourRGBA(int co_
= 0) noexcept
: co(co_
) {
168 constexpr ColourRGBA(unsigned int red
, unsigned int green
, unsigned int blue
, unsigned int alpha
=0xff) noexcept
:
169 ColourRGBA(red
| (green
<< 8) | (blue
<< 16) | (alpha
<< 24)) {
172 constexpr ColourRGBA(ColourRGBA cd
, unsigned int alpha
) noexcept
:
173 ColourRGBA(cd
.OpaqueRGB() | (alpha
<< 24)) {
176 static constexpr ColourRGBA
FromRGB(int co_
) noexcept
{
177 return ColourRGBA(co_
| (0xffu
<< 24));
180 static constexpr ColourRGBA
FromIpRGB(intptr_t co_
) noexcept
{
181 return ColourRGBA(static_cast<int>(co_
) | (0xffu
<< 24));
184 constexpr ColourRGBA
WithoutAlpha() const noexcept
{
185 return ColourRGBA(co
& 0xffffff);
188 constexpr ColourRGBA
Opaque() const noexcept
{
189 return ColourRGBA(co
| (0xffu
<< 24));
192 constexpr int AsInteger() const noexcept
{
196 constexpr int OpaqueRGB() const noexcept
{
197 return co
& 0xffffff;
200 // Red, green and blue values as bytes 0..255
201 constexpr unsigned char GetRed() const noexcept
{
204 constexpr unsigned char GetGreen() const noexcept
{
205 return (co
>> 8) & 0xff;
207 constexpr unsigned char GetBlue() const noexcept
{
208 return (co
>> 16) & 0xff;
210 constexpr unsigned char GetAlpha() const noexcept
{
211 return (co
>> 24) & 0xff;
214 // Red, green, blue, and alpha values as float 0..1.0
215 constexpr float GetRedComponent() const noexcept
{
216 return GetRed() / componentMaximum
;
218 constexpr float GetGreenComponent() const noexcept
{
219 return GetGreen() / componentMaximum
;
221 constexpr float GetBlueComponent() const noexcept
{
222 return GetBlue() / componentMaximum
;
224 constexpr float GetAlphaComponent() const noexcept
{
225 return GetAlpha() / componentMaximum
;
228 constexpr bool operator==(const ColourRGBA
&other
) const noexcept
{
229 return co
== other
.co
;
232 constexpr bool IsOpaque() const noexcept
{
233 return GetAlpha() == 0xff;
236 ColourRGBA
MixedWith(ColourRGBA other
) const noexcept
;
237 ColourRGBA
MixedWith(ColourRGBA other
, double proportion
) const noexcept
;
241 * Holds an RGBA colour and stroke width to stroke a shape.
247 constexpr Stroke(ColourRGBA colour_
, XYPOSITION width_
=1.0) noexcept
:
248 colour(colour_
), width(width_
) {
250 constexpr float WidthF() const noexcept
{
251 return static_cast<float>(width
);
256 * Holds an RGBA colour to fill a shape.
261 constexpr Fill(ColourRGBA colour_
) noexcept
:
267 * Holds a pair of RGBA colours and stroke width to fill and stroke a shape.
273 constexpr FillStroke(ColourRGBA colourFill_
, ColourRGBA colourStroke_
, XYPOSITION widthStroke_
=1.0) noexcept
:
274 fill(colourFill_
), stroke(colourStroke_
, widthStroke_
) {
276 constexpr FillStroke(ColourRGBA colourBoth
, XYPOSITION widthStroke_
=1.0) noexcept
:
277 fill(colourBoth
), stroke(colourBoth
, widthStroke_
) {
282 * Holds an element of a gradient with an RGBA colour and a relative position.
288 constexpr ColourStop(XYPOSITION position_
, ColourRGBA colour_
) noexcept
:
289 position(position_
), colour(colour_
) {