123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- using System;
- using System.ComponentModel;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Runtime.InteropServices;
- namespace SmartCoalApplication.SystemLayer
- {
- public static class PdnGraphics
- {
- public static PropertyItem CreatePropertyItem()
- {
- PropertyItem2 pi2 = new PropertyItem2(0, 0, 0, new byte[0]);
- return pi2.ToPropertyItem();
- }
- public static PropertyItem ClonePropertyItem(PropertyItem pi)
- {
- byte[] valueClone;
- if (pi.Value == null)
- {
- valueClone = new byte[0];
- }
- else
- {
- valueClone = (byte[])pi.Value.Clone();
- }
- PropertyItem2 pi2 = new PropertyItem2(pi.Id, pi.Len, pi.Type, valueClone);
- return pi2.ToPropertyItem();
- }
- public static string SerializePropertyItem(PropertyItem pi)
- {
- PropertyItem2 pi2 = PropertyItem2.FromPropertyItem(pi);
- return pi2.ToBlob();
- }
- public static PropertyItem DeserializePropertyItem(string piBlob)
- {
- PropertyItem2 pi2 = PropertyItem2.FromBlob(piBlob);
- return pi2.ToPropertyItem();
- }
- internal unsafe static void GetRegionScans(IntPtr hRgn, out Rectangle[] scans, out int area)
- {
- uint bytes = 0;
- int countdown = 100;
- int error = 0;
- while (countdown > 0)
- {
- bytes = SafeNativeMethods.GetRegionData(hRgn, 0, (NativeStructs.RGNDATA*)IntPtr.Zero);
- error = Marshal.GetLastWin32Error();
- if (bytes == 0)
- {
- --countdown;
- System.Threading.Thread.Sleep(5);
- }
- else
- {
- break;
- }
- }
- // But if we retry several times and it still messes up then we will finally give up.
- if (bytes == 0)
- {
- throw new Win32Exception(error, "GetRegionData returned " + bytes.ToString() + ", GetLastError() = " + error.ToString());
- }
- byte* data;
- // Up to 512 bytes, allocate on the stack. Otherwise allocate from the heap.
- if (bytes <= 512)
- {
- byte* data1 = stackalloc byte[(int)bytes];
- data = data1;
- }
- else
- {
- data = (byte*)Memory.Allocate(bytes).ToPointer();
- }
- try
- {
- NativeStructs.RGNDATA* pRgnData = (NativeStructs.RGNDATA*)data;
- uint result = SafeNativeMethods.GetRegionData(hRgn, bytes, pRgnData);
- if (result != bytes)
- {
- throw new OutOfMemoryException("SafeNativeMethods.GetRegionData returned 0");
- }
- NativeStructs.RECT* pRects = NativeStructs.RGNDATA.GetRectsPointer(pRgnData);
- scans = new Rectangle[pRgnData->rdh.nCount];
- area = 0;
- for (int i = 0; i < scans.Length; ++i)
- {
- scans[i] = Rectangle.FromLTRB(pRects[i].left, pRects[i].top, pRects[i].right, pRects[i].bottom);
- area += scans[i].Width * scans[i].Height;
- }
- pRects = null;
- pRgnData = null;
- }
- finally
- {
- if (bytes > 512)
- {
- Memory.Free(new IntPtr(data));
- }
- }
- }
- /// <summary>
- /// Retrieves an array of rectangles that approximates a region, and computes the
- /// pixel area of it. This method is necessary to work around some bugs in .NET
- /// and to increase performance for the way in which we typically use this data.
- /// </summary>
- /// <param name="region">The Region to retrieve data from.</param>
- /// <param name="scans">An array of Rectangle to put the scans into.</param>
- /// <param name="area">An integer to write the computed area of the region into.</param>
- /// <remarks>
- /// Note to implementors: Simple implementations may simple call region.GetRegionScans()
- /// and process the data for the 'out' variables.</remarks>
- public static void GetRegionScans(Region region, out Rectangle[] scans, out int area)
- {
- using (NullGraphics nullGraphics = new NullGraphics())
- {
- IntPtr hRgn = IntPtr.Zero;
- try
- {
- hRgn = region.GetHrgn(nullGraphics.Graphics);
- GetRegionScans(hRgn, out scans, out area);
- }
- finally
- {
- if (hRgn != IntPtr.Zero)
- {
- SafeNativeMethods.DeleteObject(hRgn);
- hRgn = IntPtr.Zero;
- }
- }
- }
- GC.KeepAlive(region);
- }
- }
- }
|