123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- using System;
- using System.Drawing;
- namespace PaintDotNet
- {
- /// <summary>
- /// 封装了缩放坐标的功能
- /// </summary>
- public struct ScaleFactor
- {
- /// <summary>
- /// 分母
- /// </summary>
- private int denominator;
- /// <summary>
- /// 分子
- /// </summary>
- private int numerator;
- public int Denominator
- {
- get
- {
- return denominator;
- }
- }
- public int Numerator
- {
- get
- {
- return numerator;
- }
- }
- /// <summary>
- /// 缩放比例
- /// </summary>
- public double Ratio
- {
- get
- {
- return (double)numerator / (double)denominator;
- }
- }
- public static readonly ScaleFactor OneToOne = new ScaleFactor(1, 1);
- public static readonly ScaleFactor MinValue = new ScaleFactor(1, 100);
- public static readonly ScaleFactor MaxValue = new ScaleFactor(32, 1);
- private void Clamp()
- {
- if (this < MinValue)
- {
- this = MinValue;
- }
- else if (this > MaxValue)
- {
- this = MaxValue;
- }
- }
- public static ScaleFactor UseIfValid(int numerator, int denominator, ScaleFactor lastResort)
- {
- if (numerator <= 0 || denominator <= 0)
- {
- return lastResort;
- }
- else
- {
- return new ScaleFactor(numerator, denominator);
- }
- }
- public static ScaleFactor Min(int n1, int d1, int n2, int d2, ScaleFactor lastResort)
- {
- ScaleFactor a = UseIfValid(n1, d1, lastResort);
- ScaleFactor b = UseIfValid(n2, d2, lastResort);
- return ScaleFactor.Min(a, b);
- }
- public static ScaleFactor Max(int n1, int d1, int n2, int d2, ScaleFactor lastResort)
- {
- ScaleFactor a = UseIfValid(n1, d1, lastResort);
- ScaleFactor b = UseIfValid(n2, d2, lastResort);
- return ScaleFactor.Max(a, b);
- }
- public static ScaleFactor Min(ScaleFactor lhs, ScaleFactor rhs)
- {
- if (lhs < rhs)
- {
- return lhs;
- }
- else
- {
- return rhs;
- }
- }
- public static ScaleFactor Max(ScaleFactor lhs, ScaleFactor rhs)
- {
- if (lhs > rhs)
- {
- return lhs;
- }
- else
- {
- return lhs;
- }
- }
- public static bool operator ==(ScaleFactor lhs, ScaleFactor rhs)
- {
- return (lhs.numerator * rhs.denominator) == (rhs.numerator * lhs.denominator);
- }
- public static bool operator !=(ScaleFactor lhs, ScaleFactor rhs)
- {
- return !(lhs == rhs);
- }
- public static bool operator <(ScaleFactor lhs, ScaleFactor rhs)
- {
- return (lhs.numerator * rhs.denominator) < (rhs.numerator * lhs.denominator);
- }
- public static bool operator <=(ScaleFactor lhs, ScaleFactor rhs)
- {
- return (lhs.numerator * rhs.denominator) <= (rhs.numerator * lhs.denominator);
- }
- public static bool operator >(ScaleFactor lhs, ScaleFactor rhs)
- {
- return (lhs.numerator * rhs.denominator) > (rhs.numerator * lhs.denominator);
- }
- public static bool operator >=(ScaleFactor lhs, ScaleFactor rhs)
- {
- return (lhs.numerator * rhs.denominator) >= (rhs.numerator * lhs.denominator);
- }
- public override bool Equals(object obj)
- {
- if (obj is ScaleFactor)
- {
- ScaleFactor rhs = (ScaleFactor)obj;
- return this == rhs;
- }
- else
- {
- return false;
- }
- }
- public override int GetHashCode()
- {
- return numerator.GetHashCode() ^ denominator.GetHashCode();
- }
- public override string ToString()
- {
- try
- {
- var percentageFormat = PdnResources.GetString("ScaleFactor.Percentage.Format");
- return string.Format(percentageFormat, unchecked(Math.Round(unchecked(100 * Ratio))));
- }
- catch (ArithmeticException)
- {
- return "--";
- }
- }
- public int ScaleScalar(int x)
- {
- return (int)(((long)x * numerator) / denominator);
- }
- public int UnscaleScalar(int x)
- {
- return (int)(((long)x * denominator) / numerator);
- }
- public float ScaleScalar(float x)
- {
- return (x * (float)numerator) / (float)denominator;
- }
- public float UnscaleScalar(float x)
- {
- return (x * (float)denominator) / (float)numerator;
- }
- public double ScaleScalar(double x)
- {
- return (x * (double)numerator) / (double)denominator;
- }
- public double UnscaleScalar(double x)
- {
- return (x * (double)denominator) / (double)numerator;
- }
- public Point ScalePoint(Point p)
- {
- return new Point(ScaleScalar(p.X), ScaleScalar(p.Y));
- }
- public PointF ScalePoint(PointF p)
- {
- return new PointF(ScaleScalar(p.X), ScaleScalar(p.Y));
- }
- public PointF ScalePointJustX(PointF p)
- {
- return new PointF(ScaleScalar(p.X), p.Y);
- }
- public PointF ScalePointJustY(PointF p)
- {
- return new PointF(p.X, ScaleScalar(p.Y));
- }
- public PointF UnscalePoint(PointF p)
- {
- return new PointF(UnscaleScalar(p.X), UnscaleScalar(p.Y));
- }
- public PointF UnscalePointJustX(PointF p)
- {
- return new PointF(UnscaleScalar(p.X), p.Y);
- }
- public PointF UnscalePointJustY(PointF p)
- {
- return new PointF(p.X, UnscaleScalar(p.Y));
- }
- public Point ScalePointJustX(Point p)
- {
- return new Point(ScaleScalar(p.X), p.Y);
- }
- public Point ScalePointJustY(Point p)
- {
- return new Point(p.X, ScaleScalar(p.Y));
- }
- public Point UnscalePoint(Point p)
- {
- return new Point(UnscaleScalar(p.X), UnscaleScalar(p.Y));
- }
- public Point UnscalePointJustX(Point p)
- {
- return new Point(UnscaleScalar(p.X), p.Y);
- }
- public Point UnscalePointJustY(Point p)
- {
- return new Point(p.X, UnscaleScalar(p.Y));
- }
- public SizeF ScaleSize(SizeF s)
- {
- return new SizeF(ScaleScalar(s.Width), ScaleScalar(s.Height));
- }
- public SizeF UnscaleSize(SizeF s)
- {
- return new SizeF(UnscaleScalar(s.Width), UnscaleScalar(s.Height));
- }
- public Size ScaleSize(Size s)
- {
- return new Size(ScaleScalar(s.Width), ScaleScalar(s.Height));
- }
- public Size UnscaleSize(Size s)
- {
- return new Size(UnscaleScalar(s.Width), UnscaleScalar(s.Height));
- }
- public RectangleF ScaleRectangle(RectangleF rectF)
- {
- return new RectangleF(ScalePoint(rectF.Location), ScaleSize(rectF.Size));
- }
- public RectangleF UnscaleRectangle(RectangleF rectF)
- {
- return new RectangleF(UnscalePoint(rectF.Location), UnscaleSize(rectF.Size));
- }
- public Rectangle ScaleRectangle(Rectangle rect)
- {
- return new Rectangle(ScalePoint(rect.Location), ScaleSize(rect.Size));
- }
- public Rectangle UnscaleRectangle(Rectangle rect)
- {
- return new Rectangle(UnscalePoint(rect.Location), UnscaleSize(rect.Size));
- }
- private static readonly double[] scales =
- {
- 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.08, 0.12, 0.16, 0.25, 0.33, 0.50, 0.66, 1,
- 2, 3, 4, 5, 6, 7, 8, 12, 16, 24, 32
- };
- /// <summary>
- /// Gets a list of values that GetNextLarger() and GetNextSmaller() will cycle through.
- /// </summary>
- /// <remarks>
- /// 1.0 is guaranteed to be in the array returned by this property. This list is also
- /// sorted in ascending order.
- /// </remarks>
- public static double[] PresetValues
- {
- get
- {
- double[] returnValue = new double[scales.Length];
- scales.CopyTo(returnValue, 0);
- return returnValue;
- }
- }
- /// <summary>
- /// Rounds the current scaling factor up to the next power of two.
- /// </summary>
- /// <returns>The new ScaleFactor value.</returns>
- public ScaleFactor GetNextLarger()
- {
- double ratio = Ratio + 0.005;
- int index = Array.FindIndex(
- scales,
- delegate (double scale)
- {
- return ratio <= scale;
- });
- if (index == -1)
- {
- index = scales.Length;
- }
- index = Math.Min(index, scales.Length - 1);
- return ScaleFactor.FromDouble(scales[index]);
- }
- public ScaleFactor GetNextSmaller()
- {
- double ratio = Ratio - 0.005;
- int index = Array.FindIndex(
- scales,
- delegate (double scale)
- {
- return ratio <= scale;
- });
- --index;
- if (index == -1)
- {
- index = 0;
- }
- index = Math.Max(index, 0);
- return ScaleFactor.FromDouble(scales[index]);
- }
- private static ScaleFactor Reduce(int numerator, int denominator)
- {
- int factor = 2;
- while (factor < denominator && factor < numerator)
- {
- if ((numerator % factor) == 0 && (denominator % factor) == 0)
- {
- numerator /= factor;
- denominator /= factor;
- }
- else
- {
- ++factor;
- }
- }
- return new ScaleFactor(numerator, denominator);
- }
- public static ScaleFactor FromDouble(double scalar)
- {
- int numerator = (int)(Math.Floor(scalar * 1000.0));
- int denominator = 1000;
- return Reduce(numerator, denominator);
- }
- public ScaleFactor(int numerator, int denominator)
- {
- if (denominator <= 0)
- {
- throw new ArgumentOutOfRangeException("denominator", "must be greater than 0");
- }
- if (numerator < 0)
- {
- throw new ArgumentOutOfRangeException("numerator", "must be greater than 0");
- }
- this.numerator = numerator;
- this.denominator = denominator;
- this.Clamp();
- }
- }
- }
|