ByteStreamGeometryContext.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Media / ByteStreamGeometryContext.cs / 1305600 / ByteStreamGeometryContext.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// This class is used by the StreamGeometry class to generate an inlined, 
// flattened geometry stream. 
//
//--------------------------------------------------------------------------- 

using MS.Utility;
using MS.Internal;
using MS.Internal.PresentationCore; 
using System;
using System.Collections; 
using System.Collections.Generic; 
using System.Runtime.InteropServices;
using System.Windows.Threading; 
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Composition; 
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging; 
using System.Windows.Media.Media3D; 
using System.Diagnostics;
using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID;
using System.Security;
using System.Security.Permissions;
 
namespace System.Windows.Media
{ 
    ///  
    ///     ByteStreamGeometryContext
    ///  
    internal class ByteStreamGeometryContext : CapacityStreamGeometryContext
    {
        #region Constructors
 
        /// 
        /// Creates a geometry stream context. 
        ///  
        /// 
        /// Critical - it has an unsafe block 
        /// TreatAsSafe - manipulating a buffer is considered safe
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal ByteStreamGeometryContext() 
        {
            // For now, we just write this into the stream.  We'll update its fields as we go. 
            MIL_PATHGEOMETRY tempPath = new MIL_PATHGEOMETRY(); 

            unsafe 
            {
                AppendData((byte*)&tempPath, sizeof(MIL_PATHGEOMETRY));

                // Initialize the size to include the MIL_PATHGEOMETRY itself 
                // All other fields are intentionally left as 0;
                _currentPathGeometryData.Size = (uint)sizeof(MIL_PATHGEOMETRY); 
            } 
        }
 
        #endregion Constructors

        #region Public Methods
 
        /// 
        /// Closes the StreamContext and flushes the content. 
        /// Afterwards the StreamContext can not be used anymore. 
        /// This call does not require all Push calls to have been Popped.
        ///  
        /// 
        /// This call is illegal if this object has already been closed or disposed.
        /// 
        public override void Close() 
        {
            VerifyApi(); 
            ((IDisposable)this).Dispose(); 
        }
 
        /// 
        /// BeginFigure - Start a new figure.
        /// 
        ///  
        /// Critical - it has an unsafe block
        /// PublicOK - This function takes the address of a stack variable. 
        ///  
        [SecurityCritical]
        public override void BeginFigure(Point startPoint, bool isFilled, bool isClosed) 
        {
            VerifyApi();

            // Don't forget to close out the previous segment/figure 
            FinishFigure();
 
            // Remember the location - we set this only after successful allocation in case it throws 
            // and we're re-entered.
            int oldOffset = _currOffset; 

            MIL_PATHFIGURE tempFigure;

            unsafe 
            {
                AppendData((byte*)&tempFigure, sizeof(MIL_PATHFIGURE)); 
            } 

            _currentPathFigureDataOffset = oldOffset; 
            _currentPathFigureData.StartPoint = startPoint;
            _currentPathFigureData.Flags |= isFilled ? MilPathFigureFlags.IsFillable : 0;
            _currentPathFigureData.Flags |= isClosed ? MilPathFigureFlags.IsClosed : 0;
            _currentPathFigureData.BackSize = _lastFigureSize; 
            _currentPathFigureData.Size = (UInt32)(_currOffset - _currentPathFigureDataOffset);
        } 
 
        /// 
        /// LineTo - append a LineTo to the current figure. 
        /// 
        public override void LineTo(Point point, bool isStroked, bool isSmoothJoin)
        {
            VerifyApi(); 

            _scratchForLine[0] = point; 
            GenericPolyTo(_scratchForLine, 
                          isStroked,
                          isSmoothJoin, 
                          false /* does not have curves */,
                          1 /* pointCountMultiple */,
                          MIL_SEGMENT_TYPE.MilSegmentPolyLine);
        } 

        ///  
        /// QuadraticBezierTo - append a QuadraticBezierTo to the current figure. 
        /// 
        public override void QuadraticBezierTo(Point point1, Point point2, bool isStroked, bool isSmoothJoin) 
        {
            VerifyApi();

            _scratchForQuadraticBezier[0] = point1; 
            _scratchForQuadraticBezier[1] = point2;
            GenericPolyTo(_scratchForQuadraticBezier, 
                          isStroked, 
                          isSmoothJoin,
                          true /* has curves */, 
                          2 /* pointCountMultiple */,
                          MIL_SEGMENT_TYPE.MilSegmentPolyQuadraticBezier);
        }
 
        /// 
        /// BezierTo - apply a BezierTo to the current figure. 
        ///  
        public override void BezierTo(Point point1, Point point2, Point point3, bool isStroked, bool isSmoothJoin)
        { 
            VerifyApi();

            _scratchForBezier[0] = point1;
            _scratchForBezier[1] = point2; 
            _scratchForBezier[2] = point3;
            GenericPolyTo(_scratchForBezier, 
                          isStroked, 
                          isSmoothJoin,
                          true /* has curves */, 
                          3 /* pointCountMultiple */,
                          MIL_SEGMENT_TYPE.MilSegmentPolyBezier);
        }
 
        /// 
        /// PolyLineTo - append a PolyLineTo to the current figure. 
        ///  
        public override void PolyLineTo(IList points, bool isStroked, bool isSmoothJoin)
        { 
            VerifyApi();

            GenericPolyTo(points,
                          isStroked, 
                          isSmoothJoin,
                          false /* does not have curves */, 
                          1 /* pointCountMultiple */, 
                          MIL_SEGMENT_TYPE.MilSegmentPolyLine);
        } 

        /// 
        /// PolyQuadraticBezierTo - append a PolyQuadraticBezierTo to the current figure.
        ///  
        public override void PolyQuadraticBezierTo(IList points, bool isStroked, bool isSmoothJoin)
        { 
            VerifyApi(); 

            GenericPolyTo(points, 
                          isStroked,
                          isSmoothJoin,
                          true /* has curves */,
                          2 /* pointCountMultiple */, 
                          MIL_SEGMENT_TYPE.MilSegmentPolyQuadraticBezier);
        } 
 
        /// 
        /// PolyBezierTo - append a PolyBezierTo to the current figure. 
        /// 
        public override void PolyBezierTo(IList points, bool isStroked, bool isSmoothJoin)
        {
            VerifyApi(); 

            GenericPolyTo(points, 
                          isStroked, 
                          isSmoothJoin,
                          true /* has curves */, 
                          3 /* pointCountMultiple */,
                          MIL_SEGMENT_TYPE.MilSegmentPolyBezier);
        }
 
