From 03bd984c03dc23bc8c00adc4750290b8ab736caf Mon Sep 17 00:00:00 2001 From: Jeremy Kuhne Date: Mon, 19 Apr 2021 16:00:36 -0700 Subject: [PATCH] Use new GetContext overloads Use new Graphics.GetContext overloads that minimize allocations and remove warning suppression. --- .../Windows/Forms/DeviceContextHdcScope.cs | 75 ++++++++++--------- .../Forms/Internal/DrawingEventArgs.cs | 17 ++--- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/System.Windows.Forms.Primitives/src/System/Windows/Forms/DeviceContextHdcScope.cs b/src/System.Windows.Forms.Primitives/src/System/Windows/Forms/DeviceContextHdcScope.cs index cbac0de403c..99c83ba06c4 100644 --- a/src/System.Windows.Forms.Primitives/src/System/Windows/Forms/DeviceContextHdcScope.cs +++ b/src/System.Windows.Forms.Primitives/src/System/Windows/Forms/DeviceContextHdcScope.cs @@ -146,59 +146,62 @@ public unsafe DeviceContextHdcScope( bool applyTransform = applyGraphicsState.HasFlag(ApplyGraphicsProperties.TranslateTransform); bool applyClipping = applyGraphicsState.HasFlag(ApplyGraphicsProperties.Clipping); -#pragma warning disable SYSLIB0016 // Type or member is obsolete - // This API is very expensive and cannot be called after GetHdc() - object[]? data = applyTransform || applyClipping ? (object[])graphics.GetContextInfo() : null; -#pragma warning restore SYSLIB0016 // Type or member is obsolete + Region? clipRegion = null; + PointF offset = default; + if (applyClipping) + { + graphics.GetContextInfo(out offset, out clipRegion); + } + else if (applyTransform) + { + graphics.GetContextInfo(out offset); + } - using Region? clipRegion = (Region?)data?[0]; - using Matrix? worldTransform = (Matrix?)data?[1]; + using (clipRegion) + { + applyTransform = applyTransform && !offset.IsEmpty; + applyClipping = clipRegion is not null; - // elements (XFORM) = [eM11, eM12, eM21, eM22, eDx, eDy], eDx/eDy specify the translation offset. - float[]? elements = applyTransform ? worldTransform?.Elements : null; - int dx = elements is not null ? (int)elements[4] : 0; - int dy = elements is not null ? (int)elements[5] : 0; - applyTransform = applyTransform && elements is not null && (dx != 0 || dy != 0); + using var graphicsRegion = applyClipping ? new Gdi32.RegionScope(clipRegion!, graphics) : default; + applyClipping = applyClipping && !graphicsRegion!.Region.IsNull; - using var graphicsRegion = applyClipping ? new Gdi32.RegionScope(clipRegion!, graphics) : default; - applyClipping = applyClipping && !graphicsRegion!.Region.IsNull; + HDC = (Gdi32.HDC)graphics.GetHdc(); - HDC = (Gdi32.HDC)graphics.GetHdc(); + if (saveHdcState || applyClipping || applyTransform) + { + _savedHdcState = Gdi32.SaveDC(HDC); + } - if (saveHdcState || applyClipping || applyTransform) - { - _savedHdcState = Gdi32.SaveDC(HDC); - } + if (applyClipping) + { + // If the Graphics object was created from a native DC the actual clipping region is the intersection + // beteween the original DC clip region and the GDI+ one - for display Graphics it is the same as + // Graphics.VisibleClipBounds. - if (applyClipping) - { - // If the Graphics object was created from a native DC the actual clipping region is the intersection - // beteween the original DC clip region and the GDI+ one - for display Graphics it is the same as - // Graphics.VisibleClipBounds. + RegionType type; - RegionType type; + using var dcRegion = new Gdi32.RegionScope(HDC); + if (!dcRegion.IsNull) + { + type = Gdi32.CombineRgn(graphicsRegion!, dcRegion, graphicsRegion!, Gdi32.RGN.AND); + if (type == RegionType.ERROR) + { + throw new Win32Exception(); + } + } - using var dcRegion = new Gdi32.RegionScope(HDC); - if (!dcRegion.IsNull) - { - type = Gdi32.CombineRgn(graphicsRegion!, dcRegion, graphicsRegion!, Gdi32.RGN.AND); + type = Gdi32.SelectClipRgn(HDC, graphicsRegion!); if (type == RegionType.ERROR) { throw new Win32Exception(); } } - type = Gdi32.SelectClipRgn(HDC, graphicsRegion!); - if (type == RegionType.ERROR) + if (applyTransform) { - throw new Win32Exception(); + Gdi32.OffsetViewportOrgEx(HDC, (int)offset.X, (int)offset.Y, null); } } - - if (applyTransform) - { - Gdi32.OffsetViewportOrgEx(HDC, dx, dy, null); - } } public static implicit operator Gdi32.HDC(in DeviceContextHdcScope scope) => scope.HDC; diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Internal/DrawingEventArgs.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Internal/DrawingEventArgs.cs index 779b6e5b3d1..5437c540bd0 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Internal/DrawingEventArgs.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Internal/DrawingEventArgs.cs @@ -156,18 +156,15 @@ internal static void CheckGraphicsForState(Graphics? graphics, DrawingEventFlags return; } -#pragma warning disable SYSLIB0016 // Type or member is obsolete // Check to see if we've actually corrupted the state - object[] data = (object[])graphics.GetContextInfo(); -#pragma warning restore SYSLIB0016 // Type or member is obsolete + graphics.GetContextInfo(out PointF offset, out Region? clip); - using Region clipRegion = (Region)data[0]; - using Matrix worldTransform = (Matrix)data[1]; - - float[] elements = worldTransform?.Elements!; - bool isInfinite = clipRegion.IsInfinite(graphics); - Debug.Assert((int)elements[4] == 0 && (int)elements[5] == 0, "transform has been modified"); - Debug.Assert(isInfinite, "clipping as been applied"); + using (clip) + { + bool isInfinite = clip?.IsInfinite(graphics) ?? true; + Debug.Assert(offset.IsEmpty, "transform has been modified"); + Debug.Assert(isInfinite, "clipping as been applied"); + } } } }