binding/SkiaSharp/MathTypes.cs (560 lines of code) (raw):
#nullable disable
using System;
using System.Numerics;
namespace SkiaSharp
{
public partial struct SKPoint
{
public static readonly SKPoint Empty;
public SKPoint (float x, float y)
{
this.x = x;
this.y = y;
}
public readonly bool IsEmpty => this == Empty;
public readonly float Length => (float)Math.Sqrt (x * x + y * y);
public readonly float LengthSquared => x * x + y * y;
public void Offset (SKPoint p)
{
x += p.x;
y += p.y;
}
public void Offset (float dx, float dy)
{
x += dx;
y += dy;
}
public readonly override string ToString () => $"{{X={x}, Y={y}}}";
public static SKPoint Normalize (SKPoint point)
{
var ls = point.x * point.x + point.y * point.y;
var invNorm = 1.0 / Math.Sqrt (ls);
return new SKPoint ((float)(point.x * invNorm), (float)(point.y * invNorm));
}
public static float Distance (SKPoint point, SKPoint other)
{
var dx = point.x - other.x;
var dy = point.y - other.y;
var ls = dx * dx + dy * dy;
return (float)Math.Sqrt (ls);
}
public static float DistanceSquared (SKPoint point, SKPoint other)
{
var dx = point.x - other.x;
var dy = point.y - other.y;
return dx * dx + dy * dy;
}
public static SKPoint Reflect (SKPoint point, SKPoint normal)
{
var dot = point.x * point.x + point.y * point.y;
return new SKPoint (
point.x - 2.0f * dot * normal.x,
point.y - 2.0f * dot * normal.y);
}
public static SKPoint Add (SKPoint pt, SKSizeI sz) => pt + sz;
public static SKPoint Add (SKPoint pt, SKSize sz) => pt + sz;
public static SKPoint Add (SKPoint pt, SKPointI sz) => pt + sz;
public static SKPoint Add (SKPoint pt, SKPoint sz) => pt + sz;
public static SKPoint Subtract (SKPoint pt, SKSizeI sz) => pt - sz;
public static SKPoint Subtract (SKPoint pt, SKSize sz) => pt - sz;
public static SKPoint Subtract (SKPoint pt, SKPointI sz) => pt - sz;
public static SKPoint Subtract (SKPoint pt, SKPoint sz) => pt - sz;
public static SKPoint operator + (SKPoint pt, SKSizeI sz) =>
new SKPoint (pt.x + sz.Width, pt.y + sz.Height);
public static SKPoint operator + (SKPoint pt, SKSize sz) =>
new SKPoint (pt.x + sz.Width, pt.y + sz.Height);
public static SKPoint operator + (SKPoint pt, SKPointI sz) =>
new SKPoint (pt.x + sz.X, pt.y + sz.Y);
public static SKPoint operator + (SKPoint pt, SKPoint sz) =>
new SKPoint (pt.x + sz.X, pt.y + sz.Y);
public static SKPoint operator - (SKPoint pt, SKSizeI sz) =>
new SKPoint (pt.X - sz.Width, pt.Y - sz.Height);
public static SKPoint operator - (SKPoint pt, SKSize sz) =>
new SKPoint (pt.X - sz.Width, pt.Y - sz.Height);
public static SKPoint operator - (SKPoint pt, SKPointI sz) =>
new SKPoint (pt.X - sz.X, pt.Y - sz.Y);
public static SKPoint operator - (SKPoint pt, SKPoint sz) =>
new SKPoint (pt.X - sz.X, pt.Y - sz.Y);
public static implicit operator Vector2 (SKPoint point) =>
new Vector2 (point.x, point.y);
public static implicit operator SKPoint (Vector2 vector) =>
new SKPoint (vector.X, vector.Y);
}
public partial struct SKPointI
{
public static readonly SKPointI Empty;
public SKPointI (SKSizeI sz)
{
x = sz.Width;
y = sz.Height;
}
public SKPointI (int x, int y)
{
this.x = x;
this.y = y;
}
public readonly bool IsEmpty => this == Empty;
public readonly int Length => (int)Math.Sqrt (x * x + y * y);
public readonly int LengthSquared => x * x + y * y;
public void Offset (SKPointI p)
{
x += p.X;
y += p.Y;
}
public void Offset (int dx, int dy)
{
x += dx;
y += dy;
}
public readonly override string ToString () => $"{{X={x},Y={y}}}";
public static SKPointI Normalize (SKPointI point)
{
var ls = point.x * point.x + point.y * point.y;
var invNorm = 1.0 / Math.Sqrt (ls);
return new SKPointI ((int)(point.x * invNorm), (int)(point.y * invNorm));
}
public static float Distance (SKPointI point, SKPointI other)
{
var dx = point.x - other.x;
var dy = point.y - other.y;
var ls = dx * dx + dy * dy;
return (float)Math.Sqrt (ls);
}
public static float DistanceSquared (SKPointI point, SKPointI other)
{
var dx = point.x - other.x;
var dy = point.y - other.y;
return dx * dx + dy * dy;
}
public static SKPointI Reflect (SKPointI point, SKPointI normal)
{
var dot = point.x * point.x + point.y * point.y;
return new SKPointI (
(int)(point.x - 2.0f * dot * normal.x),
(int)(point.y - 2.0f * dot * normal.y));
}
public static SKPointI Ceiling (SKPoint value)
{
int x, y;
checked {
x = (int)Math.Ceiling (value.X);
y = (int)Math.Ceiling (value.Y);
}
return new SKPointI (x, y);
}
public static SKPointI Round (SKPoint value)
{
int x, y;
checked {
x = (int)Math.Round (value.X);
y = (int)Math.Round (value.Y);
}
return new SKPointI (x, y);
}
public static SKPointI Truncate (SKPoint value)
{
int x, y;
checked {
x = (int)value.X;
y = (int)value.Y;
}
return new SKPointI (x, y);
}
public static SKPointI Add (SKPointI pt, SKSizeI sz) => pt + sz;
public static SKPointI Add (SKPointI pt, SKPointI sz) => pt + sz;
public static SKPointI Subtract (SKPointI pt, SKSizeI sz) => pt - sz;
public static SKPointI Subtract (SKPointI pt, SKPointI sz) => pt - sz;
public static SKPointI operator + (SKPointI pt, SKSizeI sz) =>
new SKPointI (pt.X + sz.Width, pt.Y + sz.Height);
public static SKPointI operator + (SKPointI pt, SKPointI sz) =>
new SKPointI (pt.X + sz.X, pt.Y + sz.Y);
public static SKPointI operator - (SKPointI pt, SKSizeI sz) =>
new SKPointI (pt.X - sz.Width, pt.Y - sz.Height);
public static SKPointI operator - (SKPointI pt, SKPointI sz) =>
new SKPointI (pt.X - sz.X, pt.Y - sz.Y);
public static explicit operator SKSizeI (SKPointI p) =>
new SKSizeI (p.X, p.Y);
public static implicit operator SKPoint (SKPointI p) =>
new SKPoint (p.X, p.Y);
public static implicit operator Vector2 (SKPointI point) =>
new Vector2 (point.x, point.y);
}
public partial struct SKPoint3
{
public static readonly SKPoint3 Empty;
public SKPoint3 (float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
public readonly bool IsEmpty => this == Empty;
public readonly override string ToString () => $"{{X={x}, Y={y}, Z={z}}}";
public static SKPoint3 Add (SKPoint3 pt, SKPoint3 sz) => pt + sz;
public static SKPoint3 Subtract (SKPoint3 pt, SKPoint3 sz) => pt - sz;
public static SKPoint3 operator + (SKPoint3 pt, SKPoint3 sz) =>
new SKPoint3 (pt.X + sz.X, pt.Y + sz.Y, pt.Z + sz.Z);
public static SKPoint3 operator - (SKPoint3 pt, SKPoint3 sz) =>
new SKPoint3 (pt.X - sz.X, pt.Y - sz.Y, pt.Z - sz.Z);
public static implicit operator Vector3 (SKPoint3 point) =>
new Vector3 (point.x, point.y, point.z);
public static implicit operator SKPoint3 (Vector3 vector) =>
new SKPoint3 (vector.X, vector.Y, vector.Z);
}
public partial struct SKSize
{
public static readonly SKSize Empty;
public SKSize (float width, float height)
{
w = width;
h = height;
}
public SKSize (SKPoint pt)
{
w = pt.X;
h = pt.Y;
}
public readonly bool IsEmpty => this == Empty;
public readonly SKPoint ToPoint () =>
new SKPoint (w, h);
public readonly SKSizeI ToSizeI ()
{
int w, h;
checked {
w = (int)this.w;
h = (int)this.h;
}
return new SKSizeI (w, h);
}
public readonly override string ToString () =>
$"{{Width={w}, Height={h}}}";
public static SKSize Add (SKSize sz1, SKSize sz2) => sz1 + sz2;
public static SKSize Subtract (SKSize sz1, SKSize sz2) => sz1 - sz2;
public static SKSize operator + (SKSize sz1, SKSize sz2) =>
new SKSize (sz1.Width + sz2.Width, sz1.Height + sz2.Height);
public static SKSize operator - (SKSize sz1, SKSize sz2) =>
new SKSize (sz1.Width - sz2.Width, sz1.Height - sz2.Height);
public static explicit operator SKPoint (SKSize size) =>
new SKPoint (size.Width, size.Height);
public static implicit operator SKSize (SKSizeI size) =>
new SKSize (size.Width, size.Height);
}
public partial struct SKSizeI
{
public static readonly SKSizeI Empty;
public SKSizeI (int width, int height)
{
w = width;
h = height;
}
public SKSizeI (SKPointI pt)
{
w = pt.X;
h = pt.Y;
}
public readonly bool IsEmpty => this == Empty;
public readonly SKPointI ToPointI () => new SKPointI (w, h);
public readonly override string ToString () =>
$"{{Width={w}, Height={h}}}";
public static SKSizeI Add (SKSizeI sz1, SKSizeI sz2) => sz1 + sz2;
public static SKSizeI Subtract (SKSizeI sz1, SKSizeI sz2) => sz1 - sz2;
public static SKSizeI operator + (SKSizeI sz1, SKSizeI sz2) =>
new SKSizeI (sz1.Width + sz2.Width, sz1.Height + sz2.Height);
public static SKSizeI operator - (SKSizeI sz1, SKSizeI sz2) =>
new SKSizeI (sz1.Width - sz2.Width, sz1.Height - sz2.Height);
public static explicit operator SKPointI (SKSizeI size) =>
new SKPointI (size.Width, size.Height);
}
public partial struct SKRect
{
public static readonly SKRect Empty;
public SKRect (float left, float top, float right, float bottom)
{
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
}
public readonly float MidX => left + (Width / 2f);
public readonly float MidY => top + (Height / 2f);
public readonly float Width => right - left;
public readonly float Height => bottom - top;
public readonly bool IsEmpty => this == Empty;
public SKSize Size {
readonly get => new SKSize (Width, Height);
set {
right = left + value.Width;
bottom = top + value.Height;
}
}
public SKPoint Location {
readonly get => new SKPoint (left, top);
set => this = SKRect.Create (value, Size);
}
public readonly SKRect Standardized {
get {
if (left > right) {
if (top > bottom) {
return new SKRect (right, bottom, left, top);
} else {
return new SKRect (right, top, left, bottom);
}
} else {
if (top > bottom) {
return new SKRect (left, bottom, right, top);
} else {
return new SKRect (left, top, right, bottom);
}
}
}
}
public readonly SKRect AspectFit (SKSize size) => AspectResize (size, true);
public readonly SKRect AspectFill (SKSize size) => AspectResize (size, false);
private readonly SKRect AspectResize (SKSize size, bool fit)
{
if (size.Width == 0 || size.Height == 0 || Width == 0 || Height == 0)
return Create (MidX, MidY, 0, 0);
var aspectWidth = size.Width;
var aspectHeight = size.Height;
var imgAspect = aspectWidth / aspectHeight;
var fullRectAspect = Width / Height;
var compare = fit ? (fullRectAspect > imgAspect) : (fullRectAspect < imgAspect);
if (compare) {
aspectHeight = Height;
aspectWidth = aspectHeight * imgAspect;
} else {
aspectWidth = Width;
aspectHeight = aspectWidth / imgAspect;
}
var aspectLeft = MidX - (aspectWidth / 2f);
var aspectTop = MidY - (aspectHeight / 2f);
return Create (aspectLeft, aspectTop, aspectWidth, aspectHeight);
}
public static SKRect Inflate (SKRect rect, float x, float y)
{
var r = new SKRect (rect.left, rect.top, rect.right, rect.bottom);
r.Inflate (x, y);
return r;
}
public void Inflate (SKSize size) =>
Inflate (size.Width, size.Height);
public void Inflate (float x, float y)
{
left -= x;
top -= y;
right += x;
bottom += y;
}
public static SKRect Intersect (SKRect a, SKRect b)
{
if (!a.IntersectsWithInclusive (b)) {
return Empty;
}
return new SKRect (
Math.Max (a.left, b.left),
Math.Max (a.top, b.top),
Math.Min (a.right, b.right),
Math.Min (a.bottom, b.bottom));
}
public void Intersect (SKRect rect) =>
this = Intersect (this, rect);
public static SKRect Union (SKRect a, SKRect b) =>
new SKRect (
Math.Min (a.left, b.left),
Math.Min (a.top, b.top),
Math.Max (a.right, b.right),
Math.Max (a.bottom, b.bottom));
public void Union (SKRect rect) =>
this = Union (this, rect);
public static implicit operator SKRect (SKRectI r) =>
new SKRect (r.Left, r.Top, r.Right, r.Bottom);
public readonly bool Contains (float x, float y) =>
(x >= left) && (x < right) && (y >= top) && (y < bottom);
public readonly bool Contains (SKPoint pt) =>
Contains (pt.X, pt.Y);
public readonly bool Contains (SKRect rect) =>
(left <= rect.left) && (right >= rect.right) &&
(top <= rect.top) && (bottom >= rect.bottom);
public readonly bool IntersectsWith (SKRect rect) =>
(left < rect.right) && (right > rect.left) && (top < rect.bottom) && (bottom > rect.top);
public readonly bool IntersectsWithInclusive (SKRect rect) =>
(left <= rect.right) && (right >= rect.left) && (top <= rect.bottom) && (bottom >= rect.top);
public void Offset (float x, float y)
{
left += x;
top += y;
right += x;
bottom += y;
}
public void Offset (SKPoint pos) => Offset (pos.X, pos.Y);
public readonly override string ToString () =>
$"{{Left={Left},Top={Top},Width={Width},Height={Height}}}";
public static SKRect Create (SKPoint location, SKSize size) =>
Create (location.X, location.Y, size.Width, size.Height);
public static SKRect Create (SKSize size) =>
Create (SKPoint.Empty, size);
public static SKRect Create (float width, float height) =>
new SKRect (SKPoint.Empty.X, SKPoint.Empty.Y, width, height);
public static SKRect Create (float x, float y, float width, float height) =>
new SKRect (x, y, x + width, y + height);
}
public partial struct SKRectI
{
public static readonly SKRectI Empty;
public SKRectI (int left, int top, int right, int bottom)
{
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
}
public readonly int MidX => left + (Width / 2);
public readonly int MidY => top + (Height / 2);
public readonly int Width => right - left;
public readonly int Height => bottom - top;
public readonly bool IsEmpty => this == Empty;
public SKSizeI Size {
readonly get => new SKSizeI (Width, Height);
set {
right = left + value.Width;
bottom = top + value.Height;
}
}
public SKPointI Location {
readonly get => new SKPointI (left, top);
set => this = SKRectI.Create (value, Size);
}
public readonly SKRectI Standardized {
get {
if (left > right) {
if (top > bottom) {
return new SKRectI (right, bottom, left, top);
} else {
return new SKRectI (right, top, left, bottom);
}
} else {
if (top > bottom) {
return new SKRectI (left, bottom, right, top);
} else {
return new SKRectI (left, top, right, bottom);
}
}
}
}
public readonly SKRectI AspectFit (SKSizeI size) =>
Floor (((SKRect)this).AspectFit (size));
public readonly SKRectI AspectFill (SKSizeI size) =>
Floor (((SKRect)this).AspectFill (size));
public static SKRectI Ceiling (SKRect value) =>
Ceiling (value, false);
public static SKRectI Ceiling (SKRect value, bool outwards)
{
int x, y, r, b;
checked {
x = (int)(outwards && value.Width > 0 ? Math.Floor (value.Left) : Math.Ceiling (value.Left));
y = (int)(outwards && value.Height > 0 ? Math.Floor (value.Top) : Math.Ceiling (value.Top));
r = (int)(outwards && value.Width < 0 ? Math.Floor (value.Right) : Math.Ceiling (value.Right));
b = (int)(outwards && value.Height < 0 ? Math.Floor (value.Bottom) : Math.Ceiling (value.Bottom));
}
return new SKRectI (x, y, r, b);
}
public static SKRectI Inflate (SKRectI rect, int x, int y)
{
var r = new SKRectI (rect.left, rect.top, rect.right, rect.bottom);
r.Inflate (x, y);
return r;
}
public void Inflate (SKSizeI size) =>
Inflate (size.Width, size.Height);
public void Inflate (int width, int height)
{
left -= width;
top -= height;
right += width;
bottom += height;
}
public static SKRectI Intersect (SKRectI a, SKRectI b)
{
if (!a.IntersectsWithInclusive (b))
return Empty;
return new SKRectI (
Math.Max (a.left, b.left),
Math.Max (a.top, b.top),
Math.Min (a.right, b.right),
Math.Min (a.bottom, b.bottom));
}
public void Intersect (SKRectI rect) =>
this = Intersect (this, rect);
public static SKRectI Round (SKRect value)
{
int x, y, r, b;
checked {
x = (int)Math.Round (value.Left);
y = (int)Math.Round (value.Top);
r = (int)Math.Round (value.Right);
b = (int)Math.Round (value.Bottom);
}
return new SKRectI (x, y, r, b);
}
public static SKRectI Floor (SKRect value) => Floor (value, false);
public static SKRectI Floor (SKRect value, bool inwards)
{
int x, y, r, b;
checked {
x = (int)(inwards && value.Width > 0 ? Math.Ceiling (value.Left) : Math.Floor (value.Left));
y = (int)(inwards && value.Height > 0 ? Math.Ceiling (value.Top) : Math.Floor (value.Top));
r = (int)(inwards && value.Width < 0 ? Math.Ceiling (value.Right) : Math.Floor (value.Right));
b = (int)(inwards && value.Height < 0 ? Math.Ceiling (value.Bottom) : Math.Floor (value.Bottom));
}
return new SKRectI (x, y, r, b);
}
public static SKRectI Truncate (SKRect value)
{
int x, y, r, b;
checked {
x = (int)value.Left;
y = (int)value.Top;
r = (int)value.Right;
b = (int)value.Bottom;
}
return new SKRectI (x, y, r, b);
}
public static SKRectI Union (SKRectI a, SKRectI b) =>
new SKRectI (
Math.Min (a.Left, b.Left),
Math.Min (a.Top, b.Top),
Math.Max (a.Right, b.Right),
Math.Max (a.Bottom, b.Bottom));
public void Union (SKRectI rect) =>
this = Union (this, rect);
public readonly bool Contains (int x, int y) =>
(x >= left) && (x < right) && (y >= top) && (y < bottom);
public readonly bool Contains (SKPointI pt) =>
Contains (pt.X, pt.Y);
public readonly bool Contains (SKRectI rect) =>
(left <= rect.left) && (right >= rect.right) &&
(top <= rect.top) && (bottom >= rect.bottom);
public readonly bool IntersectsWith (SKRectI rect) =>
(left < rect.right) && (right > rect.left) && (top < rect.bottom) && (bottom > rect.top);
public readonly bool IntersectsWithInclusive (SKRectI rect) =>
(left <= rect.right) && (right >= rect.left) && (top <= rect.bottom) && (bottom >= rect.top);
public void Offset (int x, int y)
{
left += x;
top += y;
right += x;
bottom += y;
}
public void Offset (SKPointI pos) => Offset (pos.X, pos.Y);
public readonly override string ToString () =>
$"{{Left={Left},Top={Top},Width={Width},Height={Height}}}";
public static SKRectI Create (SKSizeI size) =>
Create (SKPointI.Empty.X, SKPointI.Empty.Y, size.Width, size.Height);
public static SKRectI Create (SKPointI location, SKSizeI size) =>
Create (location.X, location.Y, size.Width, size.Height);
public static SKRectI Create (int width, int height) =>
new SKRectI (SKPointI.Empty.X, SKPointI.Empty.X, width, height);
public static SKRectI Create (int x, int y, int width, int height) =>
new SKRectI (x, y, x + width, y + height);
}
}