        /// 
        /// ArcTo - append an ArcTo to the current figure. 
        ///  
        /// 
        /// Critical - it has an unsafe block 
        /// PublicOk - This function takes the address of a stack variable.
        /// 
        [SecurityCritical]
        public override void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection, bool isStroked, bool isSmoothJoin) 
        {
            VerifyApi(); 
 
            if (_currentPathFigureDataOffset == -1)
            { 
                throw new InvalidOperationException(SR.Get(SRID.StreamGeometry_NeedBeginFigure));
            }

            FinishSegment(); 

            MIL_SEGMENT_ARC arcToSegment = new MIL_SEGMENT_ARC(); 
            arcToSegment.Type = MIL_SEGMENT_TYPE.MilSegmentArc; 

            arcToSegment.Flags |= isStroked ? 0 : MILCoreSegFlags.SegIsAGap; 
            arcToSegment.Flags |= isSmoothJoin ? MILCoreSegFlags.SegSmoothJoin : 0;
            arcToSegment.Flags |= MILCoreSegFlags.SegIsCurved;
            arcToSegment.BackSize = _lastSegmentSize;
 
            arcToSegment.Point = point;
            arcToSegment.Size = size; 
            arcToSegment.XRotation = rotationAngle; 
            arcToSegment.LargeArc = (uint)(isLargeArc ? 1 : 0);
            arcToSegment.Sweep = (uint)(sweepDirection == SweepDirection.Clockwise ? 1 : 0); 

            int offsetToArcToSegment = _currOffset;

            unsafe 
            {
                AppendData((byte*)(&arcToSegment), sizeof(MIL_SEGMENT_ARC)); 
                _lastSegmentSize = (UInt32)sizeof(MIL_SEGMENT_ARC); 
            }
 
            // Update the current path figure data
            _currentPathFigureData.Flags |= isStroked ? 0 : MilPathFigureFlags.HasGaps;

            _currentPathFigureData.Flags |= MilPathFigureFlags.HasCurves; 

            _currentPathFigureData.Count++; 
 
            // Always keep the OffsetToLastSegment and Size accurate
            _currentPathFigureData.Size = (UInt32)(_currOffset - _currentPathFigureDataOffset); 

            _currentPathFigureData.OffsetToLastSegment =
                (UInt32)(offsetToArcToSegment - _currentPathFigureDataOffset);
        } 

        #endregion Public Methods 
 
        #region Internal Methods
 
        /// 
        /// GetData - Retrieves the data stream built by this Context.
        /// 
        internal byte[] GetData() 
        {
            ShrinkToFit(); 
 
            return _chunkList[0];
        } 

        override internal void SetClosedState(bool isClosed)
        {
            if (_currentPathFigureDataOffset == -1) 
            {
                throw new InvalidOperationException(SR.Get(SRID.StreamGeometry_NeedBeginFigure)); 
            } 

            // Clear out the IsClosed flag, then set it as appropriate. 
            _currentPathFigureData.Flags &= ~MilPathFigureFlags.IsClosed;
            _currentPathFigureData.Flags |= isClosed ? MilPathFigureFlags.IsClosed : 0;
        }
 
        #endregion Internal Methods
 
        #region Private Methods 

        ///  
        /// This verifies that the API can be called at this time.
        /// 
        private void VerifyApi()
        { 
            VerifyAccess();
 
            if (_disposed) 
            {
                throw new ObjectDisposedException("ByteStreamGeometryContext"); 
            }
        }

        ///  
        /// CloseCore - This method is implemented by derived classes to hand off the content
        /// to its eventual destination. 
        ///  
        protected virtual void CloseCore(byte[] geometryData) {}
 
        /// 
        /// This is the same as the Close call:
        /// Closes the Context and flushes the content.
        /// Afterwards the Context can not be used anymore. 
        /// This call does not require all Push calls to have been Popped.
        ///  
        ///  
        /// This call is illegal if this object has already been closed or disposed.
        ///  
        /// 
        /// Critical - it has an unsafe block
        /// TreatAsSafe - manipulating a buffer is considered safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal override void DisposeCore() 
        { 
            if (!_disposed)
            { 
                FinishFigure();

                unsafe
                { 
                    // We have to have at least this much data already in the stream
                    checked 
                    { 
                        Debug.Assert(sizeof(MIL_PATHGEOMETRY) <= _currOffset);
                        Debug.Assert(_currentPathGeometryData.Size == (uint)_currOffset); 
                    }

                    fixed (MIL_PATHGEOMETRY* pCurrentPathGeometryData = &_currentPathGeometryData)
                    { 
                        OverwriteData((byte *)pCurrentPathGeometryData, 0, sizeof(MIL_PATHGEOMETRY));
                    } 
                } 

                ShrinkToFit(); 

                CloseCore(_chunkList[0]);

                _disposed = true; 
            }
        } 
 
/// 
        /// ReadData - reads data from a specified location in the buffer 
        /// 
        /// 
        ///   byte* pointing to at least cbDataSize bytes into which will be copied the desired data
        ///  
        ///  int - the offset, in bytes, of the requested data. Must be >= 0. 
        ///  int - the size, in bytes, of the requested data. Must be >= 0.  
        ///  
        ///     Critical: This code has unsafe code and dereferences a pointer
        ///  
        [SecurityCritical]
        private unsafe void ReadData(byte* pbData,
                                      int bufferOffset,
                                      int cbDataSize) 
        {
            Invariant.Assert(cbDataSize >= 0); 
            Invariant.Assert(bufferOffset >= 0); 

            // 
            //


 
            checked
            { 
                Invariant.Assert(_currOffset >= bufferOffset+cbDataSize); 
            }
 
            ReadWriteData(true /* reading */, pbData, cbDataSize, 0, ref bufferOffset);
        }

        ///  
        /// OverwriteData - overwrite data in the buffer.
        ///  
        ///  
        ///   byte* pointing to at least cbDataSize bytes which will be copied to the stream.
        ///  
        ///  int - the offset, in bytes, at which the data should be writen. Must be >= 0. 
        ///  int - the size, in bytes, of pbData. Must be >= 0. 
        /// 
        ///     Critical: This code has unsafe code and dereferences a pointer 
        /// 
        [SecurityCritical] 
        private unsafe void OverwriteData(byte* pbData, 
                                      int bufferOffset,
                                      int cbDataSize) 
        {
            Invariant.Assert(cbDataSize >= 0);

            checked 
            {
                int newOffset = bufferOffset + cbDataSize; 
 
                Invariant.Assert(newOffset <= _currOffset);
            } 

            ReadWriteData(false /* writing */, pbData, cbDataSize, 0, ref bufferOffset);
        }
 
