aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/unit/testGeometry.cxx
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2021-09-15 09:36:45 +1000
committerNeil <nyamatongwe@gmail.com>2021-09-15 09:36:45 +1000
commitd4a5d7d6955982496ba523a439fc98276a28e2d8 (patch)
treef9cd5e2a57e247dc59f47404cfea8469cc74b35c /test/unit/testGeometry.cxx
parentda71ace9e135d3494fafa7d67483ff1c217faa04 (diff)
downloadscintilla-mirror-d4a5d7d6955982496ba523a439fc98276a28e2d8.tar.gz
Move colour mixing implementations into implementation file.
Avoids some warnings but drops constexpr. Use MixedWith in PlatWin for GDI instead of local implementation. Add unit tests for Geometry.
Diffstat (limited to 'test/unit/testGeometry.cxx')
-rw-r--r--test/unit/testGeometry.cxx233
1 files changed, 233 insertions, 0 deletions
diff --git a/test/unit/testGeometry.cxx b/test/unit/testGeometry.cxx
new file mode 100644
index 000000000..1dca8903c
--- /dev/null
+++ b/test/unit/testGeometry.cxx
@@ -0,0 +1,233 @@
+/** @file testDocument.cxx
+ ** Unit Tests for Scintilla internal data structures
+ **/
+
+#include <cstdint>
+
+#include "Geometry.h"
+
+#include "catch.hpp"
+
+using namespace Scintilla;
+using namespace Scintilla::Internal;
+
+// Test Geometry.
+
+TEST_CASE("Point") {
+
+ SECTION("Point") {
+ constexpr Point pt(1.0, 2.0);
+ REQUIRE(pt.x == 1.0);
+ REQUIRE(pt.y == 2.0);
+
+ constexpr Point pti = Point::FromInts(1, 2);
+ REQUIRE(pt == pti);
+
+ constexpr Point pt2 = pt + pt;
+ REQUIRE(pt != pt2);
+
+ constexpr Point ptBack = pt2 - pt;
+ REQUIRE(pt == ptBack);
+ }
+
+}
+
+TEST_CASE("Interval") {
+
+ SECTION("Interval") {
+ constexpr Interval interval { 1.0, 2.0 };
+ REQUIRE(interval.left == 1.0);
+ REQUIRE(interval.right == 2.0);
+ REQUIRE(interval.Width() == 1.0);
+ REQUIRE(!interval.Empty());
+
+ constexpr Interval empty { 4.0, 4.0 };
+ REQUIRE(empty.Empty());
+ REQUIRE(empty.Width() == 0.0);
+ REQUIRE(!(interval == empty));
+ REQUIRE(!(interval.Intersects(empty)));
+
+ constexpr Interval inside { 1.7, 1.8 };
+ REQUIRE(interval.Intersects(inside));
+ constexpr Interval straddles { 1.7, 2.8 };
+ REQUIRE(interval.Intersects(straddles));
+ }
+
+ SECTION("Interval") {
+ constexpr Interval interval1{ 1.0, 3.0 };
+ constexpr Interval interval2{ 2.0, 4.0 };
+ REQUIRE(Intersection(interval1, interval2) == Interval{ 2.0, 3.0 });
+ }
+}
+
+TEST_CASE("PRectangle") {
+
+ SECTION("PRectangle") {
+ constexpr PRectangle rc(1.0, 2.0, 3.0, 4.0);
+ REQUIRE(rc.left == 1.0);
+ REQUIRE(rc.top == 2.0);
+ REQUIRE(rc.right == 3.0);
+ REQUIRE(rc.bottom == 4.0);
+ REQUIRE(rc.Width() == 2.0);
+ REQUIRE(rc.Height() == 2.0);
+ REQUIRE(!rc.Empty());
+
+ constexpr PRectangle rci = PRectangle::FromInts(1, 2, 3, 4);
+ REQUIRE(rc == rci);
+
+ constexpr PRectangle rcEmpty;
+ REQUIRE(rcEmpty.Empty());
+ }
+
+ SECTION("Contains") {
+ constexpr PRectangle rc(1.0, 2.0, 3.0, 4.0);
+ constexpr Point pt(1.5, 2.5);
+ REQUIRE(rc.Contains(pt));
+ REQUIRE(rc.ContainsWholePixel(pt));
+ constexpr Point ptNearEdge(2.9, 2.5);
+ REQUIRE(rc.Contains(ptNearEdge));
+ REQUIRE(!rc.ContainsWholePixel(ptNearEdge));
+ constexpr Point ptOutside(1.5, 20.5);
+ REQUIRE(!rc.Contains(ptOutside));
+ REQUIRE(!rc.ContainsWholePixel(ptOutside));
+
+ constexpr PRectangle rcInside(1.5, 2.0, 2.5, 4.0);
+ REQUIRE(rc.Contains(rcInside));
+ REQUIRE(rc.Intersects(rcInside));
+
+ constexpr PRectangle rcIntersects(1.5, 2.0, 3.5, 4.0);
+ REQUIRE(!rc.Contains(rcIntersects));
+ REQUIRE(rc.Intersects(rcIntersects));
+
+ constexpr PRectangle rcSeparate(11.0, 12.0, 13.0, 14.0);
+ REQUIRE(!rc.Contains(rcSeparate));
+ REQUIRE(!rc.Intersects(rcSeparate));
+
+ constexpr Point ptCentre = rc.Centre();
+ REQUIRE(ptCentre == Point(2.0, 3.0));
+ }
+
+ SECTION("Move") {
+ PRectangle rc(1.0, 2.0, 3.0, 4.0);
+ rc.Move(1.0, 10.0);
+ REQUIRE(rc == PRectangle(2.0, 12.0, 4.0, 14.0));
+ }
+
+ SECTION("Inset") {
+ constexpr PRectangle rc(1.0, 2.0, 3.0, 4.0);
+ constexpr PRectangle rcInset = rc.Inset(0.5);
+ REQUIRE(rcInset == PRectangle(1.5, 2.5, 2.5, 3.5));
+
+ constexpr PRectangle rcInsetPt = rc.Inset(Point(0.25, 0.5));
+ REQUIRE(rcInsetPt == PRectangle(1.25, 2.5, 2.75, 3.5));
+ }
+
+ SECTION("Clamp") {
+ constexpr PRectangle rc(1.0, 2.0, 3.0, 4.0);
+
+ const PRectangle cutBottom = Clamp(rc, Edge::bottom, 3.5);
+ REQUIRE(cutBottom == PRectangle(1.0, 2.0, 3.0, 3.5));
+
+ const PRectangle justBottom = Side(rc, Edge::bottom, 0.5);
+ REQUIRE(justBottom == PRectangle(1.0, 3.5, 3.0, 4.0));
+
+ constexpr PRectangle rcInset = rc.Inset(0.5);
+ REQUIRE(rcInset == PRectangle(1.5, 2.5, 2.5, 3.5));
+
+ constexpr PRectangle rcInsetPt = rc.Inset(Point(0.25, 0.5));
+ REQUIRE(rcInsetPt == PRectangle(1.25, 2.5, 2.75, 3.5));
+
+ const Interval bounds = HorizontalBounds(rcInsetPt);
+ REQUIRE(bounds == Interval{ 1.25, 2.75 });
+
+ const PRectangle applyBounds = Intersection(rc, bounds);
+ REQUIRE(applyBounds == PRectangle(1.25, 2.0, 2.75, 4.0));
+ }
+
+ SECTION("PixelAlign") {
+ // Whole pixels
+ REQUIRE(PixelAlign(1.0, 1) == 1.0);
+ REQUIRE(PixelAlignFloor(1.0, 1) == 1.0);
+
+ REQUIRE(PixelAlign(1.25, 1) == 1.0);
+ REQUIRE(PixelAlignFloor(1.25, 1) == 1.0);
+
+ REQUIRE(PixelAlign(1.5, 1) == 2.0);
+ REQUIRE(PixelAlignFloor(1.5, 1) == 1.0);
+
+ REQUIRE(PixelAlign(1.75, 1) == 2.0);
+ REQUIRE(PixelAlignFloor(1.75, 1) == 1.0);
+
+ // Half pixels
+ REQUIRE(PixelAlign(1.0, 2) == 1.0);
+ REQUIRE(PixelAlignFloor(1.0, 2) == 1.0);
+
+ REQUIRE(PixelAlign(1.25, 2) == 1.5);
+ REQUIRE(PixelAlignFloor(1.25, 2) == 1.0);
+
+ REQUIRE(PixelAlign(1.5, 2) == 1.5);
+ REQUIRE(PixelAlignFloor(1.5, 2) == 1.5);
+
+ REQUIRE(PixelAlign(1.75, 2) == 2.0);
+ REQUIRE(PixelAlignFloor(1.75, 2) == 1.5);
+
+ REQUIRE(PixelAlign(Point(1.75, 1.25), 2) == Point(2.0, 1.5));
+ REQUIRE(PixelAlign(Point(1.5, 1.0), 2) == Point(1.5, 1.0));
+
+ // x->round, y->floored
+ REQUIRE(PixelAlign(PRectangle(1.0, 1.25, 1.5, 1.75), 2) == PRectangle(1.0, 1.0, 1.5, 1.5));
+
+ // x->outside(floor left, ceil right), y->floored
+ REQUIRE(PixelAlignOutside(PRectangle(1.1, 1.25, 1.6, 1.75), 2) == PRectangle(1.0, 1.0, 2.0, 1.5));
+ }
+
+}
+
+TEST_CASE("ColourRGBA") {
+
+ SECTION("ColourRGBA") {
+ constexpr ColourRGBA colour(0x10203040);
+ constexpr ColourRGBA colourFromRGB(0x40, 0x30, 0x20, 0x10);
+
+ REQUIRE(colour == colourFromRGB);
+ REQUIRE(colour.GetRed() == 0x40);
+ REQUIRE(colour.GetGreen() == 0x30);
+ REQUIRE(colour.GetBlue() == 0x20);
+ REQUIRE(colour.GetAlpha() == 0x10);
+ REQUIRE(!colour.IsOpaque());
+ REQUIRE(colour.AsInteger() == 0x10203040);
+
+ REQUIRE(ColourRGBA(colour, 0x80) == ColourRGBA(0x40, 0x30, 0x20, 0x80));
+ REQUIRE(ColourRGBA::FromRGB(0x203040) == ColourRGBA(0x40, 0x30, 0x20, 0xff));
+ REQUIRE(ColourRGBA::FromIpRGB(0x203040) == ColourRGBA(0x40, 0x30, 0x20, 0xff));
+
+ constexpr ColourRGBA colour01(0x00ff00ff);
+ REQUIRE(colour01.GetRedComponent() == 1.0);
+ REQUIRE(colour01.GetGreenComponent() == 0.0);
+ REQUIRE(colour01.GetBlueComponent() == 1.0);
+ REQUIRE(colour01.GetAlphaComponent() == 0.0);
+
+ // Opaque colours
+ constexpr ColourRGBA colourRGB(0xff203040);
+ REQUIRE(colourRGB.IsOpaque());
+ constexpr ColourRGBA colourOpaque(0x40, 0x30, 0x20, 0xff);
+ REQUIRE(colourRGB == colourOpaque);
+
+ REQUIRE(colourRGB.OpaqueRGB() == 0x203040);
+ REQUIRE(colourRGB.WithoutAlpha() == ColourRGBA(0x40, 0x30, 0x20, 0));
+ }
+
+ SECTION("Mixing") {
+ constexpr ColourRGBA colourMin(0x10, 0x20, 0x30, 0x40);
+ constexpr ColourRGBA colourMax(0x30, 0x60, 0x90, 0xC0);
+
+ constexpr ColourRGBA colourMid(0x20, 0x40, 0x60, 0x80);
+ REQUIRE(colourMin.MixedWith(colourMax) == colourMid);
+ REQUIRE(colourMin.MixedWith(colourMax, 0.5) == colourMid);
+
+ // 3/4 between min and max
+ constexpr ColourRGBA colour75(0x28, 0x50, 0x78, 0xA0);
+ REQUIRE(colourMin.MixedWith(colourMax, 0.75) == colour75);
+ }
+
+}