Size.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using System;
  4. using System.Globalization;
  5. using Avalonia.Animation.Animators;
  6. using Avalonia.Utilities;
  7. namespace Avalonia
  8. {
  9. /// <summary>
  10. /// Defines a size.
  11. /// </summary>
  12. public readonly struct Size : IEquatable<Size>
  13. {
  14. static Size()
  15. {
  16. Animation.Animation.RegisterAnimator<SizeAnimator>(prop => typeof(Size).IsAssignableFrom(prop.PropertyType));
  17. }
  18. /// <summary>
  19. /// A size representing infinity.
  20. /// </summary>
  21. public static readonly Size Infinity = new Size(double.PositiveInfinity, double.PositiveInfinity);
  22. /// <summary>
  23. /// A size representing zero
  24. /// </summary>
  25. public static readonly Size Empty = new Size(0, 0);
  26. /// <summary>
  27. /// The width.
  28. /// </summary>
  29. private readonly double _width;
  30. /// <summary>
  31. /// The height.
  32. /// </summary>
  33. private readonly double _height;
  34. /// <summary>
  35. /// Initializes a new instance of the <see cref="Size"/> structure.
  36. /// </summary>
  37. /// <param name="width">The width.</param>
  38. /// <param name="height">The height.</param>
  39. public Size(double width, double height)
  40. {
  41. _width = width;
  42. _height = height;
  43. }
  44. /// <summary>
  45. /// Gets the aspect ratio of the size.
  46. /// </summary>
  47. public double AspectRatio => _width / _height;
  48. /// <summary>
  49. /// Gets the width.
  50. /// </summary>
  51. public double Width => _width;
  52. /// <summary>
  53. /// Gets the height.
  54. /// </summary>
  55. public double Height => _height;
  56. /// <summary>
  57. /// Checks for equality between two <see cref="Size"/>s.
  58. /// </summary>
  59. /// <param name="left">The first size.</param>
  60. /// <param name="right">The second size.</param>
  61. /// <returns>True if the sizes are equal; otherwise false.</returns>
  62. public static bool operator ==(Size left, Size right)
  63. {
  64. return left.Equals(right);
  65. }
  66. /// <summary>
  67. /// Checks for inequality between two <see cref="Size"/>s.
  68. /// </summary>
  69. /// <param name="left">The first size.</param>
  70. /// <param name="right">The second size.</param>
  71. /// <returns>True if the sizes are unequal; otherwise false.</returns>
  72. public static bool operator !=(Size left, Size right)
  73. {
  74. return !(left == right);
  75. }
  76. /// <summary>
  77. /// Scales a size.
  78. /// </summary>
  79. /// <param name="size">The size</param>
  80. /// <param name="scale">The scaling factor.</param>
  81. /// <returns>The scaled size.</returns>
  82. public static Size operator *(Size size, Vector scale)
  83. {
  84. return new Size(size._width * scale.X, size._height * scale.Y);
  85. }
  86. /// <summary>
  87. /// Scales a size.
  88. /// </summary>
  89. /// <param name="size">The size</param>
  90. /// <param name="scale">The scaling factor.</param>
  91. /// <returns>The scaled size.</returns>
  92. public static Size operator /(Size size, Vector scale)
  93. {
  94. return new Size(size._width / scale.X, size._height / scale.Y);
  95. }
  96. /// <summary>
  97. /// Divides a size by another size to produce a scaling factor.
  98. /// </summary>
  99. /// <param name="left">The first size</param>
  100. /// <param name="right">The second size.</param>
  101. /// <returns>The scaled size.</returns>
  102. public static Vector operator /(Size left, Size right)
  103. {
  104. return new Vector(left._width / right._width, left._height / right._height);
  105. }
  106. /// <summary>
  107. /// Scales a size.
  108. /// </summary>
  109. /// <param name="size">The size</param>
  110. /// <param name="scale">The scaling factor.</param>
  111. /// <returns>The scaled size.</returns>
  112. public static Size operator *(Size size, double scale)
  113. {
  114. return new Size(size._width * scale, size._height * scale);
  115. }
  116. /// <summary>
  117. /// Scales a size.
  118. /// </summary>
  119. /// <param name="size">The size</param>
  120. /// <param name="scale">The scaling factor.</param>
  121. /// <returns>The scaled size.</returns>
  122. public static Size operator /(Size size, double scale)
  123. {
  124. return new Size(size._width / scale, size._height / scale);
  125. }
  126. public static Size operator +(Size size, Size toAdd)
  127. {
  128. return new Size(size._width + toAdd._width, size._height + toAdd._height);
  129. }
  130. public static Size operator -(Size size, Size toSubtract)
  131. {
  132. return new Size(size._width - toSubtract._width, size._height - toSubtract._height);
  133. }
  134. /// <summary>
  135. /// Parses a <see cref="Size"/> string.
  136. /// </summary>
  137. /// <param name="s">The string.</param>
  138. /// <returns>The <see cref="Size"/>.</returns>
  139. public static Size Parse(string s)
  140. {
  141. using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Size."))
  142. {
  143. return new Size(
  144. tokenizer.ReadDouble(),
  145. tokenizer.ReadDouble());
  146. }
  147. }
  148. /// <summary>
  149. /// Constrains the size.
  150. /// </summary>
  151. /// <param name="constraint">The size to constrain to.</param>
  152. /// <returns>The constrained size.</returns>
  153. public Size Constrain(Size constraint)
  154. {
  155. return new Size(
  156. Math.Min(_width, constraint._width),
  157. Math.Min(_height, constraint._height));
  158. }
  159. /// <summary>
  160. /// Deflates the size by a <see cref="Thickness"/>.
  161. /// </summary>
  162. /// <param name="thickness">The thickness.</param>
  163. /// <returns>The deflated size.</returns>
  164. /// <remarks>The deflated size cannot be less than 0.</remarks>
  165. public Size Deflate(Thickness thickness)
  166. {
  167. return new Size(
  168. Math.Max(0, _width - thickness.Left - thickness.Right),
  169. Math.Max(0, _height - thickness.Top - thickness.Bottom));
  170. }
  171. /// <summary>
  172. /// Returns a boolean indicating whether the size is equal to the other given size.
  173. /// </summary>
  174. /// <param name="other">The other size to test equality against.</param>
  175. /// <returns>True if this size is equal to other; False otherwise.</returns>
  176. public bool Equals(Size other)
  177. {
  178. // ReSharper disable CompareOfFloatsByEqualityOperator
  179. return _width == other._width &&
  180. _height == other._height;
  181. // ReSharper enable CompareOfFloatsByEqualityOperator
  182. }
  183. /// <summary>
  184. /// Checks for equality between a size and an object.
  185. /// </summary>
  186. /// <param name="obj">The object.</param>
  187. /// <returns>
  188. /// True if <paramref name="obj"/> is a size that equals the current size.
  189. /// </returns>
  190. public override bool Equals(object obj) => obj is Size other && Equals(other);
  191. /// <summary>
  192. /// Returns a hash code for a <see cref="Size"/>.
  193. /// </summary>
  194. /// <returns>The hash code.</returns>
  195. public override int GetHashCode()
  196. {
  197. unchecked
  198. {
  199. int hash = 17;
  200. hash = (hash * 23) + Width.GetHashCode();
  201. hash = (hash * 23) + Height.GetHashCode();
  202. return hash;
  203. }
  204. }
  205. /// <summary>
  206. /// Inflates the size by a <see cref="Thickness"/>.
  207. /// </summary>
  208. /// <param name="thickness">The thickness.</param>
  209. /// <returns>The inflated size.</returns>
  210. public Size Inflate(Thickness thickness)
  211. {
  212. return new Size(
  213. _width + thickness.Left + thickness.Right,
  214. _height + thickness.Top + thickness.Bottom);
  215. }
  216. /// <summary>
  217. /// Returns a new <see cref="Size"/> with the same height and the specified width.
  218. /// </summary>
  219. /// <param name="width">The width.</param>
  220. /// <returns>The new <see cref="Size"/>.</returns>
  221. public Size WithWidth(double width)
  222. {
  223. return new Size(width, _height);
  224. }
  225. /// <summary>
  226. /// Returns a new <see cref="Size"/> with the same width and the specified height.
  227. /// </summary>
  228. /// <param name="height">The height.</param>
  229. /// <returns>The new <see cref="Size"/>.</returns>
  230. public Size WithHeight(double height)
  231. {
  232. return new Size(_width, height);
  233. }
  234. /// <summary>
  235. /// Returns the string representation of the size.
  236. /// </summary>
  237. /// <returns>The string representation of the size.</returns>
  238. public override string ToString()
  239. {
  240. return string.Format(CultureInfo.InvariantCulture, "{0}, {1}", _width, _height);
  241. }
  242. }
  243. }