Skip to content

Commit

Permalink
Floor outwards when converting to SKRectI (#2568)
Browse files Browse the repository at this point in the history
Truncation will chop off parts, and this will lose value. Flooring outwards ensure that the size touches the edge of the containing rect. This is useful that any partial overhang with integer sizes can be clipped when drawing.
  • Loading branch information
mattleibow authored Aug 20, 2023
1 parent 38af546 commit 8fd4dc5
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 45 deletions.
4 changes: 2 additions & 2 deletions binding/SkiaSharp/MathTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -567,10 +567,10 @@ public readonly SKRectI Standardized {
}

public readonly SKRectI AspectFit (SKSizeI size) =>
Truncate (((SKRect)this).AspectFit (size));
Floor (((SKRect)this).AspectFit (size));

public readonly SKRectI AspectFill (SKSizeI size) =>
Truncate (((SKRect)this).AspectFill (size));
Floor (((SKRect)this).AspectFill (size));

public static SKRectI Ceiling (SKRect value) =>
Ceiling (value, false);
Expand Down
114 changes: 71 additions & 43 deletions tests/Tests/SkiaSharp/SKBasicTypesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

namespace SkiaSharp.Tests
{
public class SKBasicTypesTest : SKTest
public class SKImageInfoTest : SKTest
{
[SkippableFact]
public void ImageInfoMethodsDoNotModifySource()
public void MethodsDoNotModifySource()
{
var info = new SKImageInfo(100, 30, SKColorType.Rgb565, SKAlphaType.Unpremul);

Expand All @@ -19,9 +19,12 @@ public void ImageInfoMethodsDoNotModifySource()
Assert.Equal(SKColorType.Rgb565, info.ColorType);
Assert.Equal(SKColorType.Gray8, copy.ColorType);
}
}

public class SKRectTest : SKTest
{
[SkippableFact]
public void RectangleHasCorrectProperties()
public void HasCorrectProperties()
{
var rect = new SKRect(15, 25, 55, 75);

Expand All @@ -38,7 +41,7 @@ public void RectangleHasCorrectProperties()
}

[SkippableFact]
public void RectangleOffsetsCorrectly()
public void OffsetsCorrectly()
{
var expected = new SKRect(25, 30, 65, 80);

Expand All @@ -53,7 +56,7 @@ public void RectangleOffsetsCorrectly()
}

[SkippableFact]
public void RectangleInflatesCorrectly()
public void InflatesCorrectly()
{
var rect = new SKRect(15, 25, 55, 75);

Expand All @@ -71,7 +74,7 @@ public void RectangleInflatesCorrectly()
}

[SkippableFact]
public void RectangleStandardizeCorrectly()
public void StandardizeCorrectly()
{
var rect = new SKRect(5, 5, 15, 15);
Assert.Equal(10, rect.Width);
Expand All @@ -95,48 +98,73 @@ public void RectangleStandardizeCorrectly()
Assert.Equal(rect, negWH.Standardized);
}

[SkippableFact]
public void RectangleAspectFitIsCorrect()
[SkippableTheory]
[InlineData(/*frame:*/ 5, 5, 20, 20, /*size:*/ 5, 10, /*result:*/ 5 + 5, 5 + 0, 10, 20)] // tall image in a square frame
[InlineData(/*frame:*/ 5, 5, 20, 20, /*size:*/ 10, 5, /*result:*/ 5 + 0, 5 + 5, 20, 10)] // wide image in a square frame
public void AspectFitIsCorrect(float rX, float rY, float rW, float rH, float sW, float sH, float eX, float eY, float eW, float eH)
{
var bigRect = SKRect.Create(5, 5, 20, 20);
var tallSize = new SKSize(5, 10);
var wideSize = new SKSize(10, 5);

var fitTall = bigRect.AspectFit(tallSize);
Assert.Equal(5 + 5, fitTall.Left);
Assert.Equal(5 + 0, fitTall.Top);
Assert.Equal(10, fitTall.Width);
Assert.Equal(20, fitTall.Height);

var fitWide = bigRect.AspectFit(wideSize);
Assert.Equal(5 + 0, fitWide.Left);
Assert.Equal(5 + 5, fitWide.Top);
Assert.Equal(20, fitWide.Width);
Assert.Equal(10, fitWide.Height);
var expected = SKRect.Create(eX, eY, eW, eH);

var bigRect = SKRect.Create(rX, rY, rW, rH);
var imageSize = new SKSize(sW, sH);

var fit = bigRect.AspectFit(imageSize);

Assert.Equal(expected, fit);
}

[SkippableFact]
public void RectangleAspectFillIsCorrect()
[SkippableTheory]
[InlineData(/*frame:*/ 5, 5, 20, 20, /*size:*/ 5, 10, /*result:*/ 5 + 0, 5 - 10, 20, 40)] // tall image in a square frame
[InlineData(/*frame:*/ 5, 5, 20, 20, /*size:*/ 10, 5, /*result:*/ 5 - 10, 5 + 0, 40, 20)] // wide image in a square frame
[InlineData(/*frame:*/ 0, 0, 1024, 767, /*size:*/ 1024, 1024, /*result:*/ 0, -128.5f, 1024, 1024)] // #2562
public void AspectFillIsCorrect(float rX, float rY, float rW, float rH, float sW, float sH, float eX, float eY, float eW, float eH)
{
var expected = SKRect.Create(eX, eY, eW, eH);

var bigRect = SKRect.Create(rX, rY, rW, rH);
var imageSize = new SKSize(sW, sH);

var fit = bigRect.AspectFill(imageSize);

Assert.Equal(expected, fit);
}
}

public class SKRectITest : SKTest
{
[SkippableTheory]
[InlineData(/*frame:*/ 5, 5, 20, 20, /*size:*/ 5, 10, /*result:*/ 5 + 5, 5 + 0, 10, 20)] // tall image in a square frame
[InlineData(/*frame:*/ 5, 5, 20, 20, /*size:*/ 10, 5, /*result:*/ 5 + 0, 5 + 5, 20, 10)] // wide image in a square frame
public void AspectFitIsCorrect(int rX, int rY, int rW, int rH, int sW, int sH, int eX, int eY, int eW, int eH)
{
var expected = SKRectI.Create(eX, eY, eW, eH);

var bigRect = SKRectI.Create(rX, rY, rW, rH);
var imageSize = new SKSizeI(sW, sH);

var fit = bigRect.AspectFit(imageSize);

Assert.Equal(expected, fit);
}

[SkippableTheory]
[InlineData(/*frame:*/ 5, 5, 20, 20, /*size:*/ 5, 10, /*result:*/ 5 + 0, 5 - 10, 20, 40)] // tall image in a square frame
[InlineData(/*frame:*/ 5, 5, 20, 20, /*size:*/ 10, 5, /*result:*/ 5 - 10, 5 + 0, 40, 20)] // wide image in a square frame
[InlineData(/*frame:*/ 0, 0, 1024, 767, /*size:*/ 1024, 1024, /*result:*/ 0, -129f, 1024, 1024)] // #2562
public void AspectFillIsCorrect(int rX, int rY, int rW, int rH, int sW, int sH, int eX, int eY, int eW, int eH)
{
var bigRect = SKRect.Create(5, 5, 20, 20);
var tallSize = new SKSize(5, 10);
var wideSize = new SKSize(10, 5);

var fitTall = bigRect.AspectFill(tallSize);
Assert.Equal(5 + 0, fitTall.Left);
Assert.Equal(5 - 10, fitTall.Top);
Assert.Equal(20, fitTall.Width);
Assert.Equal(40, fitTall.Height);

var fitWide = bigRect.AspectFill(wideSize);
Assert.Equal(5 - 10, fitWide.Left);
Assert.Equal(5 + 0, fitWide.Top);
Assert.Equal(40, fitWide.Width);
Assert.Equal(20, fitWide.Height);
var expected = SKRectI.Create(eX, eY, eW, eH);

var bigRect = SKRectI.Create(rX, rY, rW, rH);
var imageSize = new SKSizeI(sW, sH);

var fit = bigRect.AspectFill(imageSize);

Assert.Equal(expected, fit);
}

[SkippableFact]
public void SKRectICeilingWorksAsExpected()
public void CeilingWorksAsExpected()
{
Assert.Equal(new SKRectI(6, 6, 21, 21), SKRectI.Ceiling(new SKRect(5.5f, 5.5f, 20.5f, 20.5f)));
Assert.Equal(new SKRectI(5, 5, 21, 21), SKRectI.Ceiling(new SKRect(5.5f, 5.5f, 20.5f, 20.5f), true));
Expand All @@ -147,7 +175,7 @@ public void SKRectICeilingWorksAsExpected()
}

[SkippableFact]
public void SKRectIFloorWorksAsExpected()
public void FloorWorksAsExpected()
{
Assert.Equal(new SKRectI(5, 5, 20, 20), SKRectI.Floor(new SKRect(5.5f, 5.5f, 20.5f, 20.5f)));
Assert.Equal(new SKRectI(6, 6, 20, 20), SKRectI.Floor(new SKRect(5.5f, 5.5f, 20.5f, 20.5f), true));
Expand All @@ -158,7 +186,7 @@ public void SKRectIFloorWorksAsExpected()
}

[SkippableFact]
public void SKRectIRoundWorksAsExpected()
public void RoundWorksAsExpected()
{
Assert.Equal(new SKRectI(6, 6, 21, 21), SKRectI.Round(new SKRect(5.51f, 5.51f, 20.51f, 20.51f)));
Assert.Equal(new SKRectI(5, 6, 20, 21), SKRectI.Round(new SKRect(5.41f, 5.61f, 20.41f, 20.61f)));
Expand Down

0 comments on commit 8fd4dc5

Please sign in to comment.