Example #1
0
        private static PathGeometryData MakeEmptyPathGeometryData()
        {
            PathGeometryData data = new PathGeometryData();

            data.FillRule = FillRule.EvenOdd;
            data.Matrix   = CompositionResourceManager.MatrixToMilMatrix3x2D(Matrix.Identity);

            unsafe
            {
                int size = sizeof(MIL_PATHGEOMETRY);

                data.SerializedData = new byte[size];

                fixed(byte *pbData = data.SerializedData)
                {
                    MIL_PATHGEOMETRY *pPathGeometry = (MIL_PATHGEOMETRY *)pbData;

                    // implicitly set pPathGeometry->Flags = 0;
                    pPathGeometry->FigureCount = 0;
                    pPathGeometry->Size        = (UInt32)size;
                }
            }

            return(data);
        }
Example #2
0
        /// <summary>
        /// GetPathGeometryData - returns a byte[] which contains this Geometry represented
        /// as a path geometry's serialized format.
        /// </summary>
        internal override PathGeometryData GetPathGeometryData()
        {
            if (IsObviouslyEmpty())
            {
                return(Geometry.GetEmptyPathGeometryData());
            }

            PathGeometryData data = new PathGeometryData();

            data.FillRule = FillRule.EvenOdd;
            data.Matrix   = CompositionResourceManager.TransformToMilMatrix3x2D(Transform);

            Point[] points = GetPointList();

            ByteStreamGeometryContext ctx = new ByteStreamGeometryContext();

            ctx.BeginFigure(points[0], true /* is filled */, true /* is closed */);

            // i == 0, 3, 6, 9
            for (int i = 0; i < 12; i += 3)
            {
                ctx.BezierTo(points[i + 1], points[i + 2], points[i + 3], true /* is stroked */, true /* is smooth join */);
            }

            ctx.Close();
            data.SerializedData = ctx.GetData();

            return(data);
        }
Example #3
0
        /// <summary>
        /// Gets the bounds of this PathGeometry as an axis-aligned bounding box with pen and/or transform
        /// </summary>
        internal static Rect GetPathBounds(
            PathGeometryData pathData,
            Pen pen,
            Matrix worldMatrix,
            double tolerance,
            ToleranceType type,
            bool skipHollows)
        {
            if (pathData.IsEmpty())
            {
                return(Rect.Empty);
            }
            else
            {
                MilRectD bounds = PathGeometry.GetPathBoundsAsRB(
                    pathData,
                    pen,
                    worldMatrix,
                    tolerance,
                    type,
                    skipHollows);

                return(bounds.AsRect);
            }
        }
Example #4
0
        /// <summary>
        /// GetPathGeometryData - returns a struct which contains this Geometry represented
        /// as a path geometry's serialized format.
        /// </summary>
        internal override PathGeometryData GetPathGeometryData()
        {
            PathGeometryData data = new PathGeometryData();

            data.FillRule = FillRule;
            data.Matrix   = CompositionResourceManager.TransformToMilMatrix3x2D(Transform);

            if (IsObviouslyEmpty())
            {
                return(Geometry.GetEmptyPathGeometryData());
            }

            ByteStreamGeometryContext ctx = new ByteStreamGeometryContext();

            PathFigureCollection figures = Figures;

            int figureCount = figures == null ? 0 : figures.Count;

            for (int i = 0; i < figureCount; i++)
            {
                figures.Internal_GetItem(i).SerializeData(ctx);
            }

            ctx.Close();
            data.SerializedData = ctx.GetData();

            return(data);
        }
Example #5
0
        public void GetPointAtFractionLength(
            double progress,
            out Point point,
            out Point tangent)
        {
            if (IsEmpty())
            {
                point   = new Point();
                tangent = new Point();
                return;
            }

            unsafe
            {
                PathGeometryData pathData = GetPathGeometryData();

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

                    HRESULT.Check(MilCoreApi.MilUtility_GetPointAtLengthFraction(
                                      &pathData.Matrix,
                                      pathData.FillRule,
                                      pbPathData,
                                      pathData.Size,
                                      progress,
                                      out point,
                                      out tangent));
                }
            }
        }
Example #6
0
        private static PathGeometryData MakeEmptyGeometryData()
        {
            PathGeometryData data = new PathGeometryData();

            data.FillRule = FillRule.EvenOdd;
            data.Offset   = Vector.Zero;
            return(data);
        }
Example #7
0
        public TechMapPath(Location p_startPoint, Location p_endPoint, byte p_groupIndex = 1)
        {
            this.startPoint = p_startPoint;
            this.endPoint   = p_endPoint;
            this.groupIndex = p_groupIndex;

            QuadraticBezierSegmentData mapQuadraticBezierSegment = new QuadraticBezierSegmentData()
            {
                Point1 = this.middlePoint, Point2 = p_endPoint
            };
            PathFigureData mapPathFigure = new PathFigureData()
            {
                StartPoint = p_startPoint, IsClosed = false
            };

            mapPathFigure.Segments.Add(mapQuadraticBezierSegment);

            PathGeometryData mapPathGeometry = new PathGeometryData();

            mapPathGeometry.Figures.Add(mapPathFigure);

            Brush stroke = Brushes.Transparent;

            this.Data = mapPathGeometry;
            switch (groupIndex)
            {
            case 1: { stroke = new SolidColorBrush(Colors.Red); break; }

            case 2: { stroke = new SolidColorBrush(Colors.Orange); break; }

            case 3: { stroke = new SolidColorBrush(Colors.Yellow); break; }

            case 4: { stroke = new SolidColorBrush(Colors.Green); break; }

            case 5: { stroke = new SolidColorBrush(Colors.LightBlue); break; }

            case 6: { stroke = new SolidColorBrush(Colors.Blue); break; }

            case 7: { stroke = new SolidColorBrush(Colors.Violet); break; }

            case 8: { stroke = new SolidColorBrush(Colors.Black); break; }
            }
            this.HighlightFill = new MapShapeFill()
            {
                Stroke = new SolidColorBrush(Colors.Green), StrokeThickness = 2
            };
            this.ShapeFill = new MapShapeFill()
            {
                Stroke = stroke, StrokeThickness = 10
            };
            this.SelectedFill = new MapShapeFill()
            {
                Stroke = Brushes.Black, StrokeThickness = 10
            };
        }
