Esempio n. 1
0
        public virtual PathGeometry GetWidenedPathGeometry(Pen pen, double tolerance, ToleranceType type)
        {
            ReadPreamble();

            if (pen == null)
            {
                throw new System.ArgumentNullException("pen");
            }

            if (IsObviouslyEmpty())
            {
                return new PathGeometry();
            }

            PathGeometryData pathData = GetPathGeometryData();

            if (pathData.IsEmpty())
            {
                return new PathGeometry();
            }

            PathGeometry resultGeometry = null;

            unsafe
            {
                MIL_PEN_DATA penData;
                double[] dashArray = null;

                pen.GetBasicPenData(&penData, out dashArray);

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

                    FillRule fillRule = FillRule.Nonzero;

                    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)
                    {
                        handle = GCHandle.Alloc(dashArray, GCHandleType.Pinned);
                    }

                    try
                    {
                        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)
                        {
                            // 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();
                        }
                        else
                        {
                            HRESULT.Check(hr);

                            resultGeometry = new PathGeometry(list.Figures, fillRule, null);
                        }
                    }
                    finally
                    {
                        if (handle.IsAllocated)
                        {
                            handle.Free();
                        }
                    }

                }

                return resultGeometry;
            }
        }
        internal static MilRectD GetPathBoundsAsRB(
            PathGeometryData pathData,
            Pen pen, 
            Matrix worldMatrix, 
            double tolerance, 
            ToleranceType type, 
            bool skipHollows)
        {
            // This method can't handle the empty geometry case, as it's impossible for us to
            // return Rect.Empty. Callers should do their own check.
            Debug.Assert(!pathData.IsEmpty());

            unsafe
            {
                MIL_PEN_DATA penData;
                double[] dashArray = null;

                // If we have a pen, populate the CMD struct
                if (pen != null)
                {
                    pen.GetBasicPenData(&penData, out dashArray);
                }

                MilMatrix3x2D worldMatrix3X2 = CompositionResourceManager.MatrixToMilMatrix3x2D(ref worldMatrix);

                fixed (byte *pbPathData = pathData.SerializedData)
                {
                    MilRectD bounds;

                    Debug.Assert(pbPathData != (byte*)0);

                    fixed (double *pDashArray = dashArray)
                    {
                        int hr = UnsafeNativeMethods.MilCoreApi.MilUtility_PathGeometryBounds(
                            (pen == null) ? null : &penData,
                            pDashArray,
                            &worldMatrix3X2,
                            pathData.FillRule,
                            pbPathData,
                            pathData.Size,
                            &pathData.Matrix,
                            tolerance,
                            type == ToleranceType.Relative,
                            skipHollows,
                            &bounds
                            );

                        if (hr == (int)MILErrors.WGXERR_BADNUMBER)
                        {
                            // When we encounter NaNs in the renderer, we absorb the error and draw
                            // nothing. To be consistent, we report that the geometry has empty bounds
                            // (NaN will get transformed into Rect.Empty higher up).

                            bounds = MilRectD.NaN;
                        }
                        else
                        {
                            HRESULT.Check(hr);
                        }
                    }

                    return bounds;
                }
            }
        }
Esempio n. 3
0
        internal virtual bool ContainsInternal(Pen pen, Point hitPoint, double tolerance, ToleranceType type)
        {
            if (IsObviouslyEmpty())
            {
                return false;
            }

            PathGeometryData pathData = GetPathGeometryData();

            if (pathData.IsEmpty())
            {
                return false;
            }

            bool contains = false;

            unsafe
            {   
                MIL_PEN_DATA penData;
                double[] dashArray = null;

                // If we have a pen, populate the CMD struct
                if (pen != null)
                {
                    pen.GetBasicPenData(&penData, out dashArray);
                }

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

                    fixed (double * dashArrayFixed = dashArray)
                    {
                        int hr = MilCoreApi.MilUtility_PathGeometryHitTest(
                                &pathData.Matrix,
                                (pen == null) ? null : &penData,
                                dashArrayFixed,
                                pathData.FillRule,
                                pbPathData,
                                pathData.Size,
                                tolerance,
                                type == ToleranceType.Relative,
                                &hitPoint,
                                out contains);

                        if (hr == (int)MILErrors.WGXERR_BADNUMBER)
                        {
                            // When we encounter NaNs in the renderer, we absorb the error and draw
                            // nothing. To be consistent, we report that the geometry is never hittable.
                            contains = false;
                        }
                        else
                        {
                            HRESULT.Check(hr);
                        }
                    }
                }
            }

            return contains;
        }