        /// 
        /// AppendData - append data to the buffer. 
        ///  
        /// 
        ///   byte* pointing to at least cbDataSize bytes which will be copied to the stream. 
        /// 
        ///  int - the size, in bytes, of pbData. Must be >= 0. 
        /// 
        ///     Critical: This code has unsafe code and dereferences a pointer 
        /// 
        [SecurityCritical] 
        private unsafe void AppendData(byte* pbData, 
                                      int cbDataSize)
        { 
            Invariant.Assert(cbDataSize >= 0);

            int newOffset;
 
            checked
            { 
                newOffset = _currOffset + cbDataSize; 
            }
 
            if (_chunkList.Count == 0)
            {
                _chunkList.Add(new byte[c_defaultChunkSize]);
            } 

            ReadWriteData(false /* writing */, pbData, cbDataSize, _chunkList.Count-1, ref _currChunkOffset); 
 
            _currOffset = newOffset;
        } 

        /// 
        /// ShrinkToFit - Shrink the data to fit in exactly one chunk
        ///  
        /// 
        ///     Critical: This code has unsafe code and dereferences a pointer 
        ///     TreatAsSafe - manipulating a buffer is considered safe 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal void ShrinkToFit()
        {
            Debug.Assert(_chunkList.Count != 0);
 
            if (_chunkList.Count > 1 ||
                _chunkList[0].Length != _currOffset) 
            { 
                byte [] buffer = new byte[_currOffset];
 
                unsafe
                {
                    fixed (byte *pbData = buffer)
                    { 
                        ReadData(pbData, 0, _currOffset);
                    } 
 
                    _chunkList = new FrugalStructList();
                    _chunkList.Add(buffer); 
                }
            }
        }
 
        /// 
        /// ReadWriteData - read from/write to buffer. 
        ///  
        ///  bool - is the buffer read from or written to?
        ///  
        ///   byte* pointing to at least cbDataSize bytes which will be copied to/from the stream.
        /// 
        ///  int - the size, in bytes, of pbData. Must be >= 0. 
        ///  the current chunk to start writing to/reading from  
        ///  in/out: the current position in the current chunk. 
        ///  
        ///     Critical: This code has unsafe code and dereferences a pointer 
        /// 
        [SecurityCritical] 
        private unsafe void ReadWriteData(bool reading,
                                          byte* pbData,
                                          int cbDataSize,
                                          int currentChunk, 
                                          ref int bufferOffset)
        { 
            Invariant.Assert(cbDataSize >= 0); 

            // Skip past irrelevant chunks 
            while (bufferOffset > _chunkList[currentChunk].Length)
            {
                bufferOffset -= _chunkList[currentChunk].Length;
                currentChunk++; 
            }
 
            // Arithmetic should be checked by the caller (AppendData or OverwriteData) 

            while (cbDataSize > 0) 
            {
                int cbDataForThisChunk = Math.Min(cbDataSize,
                    _chunkList[currentChunk].Length - bufferOffset);
 
                if (cbDataForThisChunk > 0)
                { 
                    // At this point, _buffer must be non-null and 
                    // _buffer.Length must be >= newOffset
                    Invariant.Assert((_chunkList[currentChunk] != null) 
                        && (_chunkList[currentChunk].Length >= bufferOffset + cbDataForThisChunk));

                    // Also, because pinning a 0-length buffer fails, we assert this too.
                    Invariant.Assert(_chunkList[currentChunk].Length > 0); 

                    if (reading) 
                    { 
                        Marshal.Copy(_chunkList[currentChunk], bufferOffset, (IntPtr)pbData, cbDataForThisChunk);
                    } 
                    else
                    {
                        Marshal.Copy((IntPtr)pbData, _chunkList[currentChunk], bufferOffset, cbDataForThisChunk);
                    } 

                    cbDataSize -= cbDataForThisChunk; 
                    pbData += cbDataForThisChunk; 
                    bufferOffset += cbDataForThisChunk;
                } 

                if (cbDataSize > 0)
                {
                    checked {currentChunk++;} 

                    if (_chunkList.Count == currentChunk) 
                    { 
                        Invariant.Assert(!reading);
 
                        // Exponential growth early on. Later, linear growth.
                        int newChunkSize = Math.Min(2*_chunkList[_chunkList.Count-1].Length, c_maxChunkSize);

                        _chunkList.Add(new byte[newChunkSize]); 
                    }
 
                    bufferOffset = 0; 
                }
            } 
        }

        /// 
        /// FinishFigure - called to completed any outstanding Figure which may be present. 
        /// If there is one, we write its data into the stream at the appropriate offset
        /// and update the path's flags/size/figure count/etc based on this Figure. 
        /// After this call, a new figure needs to be started for any segment-building APIs 
        /// to be legal.
        ///  
        /// 
        /// Critical - it has an unsafe block
        /// TreatAsSafe - manipulating a buffer is considered safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void FinishFigure() 
        { 
            if (_currentPathFigureDataOffset != -1)
            { 
                FinishSegment();

                unsafe
                { 
                    // We have to have at least this much data already in the stream
                    checked 
                    { 
                        Debug.Assert(_currentPathFigureDataOffset + sizeof(MIL_PATHFIGURE) <= _currOffset);
                    } 

                    fixed (MIL_PATHFIGURE* pCurrentPathFigureData = &_currentPathFigureData)
                    {
                        OverwriteData((byte *)pCurrentPathFigureData, _currentPathFigureDataOffset, sizeof(MIL_PATHFIGURE)); 
                    }
                } 
 
                _currentPathGeometryData.Flags |= ((_currentPathFigureData.Flags & MilPathFigureFlags.HasCurves) != 0) ? MilPathGeometryFlags.HasCurves : 0;
                _currentPathGeometryData.Flags |= ((_currentPathFigureData.Flags & MilPathFigureFlags.HasGaps) != 0) ? MilPathGeometryFlags.HasGaps : 0; 
                _currentPathGeometryData.Flags |= ((_currentPathFigureData.Flags & MilPathFigureFlags.IsFillable) == 0) ? MilPathGeometryFlags.HasHollows : 0;
                _currentPathGeometryData.FigureCount++;
                _currentPathGeometryData.Size = (UInt32)(_currOffset);
 
                _lastFigureSize = _currentPathFigureData.Size;
 
                // Initialize _currentPathFigureData (this really just 0's out the memory) 
                _currentPathFigureDataOffset = -1;
                _currentPathFigureData = new MIL_PATHFIGURE(); 

                // We must also clear _lastSegmentSize, since there is now no "last segment"
                _lastSegmentSize = 0;
            } 
        }
 