Example #8
0
        public virtual PathGeometry GetOutlinedPathGeometry(double tolerance, ToleranceType type)
        {
            ReadPreamble();

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

            PathGeometryData pathData = GetPathGeometryData();

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

            PathGeometry resultGeometry = null;

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

                    FillRule fillRule = FillRule.Nonzero;

                    PathGeometry.FigureList list = new PathGeometry.FigureList();

                    int hr = UnsafeNativeMethods.MilCoreApi.MilUtility_PathGeometryOutline(
                        &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);
                    }
                }
            }

            return(resultGeometry);
        }
Example #9
0
        private void ManualUpdateResource(DUCE.Channel channel, bool skipOnChannelCheck)
        {
            // If we're told we can skip the channel check, then we must be on channel
            Debug.Assert(!skipOnChannelCheck || _duceResource.IsOnChannel(channel));

            if (skipOnChannelCheck || _duceResource.IsOnChannel(channel))
            {
                checked
                {
                    Transform vTransform = Transform;

                    // Obtain handles for properties that implement DUCE.IResource
                    DUCE.ResourceHandle hTransform;
                    if (vTransform == null ||
                        Object.ReferenceEquals(vTransform, Transform.Identity)
                        )
                    {
                        hTransform = DUCE.ResourceHandle.Null;
                    }
                    else
                    {
                        hTransform = ((DUCE.IResource)vTransform).GetHandle(channel);
                    }

                    DUCE.MILCMD_PATHGEOMETRY data;
                    data.Type       = MILCMD.MilCmdPathGeometry;
                    data.Handle     = _duceResource.GetHandle(channel);
                    data.hTransform = hTransform;
                    data.FillRule   = FillRule;

                    PathGeometryData pathData = GetPathGeometryData();

                    data.FiguresSize = pathData.Size;

                    unsafe
                    {
                        channel.BeginCommand(
                            (byte *)&data,
                            sizeof(DUCE.MILCMD_PATHGEOMETRY),
                            (int)data.FiguresSize
                            );

                        fixed(byte *pPathData = pathData.SerializedData)
                        {
                            channel.AppendCommandData(pPathData, (int)data.FiguresSize);
                        }
                    }

                    channel.EndCommand();
                }
            }
        }
Example #10
0
        internal static IntersectionDetail HitTestWithPathGeometry(
            Geometry geometry1,
            Geometry geometry2,
            double tolerance,
            ToleranceType type)
        {
            IntersectionDetail detail = IntersectionDetail.NotCalculated;

            unsafe
            {
                PathGeometryData data1 = geometry1.GetPathGeometryData();
                PathGeometryData data2 = geometry2.GetPathGeometryData();

                fixed(byte *pbPathData1 = data1.SerializedData)
                {
                    Debug.Assert(pbPathData1 != (byte *)0);

                    fixed(byte *pbPathData2 = data2.SerializedData)
                    {
                        Debug.Assert(pbPathData2 != (byte *)0);

                        int hr = MilCoreApi.MilUtility_PathGeometryHitTestPathGeometry(
                            &data1.Matrix,
                            data1.FillRule,
                            pbPathData1,
                            data1.Size,
                            &data2.Matrix,
                            data2.FillRule,
                            pbPathData2,
                            data2.Size,
                            tolerance,
                            type == ToleranceType.Relative,
                            &detail);

                        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.
                            detail = IntersectionDetail.Empty;
                        }
                        else
                        {
                            HRESULT.Check(hr);
                        }
                    }
                }
            }

            Debug.Assert(detail != IntersectionDetail.NotCalculated);

            return(detail);
        }
Example #11
0
        public virtual double GetArea(double tolerance, ToleranceType type)
        {
            ReadPreamble();

            if (IsObviouslyEmpty())
            {
                return(0);
            }

            PathGeometryData pathData = GetPathGeometryData();

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

            double area;

            unsafe
            {
                // Call the core method on the path data
                fixed(byte *pbPathData = pathData.SerializedData)
                {
                    Debug.Assert(pbPathData != (byte *)0);

                    int hr = MilCoreApi.MilUtility_GeometryGetArea(
                        pathData.FillRule,
                        pbPathData,
                        pathData.Size,
                        &pathData.Matrix,
                        tolerance,
                        type == ToleranceType.Relative,
                        &area);

                    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 0 area.
                        area = 0.0;
                    }
                    else
                    {
                        HRESULT.Check(hr);
                    }
                }
            }

            return(area);
        }
Example #12
0
        /// <summary>
        /// GetPathGeometryData - returns a struct which contains this Geometry represented
        /// as a path geometry's serialized format.
        /// </summary>
        internal override PathGeometryData GetPathGeometryData()
        {
            if (IsEmpty())
            {
                return(Geometry.GetEmptyPathGeometryData());
            }

            PathGeometryData data = new PathGeometryData();

            data.FillRule       = FillRule;
            data.Matrix         = CompositionResourceManager.TransformToMilMatrix3x2D(Transform);
            data.SerializedData = _data;

            return(data);
        }