Esempio n. 4
0
        internal unsafe bool ContainsInternal(Pen pen, Point hitPoint, double tolerance, ToleranceType type, 
                                                Point *pPoints, uint pointCount, byte *pTypes, uint typeCount)
        {
            bool contains = false;

            MilMatrix3x2D matrix = CompositionResourceManager.TransformToMilMatrix3x2D(Transform);

            MIL_PEN_DATA penData;
            double[] dashArray = null;

            if (pen != null)
            {
                pen.GetBasicPenData(&penData, out dashArray);
            }

            fixed (double *dashArrayFixed = dashArray)
            {
                int hr = MilCoreApi.MilUtility_PolygonHitTest(
                        &matrix,
                        (pen == null) ? null : &penData,
                        dashArrayFixed,
                        pPoints,
                        pTypes,
                        pointCount,
                        typeCount,
                        tolerance,
                        type == ToleranceType.Relative,
                        &hitPoint,
                        out contains);

                if (hr == (int)MILErrors.WGXERR_BADNUMBER)
                {
                    // When we encounter NaNs in the renderer, we absorb the error and draw
                    // nothing. To be consistent, we report that the geometry is never hittable.
                    contains = false;
                }
                else
                {
                    HRESULT.Check(hr);
                }
            }

            return contains;
        }
Esempio n. 5
0
        internal unsafe static Rect GetBoundsHelper(
            Pen pen, 
            Matrix *pWorldMatrix, 
            Point* pPoints, 
            byte *pTypes, 
            uint pointCount,
            uint segmentCount,
            Matrix *pGeometryMatrix,
            double tolerance, 
            ToleranceType type,
            bool fSkipHollows)
        {
            MIL_PEN_DATA penData;
            double[] dashArray = null;

            // If the pen contributes to the bounds, populate the CMD struct
            bool fPenContributesToBounds = Pen.ContributesToBounds(pen);

            if (fPenContributesToBounds)
            {
                pen.GetBasicPenData(&penData, out dashArray);
            }

            MilMatrix3x2D geometryMatrix;
            if (pGeometryMatrix != null)
            {
                geometryMatrix = CompositionResourceManager.MatrixToMilMatrix3x2D(ref (*pGeometryMatrix));
            }

            Debug.Assert(pWorldMatrix != null);
            MilMatrix3x2D worldMatrix =
                CompositionResourceManager.MatrixToMilMatrix3x2D(ref (*pWorldMatrix));

            Rect bounds;

            fixed (double *pDashArray = dashArray)
            {
                int hr = MilCoreApi.MilUtility_PolygonBounds(
                    &worldMatrix,
                    (fPenContributesToBounds) ? &penData : null,
                    (dashArray == null) ? null : pDashArray,
                    pPoints,
                    pTypes,
                    pointCount,
                    segmentCount,
                    (pGeometryMatrix == null) ? null : &geometryMatrix,
                    tolerance,
                    type == ToleranceType.Relative,
                    fSkipHollows,
                    &bounds
                );

                if (hr == (int)MILErrors.WGXERR_BADNUMBER)
                {
                    // When we encounter NaNs in the renderer, we absorb the error and draw
                    // nothing. To be consistent, we report that the geometry has empty bounds.
                    bounds = Rect.Empty;
                }
                else
                {
                    HRESULT.Check(hr);
                }
            }

            return bounds;
        }
Esempio n. 6
0
        internal virtual bool ContainsInternal(Pen pen, Point hitPoint, double tolerance, ToleranceType type)
        {
            if (IsObviouslyEmpty())
            {
                return(false);
            }

            PathGeometryData pathData = GetPathGeometryData();

            if (pathData.IsEmpty())
            {
                return(false);
            }

            bool contains = false;

            unsafe
            {
                MIL_PEN_DATA penData;
                double[]     dashArray = null;

                // If we have a pen, populate the CMD struct
                if (pen != null)
                {
                    pen.GetBasicPenData(&penData, out dashArray);
                }

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

                    fixed(double *dashArrayFixed = dashArray)
                    {
                        int hr = MilCoreApi.MilUtility_PathGeometryHitTest(
                            &pathData.Matrix,
                            (pen == null) ? null : &penData,
                            dashArrayFixed,
                            pathData.FillRule,
                            pbPathData,
                            pathData.Size,
                            tolerance,
                            type == ToleranceType.Relative,
                            &hitPoint,
                            out contains);

                        if (hr == (int)MILErrors.WGXERR_BADNUMBER)
                        {
                            // When we encounter NaNs in the renderer, we absorb the error and draw
                            // nothing. To be consistent, we report that the geometry is never hittable.
                            contains = false;
                        }
                        else
                        {
                            HRESULT.Check(hr);
                        }
                    }
                }
            }

            return(contains);
        }
