Ejemplo n.º 1
0
        /// <summary>
        ///  Gets the <see cref="Gdi32.HDC"/> from the the given <paramref name="deviceContext"/>.
        /// </summary>
        /// <remarks>
        ///  When a <see cref="Graphics"/> object is created from a <see cref="Gdi32.HDC"/> the clipping region and
        ///  the viewport origin are applied (<see cref="Gdi32.GetViewportExtEx(Gdi32.HDC, out Size)"/>). The clipping
        ///  region isn't reflected in <see cref="Graphics.Clip"/>, which is combined with the HDC HRegion.
        ///
        ///  The Graphics object saves and restores DC state when performing operations that would modify the DC to
        ///  maintain the DC in its original or returned state after <see cref="Graphics.ReleaseHdc()"/>.
        /// </remarks>
        /// <param name="applyGraphicsState">
        ///  Applies the origin transform and clipping region of the <paramref name="deviceContext"/> if it is an
        ///  object of type <see cref="Graphics"/>. Otherwise this is a no-op.
        /// </param>
        /// <param name="saveHdcState">
        ///  When true, saves and restores the <see cref="Gdi32.HDC"/> state.
        /// </param>
        public DeviceContextHdcScope(
            IDeviceContext deviceContext,
            bool applyGraphicsState = true,
            bool saveHdcState       = false)
        {
            DeviceContext = deviceContext ?? throw new ArgumentNullException(nameof(deviceContext));
            ApplyGraphicsProperties apply = applyGraphicsState ? ApplyGraphicsProperties.All : ApplyGraphicsProperties.None;

            _savedHdcState = 0;

            if (apply == ApplyGraphicsProperties.None || !(DeviceContext is Graphics graphics))
            {
                // GetHdc() locks the Graphics object, it cannot be used until ReleaseHdc() is called
                HDC            = (Gdi32.HDC)DeviceContext.GetHdc();
                _savedHdcState = saveHdcState ? Gdi32.SaveDC(HDC) : 0;
                return;
            }

            bool applyTransform = apply.HasFlag(ApplyGraphicsProperties.TranslateTransform);
            bool applyClipping  = apply.HasFlag(ApplyGraphicsProperties.Clipping);

            // This API is very expensive
            object[]? data = applyTransform || applyClipping ? (object[])graphics.GetContextInfo() : null;

            using Region? clipRegion     = (Region?)data?[0];
            using Matrix? worldTransform = (Matrix?)data?[1];

            // elements (XFORM) = [eM11, eM12, eM21, eM22, eDx, eDy], eDx/eDy specify the translation offset.
            float[]? elements = applyTransform ? worldTransform?.Elements : null;
            int dx = elements != null ? (int)elements[4] : 0;
            int dy = elements != null ? (int)elements[5] : 0;

            applyTransform = applyTransform && elements != null && (dx != 0 || dy != 0);

            using var graphicsRegion = applyClipping ? new Gdi32.RegionScope(clipRegion !, graphics) : default;
Ejemplo n.º 2
0
        public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties properties)
        {
            Debug.Assert(g != null, "null Graphics object.");

            WindowsRegion?wr = null;

            PointF offset = default;

            if (properties != ApplyGraphicsProperties.None)
            {
                Region?clip = null;

                if (properties.HasFlag(ApplyGraphicsProperties.Clipping))
                {
                    g.GetContextInfo(out offset, out clip);
                }
                else
                {
                    g.GetContextInfo(out offset);
                }

                if (clip is not null)
                {
                    // We have to create the WindowsRegion and dipose the Region object before locking the Graphics object,
                    // in case of an unlikely exception before releasing the WindowsRegion, the finalizer will do it for us.
                    // (no try-finally block since this method is used frequently - perf).

                    // If clipping has not been set (Region.IsInfinite) GetContextInfo will return a null Region.

                    wr = WindowsRegion.FromRegion(clip, g); // WindowsRegion will take ownership of the hRegion.
                    clip.Dispose();                         // Disposing the Region object doesn't destroy the hRegion.
                }
            }

            WindowsGraphics wg = FromHdc(g.GetHdc()); // This locks the Graphics object.

            wg._graphics = g;

            // Apply transform and clip
            if (wr is not null)
            {
                using (wr)
                {
                    // 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.
                    wg.DeviceContext.IntersectClip(wr);
                }
            }

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

            return(wg);
        }