        ///  
        /// FinishSegment - called to completed any outstanding Segment which may be present.
        /// If there is one, we write its data into the stream at the appropriate offset 
        /// and update the figure's flags/size/segment count/etc based on this Segment.
        /// 
        /// 
        /// Critical - it has an unsafe block 
        /// TreatAsSafe - manipulating a buffer is considered safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private void FinishSegment()
        { 
            if (_currentPolySegmentDataOffset != -1)
            {
                unsafe
                { 
                    // We have to have at least this much data already in the stream
                    checked 
                    { 
                        Debug.Assert(_currentPolySegmentDataOffset + sizeof(MIL_SEGMENT_POLY) <= _currOffset);
                    } 

                    fixed (MIL_SEGMENT_POLY* pCurrentPolySegmentData = &_currentPolySegmentData)
                    {
                        OverwriteData((byte *)pCurrentPolySegmentData, _currentPolySegmentDataOffset, sizeof(MIL_SEGMENT_POLY)); 
                    }
 
                    _lastSegmentSize = (UInt32)(sizeof(MIL_SEGMENT_POLY) + (sizeof(Point) * _currentPolySegmentData.Count)); 
                }
 
                // Update the current path figure data
                if ((_currentPolySegmentData.Flags & MILCoreSegFlags.SegIsAGap) != 0)
                {
                    _currentPathFigureData.Flags |= MilPathFigureFlags.HasGaps; 
                }
 
                if ((_currentPolySegmentData.Flags & MILCoreSegFlags.SegIsCurved) != 0) 
                {
                    _currentPathFigureData.Flags |= MilPathFigureFlags.HasCurves; 
                }

                _currentPathFigureData.Count++;
 
                // Always keep the OffsetToLastSegment and Size accurate
                _currentPathFigureData.Size = (UInt32)(_currOffset - _currentPathFigureDataOffset); 
 
                _currentPathFigureData.OffsetToLastSegment =
                    (UInt32)(_currentPolySegmentDataOffset - _currentPathFigureDataOffset); 

                // Initialize _currentPolySegmentData (this really just 0's out the memory)
                _currentPolySegmentDataOffset = -1;
                _currentPolySegmentData = new MIL_SEGMENT_POLY(); 
            }
        } 
 
        /// 
        /// Critical - it has an unsafe block 
        /// TreatAsSafe - manipulating a buffer is considered safe
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void GenericPolyTo(IList points, 
                                   bool isStroked,
                                   bool isSmoothJoin, 
                                   bool hasCurves, 
                                   int pointCountMultiple,
                                   MIL_SEGMENT_TYPE segmentType) 
        {
            if (_currentPathFigureDataOffset == -1)
            {
                throw new InvalidOperationException(SR.Get(SRID.StreamGeometry_NeedBeginFigure)); 
            }
 
            if (points == null) 
            {
                return; 
            }

            int count = points.Count;
            count -= count % pointCountMultiple; 

            if (count <= 0) 
            { 
                return;
            } 

            // Do we need to finish the old segment?
            // Yes, if there is an old segment and if its type or flags are different from
            // the new segment. 
            if ( (_currentPolySegmentDataOffset != -1) &&
                 ( 
                   (_currentPolySegmentData.Type != segmentType) || 
                   ( ((_currentPolySegmentData.Flags & MILCoreSegFlags.SegIsAGap) == 0) != isStroked ) ||
                   ( ((_currentPolySegmentData.Flags & MILCoreSegFlags.SegSmoothJoin) != 0) != isSmoothJoin ) 
                 )
               )
            {
                FinishSegment(); 
            }
 
            // Do we need to start a new segment? 
            if (_currentPolySegmentDataOffset == -1)
            { 
                MIL_SEGMENT_POLY tempSegment;
                int oldOffset = _currOffset;

                unsafe 
                {
                    AppendData((byte*)&tempSegment, sizeof(MIL_SEGMENT_POLY)); 
                } 

                _currentPolySegmentDataOffset = oldOffset; 
                _currentPolySegmentData.Type = segmentType;
                _currentPolySegmentData.Flags |= isStroked ? 0 : MILCoreSegFlags.SegIsAGap;
                _currentPolySegmentData.Flags |= hasCurves ? MILCoreSegFlags.SegIsCurved : 0;
                _currentPolySegmentData.Flags |= isSmoothJoin ? MILCoreSegFlags.SegSmoothJoin : 0; 
                _currentPolySegmentData.BackSize = _lastSegmentSize;
            } 
 
            // Assert that everything is ready to go
            Debug.Assert((_currentPolySegmentDataOffset != -1) && 
                         (_currentPolySegmentData.Type == segmentType) &&
                         (((_currentPolySegmentData.Flags & MILCoreSegFlags.SegIsAGap) == 0) == isStroked) &&
                         (((_currentPolySegmentData.Flags & MILCoreSegFlags.SegSmoothJoin) != 0) == isSmoothJoin));
 
            for (int i = 0; i < count; i++)
            { 
                Point p = points[i]; 

                unsafe 
                {
                    AppendData((byte*)&p, sizeof(Point));
                }
 
                _currentPolySegmentData.Count++;
            } 
        } 

        #endregion Private Methods 

        #region Fields

        private bool _disposed; 
        private int _currChunkOffset;
        FrugalStructList _chunkList; 
        private int _currOffset; 
        private MIL_PATHGEOMETRY _currentPathGeometryData;
        private MIL_PATHFIGURE _currentPathFigureData; 
        private int _currentPathFigureDataOffset = -1;
        private MIL_SEGMENT_POLY _currentPolySegmentData;
        private int _currentPolySegmentDataOffset = -1;
        private UInt32 _lastSegmentSize = 0; 
        private UInt32 _lastFigureSize = 0;
        private Point[] _scratchForLine = new Point[1]; 
        private Point[] _scratchForQuadraticBezier = new Point[2]; 
        private Point[] _scratchForBezier = new Point[3];
 
        private const int c_defaultChunkSize = 2*1024;
        private const int c_maxChunkSize = 1024*1024;

