PageRenderTime 68ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Core/Utility.cs

https://bitbucket.org/tuldok89/openpdn
C# | 3143 lines | 2384 code | 493 blank | 266 comment | 337 complexity | ef47c96c16a4ad561e769079360fb56c MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////////
  2. // Paint.NET //
  3. // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. //
  4. // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
  5. // See src/Resources/Files/License.txt for full licensing and attribution //
  6. // details. //
  7. // . //
  8. /////////////////////////////////////////////////////////////////////////////////
  9. using System.Linq;
  10. using PaintDotNet.Base;
  11. using PaintDotNet.SystemLayer;
  12. using System;
  13. using System.Collections;
  14. using System.Collections.Generic;
  15. using System.ComponentModel;
  16. using System.Drawing;
  17. using System.Drawing.Drawing2D;
  18. using System.Drawing.Imaging;
  19. using System.IO;
  20. using System.Net;
  21. using System.Reflection;
  22. using System.Runtime.InteropServices;
  23. using System.Runtime.Serialization.Formatters.Binary;
  24. using System.Text;
  25. using System.Windows.Forms;
  26. namespace PaintDotNet
  27. {
  28. /// <summary>
  29. /// Defines miscellaneous constants and static functions.
  30. /// </summary>
  31. /// // TODO: refactor into mini static classes
  32. public static class Utility
  33. {
  34. internal static bool IsNumber(float x)
  35. {
  36. return x >= float.MinValue && x <= float.MaxValue;
  37. }
  38. internal static bool IsNumber(double x)
  39. {
  40. return x >= double.MinValue && x <= double.MaxValue;
  41. }
  42. internal static int Min(int val0, params int[] vals)
  43. {
  44. int min = val0;
  45. foreach (int t in vals)
  46. {
  47. if (t < min)
  48. {
  49. min = t;
  50. }
  51. }
  52. return min;
  53. }
  54. internal static int Max(int val0, params int[] vals)
  55. {
  56. int max = val0;
  57. foreach (int t in vals)
  58. {
  59. if (t > max)
  60. {
  61. max = t;
  62. }
  63. }
  64. return max;
  65. }
  66. public static PointF[] GetRgssOffsets(int quality)
  67. {
  68. unsafe
  69. {
  70. int sampleCount = quality * quality;
  71. var samplesArray = new PointF[sampleCount];
  72. fixed (PointF* pSamplesArray = samplesArray)
  73. {
  74. GetRgssOffsets(pSamplesArray, sampleCount, quality);
  75. }
  76. return samplesArray;
  77. }
  78. }
  79. public static unsafe void GetRgssOffsets(PointF* samplesArray, int sampleCount, int quality)
  80. {
  81. if (sampleCount < 1)
  82. {
  83. throw new ArgumentOutOfRangeException("sampleCount", "sampleCount must be [0, int.MaxValue]");
  84. }
  85. if (sampleCount != quality * quality)
  86. {
  87. throw new ArgumentOutOfRangeException("sampleCount != (quality * quality)");
  88. }
  89. if (sampleCount == 1)
  90. {
  91. samplesArray[0] = new PointF(0.0f, 0.0f);
  92. }
  93. else
  94. {
  95. for (int i = 0; i < sampleCount; ++i)
  96. {
  97. double y = (i + 1d) / (sampleCount + 1d);
  98. double x = y * quality;
  99. x -= (int)x;
  100. samplesArray[i] = new PointF((float)(x - 0.5d), (float)(y - 0.5d));
  101. }
  102. }
  103. }
  104. public static bool IsObsolete(Type type, bool inherit)
  105. {
  106. object[] attrs = type.GetCustomAttributes(typeof(ObsoleteAttribute), inherit);
  107. return (attrs.Length != 0);
  108. }
  109. public static void DrawDropShadow1Px(Graphics g, Rectangle rect)
  110. {
  111. Brush b0 = new SolidBrush(Color.FromArgb(15, Color.Black));
  112. Brush b1 = new SolidBrush(Color.FromArgb(47, Color.Black));
  113. var p2 = new Pen(Color.FromArgb(63, Color.Black));
  114. g.FillRectangle(b0, rect.Left, rect.Top, 1, 1);
  115. g.FillRectangle(b1, rect.Left + 1, rect.Top, 1, 1);
  116. g.FillRectangle(b1, rect.Left, rect.Top + 1, 1, 1);
  117. g.FillRectangle(b0, rect.Right - 1, rect.Top, 1, 1);
  118. g.FillRectangle(b1, rect.Right - 2, rect.Top, 1, 1);
  119. g.FillRectangle(b1, rect.Right - 1, rect.Top + 1, 1, 1);
  120. g.FillRectangle(b0, rect.Left, rect.Bottom - 1, 1, 1);
  121. g.FillRectangle(b1, rect.Left + 1, rect.Bottom - 1, 1, 1);
  122. g.FillRectangle(b1, rect.Left, rect.Bottom - 2, 1, 1);
  123. g.FillRectangle(b0, rect.Right - 1, rect.Bottom - 1, 1, 1);
  124. g.FillRectangle(b1, rect.Right - 2, rect.Bottom - 1, 1, 1);
  125. g.FillRectangle(b1, rect.Right - 1, rect.Bottom - 2, 1, 1);
  126. g.DrawLine(p2, rect.Left + 2, rect.Top, rect.Right - 3, rect.Top);
  127. g.DrawLine(p2, rect.Left, rect.Top + 2, rect.Left, rect.Bottom - 3);
  128. g.DrawLine(p2, rect.Left + 2, rect.Bottom - 1, rect.Right - 3, rect.Bottom - 1);
  129. g.DrawLine(p2, rect.Right - 1, rect.Top + 2, rect.Right - 1, rect.Bottom - 3);
  130. b0.Dispose();
  131. b0 = null;
  132. b1.Dispose();
  133. b1 = null;
  134. p2.Dispose();
  135. p2 = null;
  136. }
  137. public static Keys LetterOrDigitCharToKeys(char c)
  138. {
  139. if (c >= 'a' && c <= 'z')
  140. {
  141. return (Keys)(c - 'a' + (int)Keys.A);
  142. }
  143. if (c >= 'A' && c <= 'Z')
  144. {
  145. return (Keys)(c - 'A' + (int)Keys.A);
  146. }
  147. if (c >= '0' && c <= '9')
  148. {
  149. return (Keys)(c - '0' + (int)Keys.D0);
  150. }
  151. return Keys.None;
  152. }
  153. public static Control FindFocus()
  154. {
  155. return (from Form form in Application.OpenForms select FindFocus(form)).FirstOrDefault(focused => focused != null);
  156. }
  157. private static Control FindFocus(Control c)
  158. {
  159. return c.Focused ? c : (from Control child in c.Controls select FindFocus(child)).FirstOrDefault(f => f != null);
  160. }
  161. public static void DrawColorRectangle(Graphics g, Rectangle rect, Color color, bool drawBorder)
  162. {
  163. int inflateAmt = drawBorder ? -2 : 0;
  164. Rectangle colorRectangle = Rectangle.Inflate(rect, inflateAmt, inflateAmt);
  165. Brush colorBrush = new LinearGradientBrush(colorRectangle, Color.FromArgb(255, color), color, 90.0f, false);
  166. var backgroundBrush = new HatchBrush(HatchStyle.LargeCheckerBoard, Color.FromArgb(191, 191, 191), Color.FromArgb(255, 255, 255));
  167. if (drawBorder)
  168. {
  169. g.DrawRectangle(Pens.Black, rect.Left, rect.Top, rect.Width - 1, rect.Height - 1);
  170. g.DrawRectangle(Pens.White, rect.Left + 1, rect.Top + 1, rect.Width - 3, rect.Height - 3);
  171. }
  172. PixelOffsetMode oldPOM = g.PixelOffsetMode;
  173. g.PixelOffsetMode = PixelOffsetMode.Half;
  174. g.FillRectangle(backgroundBrush, colorRectangle);
  175. g.FillRectangle(colorBrush, colorRectangle);
  176. g.PixelOffsetMode = oldPOM;
  177. backgroundBrush.Dispose();
  178. colorBrush.Dispose();
  179. }
  180. public static Size ComputeThumbnailSize(Size originalSize, int maxEdgeLength)
  181. {
  182. Size thumbSize;
  183. if (originalSize.Width > originalSize.Height)
  184. {
  185. int longSide = Math.Min(originalSize.Width, maxEdgeLength);
  186. thumbSize = new Size(longSide, Math.Max(1, (originalSize.Height * longSide) / originalSize.Width));
  187. }
  188. else if (originalSize.Height > originalSize.Width)
  189. {
  190. int longSide = Math.Min(originalSize.Height, maxEdgeLength);
  191. thumbSize = new Size(Math.Max(1, (originalSize.Width * longSide) / originalSize.Height), longSide);
  192. }
  193. else // if (docSize.Width == docSize.Height)
  194. {
  195. int longSide = Math.Min(originalSize.Width, maxEdgeLength);
  196. thumbSize = new Size(longSide, longSide);
  197. }
  198. return thumbSize;
  199. }
  200. public static bool IsClipboardImageAvailable()
  201. {
  202. try
  203. {
  204. return System.Windows.Forms.Clipboard.ContainsImage() ||
  205. System.Windows.Forms.Clipboard.ContainsData(DataFormats.EnhancedMetafile);
  206. }
  207. catch (ExternalException)
  208. {
  209. return false;
  210. }
  211. }
  212. public static Font CreateFont(string name, float size, FontStyle style)
  213. {
  214. Font returnFont;
  215. try
  216. {
  217. returnFont = new Font(name, size, style);
  218. }
  219. catch (Exception)
  220. {
  221. returnFont = new Font(FontFamily.GenericSansSerif, size);
  222. }
  223. return returnFont;
  224. }
  225. public static Font CreateFont(string name, float size, string backupName, float backupSize, FontStyle style)
  226. {
  227. Font returnFont;
  228. try
  229. {
  230. returnFont = new Font(name, size, style);
  231. }
  232. catch (Exception)
  233. {
  234. returnFont = CreateFont(backupName, backupSize, style);
  235. }
  236. return returnFont;
  237. }
  238. public static readonly Color TransparentKey = Color.FromArgb(192, 192, 192);
  239. public static string WebExceptionToErrorMessage(WebException wex)
  240. {
  241. string errorMessage;
  242. switch (wex.Status)
  243. {
  244. case WebExceptionStatus.ProtocolError:
  245. string format = PdnResources.GetString("WebExceptionStatus.ProtocolError.Format");
  246. HttpStatusCode statusCode = ((HttpWebResponse)wex.Response).StatusCode;
  247. errorMessage = string.Format(format, statusCode, (int)statusCode);
  248. break;
  249. default:
  250. string stringName = "WebExceptionStatus." + wex.Status;
  251. errorMessage = PdnResources.GetString(stringName);
  252. break;
  253. }
  254. return errorMessage;
  255. }
  256. private static bool _allowGcFullCollect = true;
  257. public static bool AllowGCFullCollect
  258. {
  259. get
  260. {
  261. return _allowGcFullCollect;
  262. }
  263. set
  264. {
  265. _allowGcFullCollect = value;
  266. }
  267. }
  268. public static void GCFullCollect()
  269. {
  270. if (!AllowGCFullCollect) return;
  271. GC.Collect();
  272. GC.WaitForPendingFinalizers();
  273. GC.Collect();
  274. GC.WaitForPendingFinalizers();
  275. }
  276. private static int _defaultSimplificationFactor = 50;
  277. public static int DefaultSimplificationFactor
  278. {
  279. get
  280. {
  281. return _defaultSimplificationFactor;
  282. }
  283. set
  284. {
  285. _defaultSimplificationFactor = value;
  286. }
  287. }
  288. public static bool IsArrowKey(Keys keyData)
  289. {
  290. Keys key = keyData & Keys.KeyCode;
  291. return key == Keys.Up || key == Keys.Down || key == Keys.Left || key == Keys.Right;
  292. }
  293. public static bool DoesControlHaveMouseCaptured(Control control)
  294. {
  295. bool result = false;
  296. result |= control.Capture;
  297. return control.Controls.Cast<Control>().Aggregate(result, (current, c) => current | DoesControlHaveMouseCaptured(c));
  298. }
  299. public static void SplitRectangle(Rectangle rect, Rectangle[] rects)
  300. {
  301. int height = rect.Height;
  302. for (int i = 0; i < rects.Length; ++i)
  303. {
  304. Rectangle newRect = Rectangle.FromLTRB(rect.Left,
  305. rect.Top + ((height * i) / rects.Length),
  306. rect.Right,
  307. rect.Top + ((height * (i + 1)) / rects.Length));
  308. rects[i] = newRect;
  309. }
  310. }
  311. public static long TicksToMs(long ticks)
  312. {
  313. return ticks / 10000;
  314. }
  315. public static string GetStaticName(Type type)
  316. {
  317. PropertyInfo pi = type.GetProperty("StaticName", BindingFlags.Static | BindingFlags.Public | BindingFlags.GetProperty);
  318. return (string)pi.GetValue(null, null);
  319. }
  320. public static readonly float[][] Identity5X5F = new[]
  321. {
  322. new float[] { 1, 0, 0, 0, 0 },
  323. new float[] { 0, 1, 0, 0, 0 },
  324. new float[] { 0, 0, 1, 0, 0 },
  325. new float[] { 0, 0, 0, 1, 0 },
  326. new float[] { 0, 0, 0, 0, 1 }
  327. };
  328. public static readonly ColorMatrix IdentityColorMatrix = new ColorMatrix(Identity5X5F);
  329. [ThreadStatic]
  330. private static Matrix _identityMatrix;
  331. public static Matrix IdentityMatrix
  332. {
  333. get
  334. {
  335. if (_identityMatrix == null)
  336. {
  337. _identityMatrix = new Matrix();
  338. _identityMatrix.Reset();
  339. }
  340. return _identityMatrix;
  341. }
  342. }
  343. /// <summary>
  344. /// Rounds an integer to the smallest power of 2 that is greater
  345. /// than or equal to it.
  346. /// </summary>
  347. public static int Log2RoundUp(int x)
  348. {
  349. if (x == 0)
  350. {
  351. return 1;
  352. }
  353. if (x == 1)
  354. {
  355. return 1;
  356. }
  357. return 1 << (1 + HighestBit(x - 1));
  358. }
  359. private static int HighestBit(int x)
  360. {
  361. if (x == 0)
  362. {
  363. return 0;
  364. }
  365. int b = 0;
  366. int hi = 0;
  367. while (b <= 30)
  368. {
  369. if ((x & (1 << b)) != 0)
  370. {
  371. hi = b;
  372. }
  373. ++b;
  374. }
  375. return hi;
  376. }
  377. /*
  378. private int CountBits(int x)
  379. {
  380. var y = (uint)x;
  381. int count = 0;
  382. for (int bit = 0; bit < 32; ++bit)
  383. {
  384. if ((y & ((uint)1 << bit)) != 0)
  385. {
  386. ++count;
  387. }
  388. }
  389. return count; //POSSIBLE UNUSED METHOD
  390. }
  391. */
  392. public static string RemoveSpaces(string s)
  393. {
  394. var sb = new StringBuilder();
  395. foreach (char c in s.Where(c => !char.IsWhiteSpace(c)))
  396. {
  397. sb.Append(c);
  398. }
  399. return sb.ToString();
  400. }
  401. public static int Max(int[,] array)
  402. {
  403. int max = int.MinValue;
  404. for (int i = array.GetLowerBound(0); i <= array.GetUpperBound(0); ++i)
  405. {
  406. for (int j = array.GetLowerBound(1); j <= array.GetUpperBound(1); ++j)
  407. {
  408. if (array[i,j] > max)
  409. {
  410. max = array[i,j];
  411. }
  412. }
  413. }
  414. return max;
  415. }
  416. public static int Sum(int[][] array)
  417. {
  418. int sum = 0;
  419. foreach (int[] row in array)
  420. {
  421. sum = row.Sum();
  422. }
  423. return sum;
  424. }
  425. // TODO: obsolete these NUD funcitons, move them into PdnNumericUpDown
  426. public static void ClipNumericUpDown(NumericUpDown upDown)
  427. {
  428. if (upDown.Value < upDown.Minimum)
  429. {
  430. upDown.Value = upDown.Minimum;
  431. }
  432. else if (upDown.Value > upDown.Maximum)
  433. {
  434. upDown.Value = upDown.Maximum;
  435. }
  436. }
  437. public static bool GetUpDownValueFromText(NumericUpDown nud, out double val)
  438. {
  439. if (nud.Text == string.Empty)
  440. {
  441. val = 0;
  442. return false;
  443. }
  444. try
  445. {
  446. val = nud.DecimalPlaces == 0 ? int.Parse(nud.Text) : double.Parse(nud.Text);
  447. }
  448. catch
  449. {
  450. val = 0;
  451. return false;
  452. }
  453. return true;
  454. }
  455. public static bool CheckNumericUpDown(NumericUpDown upDown)
  456. {
  457. int a;
  458. bool result = int.TryParse(upDown.Text, out a);
  459. return result && (a <= (int)upDown.Maximum) && (a >= (int)upDown.Minimum);
  460. }
  461. public static void SetNumericUpDownValue(NumericUpDown upDown, decimal newValue)
  462. {
  463. if (upDown.Value != newValue)
  464. {
  465. upDown.Value = newValue;
  466. }
  467. }
  468. public static void SetNumericUpDownValue(NumericUpDown upDown, int newValue)
  469. {
  470. SetNumericUpDownValue(upDown, (decimal)newValue);
  471. }
  472. public static string SizeStringFromBytes(long bytes)
  473. {
  474. var bytesDouble = (double)bytes;
  475. string toStringFormat;
  476. string formatString;
  477. if (bytesDouble > (1024 * 1024 * 1024))
  478. {
  479. // Gigs
  480. bytesDouble /= 1024 * 1024 * 1024;
  481. toStringFormat = "F1";
  482. formatString = PdnResources.GetString("Utility.SizeStringFromBytes.GBFormat");
  483. }
  484. else if (bytesDouble > (1024 * 1024))
  485. {
  486. // Megs
  487. bytesDouble /= 1024 * 1024;
  488. toStringFormat = "F1";
  489. formatString = PdnResources.GetString("Utility.SizeStringFromBytes.MBFormat");
  490. }
  491. else if (bytesDouble > (1024))
  492. {
  493. // K
  494. bytesDouble /= 1024;
  495. toStringFormat = "F1";
  496. formatString = PdnResources.GetString("Utility.SizeStringFromBytes.KBFormat");
  497. }
  498. else
  499. {
  500. // Bytes
  501. toStringFormat = "F0";
  502. formatString = PdnResources.GetString("Utility.SizeStringFromBytes.BytesFormat");
  503. }
  504. string bytesString = bytesDouble.ToString(toStringFormat);
  505. string sizeString = string.Format(formatString, bytesString);
  506. return sizeString;
  507. }
  508. public static void ShowWiaError(IWin32Window owner)
  509. {
  510. // WIA requires Windows XP SP1 or later, or Windows Server 2003
  511. // So if we know they're on WS2k3, we tell them to enable WIA.
  512. // If they're on XP or later, tell them that WIA isn't available.
  513. // Otherwise we tell them they need XP SP1 (for the Win2K folks).
  514. ErrorBox(owner,
  515. OS.Type == OSType.Server
  516. ? PdnResources.GetString("WIA.Error.EnableMe")
  517. : PdnResources.GetString("WIA.Error.UnableToLoad"));
  518. }
  519. public static void ShowNonAdminErrorBox(IWin32Window parent)
  520. {
  521. ErrorBox(parent, PdnResources.GetString("NonAdminErrorBox.Message"));
  522. }
  523. public static void ErrorBox(IWin32Window parent, string message)
  524. {
  525. MessageBox.Show(parent, message, PdnInfo.GetBareProductName(), MessageBoxButtons.OK, MessageBoxIcon.Error);
  526. }
  527. public static DialogResult ErrorBoxOkCancel(IWin32Window parent, string message)
  528. {
  529. return MessageBox.Show(parent, message, PdnInfo.GetBareProductName(), MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
  530. }
  531. public static void InfoBox(IWin32Window parent, string message)
  532. {
  533. MessageBox.Show(parent, message, PdnInfo.GetBareProductName(), MessageBoxButtons.OK, MessageBoxIcon.Information);
  534. }
  535. public static DialogResult InfoBoxOkCancel(IWin32Window parent, string message)
  536. {
  537. return MessageBox.Show(parent, message, PdnInfo.GetBareProductName(), MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
  538. }
  539. public static DialogResult AskOkCancel(IWin32Window parent, string question)
  540. {
  541. return MessageBox.Show(parent, question, PdnInfo.GetBareProductName(), MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
  542. }
  543. public static DialogResult AskYesNo(IWin32Window parent, string question)
  544. {
  545. return MessageBox.Show(parent, question, PdnInfo.GetBareProductName(), MessageBoxButtons.YesNo, MessageBoxIcon.Question);
  546. }
  547. public static DialogResult AskYesNoCancel(IWin32Window parent, string question)
  548. {
  549. return MessageBox.Show(parent, question, PdnInfo.GetBareProductName(), MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
  550. }
  551. public static Icon ImageToIcon(Image image)
  552. {
  553. return ImageToIcon(image, TransparentKey);
  554. }
  555. public static Icon ImageToIcon(Image image, bool disposeImage)
  556. {
  557. return ImageToIcon(image, TransparentKey, disposeImage);
  558. }
  559. public static Icon ImageToIcon(Image image, Color seeThru)
  560. {
  561. return ImageToIcon(image, seeThru, false);
  562. }
  563. /// <summary>
  564. /// Converts an Image to an Icon.
  565. /// </summary>
  566. /// <param name="image">The Image to convert to an icon. Must be an appropriate icon size (32x32, 16x16, etc).</param>
  567. /// <param name="seeThru">The color that will be treated as transparent in the icon.</param>
  568. /// <param name="disposeImage">Whether or not to dispose the passed-in Image.</param>
  569. /// <returns>An Icon representation of the Image.</returns>
  570. public static Icon ImageToIcon(Image image, Color seeThru, bool disposeImage)
  571. {
  572. var bitmap = new Bitmap(image);
  573. for (int y = 0; y < bitmap.Height; ++y)
  574. {
  575. for (int x = 0; x < bitmap.Width; ++x)
  576. {
  577. if (bitmap.GetPixel(x, y) == seeThru)
  578. {
  579. bitmap.SetPixel(x, y, Color.FromArgb(0));
  580. }
  581. }
  582. }
  583. Icon icon = Icon.FromHandle(bitmap.GetHicon());
  584. bitmap.Dispose();
  585. if (disposeImage)
  586. {
  587. image.Dispose();
  588. }
  589. return icon;
  590. }
  591. public static Icon BitmapToIcon(Bitmap bitmap, bool disposeBitmap)
  592. {
  593. Icon icon = Icon.FromHandle(bitmap.GetHicon());
  594. if (disposeBitmap)
  595. {
  596. bitmap.Dispose();
  597. }
  598. return icon;
  599. }
  600. public static Icon SurfaceToIcon(Surface surface, bool disposeSurface)
  601. {
  602. Bitmap bitmap = surface.CreateAliasedBitmap();
  603. Icon icon = Icon.FromHandle(bitmap.GetHicon());
  604. bitmap.Dispose();
  605. if (disposeSurface)
  606. {
  607. surface.Dispose();
  608. }
  609. return icon;
  610. }
  611. public static Point GetRectangleCenter(Rectangle rect)
  612. {
  613. return new Point((rect.Left + rect.Right) / 2, (rect.Top + rect.Bottom) / 2);
  614. }
  615. public static PointF GetRectangleCenter(RectangleF rect)
  616. {
  617. return new PointF((rect.Left + rect.Right) / 2, (rect.Top + rect.Bottom) / 2);
  618. }
  619. public static Scanline[] GetRectangleScans(Rectangle rect)
  620. {
  621. var scans = new Scanline[rect.Height];
  622. for (int y = 0; y < rect.Height; ++y)
  623. {
  624. scans[y] = new Scanline(rect.X, rect.Y + y, rect.Width);
  625. }
  626. return scans;
  627. }
  628. public static Scanline[] GetRegionScans(Rectangle[] region)
  629. {
  630. int scanCount = region.Sum(t => t.Height);
  631. var scans = new Scanline[scanCount];
  632. int scanIndex = 0;
  633. foreach (Rectangle rect in region)
  634. {
  635. for (int y = 0; y < rect.Height; ++y)
  636. {
  637. scans[scanIndex] = new Scanline(rect.X, rect.Y + y, rect.Width);
  638. ++scanIndex;
  639. }
  640. }
  641. return scans;
  642. }
  643. public static Rectangle[] ScanlinesToRectangles(Scanline[] scans)
  644. {
  645. return ScanlinesToRectangles(scans, 0, scans.Length);
  646. }
  647. public static Rectangle[] ScanlinesToRectangles(Scanline[] scans, int startIndex, int length)
  648. {
  649. var rects = new Rectangle[length];
  650. for (int i = 0; i < length; ++i)
  651. {
  652. Scanline scan = scans[i + startIndex];
  653. rects[i] = new Rectangle(scan.X, scan.Y, scan.Length, 1);
  654. }
  655. return rects;
  656. }
  657. /// <summary>
  658. /// Found on Google Groups when searching for "Region.Union" while looking
  659. /// for bugs:
  660. /// ---
  661. /// Hello,
  662. ///
  663. /// I did not run your code, but I know Region.Union is flawed in both 1.0 and
  664. /// 1.1, so I assume it is in the gdi+ unmanged code dll. The best workaround,
  665. /// in terms of speed, is to use a PdnGraphicsPath, but it must be a path with
  666. /// FillMode = FillMode.Winding. You add the rectangles to the path, then you do
  667. /// union onto an empty region with the path. The important point is to do only
  668. /// one union call on a given empty region. We created a "super region" object
  669. /// to hide all these bugs and optimize clipping operations. In fact, it is much
  670. /// faster to use the path than to call Region.Union for each rectangle.
  671. ///
  672. /// Too bad about Region.Union. A lot of people will hit this bug, as it is
  673. /// essential in high-performance animation.
  674. ///
  675. /// Regards,
  676. /// Frank Hileman
  677. /// Prodige Software Corporation
  678. /// ---
  679. /// </summary>
  680. /// <param name="rectsF"></param>
  681. /// <param name="startIndex"></param>
  682. /// <param name="length"></param>
  683. /// <returns></returns>
  684. public static PdnRegion RectanglesToRegion(RectangleF[] rectsF, int startIndex, int length)
  685. {
  686. PdnRegion region;
  687. if (rectsF == null || rectsF.Length == 0 || length == 0)
  688. {
  689. region = PdnRegion.CreateEmpty();
  690. }
  691. else
  692. {
  693. using (var path = new PdnGraphicsPath())
  694. {
  695. path.FillMode = FillMode.Winding;
  696. if (startIndex == 0 && length == rectsF.Length)
  697. {
  698. path.AddRectangles(rectsF);
  699. }
  700. else
  701. {
  702. for (int i = startIndex; i < startIndex + length; ++i)
  703. {
  704. path.AddRectangle(rectsF[i]);
  705. }
  706. }
  707. region = new PdnRegion(path);
  708. }
  709. }
  710. return region;
  711. }
  712. public static PdnRegion RectanglesToRegion(RectangleF[] rectsF)
  713. {
  714. return RectanglesToRegion(rectsF, 0, rectsF != null ? rectsF.Length : 0);
  715. }
  716. public static PdnRegion RectanglesToRegion(RectangleF[] rectsF1, RectangleF[] rectsF2, params RectangleF[][] rectsFA)
  717. {
  718. using (var path = new PdnGraphicsPath())
  719. {
  720. path.FillMode = FillMode.Winding;
  721. if (rectsF1 != null && rectsF1.Length > 0)
  722. {
  723. path.AddRectangles(rectsF1);
  724. }
  725. if (rectsF2 != null && rectsF2.Length > 0)
  726. {
  727. path.AddRectangles(rectsF2);
  728. }
  729. foreach (RectangleF[] rectsF in rectsFA.Where(rectsF => rectsF != null && rectsF.Length > 0))
  730. {
  731. path.AddRectangles(rectsF);
  732. }
  733. return new PdnRegion(path);
  734. }
  735. }
  736. public static PdnRegion RectanglesToRegion(Rectangle[] rects, int startIndex, int length)
  737. {
  738. PdnRegion region;
  739. if (length == 0)
  740. {
  741. region = PdnRegion.CreateEmpty();
  742. }
  743. else
  744. {
  745. using (var path = new PdnGraphicsPath())
  746. {
  747. path.FillMode = FillMode.Winding;
  748. if (startIndex == 0 && length == rects.Length)
  749. {
  750. path.AddRectangles(rects);
  751. }
  752. else
  753. {
  754. for (int i = startIndex; i < startIndex + length; ++i)
  755. {
  756. path.AddRectangle(rects[i]);
  757. }
  758. }
  759. region = new PdnRegion(path);
  760. path.Dispose();
  761. }
  762. }
  763. return region;
  764. }
  765. public static PdnRegion RectanglesToRegion(Rectangle[] rects)
  766. {
  767. return RectanglesToRegion(rects, 0, rects.Length);
  768. }
  769. public static int GetRegionArea(RectangleF[] rectsF)
  770. {
  771. return rectsF.Select(rectF => Rectangle.Truncate(rectF)).Select(rect => rect.Width*rect.Height).Sum();
  772. }
  773. public static RectangleF RectangleFromCenter(PointF center, float halfSize)
  774. {
  775. var ret = new RectangleF(center.X, center.Y, 0, 0);
  776. ret.Inflate(halfSize, halfSize);
  777. return ret;
  778. }
  779. public static List<PointF> PointListToPointFList(List<Point> ptList)
  780. {
  781. var ret = new List<PointF>(ptList.Count);
  782. ret.AddRange(ptList.Select(t => (PointF) t));
  783. return ret;
  784. }
  785. public static PointF[] PointArrayToPointFArray(Point[] ptArray)
  786. {
  787. var ret = new PointF[ptArray.Length];
  788. for (int i = 0; i < ret.Length; ++i)
  789. {
  790. ret[i] = ptArray[i];
  791. }
  792. return ret;
  793. }
  794. public static Rectangle[] InflateRectangles(Rectangle[] rects, int amount)
  795. {
  796. var inflated = new Rectangle[rects.Length];
  797. for (int i = 0; i < rects.Length; ++i)
  798. {
  799. inflated[i] = Rectangle.Inflate(rects[i], amount, amount);
  800. }
  801. return inflated;
  802. }
  803. public static void InflateRectanglesInPlace(Rectangle[] rects, int amount)
  804. {
  805. for (int i = 0; i < rects.Length; ++i)
  806. {
  807. rects[i].Inflate(amount, amount);
  808. }
  809. }
  810. public static RectangleF[] InflateRectangles(RectangleF[] rectsF, int amount)
  811. {
  812. var inflated = new RectangleF[rectsF.Length];
  813. for (int i = 0; i < rectsF.Length; ++i)
  814. {
  815. inflated[i] = RectangleF.Inflate(rectsF[i], amount, amount);
  816. }
  817. return inflated;
  818. }
  819. public static void InflateRectanglesInPlace(RectangleF[] rectsF, float amount)
  820. {
  821. for (int i = 0; i < rectsF.Length; ++i)
  822. {
  823. rectsF[i].Inflate(amount, amount);
  824. }
  825. }
  826. public static Rectangle PointsToConstrainedRectangle(Point a, Point b)
  827. {
  828. Rectangle rect = PointsToRectangle(a, b);
  829. int minWH = Math.Min(rect.Width, rect.Height);
  830. rect.Width = minWH;
  831. rect.Height = minWH;
  832. if (rect.Y != a.Y)
  833. {
  834. rect.Location = new Point(rect.X, a.Y - minWH);
  835. }
  836. if (rect.X != a.X)
  837. {
  838. rect.Location = new Point(a.X - minWH, rect.Y);
  839. }
  840. return rect;
  841. }
  842. public static RectangleF PointsToConstrainedRectangle(PointF a, PointF b)
  843. {
  844. RectangleF rect = PointsToRectangle(a, b);
  845. float minWH = Math.Min(rect.Width, rect.Height);
  846. rect.Width = minWH;
  847. rect.Height = minWH;
  848. if (rect.Y != a.Y)
  849. {
  850. rect.Location = new PointF(rect.X, a.Y - minWH);
  851. }
  852. if (rect.X != a.X)
  853. {
  854. rect.Location = new PointF(a.X - minWH, rect.Y);
  855. }
  856. return rect;
  857. }
  858. /// <summary>
  859. /// Takes two points and creates a bounding rectangle from them.
  860. /// </summary>
  861. /// <param name="a">One corner of the rectangle.</param>
  862. /// <param name="b">The other corner of the rectangle.</param>
  863. /// <returns>A Rectangle instance that bounds the two points.</returns>
  864. public static Rectangle PointsToRectangle(Point a, Point b)
  865. {
  866. int x = Math.Min(a.X, b.X);
  867. int y = Math.Min(a.Y, b.Y);
  868. int width = Math.Abs(a.X - b.X) + 1;
  869. int height = Math.Abs(a.Y - b.Y) + 1;
  870. return new Rectangle(x, y, width, height);
  871. }
  872. public static RectangleF PointsToRectangle(PointF a, PointF b)
  873. {
  874. float x = Math.Min(a.X, b.X);
  875. float y = Math.Min(a.Y, b.Y);
  876. float width = Math.Abs(a.X - b.X) + 1;
  877. float height = Math.Abs(a.Y - b.Y) + 1;
  878. return new RectangleF(x, y, width, height);
  879. }
  880. public static Rectangle PointsToRectangleExclusive(Point a, Point b)
  881. {
  882. int x = Math.Min(a.X, b.X);
  883. int y = Math.Min(a.Y, b.Y);
  884. int width = Math.Abs(a.X - b.X);
  885. int height = Math.Abs(a.Y - b.Y);
  886. return new Rectangle(x, y, width, height);
  887. }
  888. public static RectangleF PointsToRectangleExclusive(PointF a, PointF b)
  889. {
  890. float x = Math.Min(a.X, b.X);
  891. float y = Math.Min(a.Y, b.Y);
  892. float width = Math.Abs(a.X - b.X);
  893. float height = Math.Abs(a.Y - b.Y);
  894. return new RectangleF(x, y, width, height);
  895. }
  896. public static RectangleF[] PointsToRectangles(PointF[] pointsF)
  897. {
  898. if (pointsF.Length == 0)
  899. {
  900. return new RectangleF[] { };
  901. }
  902. if (pointsF.Length == 1)
  903. {
  904. return new[] { new RectangleF(pointsF[0].X, pointsF[0].Y, 1, 1) };
  905. }
  906. var rectsF = new RectangleF[pointsF.Length - 1];
  907. for (int i = 0; i < pointsF.Length - 1; ++i)
  908. {
  909. rectsF[i] = PointsToRectangle(pointsF[i], pointsF[i + 1]);
  910. }
  911. return rectsF;
  912. }
  913. public static Rectangle[] PointsToRectangles(Point[] points)
  914. {
  915. if (points.Length == 0)
  916. {
  917. return new Rectangle[] { };
  918. }
  919. if (points.Length == 1)
  920. {
  921. return new[] { new Rectangle(points[0].X, points[0].Y, 1, 1) };
  922. }
  923. var rects = new Rectangle[points.Length - 1];
  924. for (int i = 0; i < points.Length - 1; ++i)
  925. {
  926. rects[i] = PointsToRectangle(points[i], points[i + 1]);
  927. }
  928. return rects;
  929. }
  930. /// <summary>
  931. /// Converts a RectangleF to RectangleF by rounding down the Location and rounding
  932. /// up the Size.
  933. /// </summary>
  934. public static Rectangle RoundRectangle(RectangleF rectF)
  935. {
  936. var left = (float)Math.Floor(rectF.Left);
  937. var top = (float)Math.Floor(rectF.Top);
  938. var right = (float)Math.Ceiling(rectF.Right);
  939. var bottom = (float)Math.Ceiling(rectF.Bottom);
  940. return Rectangle.Truncate(RectangleF.FromLTRB(left, top, right, bottom));
  941. }
  942. public static Stack Reverse(Stack reverseMe)
  943. {
  944. var reversed = new Stack();
  945. foreach (object o in reverseMe)
  946. {
  947. reversed.Push(o);
  948. }
  949. return reversed;
  950. }
  951. public static void SerializeObjectToStream(object graph, Stream stream)
  952. {
  953. new BinaryFormatter().Serialize(stream, graph);
  954. }
  955. public static object DeserializeObjectFromStream(Stream stream)
  956. {
  957. return new BinaryFormatter().Deserialize(stream);
  958. }
  959. [Obsolete("Use rect.Contains() instead", true)]
  960. public static bool IsPointInRectangle(Point pt, Rectangle rect)
  961. {
  962. return rect.Contains(pt);
  963. }
  964. [Obsolete("Use rect.Contains() instead", true)]
  965. public static bool IsPointInRectangle(int x, int y, Rectangle rect)
  966. {
  967. return rect.Contains(x, y);
  968. }
  969. public static Bitmap FullCloneBitmap(Bitmap cloneMe)
  970. {
  971. var bitmap = new Bitmap(cloneMe.Width, cloneMe.Height, cloneMe.PixelFormat);
  972. using (Graphics g = Graphics.FromImage(bitmap))
  973. {
  974. g.DrawImage(cloneMe, 0, 0, cloneMe.Width, cloneMe.Height);
  975. }
  976. return bitmap;
  977. }
  978. /// <summary>
  979. /// Allows you to find the bounding box for a Region object without requiring
  980. /// the presence of a Graphics object.
  981. /// (Region.GetBounds takes a Graphics instance as its only parameter.)
  982. /// </summary>
  983. /// <param name="region">The region you want to find a bounding box for.</param>
  984. /// <returns>A RectangleF structure that surrounds the Region.</returns>
  985. public static Rectangle GetRegionBounds(PdnRegion region)
  986. {
  987. Rectangle[] rects = region.GetRegionScansReadOnlyInt();
  988. return GetRegionBounds(rects, 0, rects.Length);
  989. }
  990. /// <summary>
  991. /// Allows you to find the bounding box for a "region" that is described as an
  992. /// array of bounding boxes.
  993. /// </summary>
  994. /// <param name="rectsF">The "region" you want to find a bounding box for.</param>
  995. /// <param name="startIndex"></param>
  996. /// <param name="length"></param>
  997. /// <returns>A RectangleF structure that surrounds the Region.</returns>
  998. public static RectangleF GetRegionBounds(RectangleF[] rectsF, int startIndex, int length)
  999. {
  1000. if (rectsF.Length == 0)
  1001. {
  1002. return RectangleF.Empty;
  1003. }
  1004. float left = rectsF[startIndex].Left;
  1005. float top = rectsF[startIndex].Top;
  1006. float right = rectsF[startIndex].Right;
  1007. float bottom = rectsF[startIndex].Bottom;
  1008. for (int i = startIndex + 1; i < startIndex + length; ++i)
  1009. {
  1010. RectangleF rectF = rectsF[i];
  1011. if (rectF.Left < left)
  1012. {
  1013. left = rectF.Left;
  1014. }
  1015. if (rectF.Top < top)
  1016. {
  1017. top = rectF.Top;
  1018. }
  1019. if (rectF.Right > right)
  1020. {
  1021. right = rectF.Right;
  1022. }
  1023. if (rectF.Bottom > bottom)
  1024. {
  1025. bottom = rectF.Bottom;
  1026. }
  1027. }
  1028. return RectangleF.FromLTRB(left, top, right, bottom);
  1029. }
  1030. public static RectangleF GetTraceBounds(PointF[] pointsF, int startIndex, int length)
  1031. {
  1032. if (pointsF.Length == 0)
  1033. {
  1034. return RectangleF.Empty;
  1035. }
  1036. float left = pointsF[startIndex].X;
  1037. float top = pointsF[startIndex].Y;
  1038. float right = 1 + pointsF[startIndex].X;
  1039. float bottom = 1 + pointsF[startIndex].Y;
  1040. for (int i = startIndex + 1; i < startIndex + length; ++i)
  1041. {
  1042. PointF pointF = pointsF[i];
  1043. if (pointF.X < left)
  1044. {
  1045. left = pointF.X;
  1046. }
  1047. if (pointF.Y < top)
  1048. {
  1049. top = pointF.Y;
  1050. }
  1051. if (pointF.X > right)
  1052. {
  1053. right = pointF.X;
  1054. }
  1055. if (pointF.Y > bottom)
  1056. {
  1057. bottom = pointF.Y;
  1058. }
  1059. }
  1060. return RectangleF.FromLTRB(left, top, right, bottom);
  1061. }
  1062. public static Rectangle GetTraceBounds(Point[] points, int startIndex, int length)
  1063. {
  1064. if (points.Length == 0)
  1065. {
  1066. return Rectangle.Empty;
  1067. }
  1068. int left = points[startIndex].X;
  1069. int top = points[startIndex].Y;
  1070. int right = 1 + points[startIndex].X;
  1071. int bottom = 1 + points[startIndex].Y;
  1072. for (int i = startIndex + 1; i < startIndex + length; ++i)
  1073. {
  1074. Point point = points[i];
  1075. if (point.X < left)
  1076. {
  1077. left = point.X;
  1078. }
  1079. if (point.Y < top)
  1080. {
  1081. top = point.Y;
  1082. }
  1083. if (point.X > right)
  1084. {
  1085. right = point.X;
  1086. }
  1087. if (point.Y > bottom)
  1088. {
  1089. bottom = point.Y;
  1090. }
  1091. }
  1092. return Rectangle.FromLTRB(left, top, right, bottom);
  1093. }
  1094. /// <summary>
  1095. /// Allows you to find the bounding box for a "region" that is described as an
  1096. /// array of bounding boxes.
  1097. /// </summary>
  1098. /// <param name="rectsF">The "region" you want to find a bounding box for.</param>
  1099. /// <param name="rects"></param>
  1100. /// <param name="startIndex"></param>
  1101. /// <param name="length"></param>
  1102. /// <returns>A RectangleF structure that surrounds the Region.</returns>
  1103. public static Rectangle GetRegionBounds(Rectangle[] rects, int startIndex, int length)
  1104. {
  1105. if (rects.Length == 0)
  1106. {
  1107. return Rectangle.Empty;
  1108. }
  1109. int left = rects[startIndex].Left;
  1110. int top = rects[startIndex].Top;
  1111. int right = rects[startIndex].Right;
  1112. int bottom = rects[startIndex].Bottom;
  1113. for (int i = startIndex + 1; i < startIndex + length; ++i)
  1114. {
  1115. Rectangle rect = rects[i];
  1116. if (rect.Left < left)
  1117. {
  1118. left = rect.Left;
  1119. }
  1120. if (rect.Top < top)
  1121. {
  1122. top = rect.Top;
  1123. }
  1124. if (rect.Right > right)
  1125. {
  1126. right = rect.Right;
  1127. }
  1128. if (rect.Bottom > bottom)
  1129. {
  1130. bottom = rect.Bottom;
  1131. }
  1132. }
  1133. return Rectangle.FromLTRB(left, top, right, bottom);
  1134. }
  1135. public static RectangleF GetRegionBounds(RectangleF[] rectsF)
  1136. {
  1137. return GetRegionBounds(rectsF, 0, rectsF.Length);
  1138. }
  1139. public static Rectangle GetRegionBounds(Rectangle[] rects)
  1140. {
  1141. return GetRegionBounds(rects, 0, rects.Length);
  1142. }
  1143. /*
  1144. private static float DistanceSquared(IList<RectangleF> rectsF, int indexA, int indexB)
  1145. {
  1146. var centerA = new PointF(rectsF[indexA].Left + (rectsF[indexA].Width / 2), rectsF[indexA].Top + (rectsF[indexA].Height / 2));
  1147. var centerB = new PointF(rectsF[indexB].Left + (rectsF[indexB].Width / 2), rectsF[indexB].Top + (rectsF[indexB].Height / 2));
  1148. return ((centerA.X - centerB.X) * (centerA.X - centerB.X)) +
  1149. ((centerA.Y - centerB.Y) * (centerA.Y - centerB.Y)); UNUSED METHOD
  1150. }
  1151. */
  1152. /// <summary>
  1153. /// Simplifies a Region into N number of bounding boxes.
  1154. /// </summary>
  1155. /// <param name="region">The Region to simplify.</param>
  1156. /// <param name="complexity">The maximum number of bounding boxes to return, or 0 for however many are necessary (equivalent to using Region.GetRegionScans).</param>
  1157. /// <returns></returns>
  1158. public static Rectangle[] SimplifyRegion(PdnRegion region, int complexity)
  1159. {
  1160. Rectangle[] rects = region.GetRegionScansReadOnlyInt();
  1161. return SimplifyRegion(rects, complexity);
  1162. }
  1163. public static Rectangle[] SimplifyRegion(Rectangle[] rects, int complexity)
  1164. {
  1165. if (complexity == 0 || rects.Length < complexity)
  1166. {
  1167. return (Rectangle[])rects.Clone();
  1168. }
  1169. var boxes = new Rectangle[complexity];
  1170. for (int i = 0; i < complexity; ++i)
  1171. {
  1172. int startIndex = (i * rects.Length) / complexity;
  1173. int length = Math.Min(rects.Length, ((i + 1) * rects.Length) / complexity) - startIndex;
  1174. boxes[i] = GetRegionBounds(rects, startIndex, length);
  1175. }
  1176. return boxes;
  1177. }
  1178. public static RectangleF[] SimplifyTrace(PointF[] pointsF, int complexity)
  1179. {
  1180. if (complexity == 0 ||
  1181. (pointsF.Length - 1) < complexity)
  1182. {
  1183. return PointsToRectangles(pointsF);
  1184. }
  1185. var boxes = new RectangleF[complexity];
  1186. int parLength = pointsF.Length - 1; // "(points as Rectangles).Length"
  1187. for (int i = 0; i < complexity; ++i)
  1188. {
  1189. int startIndex = (i * parLength) / complexity;
  1190. int length = Math.Min(parLength, ((i + 1) * parLength) / complexity) - startIndex;
  1191. boxes[i] = GetTraceBounds(pointsF, startIndex, length + 1);
  1192. }
  1193. return boxes;
  1194. }
  1195. public static Rectangle[] SimplifyTrace(PdnGraphicsPath trace, int complexity)
  1196. {
  1197. return SimplifyRegion(TraceToRectangles(trace), complexity);
  1198. }
  1199. public static Rectangle[] SimplifyTrace(PdnGraphicsPath trace)
  1200. {
  1201. return SimplifyTrace(trace, DefaultSimplificationFactor);
  1202. }
  1203. public static Rectangle[] TraceToRectangles(PdnGraphicsPath trace, int complexity)
  1204. {
  1205. int pointCount = trace.PointCount;
  1206. if (pointCount == 0)
  1207. {
  1208. return new Rectangle[0];
  1209. }
  1210. PointF[] pathPoints = trace.PathPoints;
  1211. byte[] pathTypes = trace.PathTypes;
  1212. int figureStart = 0;
  1213. // first get count of rectangles we'll need
  1214. var rects = new Rectangle[pointCount];
  1215. for (int i = 0; i < pointCount; ++i)
  1216. {
  1217. byte type = pathTypes[i];
  1218. Point a = Point.Truncate(pathPoints[i]);
  1219. Point b;
  1220. if ((type & (byte)PathPointType.CloseSubpath) != 0)
  1221. {
  1222. b = Point.Truncate(pathPoints[figureStart]);
  1223. figureStart = i + 1;
  1224. }
  1225. else
  1226. {
  1227. b = Point.Truncate(pathPoints[i + 1]);
  1228. }
  1229. rects[i] = PointsToRectangle(a, b);
  1230. }
  1231. return rects;
  1232. }
  1233. public static Rectangle[] TraceToRectangles(PdnGraphicsPath trace)
  1234. {
  1235. return TraceToRectangles(trace, DefaultSimplificationFactor);
  1236. }
  1237. public static RectangleF[] SimplifyTrace(PointF[] pointsF)
  1238. {
  1239. return SimplifyTrace(pointsF, _defaultSimplificationFactor);
  1240. }
  1241. public static Rectangle[] SimplifyAndInflateRegion(Rectangle[] rects, int complexity, int inflationAmount)
  1242. {
  1243. Rectangle[] simplified = SimplifyRegion(rects, complexity);
  1244. for (int i = 0; i < simplified.Length; ++i)
  1245. {
  1246. simplified[i].Inflate(inflationAmount, inflationAmount);
  1247. }
  1248. return simplified;
  1249. }
  1250. public static Rectangle[] SimplifyAndInflateRegion(Rectangle[] rects)
  1251. {
  1252. return SimplifyAndInflateRegion(rects, _defaultSimplificationFactor, 1);
  1253. }
  1254. public static PdnRegion SimplifyAndInflateRegion(PdnRegion region, int complexity, int inflationAmount)
  1255. {
  1256. Rectangle[] rectRegion = SimplifyRegion(region, complexity);
  1257. for (int i = 0; i < rectRegion.Length; ++i)
  1258. {
  1259. rectRegion[i].Inflate(inflationAmount, inflationAmount);
  1260. }
  1261. return RectanglesToRegion(rectRegion);
  1262. }
  1263. public static PdnRegion SimplifyAndInflateRegion(PdnRegion region)
  1264. {
  1265. return SimplifyAndInflateRegion(region, _defaultSimplificationFactor, 1);
  1266. }
  1267. public static RectangleF[] TranslateRectangles(RectangleF[] rectsF, PointF offset)
  1268. {
  1269. var retRectsF = new RectangleF[rectsF.Length];
  1270. int i = 0;
  1271. foreach (RectangleF rectF in rectsF)
  1272. {
  1273. retRectsF[i] = new RectangleF(rectF.X + offset.X, rectF.Y + offset.Y, rectF.Width, rectF.Height);
  1274. ++i;
  1275. }
  1276. return retRectsF;
  1277. }
  1278. public static Rectangle[] TranslateRectangles(Rectangle[] rects, int dx, int dy)
  1279. {
  1280. var retRects = new Rectangle[rects.Length];
  1281. for (int i = 0; i < rects.Length; ++i)
  1282. {
  1283. retRects[i] = new Rectangle(rects[i].X + dx, rects[i].Y + dy, rects[i].Width, rects[i].Height);
  1284. }
  1285. return retRects;
  1286. }
  1287. public static void TranslatePointsInPlace(PointF[] ptsF, float dx, float dy)
  1288. {
  1289. for (int i = 0; i < ptsF.Length; ++i)
  1290. {
  1291. ptsF[i].X += dx;
  1292. ptsF[i].Y += dy;
  1293. }
  1294. }
  1295. public static void TranslatePointsInPlace(Point[] pts, int dx, int dy)
  1296. {
  1297. for (int i = 0; i < pts.Length; ++i)
  1298. {
  1299. pts[i].X += dx;
  1300. pts[i].Y += dy;
  1301. }
  1302. }
  1303. public static Rectangle[] TruncateRectangles(RectangleF[] rectsF)
  1304. {
  1305. var rects = new Rectangle[rectsF.Length];
  1306. for (int i = 0; i < rectsF.Length; ++i)
  1307. {
  1308. rects[i] = Rectangle.Truncate(rectsF[i]);
  1309. }
  1310. return rects;
  1311. }
  1312. public static Point[] TruncatePoints(PointF[] pointsF)
  1313. {
  1314. var points = new Point[pointsF.Length];
  1315. for (int i = 0; i < pointsF.Length; ++i)
  1316. {
  1317. points[i] = Point.Truncate(pointsF[i]);
  1318. }
  1319. return points;
  1320. }
  1321. public static Point[] RoundPoints(PointF[] pointsF)
  1322. {
  1323. var points = new Point[pointsF.Length];
  1324. for (int i = 0; i < pointsF.Length; ++i)
  1325. {
  1326. points[i] = Point.Round(pointsF[i]);
  1327. }
  1328. return points;
  1329. }
  1330. /// <summary>
  1331. /// The Sutherland-Hodgman clipping alrogithm.
  1332. /// http://ezekiel.vancouver.wsu.edu/~cs442/lectures/clip/clip/index.html
  1333. ///
  1334. /// # Clipping a convex polygon to a convex region (e.g., rectangle) will always produce a convex polygon (or no polygon if completely outside the clipping region).
  1335. /// # Clipping a concave polygon to a rectangle may produce several polygons (see figure above) or, as the following algorithm does, produce a single, possibly degenerate, polygon.
  1336. /// # Divide and conquer: Clip entire polygon against a single edge (i.e., half-plane). Repeat for each edge in the clipping region.
  1337. ///
  1338. /// The input is a sequence of vertices: {v0, v1, ... vn} given as an array of Points
  1339. /// the result is a sequence of vertices, given as an array of Points. This result may have
  1340. /// less than, equal, more than, or 0 vertices.
  1341. /// </summary>
  1342. /// <param name="vertices"></param>
  1343. ///<param name="bounds"></param>
  1344. ///<param name="v"></param>
  1345. ///<returns></returns>
  1346. public static List<PointF> SutherlandHodgman(RectangleF bounds, List<PointF> v)
  1347. {
  1348. List<PointF> p1 = SutherlandHodgmanOneAxis(bounds, RectangleEdge.Left, v);
  1349. List<PointF> p2 = SutherlandHodgmanOneAxis(bounds, RectangleEdge.Right, p1);
  1350. List<PointF> p3 = SutherlandHodgmanOneAxis(bounds, RectangleEdge.Top, p2);
  1351. List<PointF> p4 = SutherlandHodgmanOneAxis(bounds, RectangleEdge.Bottom, p3);
  1352. return p4;
  1353. }
  1354. private enum RectangleEdge
  1355. {
  1356. Left,
  1357. Right,
  1358. Top,
  1359. Bottom
  1360. }
  1361. private static List<PointF> SutherlandHodgmanOneAxis(RectangleF bounds, RectangleEdge edge, IList<PointF> v)
  1362. {
  1363. if (v.Count == 0)
  1364. {
  1365. return new List<PointF>();
  1366. }
  1367. var polygon = new List<PointF>();
  1368. PointF s = v[v.Count - 1];
  1369. foreach (PointF p in v)
  1370. {
  1371. bool pIn = IsInside(bounds, edge, p);
  1372. bool sIn = IsInside(bounds, edge, s);
  1373. if (sIn && pIn)
  1374. {
  1375. // case 1: inside -> inside
  1376. polygon.Add(p);
  1377. }
  1378. else if (sIn)
  1379. {
  1380. // case 2: inside -> outside
  1381. polygon.Add(LineIntercept(bounds, edge, s, p));
  1382. }
  1383. else if (!pIn)
  1384. {
  1385. // case 3: outside -> outside
  1386. // emit nothing
  1387. }
  1388. else
  1389. {
  1390. // case 4: outside -> inside
  1391. polygon.Add(LineIntercept(bounds, edge, s, p));
  1392. polygon.Add(p);
  1393. }
  1394. s = p;
  1395. }
  1396. return polygon;
  1397. }
  1398. private static bool IsInside(RectangleF bounds, RectangleEdge edge, PointF p)
  1399. {
  1400. switch (edge)
  1401. {
  1402. case RectangleEdge.Left:
  1403. return !(p.X < bounds.Left);
  1404. case RectangleEdge.Right:
  1405. return !(p.X >= bounds.Right);
  1406. case RectangleEdge.Top:
  1407. return !(p.Y < bounds.Top);
  1408. case RectangleEdge.Bottom:
  1409. return !(p.Y >= bounds.Bottom);
  1410. default:
  1411. throw new InvalidEnumArgumentException("edge");
  1412. }
  1413. }
  1414. /* UNUSED METHOD
  1415. private static Point LineIntercept(Rectangle bounds, RectangleEdge edge, Point a, Point b)
  1416. {
  1417. if (a == b)
  1418. {
  1419. return a;
  1420. }
  1421. switch (edge)
  1422. {
  1423. case RectangleEdge.Bottom:
  1424. if (b.Y == a.Y)
  1425. {
  1426. throw new ArgumentException("no intercept found");
  1427. }
  1428. return new Point(a.X + (((b.X - a.X) * (bounds.Bottom - a.Y)) / (b.Y - a.Y)), bounds.Bottom);
  1429. case RectangleEdge.Left:
  1430. if (b.X == a.X)
  1431. {
  1432. throw new ArgumentException("no intercept found");
  1433. }
  1434. return new Point(bounds.Left, a.Y + (((b.Y - a.Y) * (bounds.Left - a.X)) / (b.X - a.X)));
  1435. case RectangleEdge.Right:
  1436. if (b.X == a.X)
  1437. {
  1438. throw new ArgumentException("no intercept found");
  1439. }
  1440. return new Point(bounds.Right, a.Y + (((b.Y - a.Y) * (bounds.Right - a.X)) / (b.X - a.X)));
  1441. case RectangleEdge.Top:
  1442. if (b.Y == a.Y)
  1443. {
  1444. throw new ArgumentException("no intercept found");
  1445. }
  1446. return new Point(a.X + (((b.X - a.X) * (bounds.Top - a.Y)) / (b.Y - a.Y)), bounds.Top);
  1447. }
  1448. throw new ArgumentException("no intercept found");
  1449. }
  1450. */
  1451. private static PointF LineIntercept(RectangleF bounds, RectangleEdge edge, PointF a, PointF b)
  1452. {
  1453. if (a == b)
  1454. {
  1455. return a;
  1456. }
  1457. switch (edge)
  1458. {
  1459. case RectangleEdge.Bottom:
  1460. if (b.Y == a.Y)
  1461. {
  1462. throw new ArgumentException("no intercept found");
  1463. }
  1464. return new PointF(a.X + (((b.X - a.X) * (bounds.Bottom - a.Y)) / (b.Y - a.Y)), bounds.Bottom);
  1465. case RectangleEdge.Left:
  1466. if (b.X == a.X)
  1467. {
  1468. throw new ArgumentException("no intercept found");
  1469. }
  1470. return new PointF(bounds.Left, a.Y + (((b.Y - a.Y) * (bounds.Left - a.X)) / (b.X - a.X)));
  1471. case RectangleEdge.Right:
  1472. if (b.X == a.X)
  1473. {
  1474. throw new ArgumentException("no intercept found");
  1475. }
  1476. return new PointF(bounds.Right, a.Y + (((b.Y - a.Y) * (bounds.Right - a.X)) / (b.X - a.X)));
  1477. case RectangleEdge.Top:
  1478. if (b.Y == a.Y)
  1479. {
  1480. throw new ArgumentException("no intercept found");
  1481. }
  1482. return new PointF(a.X + (((b.X - a.X) * (bounds.Top - a.Y)) / (b.Y - a.Y)), bounds.Top);
  1483. }
  1484. throw new ArgumentException("no intercept found");
  1485. }
  1486. public static Point[] GetLinePoints(Point first, Point second)
  1487. {
  1488. Point[] coords;
  1489. int x1 = first.X;
  1490. int y1 = first.Y;
  1491. int x2 = second.X;
  1492. int y2 = second.Y;
  1493. int dx = x2 - x1;
  1494. int dy = y2 - y1;
  1495. int dxabs = Math.Abs(dx);
  1496. int dyabs = Math.Abs(dy);
  1497. int px = x1;
  1498. int py = y1;
  1499. int sdx = Math.Sign(dx);
  1500. int sdy = Math.Sign(dy);
  1501. int x = 0;
  1502. int y = 0;
  1503. if (dxabs > dyabs)
  1504. {
  1505. coords = new Point[dxabs + 1];
  1506. for (int i = 0; i <= dxabs; i++)
  1507. {
  1508. y += dyabs;
  1509. if (y >= dxabs)
  1510. {
  1511. y -= dxabs;
  1512. py += sdy;
  1513. }
  1514. coords[i] = new Point(px, py);
  1515. px += sdx;
  1516. }
  1517. }
  1518. else
  1519. // had to add in this cludge for slopes of 1 ... wasn't drawing half the line
  1520. if (dxabs == dyabs)
  1521. {
  1522. coords = new Point[dxabs + 1];
  1523. for (int i = 0; i <= dxabs; i++)
  1524. {
  1525. coords[i] = new Point(px, py);
  1526. px += sdx;
  1527. py += sdy;
  1528. }
  1529. }
  1530. else
  1531. {
  1532. coords = new Point[dyabs + 1];
  1533. for (int i = 0; i <= dyabs; i++)
  1534. {
  1535. x += dxabs;
  1536. if (x >= dyabs)
  1537. {
  1538. x -= dyabs;
  1539. px += sdx;
  1540. }
  1541. coords[i] = new Point(px, py);
  1542. py += sdy;
  1543. }
  1544. }
  1545. return coords;
  1546. }
  1547. public static long GetTimeMs()
  1548. {
  1549. return TicksToMs(DateTime.Now.Ticks);
  1550. }
  1551. /// <summary>
  1552. /// Returns the Distance between two points
  1553. /// </summary>
  1554. public static float Distance(PointF a, PointF b)
  1555. {
  1556. return Magnitude(new PointF(a.X - b.X, a.Y - b.Y));
  1557. }
  1558. /// <summary>
  1559. /// Returns the Magnitude (distance to origin) of a point
  1560. /// </summary>
  1561. // TODO: In v4.0 codebase, turn this into an extension method
  1562. public static float Magnitude(PointF p)
  1563. {
  1564. return (float)Math.Sqrt(p.X * p.X + p.Y * p.Y);
  1565. }
  1566. // TODO: In v4.0 codebase, turn this into an extension method
  1567. public static double Clamp(double x, double min, double max)
  1568. {
  1569. if (x < min)
  1570. {
  1571. return min;
  1572. }
  1573. return x > max ? max : x;
  1574. }
  1575. // TODO: In v4.0 codebase, turn this into an extension method
  1576. public static float Clamp(float x, float min, float max)
  1577. {
  1578. if (x < min)
  1579. {
  1580. return min;
  1581. }
  1582. return x > max ? max : x;
  1583. }
  1584. // TODO: In v4.0 codebase, turn this into an extension method
  1585. public static int Clamp(int x, int min, int max)
  1586. {
  1587. if (x < min)
  1588. {
  1589. return min;
  1590. }
  1591. return x > max ? max : x;
  1592. }
  1593. public static byte ClampToByte(double x)
  1594. {
  1595. if (x > 255)
  1596. {
  1597. return 255;
  1598. }
  1599. if (x < 0)
  1600. {
  1601. return 0;
  1602. }
  1603. return (byte)x;
  1604. }
  1605. public static byte ClampToByte(float x)
  1606. {
  1607. if (x > 255)
  1608. {
  1609. return 255;
  1610. }
  1611. if (x < 0)
  1612. {
  1613. return 0;
  1614. }
  1615. return (byte)x;
  1616. }
  1617. public static byte ClampToByte(int x)
  1618. {
  1619. if (x > 255)
  1620. {
  1621. return 255;
  1622. }
  1623. if (x < 0)
  1624. {
  1625. return 0;
  1626. }
  1627. return (byte)x;
  1628. }
  1629. public static float Lerp(float from, float to, float frac)
  1630. {
  1631. return (from + frac * (to - from));
  1632. }
  1633. public static double Lerp(double from, double to, double frac)
  1634. {
  1635. return (from + frac * (to - from));
  1636. }
  1637. public static PointF Lerp(PointF from, PointF to, float frac)
  1638. {
  1639. return new PointF(Lerp(from.X, to.X, frac), Lerp(from.Y, to.Y, frac));
  1640. }
  1641. public static int ColorDifference(ColorBgra a, ColorBgra b)
  1642. {
  1643. return (int)Math.Ceiling(Math.Sqrt(ColorDifferenceSquared(a, b)));
  1644. }
  1645. public static int ColorDifferenceSquared(ColorBgra a, ColorBgra b)
  1646. {
  1647. int diffSq = 0;
  1648. int tmp = a.R - b.R;
  1649. diffSq += tmp * tmp;
  1650. tmp = a.G - b.G;
  1651. diffSq += tmp * tmp;
  1652. tmp = a.B - b.B;
  1653. diffSq += tmp * tmp;
  1654. return diffSq / 3;
  1655. }
  1656. public static DialogResult ShowDialog(Form showMe, IWin32Window owner)
  1657. {
  1658. DialogResult dr;
  1659. if (showMe is PdnBaseForm)
  1660. {
  1661. var showMe2 = (PdnBaseForm)showMe;
  1662. double oldOpacity = showMe2.Opacity;
  1663. showMe2.Opacity = 0.9;
  1664. dr = showMe2.ShowDialog(owner);
  1665. showMe2.Opacity = oldOpacity;
  1666. }
  1667. else
  1668. {
  1669. double oldOpacity = showMe.Opacity;
  1670. showMe.Opacity = 0.9;
  1671. dr = showMe.ShowDialog(owner);
  1672. showMe.Opacity = oldOpacity;
  1673. }
  1674. var control = owner as Control;
  1675. if (control != null)
  1676. {
  1677. Form form = control.FindForm();
  1678. if (form != null)
  1679. {
  1680. form.Activate();
  1681. }
  1682. control.Update();
  1683. }
  1684. return dr;
  1685. }
  1686. public static void ShowHelp(Control parent)
  1687. {
  1688. string helpFileUrlFormat = PdnResources.GetString("HelpFile.Url.Format");
  1689. const string baseSiteUrl = InvariantStrings.WebsiteUrl;
  1690. string helpFileUrl = string.Format(helpFileUrlFormat, baseSiteUrl);
  1691. PdnInfo.OpenUrl(parent, helpFileUrl);
  1692. }
  1693. /// <summary>
  1694. /// Reads a 16-bit unsigned integer from a Stream in little-endian format.
  1695. /// </summary>
  1696. /// <param name="stream"></param>
  1697. /// <returns>-1 on failure, else the 16-bit unsigned integer that was read.</returns>
  1698. public static int ReadUInt16(Stream stream)
  1699. {
  1700. int byte1 = stream.ReadByte();
  1701. if (byte1 == -1)
  1702. {
  1703. return -1;
  1704. }
  1705. int byte2 = stream.ReadByte();
  1706. if (byte2 == -1)
  1707. {
  1708. return -1;
  1709. }
  1710. return byte1 + (byte2 << 8);
  1711. }
  1712. public static void WriteUInt16(Stream stream, UInt16 word)
  1713. {
  1714. stream.WriteByte((byte)(word & 0xff));
  1715. stream.WriteByte((byte)(word >> 8));
  1716. }
  1717. public static void WriteUInt24(Stream stream, int uint24)
  1718. {
  1719. stream.WriteByte((byte)(uint24 & 0xff));
  1720. stream.WriteByte((byte)((uint24 >> 8) & 0xff));
  1721. stream.WriteByte((byte)((uint24 >> 16) & 0xff));
  1722. }
  1723. public static void WriteUInt32(Stream stream, UInt32 uint32)
  1724. {
  1725. stream.WriteByte((byte)(uint32 & 0xff));
  1726. stream.WriteByte((byte)((uint32 >> 8) & 0xff));
  1727. stream.WriteByte((byte)((uint32 >> 16) & 0xff));
  1728. stream.WriteByte((byte)((uint32 >> 24) & 0xff));
  1729. }
  1730. /// <summary>
  1731. /// Reads a 24-bit unsigned integer from a Stream in little-endian format.
  1732. /// </summary>
  1733. /// <param name="stream"></param>
  1734. /// <returns>-1 on failure, else the 24-bit unsigned integer that was read.</returns>
  1735. public static int ReadUInt24(Stream stream)
  1736. {
  1737. int byte1 = stream.ReadByte();
  1738. if (byte1 == -1)
  1739. {
  1740. return -1;
  1741. }
  1742. int byte2 = stream.ReadByte();
  1743. if (byte2 == -1)
  1744. {
  1745. return -1;
  1746. }
  1747. int byte3 = stream.ReadByte();
  1748. if (byte3 == -1)
  1749. {
  1750. return -1;
  1751. }
  1752. return byte1 + (byte2 << 8) + (byte3 << 16);
  1753. }
  1754. /// <summary>
  1755. /// Reads a 32-bit unsigned integer from a Stream in little-endian format.
  1756. /// </summary>
  1757. /// <param name="stream"></param>
  1758. /// <returns>-1 on failure, else the 32-bit unsigned integer that was read.</returns>
  1759. public static long ReadUInt32(Stream stream)
  1760. {
  1761. int byte1 = stream.ReadByte();
  1762. if (byte1 == -1)
  1763. {
  1764. return -1;
  1765. }
  1766. int byte2 = stream.ReadByte();
  1767. if (byte2 == -1)
  1768. {
  1769. return -1;
  1770. }
  1771. int byte3 = stream.ReadByte();
  1772. if (byte3 == -1)
  1773. {
  1774. return -1;
  1775. }
  1776. int byte4 = stream.ReadByte();
  1777. if (byte4 == -1)
  1778. {
  1779. return -1;
  1780. }
  1781. return unchecked((uint)(byte1 + (byte2 << 8) + (byte3 << 16) + (byte4 << 24)));
  1782. }
  1783. public static int ReadFromStream(Stream input, byte[] buffer, int offset, int count)
  1784. {
  1785. int totalBytesRead = 0;
  1786. while (totalBytesRead < count)
  1787. {
  1788. int bytesRead = input.Read(buffer, offset + totalBytesRead, count - totalBytesRead);
  1789. if (bytesRead == 0)
  1790. {
  1791. throw new IOException("ran out of data");
  1792. }
  1793. totalBytesRead += bytesRead;
  1794. }
  1795. return totalBytesRead;
  1796. }
  1797. public static long CopyStream(Stream input, Stream output, long maxBytes)
  1798. {
  1799. long bytesCopied = 0;
  1800. var buffer = new byte[4096];
  1801. while (true)
  1802. {
  1803. int bytesRead = input.Read(buffer, 0, buffer.Length);
  1804. if (bytesRead == 0)
  1805. {
  1806. break;
  1807. }
  1808. int bytesToCopy;
  1809. if (maxBytes != -1 && (bytesCopied + bytesRead) > maxBytes)
  1810. {
  1811. bytesToCopy = (int)(maxBytes - bytesCopied);
  1812. }
  1813. else
  1814. {
  1815. bytesToCopy = bytesRead;
  1816. }
  1817. output.Write(buffer, 0, bytesRead);
  1818. bytesCopied += bytesToCopy;
  1819. if (bytesToCopy != bytesRead)
  1820. {
  1821. break;
  1822. }
  1823. }
  1824. return bytesCopied;
  1825. }
  1826. public static long CopyStream(Stream input, Stream output)
  1827. {
  1828. return CopyStream(input, output, -1);
  1829. }
  1830. private struct Edge
  1831. {
  1832. public readonly int Miny; // int
  1833. public readonly int Maxy; // int
  1834. public int X; // fixed point: 24.8
  1835. public readonly int Dxdy; // fixed point: 24.8
  1836. public Edge(int miny, int maxy, int x, int dxdy)
  1837. {
  1838. Miny = miny;
  1839. Maxy = maxy;
  1840. X = x;
  1841. Dxdy = dxdy;
  1842. }
  1843. }
  1844. public static Scanline[] GetScans(Point[] vertices)
  1845. {
  1846. return GetScans(vertices, 0, vertices.Length);
  1847. }
  1848. public static Scanline[] GetScans(Point[] vertices, int startIndex, int length)
  1849. {
  1850. if (length > vertices.Length - startIndex)
  1851. {
  1852. throw new ArgumentException("out of bounds: length > vertices.Length - startIndex");
  1853. }
  1854. int ymax = 0;
  1855. // Build edge table
  1856. var edgeTable = new Edge[length];
  1857. int edgeCount = 0;
  1858. for (int i = startIndex; i < startIndex + length; ++i)
  1859. {
  1860. Point top = vertices[i];
  1861. Point bottom = vertices[(((i + 1) - startIndex) % length) + startIndex];
  1862. if (top.Y > bottom.Y)
  1863. {
  1864. Point temp = top;
  1865. top = bottom;
  1866. bottom = temp;
  1867. }
  1868. int dy = bottom.Y - top.Y;
  1869. if (dy == 0) continue;
  1870. edgeTable[edgeCount] = new Edge(top.Y, bottom.Y, top.X << 8, (((bottom.X - top.X) << 8) / dy));
  1871. ymax = Math.Max(ymax, bottom.Y);
  1872. ++edgeCount;
  1873. }
  1874. // Sort edge table by miny
  1875. for (int i = 0; i < edgeCount - 1; ++i)
  1876. {
  1877. int min = i;
  1878. for (int j = i + 1; j < edgeCount; ++j)
  1879. {
  1880. if (edgeTable[j].Miny < edgeTable[min].Miny)
  1881. {
  1882. min = j;
  1883. }
  1884. }
  1885. if (min == i) continue;
  1886. Edge temp = edgeTable[min];
  1887. edgeTable[min] = edgeTable[i];
  1888. edgeTable[i] = temp;
  1889. }
  1890. // Compute how many scanlines we will be emitting
  1891. int scanCount = 0;
  1892. int activeLow = 0;
  1893. int activeHigh = 0;
  1894. int yscan1 = edgeTable[0].Miny;
  1895. // we assume that edgeTable[0].miny == yscan
  1896. while (activeHigh < edgeCount - 1 &&
  1897. edgeTable[activeHigh + 1].Miny == yscan1)
  1898. {
  1899. ++activeHigh;
  1900. }
  1901. while (yscan1 <= ymax)
  1902. {
  1903. // Find new edges where yscan == miny
  1904. while (activeHigh < edgeCount - 1 &&
  1905. edgeTable[activeHigh + 1].Miny == yscan1)
  1906. {
  1907. ++activeHigh;
  1908. }
  1909. int count = 0;
  1910. for (int i = activeLow; i <= activeHigh; ++i)
  1911. {
  1912. if (edgeTable[i].Maxy > yscan1)
  1913. {
  1914. ++count;
  1915. }
  1916. }
  1917. scanCount += count / 2;
  1918. ++yscan1;
  1919. // Remove edges where yscan == maxy
  1920. while (activeLow < edgeCount - 1 &&
  1921. edgeTable[activeLow].Maxy <= yscan1)
  1922. {
  1923. ++activeLow;
  1924. }
  1925. if (activeLow > activeHigh)
  1926. {
  1927. activeHigh = activeLow;
  1928. }
  1929. }
  1930. // Allocate scanlines that we'll return
  1931. var scans = new Scanline[scanCount];
  1932. // Active Edge Table (AET): it is indices into the Edge Table (ET)
  1933. var active = new int[edgeCount];
  1934. int activeCount = 0;
  1935. int yscan2 = edgeTable[0].Miny;
  1936. int scansIndex = 0;
  1937. // Repeat until both the ET and AET are empty
  1938. while (yscan2 <= ymax)
  1939. {
  1940. // Move any edges from the ET to the AET where yscan == miny
  1941. for (int i = 0; i < edgeCount; ++i)
  1942. {
  1943. if (edgeTable[i].Miny != yscan2) continue;
  1944. active[activeCount] = i;
  1945. ++activeCount;
  1946. }
  1947. // Sort the AET on x
  1948. for (int i = 0; i < activeCount - 1; ++i)
  1949. {
  1950. int min = i;
  1951. for (int j = i + 1; j < activeCount; ++j)
  1952. {
  1953. if (edgeTable[active[j]].X < edgeTable[active[min]].X)
  1954. {
  1955. min = j;
  1956. }
  1957. }
  1958. if (min == i) continue;
  1959. int temp = active[min];
  1960. active[min] = active[i];
  1961. active[i] = temp;
  1962. }
  1963. // For each pair of entries in the AET, fill in pixels between their info
  1964. for (int i = 0; i < activeCount; i += 2)
  1965. {
  1966. Edge el = edgeTable[active[i]];
  1967. Edge er = edgeTable[active[i + 1]];
  1968. int startx = (el.X + 0xff) >> 8; // ceil(x)
  1969. int endx = er.X >> 8; // floor(x)
  1970. scans[scansIndex] = new Scanline(startx, yscan2, endx - startx);
  1971. ++scansIndex;
  1972. }
  1973. ++yscan2;
  1974. // Remove from the AET any edge where yscan == maxy
  1975. int k = 0;
  1976. while (k < activeCount && activeCount > 0)
  1977. {
  1978. if (edgeTable[active[k]].Maxy == yscan2)
  1979. {
  1980. // remove by shifting everything down one
  1981. for (int j = k + 1; j < activeCount; ++j)
  1982. {
  1983. active[j - 1] = active[j];
  1984. }
  1985. --activeCount;
  1986. }
  1987. else
  1988. {
  1989. ++k;
  1990. }
  1991. }
  1992. // Update x for each entry in AET
  1993. for (int i = 0; i < activeCount; ++i)
  1994. {
  1995. edgeTable[active[i]].X += edgeTable[active[i]].Dxdy;
  1996. }
  1997. }
  1998. return scans;
  1999. }
  2000. public static PointF TransformOnePoint(Matrix matrix, PointF ptF)
  2001. {
  2002. var ptFs = new[] { ptF };
  2003. matrix.TransformPoints(ptFs);
  2004. return ptFs[0];
  2005. }
  2006. public static PointF TransformOneVector(Matrix matrix, PointF ptF)
  2007. {
  2008. var ptFs = new[] { ptF };
  2009. matrix.TransformVectors(ptFs);
  2010. return ptFs[0];
  2011. }
  2012. public static PointF NormalizeVector(PointF vecF)
  2013. {
  2014. float magnitude = Magnitude(vecF);
  2015. vecF.X /= magnitude;
  2016. vecF.Y /= magnitude;
  2017. return vecF;
  2018. }
  2019. public static PointF NormalizeVector2(PointF vecF)
  2020. {
  2021. float magnitude = Magnitude(vecF);
  2022. if (magnitude == 0)
  2023. {
  2024. vecF.X = 0;
  2025. vecF.Y = 0;
  2026. }
  2027. else
  2028. {
  2029. vecF.X /= magnitude;
  2030. vecF.Y /= magnitude;
  2031. }
  2032. return vecF;
  2033. }
  2034. public static void NormalizeVectors(PointF[] vecsF)
  2035. {
  2036. for (int i = 0; i < vecsF.Length; ++i)
  2037. {
  2038. vecsF[i] = NormalizeVector(vecsF[i]);
  2039. }
  2040. }
  2041. public static PointF RotateVector(PointF vecF, float angleDelta)
  2042. {
  2043. angleDelta *= (float)( Math.PI / 180.0);
  2044. float vecFLen = Magnitude(vecF);
  2045. float vecFAngle = angleDelta + (float)Math.Atan2(vecF.Y, vecF.X);
  2046. vecF.X = (float)Math.Cos(vecFAngle);
  2047. vecF.Y = (float)Math.Sin(vecFAngle);
  2048. return vecF;
  2049. }
  2050. public static void RotateVectors(PointF[] vecFs, float angleDelta)
  2051. {
  2052. for (int i = 0; i < vecFs.Length; ++i)
  2053. {
  2054. vecFs[i] = RotateVector(vecFs[i], angleDelta);
  2055. }
  2056. }
  2057. public static PointF MultiplyVector(PointF vecF, float scalar)
  2058. {
  2059. return new PointF(vecF.X * scalar, vecF.Y * scalar);
  2060. }
  2061. public static PointF AddVectors(PointF a, PointF b)
  2062. {
  2063. return new PointF(a.X + b.X, a.Y + b.Y);
  2064. }
  2065. public static PointF SubtractVectors(PointF lhs, PointF rhs)
  2066. {
  2067. return new PointF(lhs.X - rhs.X, lhs.Y - rhs.Y);
  2068. }
  2069. public static PointF NegateVector(PointF v)
  2070. {
  2071. return new PointF(-v.X, -v.Y);
  2072. }
  2073. public static float GetAngleOfTransform(Matrix matrix)
  2074. {
  2075. var pts = new[] { new PointF(1.0f, 0.0f) };
  2076. matrix.TransformVectors(pts);
  2077. double atan2 = Math.Atan2(pts[0].Y, pts[0].X);
  2078. double angle = atan2 * (180.0f / Math.PI);
  2079. return (float)angle;
  2080. }
  2081. public static bool IsTransformFlipped(Matrix matrix)
  2082. {
  2083. var ptX = new PointF(1.0f, 0.0f);
  2084. PointF ptXT = TransformOneVector(matrix, ptX);
  2085. double atan2X = Math.Atan2(ptXT.Y, ptXT.X);
  2086. double angleX = atan2X * (180.0 / Math.PI);
  2087. var ptY = new PointF(0.0f, 1.0f);
  2088. PointF ptYT = TransformOneVector(matrix, ptY);
  2089. double atan2Y = Math.Atan2(ptYT.Y, ptYT.X);
  2090. double angleY = (atan2Y * (180.0 / Math.PI)) - 90.0;
  2091. while (angleX < 0)
  2092. {
  2093. angleX += 360;
  2094. }
  2095. while (angleY < 0)
  2096. {
  2097. angleY += 360;
  2098. }
  2099. double angleDelta = Math.Abs(angleX - angleY);
  2100. return angleDelta > 1.0 && angleDelta < 359.0;
  2101. }
  2102. /// <summary>
  2103. /// Calculates the dot product of two vectors.
  2104. /// </summary>
  2105. public static float DotProduct(PointF lhs, PointF rhs)
  2106. {
  2107. return lhs.X * rhs.X + lhs.Y * rhs.Y;
  2108. }
  2109. /// <summary>
  2110. /// Calculates the orthogonal projection of y on to u.
  2111. /// yhat = u * ((y dot u) / (u dot u))
  2112. /// z = y - yhat
  2113. /// Section 6.2 (pg. 381) of Linear Algebra and its Applications, Second Edition, by David C. Lay
  2114. /// </summary>
  2115. /// <param name="y">The vector to decompose</param>
  2116. /// <param name="u">The non-zero vector to project y on to</param>
  2117. /// <param name="yhat">The orthogonal projection of y onto u</param>
  2118. /// <param name="yhatLen">The length of yhat such that yhat = yhatLen * u</param>
  2119. /// <param name="z">The component of y orthogonal to u</param>
  2120. /// <remarks>
  2121. /// As a special case, if u=(0,0) the results are all zero.
  2122. /// </remarks>
  2123. public static void GetProjection(PointF y, PointF u, out PointF yhat, out float yhatLen, out PointF z)
  2124. {
  2125. if (u.X == 0 && u.Y == 0)
  2126. {
  2127. yhat = new PointF(0, 0);
  2128. yhatLen = 0;
  2129. z = new PointF(0, 0);
  2130. }
  2131. else
  2132. {
  2133. float yDotU = DotProduct(y, u);
  2134. float uDotU = DotProduct(u, u);
  2135. yhatLen = yDotU / uDotU;
  2136. yhat = MultiplyVector(u, yhatLen);
  2137. z = SubtractVectors(y, yhat);
  2138. }
  2139. }
  2140. public static int GreatestCommonDivisor(int a, int b)
  2141. {
  2142. int r;
  2143. if (a < b)
  2144. {
  2145. r = a;
  2146. a = b;
  2147. b = r;
  2148. }
  2149. do
  2150. {
  2151. r = a % b;
  2152. a = b;
  2153. b = r;
  2154. } while (r != 0);
  2155. return a;
  2156. }
  2157. public static void Swap(ref int a, ref int b)
  2158. {
  2159. int t = a;
  2160. a = b;
  2161. b = t;
  2162. }
  2163. public static void Swap<T>(ref T a, ref T b)
  2164. {
  2165. T t = a;
  2166. a = b;
  2167. b = t;
  2168. }
  2169. private static byte[] DownloadSmallFile(Uri uri, IWebProxy proxy)
  2170. {
  2171. WebRequest request = WebRequest.Create(uri);
  2172. if (proxy != null)
  2173. {
  2174. request.Proxy = proxy;
  2175. }
  2176. request.Timeout = 5000;
  2177. WebResponse response = request.GetResponse();
  2178. if (response != null) // if any bugs occur, check from this line to the line where another // is
  2179. {
  2180. Stream stream = response.GetResponseStream();
  2181. try
  2182. {
  2183. var buffer = new byte[8192];
  2184. int offset = 0;
  2185. while (offset < buffer.Length)
  2186. {
  2187. if (stream == null) continue;
  2188. int bytesRead = stream.Read(buffer, offset, buffer.Length - offset);
  2189. if (bytesRead == 0)
  2190. {
  2191. var smallerBuffer = new byte[offset + bytesRead];
  2192. for (int i = 0; i < offset + bytesRead; ++i)
  2193. {
  2194. smallerBuffer[i] = buffer[i];
  2195. }
  2196. buffer = smallerBuffer;
  2197. }
  2198. offset += bytesRead;
  2199. }
  2200. return buffer;
  2201. }
  2202. finally
  2203. {
  2204. if (stream != null)
  2205. {
  2206. stream.Close();
  2207. stream = null;
  2208. }
  2209. {
  2210. response.Close();
  2211. response = null;
  2212. }
  2213. }
  2214. }
  2215. return new byte[] {}; //
  2216. }
  2217. public static T[] RepeatArray<T>(T[] array, int repeatCount)
  2218. {
  2219. var returnArray = new T[repeatCount * array.Length];
  2220. for (int i = 0; i < repeatCount; ++i)
  2221. {
  2222. for (int j = 0; j < array.Length; ++j)
  2223. {
  2224. int index = (i * array.Length) + j;
  2225. returnArray[index] = array[j];
  2226. }
  2227. }
  2228. return returnArray;
  2229. }
  2230. /// <summary>
  2231. /// Downloads a small file (max 8192 bytes) and returns it as a byte array.
  2232. /// </summary>
  2233. /// <returns>The contents of the file if downloaded successfully.</returns>
  2234. public static byte[] DownloadSmallFile(Uri uri)
  2235. {
  2236. byte[] bytes = null;
  2237. Exception exception = null;
  2238. WebProxy[] proxiesPre = Network.GetProxyList();
  2239. WebProxy[] proxies = RepeatArray(proxiesPre, 2); // see bug #1942
  2240. foreach (WebProxy proxy in proxies)
  2241. {
  2242. try
  2243. {
  2244. bytes = DownloadSmallFile(uri, proxy);
  2245. exception = null;
  2246. }
  2247. catch (Exception ex)
  2248. {
  2249. exception = ex;
  2250. bytes = null;
  2251. }
  2252. if (bytes != null)
  2253. {
  2254. break;
  2255. }
  2256. }
  2257. if (exception != null)
  2258. {
  2259. var we = exception as WebException;
  2260. if (we != null)
  2261. {
  2262. throw new WebException(null, we, we.Status, we.Response);
  2263. }
  2264. throw new ApplicationException("An exception occurred while trying to download '" + uri + "'", exception);
  2265. }
  2266. return bytes;
  2267. }
  2268. private static void DownloadFile(Uri uri, Stream output, IWebProxy proxy, ProgressEventHandler progressCallback)
  2269. {
  2270. WebRequest request = WebRequest.Create(uri);
  2271. if (proxy != null)
  2272. {
  2273. request.Proxy = proxy;
  2274. }
  2275. request.Timeout = 5000;
  2276. WebResponse response = request.GetResponse();
  2277. Stream stream = null;
  2278. SiphonStream siphonOutputStream = null;
  2279. try
  2280. {
  2281. if (response != null) stream = response.GetResponseStream();
  2282. siphonOutputStream = new SiphonStream(output, 1024); // monitor the completion of writes to 'output'
  2283. WebResponse response1 = response;
  2284. siphonOutputStream.IOFinished +=
  2285. delegate(object sender, IOEventArgs e)
  2286. {
  2287. if (progressCallback == null) return;
  2288. if (response1 == null) return;
  2289. double percent = 100.0 * Clamp(((double)e.Position / (double)response1.ContentLength), 0, 100);
  2290. progressCallback(uri, new ProgressEventArgs(percent));
  2291. };
  2292. CopyStream(stream, siphonOutputStream, 128 * 1024 * 1024); // cap at 128mb
  2293. siphonOutputStream.Flush();
  2294. }
  2295. finally
  2296. {
  2297. if (siphonOutputStream != null)
  2298. {
  2299. siphonOutputStream.Close();
  2300. siphonOutputStream = null;
  2301. }
  2302. if (stream != null)
  2303. {
  2304. stream.Close();
  2305. stream = null;
  2306. }
  2307. if (response != null)
  2308. {
  2309. response.Close();
  2310. response = null;
  2311. }
  2312. }
  2313. }
  2314. /// <summary>
  2315. /// Download a file (max 128MB) and saves it to the given Stream.
  2316. /// </summary>
  2317. public static void DownloadFile(Uri uri, Stream output, ProgressEventHandler progressCallback)
  2318. {
  2319. long startPosition = output.Position;
  2320. Exception exception = null;
  2321. WebProxy[] proxies = Network.GetProxyList();
  2322. foreach (WebProxy proxy in proxies)
  2323. {
  2324. bool success = false;
  2325. try
  2326. {
  2327. DownloadFile(uri, output, proxy, progressCallback);
  2328. exception = null;
  2329. success = true;
  2330. }
  2331. catch (Exception ex)
  2332. {
  2333. exception = ex;
  2334. }
  2335. // If the output stream was written to, then we know
  2336. // that we were either successful in downloading the
  2337. // file, or there was an error unrelated to using the
  2338. // proxy (maybe they unplugged the network cable, who
  2339. // knows!)
  2340. if (output.Position != startPosition || success)
  2341. {
  2342. break;
  2343. }
  2344. }
  2345. if (exception == null)
  2346. {
  2347. }
  2348. else
  2349. {
  2350. var we = exception as WebException;
  2351. if (we != null)
  2352. {
  2353. throw new WebException(null, we, we.Status, we.Response);
  2354. }
  2355. throw new ApplicationException(
  2356. "An exception occurred while trying to download '" + uri + "'", exception);
  2357. }
  2358. }
  2359. public static byte FastScaleByteByByte(byte a, byte b)
  2360. {
  2361. int r1 = a * b + 0x80;
  2362. int r2 = ((r1 >> 8) + r1) >> 8;
  2363. return (byte)r2;
  2364. }
  2365. public static int FastDivideShortByByte(ushort n, byte d)
  2366. {
  2367. int i = d * 3;
  2368. uint m = MasTable[i];
  2369. uint a = MasTable[i + 1];
  2370. uint s = MasTable[i + 2];
  2371. uint nTimesMPlusA = unchecked((n * m) + a);
  2372. uint shifted = nTimesMPlusA >> (int)s;
  2373. var r = (int)shifted;
  2374. return r;
  2375. }
  2376. // i = z * 3;
  2377. // (x / z) = ((x * masTable[i]) + masTable[i + 1]) >> masTable[i + 2)
  2378. private static readonly uint[] MasTable =
  2379. {
  2380. 0x00000000, 0x00000000, 0, // 0
  2381. 0x00000001, 0x00000000, 0, // 1
  2382. 0x00000001, 0x00000000, 1, // 2
  2383. 0xAAAAAAAB, 0x00000000, 33, // 3
  2384. 0x00000001, 0x00000000, 2, // 4
  2385. 0xCCCCCCCD, 0x00000000, 34, // 5
  2386. 0xAAAAAAAB, 0x00000000, 34, // 6
  2387. 0x49249249, 0x49249249, 33, // 7
  2388. 0x00000001, 0x00000000, 3, // 8
  2389. 0x38E38E39, 0x00000000, 33, // 9
  2390. 0xCCCCCCCD, 0x00000000, 35, // 10
  2391. 0xBA2E8BA3, 0x00000000, 35, // 11
  2392. 0xAAAAAAAB, 0x00000000, 35, // 12
  2393. 0x4EC4EC4F, 0x00000000, 34, // 13
  2394. 0x49249249, 0x49249249, 34, // 14
  2395. 0x88888889, 0x00000000, 35, // 15
  2396. 0x00000001, 0x00000000, 4, // 16
  2397. 0xF0F0F0F1, 0x00000000, 36, // 17
  2398. 0x38E38E39, 0x00000000, 34, // 18
  2399. 0xD79435E5, 0xD79435E5, 36, // 19
  2400. 0xCCCCCCCD, 0x00000000, 36, // 20
  2401. 0xC30C30C3, 0xC30C30C3, 36, // 21
  2402. 0xBA2E8BA3, 0x00000000, 36, // 22
  2403. 0xB21642C9, 0x00000000, 36, // 23
  2404. 0xAAAAAAAB, 0x00000000, 36, // 24
  2405. 0x51EB851F, 0x00000000, 35, // 25
  2406. 0x4EC4EC4F, 0x00000000, 35, // 26
  2407. 0x97B425ED, 0x97B425ED, 36, // 27
  2408. 0x49249249, 0x49249249, 35, // 28
  2409. 0x8D3DCB09, 0x00000000, 36, // 29
  2410. 0x88888889, 0x00000000, 36, // 30
  2411. 0x42108421, 0x42108421, 35, // 31
  2412. 0x00000001, 0x00000000, 5, // 32
  2413. 0x3E0F83E1, 0x00000000, 35, // 33
  2414. 0xF0F0F0F1, 0x00000000, 37, // 34
  2415. 0x75075075, 0x75075075, 36, // 35
  2416. 0x38E38E39, 0x00000000, 35, // 36
  2417. 0x6EB3E453, 0x6EB3E453, 36, // 37
  2418. 0xD79435E5, 0xD79435E5, 37, // 38
  2419. 0x69069069, 0x69069069, 36, // 39
  2420. 0xCCCCCCCD, 0x00000000, 37, // 40
  2421. 0xC7CE0C7D, 0x00000000, 37, // 41
  2422. 0xC30C30C3, 0xC30C30C3, 37, // 42
  2423. 0x2FA0BE83, 0x00000000, 35, // 43
  2424. 0xBA2E8BA3, 0x00000000, 37, // 44
  2425. 0x5B05B05B, 0x5B05B05B, 36, // 45
  2426. 0xB21642C9, 0x00000000, 37, // 46
  2427. 0xAE4C415D, 0x00000000, 37, // 47
  2428. 0xAAAAAAAB, 0x00000000, 37, // 48
  2429. 0x5397829D, 0x00000000, 36, // 49
  2430. 0x51EB851F, 0x00000000, 36, // 50
  2431. 0xA0A0A0A1, 0x00000000, 37, // 51
  2432. 0x4EC4EC4F, 0x00000000, 36, // 52
  2433. 0x9A90E7D9, 0x9A90E7D9, 37, // 53
  2434. 0x97B425ED, 0x97B425ED, 37, // 54
  2435. 0x94F2094F, 0x94F2094F, 37, // 55
  2436. 0x49249249, 0x49249249, 36, // 56
  2437. 0x47DC11F7, 0x47DC11F7, 36, // 57
  2438. 0x8D3DCB09, 0x00000000, 37, // 58
  2439. 0x22B63CBF, 0x00000000, 35, // 59
  2440. 0x88888889, 0x00000000, 37, // 60
  2441. 0x4325C53F, 0x00000000, 36, // 61
  2442. 0x42108421, 0x42108421, 36, // 62
  2443. 0x41041041, 0x41041041, 36, // 63
  2444. 0x00000001, 0x00000000, 6, // 64
  2445. 0xFC0FC0FD, 0x00000000, 38, // 65
  2446. 0x3E0F83E1, 0x00000000, 36, // 66
  2447. 0x07A44C6B, 0x00000000, 33, // 67
  2448. 0xF0F0F0F1, 0x00000000, 38, // 68
  2449. 0x76B981DB, 0x00000000, 37, // 69
  2450. 0x75075075, 0x75075075, 37, // 70
  2451. 0xE6C2B449, 0x00000000, 38, // 71
  2452. 0x38E38E39, 0x00000000, 36, // 72
  2453. 0x381C0E07, 0x381C0E07, 36, // 73
  2454. 0x6EB3E453, 0x6EB3E453, 37, // 74
  2455. 0x1B4E81B5, 0x00000000, 35, // 75
  2456. 0xD79435E5, 0xD79435E5, 38, // 76
  2457. 0x3531DEC1, 0x00000000, 36, // 77
  2458. 0x69069069, 0x69069069, 37, // 78
  2459. 0xCF6474A9, 0x00000000, 38, // 79
  2460. 0xCCCCCCCD, 0x00000000, 38, // 80
  2461. 0xCA4587E7, 0x00000000, 38, // 81
  2462. 0xC7CE0C7D, 0x00000000, 38, // 82
  2463. 0x3159721F, 0x00000000, 36, // 83
  2464. 0xC30C30C3, 0xC30C30C3, 38, // 84
  2465. 0xC0C0C0C1, 0x00000000, 38, // 85
  2466. 0x2FA0BE83, 0x00000000, 36, // 86
  2467. 0x2F149903, 0x00000000, 36, // 87
  2468. 0xBA2E8BA3, 0x00000000, 38, // 88
  2469. 0xB81702E1, 0x00000000, 38, // 89
  2470. 0x5B05B05B, 0x5B05B05B, 37, // 90
  2471. 0x2D02D02D, 0x2D02D02D, 36, // 91
  2472. 0xB21642C9, 0x00000000, 38, // 92
  2473. 0xB02C0B03, 0x00000000, 38, // 93
  2474. 0xAE4C415D, 0x00000000, 38, // 94
  2475. 0x2B1DA461, 0x2B1DA461, 36, // 95
  2476. 0xAAAAAAAB, 0x00000000, 38, // 96
  2477. 0xA8E83F57, 0xA8E83F57, 38, // 97
  2478. 0x5397829D, 0x00000000, 37, // 98
  2479. 0xA57EB503, 0x00000000, 38, // 99
  2480. 0x51EB851F, 0x00000000, 37, // 100
  2481. 0xA237C32B, 0xA237C32B, 38, // 101
  2482. 0xA0A0A0A1, 0x00000000, 38, // 102
  2483. 0x9F1165E7, 0x9F1165E7, 38, // 103
  2484. 0x4EC4EC4F, 0x00000000, 37, // 104
  2485. 0x27027027, 0x27027027, 36, // 105
  2486. 0x9A90E7D9, 0x9A90E7D9, 38, // 106
  2487. 0x991F1A51, 0x991F1A51, 38, // 107
  2488. 0x97B425ED, 0x97B425ED, 38, // 108
  2489. 0x2593F69B, 0x2593F69B, 36, // 109
  2490. 0x94F2094F, 0x94F2094F, 38, // 110
  2491. 0x24E6A171, 0x24E6A171, 36, // 111
  2492. 0x49249249, 0x49249249, 37, // 112
  2493. 0x90FDBC09, 0x90FDBC09, 38, // 113
  2494. 0x47DC11F7, 0x47DC11F7, 37, // 114
  2495. 0x8E78356D, 0x8E78356D, 38, // 115
  2496. 0x8D3DCB09, 0x00000000, 38, // 116
  2497. 0x23023023, 0x23023023, 36, // 117
  2498. 0x22B63CBF, 0x00000000, 36, // 118
  2499. 0x44D72045, 0x00000000, 37, // 119
  2500. 0x88888889, 0x00000000, 38, // 120
  2501. 0x8767AB5F, 0x8767AB5F, 38, // 121
  2502. 0x4325C53F, 0x00000000, 37, // 122
  2503. 0x85340853, 0x85340853, 38, // 123
  2504. 0x42108421, 0x42108421, 37, // 124
  2505. 0x10624DD3, 0x00000000, 35, // 125
  2506. 0x41041041, 0x41041041, 37, // 126
  2507. 0x10204081, 0x10204081, 35, // 127
  2508. 0x00000001, 0x00000000, 7, // 128
  2509. 0x0FE03F81, 0x00000000, 35, // 129
  2510. 0xFC0FC0FD, 0x00000000, 39, // 130
  2511. 0xFA232CF3, 0x00000000, 39, // 131
  2512. 0x3E0F83E1, 0x00000000, 37, // 132
  2513. 0xF6603D99, 0x00000000, 39, // 133
  2514. 0x07A44C6B, 0x00000000, 34, // 134
  2515. 0xF2B9D649, 0x00000000, 39, // 135
  2516. 0xF0F0F0F1, 0x00000000, 39, // 136
  2517. 0x077975B9, 0x00000000, 34, // 137
  2518. 0x76B981DB, 0x00000000, 38, // 138
  2519. 0x75DED953, 0x00000000, 38, // 139
  2520. 0x75075075, 0x75075075, 38, // 140
  2521. 0x3A196B1F, 0x00000000, 37, // 141
  2522. 0xE6C2B449, 0x00000000, 39, // 142
  2523. 0xE525982B, 0x00000000, 39, // 143
  2524. 0x38E38E39, 0x00000000, 37, // 144
  2525. 0xE1FC780F, 0x00000000, 39, // 145
  2526. 0x381C0E07, 0x381C0E07, 37, // 146
  2527. 0xDEE95C4D, 0x00000000, 39, // 147
  2528. 0x6EB3E453, 0x6EB3E453, 38, // 148
  2529. 0xDBEB61EF, 0x00000000, 39, // 149
  2530. 0x1B4E81B5, 0x00000000, 36, // 150
  2531. 0x36406C81, 0x00000000, 37, // 151
  2532. 0xD79435E5, 0xD79435E5, 39, // 152
  2533. 0xD62B80D7, 0x00000000, 39, // 153
  2534. 0x3531DEC1, 0x00000000, 37, // 154
  2535. 0xD3680D37, 0x00000000, 39, // 155
  2536. 0x69069069, 0x69069069, 38, // 156
  2537. 0x342DA7F3, 0x00000000, 37, // 157
  2538. 0xCF6474A9, 0x00000000, 39, // 158
  2539. 0xCE168A77, 0xCE168A77, 39, // 159
  2540. 0xCCCCCCCD, 0x00000000, 39, // 160
  2541. 0xCB8727C1, 0x00000000, 39, // 161
  2542. 0xCA4587E7, 0x00000000, 39, // 162
  2543. 0xC907DA4F, 0x00000000, 39, // 163
  2544. 0xC7CE0C7D, 0x00000000, 39, // 164
  2545. 0x634C0635, 0x00000000, 38, // 165
  2546. 0x3159721F, 0x00000000, 37, // 166
  2547. 0x621B97C3, 0x00000000, 38, // 167
  2548. 0xC30C30C3, 0xC30C30C3, 39, // 168
  2549. 0x60F25DEB, 0x00000000, 38, // 169
  2550. 0xC0C0C0C1, 0x00000000, 39, // 170
  2551. 0x17F405FD, 0x17F405FD, 36, // 171
  2552. 0x2FA0BE83, 0x00000000, 37, // 172
  2553. 0xBD691047, 0xBD691047, 39, // 173
  2554. 0x2F149903, 0x00000000, 37, // 174
  2555. 0x5D9F7391, 0x00000000, 38, // 175
  2556. 0xBA2E8BA3, 0x00000000, 39, // 176
  2557. 0x5C90A1FD, 0x5C90A1FD, 38, // 177
  2558. 0xB81702E1, 0x00000000, 39, // 178
  2559. 0x5B87DDAD, 0x5B87DDAD, 38, // 179
  2560. 0x5B05B05B, 0x5B05B05B, 38, // 180
  2561. 0xB509E68B, 0x00000000, 39, // 181
  2562. 0x2D02D02D, 0x2D02D02D, 37, // 182
  2563. 0xB30F6353, 0x00000000, 39, // 183
  2564. 0xB21642C9, 0x00000000, 39, // 184
  2565. 0x1623FA77, 0x1623FA77, 36, // 185
  2566. 0xB02C0B03, 0x00000000, 39, // 186
  2567. 0xAF3ADDC7, 0x00000000, 39, // 187
  2568. 0xAE4C415D, 0x00000000, 39, // 188
  2569. 0x15AC056B, 0x15AC056B, 36, // 189
  2570. 0x2B1DA461, 0x2B1DA461, 37, // 190
  2571. 0xAB8F69E3, 0x00000000, 39, // 191
  2572. 0xAAAAAAAB, 0x00000000, 39, // 192
  2573. 0x15390949, 0x00000000, 36, // 193
  2574. 0xA8E83F57, 0xA8E83F57, 39, // 194
  2575. 0x15015015, 0x15015015, 36, // 195
  2576. 0x5397829D, 0x00000000, 38, // 196
  2577. 0xA655C439, 0xA655C439, 39, // 197
  2578. 0xA57EB503, 0x00000000, 39, // 198
  2579. 0x5254E78F, 0x00000000, 38, // 199
  2580. 0x51EB851F, 0x00000000, 38, // 200
  2581. 0x028C1979, 0x00000000, 33, // 201
  2582. 0xA237C32B, 0xA237C32B, 39, // 202
  2583. 0xA16B312F, 0x00000000, 39, // 203
  2584. 0xA0A0A0A1, 0x00000000, 39, // 204
  2585. 0x4FEC04FF, 0x00000000, 38, // 205
  2586. 0x9F1165E7, 0x9F1165E7, 39, // 206
  2587. 0x27932B49, 0x00000000, 37, // 207
  2588. 0x4EC4EC4F, 0x00000000, 38, // 208
  2589. 0x9CC8E161, 0x00000000, 39, // 209
  2590. 0x27027027, 0x27027027, 37, // 210
  2591. 0x9B4C6F9F, 0x00000000, 39, // 211
  2592. 0x9A90E7D9, 0x9A90E7D9, 39, // 212
  2593. 0x99D722DB, 0x00000000, 39, // 213
  2594. 0x991F1A51, 0x991F1A51, 39, // 214
  2595. 0x4C346405, 0x00000000, 38, // 215
  2596. 0x97B425ED, 0x97B425ED, 39, // 216
  2597. 0x4B809701, 0x4B809701, 38, // 217
  2598. 0x2593F69B, 0x2593F69B, 37, // 218
  2599. 0x12B404AD, 0x12B404AD, 36, // 219
  2600. 0x94F2094F, 0x94F2094F, 39, // 220
  2601. 0x25116025, 0x25116025, 37, // 221
  2602. 0x24E6A171, 0x24E6A171, 37, // 222
  2603. 0x24BC44E1, 0x24BC44E1, 37, // 223
  2604. 0x49249249, 0x49249249, 38, // 224
  2605. 0x91A2B3C5, 0x00000000, 39, // 225
  2606. 0x90FDBC09, 0x90FDBC09, 39, // 226
  2607. 0x905A3863, 0x905A3863, 39, // 227
  2608. 0x47DC11F7, 0x47DC11F7, 38, // 228
  2609. 0x478BBCED, 0x00000000, 38, // 229
  2610. 0x8E78356D, 0x8E78356D, 39, // 230
  2611. 0x46ED2901, 0x46ED2901, 38, // 231
  2612. 0x8D3DCB09, 0x00000000, 39, // 232
  2613. 0x2328A701, 0x2328A701, 37, // 233
  2614. 0x23023023, 0x23023023, 37, // 234
  2615. 0x45B81A25, 0x45B81A25, 38, // 235
  2616. 0x22B63CBF, 0x00000000, 37, // 236
  2617. 0x08A42F87, 0x08A42F87, 35, // 237
  2618. 0x44D72045, 0x00000000, 38, // 238
  2619. 0x891AC73B, 0x00000000, 39, // 239
  2620. 0x88888889, 0x00000000, 39, // 240
  2621. 0x10FEF011, 0x00000000, 36, // 241
  2622. 0x8767AB5F, 0x8767AB5F, 39, // 242
  2623. 0x86D90545, 0x00000000, 39, // 243
  2624. 0x4325C53F, 0x00000000, 38, // 244
  2625. 0x85BF3761, 0x85BF3761, 39, // 245
  2626. 0x85340853, 0x85340853, 39, // 246
  2627. 0x10953F39, 0x10953F39, 36, // 247
  2628. 0x42108421, 0x42108421, 38, // 248
  2629. 0x41CC9829, 0x41CC9829, 38, // 249
  2630. 0x10624DD3, 0x00000000, 36, // 250
  2631. 0x828CBFBF, 0x00000000, 39, // 251
  2632. 0x41041041, 0x41041041, 38, // 252
  2633. 0x81848DA9, 0x00000000, 39, // 253
  2634. 0x10204081, 0x10204081, 36, // 254
  2635. 0x80808081, 0x00000000, 39 // 255
  2636. };
  2637. }
  2638. }