Esempio n. 7
0
        internal unsafe static Rect GetBoundsHelper(
            Pen pen,
            Matrix *pWorldMatrix,
            Point *pPoints,
            byte *pTypes,
            uint pointCount,
            uint segmentCount,
            Matrix *pGeometryMatrix,
            double tolerance,
            ToleranceType type,
            bool fSkipHollows)
        {
            MIL_PEN_DATA penData;

            double[] dashArray = null;

            // If the pen contributes to the bounds, populate the CMD struct
            bool fPenContributesToBounds = Pen.ContributesToBounds(pen);

            if (fPenContributesToBounds)
            {
                pen.GetBasicPenData(&penData, out dashArray);
            }

            MilMatrix3x2D geometryMatrix;

            if (pGeometryMatrix != null)
            {
                geometryMatrix = CompositionResourceManager.MatrixToMilMatrix3x2D(ref (*pGeometryMatrix));
            }

            Debug.Assert(pWorldMatrix != null);
            MilMatrix3x2D worldMatrix =
                CompositionResourceManager.MatrixToMilMatrix3x2D(ref (*pWorldMatrix));

            Rect bounds;

            fixed(double *pDashArray = dashArray)
            {
                int hr = MilCoreApi.MilUtility_PolygonBounds(
                    &worldMatrix,
                    (fPenContributesToBounds) ? &penData : null,
                    (dashArray == null) ? null : pDashArray,
                    pPoints,
                    pTypes,
                    pointCount,
                    segmentCount,
                    (pGeometryMatrix == null) ? null : &geometryMatrix,
                    tolerance,
                    type == ToleranceType.Relative,
                    fSkipHollows,
                    &bounds
                    );

                if (hr == (int)MILErrors.WGXERR_BADNUMBER)
                {
                    // When we encounter NaNs in the renderer, we absorb the error and draw
                    // nothing. To be consistent, we report that the geometry has empty bounds.
                    bounds = Rect.Empty;
                }
                else
                {
                    HRESULT.Check(hr);
                }
            }

            return(bounds);
        }
Esempio n. 8
0
        /// <summary>
        /// Create the contour of the stroke defined by given pen when it draws this path
        /// </summary>
        /// <param name="pen">The pen used for stroking this path</param>
        /// <param name="tolerance">The computational error tolerance</param>
        /// <param name="type">The way the error tolerance will be interpreted - relative or absolute</param>
        /// <returns>Returns the contour as a PathGeometry.</returns>
        public virtual PathGeometry GetWidenedPathGeometry(Pen pen, double tolerance, ToleranceType type)
        {
            ReadPreamble();

            if (pen == null)
            {
                throw new System.ArgumentNullException("pen");
            }

            if (IsObviouslyEmpty())
            {
                return(new PathGeometry());
            }

            PathGeometryData pathData = GetPathGeometryData();

            if (pathData.IsEmpty())
            {
                return(new PathGeometry());
            }

            PathGeometry resultGeometry = null;

            unsafe
            {
                MIL_PEN_DATA penData;
                double[]     dashArray = null;

                pen.GetBasicPenData(&penData, out dashArray);

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

                    FillRule fillRule = FillRule.Nonzero;

                    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)
                    {
                        handle = GCHandle.Alloc(dashArray, GCHandleType.Pinned);
                    }

                    try
                    {
                        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)
                        {
                            // 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();
                        }
                        else
                        {
                            HRESULT.Check(hr);

                            resultGeometry = new PathGeometry(list.Figures, fillRule, null);
                        }
                    }
                    finally
                    {
                        if (handle.IsAllocated)
                        {
                            handle.Free();
                        }
                    }
                }

                return(resultGeometry);
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Gets the bounds of this PathGeometry as an axis-aligned bounding box with pen and/or transform
        ///
        /// This function should not be called with a PathGeometryData that's known to be empty, since MilRectD
        /// does not offer a standard way of representing this.
        /// </summary>
        internal static MilRectD GetPathBoundsAsRB(
            PathGeometryData pathData,
            Pen pen,
            Matrix worldMatrix,
            double tolerance,
            ToleranceType type,
            bool skipHollows)
        {
            // This method can't handle the empty geometry case, as it's impossible for us to
            // return Rect.Empty. Callers should do their own check.
            Debug.Assert(!pathData.IsEmpty());

            unsafe
            {
                MIL_PEN_DATA penData;
                double[]     dashArray = null;

                // If we have a pen, populate the CMD struct
                if (pen != null)
                {
                    pen.GetBasicPenData(&penData, out dashArray);
                }

                MilMatrix3x2D worldMatrix3X2 = CompositionResourceManager.MatrixToMilMatrix3x2D(ref worldMatrix);

                fixed(byte *pbPathData = pathData.SerializedData)
                {
                    MilRectD bounds;

                    Debug.Assert(pbPathData != (byte *)0);

                    fixed(double *pDashArray = dashArray)
                    {
                        int hr = UnsafeNativeMethods.MilCoreApi.MilUtility_PathGeometryBounds(
                            (pen == null) ? null : &penData,
                            pDashArray,
                            &worldMatrix3X2,
                            pathData.FillRule,
                            pbPathData,
                            pathData.Size,
                            &pathData.Matrix,
                            tolerance,
                            type == ToleranceType.Relative,
                            skipHollows,
                            &bounds
                            );

                        if (hr == (int)MILErrors.WGXERR_BADNUMBER)
                        {
                            // When we encounter NaNs in the renderer, we absorb the error and draw
                            // nothing. To be consistent, we report that the geometry has empty bounds
                            // (NaN will get transformed into Rect.Empty higher up).

                            bounds = MilRectD.NaN;
                        }
                        else
                        {
                            HRESULT.Check(hr);
                        }
                    }

                    return(bounds);
                }
            }
        }