        #endregion Fields 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// This class is used by the StreamGeometry class to generate an inlined, 
// flattened geometry stream. 
//
//--------------------------------------------------------------------------- 

using MS.Utility;
using MS.Internal;
using MS.Internal.PresentationCore; 
using System;
using System.Collections; 
using System.Collections.Generic; 
using System.Runtime.InteropServices;
using System.Windows.Threading; 
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Composition; 
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging; 
using System.Windows.Media.Media3D; 
using System.Diagnostics;
using SR=MS.Internal.PresentationCore.SR; 
using SRID=MS.Internal.PresentationCore.SRID;
using System.Security;
using System.Security.Permissions;
 
namespace System.Windows.Media
{ 
    ///  
    ///     ByteStreamGeometryContext
    ///  
    internal class ByteStreamGeometryContext : CapacityStreamGeometryContext
    {
        #region Constructors
 
        /// 
        /// Creates a geometry stream context. 
        ///  
        /// 
        /// Critical - it has an unsafe block 
        /// TreatAsSafe - manipulating a buffer is considered safe
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal ByteStreamGeometryContext() 
        {
            // For now, we just write this into the stream.  We'll update its fields as we go. 
            MIL_PATHGEOMETRY tempPath = new MIL_PATHGEOMETRY(); 

            unsafe 
            {
                AppendData((byte*)&tempPath, sizeof(MIL_PATHGEOMETRY));

                // Initialize the size to include the MIL_PATHGEOMETRY itself 
                // All other fields are intentionally left as 0;
                _currentPathGeometryData.Size = (uint)sizeof(MIL_PATHGEOMETRY); 
            } 
        }
 
        #endregion Constructors

        #region Public Methods
 
        /// 
        /// Closes the StreamContext and flushes the content. 
        /// Afterwards the StreamContext can not be used anymore. 
        /// This call does not require all Push calls to have been Popped.
        ///  
        /// 
        /// This call is illegal if this object has already been closed or disposed.
        /// 
        public override void Close() 
        {
            VerifyApi(); 
            ((IDisposable)this).Dispose(); 
        }
 
        /// 
        /// BeginFigure - Start a new figure.
        /// 
        ///  
        /// Critical - it has an unsafe block
        /// PublicOK - This function takes the address of a stack variable. 
        ///  
        [SecurityCritical]
        public override void BeginFigure(Point startPoint, bool isFilled, bool isClosed) 
        {
            VerifyApi();

            // Don't forget to close out the previous segment/figure 
            FinishFigure();
 
            // Remember the location - we set this only after successful allocation in case it throws 
            // and we're re-entered.
            int oldOffset = _currOffset; 

            MIL_PATHFIGURE tempFigure;

            unsafe 
            {
                AppendData((byte*)&tempFigure, sizeof(MIL_PATHFIGURE)); 
            } 

            _currentPathFigureDataOffset = oldOffset; 
            _currentPathFigureData.StartPoint = startPoint;
            _currentPathFigureData.Flags |= isFilled ? MilPathFigureFlags.IsFillable : 0;
            _currentPathFigureData.Flags |= isClosed ? MilPathFigureFlags.IsClosed : 0;
            _currentPathFigureData.BackSize = _lastFigureSize; 
            _currentPathFigureData.Size = (UInt32)(_currOffset - _currentPathFigureDataOffset);
        } 
 
        /// 
        /// LineTo - append a LineTo to the current figure. 
        /// 
        public override void LineTo(Point point, bool isStroked, bool isSmoothJoin)
        {
            VerifyApi(); 

            _scratchForLine[0] = point; 
            GenericPolyTo(_scratchForLine, 
                          isStroked,
                          isSmoothJoin, 
                          false /* does not have curves */,
                          1 /* pointCountMultiple */,
                          MIL_SEGMENT_TYPE.MilSegmentPolyLine);
        } 

        ///  
        /// QuadraticBezierTo - append a QuadraticBezierTo to the current figure. 
        /// 
        public override void QuadraticBezierTo(Point point1, Point point2, bool isStroked, bool isSmoothJoin) 
        {
            VerifyApi();

            _scratchForQuadraticBezier[0] = point1; 
            _scratchForQuadraticBezier[1] = point2;
            GenericPolyTo(_scratchForQuadraticBezier, 
                          isStroked, 
                          isSmoothJoin,
                          true /* has curves */, 
                          2 /* pointCountMultiple */,
                          MIL_SEGMENT_TYPE.MilSegmentPolyQuadraticBezier);
        }
 
        /// 
        /// BezierTo - apply a BezierTo to the current figure. 
        ///  
        public override void BezierTo(Point point1, Point point2, Point point3, bool isStroked, bool isSmoothJoin)
        { 
            VerifyApi();

            _scratchForBezier[0] = point1;
            _scratchForBezier[1] = point2; 
            _scratchForBezier[2] = point3;
            GenericPolyTo(_scratchForBezier, 
                          isStroked, 
                          isSmoothJoin,
                          true /* has curves */, 
                          3 /* pointCountMultiple */,
                          MIL_SEGMENT_TYPE.MilSegmentPolyBezier);
        }
 
        /// 
        /// PolyLineTo - append a PolyLineTo to the current figure. 
        ///  
        public override void PolyLineTo(IList points, bool isStroked, bool isSmoothJoin)
        { 
            VerifyApi();

            GenericPolyTo(points,
                          isStroked, 
                          isSmoothJoin,
                          false /* does not have curves */, 
                          1 /* pointCountMultiple */, 
                          MIL_SEGMENT_TYPE.MilSegmentPolyLine);
        } 

        /// 
        /// PolyQuadraticBezierTo - append a PolyQuadraticBezierTo to the current figure.
        ///  
        public override void PolyQuadraticBezierTo(IList points, bool isStroked, bool isSmoothJoin)
        { 
            VerifyApi(); 

            GenericPolyTo(points, 
                          isStroked,
                          isSmoothJoin,
                          true /* has curves */,
                          2 /* pointCountMultiple */, 
                          MIL_SEGMENT_TYPE.MilSegmentPolyQuadraticBezier);
        } 
 
        /// 
        /// PolyBezierTo - append a PolyBezierTo to the current figure. 
        /// 
        public override void PolyBezierTo(IList points, bool isStroked, bool isSmoothJoin)
        {
            VerifyApi(); 

            GenericPolyTo(points, 
                          isStroked, 
                          isSmoothJoin,
                          true /* has curves */, 
                          3 /* pointCountMultiple */,
                          MIL_SEGMENT_TYPE.MilSegmentPolyBezier);
        }
 