Example #13
0
        /// <summary>
        /// Creates the path geometry.
        /// </summary>
        /// <param name="geometryData">The geometry data.</param>
        /// <returns></returns>
        public static PathGeometry CreatePathGeometry(PathGeometryData geometryData)
        {
            var figures = new List <PathFigure>();

            foreach (var figureData in geometryData.Figures)
            {
                var segments = new List <PathSegment>();
                foreach (var segmentData in figureData.Segments)
                {
                    switch (segmentData.SegmentType)
                    {
                    case SegmentType.ArcSegment:
                        throw new NotImplementedException("{FD35628A-FB82-491E-B042-ED2F893D342B}");

                    case SegmentType.BezierSegment:
                        throw new NotImplementedException("{1B510116-A6D7-448B-99FF-D9F67210E8D3}");

                    case SegmentType.LineSegment: {
                        segments.Add(new LineSegment(segmentData.Nodes[0].Point, segmentData.Nodes[0].IsStroked));
                        break;
                    }

                    case SegmentType.PolyBezierSegment:
                        throw new NotImplementedException("{1EF8B9A9-BC3E-439C-A14E-3C56812D2002}");

                    case SegmentType.PolyLineSegment: {
                        var points = new List <Point>();
                        foreach (var nodeData in segmentData.Nodes)
                        {
                            points.Add(nodeData.Point);
                        }
                        segments.Add(new PolyLineSegment(points, segmentData.Nodes[0].IsStroked));
                        break;
                    }

                    case SegmentType.PolyQuadraticBezierSegment:
                        throw new NotImplementedException("{CD280F38-FC56-4838-A5D2-2BE04B5801C8}");

                    case SegmentType.QuadraticBezierSegment:
                        throw new NotImplementedException("{7DE58DAC-9A43-4657-90A5-7B38F5748C4C}");
                    }
                }
                figures.Add(new PathFigure(figureData.StartPoint, segments, figureData.IsClosed));
            }
            return(new PathGeometry(figures));
        }
Example #14
0
        /// <summary>
        /// Returns the axis-aligned bounding rectangle when stroked with a pen, after applying
        /// the supplied transform (if non-null).
        /// </summary>
        internal virtual Rect GetBoundsInternal(Pen pen, Matrix matrix, double tolerance, ToleranceType type)
        {
            if (IsObviouslyEmpty())
            {
                return(Rect.Empty);
            }

            PathGeometryData pathData = GetPathGeometryData();

            return(PathGeometry.GetPathBounds(
                       pathData,
                       pen,
                       matrix,
                       tolerance,
                       type,
                       true)); /* skip hollows */
        }
Example #15
0
        /// <summary>
        /// GetPathGeometryData - returns a byte[] which contains this Geometry represented
        /// as a path geometry's serialized format.
        /// </summary>
        internal override PathGeometryData GetPathGeometryData()
        {
            if (IsObviouslyEmpty())
            {
                return(Geometry.GetEmptyPathGeometryData());
            }

            PathGeometryData data = new PathGeometryData();

            data.FillRule = FillRule.EvenOdd;
            data.Matrix   = CompositionResourceManager.TransformToMilMatrix3x2D(Transform);

            double radiusX = RadiusX;
            double radiusY = RadiusY;
            Rect   rect    = Rect;

            ByteStreamGeometryContext ctx = new ByteStreamGeometryContext();

            if (IsRounded(radiusX, radiusY))
            {
                Point[] points = GetPointList(rect, radiusX, radiusY);

                ctx.BeginFigure(points[0], true /* is filled */, true /* is closed */);
                ctx.BezierTo(points[1], points[2], points[3], true /* is stroked */, false /* is smooth join */);
                ctx.LineTo(points[4], true /* is stroked */, false /* is smooth join */);
                ctx.BezierTo(points[5], points[6], points[7], true /* is stroked */, false /* is smooth join */);
                ctx.LineTo(points[8], true /* is stroked */, false /* is smooth join */);
                ctx.BezierTo(points[9], points[10], points[11], true /* is stroked */, false /* is smooth join */);
                ctx.LineTo(points[12], true /* is stroked */, false /* is smooth join */);
                ctx.BezierTo(points[13], points[14], points[15], true /* is stroked */, false /* is smooth join */);
            }
            else
            {
                ctx.BeginFigure(rect.TopLeft, true /* is filled */, true /* is closed */);
                ctx.LineTo(Rect.TopRight, true /* is stroked */, false /* is smooth join */);
                ctx.LineTo(Rect.BottomRight, true /* is stroked */, false /* is smooth join */);
                ctx.LineTo(Rect.BottomLeft, true /* is stroked */, false /* is smooth join */);
            }

            ctx.Close();
            data.SerializedData = ctx.GetData();

            return(data);
        }
