/// <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); } }
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); }
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); }
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 } } } } } } } }
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 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); }
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> /// 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; } }
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 } } } } } } } }