Skip to content

Commit

Permalink
replace GCHandle for short-term pinning with fixed statements (#9365)
Browse files Browse the repository at this point in the history
  • Loading branch information
h3xds1nz authored Jan 31, 2025
1 parent 6110f47 commit b1d86ae
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -679,65 +679,62 @@ public virtual PathGeometry GetWidenedPathGeometry(Pen pen, double tolerance, To
unsafe
{
MIL_PEN_DATA penData;
double[] dashArray = null;

pen.GetBasicPenData(&penData, out dashArray);
pen.GetBasicPenData(&penData, out double[] dashArray);

fixed (byte *pbPathData = pathData.SerializedData)
fixed (byte* pbPathData = pathData.SerializedData)
{
Debug.Assert(pbPathData != (byte*)0);

FillRule fillRule = FillRule.Nonzero;
PathGeometry.FigureList list = new();

PathGeometry.FigureList list = new PathGeometry.FigureList();

// The handle to the pDashArray, if we have one.
// Since the dash array is optional, we may not need to Free it.
GCHandle handle = new GCHandle();

// Pin the pDashArray, if we have one.
if (dashArray != null)
int hr; //If we don't have dashArray, we call without it (its optional)
if (dashArray is null)
{
handle = GCHandle.Alloc(dashArray, GCHandleType.Pinned);
hr = UnsafeNativeMethods.MilCoreApi.MilUtility_PathGeometryWiden(&penData,
null,
&pathData.Matrix,
pathData.FillRule,
pbPathData,
pathData.Size,
tolerance,
type == ToleranceType.Relative,
new PathGeometry.AddFigureToListDelegate(list.AddFigureToList),
out fillRule);
}

try
else // Pin the dashArray and use it, if we have one.
{
int hr = UnsafeNativeMethods.MilCoreApi.MilUtility_PathGeometryWiden(
&penData,
(dashArray == null) ? null : (double*)handle.AddrOfPinnedObject(),
&pathData.Matrix,
pathData.FillRule,
pbPathData,
pathData.Size,
tolerance,
type == ToleranceType.Relative,
new PathGeometry.AddFigureToListDelegate(list.AddFigureToList),
out fillRule);

if (hr == (int)MILErrors.WGXERR_BADNUMBER)
fixed (double* ptrDashArray = dashArray)
{
// When we encounter NaNs in the renderer, we absorb the error and draw
// nothing. To be consistent, we return an empty geometry.
resultGeometry = new PathGeometry();
hr = UnsafeNativeMethods.MilCoreApi.MilUtility_PathGeometryWiden(&penData,
ptrDashArray,
&pathData.Matrix,
pathData.FillRule,
pbPathData,
pathData.Size,
tolerance,
type == ToleranceType.Relative,
new PathGeometry.AddFigureToListDelegate(list.AddFigureToList),
out fillRule);
}
else
{
HRESULT.Check(hr);
}

resultGeometry = new PathGeometry(list.Figures, fillRule, null);
}
if (hr == (int)MILErrors.WGXERR_BADNUMBER)
{
// When we encounter NaNs in the renderer, we absorb the error and draw
// nothing. To be consistent, we return an empty geometry.
resultGeometry = new PathGeometry();
}
finally
else
{
if (handle.IsAllocated)
{
handle.Free();
}
HRESULT.Check(hr);

resultGeometry = new PathGeometry(list.Figures, fillRule, null);
}
}

return resultGeometry;
return resultGeometry;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ internal void InitVector(Array array, Type type, VarEnum varEnum)

internal void Init(Array array, Type type, VarEnum vt)
{
varType = (ushort) vt;
varType = (ushort)vt;
ca.cElems = 0;
ca.pElems = IntPtr.Zero;

Expand All @@ -131,17 +131,16 @@ internal void Init(Array array, Type type, VarEnum vt)
if (length > 0)
{
long size = Marshal.SizeOf(type) * length;

IntPtr destPtr =IntPtr.Zero;
GCHandle handle = new GCHandle();
IntPtr destPtr = IntPtr.Zero;

try
{
destPtr = Marshal.AllocCoTaskMem((int) size);
handle = GCHandle.Alloc(array, GCHandleType.Pinned);
destPtr = Marshal.AllocCoTaskMem((int)size);

unsafe
{
CopyBytes((byte *) destPtr, (int)size, (byte *)handle.AddrOfPinnedObject(), (int)size);
fixed (byte* sourcePtr = &MemoryMarshal.GetArrayDataReference(array))
CopyBytes((byte*)destPtr, (int)size, sourcePtr, (int)size);
}

ca.cElems = (uint)length;
Expand All @@ -151,11 +150,6 @@ internal void Init(Array array, Type type, VarEnum vt)
}
finally
{
if (handle.IsAllocated)
{
handle.Free();
}

if (destPtr != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(destPtr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,24 +397,16 @@ int destinationY
}

// Get the address of the data in the array by pinning it.
GCHandle arrayHandle = GCHandle.Alloc(sourceBuffer, GCHandleType.Pinned);
try
unsafe
{
unsafe
{
IntPtr buffer = arrayHandle.AddrOfPinnedObject();
fixed (byte* buffer = &MemoryMarshal.GetArrayDataReference(sourceBuffer))
WritePixelsImpl(sourceRect,
buffer,
(nint)buffer,
sourceBufferSize,
sourceBufferStride,
destinationX,
destinationY,
/*backwardsCompat*/ false);
}
}
finally
{
arrayHandle.Free();
}
}

Expand Down Expand Up @@ -532,28 +524,25 @@ int offset
sourceRect.Y = 0;

// Get the address of the data in the array by pinning it.
GCHandle arrayHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned);
try
unsafe
{
IntPtr buffer = arrayHandle.AddrOfPinnedObject();

checked
fixed (byte* buffer = &MemoryMarshal.GetArrayDataReference(pixels))
{
buffer = new IntPtr(((long) buffer) + (long) offsetInBytes);
sourceBufferSize -= offsetInBytes;
nint adjustedBuffer;
checked
{
adjustedBuffer = new IntPtr(((long)buffer) + (long)offsetInBytes);
sourceBufferSize -= offsetInBytes;
}

WritePixelsImpl(sourceRect,
adjustedBuffer,
sourceBufferSize,
stride,
destinationX,
destinationY,
/*backwardsCompat*/ true);
}

WritePixelsImpl(sourceRect,
buffer,
sourceBufferSize,
stride,
destinationX,
destinationY,
/*backwardsCompat*/ true);
}
finally
{
arrayHandle.Free();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,15 +314,12 @@ public static unsafe (int length, IntPtr data) FromManagedArray(Array array)
public static unsafe void CopyManagedArray(Array array, IntPtr data)
{
if (array is null)
{
return;
}
var length = array.Length;
var byte_length = length * Marshal.SizeOf<T>();
var array_handle = GCHandle.Alloc(array, GCHandleType.Pinned);
var array_data = array_handle.AddrOfPinnedObject();
Buffer.MemoryCopy(array_data.ToPointer(), data.ToPointer(), byte_length, byte_length);
array_handle.Free();

int byte_length = array.Length * Marshal.SizeOf<T>();

fixed (void* array_data = &MemoryMarshal.GetArrayDataReference(array))
Buffer.MemoryCopy(array_data, data.ToPointer(), byte_length, byte_length);
}

public static void DisposeMarshalerArray(object box)
Expand Down

0 comments on commit b1d86ae

Please sign in to comment.