Ejemplo n.º 3
0
        public WindowsGraphicsWrapper(IDeviceContext idc, TextFormatFlags flags)
        {
            if (idc is Graphics)
            {
                ApplyGraphicsProperties properties = ApplyGraphicsProperties.None;

                if ((flags & TextFormatFlags.PreserveGraphicsClipping) != 0)
                {
                    properties |= ApplyGraphicsProperties.Clipping;
                }

                if ((flags & TextFormatFlags.PreserveGraphicsTranslateTransform) != 0)
                {
                    properties |= ApplyGraphicsProperties.TranslateTransform;
                }

                // Create the WindowsGraphics from the Grahpics object only if Graphics properties need
                // to be reapplied to the DC wrapped by the WindowsGraphics.
                if (properties != ApplyGraphicsProperties.None)
                {
                    wg = WindowsGraphics.FromGraphics(idc as Graphics, properties);
                }
            }
            else
            {
                // If passed-in IDeviceContext object is a WindowsGraphics we can use it directly.
                wg = idc as WindowsGraphics;

                if (wg != null)
                {
                    // In this case we cache the idc to compare it against the wg in the Dispose method to avoid
                    // disposing of the wg.
                    this.idc = idc;
                }
            }

            if (wg == null)
            {
                // The IDeviceContext object is not a WindowsGraphics, or it is a custom IDeviceContext, or
                // it is a Graphics object but we did not need to re-apply Graphics propertiesto the hdc.
                // So create the WindowsGraphics from the hdc directly.
                // Cache the IDC so the hdc can be released on dispose.
                this.idc = idc;
                wg       = WindowsGraphics.FromHdc(idc.GetHdc());
            }

            // Set text padding on the WindowsGraphics (if any).
            if ((flags & TextFormatFlags.LeftAndRightPadding) != 0)
            {
                wg.TextPadding = TextPaddingOptions.LeftAndRightPadding;
            }
            else if ((flags & TextFormatFlags.NoPadding) != 0)
            {
                wg.TextPadding = TextPaddingOptions.NoPadding;
            }
            // else wg.TextPadding = TextPaddingOptions.GlyphOverhangPadding - the default value.
        }
        public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties properties)
        {
            WindowsRegion wr = null;

            float[] elements = null;
            Region  region   = null;
            Matrix  matrix   = null;

            if (((properties & ApplyGraphicsProperties.TranslateTransform) != ApplyGraphicsProperties.None) || ((properties & ApplyGraphicsProperties.Clipping) != ApplyGraphicsProperties.None))
            {
                object[] contextInfo = g.GetContextInfo() as object[];
                if ((contextInfo != null) && (contextInfo.Length == 2))
                {
                    region = contextInfo[0] as Region;
                    matrix = contextInfo[1] as Matrix;
                }
                if (matrix != null)
                {
                    if ((properties & ApplyGraphicsProperties.TranslateTransform) != ApplyGraphicsProperties.None)
                    {
                        elements = matrix.Elements;
                    }
                    matrix.Dispose();
                }
                if (region != null)
                {
                    if (((properties & ApplyGraphicsProperties.Clipping) != ApplyGraphicsProperties.None) && !region.IsInfinite(g))
                    {
                        wr = WindowsRegion.FromRegion(region, g);
                    }
                    region.Dispose();
                }
            }
            WindowsGraphics graphics = FromHdc(g.GetHdc());

            graphics.graphics = g;
            if (wr != null)
            {
                using (wr)
                {
                    graphics.DeviceContext.IntersectClip(wr);
                }
            }
            if (elements != null)
            {
                graphics.DeviceContext.TranslateTransform((int)elements[4], (int)elements[5]);
            }
            return(graphics);
        }
