-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Fix blittable array instead of copying #30099
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -183,46 +183,36 @@ public FillMode FillMode | |||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| private PathData _GetPathData() | ||||||||||||||||
| private unsafe PathData _GetPathData() | ||||||||||||||||
| { | ||||||||||||||||
| int ptSize = Marshal.SizeOf(typeof(GPPOINTF)); | ||||||||||||||||
| int count = PointCount; | ||||||||||||||||
|
|
||||||||||||||||
| int numPts = PointCount; | ||||||||||||||||
| PathData pathData = new PathData() | ||||||||||||||||
| { | ||||||||||||||||
| Types = new byte[count], | ||||||||||||||||
| Points = new PointF[count] | ||||||||||||||||
| }; | ||||||||||||||||
|
|
||||||||||||||||
| PathData pathData = new PathData() { Types = new byte[numPts] }; | ||||||||||||||||
| if (count == 0) | ||||||||||||||||
| return pathData; | ||||||||||||||||
|
|
||||||||||||||||
| IntPtr memoryPathData = Marshal.AllocHGlobal(3 * IntPtr.Size); | ||||||||||||||||
| IntPtr memoryPoints = Marshal.AllocHGlobal(checked(ptSize * numPts)); | ||||||||||||||||
| try | ||||||||||||||||
| fixed (byte* t = pathData.Types) | ||||||||||||||||
| fixed (PointF* p = pathData.Points) | ||||||||||||||||
| { | ||||||||||||||||
| GCHandle typesHandle = GCHandle.Alloc(pathData.Types, GCHandleType.Pinned); | ||||||||||||||||
| try | ||||||||||||||||
| GpPathData data = new GpPathData | ||||||||||||||||
| { | ||||||||||||||||
| IntPtr typesPtr = typesHandle.AddrOfPinnedObject(); | ||||||||||||||||
| Count = count, | ||||||||||||||||
| Points = p, | ||||||||||||||||
| Types = t | ||||||||||||||||
| }; | ||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't this have to be
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Correct. The language won't even let you use fixed here (assuming you're referring to |
||||||||||||||||
|
|
||||||||||||||||
| Marshal.StructureToPtr(numPts, memoryPathData, false); | ||||||||||||||||
| Marshal.StructureToPtr(memoryPoints, (IntPtr)((long)memoryPathData + IntPtr.Size), false); | ||||||||||||||||
| Marshal.StructureToPtr(typesPtr, (IntPtr)((long)memoryPathData + 2 * IntPtr.Size), false); | ||||||||||||||||
|
|
||||||||||||||||
| int status = SafeNativeMethods.Gdip.GdipGetPathData(new HandleRef(this, nativePath), memoryPathData); | ||||||||||||||||
|
|
||||||||||||||||
| if (status != SafeNativeMethods.Gdip.Ok) | ||||||||||||||||
| { | ||||||||||||||||
| throw SafeNativeMethods.Gdip.StatusException(status); | ||||||||||||||||
| } | ||||||||||||||||
| int status = SafeNativeMethods.Gdip.GdipGetPathData(new HandleRef(this, nativePath), &data); | ||||||||||||||||
|
|
||||||||||||||||
| pathData.Points = SafeNativeMethods.Gdip.ConvertGPPOINTFArrayF(memoryPoints, numPts); | ||||||||||||||||
| } | ||||||||||||||||
| finally | ||||||||||||||||
| if (status != SafeNativeMethods.Gdip.Ok) | ||||||||||||||||
| { | ||||||||||||||||
| typesHandle.Free(); | ||||||||||||||||
| throw SafeNativeMethods.Gdip.StatusException(status); | ||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a helper for this: SafeNativeMethods.Gdip.CheckStatus(status);corefx/src/System.Drawing.Common/src/System/Drawing/Gdiplus.cs Lines 261 to 267 in b5b75ee
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I plan to rationalize out the variety of helpers in a separate change. |
||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| finally | ||||||||||||||||
| { | ||||||||||||||||
| Marshal.FreeHGlobal(memoryPathData); | ||||||||||||||||
| Marshal.FreeHGlobal(memoryPoints); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| return pathData; | ||||||||||||||||
| } | ||||||||||||||||
|
|
@@ -1094,29 +1084,22 @@ public byte[] PathTypes | |||||||||||||||
| return types; | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| public PointF[] PathPoints | ||||||||||||||||
|
|
||||||||||||||||
| public unsafe PointF[] PathPoints | ||||||||||||||||
| { | ||||||||||||||||
| get | ||||||||||||||||
| { | ||||||||||||||||
| int count = PointCount; | ||||||||||||||||
| int size = Marshal.SizeOf(typeof(GPPOINTF)); | ||||||||||||||||
| IntPtr buf = Marshal.AllocHGlobal(checked(count * size)); | ||||||||||||||||
| try | ||||||||||||||||
| PointF[] points = new PointF[PointCount]; | ||||||||||||||||
| fixed(PointF* p = points) | ||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: space before (
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. D'oh, I searched and didn't click on this result. I'll get it in the next change. |
||||||||||||||||
| { | ||||||||||||||||
| int status = SafeNativeMethods.Gdip.GdipGetPathPoints(new HandleRef(this, nativePath), new HandleRef(null, buf), count); | ||||||||||||||||
| int status = SafeNativeMethods.Gdip.GdipGetPathPoints(new HandleRef(this, nativePath), p, points.Length); | ||||||||||||||||
|
|
||||||||||||||||
| if (status != SafeNativeMethods.Gdip.Ok) | ||||||||||||||||
| { | ||||||||||||||||
| throw SafeNativeMethods.Gdip.StatusException(status); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| PointF[] points = SafeNativeMethods.Gdip.ConvertGPPOINTFArrayF(buf, count); | ||||||||||||||||
| return points; | ||||||||||||||||
| } | ||||||||||||||||
| finally | ||||||||||||||||
| { | ||||||||||||||||
| Marshal.FreeHGlobal(buf); | ||||||||||||||||
| } | ||||||||||||||||
| return points; | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,9 +3,8 @@ | |
| // See the LICENSE file in the project root for more information. | ||
|
|
||
| using System.Diagnostics; | ||
| using System.Runtime.InteropServices; | ||
| using System.Drawing.Internal; | ||
| using System.Globalization; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| namespace System.Drawing.Drawing2D | ||
| { | ||
|
|
@@ -169,73 +168,51 @@ public unsafe int Enumerate(ref PointF[] points, ref byte[] types) | |
| if (points.Length != types.Length) | ||
| throw SafeNativeMethods.Gdip.StatusException(SafeNativeMethods.Gdip.InvalidParameter); | ||
|
|
||
| int resultCount = 0; | ||
| int size = Marshal.SizeOf(typeof(GPPOINTF)); | ||
| int count = points.Length; | ||
| byte[] typesLocal = new byte[count]; | ||
| if (points.Length == 0) | ||
| return 0; | ||
|
|
||
| IntPtr memoryPts = Marshal.AllocHGlobal(checked(count * size)); | ||
| try | ||
| fixed (PointF* p = points) | ||
| fixed (byte* t = types) | ||
| { | ||
| int status = SafeNativeMethods.Gdip.GdipPathIterEnumerate(new HandleRef(this, nativeIter), out resultCount, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice to rename nativeIter to nativeIterator, or something like this, perhaps not in the scope of this change.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm going to follow up this change with a style pass. I'll look at private/internal members. |
||
| memoryPts, typesLocal, count); | ||
| int status = SafeNativeMethods.Gdip.GdipPathIterEnumerate( | ||
| new HandleRef(this, nativeIter), | ||
| out int resultCount, | ||
| p, | ||
| t, | ||
| points.Length); | ||
|
|
||
| if (status != SafeNativeMethods.Gdip.Ok) | ||
| { | ||
| throw SafeNativeMethods.Gdip.StatusException(status); | ||
| } | ||
|
|
||
| if (resultCount < count) | ||
| { | ||
| SafeNativeMethods.ZeroMemory((byte*)(checked((long)memoryPts + resultCount * size)), (ulong)((count - resultCount) * size)); | ||
| } | ||
|
|
||
| points = SafeNativeMethods.Gdip.ConvertGPPOINTFArrayF(memoryPts, count); | ||
| typesLocal.CopyTo(types, 0); | ||
| } | ||
| finally | ||
| { | ||
| Marshal.FreeHGlobal(memoryPts); | ||
| return resultCount; | ||
| } | ||
|
|
||
| return resultCount; | ||
| } | ||
|
|
||
| public unsafe int CopyData(ref PointF[] points, ref byte[] types, int startIndex, int endIndex) | ||
| { | ||
| if ((points.Length != types.Length) || (endIndex - startIndex + 1 > points.Length)) | ||
| throw SafeNativeMethods.Gdip.StatusException(SafeNativeMethods.Gdip.InvalidParameter); | ||
|
|
||
| int resultCount = 0; | ||
| int size = Marshal.SizeOf(typeof(GPPOINTF)); | ||
| int count = points.Length; | ||
| byte[] typesLocal = new byte[count]; | ||
|
|
||
| IntPtr memoryPts = Marshal.AllocHGlobal(checked(count * size)); | ||
| try | ||
| fixed (PointF* p = points) | ||
| fixed (byte* t = types) | ||
| { | ||
| int status = SafeNativeMethods.Gdip.GdipPathIterCopyData(new HandleRef(this, nativeIter), out resultCount, | ||
| memoryPts, typesLocal, startIndex, endIndex); | ||
| int status = SafeNativeMethods.Gdip.GdipPathIterCopyData( | ||
| new HandleRef(this, nativeIter), | ||
| out int resultCount, | ||
| p, | ||
| t, | ||
| startIndex, | ||
| endIndex); | ||
|
|
||
| if (status != SafeNativeMethods.Gdip.Ok) | ||
| { | ||
| throw SafeNativeMethods.Gdip.StatusException(status); | ||
| } | ||
|
|
||
| if (resultCount < count) | ||
| { | ||
| SafeNativeMethods.ZeroMemory((byte*)(checked((long)memoryPts + resultCount * size)), (ulong)((count - resultCount) * size)); | ||
| } | ||
|
|
||
| points = SafeNativeMethods.Gdip.ConvertGPPOINTFArrayF(memoryPts, count); | ||
| typesLocal.CopyTo(types, 0); | ||
| } | ||
| finally | ||
| { | ||
| Marshal.FreeHGlobal(memoryPts); | ||
| return resultCount; | ||
| } | ||
|
|
||
| return resultCount; | ||
| } | ||
|
|
||
| // handle to native path iterator object | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How common is this case? If common, consider moving it earlier and doing:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not common.