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 } } } } } } } }
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 } } } } } } } }