mirror of
				https://github.com/notepad-plus-plus/notepad-plus-plus.git
				synced 2025-10-31 19:44:06 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			247 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			247 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /** @file testGeometry.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(PixelAlignCeil(1.0, 1) == 1.0);
 | |
| 
 | |
| 		REQUIRE(PixelAlign(1.25, 1) == 1.0);
 | |
| 		REQUIRE(PixelAlignFloor(1.25, 1) == 1.0);
 | |
| 		REQUIRE(PixelAlignCeil(1.25, 1) == 2.0);
 | |
| 
 | |
| 		REQUIRE(PixelAlign(1.5, 1) == 2.0);
 | |
| 		REQUIRE(PixelAlignFloor(1.5, 1) == 1.0);
 | |
| 		REQUIRE(PixelAlignCeil(1.5, 1) == 2.0);
 | |
| 
 | |
| 		REQUIRE(PixelAlign(1.75, 1) == 2.0);
 | |
| 		REQUIRE(PixelAlignFloor(1.75, 1) == 1.0);
 | |
| 		REQUIRE(PixelAlignCeil(1.75, 1) == 2.0);
 | |
| 
 | |
| 		REQUIRE(PixelAlign(Point(1.75, 1.25), 1) == Point(2.0, 1.0));
 | |
| 		REQUIRE(PixelAlign(Point(1.5, 1.0), 1) == Point(2.0, 1.0));
 | |
| 
 | |
| 		// Half pixels
 | |
| 		REQUIRE(PixelAlign(1.0, 2) == 1.0);
 | |
| 		REQUIRE(PixelAlignFloor(1.0, 2) == 1.0);
 | |
| 		REQUIRE(PixelAlignCeil(1.0, 2) == 1.0);
 | |
| 
 | |
| 		REQUIRE(PixelAlign(1.25, 2) == 1.5);
 | |
| 		REQUIRE(PixelAlignFloor(1.25, 2) == 1.0);
 | |
| 		REQUIRE(PixelAlignCeil(1.25, 2) == 1.5);
 | |
| 
 | |
| 		REQUIRE(PixelAlign(1.5, 2) == 1.5);
 | |
| 		REQUIRE(PixelAlignFloor(1.5, 2) == 1.5);
 | |
| 		REQUIRE(PixelAlignCeil(1.5, 2) == 1.5);
 | |
| 
 | |
| 		REQUIRE(PixelAlign(1.75, 2) == 2.0);
 | |
| 		REQUIRE(PixelAlignFloor(1.75, 2) == 1.5);
 | |
| 		REQUIRE(PixelAlignCeil(1.75, 2) == 2.0);
 | |
| 
 | |
| 		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), 1) == PRectangle(1.0, 1.0, 2.0, 1.0));
 | |
| 		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), 1) == PRectangle(1.0, 1.0, 2.0, 1.0));
 | |
| 		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);
 | |
| 	}
 | |
| 
 | |
| }
 |