Skip to content

Commit

Permalink
Optimize Matrix.Elements (#47932)
Browse files Browse the repository at this point in the history
* Optimize Matrix.Elements

Just pin the array. There is no need to allocate native memory and copy.

* Move more element usage to the stack.

* Remove DeleteObject call
  • Loading branch information
JeremyKuhne committed Feb 9, 2021
1 parent 171812b commit d8aa4c6
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using Gdip = System.Drawing.SafeNativeMethods.Gdip;
Expand Down Expand Up @@ -86,25 +87,35 @@ public float[] Elements
{
get
{
IntPtr buf = Marshal.AllocHGlobal(6 * 8); // 6 elements x 8 bytes (float)
float[] elements = new float[6];
GetElements(elements);
return elements;
}
}

try
{
Gdip.CheckStatus(Gdip.GdipGetMatrixElements(new HandleRef(this, NativeMatrix), buf));
internal unsafe void GetElements(Span<float> elements)
{
Debug.Assert(elements.Length >= 6);

float[] m = new float[6];
Marshal.Copy(buf, m, 0, 6);
return m;
}
finally
{
Marshal.FreeHGlobal(buf);
}
fixed (float* m = elements)
{
Gdip.CheckStatus(Gdip.GdipGetMatrixElements(new HandleRef(this, NativeMatrix), m));
}
}

public float OffsetX => Elements[4];
public float OffsetY => Elements[5];
public unsafe float OffsetX => Offset.X;

public unsafe float OffsetY => Offset.Y;

internal unsafe PointF Offset
{
get
{
Span<float> elements = stackalloc float[6];
GetElements(elements);
return new PointF(elements[4], elements[5]);
}
}

public void Reset()
{
Expand Down Expand Up @@ -263,6 +274,7 @@ public bool IsIdentity
return isIdentity != 0;
}
}

public override bool Equals([NotNullWhen(true)] object? obj)
{
if (!(obj is Matrix matrix2))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ internal static unsafe partial class Gdip
internal static extern int GdipVectorTransformMatrixPointsI(HandleRef matrix, Point* pts, int count);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetMatrixElements(HandleRef matrix, IntPtr m);
internal static extern unsafe int GdipGetMatrixElements(HandleRef matrix, float* m);

[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipIsMatrixInvertible(HandleRef matrix, out int boolean);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -691,9 +691,7 @@ public object GetContextInfo()

if (!cumulTransform.IsIdentity)
{
float[] elements = cumulTransform.Elements;
currentOffset.X = elements[4];
currentOffset.Y = elements[5];
currentOffset = cumulTransform.Offset;
}

GraphicsContext? context = _previousContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ public GraphicsContext(Graphics g)
Matrix transform = g.Transform;
if (!transform.IsIdentity)
{
float[] elements = transform.Elements;
_transformOffset.X = elements[4];
_transformOffset.Y = elements[5];
_transformOffset = transform.Offset;
}
transform.Dispose();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Buffers;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Internal;
using System.IO;
Expand Down Expand Up @@ -418,8 +419,11 @@ internal void Draw(Graphics graphics, int x, int y)
internal void Draw(Graphics graphics, Rectangle targetRect)
{
Rectangle copy = targetRect;
copy.X += (int)graphics.Transform.OffsetX;
copy.Y += (int)graphics.Transform.OffsetY;

using Matrix transform = graphics.Transform;
PointF offset = transform.Offset;
copy.X += (int)offset.X;
copy.Y += (int)offset.Y;

using (WindowsGraphics wg = WindowsGraphics.FromGraphics(graphics, ApplyGraphicsProperties.Clipping))
{
Expand All @@ -435,8 +439,10 @@ internal void Draw(Graphics graphics, Rectangle targetRect)
internal void DrawUnstretched(Graphics graphics, Rectangle targetRect)
{
Rectangle copy = targetRect;
copy.X += (int)graphics.Transform.OffsetX;
copy.Y += (int)graphics.Transform.OffsetY;
using Matrix transform = graphics.Transform;
PointF offset = transform.Offset;
copy.X += (int)offset.X;
copy.Y += (int)offset.Y;

using (WindowsGraphics wg = WindowsGraphics.FromGraphics(graphics, ApplyGraphicsProperties.Clipping))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties p
Debug.Assert(g != null, "null Graphics object.");

WindowsRegion? wr = null;
float[]? elements = null;

PointF offset = default;

Region? clipRgn = null;
Matrix? worldTransf = null;
Expand All @@ -71,7 +72,7 @@ public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties p
{
if ((properties & ApplyGraphicsProperties.TranslateTransform) != 0)
{
elements = worldTransf.Elements;
offset = worldTransf.Offset;
}

worldTransf.Dispose();
Expand Down Expand Up @@ -110,10 +111,10 @@ public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties p
}
}

if (elements != null)
if (offset != default)
{
// elements (XFORM) = [eM11, eM12, eM21, eM22, eDx, eDy], eDx/eDy specify the translation offset.
wg.DeviceContext.TranslateTransform((int)elements[4], (int)elements[5]);
wg.DeviceContext.TranslateTransform((int)offset.X, (int)offset.Y);
}

return wg;
Expand Down

0 comments on commit d8aa4c6

Please sign in to comment.