Example #16
0
        /// <summary>
        /// GetPathGeometryData - returns a byte[] which contains this Geometry represented
        /// as a path geometry's serialized format.
        /// </summary>
        internal override PathGeometryData GetPathGeometryData()
        {
            if (IsObviouslyEmpty())
            {
                return(Geometry.GetEmptyPathGeometryData());
            }

            PathGeometryData data = new PathGeometryData();

            data.FillRule = FillRule.EvenOdd;
            data.Matrix   = CompositionResourceManager.TransformToMilMatrix3x2D(Transform);

            ByteStreamGeometryContext ctx = new ByteStreamGeometryContext();

            ctx.BeginFigure(StartPoint, true /* is filled */, false /* is closed */);
            ctx.LineTo(EndPoint, true /* is stroked */, false /* is smooth join */);

            ctx.Close();
            data.SerializedData = ctx.GetData();

            return(data);
        }
        /// <summary>
        /// GetPathGeometryData - returns a struct which contains this Geometry represented
        /// as a path geometry's serialized format.
        /// </summary>
        internal override PathGeometryData GetPathGeometryData()
        {
            if (IsEmpty())
            {
                return Geometry.GetEmptyPathGeometryData();
            }

            PathGeometryData data = new PathGeometryData();
            data.FillRule = FillRule;
            data.Matrix = CompositionResourceManager.TransformToMilMatrix3x2D(Transform);
            data.SerializedData = _data;

            return data;
        }
        /// <summary>
        /// GetPathGeometryData - returns a struct which contains this Geometry represented
        /// as a path geometry's serialized format.
        /// </summary>
        internal override PathGeometryData GetPathGeometryData()
        {
            PathGeometryData data = new PathGeometryData();
            data.FillRule = FillRule;
            data.Matrix = CompositionResourceManager.TransformToMilMatrix3x2D(Transform);
            
            if (IsObviouslyEmpty())
            {
                return Geometry.GetEmptyPathGeometryData();                
            }

            ByteStreamGeometryContext ctx = new ByteStreamGeometryContext();

            PathFigureCollection figures = Figures;

            int figureCount = figures == null ? 0 : figures.Count;

            for (int i = 0; i < figureCount; i++)
            {
                figures.Internal_GetItem(i).SerializeData(ctx);
            }

            ctx.Close();
            data.SerializedData = ctx.GetData();

            return data;
        }