Ejemplo n.º 5
0
        public static WindowsGraphics FromGraphics(Graphics graphics, ApplyGraphicsProperties properties)
        {
            bool applyTransform = properties.HasFlag(ApplyGraphicsProperties.TranslateTransform);
            bool applyClipping  = properties.HasFlag(ApplyGraphicsProperties.Clipping);

            object[]? data = applyTransform || applyClipping ? (object[])graphics.GetContextInfo() : null;

            using Region? clipRegion     = (Region?)data?[0];
            using Matrix? worldTransform = (Matrix?)data?[1];

            float[]? elements = applyTransform ? worldTransform?.Elements : null;

            // Apply transform and clip

            applyClipping            = applyClipping && !clipRegion !.IsInfinite(graphics);
            using var graphicsRegion = applyClipping ? new Gdi32.RegionScope(clipRegion !, graphics) : default;
 public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties properties)
 {
     WindowsRegion wr = null;
     float[] elements = null;
     Region region = null;
     Matrix matrix = null;
     if (((properties & ApplyGraphicsProperties.TranslateTransform) != ApplyGraphicsProperties.None) || ((properties & ApplyGraphicsProperties.Clipping) != ApplyGraphicsProperties.None))
     {
         object[] contextInfo = g.GetContextInfo() as object[];
         if ((contextInfo != null) && (contextInfo.Length == 2))
         {
             region = contextInfo[0] as Region;
             matrix = contextInfo[1] as Matrix;
         }
         if (matrix != null)
         {
             if ((properties & ApplyGraphicsProperties.TranslateTransform) != ApplyGraphicsProperties.None)
             {
                 elements = matrix.Elements;
             }
             matrix.Dispose();
         }
         if (region != null)
         {
             if (((properties & ApplyGraphicsProperties.Clipping) != ApplyGraphicsProperties.None) && !region.IsInfinite(g))
             {
                 wr = WindowsRegion.FromRegion(region, g);
             }
             region.Dispose();
         }
     }
     WindowsGraphics graphics = FromHdc(g.GetHdc());
     graphics.graphics = g;
     if (wr != null)
     {
         using (wr)
         {
             graphics.DeviceContext.IntersectClip(wr);
         }
     }
     if (elements != null)
     {
         graphics.DeviceContext.TranslateTransform((int) elements[4], (int) elements[5]);
     }
     return graphics;
 }
Ejemplo n.º 7
0
        /// <summary>
        ///  Prefer to use <see cref="DeviceContextHdcScope(IDeviceContext, bool, bool)"/>.
        /// </summary>
        /// <remarks>
        ///  <para>
        ///   Ideally we'd not bifurcate what properties we apply unless we're absolutely sure we only want one.
        ///  </para>
        /// </remarks>
        public unsafe DeviceContextHdcScope(
            IDeviceContext deviceContext,
            ApplyGraphicsProperties applyGraphicsState,
            bool saveHdcState = false)
        {
            if (deviceContext is null)
            {
                // As we're throwing in the constructor, `this` will never be passed back and as such .Dispose()
                // can't be called. We don't have anything to release at this point so there is no point in having
                // the finalizer run.
#if DEBUG
                DisposalTracking.SuppressFinalize(this !);
#endif
                throw new ArgumentNullException(nameof(deviceContext));
            }

            DeviceContext  = deviceContext;
            _savedHdcState = 0;

            HDC = default;

            IGraphicsHdcProvider?provider = deviceContext as IGraphicsHdcProvider;
            Graphics?            graphics = deviceContext as Graphics;

            // There are three states of IDeviceContext that come into this class:
            //
            //  1. One that also implements IGraphicsHdcProvider
            //  2. One that is directly on Graphics
            //  3. All other IDeviceContext instances
            //
            // In the third case there is no Graphics to apply Properties from. In the second case we must query
            // the Graphics object itself for Properties (transform and clip). In the first case the
            // IGraphicsHdcProvider will let us know if we have an "unclean" Graphics object that we need to apply
            // Properties from.
            //
            // PaintEventArgs implements IGraphicsHdcProvider and uses it to let us know that either (1) a Graphics
            // object hasn't been created yet, OR (2) the Graphics object has never been given a transform or clip.

            bool needToApplyProperties = applyGraphicsState != ApplyGraphicsProperties.None;
            if (graphics is null && provider is null)
            {
                // We have an IDeviceContext (case 3 above), we can't apply properties because there is no
                // Graphics object available.
                needToApplyProperties = false;
            }
Ejemplo n.º 8
0
 public WindowsGraphicsWrapper(IDeviceContext idc, TextFormatFlags flags)
 {
     if (idc is Graphics)
     {
         ApplyGraphicsProperties none = ApplyGraphicsProperties.None;
         if ((flags & TextFormatFlags.PreserveGraphicsClipping) != TextFormatFlags.Default)
         {
             none |= ApplyGraphicsProperties.Clipping;
         }
         if ((flags & TextFormatFlags.PreserveGraphicsTranslateTransform) != TextFormatFlags.Default)
         {
             none |= ApplyGraphicsProperties.TranslateTransform;
         }
         if (none != ApplyGraphicsProperties.None)
         {
             this.wg = System.Windows.Forms.Internal.WindowsGraphics.FromGraphics(idc as Graphics, none);
         }
     }
     else
     {
         this.wg = idc as System.Windows.Forms.Internal.WindowsGraphics;
         if (this.wg != null)
         {
             this.idc = idc;
         }
     }
     if (this.wg == null)
     {
         this.idc = idc;
         this.wg  = System.Windows.Forms.Internal.WindowsGraphics.FromHdc(idc.GetHdc());
     }
     if ((flags & TextFormatFlags.LeftAndRightPadding) != TextFormatFlags.Default)
     {
         this.wg.TextPadding = TextPaddingOptions.LeftAndRightPadding;
     }
     else if ((flags & TextFormatFlags.NoPadding) != TextFormatFlags.Default)
     {
         this.wg.TextPadding = TextPaddingOptions.NoPadding;
     }
 }
Ejemplo n.º 9
0
        public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties properties)
        {
            Debug.Assert(g != null, "null Graphics object.");

            WindowsRegion wr = null;

            float[] elements = null;

            Region clipRgn     = null;
            Matrix worldTransf = null;

            if ((properties & ApplyGraphicsProperties.TranslateTransform) != 0 || (properties & ApplyGraphicsProperties.Clipping) != 0)
            {
                if (g.GetContextInfo() is object[] data && data.Length == 2)
                {
                    clipRgn     = data[0] as Region;
                    worldTransf = data[1] as Matrix;
                }

                if (worldTransf != null)
                {
                    if ((properties & ApplyGraphicsProperties.TranslateTransform) != 0)
                    {
                        elements = worldTransf.Elements;
                    }

                    worldTransf.Dispose();
                }

                if (clipRgn != null)
                {
                    if ((properties & ApplyGraphicsProperties.Clipping) != 0)
                    {
                        // We have to create the WindowsRegion and dipose the Region object before locking the Graphics object,
                        // in case of an unlikely exception before releasing the WindowsRegion, the finalizer will do it for us.
                        // (no try-finally block since this method is used frequently - perf).
                        // If the Graphics.Clip has not been set (Region.IsInfinite) we don't need to apply it to the DC.
                        if (!clipRgn.IsInfinite(g))
                        {
                            wr = WindowsRegion.FromRegion(clipRgn, g); // WindowsRegion will take ownership of the hRegion.
                        }
                    }

                    clipRgn.Dispose(); // Disposing the Region object doesn't destroy the hRegion.
                }
            }

            WindowsGraphics wg = FromHdc(g.GetHdc()); // This locks the Graphics object.

            wg._graphics = g;

            // Apply transform and clip
            if (wr != null)
            {
                using (wr)
                {
                    // 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.
                    wg.DeviceContext.IntersectClip(wr);
                }
            }

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

            return(wg);
        }
Ejemplo n.º 10
0
        /// <summary>
        ///     Creates a WindowsGraphics object from a Graphics object.  Clipping and coordinate transforms
        ///     are preserved.
        ///
        ///     Notes:
        ///     - The passed Graphics object cannot be used until the WindowsGraphics is disposed
        ///     since it borrows the hdc from the Graphics object locking it.
        ///     - Changes to the hdc using the WindowsGraphics object are not preserved into the Graphics object;
        ///     the hdc is returned to the Graphics object intact.
        ///
        ///     Some background about how Graphics uses the internal hdc when created from an existing one
        ///     (mail from GillesK from GDI+ team):
        ///     User has an HDC with a particular state:
        ///     Graphics object gets created based on that HDC. We query the HDC for its state and apply it to the Graphics.
        ///     At this stage, we do a SaveHDC and clear everything out of it.
        ///     User calls GetHdc. We restore the HDC to the state it was in and give it to the user.
        ///     User calls ReleaseHdc, we save the current state of the HDC and clear everything
        ///     (so that the graphics state gets applied next time we use it).
        ///     Next time the user calls GetHdc we give him back the state after the second ReleaseHdc.
        ///     (But the state changes between the GetHdc and ReleaseHdc are not applied to the Graphics).
        ///     Please note that this only applies the HDC created graphics, for Bitmap derived graphics, GetHdc creates a new DIBSection and
        ///     things get a lot more complicated.
        /// </summary>


        public static WindowsGraphics FromGraphics(Graphics g)
        {
            ApplyGraphicsProperties properties = ApplyGraphicsProperties.All;

            return(WindowsGraphics.FromGraphics(g, properties));
        }
Ejemplo n.º 11
0
        public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties properties)
        {
            Debug.Assert( g != null, "null Graphics object." );
            //Debug.Assert( properties != ApplyGraphicsProperties.None, "Consider using other WindowsGraphics constructor if not preserving Graphics properties." );

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

            Region clipRgn = null;
            Matrix worldTransf = null;

            if ((properties & ApplyGraphicsProperties.TranslateTransform) != 0 || (properties & ApplyGraphicsProperties.Clipping) != 0)
            {
                object[] data = g.GetContextInfo() as object[];

                if( data != null && data.Length == 2 )
                {
                    clipRgn = data[0] as Region;
                    worldTransf = data[1] as Matrix;
                }

                if( worldTransf != null )
                {
                    if ((properties & ApplyGraphicsProperties.TranslateTransform) != 0) 
                    {
                        elements = worldTransf.Elements;
                    }
                    worldTransf.Dispose();
                }

                if( clipRgn != null )
                {
                    if ((properties & ApplyGraphicsProperties.Clipping) != 0)
                    {
                        // We have to create the WindowsRegion and dipose the Region object before locking the Graphics object,
                        // in case of an unlikely exception before releasing the WindowsRegion, the finalizer will do it for us.
                        // (no try-finally block since this method is used frequently - perf).
                        // See VSWhidbey#383762
                        // If the Graphics.Clip has not been set (Region.IsInfinite) we don't need to apply it to the DC.
                        if (!clipRgn.IsInfinite(g)) 
                        {
                            wr = WindowsRegion.FromRegion(clipRgn, g); // WindowsRegion will take ownership of the hRegion.
                        }
                    }
                    clipRgn.Dispose(); // Disposing the Region object doesn't destroy the hRegion.
                }
            }

            WindowsGraphics wg = WindowsGraphics.FromHdc( g.GetHdc() ); // This locks the Graphics object.
            wg.graphics = g;

            // Apply transform and clip
            if (wr != null)
            {
                using (wr)
                {
                    // 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. See VSW#490404.
                    wg.DeviceContext.IntersectClip(wr);

                }
            }

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

            return wg;
        }
        public static WindowsGraphics FromGraphics(Graphics g)
        {
            ApplyGraphicsProperties all = ApplyGraphicsProperties.All;

            return(FromGraphics(g, all));
        }