        /// 
        /// ArcTo - append an ArcTo to the current figure. 
        ///  
        /// 
        /// Critical - it has an unsafe block 
        /// PublicOk - This function takes the address of a stack variable.
        /// 
        [SecurityCritical]
        public override void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection, bool isStroked, bool isSmoothJoin) 
        {
            VerifyApi(); 
 
            if (_currentPathFigureDataOffset == -1)
            { 
                throw new InvalidOperationException(SR.Get(SRID.StreamGeometry_NeedBeginFigure));
            }

            FinishSegment(); 

            MIL_SEGMENT_ARC arcToSegment = new MIL_SEGMENT_ARC(); 
            arcToSegment.Type = MIL_SEGMENT_TYPE.MilSegmentArc; 

            arcToSegment.Flags |= isStroked ? 0 : MILCoreSegFlags.SegIsAGap; 
            arcToSegment.Flags |= isSmoothJoin ? MILCoreSegFlags.SegSmoothJoin : 0;
            arcToSegment.Flags |= MILCoreSegFlags.SegIsCurved;
            arcToSegment.BackSize = _lastSegmentSize;
 
            arcToSegment.Point = point;
            arcToSegment.Size = size; 
            arcToSegment.XRotation = rotationAngle; 
            arcToSegment.LargeArc = (uint)(isLargeArc ? 1 : 0);
            arcToSegment.Sweep = (uint)(sweepDirection == SweepDirection.Clockwise ? 1 : 0); 

            int offsetToArcToSegment = _currOffset;

            unsafe 
            {
                AppendData((byte*)(&arcToSegment), sizeof(MIL_SEGMENT_ARC)); 
                _lastSegmentSize = (UInt32)sizeof(MIL_SEGMENT_ARC); 
            }
 
            // Update the current path figure data
            _currentPathFigureData.Flags |= isStroked ? 0 : MilPathFigureFlags.HasGaps;

            _currentPathFigureData.Flags |= MilPathFigureFlags.HasCurves; 

            _currentPathFigureData.Count++; 
 
            // Always keep the OffsetToLastSegment and Size accurate
            _currentPathFigureData.Size = (UInt32)(_currOffset - _currentPathFigureDataOffset); 

            _currentPathFigureData.OffsetToLastSegment =
                (UInt32)(offsetToArcToSegment - _currentPathFigureDataOffset);
        } 

        #endregion Public Methods 
 
        #region Internal Methods
 
        /// 
        /// GetData - Retrieves the data stream built by this Context.
        /// 
        internal byte[] GetData() 
        {
            ShrinkToFit(); 
 
            return _chunkList[0];
        } 

        override internal void SetClosedState(bool isClosed)
        {
            if (_currentPathFigureDataOffset == -1) 
            {
                throw new InvalidOperationException(SR.Get(SRID.StreamGeometry_NeedBeginFigure)); 
            } 

            // Clear out the IsClosed flag, then set it as appropriate. 
            _currentPathFigureData.Flags &= ~MilPathFigureFlags.IsClosed;
            _currentPathFigureData.Flags |= isClosed ? MilPathFigureFlags.IsClosed : 0;
        }
 
        #endregion Internal Methods
 
        #region Private Methods 

        ///  
        /// This verifies that the API can be called at this time.
        /// 
        private void VerifyApi()
        { 
            VerifyAccess();
 
            if (_disposed) 
            {
                throw new ObjectDisposedException("ByteStreamGeometryContext"); 
            }
        }

        ///  
        /// CloseCore - This method is implemented by derived classes to hand off the content
        /// to its eventual destination. 
        ///  
        protected virtual void CloseCore(byte[] geometryData) {}
 
        /// 
        /// This is the same as the Close call:
        /// Closes the Context and flushes the content.
        /// Afterwards the Context can not be used anymore. 
        /// This call does not require all Push calls to have been Popped.
        ///  
        ///  
        /// This call is illegal if this object has already been closed or disposed.
        ///  
        /// 
        /// Critical - it has an unsafe block
        /// TreatAsSafe - manipulating a buffer is considered safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal override void DisposeCore() 
        { 
            if (!_disposed)
            { 
                FinishFigure();

                unsafe
                { 
                    // We have to have at least this much data already in the stream
                    checked 
                    { 
                        Debug.Assert(sizeof(MIL_PATHGEOMETRY) <= _currOffset);
                        Debug.Assert(_currentPathGeometryData.Size == (uint)_currOffset); 
                    }

                    fixed (MIL_PATHGEOMETRY* pCurrentPathGeometryData = &_currentPathGeometryData)
                    { 
                        OverwriteData((byte *)pCurrentPathGeometryData, 0, sizeof(MIL_PATHGEOMETRY));
                    } 
                } 

                ShrinkToFit(); 

                CloseCore(_chunkList[0]);

                _disposed = true; 
            }
        } 
 
/// 
        /// ReadData - reads data from a specified location in the buffer 
        /// 
        /// 
        ///   byte* pointing to at least cbDataSize bytes into which will be copied the desired data
        ///  
        ///  int - the offset, in bytes, of the requested data. Must be >= 0. 
        ///  int - the size, in bytes, of the requested data. Must be >= 0.  
        ///  
        ///     Critical: This code has unsafe code and dereferences a pointer
        ///  
        [SecurityCritical]
        private unsafe void ReadData(byte* pbData,
                                      int bufferOffset,
                                      int cbDataSize) 
        {
            Invariant.Assert(cbDataSize >= 0); 
            Invariant.Assert(bufferOffset >= 0); 

            // 
            //


 
            checked
            { 
                Invariant.Assert(_currOffset >= bufferOffset+cbDataSize); 
            }
 
            ReadWriteData(true /* reading */, pbData, cbDataSize, 0, ref bufferOffset);
        }

        ///  
        /// OverwriteData - overwrite data in the buffer.
        ///  
        ///  
        ///   byte* pointing to at least cbDataSize bytes which will be copied to the stream.
        ///  
        ///  int - the offset, in bytes, at which the data should be writen. Must be >= 0. 
        ///  int - the size, in bytes, of pbData. Must be >= 0. 
        /// 
        ///     Critical: This code has unsafe code and dereferences a pointer 
        /// 
        [SecurityCritical] 
        private unsafe void OverwriteData(byte* pbData, 
                                      int bufferOffset,
                                      int cbDataSize) 
        {
            Invariant.Assert(cbDataSize >= 0);

            checked 
            {
                int newOffset = bufferOffset + cbDataSize; 
 
                Invariant.Assert(newOffset <= _currOffset);
            } 

            ReadWriteData(false /* writing */, pbData, cbDataSize, 0, ref bufferOffset);
        }
 