Example #19
0
        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);
                }
            }
        }
        internal static void ParsePathGeometryData(PathGeometryData pathData, CapacityStreamGeometryContext ctx)
        {
            if (pathData.IsEmpty())
            {
                return;
            }

            unsafe
            {
                int currentOffset = 0;

                fixed (byte* pbData = pathData.SerializedData)
                {
                    // This assert is a logical correctness test
                    Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_PATHGEOMETRY));

                    // ... while this assert tests "physical" correctness (i.e. are we running out of buffer).
                    Invariant.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_PATHGEOMETRY));

                    MIL_PATHGEOMETRY *pPathGeometry = (MIL_PATHGEOMETRY*)pbData;

                    // Move the current offset to after the Path's data
                    currentOffset += sizeof(MIL_PATHGEOMETRY);

                    // Are there any Figures to add?
                    if (pPathGeometry->FigureCount > 0)
                    {
                        // Allocate the correct number of Figures up front
                        ctx.SetFigureCount((int)pPathGeometry->FigureCount);

                        // ... and iterate on the Figures.
                        for (int i = 0; i < pPathGeometry->FigureCount; i++)
                        {
                            // We only expect well-formed data, but we should assert that we're not reading
                            // too much data.
                            Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_PATHFIGURE));

                            MIL_PATHFIGURE *pPathFigure = (MIL_PATHFIGURE*)(pbData + currentOffset);

                            // Move the current offset to the after of the Figure's data
                            currentOffset += sizeof(MIL_PATHFIGURE);

                            ctx.BeginFigure(pPathFigure->StartPoint, 
                                            ((pPathFigure->Flags & MilPathFigureFlags.IsFillable) != 0),
                                            ((pPathFigure->Flags & MilPathFigureFlags.IsClosed) != 0));

                            if (pPathFigure->Count > 0)
                            {
                                // Allocate the correct number of Segments up front
                                ctx.SetSegmentCount((int)pPathFigure->Count);

                                // ... and iterate on the Segments.
                                for (int j = 0; j < pPathFigure->Count; j++)
                                {
                                    // We only expect well-formed data, but we should assert that we're not reading too much data.
                                    Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_SEGMENT));
                                    Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_SEGMENT));

                                    MIL_SEGMENT *pSegment = (MIL_SEGMENT*)(pbData + currentOffset);

                                    switch (pSegment->Type)
                                    {
                                    case MIL_SEGMENT_TYPE.MilSegmentLine:
                                        {
                                            // We only expect well-formed data, but we should assert that we're not reading too much data.
                                            Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_SEGMENT_LINE));
                                            Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_SEGMENT_LINE));

                                            MIL_SEGMENT_LINE *pSegmentLine = (MIL_SEGMENT_LINE*)(pbData + currentOffset);

                                            ctx.LineTo(pSegmentLine->Point, 
                                                       ((pSegmentLine->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                       ((pSegmentLine->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));

                                            currentOffset += sizeof(MIL_SEGMENT_LINE);
                                        }
                                        break;
                                    case MIL_SEGMENT_TYPE.MilSegmentBezier:
                                        {
                                            // We only expect well-formed data, but we should assert that we're not reading too much data.
                                            Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_SEGMENT_BEZIER));
                                            Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_SEGMENT_BEZIER));

                                            MIL_SEGMENT_BEZIER *pSegmentBezier = (MIL_SEGMENT_BEZIER*)(pbData + currentOffset);

                                            ctx.BezierTo(pSegmentBezier->Point1, 
                                                         pSegmentBezier->Point2,
                                                         pSegmentBezier->Point3,
                                                         ((pSegmentBezier->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                         ((pSegmentBezier->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));
                                            
                                            currentOffset += sizeof(MIL_SEGMENT_BEZIER);
                                        }
                                        break;
                                    case MIL_SEGMENT_TYPE.MilSegmentQuadraticBezier:
                                        {
                                            // We only expect well-formed data, but we should assert that we're not reading too much data.
                                            Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_SEGMENT_QUADRATICBEZIER));
                                            Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_SEGMENT_QUADRATICBEZIER));

                                            MIL_SEGMENT_QUADRATICBEZIER *pSegmentQuadraticBezier = (MIL_SEGMENT_QUADRATICBEZIER*)(pbData + currentOffset);

                                            ctx.QuadraticBezierTo(pSegmentQuadraticBezier->Point1, 
                                                                  pSegmentQuadraticBezier->Point2,
                                                                  ((pSegmentQuadraticBezier->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                                  ((pSegmentQuadraticBezier->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));
                                            
                                            currentOffset += sizeof(MIL_SEGMENT_QUADRATICBEZIER);
                                        }
                                        break;
                                    case MIL_SEGMENT_TYPE.MilSegmentArc:
                                        {
                                            // We only expect well-formed data, but we should assert that we're not reading too much data.
                                            Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_SEGMENT_ARC));
                                            Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_SEGMENT_ARC));

                                            MIL_SEGMENT_ARC *pSegmentArc = (MIL_SEGMENT_ARC*)(pbData + currentOffset);

                                            ctx.ArcTo(pSegmentArc->Point,
                                                      pSegmentArc->Size,
                                                      pSegmentArc->XRotation,
                                                      (pSegmentArc->LargeArc != 0),
                                                      (pSegmentArc->Sweep == 0) ? SweepDirection.Counterclockwise : SweepDirection.Clockwise,
                                                      ((pSegmentArc->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                      ((pSegmentArc->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));
                                            
                                            currentOffset += sizeof(MIL_SEGMENT_ARC);
                                        }
                                        break;
                                    case MIL_SEGMENT_TYPE.MilSegmentPolyLine:
                                    case MIL_SEGMENT_TYPE.MilSegmentPolyBezier:
                                    case MIL_SEGMENT_TYPE.MilSegmentPolyQuadraticBezier:
                                        {
                                            // We only expect well-formed data, but we should assert that we're not reading too much data.
                                            Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_SEGMENT_POLY));
                                            Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_SEGMENT_POLY));

                                            MIL_SEGMENT_POLY *pSegmentPoly = (MIL_SEGMENT_POLY*)(pbData + currentOffset);

                                            Debug.Assert(pSegmentPoly->Count <= Int32.MaxValue);

                                            if (pSegmentPoly->Count > 0)
                                            {
                                                List<Point> points = new List<Point>((int)pSegmentPoly->Count);

                                                // We only expect well-formed data, but we should assert that we're not reading too much data.
                                                Debug.Assert(pathData.SerializedData.Length >= 
                                                             currentOffset + 
                                                             sizeof(MIL_SEGMENT_POLY) +
                                                             (int)pSegmentPoly->Count * sizeof(Point));
                                                Debug.Assert(pathData.Size >= 
                                                             currentOffset + 
                                                             sizeof(MIL_SEGMENT_POLY) +
                                                             (int)pSegmentPoly->Count * sizeof(Point));

                                                Point* pPoint = (Point*)(pbData + currentOffset + sizeof(MIL_SEGMENT_POLY));

                                                for (uint k = 0; k < pSegmentPoly->Count; k++)
                                                {
                                                    points.Add(*pPoint);
                                                    pPoint++;
                                                }

                                                switch (pSegment->Type)
                                                {
                                                case MIL_SEGMENT_TYPE.MilSegmentPolyLine:
                                                    ctx.PolyLineTo(points,
                                                                   ((pSegmentPoly->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                                   ((pSegmentPoly->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));
                                                    break;
                                                case MIL_SEGMENT_TYPE.MilSegmentPolyBezier:
                                                    ctx.PolyBezierTo(points,
                                                                     ((pSegmentPoly->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                                     ((pSegmentPoly->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));
                                                    break;
                                                case MIL_SEGMENT_TYPE.MilSegmentPolyQuadraticBezier:
                                                    ctx.PolyQuadraticBezierTo(points,
                                                                   ((pSegmentPoly->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                                   ((pSegmentPoly->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));
                                                    break;
                                                }
                                            }

                                            currentOffset += sizeof(MIL_SEGMENT_POLY) + (int)pSegmentPoly->Count * sizeof(Point);
                                        }
                                        break;
#if DEBUG
                                    case MIL_SEGMENT_TYPE.MilSegmentNone:
                                        throw new System.InvalidOperationException();
                                    default:
                                        throw new System.InvalidOperationException();
#endif
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Example #21
0
        internal static PathGeometry InternalCombine(
            Geometry geometry1,
            Geometry geometry2,
            GeometryCombineMode mode,
            Transform transform,
            double tolerance,
            ToleranceType type)
        {
            PathGeometry resultGeometry = null;

            unsafe
            {
                MilMatrix3x2D matrix = CompositionResourceManager.TransformToMilMatrix3x2D(transform);

                PathGeometryData data1 = geometry1.GetPathGeometryData();
                PathGeometryData data2 = geometry2.GetPathGeometryData();

                fixed(byte *pPathData1 = data1.SerializedData)
                {
                    Debug.Assert(pPathData1 != (byte *)0);

                    fixed(byte *pPathData2 = data2.SerializedData)
                    {
                        Debug.Assert(pPathData2 != (byte *)0);

                        FillRule fillRule = FillRule.Nonzero;

                        FigureList list = new FigureList();
                        int        hr   = UnsafeNativeMethods.MilCoreApi.MilUtility_PathGeometryCombine(
                            &matrix,
                            &data1.Matrix,
                            data1.FillRule,
                            pPathData1,
                            data1.Size,
                            &data2.Matrix,
                            data2.FillRule,
                            pPathData2,
                            data2.Size,
                            tolerance,
                            type == ToleranceType.Relative,
                            new AddFigureToListDelegate(list.AddFigureToList),
                            mode,
                            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);
                        }
                    }
                }
            }

            return(resultGeometry);
        }
        /// <summary>
        /// Gets the bounds of this PathGeometry as an axis-aligned bounding box with pen and/or transform
        /// </summary>
        internal static Rect GetPathBounds(
            PathGeometryData pathData,
            Pen pen, 
            Matrix worldMatrix, 
            double tolerance, 
            ToleranceType type, 
            bool skipHollows)
        {
            if (pathData.IsEmpty())
            {
                return Rect.Empty;
            }
            else
            {
                MilRectD bounds = PathGeometry.GetPathBoundsAsRB(
                    pathData,
                    pen,
                    worldMatrix, 
                    tolerance, 
                    type,
                    skipHollows);

                return bounds.AsRect;
            }
        }
Example #23
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;
                }
            }
        }
        /// <summary>
        /// GetPathGeometryData - returns a byte[] which contains this Geometry represented
        /// as a path geometry's serialized format.
        /// </summary>
        internal override PathGeometryData GetPathGeometryData()
        {
            if (IsObviouslyEmpty())
            {
                return Geometry.GetEmptyPathGeometryData();
            }

            PathGeometryData data = new PathGeometryData();
            data.FillRule = FillRule.EvenOdd;
            data.Matrix = CompositionResourceManager.TransformToMilMatrix3x2D(Transform);

            ByteStreamGeometryContext ctx = new ByteStreamGeometryContext();

            ctx.BeginFigure(StartPoint, true /* is filled */, false /* is closed */);
            ctx.LineTo(EndPoint, true /* is stroked */, false /* is smooth join */);
            
            ctx.Close();
            data.SerializedData = ctx.GetData();

            return data;
        }
Example #26
0
        /// <summary> Creates the path geometry data.
        /// </summary>
        /// <param name="nodes">The nodes.</param>
        /// <returns></returns>
        public static PathGeometryData CreatePathGeometryData(IEnumerable <PathNodeData> nodes)
        {
            PathGeometryData geometryData = new PathGeometryData();
            PathFigureData   figure       = null;
            PathSegmentData  segment      = null;

            foreach (var node in nodes)
            {
                if (node.SegmentType == SegmentType.StartPoint)
                {
                    figure = new PathFigureData {
                        StartPoint = node.Point, IsClosed = node.IsClosed
                    };
                    geometryData.Figures.Add(figure);
                }
                else
                {
                    switch (node.SegmentType)
                    {
                    case SegmentType.ArcSegment:
                        throw new NotImplementedException("{C3DB91D2-6511-4274-B60F-99DF3CADF0A3}");

                    case SegmentType.BezierSegment:
                        throw new NotImplementedException("{D811AFE1-EB44-4671-9F27-E7609AEF8B5B}");

                    case SegmentType.LineSegment: {
                        figure.Segments.Add(new PathSegmentData {
                                Nodes = { node }, SegmentType = node.SegmentType
                            });
                        break;
                    }

                    case SegmentType.PolyBezierSegment:
                        throw new NotImplementedException("{3C01C459-4539-4D87-8206-DF1903491B63}");

                    case SegmentType.PolyLineSegment: {
                        if (node.SegmentIndex == 0)
                        {
                            segment = new PathSegmentData {
                                Nodes = { node }, SegmentType = node.SegmentType
                            };
                            figure.Segments.Add(segment);
                        }
                        else
                        {
                            segment.Nodes.Add(node);
                        }
                        break;
                    }

                    case SegmentType.PolyQuadraticBezierSegment:
                        throw new NotImplementedException("{61171A80-E52E-4C93-B7DE-DCF9C65B93F3}");

                    case SegmentType.QuadraticBezierSegment:
                        throw new NotImplementedException("{64CA6FB1-A5B2-4F5E-BE48-5A2E85F6B6B9}");

                    default:
                        throw new NotImplementedException("{E1D79545-F131-4196-B964-A74CBB99DBFD}");
                    }
                }
            }
            return(geometryData);
        }
Example #27
0
        /// <summary>
        /// GetPathGeometryData - returns a byte[] which contains this Geometry represented
        /// as a path geometry's serialized format.
        /// </summary>
        internal override PathGeometryData GetPathGeometryData()
        {
            if (IsObviouslyEmpty())
            {
                return Geometry.GetEmptyPathGeometryData();
            }

            PathGeometryData data = new PathGeometryData();
            data.FillRule = FillRule.EvenOdd;
            data.Matrix = CompositionResourceManager.TransformToMilMatrix3x2D(Transform);

            double radiusX = RadiusX;
            double radiusY = RadiusY;
            Rect rect = Rect;

            ByteStreamGeometryContext ctx = new ByteStreamGeometryContext();

            if (IsRounded(radiusX, radiusY))
            {
                Point[] points = GetPointList(rect, radiusX, radiusY);

                ctx.BeginFigure(points[0], true /* is filled */, true /* is closed */);
                ctx.BezierTo(points[1], points[2], points[3], true /* is stroked */, false /* is smooth join */);
                ctx.LineTo(points[4], true /* is stroked */, false /* is smooth join */);
                ctx.BezierTo(points[5], points[6], points[7], true /* is stroked */, false /* is smooth join */);
                ctx.LineTo(points[8], true /* is stroked */, false /* is smooth join */);
                ctx.BezierTo(points[9], points[10], points[11], true /* is stroked */, false /* is smooth join */);
                ctx.LineTo(points[12], true /* is stroked */, false /* is smooth join */);
                ctx.BezierTo(points[13], points[14], points[15], true /* is stroked */, false /* is smooth join */);
            }
            else
            {   
                ctx.BeginFigure(rect.TopLeft, true /* is filled */, true /* is closed */);
                ctx.LineTo(Rect.TopRight, true /* is stroked */, false /* is smooth join */);
                ctx.LineTo(Rect.BottomRight, true /* is stroked */, false /* is smooth join */);
                ctx.LineTo(Rect.BottomLeft, true /* is stroked */, false /* is smooth join */);
            }

            ctx.Close();
            data.SerializedData = ctx.GetData();

            return data;
        }
Example #28
0
        internal static void ParsePathGeometryData(PathGeometryData pathData, CapacityStreamGeometryContext ctx)
        {
            if (pathData.IsEmpty())
            {
                return;
            }

            unsafe
            {
                int currentOffset = 0;

                fixed(byte *pbData = pathData.SerializedData)
                {
                    // This assert is a logical correctness test
                    Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_PATHGEOMETRY));

                    // ... while this assert tests "physical" correctness (i.e. are we running out of buffer).
                    Invariant.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_PATHGEOMETRY));

                    MIL_PATHGEOMETRY *pPathGeometry = (MIL_PATHGEOMETRY *)pbData;

                    // Move the current offset to after the Path's data
                    currentOffset += sizeof(MIL_PATHGEOMETRY);

                    // Are there any Figures to add?
                    if (pPathGeometry->FigureCount > 0)
                    {
                        // Allocate the correct number of Figures up front
                        ctx.SetFigureCount((int)pPathGeometry->FigureCount);

                        // ... and iterate on the Figures.
                        for (int i = 0; i < pPathGeometry->FigureCount; i++)
                        {
                            // We only expect well-formed data, but we should assert that we're not reading
                            // too much data.
                            Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_PATHFIGURE));

                            MIL_PATHFIGURE *pPathFigure = (MIL_PATHFIGURE *)(pbData + currentOffset);

                            // Move the current offset to the after of the Figure's data
                            currentOffset += sizeof(MIL_PATHFIGURE);

                            ctx.BeginFigure(pPathFigure->StartPoint,
                                            ((pPathFigure->Flags & MilPathFigureFlags.IsFillable) != 0),
                                            ((pPathFigure->Flags & MilPathFigureFlags.IsClosed) != 0));

                            if (pPathFigure->Count > 0)
                            {
                                // Allocate the correct number of Segments up front
                                ctx.SetSegmentCount((int)pPathFigure->Count);

                                // ... and iterate on the Segments.
                                for (int j = 0; j < pPathFigure->Count; j++)
                                {
                                    // We only expect well-formed data, but we should assert that we're not reading too much data.
                                    Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_SEGMENT));
                                    Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_SEGMENT));

                                    MIL_SEGMENT *pSegment = (MIL_SEGMENT *)(pbData + currentOffset);

                                    switch (pSegment->Type)
                                    {
                                    case MIL_SEGMENT_TYPE.MilSegmentLine:
                                    {
                                        // We only expect well-formed data, but we should assert that we're not reading too much data.
                                        Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_SEGMENT_LINE));
                                        Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_SEGMENT_LINE));

                                        MIL_SEGMENT_LINE *pSegmentLine = (MIL_SEGMENT_LINE *)(pbData + currentOffset);

                                        ctx.LineTo(pSegmentLine->Point,
                                                   ((pSegmentLine->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                   ((pSegmentLine->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));

                                        currentOffset += sizeof(MIL_SEGMENT_LINE);
                                    }
                                    break;

                                    case MIL_SEGMENT_TYPE.MilSegmentBezier:
                                    {
                                        // We only expect well-formed data, but we should assert that we're not reading too much data.
                                        Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_SEGMENT_BEZIER));
                                        Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_SEGMENT_BEZIER));

                                        MIL_SEGMENT_BEZIER *pSegmentBezier = (MIL_SEGMENT_BEZIER *)(pbData + currentOffset);

                                        ctx.BezierTo(pSegmentBezier->Point1,
                                                     pSegmentBezier->Point2,
                                                     pSegmentBezier->Point3,
                                                     ((pSegmentBezier->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                     ((pSegmentBezier->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));

                                        currentOffset += sizeof(MIL_SEGMENT_BEZIER);
                                    }
                                    break;

                                    case MIL_SEGMENT_TYPE.MilSegmentQuadraticBezier:
                                    {
                                        // We only expect well-formed data, but we should assert that we're not reading too much data.
                                        Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_SEGMENT_QUADRATICBEZIER));
                                        Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_SEGMENT_QUADRATICBEZIER));

                                        MIL_SEGMENT_QUADRATICBEZIER *pSegmentQuadraticBezier = (MIL_SEGMENT_QUADRATICBEZIER *)(pbData + currentOffset);

                                        ctx.QuadraticBezierTo(pSegmentQuadraticBezier->Point1,
                                                              pSegmentQuadraticBezier->Point2,
                                                              ((pSegmentQuadraticBezier->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                              ((pSegmentQuadraticBezier->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));

                                        currentOffset += sizeof(MIL_SEGMENT_QUADRATICBEZIER);
                                    }
                                    break;

                                    case MIL_SEGMENT_TYPE.MilSegmentArc:
                                    {
                                        // We only expect well-formed data, but we should assert that we're not reading too much data.
                                        Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_SEGMENT_ARC));
                                        Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_SEGMENT_ARC));

                                        MIL_SEGMENT_ARC *pSegmentArc = (MIL_SEGMENT_ARC *)(pbData + currentOffset);

                                        ctx.ArcTo(pSegmentArc->Point,
                                                  pSegmentArc->Size,
                                                  pSegmentArc->XRotation,
                                                  (pSegmentArc->LargeArc != 0),
                                                  (pSegmentArc->Sweep == 0) ? SweepDirection.Counterclockwise : SweepDirection.Clockwise,
                                                  ((pSegmentArc->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                  ((pSegmentArc->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));

                                        currentOffset += sizeof(MIL_SEGMENT_ARC);
                                    }
                                    break;

                                    case MIL_SEGMENT_TYPE.MilSegmentPolyLine:
                                    case MIL_SEGMENT_TYPE.MilSegmentPolyBezier:
                                    case MIL_SEGMENT_TYPE.MilSegmentPolyQuadraticBezier:
                                    {
                                        // We only expect well-formed data, but we should assert that we're not reading too much data.
                                        Debug.Assert(pathData.SerializedData.Length >= currentOffset + sizeof(MIL_SEGMENT_POLY));
                                        Debug.Assert(pathData.Size >= currentOffset + sizeof(MIL_SEGMENT_POLY));

                                        MIL_SEGMENT_POLY *pSegmentPoly = (MIL_SEGMENT_POLY *)(pbData + currentOffset);

                                        Debug.Assert(pSegmentPoly->Count <= Int32.MaxValue);

                                        if (pSegmentPoly->Count > 0)
                                        {
                                            List <Point> points = new List <Point>((int)pSegmentPoly->Count);

                                            // We only expect well-formed data, but we should assert that we're not reading too much data.
                                            Debug.Assert(pathData.SerializedData.Length >=
                                                         currentOffset +
                                                         sizeof(MIL_SEGMENT_POLY) +
                                                         (int)pSegmentPoly->Count * sizeof(Point));
                                            Debug.Assert(pathData.Size >=
                                                         currentOffset +
                                                         sizeof(MIL_SEGMENT_POLY) +
                                                         (int)pSegmentPoly->Count * sizeof(Point));

                                            Point *pPoint = (Point *)(pbData + currentOffset + sizeof(MIL_SEGMENT_POLY));

                                            for (uint k = 0; k < pSegmentPoly->Count; k++)
                                            {
                                                points.Add(*pPoint);
                                                pPoint++;
                                            }

                                            switch (pSegment->Type)
                                            {
                                            case MIL_SEGMENT_TYPE.MilSegmentPolyLine:
                                                ctx.PolyLineTo(points,
                                                               ((pSegmentPoly->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                               ((pSegmentPoly->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));
                                                break;

                                            case MIL_SEGMENT_TYPE.MilSegmentPolyBezier:
                                                ctx.PolyBezierTo(points,
                                                                 ((pSegmentPoly->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                                 ((pSegmentPoly->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));
                                                break;

                                            case MIL_SEGMENT_TYPE.MilSegmentPolyQuadraticBezier:
                                                ctx.PolyQuadraticBezierTo(points,
                                                                          ((pSegmentPoly->Flags & MILCoreSegFlags.SegIsAGap) == 0),
                                                                          ((pSegmentPoly->Flags & MILCoreSegFlags.SegSmoothJoin) != 0));
                                                break;
                                            }
                                        }

                                        currentOffset += sizeof(MIL_SEGMENT_POLY) + (int)pSegmentPoly->Count * sizeof(Point);
                                    }
                                    break;

#if DEBUG
                                    case MIL_SEGMENT_TYPE.MilSegmentNone:
                                        throw new System.InvalidOperationException();

                                    default:
                                        throw new System.InvalidOperationException();
#endif
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Example #29
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);
        }
Example #30
0
        /// <summary>
        /// GetPathGeometryData - returns a byte[] which contains this Geometry represented
        /// as a path geometry's serialized format.
        /// </summary> 
        internal override PathGeometryData GetPathGeometryData()
        { 
            if (IsObviouslyEmpty()) 
            {
                return Geometry.GetEmptyPathGeometryData(); 
            }

            PathGeometryData data = new PathGeometryData();
            data.FillRule = FillRule.EvenOdd; 
            data.Matrix = CompositionResourceManager.TransformToMilMatrix3x2D(Transform);
 
            Point[] points = GetPointList(); 

            ByteStreamGeometryContext ctx = new ByteStreamGeometryContext(); 

            ctx.BeginFigure(points[0], true /* is filled */, true /* is closed */);

            // i == 0, 3, 6, 9 
            for (int i = 0; i < 12; i += 3)
            { 
                ctx.BezierTo(points[i + 1], points[i + 2], points[i + 3], true /* is stroked */, true /* is smooth join */); 
            }
 
            ctx.Close();
            data.SerializedData = ctx.GetData();

            return data; 
        }
Example #31
0
        private static PathGeometryData MakeEmptyPathGeometryData()
        {
            PathGeometryData data = new PathGeometryData();
            data.FillRule = FillRule.EvenOdd;
            data.Matrix = CompositionResourceManager.MatrixToMilMatrix3x2D(Matrix.Identity);

            unsafe
            {
                int size = sizeof(MIL_PATHGEOMETRY);

                data.SerializedData = new byte[size];

                fixed (byte *pbData = data.SerializedData)
                {
                    MIL_PATHGEOMETRY *pPathGeometry = (MIL_PATHGEOMETRY*)pbData;

                    // implicitly set pPathGeometry->Flags = 0;
                    pPathGeometry->FigureCount = 0;
                    pPathGeometry->Size = (UInt32)size;
                }
            }

            return data;
        }