mirror of https://github.com/SixLabors/ImageSharp
68 changed files with 7494 additions and 0 deletions
@ -0,0 +1,3 @@ |
|||
[*.cs] |
|||
indent_style = space |
|||
indent_size = 4 |
|||
@ -0,0 +1,6 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<RuleSet Name="Shaper2D" ToolsVersion="14.0"> |
|||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers"> |
|||
<Rule Id="SA1413" Action="None" /> |
|||
</Rules> |
|||
</RuleSet> |
|||
@ -0,0 +1,71 @@ |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
# Visual Studio 15 |
|||
VisualStudioVersion = 15.0.26430.6 |
|||
MinimumVisualStudioVersion = 10.0.40219.1 |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{C317F1B1-D75E-4C6D-83EB-80367343E0D7}" |
|||
ProjectSection(SolutionItems) = preProject |
|||
.editorconfig = .editorconfig |
|||
appveyor.yml = appveyor.yml |
|||
build.cmd = build.cmd |
|||
README.md = README.md |
|||
EndProjectSection |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Source", "Source", "{815C0625-CD3D-440F-9F80-2D83856AB7AE}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{56801022-D71A-4FBE-BC5B-CBA08E2284EC}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{9E574A07-F879-4811-9C41-5CBDC6BAFDB7}" |
|||
ProjectSection(SolutionItems) = preProject |
|||
src\Shared\AssemblyInfo.Common.cs = src\Shared\AssemblyInfo.Common.cs |
|||
src\Shared\stylecop.json = src\Shared\stylecop.json |
|||
EndProjectSection |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{9F33164A-9EA9-4CB4-A384-A8A0A6DCA35D}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SixLabors.Primitives", "src\SixLabors.Primitives\SixLabors.Primitives.csproj", "{09E744EC-4852-4FC7-BE78-C1B399F17967}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SixLabors.Primitives.Tests", "tests\SixLabors.Primitives.Tests\SixLabors.Primitives.Tests.csproj", "{F836E8E6-B4D9-4208-8346-140C74678B91}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{09E744EC-4852-4FC7-BE78-C1B399F17967}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{09E744EC-4852-4FC7-BE78-C1B399F17967}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{09E744EC-4852-4FC7-BE78-C1B399F17967}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{09E744EC-4852-4FC7-BE78-C1B399F17967}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{F836E8E6-B4D9-4208-8346-140C74678B91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{F836E8E6-B4D9-4208-8346-140C74678B91}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{F836E8E6-B4D9-4208-8346-140C74678B91}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{F836E8E6-B4D9-4208-8346-140C74678B91}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{999EDFB3-9FE4-4E09-B669-CB02E597EC20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{999EDFB3-9FE4-4E09-B669-CB02E597EC20}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{999EDFB3-9FE4-4E09-B669-CB02E597EC20}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{999EDFB3-9FE4-4E09-B669-CB02E597EC20}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{87E262FA-57FE-4AA7-853C-9DD91E769D4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{87E262FA-57FE-4AA7-853C-9DD91E769D4B}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{87E262FA-57FE-4AA7-853C-9DD91E769D4B}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{87E262FA-57FE-4AA7-853C-9DD91E769D4B}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{32D7A12E-B392-42CE-8EFB-1B685680F5B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{32D7A12E-B392-42CE-8EFB-1B685680F5B8}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{32D7A12E-B392-42CE-8EFB-1B685680F5B8}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{32D7A12E-B392-42CE-8EFB-1B685680F5B8}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
GlobalSection(NestedProjects) = preSolution |
|||
{9E574A07-F879-4811-9C41-5CBDC6BAFDB7} = {815C0625-CD3D-440F-9F80-2D83856AB7AE} |
|||
{09E744EC-4852-4FC7-BE78-C1B399F17967} = {815C0625-CD3D-440F-9F80-2D83856AB7AE} |
|||
{F836E8E6-B4D9-4208-8346-140C74678B91} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} |
|||
{999EDFB3-9FE4-4E09-B669-CB02E597EC20} = {9F33164A-9EA9-4CB4-A384-A8A0A6DCA35D} |
|||
{87E262FA-57FE-4AA7-853C-9DD91E769D4B} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} |
|||
{32D7A12E-B392-42CE-8EFB-1B685680F5B8} = {815C0625-CD3D-440F-9F80-2D83856AB7AE} |
|||
EndGlobalSection |
|||
GlobalSection(Performance) = preSolution |
|||
HasPerformanceSessions = true |
|||
EndGlobalSection |
|||
EndGlobal |
|||
@ -0,0 +1,5 @@ |
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1200/@EntryIndexedValue">DO_NOT_SHOW</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1201/@EntryIndexedValue">DO_NOT_SHOW</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1401/@EntryIndexedValue">DO_NOT_SHOW</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1600/@EntryIndexedValue">DO_NOT_SHOW</s:String></wpf:ResourceDictionary> |
|||
@ -0,0 +1,31 @@ |
|||
version: 0.0.{build} |
|||
image: Visual Studio 2017 |
|||
|
|||
install: |
|||
- choco install gitversion.portable -pre -y |
|||
|
|||
before_build: |
|||
- cmd: dotnet --version |
|||
- ps: gitversion /l console /output buildserver |
|||
|
|||
build_script: |
|||
- cmd: build.cmd |
|||
- cmd: tests\CodeCoverage\CodeCoverage.cmd |
|||
|
|||
after_build: |
|||
- cmd: appveyor PushArtifact "artifacts\SixLabors.Primitives.%GitVersion_NuGetVersion%.nupkg" |
|||
|
|||
deploy: |
|||
- provider: NuGet |
|||
server: https://www.myget.org/F/sixlabors/api/v2/package |
|||
symbol_server: https://www.myget.org/F/sixlabors/symbols/api/v2/package |
|||
api_key: |
|||
secure: SyrSERGrjkK21TSCsHtqke5279SMxXCg2NXKjR2qaErP0khEplwxPwE8Ch5bxzyf |
|||
artifact: /.*\.nupkg/ |
|||
on: |
|||
branch: master |
|||
|
|||
# prevent the double build when a branch has an active PR |
|||
skip_branch_with_pr: true |
|||
|
|||
test: off |
|||
@ -0,0 +1,38 @@ |
|||
@echo Off |
|||
|
|||
if not "%GitVersion_NuGetVersion%" == "" ( |
|||
dotnet restore /p:packageversion=%GitVersion_NuGetVersion% |
|||
)ELSE ( |
|||
dotnet restore |
|||
) |
|||
|
|||
ECHO Building nuget packages |
|||
if not "%GitVersion_NuGetVersion%" == "" ( |
|||
dotnet build -c Release /p:packageversion=%GitVersion_NuGetVersion% |
|||
)ELSE ( |
|||
dotnet build -c Release |
|||
) |
|||
if not "%errorlevel%"=="0" goto failure |
|||
|
|||
dotnet test ./tests/SixLabors.Primitives.Tests/SixLabors.Primitives.Tests.csproj |
|||
|
|||
|
|||
if not "%GitVersion_NuGetVersion%" == "" ( |
|||
dotnet pack ./src/SixLabors.Primitives/ -c Release --output ../../artifacts --no-build /p:packageversion=%GitVersion_NuGetVersion% |
|||
)ELSE ( |
|||
dotnet pack ./src/SixLabors.Primitives/ -c Release --output ../../artifacts --no-build |
|||
) |
|||
|
|||
if not "%errorlevel%"=="0" goto failure |
|||
|
|||
:success |
|||
ECHO successfully built project |
|||
REM exit 0 |
|||
goto end |
|||
|
|||
:failure |
|||
ECHO failed to build. |
|||
REM exit -1 |
|||
goto end |
|||
|
|||
:end |
|||
@ -0,0 +1,21 @@ |
|||
codecov: |
|||
notify: |
|||
require_ci_to_pass: true |
|||
comment: off |
|||
coverage: |
|||
precision: 2 |
|||
range: |
|||
- 70.0 |
|||
- 100.0 |
|||
round: down |
|||
status: |
|||
changes: false |
|||
patch: true |
|||
project: true |
|||
parsers: |
|||
gcov: |
|||
branch_detection: |
|||
conditional: true |
|||
loop: true |
|||
macro: false |
|||
method: false |
|||
@ -0,0 +1,13 @@ |
|||
# to create a new package you create a new release/tag |
|||
# in github appveyor will build it without the -cixxx tag |
|||
# it will then be deployable cleanly to nuget.org |
|||
|
|||
branches: |
|||
master: |
|||
tag: ci |
|||
mode: ContinuousDeployment |
|||
increment: Minor |
|||
prevent-increment-of-merged-branch-version: false |
|||
track-merge-target: true |
|||
ignore: |
|||
sha: [] |
|||
@ -0,0 +1,38 @@ |
|||
// <copyright file="AssemblyInfo.Common.cs" company="Scott Williams">
|
|||
// Copyright (c) Scott Williams and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
using System.Reflection; |
|||
using System.Resources; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
// General Information about an assembly is controlled through the following
|
|||
// set of attributes. Change these attribute values to modify the information
|
|||
// associated with an assembly.
|
|||
[assembly: AssemblyDescription("A cross-platform library for processing of image files; written in C#")] |
|||
[assembly: AssemblyConfiguration("")] |
|||
[assembly: AssemblyCompany("Scott Williams")] |
|||
[assembly: AssemblyProduct("SixLabors.Shapes")] |
|||
[assembly: AssemblyCopyright("Copyright (c) Scott Williams and contributors.")] |
|||
[assembly: AssemblyTrademark("")] |
|||
[assembly: AssemblyCulture("")] |
|||
[assembly: NeutralResourcesLanguage("en")] |
|||
|
|||
// Version information for an assembly consists of the following four values:
|
|||
//
|
|||
// Major Version
|
|||
// Minor Version
|
|||
// Build Number
|
|||
// Revision
|
|||
//
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
|||
// by using the '*' as shown below:
|
|||
// [assembly: AssemblyVersion("1.0.*")]
|
|||
[assembly: AssemblyVersion("1.0.0.0")] |
|||
[assembly: AssemblyFileVersion("1.0.0.0")] |
|||
[assembly: AssemblyInformationalVersion("1.0.0.0")] |
|||
|
|||
// Ensure the internals can be tested.
|
|||
[assembly: InternalsVisibleTo("SixLabors.Shapes.Tests")] |
|||
[assembly: InternalsVisibleTo("SixLabors.Shapes.Benchmarks")] |
|||
@ -0,0 +1,9 @@ |
|||
{ |
|||
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", |
|||
"settings": { |
|||
"documentationRules": { |
|||
"companyName": "Scott Williams", |
|||
"copyrightText": "Copyright (c) Scott Williams and contributors.\nLicensed under the Apache License, Version 2.0." |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
// <copyright file="Constants.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
/// <summary>
|
|||
/// Common constants used throughout the project
|
|||
/// </summary>
|
|||
internal static class Constants |
|||
{ |
|||
/// <summary>
|
|||
/// The epsilon for comparing floating point numbers.
|
|||
/// </summary>
|
|||
public static readonly float Epsilon = 0.001f; |
|||
} |
|||
} |
|||
@ -0,0 +1,183 @@ |
|||
// <copyright file="Ellipse.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Represents an ellipse.
|
|||
/// </summary>
|
|||
public struct Ellipse : IEquatable<Ellipse> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="Ellipse"/> that has X and Y values set to zero.
|
|||
/// </summary>
|
|||
public static readonly Ellipse Empty = default(Ellipse); |
|||
|
|||
/// <summary>
|
|||
/// The center point.
|
|||
/// </summary>
|
|||
private Point center; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Ellipse"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="center">The center point.</param>
|
|||
/// <param name="radiusX">The x-radius.</param>
|
|||
/// <param name="radiusY">The y-radius.</param>
|
|||
public Ellipse(Point center, float radiusX, float radiusY) |
|||
{ |
|||
this.center = center; |
|||
this.RadiusX = radiusX; |
|||
this.RadiusY = radiusY; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the x-radius of this <see cref="Ellipse"/>.
|
|||
/// </summary>
|
|||
public float RadiusX { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the y-radius of this <see cref="Ellipse"/>.
|
|||
/// </summary>
|
|||
public float RadiusY { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="Ellipse"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Ellipse"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Ellipse"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Ellipse"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(Ellipse left, Ellipse right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Ellipse"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Ellipse"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Ellipse"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(Ellipse left, Ellipse right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the center point of the given <see cref="Ellipse"/>
|
|||
/// </summary>
|
|||
/// <param name="ellipse">The ellipse</param>
|
|||
/// <returns><see cref="Vector2"/></returns>
|
|||
public static Vector2 Center(Ellipse ellipse) |
|||
{ |
|||
return new Vector2(ellipse.center.X, ellipse.center.Y); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determines if the specfied point is contained within the rectangular region defined by
|
|||
/// this <see cref="Ellipse"/>.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-coordinate of the given point.</param>
|
|||
/// <param name="y">The y-coordinate of the given point.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
public bool Contains(int x, int y) |
|||
{ |
|||
if (this.RadiusX <= 0 || this.RadiusY <= 0) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
// TODO: SIMD?
|
|||
// This is a more general form of the circle equation
|
|||
// X^2/a^2 + Y^2/b^2 <= 1
|
|||
Point normalized = new Point(x - this.center.X, y - this.center.Y); |
|||
int nX = normalized.X; |
|||
int nY = normalized.Y; |
|||
|
|||
return ((double)(nX * nX) / (this.RadiusX * this.RadiusX)) |
|||
+ ((double)(nY * nY) / (this.RadiusY * this.RadiusY)) |
|||
<= 1.0; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.GetHashCode(this); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "Ellipse [ Empty ]"; |
|||
} |
|||
|
|||
return |
|||
$"Ellipse [ RadiusX={this.RadiusX}, RadiusY={this.RadiusX}, Centre={this.center.X},{this.center.Y} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is Ellipse) |
|||
{ |
|||
return this.Equals((Ellipse)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(Ellipse other) |
|||
{ |
|||
return this.center.Equals(other.center) |
|||
&& this.RadiusX.Equals(other.RadiusX) |
|||
&& this.RadiusY.Equals(other.RadiusY); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <param name="ellipse">
|
|||
/// The instance of <see cref="Point"/> to return the hash code for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
private int GetHashCode(Ellipse ellipse) |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = ellipse.center.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ ellipse.RadiusX.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ ellipse.RadiusY.GetHashCode(); |
|||
return hashCode; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,355 @@ |
|||
// <copyright file="LongRational.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
using System; |
|||
using System.Globalization; |
|||
using System.Text; |
|||
|
|||
/// <summary>
|
|||
/// Represents a number that can be expressed as a fraction
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This is a very simplified implementation of a rational number designed for use with metadata only.
|
|||
/// </remarks>
|
|||
internal struct LongRational : IEquatable<LongRational> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="LongRational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="numerator">
|
|||
/// The number above the line in a vulgar fraction showing how many of the parts
|
|||
/// indicated by the denominator are taken.
|
|||
/// </param>
|
|||
/// <param name="denominator">
|
|||
/// The number below the line in a vulgar fraction; a divisor.
|
|||
/// </param>
|
|||
public LongRational(long numerator, long denominator) |
|||
: this(numerator, denominator, false) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="LongRational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="numerator">
|
|||
/// The number above the line in a vulgar fraction showing how many of the parts
|
|||
/// indicated by the denominator are taken.
|
|||
/// </param>
|
|||
/// <param name="denominator">
|
|||
/// The number below the line in a vulgar fraction; a divisor.
|
|||
/// </param>
|
|||
/// <param name="simplify">
|
|||
/// Whether to attempt to simplify the fractional parts.
|
|||
/// </param>
|
|||
public LongRational(long numerator, long denominator, bool simplify) |
|||
: this() |
|||
{ |
|||
this.Numerator = numerator; |
|||
this.Denominator = denominator; |
|||
|
|||
if (simplify) |
|||
{ |
|||
this.Simplify(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="LongRational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="double"/> to create the instance from.</param>
|
|||
/// <param name="bestPrecision">Whether to use the best possible precision when parsing the value.</param>
|
|||
public LongRational(double value, bool bestPrecision) |
|||
: this() |
|||
{ |
|||
if (double.IsNaN(value)) |
|||
{ |
|||
this.Numerator = this.Denominator = 0; |
|||
return; |
|||
} |
|||
|
|||
if (double.IsPositiveInfinity(value)) |
|||
{ |
|||
this.Numerator = 1; |
|||
this.Denominator = 0; |
|||
return; |
|||
} |
|||
|
|||
if (double.IsNegativeInfinity(value)) |
|||
{ |
|||
this.Numerator = -1; |
|||
this.Denominator = 0; |
|||
return; |
|||
} |
|||
|
|||
this.Numerator = 1; |
|||
this.Denominator = 1; |
|||
|
|||
double val = Math.Abs(value); |
|||
double df = this.Numerator / (double)this.Denominator; |
|||
double epsilon = bestPrecision ? double.Epsilon : .000001; |
|||
|
|||
while (Math.Abs(df - val) > epsilon) |
|||
{ |
|||
if (df < val) |
|||
{ |
|||
this.Numerator++; |
|||
} |
|||
else |
|||
{ |
|||
this.Denominator++; |
|||
this.Numerator = (int)(val * this.Denominator); |
|||
} |
|||
|
|||
df = this.Numerator / (double)this.Denominator; |
|||
} |
|||
|
|||
if (value < 0.0) |
|||
{ |
|||
this.Numerator *= -1; |
|||
} |
|||
|
|||
this.Simplify(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the numerator of a number.
|
|||
/// </summary>
|
|||
public long Numerator |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the denominator of a number.
|
|||
/// </summary>
|
|||
public long Denominator |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this instance is indeterminate.
|
|||
/// </summary>
|
|||
public bool IsIndeterminate |
|||
{ |
|||
get |
|||
{ |
|||
if (this.Denominator != 0) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return this.Numerator == 0; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this instance is an integer (n, 1)
|
|||
/// </summary>
|
|||
public bool IsInteger => this.Denominator == 1; |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this instance is equal to negative infinity (-1, 0)
|
|||
/// </summary>
|
|||
public bool IsNegativeInfinity |
|||
{ |
|||
get |
|||
{ |
|||
if (this.Denominator != 0) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return this.Numerator == -1; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this instance is equal to positive infinity (1, 0)
|
|||
/// </summary>
|
|||
public bool IsPositiveInfinity |
|||
{ |
|||
get |
|||
{ |
|||
if (this.Denominator != 0) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return this.Numerator == 1; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this instance is equal to 0 (0, 1)
|
|||
/// </summary>
|
|||
public bool IsZero |
|||
{ |
|||
get |
|||
{ |
|||
if (this.Denominator != 1) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return this.Numerator == 0; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(LongRational other) |
|||
{ |
|||
if (this.Denominator == other.Denominator) |
|||
{ |
|||
return this.Numerator == other.Numerator; |
|||
} |
|||
|
|||
if (this.Numerator == 0 && this.Denominator == 0) |
|||
{ |
|||
return other.Numerator == 0 && other.Denominator == 0; |
|||
} |
|||
|
|||
if (other.Numerator == 0 && other.Denominator == 0) |
|||
{ |
|||
return this.Numerator == 0 && this.Denominator == 0; |
|||
} |
|||
|
|||
return (this.Numerator * other.Denominator) == (this.Denominator * other.Numerator); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.GetHashCode(this); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToString(CultureInfo.InvariantCulture); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the numeric value of this instance to its equivalent string representation using
|
|||
/// the specified culture-specific format information.
|
|||
/// </summary>
|
|||
/// <param name="provider">
|
|||
/// An object that supplies culture-specific formatting information.
|
|||
/// </param>
|
|||
/// <returns>The <see cref="string"/></returns>
|
|||
public string ToString(IFormatProvider provider) |
|||
{ |
|||
if (this.IsIndeterminate) |
|||
{ |
|||
return "[ Indeterminate ]"; |
|||
} |
|||
|
|||
if (this.IsPositiveInfinity) |
|||
{ |
|||
return "[ PositiveInfinity ]"; |
|||
} |
|||
|
|||
if (this.IsNegativeInfinity) |
|||
{ |
|||
return "[ NegativeInfinity ]"; |
|||
} |
|||
|
|||
if (this.IsZero) |
|||
{ |
|||
return "0"; |
|||
} |
|||
|
|||
if (this.IsInteger) |
|||
{ |
|||
return this.Numerator.ToString(provider); |
|||
} |
|||
|
|||
StringBuilder sb = new StringBuilder(); |
|||
sb.Append(this.Numerator.ToString(provider)); |
|||
sb.Append("/"); |
|||
sb.Append(this.Denominator.ToString(provider)); |
|||
return sb.ToString(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Finds the greatest common divisor of two <see cref="long"/> values.
|
|||
/// </summary>
|
|||
/// <param name="left">The first value</param>
|
|||
/// <param name="right">The second value</param>
|
|||
/// <returns>The <see cref="long"/></returns>
|
|||
private static long GreatestCommonDivisor(long left, long right) |
|||
{ |
|||
return right == 0 ? left : GreatestCommonDivisor(right, left % right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Simplifies the <see cref="LongRational"/>
|
|||
/// </summary>
|
|||
private void Simplify() |
|||
{ |
|||
if (this.IsIndeterminate) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (this.IsNegativeInfinity) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (this.IsPositiveInfinity) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (this.IsInteger) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (this.IsZero) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (this.Numerator == 0) |
|||
{ |
|||
this.Denominator = 0; |
|||
return; |
|||
} |
|||
|
|||
if (this.Numerator == this.Denominator) |
|||
{ |
|||
this.Numerator = 1; |
|||
this.Denominator = 1; |
|||
} |
|||
|
|||
long gcd = GreatestCommonDivisor(Math.Abs(this.Numerator), Math.Abs(this.Denominator)); |
|||
if (gcd > 1) |
|||
{ |
|||
this.Numerator = this.Numerator / gcd; |
|||
this.Denominator = this.Denominator / gcd; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <param name="rational">
|
|||
/// The instance of <see cref="LongRational"/> to return the hash code for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
private int GetHashCode(LongRational rational) |
|||
{ |
|||
return ((rational.Numerator * 397) ^ rational.Denominator).GetHashCode(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,293 @@ |
|||
// <copyright file="MathF.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
using System; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Provides single-precision floating point constants and static methods for trigonometric, logarithmic, and other common mathematical functions.
|
|||
/// </summary>
|
|||
// ReSharper disable InconsistentNaming
|
|||
internal static class MathF |
|||
{ |
|||
/// <summary>
|
|||
/// Represents the ratio of the circumference of a circle to its diameter, specified by the constant, π.
|
|||
/// </summary>
|
|||
public const float PI = (float)Math.PI; |
|||
|
|||
/// <summary>
|
|||
/// Returns the absolute value of a single-precision floating-point number.
|
|||
/// </summary>
|
|||
/// <param name="f">
|
|||
/// A number that is greater than or equal to <see cref="F:System.Single.MinValue" />, but less than or equal to <see cref="F:System.Single.MaxValue" />.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A single-precision floating-point number, x, such that 0 ≤ x ≤<see cref="F:System.Single.MaxValue" />.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Abs(float f) |
|||
{ |
|||
return Math.Abs(f); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the angle whose tangent is the quotient of two specified numbers.
|
|||
/// </summary>
|
|||
/// <param name="y">The y coordinate of a point.</param>
|
|||
/// <param name="x">The x coordinate of a point.</param>
|
|||
/// <returns>
|
|||
/// An angle, θ, measured in radians, such that -π≤θ≤π, and tan(θ) = y / x, where
|
|||
/// (x, y) is a point in the Cartesian plane. Observe the following: For (x, y) in
|
|||
/// quadrant 1, 0 < θ < π/2.For (x, y) in quadrant 2, π/2 < θ≤π.For (x, y) in quadrant
|
|||
/// 3, -π < θ < -π/2.For (x, y) in quadrant 4, -π/2 < θ < 0.For points on the boundaries
|
|||
/// of the quadrants, the return value is the following:If y is 0 and x is not negative,
|
|||
/// θ = 0.If y is 0 and x is negative, θ = π.If y is positive and x is 0, θ = π/2.If
|
|||
/// y is negative and x is 0, θ = -π/2.If y is 0 and x is 0, θ = 0. If x or y is
|
|||
/// <see cref="F:System.Single.NaN"/>, or if x and y are either <see cref="F:System.Single.PositiveInfinity"/> or
|
|||
/// <see cref="F:System.Single.NegativeInfinity"/>, the method returns <see cref="F:System.Single.NaN"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Atan2(float y, float x) |
|||
{ |
|||
return (float)Math.Atan2(y, x); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the smallest integral value that is greater than or equal to the specified single-precision floating-point number.
|
|||
/// </summary>
|
|||
/// <param name="f">A single-precision floating-point number.</param>
|
|||
/// <returns>
|
|||
/// The smallest integral value that is greater than or equal to <paramref name="f" />.
|
|||
/// If <paramref name="f" /> is equal to <see cref="F:System.Single.NaN" />, <see cref="F:System.Single.NegativeInfinity" />,
|
|||
/// or <see cref="F:System.Single.PositiveInfinity" />, that value is returned.
|
|||
/// Note that this method returns a <see cref="T:System.Single" /> instead of an integral type.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Ceiling(float f) |
|||
{ |
|||
return (float)Math.Ceiling(f); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the cosine of the specified angle.
|
|||
/// </summary>
|
|||
/// <param name="f">An angle, measured in radians.</param>
|
|||
/// <returns>
|
|||
/// The cosine of <paramref name="f"/>. If <paramref name="f"/> is equal to <see cref="F:System.Float.NaN"/>, <see cref="F:System.Float.NegativeInfinity"/>,
|
|||
/// or <see cref="F:System.Float.PositiveInfinity"/>, this method returns <see cref="F:System.Float.NaN"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Cos(float f) |
|||
{ |
|||
return (float)Math.Cos(f); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a degree (360-periodic) angle to a radian (2*Pi-periodic) angle.
|
|||
/// </summary>
|
|||
/// <param name="degree">The angle in degrees.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/> representing the degree as radians.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float DegreeToRadian(float degree) |
|||
{ |
|||
return degree * (PI / 180F); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns e raised to the specified power.
|
|||
/// </summary>
|
|||
/// <param name="f">A number specifying a power.</param>
|
|||
/// <returns>
|
|||
/// The number e raised to the power <paramref name="f" />.
|
|||
/// If <paramref name="f" /> equals <see cref="F:System.Single.NaN" /> or <see cref="F:System.Single.PositiveInfinity" />, that value is returned.
|
|||
/// If <paramref name="f" /> equals <see cref="F:System.Single.NegativeInfinity" />, 0 is returned.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Exp(float f) |
|||
{ |
|||
return (float)Math.Exp(f); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the largest integer less than or equal to the specified single-precision floating-point number.
|
|||
/// </summary>
|
|||
/// <param name="f">A single-precision floating-point number. </param>
|
|||
/// <returns>
|
|||
/// The largest integer less than or equal to <paramref name="f" />.
|
|||
/// If <paramref name="f" /> is equal to <see cref="F:System.Single.NaN" />, <see cref="F:System.Single.NegativeInfinity" />,
|
|||
/// or <see cref="F:System.Single.PositiveInfinity" />, that value is returned.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Floor(float f) |
|||
{ |
|||
return (float)Math.Floor(f); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the larger of two single-precision floating-point numbers.
|
|||
/// </summary>
|
|||
/// <param name="val1">The first of two single-precision floating-point numbers to compare. </param>
|
|||
/// <param name="val2">The second of two single-precision floating-point numbers to compare. </param>
|
|||
/// <returns>
|
|||
/// Parameter <paramref name="val1" /> or <paramref name="val2" />, whichever is larger.
|
|||
/// If <paramref name="val1" />, or <paramref name="val2" />, or both <paramref name="val1" /> and <paramref name="val2" /> are
|
|||
/// equal to <see cref="F:System.Single.NaN" />, <see cref="F:System.Single.NaN" /> is returned.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Max(float val1, float val2) |
|||
{ |
|||
return Math.Max(val1, val2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the smaller of two single-precision floating-point numbers.
|
|||
/// </summary>
|
|||
/// <param name="val1">The first of two single-precision floating-point numbers to compare. </param>
|
|||
/// <param name="val2">The second of two single-precision floating-point numbers to compare. </param>
|
|||
/// <returns>
|
|||
/// Parameter <paramref name="val1" /> or <paramref name="val2" />, whichever is smaller.
|
|||
/// If <paramref name="val1" />, <paramref name="val2" />, or both <paramref name="val1" /> and <paramref name="val2" /> are equal
|
|||
/// to <see cref="F:System.Single.NaN" />, <see cref="F:System.Single.NaN" /> is returned.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Min(float val1, float val2) |
|||
{ |
|||
return Math.Min(val1, val2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a specified number raised to the specified power.
|
|||
/// </summary>
|
|||
/// <param name="x">A single-precision floating-point number to be raised to a power. </param>
|
|||
/// <param name="y">A single-precision floating-point number that specifies a power. </param>
|
|||
/// <returns>The number <paramref name="x" /> raised to the power <paramref name="y" />.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Pow(float x, float y) |
|||
{ |
|||
return (float)Math.Pow(x, y); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a radian (2*Pi-periodic) angle to a degree (360-periodic) angle.
|
|||
/// </summary>
|
|||
/// <param name="radian">The angle in radians.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/> representing the degree as radians.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float RadianToDegree(float radian) |
|||
{ |
|||
return radian / (PI / 180F); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Rounds a single-precision floating-point value to the nearest integral value.
|
|||
/// </summary>
|
|||
/// <param name="f">A single-precision floating-point number to be rounded.</param>
|
|||
/// <returns>
|
|||
/// The integer nearest <paramref name="f" />.
|
|||
/// If the fractional component of <paramref name="f" /> is halfway between two integers, one of which is even and the other odd, then the even number is returned.
|
|||
/// Note that this method returns a <see cref="T:System.Single" /> instead of an integral type.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Round(float f) |
|||
{ |
|||
return (float)Math.Round(f); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Rounds a single-precision floating-point value to the nearest integer.
|
|||
/// A parameter specifies how to round the value if it is midway between two numbers.
|
|||
/// </summary>
|
|||
/// <param name="f">A single-precision floating-point number to be rounded. </param>
|
|||
/// <param name="mode">Specification for how to round <paramref name="f" /> if it is midway between two other numbers.</param>
|
|||
/// <returns>
|
|||
/// The integer nearest <paramref name="f" />. If <paramref name="f" /> is halfway between two integers, one of which is even
|
|||
/// and the other odd, then <paramref name="mode" /> determines which of the two is returned.
|
|||
/// Note that this method returns a <see cref="T:System.Single" /> instead of an integral type.
|
|||
/// </returns>
|
|||
/// <exception cref="T:System.ArgumentException">
|
|||
/// <paramref name="mode" /> is not a valid value of <see cref="T:System.MidpointRounding" />.</exception>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Round(float f, MidpointRounding mode) |
|||
{ |
|||
return (float)Math.Round(f, mode); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the sine of the specified angle.
|
|||
/// </summary>
|
|||
/// <param name="f">An angle, measured in radians.</param>
|
|||
/// <returns>
|
|||
/// The sine of <paramref name="f" />.
|
|||
/// If <paramref name="f" /> is equal to <see cref="F:System.Single.NaN" />, <see cref="F:System.Single.NegativeInfinity" />,
|
|||
/// or <see cref="F:System.Single.PositiveInfinity" />, this method returns <see cref="F:System.Single.NaN" />.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Sin(float f) |
|||
{ |
|||
return (float)Math.Sin(f); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the result of a normalized sine cardinal function for the given value.
|
|||
/// SinC(x) = sin(pi*x)/(pi*x).
|
|||
/// </summary>
|
|||
/// <param name="f">A single-precision floating-point number to calculate the result for.</param>
|
|||
/// <returns>
|
|||
/// The sine cardinal of <paramref name="f" />.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float SinC(float f) |
|||
{ |
|||
if (Abs(f) > Constants.Epsilon) |
|||
{ |
|||
f *= PI; |
|||
return Clean(Sin(f) / f); |
|||
} |
|||
|
|||
return 1F; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the square root of a specified number.
|
|||
/// </summary>
|
|||
/// <param name="f">The number whose square root is to be found.</param>
|
|||
/// <returns>
|
|||
/// One of the values in the following table.
|
|||
/// <paramref name="f" /> parameter Return value Zero or positive The positive square root of <paramref name="f" />.
|
|||
/// Negative <see cref="F:System.Single.NaN" />Equals <see cref="F:System.Single.NaN" />
|
|||
/// <see cref="F:System.Single.NaN" />Equals <see cref="F:System.Single.PositiveInfinity" />
|
|||
/// <see cref="F:System.Single.PositiveInfinity" />
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Sqrt(float f) |
|||
{ |
|||
return (float)Math.Sqrt(f); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Ensures that any passed float is correctly rounded to zero
|
|||
/// </summary>
|
|||
/// <param name="x">The value to clean.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>
|
|||
/// </returns>.
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static float Clean(float x) |
|||
{ |
|||
if (Abs(x) < Constants.Epsilon) |
|||
{ |
|||
return 0F; |
|||
} |
|||
|
|||
return x; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,360 @@ |
|||
// <copyright file="Matrix.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// A Matrix object for applying matrix transforms to primitives.
|
|||
/// </summary>
|
|||
public struct Matrix : IEquatable<Matrix> |
|||
{ |
|||
private Matrix3x2 backingMatrix; |
|||
|
|||
private static readonly Matrix _identity = new Matrix |
|||
{ |
|||
backingMatrix = Matrix3x2.Identity |
|||
}; |
|||
|
|||
/// <summary>
|
|||
/// Returns the multiplicative identity matrix.
|
|||
/// </summary>
|
|||
public static Matrix Identity => _identity; |
|||
|
|||
/// <summary>
|
|||
/// Returns whether the matrix is the identity matrix.
|
|||
/// </summary>
|
|||
public bool IsIdentity => this.backingMatrix.IsIdentity; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the translation component of this matrix.
|
|||
/// </summary>
|
|||
public Vector2 Translation => this.backingMatrix.Translation; |
|||
|
|||
/// <summary>
|
|||
/// Constructs a Matrix3x2 from the given components.
|
|||
/// </summary>
|
|||
public Matrix(float m11, float m12, |
|||
float m21, float m22, |
|||
float m31, float m32) |
|||
{ |
|||
this.backingMatrix = new Matrix3x2(m11, m12, m21, m22, m31, m32); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a translation matrix from the given vector.
|
|||
/// </summary>
|
|||
/// <param name="position">The translation position.</param>
|
|||
/// <returns>A translation matrix.</returns>
|
|||
public static Matrix CreateTranslation(PointF position) => Matrix3x2.CreateTranslation(position); |
|||
|
|||
/// <summary>
|
|||
/// Creates a translation matrix from the given X and Y components.
|
|||
/// </summary>
|
|||
/// <param name="xPosition">The X position.</param>
|
|||
/// <param name="yPosition">The Y position.</param>
|
|||
/// <returns>A translation matrix.</returns>
|
|||
public static Matrix CreateTranslation(float xPosition, float yPosition) => Matrix3x2.CreateTranslation(xPosition, yPosition); |
|||
|
|||
/// <summary>
|
|||
/// Creates a scale matrix from the given X and Y components.
|
|||
/// </summary>
|
|||
/// <param name="xScale">Value to scale by on the X-axis.</param>
|
|||
/// <param name="yScale">Value to scale by on the Y-axis.</param>
|
|||
/// <returns>A scaling matrix.</returns>
|
|||
public static Matrix CreateScale(float xScale, float yScale) => Matrix3x2.CreateScale(xScale, yScale); |
|||
|
|||
/// <summary>
|
|||
/// Creates a scale matrix that is offset by a given center point.
|
|||
/// </summary>
|
|||
/// <param name="xScale">Value to scale by on the X-axis.</param>
|
|||
/// <param name="yScale">Value to scale by on the Y-axis.</param>
|
|||
/// <param name="centerPoint">The center point.</param>
|
|||
/// <returns>A scaling matrix.</returns>
|
|||
public static Matrix CreateScale(float xScale, float yScale, PointF centerPoint) => Matrix3x2.CreateScale(xScale, yScale, centerPoint); |
|||
|
|||
/// <summary>
|
|||
/// Creates a scale matrix from the given vector scale.
|
|||
/// </summary>
|
|||
/// <param name="scales">The scale to use.</param>
|
|||
/// <returns>A scaling matrix.</returns>
|
|||
public static Matrix CreateScale(SizeF scales) => Matrix3x2.CreateScale(scales); |
|||
|
|||
/// <summary>
|
|||
/// Creates a scale matrix from the given vector scale with an offset from the given center point.
|
|||
/// </summary>
|
|||
/// <param name="scales">The scale to use.</param>
|
|||
/// <param name="centerPoint">The center offset.</param>
|
|||
/// <returns>A scaling matrix.</returns>
|
|||
public static Matrix CreateScale(SizeF scales, PointF centerPoint) => Matrix3x2.CreateScale(scales, centerPoint); |
|||
|
|||
/// <summary>
|
|||
/// Creates a scale matrix that scales uniformly with the given scale.
|
|||
/// </summary>
|
|||
/// <param name="scale">The uniform scale to use.</param>
|
|||
/// <returns>A scaling matrix.</returns>
|
|||
public static Matrix CreateScale(float scale) => Matrix3x2.CreateScale(scale); |
|||
|
|||
/// <summary>
|
|||
/// Creates a scale matrix that scales uniformly with the given scale with an offset from the given center.
|
|||
/// </summary>
|
|||
/// <param name="scale">The uniform scale to use.</param>
|
|||
/// <param name="centerPoint">The center offset.</param>
|
|||
/// <returns>A scaling matrix.</returns>
|
|||
public static Matrix CreateScale(float scale, PointF centerPoint) => Matrix3x2.CreateScale(scale, centerPoint); |
|||
|
|||
/// <summary>
|
|||
/// Creates a skew matrix from the given angles in radians.
|
|||
/// </summary>
|
|||
/// <param name="radiansX">The X angle, in radians.</param>
|
|||
/// <param name="radiansY">The Y angle, in radians.</param>
|
|||
/// <returns>A skew matrix.</returns>
|
|||
public static Matrix CreateSkew(float radiansX, float radiansY) => Matrix3x2.CreateSkew(radiansX, radiansY); |
|||
|
|||
/// <summary>
|
|||
/// Creates a skew matrix from the given angles in radians.
|
|||
/// </summary>
|
|||
/// <param name="degreesX">The X angle, in degrees.</param>
|
|||
/// <param name="degreesY">The Y angle, in degrees.</param>
|
|||
/// <returns>A skew matrix.</returns>
|
|||
public static Matrix CreateSkewDegrees(float degreesX, float degreesY) => Matrix3x2.CreateSkew(MathF.DegreeToRadian(degreesX), MathF.DegreeToRadian(degreesY)); |
|||
|
|||
/// <summary>
|
|||
/// Creates a skew matrix from the given angles in radians and a center point.
|
|||
/// </summary>
|
|||
/// <param name="radiansX">The X angle, in radians.</param>
|
|||
/// <param name="radiansY">The Y angle, in radians.</param>
|
|||
/// <param name="centerPoint">The center point.</param>
|
|||
/// <returns>A skew matrix.</returns>
|
|||
public static Matrix CreateSkew(float radiansX, float radiansY, PointF centerPoint) => Matrix3x2.CreateSkew(radiansX, radiansY, centerPoint); |
|||
|
|||
/// <summary>
|
|||
/// Creates a skew matrix from the given angles in radians and a center point.
|
|||
/// </summary>
|
|||
/// <param name="degreesX">The X angle, in degrees.</param>
|
|||
/// <param name="degreesY">The Y angle, in degrees.</param>
|
|||
/// <param name="centerPoint">The center point.</param>
|
|||
/// <returns>A skew matrix.</returns>
|
|||
public static Matrix CreateSkewDegrees(float degreesX, float degreesY, PointF centerPoint) => Matrix3x2.CreateSkew(MathF.DegreeToRadian(degreesX), MathF.DegreeToRadian(degreesY), centerPoint); |
|||
|
|||
/// <summary>
|
|||
/// Creates a rotation matrix using the given rotation in radians.
|
|||
/// </summary>
|
|||
/// <param name="radians">The amount of rotation, in radians.</param>
|
|||
/// <returns>A rotation matrix.</returns>
|
|||
public static Matrix CreateRotation(float radians) => System.Numerics.Matrix3x2.CreateRotation(radians); |
|||
|
|||
/// <summary>
|
|||
/// Creates a rotation matrix using the given rotation in radians.
|
|||
/// </summary>
|
|||
/// <param name="degrees">The amount of rotation, in degrees.</param>
|
|||
/// <returns>A rotation matrix.</returns>
|
|||
public static Matrix CreateRotationDegrees(float degrees) => System.Numerics.Matrix3x2.CreateRotation(MathF.DegreeToRadian(degrees)); |
|||
|
|||
/// <summary>
|
|||
/// Creates a rotation matrix using the given rotation in radians and a center point.
|
|||
/// </summary>
|
|||
/// <param name="radians">The amount of rotation, in radians.</param>
|
|||
/// <param name="centerPoint">The center point.</param>
|
|||
/// <returns>A rotation matrix.</returns>
|
|||
public static Matrix CreateRotation(float radians, PointF centerPoint) => System.Numerics.Matrix3x2.CreateRotation(radians, centerPoint); |
|||
|
|||
/// <summary>
|
|||
/// Creates a rotation matrix using the given rotation in radians and a center point.
|
|||
/// </summary>
|
|||
/// <param name="degrees">The amount of rotation, in degrees.</param>
|
|||
/// <param name="centerPoint">The center point.</param>
|
|||
/// <returns>A rotation matrix.</returns>
|
|||
public static Matrix CreateRotationDegrees(float degrees, PointF centerPoint) => Matrix3x2.CreateRotation(MathF.DegreeToRadian(degrees), centerPoint); |
|||
|
|||
/// <summary>
|
|||
/// Calculates the determinant for this matrix.
|
|||
/// The determinant is calculated by expanding the matrix with a third column whose values are (0,0,1).
|
|||
/// </summary>
|
|||
/// <returns>The determinant.</returns>
|
|||
public float GetDeterminant() => this.backingMatrix.GetDeterminant(); |
|||
|
|||
/// <summary>
|
|||
/// Attempts to invert the given matrix. If the operation succeeds, the inverted matrix is stored in the result parameter.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The source matrix.</param>
|
|||
/// <param name="result">The output matrix.</param>
|
|||
/// <returns>True if the operation succeeded, False otherwise.</returns>
|
|||
public static bool Invert(Matrix matrix, out Matrix result) |
|||
{ |
|||
Matrix3x2 m; |
|||
var b = System.Numerics.Matrix3x2.Invert(matrix.backingMatrix, out m); |
|||
result = m; |
|||
return b; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Linearly interpolates from matrix1 to matrix2, based on the third parameter.
|
|||
/// </summary>
|
|||
/// <param name="matrix1">The first source matrix.</param>
|
|||
/// <param name="matrix2">The second source matrix.</param>
|
|||
/// <param name="amount">The relative weighting of matrix2.</param>
|
|||
/// <returns>The interpolated matrix.</returns>
|
|||
public static Matrix Lerp(Matrix matrix1, Matrix matrix2, float amount) => Matrix3x2.Lerp(matrix1.backingMatrix, matrix2.backingMatrix, amount); |
|||
|
|||
/// <summary>
|
|||
/// Negates the given matrix by multiplying all values by -1.
|
|||
/// </summary>
|
|||
/// <param name="value">The source matrix.</param>
|
|||
/// <returns>The negated matrix.</returns>
|
|||
public static Matrix Negate(Matrix value) => -value.backingMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Adds each matrix element in value1 with its corresponding element in value2.
|
|||
/// </summary>
|
|||
/// <param name="value1">The first source matrix.</param>
|
|||
/// <param name="value2">The second source matrix.</param>
|
|||
/// <returns>The matrix containing the summed values.</returns>
|
|||
public static Matrix Add(Matrix value1, Matrix value2) => value1.backingMatrix + value2.backingMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Subtracts each matrix element in value2 from its corresponding element in value1.
|
|||
/// </summary>
|
|||
/// <param name="value1">The first source matrix.</param>
|
|||
/// <param name="value2">The second source matrix.</param>
|
|||
/// <returns>The matrix containing the resulting values.</returns>
|
|||
public static Matrix Subtract(Matrix value1, Matrix value2) => value1.backingMatrix - value2.backingMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Multiplies two matrices together and returns the resulting matrix.
|
|||
/// </summary>
|
|||
/// <param name="value1">The first source matrix.</param>
|
|||
/// <param name="value2">The second source matrix.</param>
|
|||
/// <returns>The product matrix.</returns>
|
|||
public static Matrix Multiply(Matrix value1, Matrix value2) => value1.backingMatrix * value2.backingMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Scales all elements in a matrix by the given scalar factor.
|
|||
/// </summary>
|
|||
/// <param name="value1">The source matrix.</param>
|
|||
/// <param name="value2">The scaling value to use.</param>
|
|||
/// <returns>The resulting matrix.</returns>
|
|||
public static Matrix Multiply(Matrix value1, float value2) => value1.backingMatrix * value2; |
|||
|
|||
/// <summary>
|
|||
/// Negates the given matrix by multiplying all values by -1.
|
|||
/// </summary>
|
|||
/// <param name="value">The source matrix.</param>
|
|||
/// <returns>The negated matrix.</returns>
|
|||
public static Matrix operator -(Matrix value) => -value.backingMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Adds each matrix element in value1 with its corresponding element in value2.
|
|||
/// </summary>
|
|||
/// <param name="value1">The first source matrix.</param>
|
|||
/// <param name="value2">The second source matrix.</param>
|
|||
/// <returns>The matrix containing the summed values.</returns>
|
|||
public static Matrix operator +(Matrix value1, Matrix value2) => value1.backingMatrix + value2.backingMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Subtracts each matrix element in value2 from its corresponding element in value1.
|
|||
/// </summary>
|
|||
/// <param name="value1">The first source matrix.</param>
|
|||
/// <param name="value2">The second source matrix.</param>
|
|||
/// <returns>The matrix containing the resulting values.</returns>
|
|||
public static Matrix operator -(Matrix value1, Matrix value2) => value1.backingMatrix - value2.backingMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Multiplies two matrices together and returns the resulting matrix.
|
|||
/// </summary>
|
|||
/// <param name="value1">The first source matrix.</param>
|
|||
/// <param name="value2">The second source matrix.</param>
|
|||
/// <returns>The product matrix.</returns>
|
|||
public static Matrix operator *(Matrix value1, Matrix value2) => value1.backingMatrix * value2.backingMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Scales all elements in a matrix by the given scalar factor.
|
|||
/// </summary>
|
|||
/// <param name="value1">The source matrix.</param>
|
|||
/// <param name="value2">The scaling value to use.</param>
|
|||
/// <returns>The resulting matrix.</returns>
|
|||
public static Matrix operator *(Matrix value1, float value2) => value1.backingMatrix * value2; |
|||
|
|||
/// <summary>
|
|||
/// Returns a boolean indicating whether the given matrices are equal.
|
|||
/// </summary>
|
|||
/// <param name="value1">The first source matrix.</param>
|
|||
/// <param name="value2">The second source matrix.</param>
|
|||
/// <returns>True if the matrices are equal; False otherwise.</returns>
|
|||
public static bool operator ==(Matrix value1, Matrix value2) => value1.backingMatrix == value2.backingMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Returns a boolean indicating whether the given matrices are not equal.
|
|||
/// </summary>
|
|||
/// <param name="value1">The first source matrix.</param>
|
|||
/// <param name="value2">The second source matrix.</param>
|
|||
/// <returns>True if the matrices are not equal; False if they are equal.</returns>
|
|||
public static bool operator !=(Matrix value1, Matrix value2) |
|||
{ |
|||
return value1.backingMatrix != value2.backingMatrix; |
|||
|
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a boolean indicating whether the matrix is equal to the other given matrix.
|
|||
/// </summary>
|
|||
/// <param name="other">The other matrix to test equality against.</param>
|
|||
/// <returns>True if this matrix is equal to other; False otherwise.</returns>
|
|||
public bool Equals(Matrix other) |
|||
{ |
|||
return this.backingMatrix == other.backingMatrix; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a boolean indicating whether the given Object is equal to this matrix instance.
|
|||
/// </summary>
|
|||
/// <param name="obj">The Object to compare against.</param>
|
|||
/// <returns>True if the Object is equal to this matrix; False otherwise.</returns>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is Matrix) |
|||
{ |
|||
return Equals((Matrix)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a String representing this matrix instance.
|
|||
/// </summary>
|
|||
/// <returns>The string representation.</returns>
|
|||
public override string ToString() => this.backingMatrix.ToString(); |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <returns>The hash code.</returns>
|
|||
public override int GetHashCode() => this.backingMatrix.GetHashCode(); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Matrix3x2"/> with the values of the specified <see cref="Matrix"/>.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The matrix.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Matrix3x2"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator Matrix3x2(Matrix matrix) => matrix.backingMatrix; |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Matrix3x2"/> with the values of the specified <see cref="Matrix"/>.
|
|||
/// </summary>
|
|||
/// <param name="matrix">The matrix.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Matrix"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator Matrix(Matrix3x2 matrix) => new Matrix { backingMatrix = matrix }; |
|||
} |
|||
} |
|||
@ -0,0 +1,257 @@ |
|||
// <copyright file="Point.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Represents an ordered pair of integer x- and y-coordinates that defines a point in
|
|||
/// a two-dimensional plane.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
|
|||
/// as it avoids the need to create new values for modification operations.
|
|||
/// </remarks>
|
|||
public struct Point : IEquatable<Point> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="Point"/> that has X and Y values set to zero.
|
|||
/// </summary>
|
|||
public static readonly Point Empty = default(Point); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Point"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="value">The horizontal and vertical position of the point.</param>
|
|||
public Point(int value) |
|||
: this() |
|||
{ |
|||
this.X = LowInt16(value); |
|||
this.Y = HighInt16(value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Point"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The horizontal position of the point.</param>
|
|||
/// <param name="y">The vertical position of the point.</param>
|
|||
public Point(int x, int y) |
|||
: this() |
|||
{ |
|||
this.X = x; |
|||
this.Y = y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Point"/> struct from the given <see cref="Size"/>.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
public Point(Size size) |
|||
{ |
|||
this.X = size.Width; |
|||
this.Y = size.Height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the x-coordinate of this <see cref="Point"/>.
|
|||
/// </summary>
|
|||
public int X { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the y-coordinate of this <see cref="Point"/>.
|
|||
/// </summary>
|
|||
public int Y { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="Point"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="PointF"/> with the coordinates of the specified <see cref="Point"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator PointF(Point point) => new PointF(point.X, point.Y); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="Point"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator Vector2(Point point) => new Vector2(point.X, point.Y); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Size"/> with the coordinates of the specified <see cref="Point"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static explicit operator Size(Point point) => new Size(point.X, point.Y); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="Point"/> by a given <see cref="Size"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Point"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Point operator +(Point point, Size size) => Add(point, size); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="Point"/> by the negative of a given <see cref="Size"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="Point"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Point operator -(Point point, Size size) => Subtract(point, size); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Point"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Point"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Point"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(Point left, Point right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Point"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Point"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Point"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(Point left, Point right) => !left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="Point"/> by the negative of a given <see cref="Size"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="Point"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Point Add(Point point, Size size) => new Point(unchecked(point.X + size.Width), unchecked(point.Y + size.Height)); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="Point"/> by the negative of a given <see cref="Size"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="Point"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Point Subtract(Point point, Size size) => new Point(unchecked(point.X - size.Width), unchecked(point.Y - size.Height)); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="PointF"/> to a <see cref="Point"/> by performing a ceiling operation on all the coordinates.
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
/// <returns>The <see cref="Point"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Point Ceiling(PointF point) => new Point(unchecked((int)MathF.Ceiling(point.X)), unchecked((int)MathF.Ceiling(point.Y))); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="PointF"/> to a <see cref="Point"/> by performing a round operation on all the coordinates.
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
/// <returns>The <see cref="Point"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Point Round(PointF point) => new Point(unchecked((int)MathF.Round(point.X)), unchecked((int)MathF.Round(point.Y))); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="PointF"/> to a <see cref="Point"/> by performing a truncate operation on all the coordinates.
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
/// <returns>The <see cref="Point"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Point Truncate(PointF point) => new Point(unchecked((int)point.X), unchecked((int)point.Y)); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Vector2"/> to a <see cref="Point"/> by performing a round operation on all the coordinates.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector</param>
|
|||
/// <returns>The <see cref="Point"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Point Round(Vector2 vector) => new Point(unchecked((int)MathF.Round(vector.X)), unchecked((int)MathF.Round(vector.Y))); |
|||
|
|||
/// <summary>
|
|||
/// Rotates a point around the given rotation matrix.
|
|||
/// </summary>
|
|||
/// <param name="point">The point to rotate</param>
|
|||
/// <param name="rotation">Rotation matrix used</param>
|
|||
/// <returns>The rotated <see cref="Point"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Point Rotate(Point point, Matrix3x2 rotation) => Round(Vector2.Transform(new Vector2(point.X, point.Y), rotation)); |
|||
|
|||
/// <summary>
|
|||
/// Skews a point using the given skew matrix.
|
|||
/// </summary>
|
|||
/// <param name="point">The point to rotate</param>
|
|||
/// <param name="skew">Rotation matrix used</param>
|
|||
/// <returns>The rotated <see cref="Point"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Point Skew(Point point, Matrix3x2 skew) => Round(Vector2.Transform(new Vector2(point.X, point.Y), skew)); |
|||
|
|||
/// <summary>
|
|||
/// Translates this <see cref="Point"/> by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="dx">The amount to offset the x-coordinate.</param>
|
|||
/// <param name="dy">The amount to offset the y-coordinate.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Offset(int dx, int dy) |
|||
{ |
|||
unchecked |
|||
{ |
|||
this.X += dx; |
|||
this.Y += dy; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Translates this <see cref="Point"/> by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="point">The <see cref="Point"/> used offset this <see cref="Point"/>.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Offset(Point point) => this.Offset(point.X, point.Y); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => this.GetHashCode(this); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "Point [ Empty ]"; |
|||
} |
|||
|
|||
return $"Point [ X={this.X}, Y={this.Y} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj is Point && this.Equals((Point)obj); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(Point other) => this.X == other.X && this.Y == other.Y; |
|||
|
|||
private static short HighInt16(int n) => unchecked((short)((n >> 16) & 0xffff)); |
|||
|
|||
private static short LowInt16(int n) => unchecked((short)(n & 0xffff)); |
|||
|
|||
private int GetHashCode(Point point) => point.X ^ point.Y; |
|||
} |
|||
} |
|||
@ -0,0 +1,233 @@ |
|||
// <copyright file="PointF.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Represents an ordered pair of single precision floating point x- and y-coordinates that defines a point in
|
|||
/// a two-dimensional plane.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
|
|||
/// as it avoids the need to create new values for modification operations.
|
|||
/// </remarks>
|
|||
public struct PointF : IEquatable<PointF> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="PointF"/> that has X and Y values set to zero.
|
|||
/// </summary>
|
|||
public static readonly PointF Empty = default(PointF); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PointF"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The horizontal position of the point.</param>
|
|||
/// <param name="y">The vertical position of the point.</param>
|
|||
public PointF(float x, float y) |
|||
: this() |
|||
{ |
|||
this.X = x; |
|||
this.Y = y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PointF"/> struct from the given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
public PointF(SizeF size) |
|||
{ |
|||
this.X = size.Width; |
|||
this.Y = size.Height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the x-coordinate of this <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
public float X { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the y-coordinate of this <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
public float Y { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="PointF"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector2"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator PointF(Vector2 vector) => new PointF(vector.X, vector.Y); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector2"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator Vector2(PointF point) => new Vector2(point.X, point.Y); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Point"/> with the coordinates of the specified <see cref="PointF"/> by truncating each of the coordinates.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Point"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static explicit operator Point(PointF point) => Point.Truncate(point); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="PointF"/> by a given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="PointF"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF operator +(PointF point, SizeF size) => Add(point, size); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF operator -(PointF point, SizeF size) => Subtract(point, size); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="PointF"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="PointF"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="PointF"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(PointF left, PointF right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="PointF"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="PointF"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="PointF"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(PointF left, PointF right) => !left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Add(PointF point, SizeF size) => new PointF(point.X + size.Width, point.Y + size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Subtract(PointF point, SizeF size) => new PointF(point.X - size.Width, point.Y - size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Rotates a point around the given rotation matrix.
|
|||
/// </summary>
|
|||
/// <param name="point">The point to rotate</param>
|
|||
/// <param name="rotation">Rotation matrix used</param>
|
|||
/// <returns>The rotated <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Rotate(PointF point, Matrix rotation) => Vector2.Transform(new Vector2(point.X, point.Y), rotation); |
|||
|
|||
/// <summary>
|
|||
/// Skews a point using the given skew matrix.
|
|||
/// </summary>
|
|||
/// <param name="point">The point to rotate</param>
|
|||
/// <param name="skew">Rotation matrix used</param>
|
|||
/// <returns>The rotated <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Skew(PointF point, Matrix skew) => Vector2.Transform(new Vector2(point.X, point.Y), skew); |
|||
|
|||
/// <summary>
|
|||
/// Translates this <see cref="PointF"/> by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="dx">The amount to offset the x-coordinate.</param>
|
|||
/// <param name="dy">The amount to offset the y-coordinate.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Offset(float dx, float dy) |
|||
{ |
|||
this.X += dx; |
|||
this.Y += dy; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Translates this <see cref="PointF"/> by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="point">The <see cref="PointF"/> used offset this <see cref="PointF"/>.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Offset(PointF point) => this.Offset(point.X, point.Y); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => this.GetHashCode(this); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "PointF [ Empty ]"; |
|||
} |
|||
|
|||
return $"PointF [ X={this.X}, Y={this.Y} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj is PointF && this.Equals((PointF)obj); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(PointF other) => this.X.Equals(other.X) && this.Y.Equals(other.Y); |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <param name="point">
|
|||
/// The instance of <see cref="PointF"/> to return the hash code for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
private int GetHashCode(PointF point) => point.X.GetHashCode() ^ point.Y.GetHashCode(); |
|||
} |
|||
} |
|||
@ -0,0 +1,189 @@ |
|||
// <copyright file="Rational.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
using System; |
|||
using System.Globalization; |
|||
|
|||
/// <summary>
|
|||
/// Represents a number that can be expressed as a fraction.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This is a very simplified implementation of a rational number designed for use with metadata only.
|
|||
/// </remarks>
|
|||
public struct Rational : IEquatable<Rational> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="uint"/> to create the rational from.</param>
|
|||
public Rational(uint value) |
|||
: this(value, 1) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="numerator">The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken.</param>
|
|||
/// <param name="denominator">The number below the line in a vulgar fraction; a divisor.</param>
|
|||
public Rational(uint numerator, uint denominator) |
|||
: this(numerator, denominator, true) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="numerator">The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken.</param>
|
|||
/// <param name="denominator">The number below the line in a vulgar fraction; a divisor.</param>
|
|||
/// <param name="simplify">Specified if the rational should be simplified.</param>
|
|||
public Rational(uint numerator, uint denominator, bool simplify) |
|||
{ |
|||
LongRational rational = new LongRational(numerator, denominator, simplify); |
|||
|
|||
this.Numerator = (uint)rational.Numerator; |
|||
this.Denominator = (uint)rational.Denominator; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="double"/> to create the instance from.</param>
|
|||
public Rational(double value) |
|||
: this(value, false) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="double"/> to create the instance from.</param>
|
|||
/// <param name="bestPrecision">Whether to use the best possible precision when parsing the value.</param>
|
|||
public Rational(double value, bool bestPrecision) |
|||
{ |
|||
LongRational rational = new LongRational(Math.Abs(value), bestPrecision); |
|||
|
|||
this.Numerator = (uint)rational.Numerator; |
|||
this.Denominator = (uint)rational.Denominator; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the numerator of a number.
|
|||
/// </summary>
|
|||
public uint Numerator { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the denominator of a number.
|
|||
/// </summary>
|
|||
public uint Denominator { get; } |
|||
|
|||
/// <summary>
|
|||
/// Determines whether the specified <see cref="Rational"/> instances are considered equal.
|
|||
/// </summary>
|
|||
/// <param name="left">The first <see cref="Rational"/> to compare.</param>
|
|||
/// <param name="right"> The second <see cref="Rational"/> to compare.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
public static bool operator ==(Rational left, Rational right) |
|||
{ |
|||
return Rational.Equals(left, right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determines whether the specified <see cref="Rational"/> instances are not considered equal.
|
|||
/// </summary>
|
|||
/// <param name="left">The first <see cref="Rational"/> to compare.</param>
|
|||
/// <param name="right"> The second <see cref="Rational"/> to compare.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
public static bool operator !=(Rational left, Rational right) |
|||
{ |
|||
return !Rational.Equals(left, right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the specified <see cref="double"/> to an instance of this type.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="double"/> to convert to an instance of this type.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rational"/>.
|
|||
/// </returns>
|
|||
public static Rational FromDouble(double value) |
|||
{ |
|||
return new Rational(value, false); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the specified <see cref="double"/> to an instance of this type.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="double"/> to convert to an instance of this type.</param>
|
|||
/// <param name="bestPrecision">Whether to use the best possible precision when parsing the value.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rational"/>.
|
|||
/// </returns>
|
|||
public static Rational FromDouble(double value, bool bestPrecision) |
|||
{ |
|||
return new Rational(value, bestPrecision); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is Rational) |
|||
{ |
|||
return this.Equals((Rational)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(Rational other) |
|||
{ |
|||
LongRational left = new LongRational(this.Numerator, this.Denominator); |
|||
LongRational right = new LongRational(other.Numerator, other.Denominator); |
|||
|
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
LongRational self = new LongRational(this.Numerator, this.Denominator); |
|||
return self.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a rational number to the nearest <see cref="double"/>.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// The <see cref="double"/>.
|
|||
/// </returns>
|
|||
public double ToDouble() |
|||
{ |
|||
return this.Numerator / (double)this.Denominator; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToString(CultureInfo.InvariantCulture); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the numeric value of this instance to its equivalent string representation using
|
|||
/// the specified culture-specific format information.
|
|||
/// </summary>
|
|||
/// <param name="provider">
|
|||
/// An object that supplies culture-specific formatting information.
|
|||
/// </param>
|
|||
/// <returns>The <see cref="string"/></returns>
|
|||
public string ToString(IFormatProvider provider) |
|||
{ |
|||
LongRational rational = new LongRational(this.Numerator, this.Denominator); |
|||
return rational.ToString(provider); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,467 @@ |
|||
// <copyright file="Rectangle.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Stores a set of four integers that represent the location and size of a rectangle.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
|
|||
/// as it avoids the need to create new values for modification operations.
|
|||
/// </remarks>
|
|||
public struct Rectangle : IEquatable<Rectangle> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="Rectangle"/> that has X, Y, Width, and Height values set to zero.
|
|||
/// </summary>
|
|||
public static readonly Rectangle Empty = default(Rectangle); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rectangle"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The horizontal position of the rectangle.</param>
|
|||
/// <param name="y">The vertical position of the rectangle.</param>
|
|||
/// <param name="width">The width of the rectangle.</param>
|
|||
/// <param name="height">The height of the rectangle.</param>
|
|||
public Rectangle(int x, int y, int width, int height) |
|||
{ |
|||
this.X = x; |
|||
this.Y = y; |
|||
this.Width = width; |
|||
this.Height = height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rectangle"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="point">
|
|||
/// The <see cref="Point"/> which specifies the rectangles point in a two-dimensional plane.
|
|||
/// </param>
|
|||
/// <param name="size">
|
|||
/// The <see cref="Size"/> which specifies the rectangles height and width.
|
|||
/// </param>
|
|||
public Rectangle(Point point, Size size) |
|||
{ |
|||
this.X = point.X; |
|||
this.Y = point.Y; |
|||
this.Width = size.Width; |
|||
this.Height = size.Height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the x-coordinate of this <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
public int X { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the y-coordinate of this <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
public int Y { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the width of this <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
public int Width { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the height of this <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
public int Height { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the coordinates of the upper-left corner of the rectangular region represented by this <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public Point Location |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => new Point(this.X, this.Y); |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
set |
|||
{ |
|||
this.X = value.X; |
|||
this.Y = value.Y; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the size of this <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public Size Size |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => new Size(this.Width, this.Height); |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
set |
|||
{ |
|||
this.Width = value.Width; |
|||
this.Height = value.Height; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="Rectangle"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Gets the y-coordinate of the top edge of this <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
public int Top |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
return this.Y; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the x-coordinate of the right edge of this <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
public int Right |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
return unchecked(this.X + this.Width); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the y-coordinate of the bottom edge of this <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
public int Bottom |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
return unchecked(this.Y + this.Height); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the x-coordinate of the left edge of this <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
public int Left |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
return this.X; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="RectangleF"/> with the coordinates of the specified <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator RectangleF(Rectangle rectangle) => new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Vector4"/> with the coordinates of the specified <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator Vector4(Rectangle rectangle) => new Vector4(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Rectangle"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Rectangle"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Rectangle"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(Rectangle left, Rectangle right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Rectangle"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Rectangle"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Rectangle"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(Rectangle left, Rectangle right) => !left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Creates a new <see cref="Rectangle"/> with the specified location and size. </summary>
|
|||
/// <param name="left">The left coordinate of the rectangle</param>
|
|||
/// <param name="top">The top coordinate of the rectangle</param>
|
|||
/// <param name="right">The right coordinate of the rectangle</param>
|
|||
/// <param name="bottom">The bottom coordinate of the rectangle</param>
|
|||
/// <returns>The <see cref="Rectangle"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
|
|||
// ReSharper disable once InconsistentNaming
|
|||
public static Rectangle FromLTRB(int left, int top, int right, int bottom) => new Rectangle(left, top, unchecked(right - left), unchecked(bottom - top)); |
|||
|
|||
/// <summary>
|
|||
/// Returns the center point of the given <see cref="Rectangle"/>
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
/// <returns>The <see cref="Point"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Point Center(Rectangle rectangle) => new Point(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2)); |
|||
|
|||
/// <summary>
|
|||
/// Creates a rectangle that represents the intersection between <paramref name="a"/> and
|
|||
/// <paramref name="b"/>. If there is no intersection, an empty rectangle is returned.
|
|||
/// </summary>
|
|||
/// <param name="a">The first rectangle</param>
|
|||
/// <param name="b">The second rectangle</param>
|
|||
/// <returns>The <see cref="Rectangle"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Rectangle Intersect(Rectangle a, Rectangle b) |
|||
{ |
|||
int x1 = Math.Max(a.X, b.X); |
|||
int x2 = Math.Min(a.Right, b.Right); |
|||
int y1 = Math.Max(a.Y, b.Y); |
|||
int y2 = Math.Min(a.Bottom, b.Bottom); |
|||
|
|||
if (x2 >= x1 && y2 >= y1) |
|||
{ |
|||
return new Rectangle(x1, y1, x2 - x1, y2 - y1); |
|||
} |
|||
|
|||
return Empty; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Rectangle"/> that is inflated by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
/// <param name="x">The amount to inflate the width by</param>
|
|||
/// <param name="y">The amount to inflate the height by</param>
|
|||
/// <returns>A new <see cref="Rectangle"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Rectangle Inflate(Rectangle rectangle, int x, int y) |
|||
{ |
|||
Rectangle r = rectangle; |
|||
r.Inflate(x, y); |
|||
return r; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="RectangleF"/> to a <see cref="Rectangle"/> by performing a ceiling operation on all the coordinates.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
/// <returns>The <see cref="Rectangle"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Rectangle Ceiling(RectangleF rectangle) |
|||
{ |
|||
unchecked |
|||
{ |
|||
return new Rectangle( |
|||
(int)MathF.Ceiling(rectangle.X), |
|||
(int)MathF.Ceiling(rectangle.Y), |
|||
(int)MathF.Ceiling(rectangle.Width), |
|||
(int)MathF.Ceiling(rectangle.Height)); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="RectangleF"/> to a <see cref="Rectangle"/> by performing a truncate operation on all the coordinates.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
/// <returns>The <see cref="Rectangle"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Rectangle Truncate(RectangleF rectangle) |
|||
{ |
|||
unchecked |
|||
{ |
|||
return new Rectangle( |
|||
(int)rectangle.X, |
|||
(int)rectangle.Y, |
|||
(int)rectangle.Width, |
|||
(int)rectangle.Height); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="RectangleF"/> to a <see cref="Rectangle"/> by performing a round operation on all the coordinates.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
/// <returns>The <see cref="Rectangle"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Rectangle Round(RectangleF rectangle) |
|||
{ |
|||
unchecked |
|||
{ |
|||
return new Rectangle( |
|||
(int)MathF.Round(rectangle.X), |
|||
(int)MathF.Round(rectangle.Y), |
|||
(int)MathF.Round(rectangle.Width), |
|||
(int)MathF.Round(rectangle.Height)); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a rectangle that represents the union between <paramref name="a"/> and <paramref name="b"/>.
|
|||
/// </summary>
|
|||
/// <param name="a">The first rectangle</param>
|
|||
/// <param name="b">The second rectangle</param>
|
|||
/// <returns>The <see cref="Rectangle"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Rectangle Union(Rectangle a, Rectangle b) |
|||
{ |
|||
int x1 = Math.Min(a.X, b.X); |
|||
int x2 = Math.Max(a.Right, b.Right); |
|||
int y1 = Math.Min(a.Y, b.Y); |
|||
int y2 = Math.Max(a.Bottom, b.Bottom); |
|||
|
|||
return new Rectangle(x1, y1, x2 - x1, y2 - y1); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a Rectangle that represents the intersection between this Rectangle and the <paramref name="rectangle"/>.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Intersect(Rectangle rectangle) |
|||
{ |
|||
Rectangle result = Intersect(rectangle, this); |
|||
|
|||
this.X = result.X; |
|||
this.Y = result.Y; |
|||
this.Width = result.Width; |
|||
this.Height = result.Height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Inflates this <see cref="Rectangle"/> by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="width">The width</param>
|
|||
/// <param name="height">The height</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Inflate(int width, int height) |
|||
{ |
|||
unchecked |
|||
{ |
|||
this.X -= width; |
|||
this.Y -= height; |
|||
|
|||
this.Width += 2 * width; |
|||
this.Height += 2 * height; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Inflates this <see cref="Rectangle"/> by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Inflate(Size size) => this.Inflate(size.Width, size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Determines if the specfied point is contained within the rectangular region defined by
|
|||
/// this <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-coordinate of the given point.</param>
|
|||
/// <param name="y">The y-coordinate of the given point.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Contains(int x, int y) => this.X <= x && x < this.Right && this.Y <= y && y < this.Bottom; |
|||
|
|||
/// <summary>
|
|||
/// Determines if the specified point is contained within the rectangular region defined by this <see cref="Rectangle"/> .
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Contains(Point point) => this.Contains(point.X, point.Y); |
|||
|
|||
/// <summary>
|
|||
/// Determines if the rectangular region represented by <paramref name="rectangle"/> is entirely contained
|
|||
/// within the rectangular region represented by this <see cref="Rectangle"/> .
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Contains(Rectangle rectangle) => |
|||
(this.X <= rectangle.X) && (rectangle.Right <= this.Right) && |
|||
(this.Y <= rectangle.Y) && (rectangle.Bottom <= this.Bottom); |
|||
|
|||
/// <summary>
|
|||
/// Determines if the specfied <see cref="Rectangle"/> intersects the rectangular region defined by
|
|||
/// this <see cref="Rectangle"/>.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The other Rectange </param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool IntersectsWith(Rectangle rectangle) => |
|||
(rectangle.X < this.Right) && (this.X < rectangle.Right) && |
|||
(rectangle.Y < this.Bottom) && (this.Y < rectangle.Bottom); |
|||
|
|||
/// <summary>
|
|||
/// Adjusts the location of this rectangle by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Offset(Point point) => this.Offset(point.X, point.Y); |
|||
|
|||
/// <summary>
|
|||
/// Adjusts the location of this rectangle by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="dx">The amount to offset the x-coordinate.</param>
|
|||
/// <param name="dy">The amount to offset the y-coordinate.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Offset(int dx, int dy) |
|||
{ |
|||
unchecked |
|||
{ |
|||
this.X += dx; |
|||
this.Y += dy; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => this.GetHashCode(this); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "Rectangle [ Empty ]"; |
|||
} |
|||
|
|||
return $"Rectangle [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj is Rectangle && this.Equals((Rectangle)obj); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(Rectangle other) => this.X == other.X && this.Y == other.Y && this.Width == other.Width && this.Height == other.Height; |
|||
|
|||
private int GetHashCode(Rectangle rectangle) |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = rectangle.X; |
|||
hashCode = (hashCode * 397) ^ rectangle.Y; |
|||
hashCode = (hashCode * 397) ^ rectangle.Width; |
|||
hashCode = (hashCode * 397) ^ rectangle.Height; |
|||
return hashCode; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,400 @@ |
|||
// <copyright file="RectangleF.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Stores a set of four single precision floating points that represent the location and size of a rectangle.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
|
|||
/// as it avoids the need to create new values for modification operations.
|
|||
/// </remarks>
|
|||
public struct RectangleF : IEquatable<RectangleF> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="RectangleF"/> that has X, Y, Width, and Height values set to zero.
|
|||
/// </summary>
|
|||
public static readonly RectangleF Empty = default(RectangleF); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="RectangleF"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The horizontal position of the rectangle.</param>
|
|||
/// <param name="y">The vertical position of the rectangle.</param>
|
|||
/// <param name="width">The width of the rectangle.</param>
|
|||
/// <param name="height">The height of the rectangle.</param>
|
|||
public RectangleF(float x, float y, float width, float height) |
|||
{ |
|||
this.X = x; |
|||
this.Y = y; |
|||
this.Width = width; |
|||
this.Height = height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="RectangleF"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="point">
|
|||
/// The <see cref="Point"/> which specifies the rectangles point in a two-dimensional plane.
|
|||
/// </param>
|
|||
/// <param name="size">
|
|||
/// The <see cref="Size"/> which specifies the rectangles height and width.
|
|||
/// </param>
|
|||
public RectangleF(PointF point, SizeF size) |
|||
{ |
|||
this.X = point.X; |
|||
this.Y = point.Y; |
|||
this.Width = size.Width; |
|||
this.Height = size.Height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the x-coordinate of this <see cref="RectangleF"/>.
|
|||
/// </summary>
|
|||
public float X { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the y-coordinate of this <see cref="RectangleF"/>.
|
|||
/// </summary>
|
|||
public float Y { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the width of this <see cref="RectangleF"/>.
|
|||
/// </summary>
|
|||
public float Width { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the height of this <see cref="RectangleF"/>.
|
|||
/// </summary>
|
|||
public float Height { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the coordinates of the upper-left corner of the rectangular region represented by this <see cref="RectangleF"/>.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public PointF Location |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => new PointF(this.X, this.Y); |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
set |
|||
{ |
|||
this.X = value.X; |
|||
this.Y = value.Y; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the size of this <see cref="RectangleF"/>.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public SizeF Size |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get => new SizeF(this.Width, this.Height); |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
set |
|||
{ |
|||
this.Width = value.Width; |
|||
this.Height = value.Height; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="RectangleF"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => (this.Width <= 0) || (this.Height <= 0); |
|||
|
|||
/// <summary>
|
|||
/// Gets the y-coordinate of the top edge of this <see cref="RectangleF"/>.
|
|||
/// </summary>
|
|||
public float Top |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
return this.Y; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the x-coordinate of the right edge of this <see cref="RectangleF"/>.
|
|||
/// </summary>
|
|||
public float Right |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
return this.X + this.Width; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the y-coordinate of the bottom edge of this <see cref="RectangleF"/>.
|
|||
/// </summary>
|
|||
public float Bottom |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
return this.Y + this.Height; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the x-coordinate of the left edge of this <see cref="RectangleF"/>.
|
|||
/// </summary>
|
|||
public float Left |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
return this.X; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Rectangle"/> with the coordinates of the specified <see cref="RectangleF"/> by truncating each coordinate.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static explicit operator Rectangle(RectangleF rectangle) => Rectangle.Truncate(rectangle); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="RectangleF"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="RectangleF"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="RectangleF"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(RectangleF left, RectangleF right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="RectangleF"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="RectangleF"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="RectangleF"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(RectangleF left, RectangleF right) => !left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Creates a new <see cref="RectangleF"/> with the specified location and size. </summary>
|
|||
/// <param name="left">The left coordinate of the rectangle</param>
|
|||
/// <param name="top">The top coordinate of the rectangle</param>
|
|||
/// <param name="right">The right coordinate of the rectangle</param>
|
|||
/// <param name="bottom">The bottom coordinate of the rectangle</param>
|
|||
/// <returns>The <see cref="RectangleF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
|
|||
// ReSharper disable once InconsistentNaming
|
|||
public static RectangleF FromLTRB(float left, float top, float right, float bottom) => new RectangleF(left, top, right - left, bottom - top); |
|||
|
|||
/// <summary>
|
|||
/// Returns the center point of the given <see cref="RectangleF"/>
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
/// <returns>The <see cref="Point"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Center(RectangleF rectangle) => new PointF(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2)); |
|||
|
|||
/// <summary>
|
|||
/// Creates a rectangle that represents the intersection between <paramref name="a"/> and
|
|||
/// <paramref name="b"/>. If there is no intersection, an empty rectangle is returned.
|
|||
/// </summary>
|
|||
/// <param name="a">The first rectangle</param>
|
|||
/// <param name="b">The second rectangle</param>
|
|||
/// <returns>The <see cref="RectangleF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static RectangleF Intersect(RectangleF a, RectangleF b) |
|||
{ |
|||
float x1 = MathF.Max(a.X, b.X); |
|||
float x2 = MathF.Min(a.Right, b.Right); |
|||
float y1 = MathF.Max(a.Y, b.Y); |
|||
float y2 = MathF.Min(a.Bottom, b.Bottom); |
|||
|
|||
if (x2 >= x1 && y2 >= y1) |
|||
{ |
|||
return new RectangleF(x1, y1, x2 - x1, y2 - y1); |
|||
} |
|||
|
|||
return Empty; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="RectangleF"/> that is inflated by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
/// <param name="x">The amount to inflate the width by</param>
|
|||
/// <param name="y">The amount to inflate the height by</param>
|
|||
/// <returns>A new <see cref="RectangleF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static RectangleF Inflate(RectangleF rectangle, float x, float y) |
|||
{ |
|||
RectangleF r = rectangle; |
|||
r.Inflate(x, y); |
|||
return r; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a rectangle that represents the union between <paramref name="a"/> and <paramref name="b"/>.
|
|||
/// </summary>
|
|||
/// <param name="a">The first rectangle</param>
|
|||
/// <param name="b">The second rectangle</param>
|
|||
/// <returns>The <see cref="RectangleF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static RectangleF Union(RectangleF a, RectangleF b) |
|||
{ |
|||
float x1 = MathF.Min(a.X, b.X); |
|||
float x2 = MathF.Max(a.Right, b.Right); |
|||
float y1 = MathF.Min(a.Y, b.Y); |
|||
float y2 = MathF.Max(a.Bottom, b.Bottom); |
|||
|
|||
return new RectangleF(x1, y1, x2 - x1, y2 - y1); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a RectangleF that represents the intersection between this RectangleF and the <paramref name="rectangle"/>.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Intersect(RectangleF rectangle) |
|||
{ |
|||
RectangleF result = Intersect(rectangle, this); |
|||
|
|||
this.X = result.X; |
|||
this.Y = result.Y; |
|||
this.Width = result.Width; |
|||
this.Height = result.Height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Inflates this <see cref="RectangleF"/> by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="width">The width</param>
|
|||
/// <param name="height">The height</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Inflate(float width, float height) |
|||
{ |
|||
this.X -= width; |
|||
this.Y -= height; |
|||
|
|||
this.Width += 2 * width; |
|||
this.Height += 2 * height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Inflates this <see cref="RectangleF"/> by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Inflate(SizeF size) => this.Inflate(size.Width, size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Determines if the specfied point is contained within the rectangular region defined by
|
|||
/// this <see cref="RectangleF"/>.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-coordinate of the given point.</param>
|
|||
/// <param name="y">The y-coordinate of the given point.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Contains(float x, float y) => this.X <= x && x < this.Right && this.Y <= y && y < this.Bottom; |
|||
|
|||
/// <summary>
|
|||
/// Determines if the specified point is contained within the rectangular region defined by this <see cref="RectangleF"/> .
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Contains(PointF point) => this.Contains(point.X, point.Y); |
|||
|
|||
/// <summary>
|
|||
/// Determines if the rectangular region represented by <paramref name="rectangle"/> is entirely contained
|
|||
/// within the rectangular region represented by this <see cref="RectangleF"/> .
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The rectangle</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Contains(RectangleF rectangle) => |
|||
(this.X <= rectangle.X) && (rectangle.Right <= this.Right) && |
|||
(this.Y <= rectangle.Y) && (rectangle.Bottom <= this.Bottom); |
|||
|
|||
/// <summary>
|
|||
/// Determines if the specfied <see cref="RectangleF"/> intersects the rectangular region defined by
|
|||
/// this <see cref="RectangleF"/>.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The other Rectange </param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool IntersectsWith(RectangleF rectangle) => |
|||
(rectangle.X < this.Right) && (this.X < rectangle.Right) && |
|||
(rectangle.Y < this.Bottom) && (this.Y < rectangle.Bottom); |
|||
|
|||
/// <summary>
|
|||
/// Adjusts the location of this rectangle by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Offset(PointF point) => this.Offset(point.X, point.Y); |
|||
|
|||
/// <summary>
|
|||
/// Adjusts the location of this rectangle by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="dx">The amount to offset the x-coordinate.</param>
|
|||
/// <param name="dy">The amount to offset the y-coordinate.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Offset(float dx, float dy) |
|||
{ |
|||
this.X += dx; |
|||
this.Y += dy; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => this.GetHashCode(this); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "RectangleF [ Empty ]"; |
|||
} |
|||
|
|||
return $"RectangleF [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj is RectangleF && this.Equals((RectangleF)obj); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(RectangleF other) => this.X.Equals(other.X) && this.Y.Equals(other.Y) && this.Width.Equals(other.Width) && this.Height.Equals(other.Height); |
|||
|
|||
private int GetHashCode(RectangleF rectangle) |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = rectangle.X.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ rectangle.Y.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ rectangle.Width.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ rectangle.Height.GetHashCode(); |
|||
return hashCode; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,189 @@ |
|||
// <copyright file="SignedRational.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
using System; |
|||
using System.Globalization; |
|||
|
|||
/// <summary>
|
|||
/// Represents a number that can be expressed as a fraction.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This is a very simplified implementation of a rational number designed for use with metadata only.
|
|||
/// </remarks>
|
|||
public struct SignedRational : IEquatable<SignedRational> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SignedRational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="int"/> to create the rational from.</param>
|
|||
public SignedRational(int value) |
|||
: this(value, 1) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SignedRational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="numerator">The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken.</param>
|
|||
/// <param name="denominator">The number below the line in a vulgar fraction; a divisor.</param>
|
|||
public SignedRational(int numerator, int denominator) |
|||
: this(numerator, denominator, true) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SignedRational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="numerator">The number above the line in a vulgar fraction showing how many of the parts indicated by the denominator are taken.</param>
|
|||
/// <param name="denominator">The number below the line in a vulgar fraction; a divisor.</param>
|
|||
/// <param name="simplify">Specified if the rational should be simplified.</param>
|
|||
public SignedRational(int numerator, int denominator, bool simplify) |
|||
{ |
|||
LongRational rational = new LongRational(numerator, denominator, simplify); |
|||
|
|||
this.Numerator = (int)rational.Numerator; |
|||
this.Denominator = (int)rational.Denominator; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SignedRational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="double"/> to create the instance from.</param>
|
|||
public SignedRational(double value) |
|||
: this(value, false) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SignedRational"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="double"/> to create the instance from.</param>
|
|||
/// <param name="bestPrecision">Whether to use the best possible precision when parsing the value.</param>
|
|||
public SignedRational(double value, bool bestPrecision) |
|||
{ |
|||
LongRational rational = new LongRational(value, bestPrecision); |
|||
|
|||
this.Numerator = (int)rational.Numerator; |
|||
this.Denominator = (int)rational.Denominator; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the numerator of a number.
|
|||
/// </summary>
|
|||
public int Numerator { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the denominator of a number.
|
|||
/// </summary>
|
|||
public int Denominator { get; } |
|||
|
|||
/// <summary>
|
|||
/// Determines whether the specified <see cref="SignedRational"/> instances are considered equal.
|
|||
/// </summary>
|
|||
/// <param name="left">The first <see cref="SignedRational"/> to compare.</param>
|
|||
/// <param name="right"> The second <see cref="SignedRational"/> to compare.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
public static bool operator ==(SignedRational left, SignedRational right) |
|||
{ |
|||
return SignedRational.Equals(left, right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determines whether the specified <see cref="SignedRational"/> instances are not considered equal.
|
|||
/// </summary>
|
|||
/// <param name="left">The first <see cref="SignedRational"/> to compare.</param>
|
|||
/// <param name="right"> The second <see cref="SignedRational"/> to compare.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
public static bool operator !=(SignedRational left, SignedRational right) |
|||
{ |
|||
return !SignedRational.Equals(left, right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the specified <see cref="double"/> to an instance of this type.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="double"/> to convert to an instance of this type.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="SignedRational"/>.
|
|||
/// </returns>
|
|||
public static SignedRational FromDouble(double value) |
|||
{ |
|||
return new SignedRational(value, false); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the specified <see cref="double"/> to an instance of this type.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="double"/> to convert to an instance of this type.</param>
|
|||
/// <param name="bestPrecision">Whether to use the best possible precision when parsing the value.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="SignedRational"/>.
|
|||
/// </returns>
|
|||
public static SignedRational FromDouble(double value, bool bestPrecision) |
|||
{ |
|||
return new SignedRational(value, bestPrecision); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is SignedRational) |
|||
{ |
|||
return this.Equals((SignedRational)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(SignedRational other) |
|||
{ |
|||
LongRational left = new LongRational(this.Numerator, this.Denominator); |
|||
LongRational right = new LongRational(other.Numerator, other.Denominator); |
|||
|
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
LongRational self = new LongRational(this.Numerator, this.Denominator); |
|||
return self.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a rational number to the nearest <see cref="double"/>.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// The <see cref="double"/>.
|
|||
/// </returns>
|
|||
public double ToDouble() |
|||
{ |
|||
return this.Numerator / (double)this.Denominator; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToString(CultureInfo.InvariantCulture); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the numeric value of this instance to its equivalent string representation using
|
|||
/// the specified culture-specific format information.
|
|||
/// </summary>
|
|||
/// <param name="provider">
|
|||
/// An object that supplies culture-specific formatting information.
|
|||
/// </param>
|
|||
/// <returns>The <see cref="string"/></returns>
|
|||
public string ToString(IFormatProvider provider) |
|||
{ |
|||
LongRational rational = new LongRational(this.Numerator, this.Denominator); |
|||
return rational.ToString(provider); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<Description>Low level primitives for use across Six Labors projects..</Description> |
|||
<AssemblyTitle>SixLabors.Primitives</AssemblyTitle> |
|||
<VersionPrefix Condition="$(packageversion) != ''">$(packageversion)</VersionPrefix> |
|||
<VersionPrefix Condition="$(packageversion) == ''">0.1.0-alpha1</VersionPrefix> |
|||
<Authors>Six Labors</Authors> |
|||
<TargetFramework>netstandard1.1</TargetFramework> |
|||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
|||
<GenerateDocumentationFile>true</GenerateDocumentationFile> |
|||
<AssemblyName>SixLabors.Primitives</AssemblyName> |
|||
<PackageId>SixLabors.Primitives</PackageId> |
|||
<PackageTags>rectangle;point;size,primitives</PackageTags> |
|||
<PackageIconUrl>https://raw.githubusercontent.com/SixLabors/Home/master/logo.png</PackageIconUrl> |
|||
<PackageProjectUrl>https://github.com/SixLabors/Primitives</PackageProjectUrl> |
|||
<PackageLicenseUrl>http://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl> |
|||
<RepositoryType>git</RepositoryType> |
|||
<RepositoryUrl>https://github.com/SixLabors/Primitives</RepositoryUrl> |
|||
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute> |
|||
<GenerateNeutralResourcesLanguageAttribute>false</GenerateNeutralResourcesLanguageAttribute> |
|||
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute> |
|||
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute> |
|||
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute> |
|||
<DebugType Condition="$(codecov) == 'true'">full</DebugType> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<Compile Include="..\Shared\*.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="System.Numerics.Vectors" Version="4.3.0" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,225 @@ |
|||
// <copyright file="Size.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Stores an ordered pair of integers, which specify a height and width.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
|
|||
/// as it avoids the need to create new values for modification operations.
|
|||
/// </remarks>
|
|||
public struct Size : IEquatable<Size> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="Size"/> that has Width and Height values set to zero.
|
|||
/// </summary>
|
|||
public static readonly Size Empty = default(Size); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Size"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="value">The width and height of the size</param>
|
|||
public Size(int value) |
|||
: this() |
|||
{ |
|||
this.Width = value; |
|||
this.Height = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Size"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="width">The width of the size.</param>
|
|||
/// <param name="height">The height of the size.</param>
|
|||
public Size(int width, int height) |
|||
{ |
|||
this.Width = width; |
|||
this.Height = height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Size"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
public Size(Size size) |
|||
: this() |
|||
{ |
|||
this.Width = size.Width; |
|||
this.Height = size.Height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Size"/> struct from the given <see cref="Point"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
public Size(Point point) |
|||
{ |
|||
this.Width = point.X; |
|||
this.Height = point.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the width of this <see cref="Size"/>.
|
|||
/// </summary>
|
|||
public int Width { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the height of this <see cref="Size"/>.
|
|||
/// </summary>
|
|||
public int Height { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="Size"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="SizeF"/> with the dimensions of the specified <see cref="Size"/>.
|
|||
/// </summary>
|
|||
/// <param name="size">The point</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator SizeF(Size size) => new SizeF(size.Width, size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Converts the given <see cref="Size"/> into a <see cref="Point"/>.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static explicit operator Point(Size size) => new Point(size.Width, size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Computes the sum of adding two sizes.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Size"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Size operator +(Size left, Size right) => Add(left, right); |
|||
|
|||
/// <summary>
|
|||
/// Computes the difference left by subtracting one size from another.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Size"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Size operator -(Size left, Size right) => Subtract(left, right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Size"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Size"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Size"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(Size left, Size right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Size"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Size"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Size"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(Size left, Size right) => !left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Performs vector addition of two <see cref="Size"/> objects.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="Size"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Size Add(Size left, Size right) => new Size(unchecked(left.Width + right.Width), unchecked(left.Height + right.Height)); |
|||
|
|||
/// <summary>
|
|||
/// Contracts a <see cref="Size"/> by another <see cref="Size"/>
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="Size"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Size Subtract(Size left, Size right) => new Size(unchecked(left.Width - right.Width), unchecked(left.Height - right.Height)); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="SizeF"/> to a <see cref="Size"/> by performing a ceiling operation on all the dimensions.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
/// <returns>The <see cref="Size"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Size Ceiling(SizeF size) => new Size(unchecked((int)MathF.Ceiling(size.Width)), unchecked((int)MathF.Ceiling(size.Height))); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="SizeF"/> to a <see cref="Size"/> by performing a round operation on all the dimensions.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
/// <returns>The <see cref="Size"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Size Round(SizeF size) => new Size(unchecked((int)MathF.Round(size.Width)), unchecked((int)MathF.Round(size.Height))); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="SizeF"/> to a <see cref="Size"/> by performing a round operation on all the dimensions.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
/// <returns>The <see cref="Size"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Size Truncate(SizeF size) => new Size(unchecked((int)size.Width), unchecked((int)size.Height)); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => this.GetHashCode(this); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "Size [ Empty ]"; |
|||
} |
|||
|
|||
return $"Size [ Width={this.Width}, Height={this.Height} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj is Size && this.Equals((Size)obj); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(Size other) => this.Width == other.Width && this.Height == other.Height; |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <param name="size">
|
|||
/// The instance of <see cref="Size"/> to return the hash code for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
private int GetHashCode(Size size) => size.Width ^ size.Height; |
|||
} |
|||
} |
|||
@ -0,0 +1,190 @@ |
|||
// <copyright file="SizeF.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Stores an ordered pair of single precision floating points, which specify a height and width.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
|
|||
/// as it avoids the need to create new values for modification operations.
|
|||
/// </remarks>
|
|||
public struct SizeF : IEquatable<SizeF> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="SizeF"/> that has Width and Height values set to zero.
|
|||
/// </summary>
|
|||
public static readonly SizeF Empty = default(SizeF); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SizeF"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="width">The width of the size.</param>
|
|||
/// <param name="height">The height of the size.</param>
|
|||
public SizeF(float width, float height) |
|||
{ |
|||
this.Width = width; |
|||
this.Height = height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SizeF"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
public SizeF(SizeF size) |
|||
: this() |
|||
{ |
|||
this.Width = size.Width; |
|||
this.Height = size.Height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SizeF"/> struct from the given <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
public SizeF(PointF point) |
|||
{ |
|||
this.Width = point.X; |
|||
this.Height = point.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the width of this <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
public float Width { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the height of this <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
public float Height { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="SizeF"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Size"/> with the dimensions of the specified <see cref="SizeF"/> by truncating each of the dimensions.
|
|||
/// </summary>
|
|||
/// <param name="size">The size.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Size"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static explicit operator Size(SizeF size) => new Size(unchecked((int)size.Width), unchecked((int)size.Height)); |
|||
|
|||
/// <summary>
|
|||
/// Converts the given <see cref="SizeF"/> into a <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static explicit operator PointF(SizeF size) => new PointF(size.Width, size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Computes the sum of adding two sizes.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="SizeF"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static SizeF operator +(SizeF left, SizeF right) => Add(left, right); |
|||
|
|||
/// <summary>
|
|||
/// Computes the difference left by subtracting one size from another.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="SizeF"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static SizeF operator -(SizeF left, SizeF right) => Subtract(left, right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="SizeF"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(SizeF left, SizeF right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="SizeF"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(SizeF left, SizeF right) => !left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Performs vector addition of two <see cref="SizeF"/> objects.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="SizeF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static SizeF Add(SizeF left, SizeF right) => new SizeF(left.Width + right.Width, left.Height + right.Height); |
|||
|
|||
/// <summary>
|
|||
/// Contracts a <see cref="SizeF"/> by another <see cref="SizeF"/>
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="SizeF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static SizeF Subtract(SizeF left, SizeF right) => new SizeF(left.Width - right.Width, left.Height - right.Height); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.GetHashCode(this); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "SizeF [ Empty ]"; |
|||
} |
|||
|
|||
return $"SizeF [ Width={this.Width}, Height={this.Height} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj is SizeF && this.Equals((SizeF)obj); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(SizeF other) => this.Width.Equals(other.Width) && this.Height.Equals(other.Height); |
|||
|
|||
private int GetHashCode(SizeF size) => size.Width.GetHashCode() ^ size.Height.GetHashCode(); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector2"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator Vector2(SizeF point) => new Vector2(point.Width, point.Height); |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
{ |
|||
"$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", |
|||
"settings": { |
|||
"documentationRules": { |
|||
"companyName": "Six Labors", |
|||
"copyrightText": "Copyright (c) Six Labors and contributors.\nLicensed under the Apache License, Version 2.0." |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
@echo off |
|||
|
|||
cd tests\CodeCoverage |
|||
|
|||
nuget restore packages.config -PackagesDirectory . |
|||
|
|||
cd .. |
|||
cd .. |
|||
|
|||
dotnet restore SixLabors.Primitives.sln |
|||
dotnet build SixLabors.Primitives.sln --no-incremental -c debug /p:codecov=true |
|||
|
|||
rem The -threshold options prevents this taking ages... |
|||
rem tests\CodeCoverage\OpenCover.4.6.519\tools\OpenCover.Console.exe -target:"dotnet.exe" -targetargs:"test tests\SixLabors.Shapes.Tests\SixLabors.Shapes.Tests.csproj --no-build -c Release /p:codecov=true" -threshold:10 -register:user -filter:"+[SixLabors.Shapes*]*" -excludebyattribute:*.ExcludeFromCodeCoverage* -hideskipped:All -returntargetcode -output:.\SixLabors.Shapes.Coverage.xml |
|||
tests\CodeCoverage\OpenCover.4.6.519\tools\OpenCover.Console.exe -target:"dotnet.exe" -targetargs:"test tests\SixLabors.Primitives.Tests\SixLabors.Primitives.Tests.csproj --no-build -c debug" -searchdirs:"tests\SixLabors.Shapes.Tests\bin\Release\netcoreapp1.1" -register:user -output:.\SixLabors.Shapes.Coverage.xml -hideskipped:All -returntargetcode -oldStyle -filter:"+[SixLabors.Primitives*]*" |
|||
|
|||
if %errorlevel% neq 0 exit /b %errorlevel% |
|||
|
|||
SET PATH=C:\\Python34;C:\\Python34\\Scripts;%PATH% |
|||
pip install codecov |
|||
codecov -f "SixLabors.Primitives.Coverage.xml" |
|||
@ -0,0 +1,166 @@ |
|||
{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch31506\stshfhich31506\stshfbi31506\deflang3081\deflangfe3081\themelang3081\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;} |
|||
{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} |
|||
{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;} |
|||
{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} |
|||
{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} |
|||
{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} |
|||
{\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} |
|||
{\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f379\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f380\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;} |
|||
{\f382\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f383\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f386\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f387\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);} |
|||
{\f409\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f410\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f412\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f413\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} |
|||
{\f416\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f417\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} |
|||
{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} |
|||
{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} |
|||
{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} |
|||
{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} |
|||
{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} |
|||
{\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;} |
|||
{\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} |
|||
{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} |
|||
{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} |
|||
{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} |
|||
{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} |
|||
{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} |
|||
{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} |
|||
{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} |
|||
{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;} |
|||
{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;} |
|||
{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} |
|||
{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} |
|||
{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} |
|||
{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0; |
|||
\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp |
|||
\f31506\fs22\lang3081\langfe1033\langfenp1033 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa200\sl276\slmult1 |
|||
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang3081\langfe1033\cgrid\langnp3081\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive |
|||
\ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* |
|||
\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1 |
|||
\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31506\afs22\alang1025 \ltrch\fcs0 \f31506\fs22\lang3081\langfe1033\cgrid\langnp3081\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}} |
|||
{\*\rsidtbl \rsid11275983\rsid14818796\rsid15367925\rsid16724145}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Shaun}{\operator Shaun} |
|||
{\creatim\yr2012\mo1\dy5\hr7\min52}{\revtim\yr2012\mo2\dy21\hr8\min10}{\version3}{\edmins2}{\nofpages1}{\nofwords157}{\nofchars900}{\*\company Microsoft}{\nofcharsws1055}{\vern49273}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/word |
|||
ml}}\paperw11906\paperh16838\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect |
|||
\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen |
|||
\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1440\dgvorigin1440\dghshow1\dgvshow1 |
|||
\jexpand\viewkind1\viewscale60\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct |
|||
\asianbrkrule\rsidroot15367925\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0 |
|||
{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 |
|||
\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 |
|||
\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang |
|||
{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14818796 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 |
|||
\f31506\fs22\lang3081\langfe1033\cgrid\langnp3081\langfenp1033 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid14818796 Copyright (c) 2011}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid16724145 -2012}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid14818796 Shaun Wilde |
|||
\par Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation |
|||
files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is fu |
|||
rnished to do so, subject to the following conditions: |
|||
\par The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
|||
\par THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
|||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid11275983 |
|||
\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a |
|||
9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad |
|||
5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 |
|||
b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 |
|||
0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 |
|||
a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f |
|||
c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 |
|||
0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 |
|||
a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 |
|||
6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b |
|||
4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b |
|||
4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210030dd4329a8060000a41b0000160000007468656d652f7468656d652f |
|||
7468656d65312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87 |
|||
615b8116d8a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad |
|||
79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b |
|||
5d8a314d3c94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab |
|||
999fb7b4717509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9 |
|||
699640f6719e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd586 |
|||
8b37a088d1e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d6 |
|||
0cf03ac1a5193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f |
|||
9e7ef3f2d117d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be |
|||
15c308d3f28acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a9979 |
|||
3849c26ae66252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d |
|||
32a423279a668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2a |
|||
f074481847bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86 |
|||
e877f0034e16bafb0e258ebb4faf06b769e888340b103d331115bebc4eb813bf83291b63624a0d1475a756c734f9bbc2cd28546ecbe1e20a3794ca175f3fae90 |
|||
fb6d2dd99bb07b55e5ccf68942bd0877b23c77b908e8db5f9db7f024d9239010f35bd4bbe2fcae387bfff9e2bc289f2fbe24cfaa301468dd8bd846dbb4ddf1c2 |
|||
ae7b4c191ba8292337a469bc25ec3d411f06f53a73e224c5292c8de0516732307070a1c0660d125c7d44553488700a4d7bddd3444299910e254ab984c3a219ae |
|||
a4adf1d0f82b7bd46cea4388ad1c12ab5d1ed8e1153d9c9f350a3246aad01c6873462b9ac05999ad5cc988826eafc3acae853a33b7ba11cd1445875ba1b236b1 |
|||
399483c90bd560b0b0263435085a21b0f22a9cf9356b38ec6046026d77eba3dc2dc60b17e92219e180643ed27acffba86e9c94c7ca9c225a0f1b0cfae0788ad5 |
|||
4adc5a9aec1b703b8b93caec1a0bd8e5de7b132fe5113cf312503b998e2c2927274bd051db6b35979b1ef271daf6c6704e86c73805af4bdd476216c26593af84 |
|||
0dfb5393d964f9cc9bad5c313709ea70f561ed3ea7b053075221d51696910d0d339585004b34272bff7213cc7a510a5454a3b349b1b206c1f0af490176745d4b |
|||
c663e2abb2b34b23da76f6352ba57ca2881844c1111ab189d8c7e07e1daaa04f40255c77988aa05fe06e4e5bdb4cb9c5394bbaf28d98c1d971ccd20867e556a7 |
|||
689ec9166e0a522183792b8907ba55ca6e943bbf2a26e52f48957218ffcf54d1fb09dc3eac04da033e5c0d0b8c74a6b43d2e54c4a10aa511f5fb021a07533b20 |
|||
5ae07e17a621a8e082dafc17e450ffb739676998b48643a4daa7211214f623150942f6a02c99e83b85583ddbbb2c4996113211551257a656ec1139246ca86be0 |
|||
aadedb3d1441a89b6a929501833b197fee7b9641a3503739e57c732a59b1f7da1cf8a73b1f9bcca0945b874d4393dbbf10b1680f66bbaa5d6f96e77b6f59113d |
|||
316bb31a795600b3d256d0cad2fe354538e7566b2bd69cc6cbcd5c38f0e2bcc63058344429dc2121fd07f63f2a7c66bf76e80d75c8f7a1b622f878a18941d840 |
|||
545fb28d07d205d20e8ea071b283369834296bdaac75d256cb37eb0bee740bbe278cad253b8bbfcf69eca23973d939b97891c6ce2cecd8da8e2d343578f6648a |
|||
c2d0383fc818c798cf64e52f597c740f1cbd05df0c264c49134cf09d4a60e8a107260f20f92d47b374e32f000000ffff0300504b030414000600080000002100 |
|||
0dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f7 |
|||
8277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89 |
|||
d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd500 |
|||
1996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0f |
|||
bfff0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6 |
|||
a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a |
|||
0000001c00000000000000000000000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d00140006000800000021 |
|||
0030dd4329a8060000a41b00001600000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d001400060008 |
|||
00000021000dd1909fb60000001b0100002700000000000000000000000000b20900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000ad0a00000000} |
|||
{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d |
|||
617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 |
|||
6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 |
|||
656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} |
|||
{\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; |
|||
\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9; |
|||
\lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7; |
|||
\lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference; |
|||
\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000 |
|||
4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 |
|||
d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
|||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
|||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
|||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
|||
fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
|||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
|||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
|||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff |
|||
ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000e00b |
|||
b50e14f0cc01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 |
|||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 |
|||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 |
|||
0000000000000000000000000000000000000000000000000105000000000000}} |
|||
Binary file not shown.
@ -0,0 +1,10 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
|
|||
<PropertyGroup> |
|||
<OpenCoverMSBuildTasksPath Condition="'$(OpenCoverMSBuildTasksPath)' == ''">$(MSBuildExtensionsPath32)\OpenCover</OpenCoverMSBuildTasksPath> |
|||
<OpenCoverMSBuildTasksLib>$(OpenCoverMSBuildTasksPath)\OpenCover.MSBuild.dll</OpenCoverMSBuildTasksLib> |
|||
</PropertyGroup> |
|||
|
|||
<UsingTask AssemblyFile="$(OpenCoverMSBuildTasksLib)" TaskName="OpenCover.MSBuild.OpenCover" /> |
|||
</Project> |
|||
@ -0,0 +1,6 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<packages> |
|||
<package id="NUnit.Runners" version="2.6.4" /> |
|||
<package id="OpenCover" version="4.6.519" /> |
|||
<package id="ReportGenerator" version="2.1.8.0" /> |
|||
</packages> |
|||
@ -0,0 +1,53 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
|||
<PropertyGroup> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProjectGuid>{0C1E1E72-A92D-4B64-83B1-FEF1D05B8605}</ProjectGuid> |
|||
<OutputType>Library</OutputType> |
|||
<AppDesignerFolder>Properties</AppDesignerFolder> |
|||
<RootNamespace>Bom</RootNamespace> |
|||
<AssemblyName>Bom</AssemblyName> |
|||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
|||
<FileAlignment>512</FileAlignment> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|||
<DebugSymbols>true</DebugSymbols> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>false</Optimize> |
|||
<OutputPath>bin\Debug\</OutputPath> |
|||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<OutputPath>bin\Release\</OutputPath> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Reference Include="System" /> |
|||
<Reference Include="System.Core" /> |
|||
<Reference Include="System.Xml.Linq" /> |
|||
<Reference Include="System.Data.DataSetExtensions" /> |
|||
<Reference Include="Microsoft.CSharp" /> |
|||
<Reference Include="System.Data" /> |
|||
<Reference Include="System.Xml" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="BomManager.cs" /> |
|||
<Compile Include="Properties\AssemblyInfo.cs" /> |
|||
</ItemGroup> |
|||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
|||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
|||
Other similar extension points exist, see Microsoft.Common.targets. |
|||
<Target Name="BeforeBuild"> |
|||
</Target> |
|||
<Target Name="AfterBuild"> |
|||
</Target> |
|||
--> |
|||
</Project> |
|||
@ -0,0 +1,17 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.ObjectModel; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Bom |
|||
{ |
|||
public class BomManager |
|||
{ |
|||
public int MethodToTest(IEnumerable<int> collection) |
|||
{ |
|||
return (collection ?? new int[0]).Sum(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
using System.Reflection; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
// General Information about an assembly is controlled through the following
|
|||
// set of attributes. Change these attribute values to modify the information
|
|||
// associated with an assembly.
|
|||
[assembly: AssemblyTitle("Bom")] |
|||
[assembly: AssemblyDescription("")] |
|||
[assembly: AssemblyConfiguration("")] |
|||
[assembly: AssemblyCompany("")] |
|||
[assembly: AssemblyProduct("Bom")] |
|||
[assembly: AssemblyCopyright("Copyright © 2014")] |
|||
[assembly: AssemblyTrademark("")] |
|||
[assembly: AssemblyCulture("")] |
|||
|
|||
// Setting ComVisible to false makes the types in this assembly not visible
|
|||
// to COM components. If you need to access a type in this assembly from
|
|||
// COM, set the ComVisible attribute to true on that type.
|
|||
[assembly: ComVisible(false)] |
|||
|
|||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|||
[assembly: Guid("2b4e3956-c04a-42f8-a367-87bc16ffa08d")] |
|||
|
|||
// Version information for an assembly consists of the following four values:
|
|||
//
|
|||
// Major Version
|
|||
// Minor Version
|
|||
// Build Number
|
|||
// Revision
|
|||
//
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
|||
// by using the '*' as shown below:
|
|||
// [assembly: AssemblyVersion("1.0.*")]
|
|||
[assembly: AssemblyVersion("1.0.0.0")] |
|||
[assembly: AssemblyFileVersion("1.0.0.0")] |
|||
@ -0,0 +1,31 @@ |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
# Visual Studio 2012 |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bom", "Bom\Bom.csproj", "{0C1E1E72-A92D-4B64-83B1-FEF1D05B8605}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BomTest", "BomTest\BomTest.csproj", "{E25E828A-5D71-4E95-AEBC-7AD21315DFEC}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{A3CD3B1D-4C14-4A8C-A57F-A265BC49FB29}" |
|||
ProjectSection(SolutionItems) = preProject |
|||
.nuget\packages.config = .nuget\packages.config |
|||
EndProjectSection |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{0C1E1E72-A92D-4B64-83B1-FEF1D05B8605}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{0C1E1E72-A92D-4B64-83B1-FEF1D05B8605}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{0C1E1E72-A92D-4B64-83B1-FEF1D05B8605}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{0C1E1E72-A92D-4B64-83B1-FEF1D05B8605}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{E25E828A-5D71-4E95-AEBC-7AD21315DFEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{E25E828A-5D71-4E95-AEBC-7AD21315DFEC}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{E25E828A-5D71-4E95-AEBC-7AD21315DFEC}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{E25E828A-5D71-4E95-AEBC-7AD21315DFEC}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
EndGlobal |
|||
@ -0,0 +1,39 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.ObjectModel; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Bom; |
|||
using NUnit.Framework; |
|||
|
|||
namespace BomTest |
|||
{ |
|||
[TestFixture] |
|||
public class BomManagerTests |
|||
{ |
|||
[Test] |
|||
public void Sum_Is_Zero_When_No_Entries() |
|||
{ |
|||
var bomManager = new BomManager(); |
|||
Assert.AreEqual(0, bomManager.MethodToTest(new Collection<int>())); |
|||
} |
|||
|
|||
[Test] |
|||
[TestCase(new[] { 0 }, 0)] |
|||
[TestCase(new[] { 1 }, 1)] |
|||
[TestCase(new[] { 1, 2, 3 }, 6)] |
|||
public void Sum_Is_Calculated_Correctly_When_Entries_Supplied(int[] data, int expected) |
|||
{ |
|||
var bomManager = new BomManager(); |
|||
Assert.AreEqual(expected, bomManager.MethodToTest(new Collection<int>(data))); |
|||
} |
|||
|
|||
[Test] |
|||
public void Sum_Is_Zero_When_Null_Collection() |
|||
{ |
|||
var bomManager = new BomManager(); |
|||
Assert.AreEqual(0, bomManager.MethodToTest(null)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
|||
<PropertyGroup> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProjectGuid>{E25E828A-5D71-4E95-AEBC-7AD21315DFEC}</ProjectGuid> |
|||
<OutputType>Library</OutputType> |
|||
<AppDesignerFolder>Properties</AppDesignerFolder> |
|||
<RootNamespace>BomTest</RootNamespace> |
|||
<AssemblyName>BomTest</AssemblyName> |
|||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
|||
<FileAlignment>512</FileAlignment> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|||
<DebugSymbols>true</DebugSymbols> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>false</Optimize> |
|||
<OutputPath>bin\Debug\</OutputPath> |
|||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<OutputPath>bin\Release\</OutputPath> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Reference Include="nunit.framework"> |
|||
<HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath> |
|||
</Reference> |
|||
<Reference Include="System" /> |
|||
<Reference Include="System.Core" /> |
|||
<Reference Include="System.Xml.Linq" /> |
|||
<Reference Include="System.Data.DataSetExtensions" /> |
|||
<Reference Include="Microsoft.CSharp" /> |
|||
<Reference Include="System.Data" /> |
|||
<Reference Include="System.Xml" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="BomManagerTests.cs" /> |
|||
<Compile Include="Properties\AssemblyInfo.cs" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<None Include="packages.config" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Bom\Bom.csproj"> |
|||
<Project>{0C1E1E72-A92D-4B64-83B1-FEF1D05B8605}</Project> |
|||
<Name>Bom</Name> |
|||
</ProjectReference> |
|||
</ItemGroup> |
|||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
|||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
|||
Other similar extension points exist, see Microsoft.Common.targets. |
|||
<Target Name="BeforeBuild"> |
|||
</Target> |
|||
<Target Name="AfterBuild"> |
|||
</Target> |
|||
--> |
|||
</Project> |
|||
@ -0,0 +1,36 @@ |
|||
using System.Reflection; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
// General Information about an assembly is controlled through the following
|
|||
// set of attributes. Change these attribute values to modify the information
|
|||
// associated with an assembly.
|
|||
[assembly: AssemblyTitle("BomTest")] |
|||
[assembly: AssemblyDescription("")] |
|||
[assembly: AssemblyConfiguration("")] |
|||
[assembly: AssemblyCompany("")] |
|||
[assembly: AssemblyProduct("BomTest")] |
|||
[assembly: AssemblyCopyright("Copyright © 2014")] |
|||
[assembly: AssemblyTrademark("")] |
|||
[assembly: AssemblyCulture("")] |
|||
|
|||
// Setting ComVisible to false makes the types in this assembly not visible
|
|||
// to COM components. If you need to access a type in this assembly from
|
|||
// COM, set the ComVisible attribute to true on that type.
|
|||
[assembly: ComVisible(false)] |
|||
|
|||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|||
[assembly: Guid("688e9792-727d-4e39-a0ae-93461aa13b49")] |
|||
|
|||
// Version information for an assembly consists of the following four values:
|
|||
//
|
|||
// Major Version
|
|||
// Minor Version
|
|||
// Build Number
|
|||
// Revision
|
|||
//
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
|||
// by using the '*' as shown below:
|
|||
// [assembly: AssemblyVersion("1.0.*")]
|
|||
[assembly: AssemblyVersion("1.0.0.0")] |
|||
[assembly: AssemblyFileVersion("1.0.0.0")] |
|||
@ -0,0 +1,4 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<packages> |
|||
<package id="NUnit" version="2.6.4" targetFramework="net45" /> |
|||
</packages> |
|||
@ -0,0 +1,5 @@ |
|||
.\packages\OpenCover.4.6.519\tools\OpenCover.Console.exe -register:user "-filter:+[Bom]* -[*Test]*" "-target:.\packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe" "-targetargs:/noshadow .\BomTest\bin\Debug\BomTest.dll" |
|||
|
|||
.\packages\ReportGenerator.2.1.8.0\tools\ReportGenerator.exe "-reports:results.xml" "-targetdir:.\coverage" |
|||
|
|||
pause |
|||
@ -0,0 +1,137 @@ |
|||
Version 4.6.519 |
|||
#528 -safemode:on to address incomplete coverage due to thread based buffers (feature) |
|||
#521 add exclude paths (feature) |
|||
#376 protect buffer allocation in multithreaded environment (fix) |
|||
#335 allow short wait timeout to be configured (feature) |
|||
#310 improved reporting - hide branches due to iterators (feature) |
|||
#352 improved reporting - hide branches due to async (feature) |
|||
#363 calculate npath comlexity (feature) |
|||
#282 exclude by process (feature) |
|||
#246 auto crash reports (feature) |
|||
#329 address ArgumentOutOfRangeException (potentially related to #274) (fix for VS2015) |
|||
#335 error on unrecognized arguments/prefixes (fix) |
|||
#328 exclude types when declaredtype is excluded (fix-feature) |
|||
#302 ignore branches in known autogenerated sequences (feature) |
|||
|
|||
Version 4.6.166 |
|||
#323 push releases and candidates to github via appveyor (prj-mgmt) |
|||
#315 update nuget package (fix for VS2015) |
|||
#320 update packages (fix for VS2015) |
|||
#304 add switch to control timeout wait (feature) |
|||
#307 add -version to args (feature) |
|||
#305 add corclr_profiler_path support (feature) |
|||
#303 support for test cases and theories during track by test (feature) |
|||
#295 exclude assembly by attribute (feature) |
|||
#288 report (to console) if can't ready body of method (diag) |
|||
#287 fix crash (fix) |
|||
#283 Add visited class/method to summary entity (feature) |
|||
#274 Use thread based buffers for performance improvement (fix) |
|||
|
|||
Version 4.5.3723 |
|||
#244 support ApplicationUnderTest.Launch to propagate required OPENCOVER environment variables (feature) |
|||
#256 support Microsoft Fakes (feature) - beta support until we bed feature in (feature) |
|||
#248 address issue with Mono.Cecil and latest PDB (.NET 4.6) version (fix) |
|||
#252 use AppVeyor for building code and pull requests (prj-mgmt) |
|||
|
|||
Version 4.5.3522 |
|||
#243 null reference exception when excluding branch point in using finally block (fix) |
|||
|
|||
Version 4.5.3427 |
|||
#234 improved IIS support (fix) |
|||
#237 handle multiple files for a method e.g. during code contract re-writes (fix) |
|||
#228 add MDB support (feature) |
|||
#226 remove branch points on methods without sequence points (fix) |
|||
#225 Enable filters to use regular expressions (feature) |
|||
#218 Auto tag release notes (prj-mgmt) |
|||
#116 output results to accumulate with previous coverage file activate by -mergeoutput (feature) |
|||
|
|||
Version 4.5.3207 |
|||
#209 The number of WaitHandles must be less than or equal to 64 (fix) |
|||
#208 Line Number for Branch Points (feature) |
|||
#207 "using" statement causes incorrect Branch Coverage (fix) |
|||
#201 NETWORK SERVICE support (feature) |
|||
|
|||
Version 4.5.2506 |
|||
#188 Bring back COR_PRF_DISABLE_ALL_NGEN_IMAGES |
|||
#190 Compiler generated "Empty" Branch Points feature high close on next release |
|||
#191 SequencePoint FileID [CodeContractClass/For] |
|||
|
|||
Version 4.5.2316 |
|||
#170 - Overflow fixed |
|||
#188 - re-introduced COR_PRF_DISABLE_ALL_NGEN_IMAGES |
|||
#174 / #176 - pass arguments as multiple variable |
|||
|
|||
Version 4.5.1923 |
|||
#168 - skip auto implemented properties |
|||
#164 - allow registryless loading |
|||
#163 - improved error messages |
|||
|
|||
Version 4.5.1604 |
|||
#156 - prepend targetdir when applying test strategies (silverlight) |
|||
|
|||
Version 4.5.1528 |
|||
#158 - fix app domain crash due to timeout of proxy |
|||
|
|||
Version 4.5.1403 |
|||
#154 - Add xUnit to the list of supported strategies for the Cover by Test feature |
|||
#150 - fix for Xslt issue |
|||
Build Environment now uses BDD tests to ensure the packages have all assemblies required to run |
|||
|
|||
Version 4.5.1314 |
|||
#148 - Fix issue with nuget and zip packages and missing Autofac assembly. |
|||
|
|||
Version 4.5.1313 |
|||
#118 - Fix communication issue between profiler and host when many processes are vying for the channel |
|||
- improved thread management |
|||
- only check if method needs tracing if coverbytest option is utilised |
|||
|
|||
Version 4.5.1310 |
|||
#128 - Add threshold limits (optional commandline) to reduce reporting of visits |
|||
#135 - Add performance counters (admin privileges required) around the memory processing queues |
|||
|
|||
Version 4.5.1302 |
|||
Update version number to reflect 4.5 support |
|||
Fix bug in summaries |
|||
|
|||
Version 4.0.1229 |
|||
Supports .NET 4.5 (not windows store apps) |
|||
#120 - Built in Summary Reports - useful for build systems |
|||
|
|||
Version 4.0.1128 |
|||
#125 - Hide compiler generated method when no source remains after skipping |
|||
#107 - fix 'sporadic' crash when dealing with Generic methods. |
|||
|
|||
Version 4.0.1118 |
|||
#137 - Fix instrumentation issue when dealing with typed clauses |
|||
#107 - fix 'sporadic' crash when dealing with Generic methods. |
|||
|
|||
Version 4.0.1107 |
|||
#133 - Remove skipped File/Module/Class/Methods from report |
|||
#130 - Support for 'returntargetcode' switch in msbuild task |
|||
#126, #127, #132 - ReportGenerator upgrades |
|||
#122 - filter from file instead of command line list option (#123 patch) |
|||
|
|||
Version 4.0.804 |
|||
#117 - fix filter crash with anonymous types |
|||
#110 - fix timeout issues due to performance woes in dealing with large number of types/methods |
|||
|
|||
Version 4.0.724 |
|||
#94 - remove thread that "may" have been the cause of the nunit-agent.exe closedown issue - switched to a shared memory buffer per child process/profiler object instantiated |
|||
#108 - merge pull request - ToolPath property for MSBuild command |
|||
|
|||
Version 4.0.519 |
|||
#102 - add msbuild parts to zip and nuget package |
|||
#99 - exclude anonymous functions if containing method is excluded |
|||
#97 - fix crash based on receiving corrupt data (sequence point with id==0) |
|||
#88 - only use COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST if oldStyle instrumentation |
|||
|
|||
Version 4.0.408 |
|||
#83 - build a zip package |
|||
#88 - provide a switch for "old school" instrumentation |
|||
#95 - fix for namespaces with spaces |
|||
|
|||
Version 4.0.301.10 |
|||
#78 - fix for endfault/endfinally |
|||
#71 - detect disabled service |
|||
|
|||
|
|||
File diff suppressed because it is too large
@ -0,0 +1,21 @@ |
|||
Welcome to OpenCover. |
|||
|
|||
OpenCover is an open source (MIT licence) code coverage utility for all .NET |
|||
Frameworks (2 and above, including Silverlight). It can handle all .NET |
|||
languages as long as the compiled assemblies use the .NET Runtime. |
|||
|
|||
It is most commonly used to gather coverage data of code that is being |
|||
exercised by unit testing i.e. nunit, mstest etc. |
|||
|
|||
We recommend that you view the documents that have also been installed |
|||
alongside the utility to get started or you can look at the documentation |
|||
provided on the wiki https://github.com/OpenCover/opencover/wiki/Usage. |
|||
|
|||
Currently OpenCover has no visualization of its results and we recommend that |
|||
your use ReportGenerator (2.1.8 and above) to view the results against your code. |
|||
|
|||
A sample project showing a possible way to use OpenCover with ReportGenerator |
|||
has also been provided for your convenience. |
|||
|
|||
If you have any issues or feature requests with OpenCover please raise them |
|||
with the project owners on https://github.com/opencover/opencover. |
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,26 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<configuration> |
|||
<configSections> |
|||
<section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration" /> |
|||
</configSections> |
|||
<autofac> |
|||
<modules> |
|||
<module type="OpenCover.Extensions.RegisterStrategiesModule, OpenCover.Extensions" /> |
|||
</modules> |
|||
</autofac> |
|||
<startup> |
|||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> |
|||
</startup> |
|||
<runtime> |
|||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> |
|||
<dependentAssembly> |
|||
<assemblyIdentity name="Mono.Cecil" publicKeyToken="0738eb9f132ed756" culture="neutral" /> |
|||
<bindingRedirect oldVersion="0.0.0.0-0.9.6.0" newVersion="0.9.6.0" /> |
|||
</dependentAssembly> |
|||
<dependentAssembly> |
|||
<assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral" /> |
|||
<bindingRedirect oldVersion="0.0.0.0-3.5.0.0" newVersion="3.5.0.0" /> |
|||
</dependentAssembly> |
|||
</assemblyBinding> |
|||
</runtime> |
|||
</configuration> |
|||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,39 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<configuration> |
|||
<configSections> |
|||
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> |
|||
</configSections> |
|||
|
|||
<log4net> |
|||
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"> |
|||
<mapping> |
|||
<level value="ERROR" /> |
|||
<foreColor value="White" /> |
|||
<backColor value="Red, HighIntensity" /> |
|||
</mapping> |
|||
<mapping> |
|||
<level value="DEBUG" /> |
|||
<backColor value="Green" /> |
|||
</mapping> |
|||
<layout type="log4net.Layout.PatternLayout"> |
|||
<conversionPattern value="%message%newline" /> |
|||
</layout> |
|||
</appender> |
|||
<appender name="OutputDebugStringAppender" type="log4net.Appender.OutputDebugStringAppender"> |
|||
<layout type="log4net.Layout.PatternLayout"> |
|||
<conversionPattern value="OpenCover: (Host) %message" /> |
|||
</layout> |
|||
</appender> |
|||
|
|||
<logger name="DebugLogger" additivity="false"> |
|||
<level value="ALL" /> |
|||
<appender-ref ref="OutputDebugStringAppender" /> |
|||
</logger> |
|||
|
|||
<root> |
|||
<appender-ref ref="ColoredConsoleAppender" /> |
|||
</root> |
|||
|
|||
</log4net> |
|||
|
|||
</configuration> |
|||
Binary file not shown.
@ -0,0 +1,332 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- |
|||
This report was provided by pawan52tiwari (https://github.com/pawan52tiwari) |
|||
see https://github.com/sawilde/opencover/issues/93 |
|||
|
|||
sample usage: |
|||
powershell -noexit -file transform.ps1 -xsl simple_report.xslt -xml ..\results\opencovertests.xml -output ..\results\simple_output.html |
|||
--> |
|||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > |
|||
<xsl:output method="html"/> |
|||
<xsl:variable name="covered.lines" select="count(/CoverageSession/Modules/Module/Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc > 0])" /> |
|||
<xsl:variable name="uncovered.lines" select="count(/CoverageSession/Modules/Module/Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc = 0])" /> |
|||
<xsl:variable name="coverable.Lines" select="count(/CoverageSession/Modules/Module/Classes/Class/Methods/Method/SequencePoints/SequencePoint)" /> |
|||
<xsl:template match="/"> |
|||
<html><body> |
|||
<h2 class="sectionheader">Code Coverage Report</h2> |
|||
<table class="overview"> |
|||
<colgroup> |
|||
<col width="130" /> |
|||
<col /> |
|||
</colgroup> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Generated on: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="/@date"/> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Parser: |
|||
</td> |
|||
<td> |
|||
Pawan Tiwari's Parser |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Assemblies: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="count(/CoverageSession/Modules/Module/ModuleName)"></xsl:value-of> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Files: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="count(/CoverageSession/Modules/Module/Files/File)"/> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Coverage: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="$covered.lines div ($uncovered.lines + $covered.lines) * 100"/>% |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Covered lines: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="$covered.lines"/> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
UnCovered lines: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="$uncovered.lines"/> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Coverable lines: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="$coverable.Lines"/> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Total lines: |
|||
</td> |
|||
<td> |
|||
Yet To be discovered |
|||
|
|||
</td> |
|||
</tr> |
|||
</table> |
|||
<h2 class="sectionheader"> |
|||
Assemblies |
|||
</h2> |
|||
<p class="toggleClasses"> |
|||
<a id="collapseAllClasses" style="text-decoration: none;color:red;font-size:10px" href="#">Collapse all classes</a> | <a id="expandAllClasses" style="text-decoration: none;color:red;font-size:10px" |
|||
href="#">Expand all classes</a> |
|||
</p> |
|||
<table class="overview"> |
|||
<colgroup> |
|||
<col /> |
|||
<col width="60" /> |
|||
<col width="105" /> |
|||
</colgroup> |
|||
<xsl:for-each select="/CoverageSession/Modules/Module"> |
|||
<xsl:sort select="ModuleName" order="ascending"/> |
|||
<xsl:sort select="ModuleName"/> |
|||
<xsl:variable name="ModulenameVariable" select="ModuleName"></xsl:variable> |
|||
<xsl:variable name="FileLocationLink" select="."></xsl:variable> |
|||
<tr class="expanded"> |
|||
<th> |
|||
<a href="#" class="toggleClassesInAssembly" style="text-decoration: none;color:red;font-size:10px" title="Collapse/Expand classes"></a> |
|||
<xsl:value-of select="ModuleName"/> |
|||
<a href="#" class="toggleAssemblyDetails" style="text-decoration: none;color:red;font-size:10px" title="Show details of assembly">Details</a> |
|||
<div class="detailspopup"> |
|||
<table class="overview"> |
|||
<colgroup> |
|||
<col width="130" /> |
|||
<col /> |
|||
</colgroup> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Classes: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="count(Classes/Class/FullName[not(contains(text(),'<'))])"></xsl:value-of> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Covered lines: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="count(Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc > 0])"></xsl:value-of> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Coverable lines: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="count(Classes/Class/Methods/Method/SequencePoints/SequencePoint)" /> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Coverage: |
|||
</td> |
|||
<td> |
|||
<xsl:choose> |
|||
<xsl:when test="(count(Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc = 0]) + count(Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc > 0])) > 0"> |
|||
<xsl:value-of select="count(Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc > 0]) div (count(Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc = 0]) + count(Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc > 0])) * 100"/>% |
|||
</xsl:when> |
|||
<xsl:otherwise> |
|||
0 |
|||
</xsl:otherwise> |
|||
</xsl:choose> |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</div> |
|||
</th> |
|||
<th title="LineCoverage"> |
|||
<xsl:if test="(Classes/Class/Methods/Method)"> |
|||
<xsl:value-of select="round(count(Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc > 0]) div (count(Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc = 0]) + count(Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc > 0])) * 100)"/>% |
|||
</xsl:if> |
|||
</th> |
|||
<td> |
|||
<xsl:variable name="width" select="count(Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc > 0]) div (count(Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc = 0]) + count(Classes/Class/Methods/Method/SequencePoints/SequencePoint[@vc > 0])) * 100"></xsl:variable> |
|||
<table class="coverage"> |
|||
<tr> |
|||
<td class="green" style="width: {$width}px;"> |
|||
  |
|||
</td> |
|||
<td class="red" style="width: {100-$width}px;"> |
|||
  |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</td> |
|||
</tr> |
|||
<xsl:for-each select="Classes/Class"> |
|||
<xsl:if test="FullName[not(contains(text(),'<'))]"> |
|||
<tr class="classrow"> |
|||
<td align="center"> |
|||
<h3 class="sectionheader"> |
|||
Class Name:<xsl:value-of select="FullName"></xsl:value-of> |
|||
</h3> |
|||
</td> |
|||
<td title="LineCoverage"> |
|||
<xsl:value-of select="round(count(Methods/Method/SequencePoints/SequencePoint[@vc > 0]) div (count(Methods/Method/SequencePoints/SequencePoint[@vc = 0]) + count(Methods/Method/SequencePoints/SequencePoint[@vc > 0])) * 100)"/>% |
|||
</td> |
|||
<td> |
|||
<table class="coverage"> |
|||
<tr width="100px"> |
|||
<xsl:variable name="Line.CoveragerClass" select="round(count(Methods/Method/SequencePoints/SequencePoint[@vc > 0]) div (count(Methods/Method/SequencePoints/SequencePoint[@vc = 0]) + count(Methods/Method/SequencePoints/SequencePoint[@vc > 0])) * 100)"></xsl:variable> |
|||
<td class="green" style="width: {$Line.CoveragerClass +9}px;"> |
|||
  |
|||
</td> |
|||
<td class="red" style="width: {100- $Line.CoveragerClass}px;"> |
|||
  |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</td> |
|||
</tr> |
|||
<tr class="classrow"> |
|||
<td colspan="3"> |
|||
<table class="overview"> |
|||
<colgroup> |
|||
<col width="130" /> |
|||
<col /> |
|||
</colgroup> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Class: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="FullName"></xsl:value-of> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Assembly: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="$ModulenameVariable"></xsl:value-of> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
File(s): |
|||
</td> |
|||
<td> |
|||
<xsl:variable name="CounterForFile" select="position()"></xsl:variable> |
|||
<xsl:value-of select="$FileLocationLink/Files/File[$CounterForFile]/@fullPath"/> |
|||
<xsl:variable name="FilePathVariable" select="//Files/File[@uid=($CounterForFile -1)]/@fullPath"></xsl:variable> |
|||
<a href="file:///{$FilePathVariable}"> |
|||
<!--<xsl:value-of select="$FilePathVariable"></xsl:value-of>--> |
|||
</a> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Coverage: |
|||
</td> |
|||
<td> |
|||
<xsl:variable name="Covered.lines" select="count(Methods/Method/SequencePoints/SequencePoint[@vc > 0])"></xsl:variable> |
|||
<xsl:value-of select="count(Methods/Method/SequencePoints/SequencePoint[@vc > 0]) div (count(Methods/Method/SequencePoints/SequencePoint[@vc = 0]) + count(Methods/Method/SequencePoints/SequencePoint[@vc > 0])) * 100"/>% |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Covered lines: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="count(Methods/Method/SequencePoints/SequencePoint[@vc > 0])"></xsl:value-of> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Coverable lines: |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="count(Methods/Method/SequencePoints/SequencePoint)"></xsl:value-of> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Total lines: |
|||
</td> |
|||
<td> |
|||
51 |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</td> |
|||
</tr> |
|||
<tr class="classrow"> |
|||
<td colspan="3"> |
|||
<table class="overview"> |
|||
<tr> |
|||
<td class="sectionheader"> |
|||
Method |
|||
</td> |
|||
<td class="sectionheader"> |
|||
Cyclomatic Complexity |
|||
</td> |
|||
<td class="sectionheader"> |
|||
Sequence Coverage |
|||
</td> |
|||
<td class="sectionheader"> |
|||
Branch Coverage |
|||
</td> |
|||
<td class="sectionheader"> |
|||
Static Method |
|||
</td> |
|||
</tr> |
|||
<xsl:for-each select="Methods/Method[@isConstructor='false']"> |
|||
<tr> |
|||
<td> |
|||
<xsl:variable name="indexvariable" select="string-length(substring-before(Name, '::'))"/> |
|||
<xsl:value-of disable-output-escaping="yes" select="substring(Name,$indexvariable +3)"></xsl:value-of> |
|||
</td> |
|||
<td> |
|||
<xsl:value-of disable-output-escaping="yes" select="@cyclomaticComplexity"></xsl:value-of> |
|||
</td> |
|||
<td> |
|||
<xsl:value-of disable-output-escaping="yes" select="@sequenceCoverage"></xsl:value-of> |
|||
</td> |
|||
<td> |
|||
<xsl:value-of disable-output-escaping="yes" select="@branchCoverage"></xsl:value-of> |
|||
</td> |
|||
<td> |
|||
<xsl:value-of disable-output-escaping="yes" select="@isStatic"></xsl:value-of> |
|||
</td> |
|||
</tr> |
|||
</xsl:for-each> |
|||
</table> |
|||
</td> |
|||
</tr> |
|||
</xsl:if> |
|||
</xsl:for-each> |
|||
</xsl:for-each> |
|||
</table> |
|||
</body></html> |
|||
</xsl:template> |
|||
</xsl:stylesheet> |
|||
@ -0,0 +1,17 @@ |
|||
[CmdletBinding()] |
|||
Param( |
|||
[Parameter(Mandatory=$True,Position=1)] |
|||
[string]$xsl, |
|||
|
|||
[Parameter(Mandatory=$True)] |
|||
[string]$xml, |
|||
|
|||
[Parameter(Mandatory=$True)] |
|||
[string]$output |
|||
) |
|||
|
|||
$xslt = New-Object System.Xml.Xsl.XslCompiledTransform; |
|||
$xslt.Load($xsl); |
|||
$xslt.Transform($xml, $output); |
|||
|
|||
Write-Host "The file has been transformed." |
|||
@ -0,0 +1,4 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<packages> |
|||
<package id="OpenCover" version="4.6.519" /> |
|||
</packages> |
|||
@ -0,0 +1,192 @@ |
|||
// <copyright file="PointFTests.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives.Tests.Numerics |
|||
{ |
|||
using System; |
|||
using System.Globalization; |
|||
using System.Numerics; |
|||
using System.Reflection; |
|||
using Xunit; |
|||
|
|||
public class PointFTests |
|||
{ |
|||
[Fact] |
|||
public void DefaultConstructorTest() |
|||
{ |
|||
Assert.Equal(PointF.Empty, new PointF()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MinValue)] |
|||
[InlineData(float.MaxValue, float.MaxValue)] |
|||
[InlineData(float.MinValue, float.MaxValue)] |
|||
[InlineData(0.0, 0.0)] |
|||
public void NonDefaultConstructorTest(float x, float y) |
|||
{ |
|||
var p1 = new PointF(x, y); |
|||
|
|||
Assert.Equal(x, p1.X); |
|||
Assert.Equal(y, p1.Y); |
|||
} |
|||
|
|||
[Fact] |
|||
public void IsEmptyDefaultsTest() |
|||
{ |
|||
Assert.True(PointF.Empty.IsEmpty); |
|||
Assert.True(new PointF().IsEmpty); |
|||
Assert.True(new PointF(0, 0).IsEmpty); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MinValue)] |
|||
[InlineData(float.MaxValue, float.MaxValue)] |
|||
public void IsEmptyRandomTest(float x, float y) |
|||
{ |
|||
Assert.False(new PointF(x, y).IsEmpty); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MinValue)] |
|||
[InlineData(float.MaxValue, float.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void CoordinatesTest(float x, float y) |
|||
{ |
|||
var p = new PointF(x, y); |
|||
Assert.Equal(x, p.X); |
|||
Assert.Equal(y, p.Y); |
|||
|
|||
p.X = 10; |
|||
Assert.Equal(10, p.X); |
|||
|
|||
p.Y = -10.123f; |
|||
Assert.Equal(-10.123, p.Y, 3); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue, int.MaxValue, int.MinValue)] |
|||
[InlineData(float.MinValue, float.MaxValue, int.MinValue, int.MaxValue)] |
|||
[InlineData(0, 0, 0, 0)] |
|||
public void ArithmeticTestWithSize(float x, float y, int x1, int y1) |
|||
{ |
|||
var p = new PointF(x, y); |
|||
var s = new Size(x1, y1); |
|||
|
|||
var addExpected = new PointF(x + x1, y + y1); |
|||
var subExpected = new PointF(x - x1, y - y1); |
|||
Assert.Equal(addExpected, p + s); |
|||
Assert.Equal(subExpected, p - s); |
|||
Assert.Equal(addExpected, PointF.Add(p, s)); |
|||
Assert.Equal(subExpected, PointF.Subtract(p, s)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void ArithmeticTestWithSizeF(float x, float y) |
|||
{ |
|||
var p = new PointF(x, y); |
|||
var s = new SizeF(y, x); |
|||
|
|||
var addExpected = new PointF(x + y, y + x); |
|||
var subExpected = new PointF(x - y, y - x); |
|||
Assert.Equal(addExpected, p + s); |
|||
Assert.Equal(subExpected, p - s); |
|||
Assert.Equal(addExpected, PointF.Add(p, s)); |
|||
Assert.Equal(subExpected, PointF.Subtract(p, s)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RotateTest() |
|||
{ |
|||
var p = new PointF(13, 17); |
|||
Matrix matrix = Matrix.CreateRotationDegrees(45, PointF.Empty); |
|||
|
|||
var pout = PointF.Rotate(p, matrix); |
|||
|
|||
Assert.Equal(new PointF(-2.82842732F, 21.2132034F), pout); |
|||
} |
|||
|
|||
[Fact] |
|||
public void SkewTest() |
|||
{ |
|||
var p = new PointF(13, 17); |
|||
Matrix matrix = Matrix.CreateSkewDegrees(45, 45, PointF.Empty); |
|||
|
|||
var pout = PointF.Skew(p, matrix); |
|||
Assert.Equal(new PointF(30, 30), pout); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MaxValue)] |
|||
[InlineData(float.MinValue, float.MinValue)] |
|||
[InlineData(float.MaxValue, float.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void EqualityTest(float x, float y) |
|||
{ |
|||
var pLeft = new PointF(x, y); |
|||
var pRight = new PointF(y, x); |
|||
|
|||
if (x == y) |
|||
{ |
|||
Assert.True(pLeft == pRight); |
|||
Assert.False(pLeft != pRight); |
|||
Assert.True(pLeft.Equals(pRight)); |
|||
Assert.True(pLeft.Equals((object)pRight)); |
|||
Assert.Equal(pLeft.GetHashCode(), pRight.GetHashCode()); |
|||
return; |
|||
} |
|||
|
|||
Assert.True(pLeft != pRight); |
|||
Assert.False(pLeft == pRight); |
|||
Assert.False(pLeft.Equals(pRight)); |
|||
Assert.False(pLeft.Equals((object)pRight)); |
|||
} |
|||
|
|||
[Fact] |
|||
public static void EqualityTest_NotPointF() |
|||
{ |
|||
var point = new PointF(0, 0); |
|||
Assert.False(point.Equals(null)); |
|||
Assert.False(point.Equals(0)); |
|||
|
|||
// If PointF implements IEquatable<PointF> (e.g. in .NET Core), then structs that are implicitly
|
|||
// convertible to var can potentially be equal.
|
|||
// See https://github.com/dotnet/corefx/issues/5255.
|
|||
bool expectsImplicitCastToPointF = typeof(IEquatable<PointF>).IsAssignableFrom(point.GetType()); |
|||
Assert.Equal(expectsImplicitCastToPointF, point.Equals(new Point(0, 0))); |
|||
|
|||
Assert.False(point.Equals((object)new Point(0, 0))); // No implicit cast
|
|||
} |
|||
|
|||
[Fact] |
|||
public static void GetHashCodeTest() |
|||
{ |
|||
var point = new PointF(10, 10); |
|||
Assert.Equal(point.GetHashCode(), new PointF(10, 10).GetHashCode()); |
|||
Assert.NotEqual(point.GetHashCode(), new PointF(20, 10).GetHashCode()); |
|||
Assert.NotEqual(point.GetHashCode(), new PointF(10, 20).GetHashCode()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringTest() |
|||
{ |
|||
var p = new PointF(5.1F, -5.123F); |
|||
Assert.Equal(string.Format(CultureInfo.CurrentCulture, "PointF [ X={0}, Y={1} ]", p.X, p.Y), p.ToString()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringEmptyTest() |
|||
{ |
|||
var p = new PointF(0, 0); |
|||
Assert.Equal("PointF [ Empty ]", p.ToString()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,252 @@ |
|||
// <copyright file="PointTests.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives.Tests |
|||
{ |
|||
using System.Globalization; |
|||
using System.Numerics; |
|||
|
|||
using Xunit; |
|||
|
|||
public class PointTests |
|||
{ |
|||
[Fact] |
|||
public void DefaultConstructorTest() |
|||
{ |
|||
Assert.Equal(Point.Empty, new Point()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void NonDefaultConstructorTest(int x, int y) |
|||
{ |
|||
var p1 = new Point(x, y); |
|||
var p2 = new Point(new Size(x, y)); |
|||
|
|||
Assert.Equal(p1, p2); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue)] |
|||
[InlineData(int.MinValue)] |
|||
[InlineData(0)] |
|||
public void SingleIntConstructorTest(int x) |
|||
{ |
|||
var p1 = new Point(x); |
|||
var p2 = new Point(unchecked((short)(x & 0xFFFF)), unchecked((short)((x >> 16) & 0xFFFF))); |
|||
|
|||
Assert.Equal(p1, p2); |
|||
} |
|||
|
|||
[Fact] |
|||
public void IsEmptyDefaultsTest() |
|||
{ |
|||
Assert.True(Point.Empty.IsEmpty); |
|||
Assert.True(new Point().IsEmpty); |
|||
Assert.True(new Point(0, 0).IsEmpty); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
public void IsEmptyRandomTest(int x, int y) |
|||
{ |
|||
Assert.False(new Point(x, y).IsEmpty); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void CoordinatesTest(int x, int y) |
|||
{ |
|||
var p = new Point(x, y); |
|||
Assert.Equal(x, p.X); |
|||
Assert.Equal(y, p.Y); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void PointFConversionTest(int x, int y) |
|||
{ |
|||
PointF p = new Point(x, y); |
|||
Assert.Equal(new PointF(x, y), p); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void SizeConversionTest(int x, int y) |
|||
{ |
|||
var sz = (Size)new Point(x, y); |
|||
Assert.Equal(new Size(x, y), sz); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void ArithmeticTest(int x, int y) |
|||
{ |
|||
Point addExpected, subExpected, p = new Point(x, y); |
|||
var s = new Size(y, x); |
|||
|
|||
unchecked |
|||
{ |
|||
addExpected = new Point(x + y, y + x); |
|||
subExpected = new Point(x - y, y - x); |
|||
} |
|||
|
|||
Assert.Equal(addExpected, p + s); |
|||
Assert.Equal(subExpected, p - s); |
|||
Assert.Equal(addExpected, Point.Add(p, s)); |
|||
Assert.Equal(subExpected, Point.Subtract(p, s)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MinValue)] |
|||
[InlineData(float.MaxValue, float.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void PointFMathematicalTest(float x, float y) |
|||
{ |
|||
var pf = new PointF(x, y); |
|||
Point pCeiling, pTruncate, pRound; |
|||
|
|||
unchecked |
|||
{ |
|||
pCeiling = new Point((int)MathF.Ceiling(x), (int)MathF.Ceiling(y)); |
|||
pTruncate = new Point((int)x, (int)y); |
|||
pRound = new Point((int)MathF.Round(x), (int)MathF.Round(y)); |
|||
} |
|||
|
|||
Assert.Equal(pCeiling, Point.Ceiling(pf)); |
|||
Assert.Equal(pRound, Point.Round(pf)); |
|||
Assert.Equal(pTruncate, (Point)pf); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void OffsetTest(int x, int y) |
|||
{ |
|||
var p1 = new Point(x, y); |
|||
var p2 = new Point(y, x); |
|||
|
|||
p1.Offset(p2); |
|||
|
|||
Assert.Equal(unchecked(p2.X + p2.Y), p1.X); |
|||
Assert.Equal(p1.X, p1.Y); |
|||
|
|||
p2.Offset(x, y); |
|||
Assert.Equal(p1, p2); |
|||
} |
|||
|
|||
[Fact] |
|||
public void RotateTest() |
|||
{ |
|||
var p = new Point(13, 17); |
|||
Matrix matrix = Matrix.CreateRotationDegrees(45, Point.Empty); |
|||
|
|||
var pout = Point.Rotate(p, matrix); |
|||
|
|||
Assert.Equal(new Point(-3, 21), pout); |
|||
} |
|||
|
|||
[Fact] |
|||
public void SkewTest() |
|||
{ |
|||
var p = new Point(13, 17); |
|||
Matrix3x2 matrix = Matrix.CreateSkewDegrees(45, 45, Point.Empty); |
|||
|
|||
var pout = Point.Skew(p, matrix); |
|||
Assert.Equal(new Point(30, 30), pout); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void EqualityTest(int x, int y) |
|||
{ |
|||
var p1 = new Point(x, y); |
|||
var p2 = new Point(x / 2 - 1, y / 2 - 1); |
|||
var p3 = new Point(x, y); |
|||
|
|||
Assert.True(p1 == p3); |
|||
Assert.True(p1 != p2); |
|||
Assert.True(p2 != p3); |
|||
|
|||
Assert.True(p1.Equals(p3)); |
|||
Assert.False(p1.Equals(p2)); |
|||
Assert.False(p2.Equals(p3)); |
|||
|
|||
Assert.True(p1.Equals((object)p3)); |
|||
Assert.False(p1.Equals((object)p2)); |
|||
Assert.False(p2.Equals((object)p3)); |
|||
|
|||
Assert.Equal(p1.GetHashCode(), p3.GetHashCode()); |
|||
} |
|||
|
|||
[Fact] |
|||
public static void EqualityTest_NotPoint() |
|||
{ |
|||
var point = new Point(0, 0); |
|||
Assert.False(point.Equals(null)); |
|||
Assert.False(point.Equals(0)); |
|||
Assert.False(point.Equals(new PointF(0, 0))); |
|||
} |
|||
|
|||
[Fact] |
|||
public static void GetHashCodeTest() |
|||
{ |
|||
var point = new Point(10, 10); |
|||
Assert.Equal(point.GetHashCode(), new Point(10, 10).GetHashCode()); |
|||
Assert.NotEqual(point.GetHashCode(), new Point(20, 10).GetHashCode()); |
|||
Assert.NotEqual(point.GetHashCode(), new Point(10, 20).GetHashCode()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(1, -2, 3, -4)] |
|||
public void ConversionTest(int x, int y, int width, int height) |
|||
{ |
|||
var rect = new Rectangle(x, y, width, height); |
|||
RectangleF rectF = rect; |
|||
Assert.Equal(x, rectF.X); |
|||
Assert.Equal(y, rectF.Y); |
|||
Assert.Equal(width, rectF.Width); |
|||
Assert.Equal(height, rectF.Height); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringTest() |
|||
{ |
|||
var p = new Point(5, -5); |
|||
Assert.Equal(string.Format(CultureInfo.CurrentCulture, "Point [ X={0}, Y={1} ]", p.X, p.Y), p.ToString()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringEmptyTest() |
|||
{ |
|||
var p = new Point(0, 0); |
|||
Assert.Equal("Point [ Empty ]", p.ToString()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,115 @@ |
|||
// <copyright file="RationalTests.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives.Tests |
|||
{ |
|||
using Xunit; |
|||
|
|||
/// <summary>
|
|||
/// Tests the <see cref="Rational"/> struct.
|
|||
/// </summary>
|
|||
public class RationalTests |
|||
{ |
|||
/// <summary>
|
|||
/// Tests the equality operators for equality.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void AreEqual() |
|||
{ |
|||
Rational r1 = new Rational(3, 2); |
|||
Rational r2 = new Rational(3, 2); |
|||
|
|||
Assert.Equal(r1, r2); |
|||
Assert.True(r1 == r2); |
|||
|
|||
Rational r3 = new Rational(7.55); |
|||
Rational r4 = new Rational(755, 100); |
|||
Rational r5 = new Rational(151, 20); |
|||
|
|||
Assert.Equal(r3, r4); |
|||
Assert.Equal(r4, r5); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Tests the equality operators for inequality.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void AreNotEqual() |
|||
{ |
|||
Rational first = new Rational(0, 100); |
|||
Rational second = new Rational(100, 100); |
|||
|
|||
Assert.NotEqual(first, second); |
|||
Assert.True(first != second); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Tests whether the Rational constructor correctly assign properties.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void ConstructorAssignsProperties() |
|||
{ |
|||
Rational rational = new Rational(7, 55); |
|||
Assert.Equal(7U, rational.Numerator); |
|||
Assert.Equal(55U, rational.Denominator); |
|||
|
|||
rational = new Rational(755, 100); |
|||
Assert.Equal(151U, rational.Numerator); |
|||
Assert.Equal(20U, rational.Denominator); |
|||
|
|||
rational = new Rational(755, 100, false); |
|||
Assert.Equal(755U, rational.Numerator); |
|||
Assert.Equal(100U, rational.Denominator); |
|||
|
|||
rational = new Rational(-7.55); |
|||
Assert.Equal(151U, rational.Numerator); |
|||
Assert.Equal(20U, rational.Denominator); |
|||
|
|||
rational = new Rational(7); |
|||
Assert.Equal(7U, rational.Numerator); |
|||
Assert.Equal(1U, rational.Denominator); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Fraction() |
|||
{ |
|||
Rational first = new Rational(1.0 / 1600); |
|||
Rational second = new Rational(1.0 / 1600, true); |
|||
Assert.False(first.Equals(second)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToDouble() |
|||
{ |
|||
Rational rational = new Rational(0, 0); |
|||
Assert.Equal(double.NaN, rational.ToDouble()); |
|||
|
|||
rational = new Rational(2, 0); |
|||
Assert.Equal(double.PositiveInfinity, rational.ToDouble()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringRepresention() |
|||
{ |
|||
Rational rational = new Rational(0, 0); |
|||
Assert.Equal("[ Indeterminate ]", rational.ToString()); |
|||
|
|||
rational = new Rational(double.PositiveInfinity); |
|||
Assert.Equal("[ PositiveInfinity ]", rational.ToString()); |
|||
|
|||
rational = new Rational(double.NegativeInfinity); |
|||
Assert.Equal("[ PositiveInfinity ]", rational.ToString()); |
|||
|
|||
rational = new Rational(0, 1); |
|||
Assert.Equal("0", rational.ToString()); |
|||
|
|||
rational = new Rational(2, 1); |
|||
Assert.Equal("2", rational.ToString()); |
|||
|
|||
rational = new Rational(1, 2); |
|||
Assert.Equal("1/2", rational.ToString()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,267 @@ |
|||
// <copyright file="RectangleFTests.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives.Tests |
|||
{ |
|||
using System; |
|||
using System.Globalization; |
|||
using System.Reflection; |
|||
|
|||
using Xunit; |
|||
|
|||
/// <summary>
|
|||
/// Tests the <see cref="RectangleF"/> struct.
|
|||
/// </summary>
|
|||
public class RectangleFTests |
|||
{ |
|||
[Fact] |
|||
public void DefaultConstructorTest() |
|||
{ |
|||
Assert.Equal(RectangleF.Empty, new RectangleF()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] |
|||
[InlineData(float.MaxValue, 0, 0, float.MaxValue)] |
|||
[InlineData(0, float.MinValue, float.MaxValue, 0)] |
|||
public void NonDefaultConstructorTest(float x, float y, float width, float height) |
|||
{ |
|||
var rect1 = new RectangleF(x, y, width, height); |
|||
var p = new PointF(x, y); |
|||
var s = new SizeF(width, height); |
|||
var rect2 = new RectangleF(p, s); |
|||
|
|||
Assert.Equal(rect1, rect2); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] |
|||
[InlineData(float.MaxValue, 0, 0, float.MaxValue)] |
|||
[InlineData(0, float.MinValue, float.MaxValue, 0)] |
|||
public void FromLTRBTest(float left, float top, float right, float bottom) |
|||
{ |
|||
var expected = new RectangleF(left, top, right - left, bottom - top); |
|||
var actual = RectangleF.FromLTRB(left, top, right, bottom); |
|||
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] |
|||
[InlineData(float.MaxValue, 0, 0, float.MaxValue)] |
|||
[InlineData(0, float.MinValue, float.MaxValue, 0)] |
|||
public void DimensionsTest(float x, float y, float width, float height) |
|||
{ |
|||
var rect = new RectangleF(x, y, width, height); |
|||
var p = new PointF(x, y); |
|||
var s = new SizeF(width, height); |
|||
|
|||
Assert.Equal(p, rect.Location); |
|||
Assert.Equal(s, rect.Size); |
|||
Assert.Equal(x, rect.X); |
|||
Assert.Equal(y, rect.Y); |
|||
Assert.Equal(width, rect.Width); |
|||
Assert.Equal(height, rect.Height); |
|||
Assert.Equal(x, rect.Left); |
|||
Assert.Equal(y, rect.Top); |
|||
Assert.Equal(x + width, rect.Right); |
|||
Assert.Equal(y + height, rect.Bottom); |
|||
} |
|||
|
|||
[Fact] |
|||
public void IsEmptyTest() |
|||
{ |
|||
Assert.True(RectangleF.Empty.IsEmpty); |
|||
Assert.True(new RectangleF().IsEmpty); |
|||
Assert.True(new RectangleF(1, -2, -10, 10).IsEmpty); |
|||
Assert.True(new RectangleF(1, -2, 10, -10).IsEmpty); |
|||
Assert.True(new RectangleF(1, -2, 0, 0).IsEmpty); |
|||
|
|||
Assert.False(new RectangleF(0, 0, 10, 10).IsEmpty); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0)] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
public static void LocationSetTest(float x, float y) |
|||
{ |
|||
var point = new PointF(x, y); |
|||
var rect = new RectangleF(10, 10, 10, 10) { Location = point }; |
|||
Assert.Equal(point, rect.Location); |
|||
Assert.Equal(point.X, rect.X); |
|||
Assert.Equal(point.Y, rect.Y); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0)] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
public static void SizeSetTest(float x, float y) |
|||
{ |
|||
var size = new SizeF(x, y); |
|||
var rect = new RectangleF(10, 10, 10, 10) { Size = size }; |
|||
Assert.Equal(size, rect.Size); |
|||
Assert.Equal(size.Width, rect.Width); |
|||
Assert.Equal(size.Height, rect.Height); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] |
|||
[InlineData(float.MaxValue, 0, 0, float.MaxValue)] |
|||
[InlineData(0, float.MinValue, float.MaxValue, 0)] |
|||
public void EqualityTest(float x, float y, float width, float height) |
|||
{ |
|||
var rect1 = new RectangleF(x, y, width, height); |
|||
var rect2 = new RectangleF(width, height, x, y); |
|||
|
|||
Assert.True(rect1 != rect2); |
|||
Assert.False(rect1 == rect2); |
|||
Assert.False(rect1.Equals(rect2)); |
|||
Assert.False(rect1.Equals((object)rect2)); |
|||
} |
|||
|
|||
[Fact] |
|||
public static void EqualityTestNotRectangleF() |
|||
{ |
|||
var rectangle = new RectangleF(0, 0, 0, 0); |
|||
Assert.False(rectangle.Equals(null)); |
|||
Assert.False(rectangle.Equals(0)); |
|||
|
|||
// If RectangleF implements IEquatable<RectangleF> (e.g. in .NET Core), then classes that are implicitly
|
|||
// convertible to RectangleF can potentially be equal.
|
|||
// See https://github.com/dotnet/corefx/issues/5255.
|
|||
bool expectsImplicitCastToRectangleF = typeof(IEquatable<RectangleF>).IsAssignableFrom(rectangle.GetType()); |
|||
Assert.Equal(expectsImplicitCastToRectangleF, rectangle.Equals(new Rectangle(0, 0, 0, 0))); |
|||
|
|||
Assert.False(rectangle.Equals((object)new Rectangle(0, 0, 0, 0))); // No implicit cast
|
|||
} |
|||
|
|||
[Fact] |
|||
public static void GetHashCodeTest() |
|||
{ |
|||
var rect1 = new RectangleF(10, 10, 10, 10); |
|||
var rect2 = new RectangleF(10, 10, 10, 10); |
|||
Assert.Equal(rect1.GetHashCode(), rect2.GetHashCode()); |
|||
Assert.NotEqual(rect1.GetHashCode(), new RectangleF(20, 10, 10, 10).GetHashCode()); |
|||
Assert.NotEqual(rect1.GetHashCode(), new RectangleF(10, 20, 10, 10).GetHashCode()); |
|||
Assert.NotEqual(rect1.GetHashCode(), new RectangleF(10, 10, 20, 10).GetHashCode()); |
|||
Assert.NotEqual(rect1.GetHashCode(), new RectangleF(10, 10, 10, 20).GetHashCode()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] |
|||
[InlineData(0, float.MinValue, float.MaxValue, 0)] |
|||
public void ContainsTest(float x, float y, float width, float height) |
|||
{ |
|||
var rect = new RectangleF(x, y, width, height); |
|||
float X = (x + width) / 2; |
|||
float Y = (y + height) / 2; |
|||
var p = new PointF(X, Y); |
|||
var r = new RectangleF(X, Y, width / 2, height / 2); |
|||
|
|||
Assert.False(rect.Contains(X, Y)); |
|||
Assert.False(rect.Contains(p)); |
|||
Assert.False(rect.Contains(r)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(float.MaxValue / 2, float.MinValue / 2, float.MinValue / 2, float.MaxValue / 2)] |
|||
[InlineData(0, float.MinValue, float.MaxValue, 0)] |
|||
public void InflateTest(float x, float y, float width, float height) |
|||
{ |
|||
var rect = new RectangleF(x, y, width, height); |
|||
var inflatedRect = new RectangleF(x - width, y - height, width + 2 * width, height + 2 * height); |
|||
|
|||
rect.Inflate(width, height); |
|||
Assert.Equal(inflatedRect, rect); |
|||
|
|||
var s = new SizeF(x, y); |
|||
inflatedRect = RectangleF.Inflate(rect, x, y); |
|||
|
|||
rect.Inflate(s); |
|||
Assert.Equal(inflatedRect, rect); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue, float.MaxValue / 2, float.MinValue / 2)] |
|||
[InlineData(0, float.MinValue, float.MaxValue, 0)] |
|||
public void IntersectTest(float x, float y, float width, float height) |
|||
{ |
|||
var rect1 = new RectangleF(x, y, width, height); |
|||
var rect2 = new RectangleF(y, x, width, height); |
|||
var expectedRect = RectangleF.Intersect(rect1, rect2); |
|||
rect1.Intersect(rect2); |
|||
Assert.Equal(expectedRect, rect1); |
|||
Assert.False(rect1.IntersectsWith(expectedRect)); |
|||
} |
|||
|
|||
[Fact] |
|||
public static void IntersectIntersectingRectsTest() |
|||
{ |
|||
var rect1 = new RectangleF(0, 0, 5, 5); |
|||
var rect2 = new RectangleF(1, 1, 3, 3); |
|||
var expected = new RectangleF(1, 1, 3, 3); |
|||
|
|||
Assert.Equal(expected, RectangleF.Intersect(rect1, rect2)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] |
|||
[InlineData(float.MaxValue, 0, 0, float.MaxValue)] |
|||
[InlineData(0, float.MinValue, float.MaxValue, 0)] |
|||
public void UnionTest(float x, float y, float width, float height) |
|||
{ |
|||
var a = new RectangleF(x, y, width, height); |
|||
var b = new RectangleF(width, height, x, y); |
|||
|
|||
float x1 = Math.Min(a.X, b.X); |
|||
float x2 = Math.Max(a.X + a.Width, b.X + b.Width); |
|||
float y1 = Math.Min(a.Y, b.Y); |
|||
float y2 = Math.Max(a.Y + a.Height, b.Y + b.Height); |
|||
|
|||
var expectedRectangle = new RectangleF(x1, y1, x2 - x1, y2 - y1); |
|||
|
|||
Assert.Equal(expectedRectangle, RectangleF.Union(a, b)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] |
|||
[InlineData(float.MaxValue, 0, 0, float.MaxValue)] |
|||
[InlineData(0, float.MinValue, float.MaxValue, 0)] |
|||
public void OffsetTest(float x, float y, float width, float height) |
|||
{ |
|||
var r1 = new RectangleF(x, y, width, height); |
|||
var expectedRect = new RectangleF(x + width, y + height, width, height); |
|||
var p = new PointF(width, height); |
|||
|
|||
r1.Offset(p); |
|||
Assert.Equal(expectedRect, r1); |
|||
|
|||
expectedRect.Offset(p); |
|||
r1.Offset(width, height); |
|||
Assert.Equal(expectedRect, r1); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringTest() |
|||
{ |
|||
var r = new RectangleF(5, 5.1F, 1.3F, 1); |
|||
Assert.Equal(string.Format(CultureInfo.CurrentCulture, "RectangleF [ X={0}, Y={1}, Width={2}, Height={3} ]", r.X, r.Y, r.Width, r.Height), r.ToString()); |
|||
} |
|||
|
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(5, -5, 0.2, -1.3)] |
|||
public void ToStringTestEmpty(float x, float y, float width, float height) |
|||
{ |
|||
var r = new RectangleF(x, y, width, height); |
|||
Assert.Equal("RectangleF [ Empty ]", r.ToString()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,308 @@ |
|||
// <copyright file="RectangleTests.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives.Tests |
|||
{ |
|||
using System; |
|||
using System.Globalization; |
|||
|
|||
using Xunit; |
|||
|
|||
/// <summary>
|
|||
/// Tests the <see cref="Rectangle"/> struct.
|
|||
/// </summary>
|
|||
public class RectangleTests |
|||
{ |
|||
[Fact] |
|||
public void DefaultConstructorTest() |
|||
{ |
|||
Assert.Equal(Rectangle.Empty, new Rectangle()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, 0, int.MinValue, 0)] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(0, int.MinValue, 0, int.MaxValue)] |
|||
public void NonDefaultConstructorTest(int x, int y, int width, int height) |
|||
{ |
|||
var rect1 = new Rectangle(x, y, width, height); |
|||
var rect2 = new Rectangle(new Point(x, y), new Size(width, height)); |
|||
|
|||
Assert.Equal(rect1, rect2); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, 0, int.MinValue, 0)] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(0, int.MinValue, 0, int.MaxValue)] |
|||
public void FromLTRBTest(int left, int top, int right, int bottom) |
|||
{ |
|||
var rect1 = new Rectangle(left, top, unchecked(right - left), unchecked(bottom - top)); |
|||
var rect2 = Rectangle.FromLTRB(left, top, right, bottom); |
|||
|
|||
Assert.Equal(rect1, rect2); |
|||
} |
|||
|
|||
[Fact] |
|||
public void EmptyTest() |
|||
{ |
|||
Assert.True(Rectangle.Empty.IsEmpty); |
|||
Assert.True(new Rectangle(0, 0, 0, 0).IsEmpty); |
|||
Assert.True(new Rectangle().IsEmpty); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, 0, int.MinValue, 0)] |
|||
[InlineData(int.MinValue, int.MaxValue, int.MinValue, int.MaxValue)] |
|||
[InlineData(0, int.MinValue, 0, int.MaxValue)] |
|||
public void NonEmptyTest(int x, int y, int width, int height) |
|||
{ |
|||
Assert.False(new Rectangle(x, y, width, height).IsEmpty); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, 0, int.MinValue, 0)] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(0, int.MinValue, 0, int.MaxValue)] |
|||
[InlineData(int.MinValue, int.MaxValue, int.MinValue, int.MaxValue)] |
|||
public void DimensionsTest(int x, int y, int width, int height) |
|||
{ |
|||
var rect = new Rectangle(x, y, width, height); |
|||
Assert.Equal(new Point(x, y), rect.Location); |
|||
Assert.Equal(new Size(width, height), rect.Size); |
|||
|
|||
Assert.Equal(x, rect.X); |
|||
Assert.Equal(y, rect.Y); |
|||
Assert.Equal(width, rect.Width); |
|||
Assert.Equal(height, rect.Height); |
|||
Assert.Equal(x, rect.Left); |
|||
Assert.Equal(y, rect.Top); |
|||
Assert.Equal(unchecked(x + width), rect.Right); |
|||
Assert.Equal(unchecked(y + height), rect.Bottom); |
|||
|
|||
var p = new Point(width, height); |
|||
var s = new Size(x, y); |
|||
rect.Location = p; |
|||
rect.Size = s; |
|||
|
|||
Assert.Equal(p, rect.Location); |
|||
Assert.Equal(s, rect.Size); |
|||
|
|||
Assert.Equal(width, rect.X); |
|||
Assert.Equal(height, rect.Y); |
|||
Assert.Equal(x, rect.Width); |
|||
Assert.Equal(y, rect.Height); |
|||
Assert.Equal(width, rect.Left); |
|||
Assert.Equal(height, rect.Top); |
|||
Assert.Equal(unchecked(x + width), rect.Right); |
|||
Assert.Equal(unchecked(y + height), rect.Bottom); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0)] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
public static void LocationSetTest(int x, int y) |
|||
{ |
|||
var point = new Point(x, y); |
|||
var rect = new Rectangle(10, 10, 10, 10) { Location = point }; |
|||
Assert.Equal(point, rect.Location); |
|||
Assert.Equal(point.X, rect.X); |
|||
Assert.Equal(point.Y, rect.Y); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0)] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
public static void SizeSetTest(int x, int y) |
|||
{ |
|||
var size = new Size(x, y); |
|||
var rect = new Rectangle(10, 10, 10, 10) { Size = size }; |
|||
Assert.Equal(size, rect.Size); |
|||
Assert.Equal(size.Width, rect.Width); |
|||
Assert.Equal(size.Height, rect.Height); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, 0, int.MinValue, 0)] |
|||
[InlineData(0, int.MinValue, 0, int.MaxValue)] |
|||
[InlineData(int.MinValue, int.MaxValue, int.MinValue, int.MaxValue)] |
|||
public void EqualityTest(int x, int y, int width, int height) |
|||
{ |
|||
var rect1 = new Rectangle(x, y, width, height); |
|||
var rect2 = new Rectangle(width / 2, height / 2, x, y); |
|||
|
|||
Assert.True(rect1 != rect2); |
|||
Assert.False(rect1 == rect2); |
|||
Assert.False(rect1.Equals(rect2)); |
|||
Assert.False(rect1.Equals((object)rect2)); |
|||
} |
|||
|
|||
[Fact] |
|||
public static void EqualityTestNotRectangle() |
|||
{ |
|||
var rectangle = new Rectangle(0, 0, 0, 0); |
|||
Assert.False(rectangle.Equals(null)); |
|||
Assert.False(rectangle.Equals(0)); |
|||
Assert.False(rectangle.Equals(new RectangleF(0, 0, 0, 0))); |
|||
} |
|||
|
|||
[Fact] |
|||
public static void GetHashCodeTest() |
|||
{ |
|||
var rect1 = new Rectangle(10, 10, 10, 10); |
|||
var rect2 = new Rectangle(10, 10, 10, 10); |
|||
Assert.Equal(rect1.GetHashCode(), rect2.GetHashCode()); |
|||
Assert.NotEqual(rect1.GetHashCode(), new Rectangle(20, 10, 10, 10).GetHashCode()); |
|||
Assert.NotEqual(rect1.GetHashCode(), new Rectangle(10, 20, 10, 10).GetHashCode()); |
|||
Assert.NotEqual(rect1.GetHashCode(), new Rectangle(10, 10, 20, 10).GetHashCode()); |
|||
Assert.NotEqual(rect1.GetHashCode(), new Rectangle(10, 10, 10, 20).GetHashCode()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue, float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MaxValue, float.MinValue, float.MaxValue)] |
|||
[InlineData(0, 0, 0, 0)] |
|||
public void RectangleFConversionTest(float x, float y, float width, float height) |
|||
{ |
|||
var rect = new RectangleF(x, y, width, height); |
|||
Rectangle rCeiling, rTruncate, rRound; |
|||
|
|||
unchecked |
|||
{ |
|||
rCeiling = new Rectangle((int)Math.Ceiling(x), (int)Math.Ceiling(y), |
|||
(int)Math.Ceiling(width), (int)Math.Ceiling(height)); |
|||
rTruncate = new Rectangle((int)x, (int)y, (int)width, (int)height); |
|||
rRound = new Rectangle((int)Math.Round(x), (int)Math.Round(y), |
|||
(int)Math.Round(width), (int)Math.Round(height)); |
|||
} |
|||
|
|||
Assert.Equal(rCeiling, Rectangle.Ceiling(rect)); |
|||
Assert.Equal(rTruncate, Rectangle.Truncate(rect)); |
|||
Assert.Equal(rRound, Rectangle.Round(rect)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] |
|||
[InlineData(0, int.MinValue, int.MaxValue, 0)] |
|||
public void ContainsTest(int x, int y, int width, int height) |
|||
{ |
|||
var rect = new Rectangle(unchecked(2 * x - width), unchecked(2 * y - height), width, height); |
|||
var p = new Point(x, y); |
|||
var r = new Rectangle(x, y, width / 2, height / 2); |
|||
|
|||
Assert.False(rect.Contains(x, y)); |
|||
Assert.False(rect.Contains(p)); |
|||
Assert.False(rect.Contains(r)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] |
|||
[InlineData(0, int.MinValue, int.MaxValue, 0)] |
|||
public void InflateTest(int x, int y, int width, int height) |
|||
{ |
|||
Rectangle inflatedRect, rect = new Rectangle(x, y, width, height); |
|||
unchecked |
|||
{ |
|||
inflatedRect = new Rectangle(x - width, y - height, width + 2 * width, height + 2 * height); |
|||
} |
|||
|
|||
Assert.Equal(inflatedRect, Rectangle.Inflate(rect, width, height)); |
|||
|
|||
rect.Inflate(width, height); |
|||
Assert.Equal(inflatedRect, rect); |
|||
|
|||
var s = new Size(x, y); |
|||
unchecked |
|||
{ |
|||
inflatedRect = new Rectangle(rect.X - x, rect.Y - y, rect.Width + 2 * x, rect.Height + 2 * y); |
|||
} |
|||
|
|||
rect.Inflate(s); |
|||
Assert.Equal(inflatedRect, rect); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] |
|||
[InlineData(0, int.MinValue, int.MaxValue, 0)] |
|||
public void IntersectTest(int x, int y, int width, int height) |
|||
{ |
|||
var rect = new Rectangle(x, y, width, height); |
|||
var expectedRect = Rectangle.Intersect(rect, rect); |
|||
rect.Intersect(rect); |
|||
Assert.Equal(expectedRect, rect); |
|||
Assert.False(rect.IntersectsWith(expectedRect)); |
|||
} |
|||
|
|||
[Fact] |
|||
public static void IntersectIntersectingRectsTest() |
|||
{ |
|||
var rect1 = new Rectangle(0, 0, 5, 5); |
|||
var rect2 = new Rectangle(1, 1, 3, 3); |
|||
var expected = new Rectangle(1, 1, 3, 3); |
|||
|
|||
Assert.Equal(expected, Rectangle.Intersect(rect1, rect2)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] |
|||
[InlineData(int.MaxValue, 0, 0, int.MaxValue)] |
|||
[InlineData(0, int.MinValue, int.MaxValue, 0)] |
|||
public void UnionTest(int x, int y, int width, int height) |
|||
{ |
|||
var a = new Rectangle(x, y, width, height); |
|||
var b = new Rectangle(width, height, x, y); |
|||
|
|||
int x1 = Math.Min(a.X, b.X); |
|||
int x2 = Math.Max(a.X + a.Width, b.X + b.Width); |
|||
int y1 = Math.Min(a.Y, b.Y); |
|||
int y2 = Math.Max(a.Y + a.Height, b.Y + b.Height); |
|||
|
|||
var expectedRectangle = new Rectangle(x1, y1, x2 - x1, y2 - y1); |
|||
|
|||
Assert.Equal(expectedRectangle, Rectangle.Union(a, b)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0, 0, 0, 0)] |
|||
[InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] |
|||
[InlineData(int.MaxValue, 0, 0, int.MaxValue)] |
|||
[InlineData(0, int.MinValue, int.MaxValue, 0)] |
|||
public void OffsetTest(int x, int y, int width, int height) |
|||
{ |
|||
var r1 = new Rectangle(x, y, width, height); |
|||
var expectedRect = new Rectangle(x + width, y + height, width, height); |
|||
var p = new Point(width, height); |
|||
|
|||
r1.Offset(p); |
|||
Assert.Equal(expectedRect, r1); |
|||
|
|||
expectedRect.Offset(p); |
|||
r1.Offset(width, height); |
|||
Assert.Equal(expectedRect, r1); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringTest() |
|||
{ |
|||
var r = new Rectangle(5, -5, 0, 1); |
|||
Assert.Equal(string.Format(CultureInfo.CurrentCulture, "Rectangle [ X={0}, Y={1}, Width={2}, Height={3} ]", r.X, r.Y, r.Width, r.Height), r.ToString()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringTestEmpty() |
|||
{ |
|||
var r = new Rectangle(0, 0, 0, 0); |
|||
Assert.Equal("Rectangle [ Empty ]", r.ToString()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,122 @@ |
|||
// <copyright file="RationalTests.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives.Tests |
|||
{ |
|||
using Xunit; |
|||
|
|||
/// <summary>
|
|||
/// Tests the <see cref="SignedRational"/> struct.
|
|||
/// </summary>
|
|||
public class SignedRationalTests |
|||
{ |
|||
/// <summary>
|
|||
/// Tests the equality operators for equality.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void AreEqual() |
|||
{ |
|||
SignedRational r1 = new SignedRational(3, 2); |
|||
SignedRational r2 = new SignedRational(3, 2); |
|||
|
|||
Assert.Equal(r1, r2); |
|||
Assert.True(r1 == r2); |
|||
|
|||
SignedRational r3 = new SignedRational(7.55); |
|||
SignedRational r4 = new SignedRational(755, 100); |
|||
SignedRational r5 = new SignedRational(151, 20); |
|||
|
|||
Assert.Equal(r3, r4); |
|||
Assert.Equal(r4, r5); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Tests the equality operators for inequality.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void AreNotEqual() |
|||
{ |
|||
SignedRational first = new SignedRational(0, 100); |
|||
SignedRational second = new SignedRational(100, 100); |
|||
|
|||
Assert.NotEqual(first, second); |
|||
Assert.True(first != second); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Tests whether the Rational constructor correctly assign properties.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void ConstructorAssignsProperties() |
|||
{ |
|||
SignedRational rational = new SignedRational(7, -55); |
|||
Assert.Equal(7, rational.Numerator); |
|||
Assert.Equal(-55, rational.Denominator); |
|||
|
|||
rational = new SignedRational(-755, 100); |
|||
Assert.Equal(-151, rational.Numerator); |
|||
Assert.Equal(20, rational.Denominator); |
|||
|
|||
rational = new SignedRational(-755, -100, false); |
|||
Assert.Equal(-755, rational.Numerator); |
|||
Assert.Equal(-100, rational.Denominator); |
|||
|
|||
rational = new SignedRational(-151, -20); |
|||
Assert.Equal(-151, rational.Numerator); |
|||
Assert.Equal(-20, rational.Denominator); |
|||
|
|||
rational = new SignedRational(-7.55); |
|||
Assert.Equal(-151, rational.Numerator); |
|||
Assert.Equal(20, rational.Denominator); |
|||
|
|||
rational = new SignedRational(7); |
|||
Assert.Equal(7, rational.Numerator); |
|||
Assert.Equal(1, rational.Denominator); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Fraction() |
|||
{ |
|||
SignedRational first = new SignedRational(1.0 / 1600); |
|||
SignedRational second = new SignedRational(1.0 / 1600, true); |
|||
Assert.False(first.Equals(second)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToDouble() |
|||
{ |
|||
SignedRational rational = new SignedRational(0, 0); |
|||
Assert.Equal(double.NaN, rational.ToDouble()); |
|||
|
|||
rational = new SignedRational(2, 0); |
|||
Assert.Equal(double.PositiveInfinity, rational.ToDouble()); |
|||
|
|||
rational = new SignedRational(-2, 0); |
|||
Assert.Equal(double.NegativeInfinity, rational.ToDouble()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringRepresention() |
|||
{ |
|||
SignedRational rational = new SignedRational(0, 0); |
|||
Assert.Equal("[ Indeterminate ]", rational.ToString()); |
|||
|
|||
rational = new SignedRational(double.PositiveInfinity); |
|||
Assert.Equal("[ PositiveInfinity ]", rational.ToString()); |
|||
|
|||
rational = new SignedRational(double.NegativeInfinity); |
|||
Assert.Equal("[ NegativeInfinity ]", rational.ToString()); |
|||
|
|||
rational = new SignedRational(0, 1); |
|||
Assert.Equal("0", rational.ToString()); |
|||
|
|||
rational = new SignedRational(2, 1); |
|||
Assert.Equal("2", rational.ToString()); |
|||
|
|||
rational = new SignedRational(1, 2); |
|||
Assert.Equal("1/2", rational.ToString()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<VersionPrefix>0.0.0</VersionPrefix> |
|||
<TargetFrameworks>netcoreapp1.1</TargetFrameworks> |
|||
<AssemblyName>SixLabors.Shapes.Tests</AssemblyName> |
|||
<PackageId>SixLabors.Shapes.Tests</PackageId> |
|||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> |
|||
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute> |
|||
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute> |
|||
<DebugType Condition="$(codecov) != ''">full</DebugType> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\SixLabors.Primitives\SixLabors.Primitives.csproj" /> |
|||
<ProjectReference Include="..\..\src\SixLabors.Shapes\SixLabors.Shapes.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" /> |
|||
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" /> |
|||
<PackageReference Include="xunit" Version="2.2.0" /> |
|||
<PackageReference Include="Moq" Version="4.7.1" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,163 @@ |
|||
// <copyright file="SizeTests.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives.Tests |
|||
{ |
|||
using System; |
|||
using System.Globalization; |
|||
using System.Reflection; |
|||
using Xunit; |
|||
|
|||
public class SizeFTests |
|||
{ |
|||
[Fact] |
|||
public void DefaultConstructorTest() |
|||
{ |
|||
Assert.Equal(SizeF.Empty, new SizeF()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MinValue)] |
|||
[InlineData(float.MaxValue, float.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void NonDefaultConstructorAndDimensionsTest(float width, float height) |
|||
{ |
|||
var s1 = new SizeF(width, height); |
|||
var p1 = new PointF(width, height); |
|||
var s2 = new SizeF(s1); |
|||
|
|||
Assert.Equal(s1, s2); |
|||
Assert.Equal(s1, new SizeF(p1)); |
|||
Assert.Equal(s2, new SizeF(p1)); |
|||
|
|||
Assert.Equal(width, s1.Width); |
|||
Assert.Equal(height, s1.Height); |
|||
|
|||
s1.Width = 10; |
|||
Assert.Equal(10, s1.Width); |
|||
|
|||
s1.Height = -10.123f; |
|||
Assert.Equal(-10.123, s1.Height, 3); |
|||
} |
|||
|
|||
[Fact] |
|||
public void IsEmptyDefaultsTest() |
|||
{ |
|||
Assert.True(SizeF.Empty.IsEmpty); |
|||
Assert.True(new SizeF().IsEmpty); |
|||
Assert.True(new SizeF(0, 0).IsEmpty); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MinValue)] |
|||
[InlineData(float.MaxValue, float.MaxValue)] |
|||
public void IsEmptyRandomTest(float width, float height) |
|||
{ |
|||
Assert.False(new SizeF(width, height).IsEmpty); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MinValue)] |
|||
[InlineData(float.MaxValue, float.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void ArithmeticTest(float width, float height) |
|||
{ |
|||
var s1 = new SizeF(width, height); |
|||
var s2 = new SizeF(height, width); |
|||
var addExpected = new SizeF(width + height, width + height); |
|||
var subExpected = new SizeF(width - height, height - width); |
|||
|
|||
Assert.Equal(addExpected, s1 + s2); |
|||
Assert.Equal(addExpected, SizeF.Add(s1, s2)); |
|||
|
|||
Assert.Equal(subExpected, s1 - s2); |
|||
Assert.Equal(subExpected, SizeF.Subtract(s1, s2)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MinValue)] |
|||
[InlineData(float.MaxValue, float.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void EqualityTest(float width, float height) |
|||
{ |
|||
var sLeft = new SizeF(width, height); |
|||
var sRight = new SizeF(height, width); |
|||
|
|||
if (width == height) |
|||
{ |
|||
Assert.True(sLeft == sRight); |
|||
Assert.False(sLeft != sRight); |
|||
Assert.True(sLeft.Equals(sRight)); |
|||
Assert.True(sLeft.Equals((object)sRight)); |
|||
Assert.Equal(sLeft.GetHashCode(), sRight.GetHashCode()); |
|||
return; |
|||
} |
|||
|
|||
Assert.True(sLeft != sRight); |
|||
Assert.False(sLeft == sRight); |
|||
Assert.False(sLeft.Equals(sRight)); |
|||
Assert.False(sLeft.Equals((object)sRight)); |
|||
} |
|||
|
|||
[Fact] |
|||
public static void EqualityTest_NotSizeF() |
|||
{ |
|||
var size = new SizeF(0, 0); |
|||
Assert.False(size.Equals(null)); |
|||
Assert.False(size.Equals(0)); |
|||
|
|||
// If SizeF implements IEquatable<SizeF> (e.g in .NET Core), then classes that are implicitly
|
|||
// convertible to SizeF can potentially be equal.
|
|||
// See https://github.com/dotnet/corefx/issues/5255.
|
|||
bool expectsImplicitCastToSizeF = typeof(IEquatable<SizeF>).IsAssignableFrom(size.GetType()); |
|||
Assert.Equal(expectsImplicitCastToSizeF, size.Equals(new Size(0, 0))); |
|||
|
|||
Assert.False(size.Equals((object)new Size(0, 0))); // No implicit cast
|
|||
} |
|||
|
|||
[Fact] |
|||
public static void GetHashCodeTest() |
|||
{ |
|||
var size = new SizeF(10, 10); |
|||
Assert.Equal(size.GetHashCode(), new SizeF(10, 10).GetHashCode()); |
|||
Assert.NotEqual(size.GetHashCode(), new SizeF(20, 10).GetHashCode()); |
|||
Assert.NotEqual(size.GetHashCode(), new SizeF(10, 20).GetHashCode()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MinValue)] |
|||
[InlineData(float.MaxValue, float.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void ConversionTest(float width, float height) |
|||
{ |
|||
var s1 = new SizeF(width, height); |
|||
var p1 = (PointF)s1; |
|||
var s2 = new Size(unchecked((int)width), unchecked((int)height)); |
|||
|
|||
Assert.Equal(new PointF(width, height), p1); |
|||
Assert.Equal(p1, (PointF)s1); |
|||
Assert.Equal(s2, (Size)s1); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringTest() |
|||
{ |
|||
var sz = new SizeF(10, 5); |
|||
Assert.Equal(string.Format(CultureInfo.CurrentCulture, "SizeF [ Width={0}, Height={1} ]", sz.Width, sz.Height), sz.ToString()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringTestEmpty() |
|||
{ |
|||
var sz = new SizeF(0, 0); |
|||
Assert.Equal("SizeF [ Empty ]", sz.ToString()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,195 @@ |
|||
// <copyright file="SizeTests.cs" company="Six Labors">
|
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace SixLabors.Primitives.Tests |
|||
{ |
|||
using System.Globalization; |
|||
using Xunit; |
|||
|
|||
/// <summary>
|
|||
/// Tests the <see cref="Size"/> struct.
|
|||
/// </summary>
|
|||
public class SizeTests |
|||
{ |
|||
[Fact] |
|||
public void DefaultConstructorTest() |
|||
{ |
|||
Assert.Equal(Size.Empty, new Size()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void NonDefaultConstructorTest(int width, int height) |
|||
{ |
|||
var s1 = new Size(width, height); |
|||
var s2 = new Size(new Point(width, height)); |
|||
|
|||
Assert.Equal(s1, s2); |
|||
|
|||
s1.Width = 10; |
|||
Assert.Equal(10, s1.Width); |
|||
|
|||
s1.Height = -10; |
|||
Assert.Equal(-10, s1.Height); |
|||
} |
|||
|
|||
[Fact] |
|||
public void IsEmptyDefaultsTest() |
|||
{ |
|||
Assert.True(Size.Empty.IsEmpty); |
|||
Assert.True(new Size().IsEmpty); |
|||
Assert.True(new Size(0, 0).IsEmpty); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
public void IsEmptyRandomTest(int width, int height) |
|||
{ |
|||
Assert.False(new Size(width, height).IsEmpty); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void DimensionsTest(int width, int height) |
|||
{ |
|||
var p = new Size(width, height); |
|||
Assert.Equal(width, p.Width); |
|||
Assert.Equal(height, p.Height); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void PointFConversionTest(int width, int height) |
|||
{ |
|||
SizeF sz = new Size(width, height); |
|||
Assert.Equal(new SizeF(width, height), sz); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void SizeConversionTest(int width, int height) |
|||
{ |
|||
var sz = (Point)new Size(width, height); |
|||
Assert.Equal(new Point(width, height), sz); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void ArithmeticTest(int width, int height) |
|||
{ |
|||
var sz1 = new Size(width, height); |
|||
var sz2 = new Size(height, width); |
|||
Size addExpected, subExpected; |
|||
|
|||
unchecked |
|||
{ |
|||
addExpected = new Size(width + height, height + width); |
|||
subExpected = new Size(width - height, height - width); |
|||
} |
|||
|
|||
Assert.Equal(addExpected, sz1 + sz2); |
|||
Assert.Equal(subExpected, sz1 - sz2); |
|||
Assert.Equal(addExpected, Size.Add(sz1, sz2)); |
|||
Assert.Equal(subExpected, Size.Subtract(sz1, sz2)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(float.MaxValue, float.MinValue)] |
|||
[InlineData(float.MinValue, float.MinValue)] |
|||
[InlineData(float.MaxValue, float.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void PointFMathematicalTest(float width, float height) |
|||
{ |
|||
var szF = new SizeF(width, height); |
|||
Size pCeiling, pTruncate, pRound; |
|||
|
|||
unchecked |
|||
{ |
|||
pCeiling = new Size((int)MathF.Ceiling(width), (int)MathF.Ceiling(height)); |
|||
pTruncate = new Size((int)width, (int)height); |
|||
pRound = new Size((int)MathF.Round(width), (int)MathF.Round(height)); |
|||
} |
|||
|
|||
Assert.Equal(pCeiling, Size.Ceiling(szF)); |
|||
Assert.Equal(pRound, Size.Round(szF)); |
|||
Assert.Equal(pTruncate, (Size)szF); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(int.MaxValue, int.MinValue)] |
|||
[InlineData(int.MinValue, int.MinValue)] |
|||
[InlineData(int.MaxValue, int.MaxValue)] |
|||
[InlineData(0, 0)] |
|||
public void EqualityTest(int width, int height) |
|||
{ |
|||
var p1 = new Size(width, height); |
|||
var p2 = new Size(unchecked(width - 1), unchecked(height - 1)); |
|||
var p3 = new Size(width, height); |
|||
|
|||
Assert.True(p1 == p3); |
|||
Assert.True(p1 != p2); |
|||
Assert.True(p2 != p3); |
|||
|
|||
Assert.True(p1.Equals(p3)); |
|||
Assert.False(p1.Equals(p2)); |
|||
Assert.False(p2.Equals(p3)); |
|||
|
|||
Assert.True(p1.Equals((object)p3)); |
|||
Assert.False(p1.Equals((object)p2)); |
|||
Assert.False(p2.Equals((object)p3)); |
|||
|
|||
Assert.Equal(p1.GetHashCode(), p3.GetHashCode()); |
|||
} |
|||
|
|||
[Fact] |
|||
public static void EqualityTest_NotSize() |
|||
{ |
|||
var size = new Size(0, 0); |
|||
Assert.False(size.Equals(null)); |
|||
Assert.False(size.Equals(0)); |
|||
Assert.False(size.Equals(new SizeF(0, 0))); |
|||
} |
|||
|
|||
[Fact] |
|||
public static void GetHashCodeTest() |
|||
{ |
|||
var size = new Size(10, 10); |
|||
Assert.Equal(size.GetHashCode(), new Size(10, 10).GetHashCode()); |
|||
Assert.NotEqual(size.GetHashCode(), new Size(20, 10).GetHashCode()); |
|||
Assert.NotEqual(size.GetHashCode(), new Size(10, 20).GetHashCode()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringTest() |
|||
{ |
|||
var sz = new Size(10, 5); |
|||
Assert.Equal(string.Format(CultureInfo.CurrentCulture, "Size [ Width={0}, Height={1} ]", sz.Width, sz.Height), sz.ToString()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToStringTestEmpty() |
|||
{ |
|||
var sz = new Size(0, 0); |
|||
Assert.Equal("Size [ Empty ]", sz.ToString()); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue