private static Rect CalculateSubgraphBoundsInnerSpace(Visual visual, bool renderBounds)
        {
            Rect boundingBoxSubGraph = Rect.Empty;

            int count = VisualTreeHelper.GetChildrenCount(visual);

            for (int i = 0; i < count; i++)
            {
                Visual child = VisualTreeHelper.GetChild(visual, i) as Visual;

                if (child != null && ((bool)CheckFlagsAndMethodInfo.Invoke(child, new object[] { Enum.Parse(VisualFlagsType, "VisibilityCache_Visible") }) || (bool)CheckFlagsAndMethodInfo.Invoke(child, new object[] { Enum.Parse(VisualFlagsType, "VisibilityCache_TakesSpace") })))
                {
                    Rect boundingBoxSubGraphChild = CalculateSubgraphBoundsOuterSpace(child, renderBounds);
                    boundingBoxSubGraph.Union(boundingBoxSubGraphChild);
                }
            }

            Rect contentBounds = VisualTreeHelper.GetContentBounds(visual);

            if (renderBounds && (bool)IsEmptyRenderBoundsMethodInfo.Invoke(visual, new object[] { contentBounds }))
            {
                contentBounds = Rect.Empty;
            }

            boundingBoxSubGraph.Union(contentBounds);

            return(boundingBoxSubGraph);
        }
        private static Rect CalculateSubgraphBoundsOuterSpace(Visual visual, bool renderBounds)
        {
            Rect boundingBoxSubGraph = CalculateSubgraphBoundsInnerSpace(visual, renderBounds);

            if ((bool)CheckFlagsAndMethodInfo.Invoke(visual, new object[] { Enum.Parse(VisualFlagsType, "NodeHasEffect") }))
            {
                Effect effect = (Effect)GetValueMethodInfo(typeof(Effect)).Invoke(EffectFieldFieldInfo.GetValue(visual), new object[] { visual });

                if (effect != null)
                {
                    Rect unitBounds            = new Rect(0, 0, 1, 1);
                    Rect unitTransformedBounds = (EffectMappingPropertyInfo.GetValue(effect) as GeneralTransform).TransformBounds(unitBounds);
                    Rect effectBounds          = (Rect)UnitToWorldMethodInfo.Invoke(null, new object[] { unitTransformedBounds, boundingBoxSubGraph });

                    boundingBoxSubGraph.Union(effectBounds);
                }
                else
                {
                    Debug.Assert(GetValueMethodInfo(BitmapEffectStateType).Invoke(BitmapEffectStateFieldFieldInfo.GetValue(visual), new object[] { visual }) != null);
                }
            }

            Geometry clip = (Geometry)GetValueMethodInfo(typeof(Geometry)).Invoke(ClipFieldFieldInfo.GetValue(visual), new object[] { visual });

            if (clip != null)
            {
                boundingBoxSubGraph.Intersect(clip.Bounds);
            }

            Transform transform = (Transform)GetValueMethodInfo(typeof(Transform)).Invoke(TransformFieldFieldInfo.GetValue(visual), new object[] { visual });

            if ((transform != null) && (!(bool)IsIdentityPropertyInfo.GetValue(transform)))
            {
                Matrix matrix = transform.Value;
                TransformRectMethodInfo.Invoke(null, new object[] { boundingBoxSubGraph, matrix });
            }

            if (!boundingBoxSubGraph.IsEmpty)
            {
                var _offset = (Vector)OffsetFieldInfo.GetValue(visual);
                boundingBoxSubGraph.X += _offset.X;
                boundingBoxSubGraph.Y += _offset.Y;
            }

            Rect?scrollClip = (Rect?)GetValueMethodInfo(typeof(Rect?)).Invoke(ScrollableAreaClipFieldFieldInfo.GetValue(visual), new object[] { visual });

            if (scrollClip.HasValue)
            {
                boundingBoxSubGraph.Intersect(scrollClip.Value);
            }

            if ((bool)RectHasNaNMethodInfo.Invoke(null, new object[] { boundingBoxSubGraph }))
            {
                boundingBoxSubGraph.X      = Double.NegativeInfinity;
                boundingBoxSubGraph.Y      = Double.NegativeInfinity;
                boundingBoxSubGraph.Width  = Double.PositiveInfinity;
                boundingBoxSubGraph.Height = Double.PositiveInfinity;
            }

            return(boundingBoxSubGraph);
        }