Ejemplo n.º 13
0
        /// <summary>
        ///  Prefer to use <see cref="DeviceContextHdcScope(IDeviceContext, bool, bool)"/>.
        /// </summary>
        /// <remarks>
        ///  Ideally we'd not bifurcate what properties we apply unless we're absolutely sure we only want one.
        /// </remarks>
        public unsafe DeviceContextHdcScope(
            IDeviceContext deviceContext,
            ApplyGraphicsProperties applyGraphicsState,
            bool saveHdcState = false)
        {
            if (deviceContext is null)
            {
                DisposalTracking.SuppressFinalize(this !);
                throw new ArgumentNullException(nameof(deviceContext));
            }

            DeviceContext  = deviceContext;
            _savedHdcState = 0;

            HDC = default;

            IGraphicsHdcProvider?provider = deviceContext as IGraphicsHdcProvider;
            Graphics?            graphics = deviceContext as Graphics;

            // If we weren't passed a Graphics object we can't save state, so it is effectively the same as apply none.
            // If we were passed an IGraphicsHdcProvider and it tells us we're clean, we also don't need to save state.
            if (applyGraphicsState == ApplyGraphicsProperties.None || graphics is null || provider?.IsGraphicsStateClean == true)
            {
                if (provider is null)
                {
                    // We have an IDeviceContext
                    HDC = (Gdi32.HDC)deviceContext.GetHdc();
                }
                else
                {
                    // We have a provider
                    HDC = provider.GetHDC();

                    if (HDC.IsNull)
                    {
                        graphics = provider.GetGraphics(createIfNeeded: true);
                        if (graphics is null)
                        {
                            throw new InvalidOperationException();
                        }
                        HDC           = (Gdi32.HDC)graphics.GetHdc();
                        DeviceContext = graphics;
                    }
                }

                _savedHdcState = saveHdcState ? Gdi32.SaveDC(HDC) : 0;
                return;
            }

            _savedHdcState = saveHdcState ? Gdi32.SaveDC(HDC) : 0;
            bool applyTransform = applyGraphicsState.HasFlag(ApplyGraphicsProperties.TranslateTransform);
            bool applyClipping  = applyGraphicsState.HasFlag(ApplyGraphicsProperties.Clipping);

            // This API is very expensive
            object[]? data = applyTransform || applyClipping ? (object[])graphics.GetContextInfo() : null;

            using Region? clipRegion     = (Region?)data?[0];
            using Matrix? worldTransform = (Matrix?)data?[1];

            // elements (XFORM) = [eM11, eM12, eM21, eM22, eDx, eDy], eDx/eDy specify the translation offset.
            float[]? elements = applyTransform ? worldTransform?.Elements : null;
            int dx = elements != null ? (int)elements[4] : 0;
            int dy = elements != null ? (int)elements[5] : 0;

            applyTransform = applyTransform && elements != null && (dx != 0 || dy != 0);

            using var graphicsRegion = applyClipping ? new Gdi32.RegionScope(clipRegion !, graphics) : default;
Ejemplo n.º 14
0
        public WindowsGraphicsWrapper(IDeviceContext deviceContext, TextFormatFlags flags)
        {
            if (deviceContext is Graphics)
            {
                ApplyGraphicsProperties properties = ApplyGraphicsProperties.None;

                if ((flags & TextFormatFlags.PreserveGraphicsClipping) != 0)
                {
                    properties |= ApplyGraphicsProperties.Clipping;
                }

                if ((flags & TextFormatFlags.PreserveGraphicsTranslateTransform) != 0)
                {
                    properties |= ApplyGraphicsProperties.TranslateTransform;
                }

                // Create the WindowsGraphics from the Grahpics object only if Graphics properties need
                // to be reapplied to the DC wrapped by the WindowsGraphics.
                if (properties != ApplyGraphicsProperties.None)
                {
                    try
                    {
                        _windowsGraphics = WindowsGraphics.FromGraphics(deviceContext as Graphics, properties);
                    }
                    catch
                    {
                        GC.SuppressFinalize(this);
                        throw;
                    }
                }
            }
            else
            {
                // If passed-in IDeviceContext object is a WindowsGraphics we can use it directly.
                _windowsGraphics = deviceContext as WindowsGraphics;

                if (_windowsGraphics != null)
                {
                    // In this case we cache the idc to compare it against the wg in the Dispose method to avoid
                    // disposing of the wg.
                    _deviceContext = deviceContext;
                }
            }

            if (_windowsGraphics == null)
            {
                // The IDeviceContext object is not a WindowsGraphics, or it is a custom IDeviceContext, or
                // it is a Graphics object but we did not need to re-apply Graphics propertiesto the hdc.
                // So create the WindowsGraphics from the hdc directly.
                // Cache the IDC so the hdc can be released ons dispose.
                try
                {
                    _deviceContext   = deviceContext;
                    _windowsGraphics = WindowsGraphics.FromHdc((Gdi32.HDC)deviceContext.GetHdc());
                }
                catch
                {
                    SuppressFinalize();
                    deviceContext.ReleaseHdc();
                    throw;
                }
            }

            // Set text padding on the WindowsGraphics (if any).
            if ((flags & TextFormatFlags.LeftAndRightPadding) != 0)
            {
                _windowsGraphics.TextPadding = TextPaddingOptions.LeftAndRightPadding;
            }
            else if ((flags & TextFormatFlags.NoPadding) != 0)
            {
                _windowsGraphics.TextPadding = TextPaddingOptions.NoPadding;
            }
            // else wg.TextPadding = TextPaddingOptions.GlyphOverhangPadding - the default value.
        }