        /// 
        /// AppendData - append data to the buffer. 
        ///  
        /// 
        ///   byte* pointing to at least cbDataSize bytes which will be copied to the stream. 
        /// 
        ///  int - the size, in bytes, of pbData. Must be >= 0. 
        /// 
        ///     Critical: This code has unsafe code and dereferences a pointer 
        /// 
        [SecurityCritical] 
        private unsafe void AppendData(byte* pbData, 
                                      int cbDataSize)
        { 
            Invariant.Assert(cbDataSize >= 0);

            int newOffset;
 
            checked
            { 
                newOffset = _currOffset + cbDataSize; 
            }
 
            if (_chunkList.Count == 0)
            {
                _chunkList.Add(new byte[c_defaultChunkSize]);
            } 

            ReadWriteData(false /* writing */, pbData, cbDataSize, _chunkList.Count-1, ref _currChunkOffset); 
 
            _currOffset = newOffset;
        } 

        /// 
        /// ShrinkToFit - Shrink the data to fit in exactly one chunk
        ///  
        /// 
        ///     Critical: This code has unsafe code and dereferences a pointer 
        ///     TreatAsSafe - manipulating a buffer is considered safe 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal void ShrinkToFit()
        {
            Debug.Assert(_chunkList.Count != 0);
 
            if (_chunkList.Count > 1 ||
                _chunkList[0].Length != _currOffset) 
            { 
                byte [] buffer = new byte[_currOffset];
 
                unsafe
                {
                    fixed (byte *pbData = buffer)
                    { 
                        ReadData(pbData, 0, _currOffset);
                    } 
 
                    _chunkList = new FrugalStructList();
                    _chunkList.Add(buffer); 
                }
            }
        }
 
        /// 
        /// ReadWriteData - read from/write to buffer. 
        ///  
        ///  bool - is the buffer read from or written to?
        ///  
        ///   byte* pointing to at least cbDataSize bytes which will be copied to/from the stream.
        /// 
        ///  int - the size, in bytes, of pbData. Must be >= 0. 
        ///  the current chunk to start writing to/reading from  
        ///  in/out: the current position in the current chunk. 
        ///  
        ///     Critical: This code has unsafe code and dereferences a pointer 
        /// 
        [SecurityCritical] 
        private unsafe void ReadWriteData(bool reading,
                                          byte* pbData,
                                          int cbDataSize,
                                          int currentChunk, 
                                          ref int bufferOffset)
        { 
            Invariant.Assert(cbDataSize >= 0); 

            // Skip past irrelevant chunks 
            while (bufferOffset > _chunkList[currentChunk].Length)
            {
                bufferOffset -= _chunkList[currentChunk].Length;
                currentChunk++; 
            }
 
            // Arithmetic should be checked by the caller (AppendData or OverwriteData) 

            while (cbDataSize > 0) 
            {
                int cbDataForThisChunk = Math.Min(cbDataSize,
                    _chunkList[currentChunk].Length - bufferOffset);
 
                if (cbDataForThisChunk > 0)
                { 
                    // At this point, _buffer must be non-null and 
                    // _buffer.Length must be >= newOffset
                    Invariant.Assert((_chunkList[currentChunk] != null) 
                        && (_chunkList[currentChunk].Length >= bufferOffset + cbDataForThisChunk));

                    // Also, because pinning a 0-length buffer fails, we assert this too.
                    Invariant.Assert(_chunkList[currentChunk].Length > 0); 

                    if (reading) 
                    { 
                        Marshal.Copy(_chunkList[currentChunk], bufferOffset, (IntPtr)pbData, cbDataForThisChunk);
                    } 
                    else
                    {
                        Marshal.Copy((IntPtr)pbData, _chunkList[currentChunk], bufferOffset, cbDataForThisChunk);
                    } 

                    cbDataSize -= cbDataForThisChunk; 
                    pbData += cbDataForThisChunk; 
                    bufferOffset += cbDataForThisChunk;
                } 

                if (cbDataSize > 0)
                {
                    checked {currentChunk++;} 

                    if (_chunkList.Count == currentChunk) 
                    { 
                        Invariant.Assert(!reading);
 
                        // Exponential growth early on. Later, linear growth.
                        int newChunkSize = Math.Min(2*_chunkList[_chunkList.Count-1].Length, c_maxChunkSize);

                        _chunkList.Add(new byte[newChunkSize]); 
                    }
 
                    bufferOffset = 0; 
                }
            } 
        }

        /// 
        /// FinishFigure - called to completed any outstanding Figure which may be present. 
        /// If there is one, we write its data into the stream at the appropriate offset
        /// and update the path's flags/size/figure count/etc based on this Figure. 
        /// After this call, a new figure needs to be started for any segment-building APIs 
        /// to be legal.
        ///  
        /// 
        /// Critical - it has an unsafe block
        /// TreatAsSafe - manipulating a buffer is considered safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void FinishFigure() 
        { 
            if (_currentPathFigureDataOffset != -1)
            { 
                FinishSegment();

                unsafe
                { 
                    // We have to have at least this much data already in the stream
                    checked 
                    { 
                        Debug.Assert(_currentPathFigureDataOffset + sizeof(MIL_PATHFIGURE) <= _currOffset);
                    } 

                    fixed (MIL_PATHFIGURE* pCurrentPathFigureData = &_currentPathFigureData)
                    {
                        OverwriteData((byte *)pCurrentPathFigureData, _currentPathFigureDataOffset, sizeof(MIL_PATHFIGURE)); 
                    }
                } 
 
                _currentPathGeometryData.Flags |= ((_currentPathFigureData.Flags & MilPathFigureFlags.HasCurves) != 0) ? MilPathGeometryFlags.HasCurves : 0;
                _currentPathGeometryData.Flags |= ((_currentPathFigureData.Flags & MilPathFigureFlags.HasGaps) != 0) ? MilPathGeometryFlags.HasGaps : 0; 
                _currentPathGeometryData.Flags |= ((_currentPathFigureData.Flags & MilPathFigureFlags.IsFillable) == 0) ? MilPathGeometryFlags.HasHollows : 0;
                _currentPathGeometryData.FigureCount++;
                _currentPathGeometryData.Size = (UInt32)(_currOffset);
 
                _lastFigureSize = _currentPathFigureData.Size;
 
                // Initialize _currentPathFigureData (this really just 0's out the memory) 
                _currentPathFigureDataOffset = -1;
                _currentPathFigureData = new MIL_PATHFIGURE(); 

                // We must also clear _lastSegmentSize, since there is now no "last segment"
                _lastSegmentSize = 0;
            } 
        }
 
