1 // Scintilla source code edit control
3 ** Helper functions for geometric 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.
17 constexpr unsigned int Mixed(unsigned char a
, unsigned char b
, double proportion
) noexcept
{
18 return static_cast<unsigned int>(a
+ proportion
* (b
- a
));
23 namespace Scintilla::Internal
{
25 PRectangle
Clamp(PRectangle rc
, Edge edge
, XYPOSITION position
) noexcept
{
28 return PRectangle(std::clamp(position
, rc
.left
, rc
.right
), rc
.top
, rc
.right
, rc
.bottom
);
30 return PRectangle(rc
.left
, std::clamp(position
, rc
.top
, rc
.bottom
), rc
.right
, rc
.bottom
);
32 return PRectangle(rc
.left
, rc
.top
, std::clamp(position
, rc
.left
, rc
.right
), rc
.bottom
);
35 return PRectangle(rc
.left
, rc
.top
, rc
.right
, std::clamp(position
, rc
.top
, rc
.bottom
));
39 PRectangle
Side(PRectangle rc
, Edge edge
, XYPOSITION size
) noexcept
{
42 return PRectangle(rc
.left
, rc
.top
, std::min(rc
.left
+ size
, rc
.right
), rc
.bottom
);
44 return PRectangle(rc
.left
, rc
.top
, rc
.right
, std::min(rc
.top
+ size
, rc
.bottom
));
46 return PRectangle(std::max(rc
.left
, rc
.right
- size
), rc
.top
, rc
.right
, rc
.bottom
);
49 return PRectangle(rc
.left
, std::max(rc
.top
, rc
.bottom
- size
), rc
.right
, rc
.bottom
);
53 Interval
Intersection(Interval a
, Interval b
) noexcept
{
54 const XYPOSITION leftMax
= std::max(a
.left
, b
.left
);
55 const XYPOSITION rightMin
= std::min(a
.right
, b
.right
);
56 // If the result would have a negative width. make empty instead.
57 const XYPOSITION rightResult
= (rightMin
>= leftMax
) ? rightMin
: leftMax
;
58 return { leftMax
, rightResult
};
61 PRectangle
Intersection(PRectangle rc
, Interval horizontalBounds
) noexcept
{
62 const Interval intersection
= Intersection(HorizontalBounds(rc
), horizontalBounds
);
63 return PRectangle(intersection
.left
, rc
.top
, intersection
.right
, rc
.bottom
);
66 Interval
HorizontalBounds(PRectangle rc
) noexcept
{
67 return { rc
.left
, rc
.right
};
70 XYPOSITION
PixelAlign(XYPOSITION xy
, int pixelDivisions
) noexcept
{
71 return std::round(xy
* pixelDivisions
) / pixelDivisions
;
74 XYPOSITION
PixelAlignFloor(XYPOSITION xy
, int pixelDivisions
) noexcept
{
75 return std::floor(xy
* pixelDivisions
) / pixelDivisions
;
78 XYPOSITION
PixelAlignCeil(XYPOSITION xy
, int pixelDivisions
) noexcept
{
79 return std::ceil(xy
* pixelDivisions
) / pixelDivisions
;
82 Point
PixelAlign(const Point
&pt
, int pixelDivisions
) noexcept
{
84 PixelAlign(pt
.x
, pixelDivisions
),
85 PixelAlign(pt
.y
, pixelDivisions
));
88 PRectangle
PixelAlign(const PRectangle
&rc
, int pixelDivisions
) noexcept
{
89 // Move left and right side to nearest pixel to avoid blurry visuals.
90 // The top and bottom should be integers but floor them to make sure.
91 // `pixelDivisions` is commonly 1 except for 'retina' displays where it is 2.
92 // On retina displays, the positions should be moved to the nearest device
93 // pixel which is the nearest half logical pixel.
95 PixelAlign(rc
.left
, pixelDivisions
),
96 PixelAlignFloor(rc
.top
, pixelDivisions
),
97 PixelAlign(rc
.right
, pixelDivisions
),
98 PixelAlignFloor(rc
.bottom
, pixelDivisions
));
101 PRectangle
PixelAlignOutside(const PRectangle
&rc
, int pixelDivisions
) noexcept
{
102 // Move left and right side to extremes (floor(left) ceil(right)) to avoid blurry visuals.
104 PixelAlignFloor(rc
.left
, pixelDivisions
),
105 PixelAlignFloor(rc
.top
, pixelDivisions
),
106 PixelAlignCeil(rc
.right
, pixelDivisions
),
107 PixelAlignFloor(rc
.bottom
, pixelDivisions
));
110 ColourRGBA
ColourRGBA::MixedWith(ColourRGBA other
) const noexcept
{
111 const unsigned int red
= (GetRed() + other
.GetRed()) / 2;
112 const unsigned int green
= (GetGreen() + other
.GetGreen()) / 2;
113 const unsigned int blue
= (GetBlue() + other
.GetBlue()) / 2;
114 const unsigned int alpha
= (GetAlpha() + other
.GetAlpha()) / 2;
115 return ColourRGBA(red
, green
, blue
, alpha
);
118 ColourRGBA
ColourRGBA::MixedWith(ColourRGBA other
, double proportion
) const noexcept
{
120 Mixed(GetRed(), other
.GetRed(), proportion
),
121 Mixed(GetGreen(), other
.GetGreen(), proportion
),
122 Mixed(GetBlue(), other
.GetBlue(), proportion
),
123 Mixed(GetAlpha(), other
.GetAlpha(), proportion
));