Merge pull request #3948 from techee/warning_fix2
[geany-mirror.git] / scintilla / src / Geometry.cxx
blobc6247f755916b214f3c594c28cb2c42e068b45cc
1 // Scintilla source code edit control
2 /** @file Geometry.cxx
3 ** Helper functions for geometric calculations.
4 **/
5 // Copyright 2020 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
8 #include <cstdint>
9 #include <cmath>
11 #include <algorithm>
13 #include "Geometry.h"
15 namespace {
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 {
26 switch (edge) {
27 case Edge::left:
28 return PRectangle(std::clamp(position, rc.left, rc.right), rc.top, rc.right, rc.bottom);
29 case Edge::top:
30 return PRectangle(rc.left, std::clamp(position, rc.top, rc.bottom), rc.right, rc.bottom);
31 case Edge::right:
32 return PRectangle(rc.left, rc.top, std::clamp(position, rc.left, rc.right), rc.bottom);
33 case Edge::bottom:
34 default:
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 {
40 switch (edge) {
41 case Edge::left:
42 return PRectangle(rc.left, rc.top, std::min(rc.left + size, rc.right), rc.bottom);
43 case Edge::top:
44 return PRectangle(rc.left, rc.top, rc.right, std::min(rc.top + size, rc.bottom));
45 case Edge::right:
46 return PRectangle(std::max(rc.left, rc.right - size), rc.top, rc.right, rc.bottom);
47 case Edge::bottom:
48 default:
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 {
83 return Point(
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.
94 return PRectangle(
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.
103 return PRectangle(
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 {
119 return ColourRGBA(
120 Mixed(GetRed(), other.GetRed(), proportion),
121 Mixed(GetGreen(), other.GetGreen(), proportion),
122 Mixed(GetBlue(), other.GetBlue(), proportion),
123 Mixed(GetAlpha(), other.GetAlpha(), proportion));