        ///  
        /// FinishSegment - called to completed any outstanding Segment which may be present.
        /// If there is one, we write its data into the stream at the appropriate offset 
        /// and update the figure's flags/size/segment count/etc based on this Segment.
        /// 
        /// 
        /// Critical - it has an unsafe block 
        /// TreatAsSafe - manipulating a buffer is considered safe
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private void FinishSegment()
        { 
            if (_currentPolySegmentDataOffset != -1)
            {
                unsafe
                { 
                    // We have to have at least this much data already in the stream
                    checked 
                    { 
                        Debug.Assert(_currentPolySegmentDataOffset + sizeof(MIL_SEGMENT_POLY) <= _currOffset);
                    } 

                    fixed (MIL_SEGMENT_POLY* pCurrentPolySegmentData = &_currentPolySegmentData)
                    {
                        OverwriteData((byte *)pCurrentPolySegmentData, _currentPolySegmentDataOffset, sizeof(MIL_SEGMENT_POLY)); 
                    }
 
                    _lastSegmentSize = (UInt32)(sizeof(MIL_SEGMENT_POLY) + (sizeof(Point) * _currentPolySegmentData.Count)); 
                }
 
                // Update the current path figure data
                if ((_currentPolySegmentData.Flags & MILCoreSegFlags.SegIsAGap) != 0)
                {
                    _currentPathFigureData.Flags |= MilPathFigureFlags.HasGaps; 
                }
 
                if ((_currentPolySegmentData.Flags & MILCoreSegFlags.SegIsCurved) != 0) 
                {
                    _currentPathFigureData.Flags |= MilPathFigureFlags.HasCurves; 
                }

                _currentPathFigureData.Count++;
 
                // Always keep the OffsetToLastSegment and Size accurate
                _currentPathFigureData.Size = (UInt32)(_currOffset - _currentPathFigureDataOffset); 
 
                _currentPathFigureData.OffsetToLastSegment =
                    (UInt32)(_currentPolySegmentDataOffset - _currentPathFigureDataOffset); 

                // Initialize _currentPolySegmentData (this really just 0's out the memory)
                _currentPolySegmentDataOffset = -1;
                _currentPolySegmentData = new MIL_SEGMENT_POLY(); 
            }
        } 
 
        /// 
        /// Critical - it has an unsafe block 
        /// TreatAsSafe - manipulating a buffer is considered safe
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void GenericPolyTo(IList points, 
                                   bool isStroked,
                                   bool isSmoothJoin, 
                                   bool hasCurves, 
                                   int pointCountMultiple,
                                   MIL_SEGMENT_TYPE segmentType) 
        {
            if (_currentPathFigureDataOffset == -1)
            {
                throw new InvalidOperationException(SR.Get(SRID.StreamGeometry_NeedBeginFigure)); 
            }
 
            if (points == null) 
            {
                return; 
            }

            int count = points.Count;
            count -= count % pointCountMultiple; 

            if (count <= 0) 
            { 
                return;
            } 

            // Do we need to finish the old segment?
            // Yes, if there is an old segment and if its type or flags are different from
            // the new segment. 
            if ( (_currentPolySegmentDataOffset != -1) &&
                 ( 
                   (_currentPolySegmentData.Type != segmentType) || 
                   ( ((_currentPolySegmentData.Flags & MILCoreSegFlags.SegIsAGap) == 0) != isStroked ) ||
                   ( ((_currentPolySegmentData.Flags & MILCoreSegFlags.SegSmoothJoin) != 0) != isSmoothJoin ) 
                 )
               )
            {
                FinishSegment(); 
            }
 
            // Do we need to start a new segment? 
            if (_currentPolySegmentDataOffset == -1)
            { 
                MIL_SEGMENT_POLY tempSegment;
                int oldOffset = _currOffset;

                unsafe 
                {
                    AppendData((byte*)&tempSegment, sizeof(MIL_SEGMENT_POLY)); 
                } 

                _currentPolySegmentDataOffset = oldOffset; 
                _currentPolySegmentData.Type = segmentType;
                _currentPolySegmentData.Flags |= isStroked ? 0 : MILCoreSegFlags.SegIsAGap;
                _currentPolySegmentData.Flags |= hasCurves ? MILCoreSegFlags.SegIsCurved : 0;
                _currentPolySegmentData.Flags |= isSmoothJoin ? MILCoreSegFlags.SegSmoothJoin : 0; 
                _currentPolySegmentData.BackSize = _lastSegmentSize;
            } 
 
            // Assert that everything is ready to go
            Debug.Assert((_currentPolySegmentDataOffset != -1) && 
                         (_currentPolySegmentData.Type == segmentType) &&
                         (((_currentPolySegmentData.Flags & MILCoreSegFlags.SegIsAGap) == 0) == isStroked) &&
                         (((_currentPolySegmentData.Flags & MILCoreSegFlags.SegSmoothJoin) != 0) == isSmoothJoin));
 
            for (int i = 0; i < count; i++)
            { 
                Point p = points[i]; 

                unsafe 
                {
                    AppendData((byte*)&p, sizeof(Point));
                }
 
                _currentPolySegmentData.Count++;
            } 
        } 

        #endregion Private Methods 

        #region Fields

        private bool _disposed; 
        private int _currChunkOffset;
        FrugalStructList _chunkList; 
        private int _currOffset; 
        private MIL_PATHGEOMETRY _currentPathGeometryData;
        private MIL_PATHFIGURE _currentPathFigureData; 
        private int _currentPathFigureDataOffset = -1;
        private MIL_SEGMENT_POLY _currentPolySegmentData;
        private int _currentPolySegmentDataOffset = -1;
        private UInt32 _lastSegmentSize = 0; 
        private UInt32 _lastFigureSize = 0;
        private Point[] _scratchForLine = new Point[1]; 
        private Point[] _scratchForQuadraticBezier = new Point[2]; 
        private Point[] _scratchForBezier = new Point[3];
 
        private const int c_defaultChunkSize = 2*1024;
        private const int c_maxChunkSize = 1024*1024;

        #endregion Fields 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK