# Patch created by pippo
# Date: Sat Feb 26 15:57:08 CET 2005
# Repository: pnetlib
# Comments:
# Add implementation for RegionData handling
#### End of Preamble ####

#### Patch data follows ####
Index: ChangeLog
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/ChangeLog,v
retrieving revision 1.2166
diff -c -r1.2166 ChangeLog
*** ChangeLog	25 Feb 2005 19:14:57 -0000	1.2166
--- ChangeLog	26 Feb 2005 14:56:49 -0000
***************
*** 1,3 ****
--- 1,9 ----
+ 2005-02-26  Marco Bosatta  <mboss@xp-obj.ch>
+ 
+ 	* System/Drawing/Region.cs,
+ 	System/Drawing/Drawing2D/RegionData.cs:
+         Add handling of RegionData byte array.
+ 
  2005-02-25  Richard Baumann  <biochem333@nyc.rr.com>
  
  	* System/Net/Sockets/Socket.cs: change connected state as needed on
Index: System.Drawing/Region.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing/Region.cs,v
retrieving revision 1.10
diff -c -r1.10 Region.cs
*** System.Drawing/Region.cs	26 Jan 2004 20:30:54 -0000	1.10
--- System.Drawing/Region.cs	26 Feb 2005 14:56:56 -0000
***************
*** 97,102 ****
--- 97,104 ----
  #endif
  public sealed class Region : MarshalByRefObject, IDisposable
  {
+         // Internal byte representation of the region
+         private RegionData rgnData;
  	// Overall extent of the region
  	private RectangleF extent;
  	// rectangles that make up the region sorted top to bottom, left to right
***************
*** 105,121 ****
  	// Constructors.
  	public Region()
  	{
  		MakeInfinite();
  	}
  
- 	[TODO]
  	public Region(GraphicsPath path)
  	{
  		if(path == null)
  		{
  			throw new ArgumentNullException("path");
  		}
! 		// TODO
  	}
  
  	public Region(Rectangle rect) : this( (RectangleF)rect)
--- 107,123 ----
  	// Constructors.
  	public Region()
  	{
+                 rgnData = new RegionData() ;
  		MakeInfinite();
  	}
  
  	public Region(GraphicsPath path)
  	{
  		if(path == null)
  		{
  			throw new ArgumentNullException("path");
  		}
!                 rgnData = new RegionData( path );
  	}
  
  	public Region(Rectangle rect) : this( (RectangleF)rect)
***************
*** 123,128 ****
--- 125,131 ----
  
  	public Region(RectangleF rect)
  	{
+                 rgnData = new RegionData( rect );
  		if (rect.Width < 0)
  			rect = new RectangleF(rect.Right, rect.Top, -rect.Width, rect.Height);
  		if (rect.Height < 0)
***************
*** 139,145 ****
  			// extent is already empty(0,0,0,0)
  			rects = new RectangleF[0];
  		}
- 		
  	}
  
  	private Region(int initialRectSize)
--- 142,147 ----
***************
*** 147,160 ****
  		rects = new RectangleF[initialRectSize];
  	}
  
! 	[TODO]
! 	public Region(RegionData rgnData)
  	{
! 		if(rgnData == null)
  		{
  			throw new ArgumentNullException("rgnData");
  		}
! 		// TODO
  	}
  
  	// Helpers, to replace missing "Math" class in some profiles.
--- 149,164 ----
  		rects = new RectangleF[initialRectSize];
  	}
  
! 	public Region(RegionData otherRgnData)
  	{
! 		if(otherRgnData == null)
  		{
  			throw new ArgumentNullException("rgnData");
  		}
!                 Region r = otherRgnData.ConstructRegion ( otherRgnData ) ;
!                 this.rects = r.rects ;
!                 this.extent = r.extent ;
!                 this.rgnData = r.GetRegionData() ;
  	}
  
  	// Helpers, to replace missing "Math" class in some profiles.
***************
*** 207,212 ****
--- 211,217 ----
  	public Region Clone()
  	{
  		Region newRegion = new Region();
+ 		newRegion.rgnData = rgnData.Clone();
  		newRegion.rects = (RectangleF[])rects.Clone();
  		newRegion.extent = extent;
  		return newRegion;
***************
*** 230,235 ****
--- 235,241 ----
  
  	public void Complement(Region region)
  	{
+                 rgnData.Complement( region ) ;
  		Region subtract = Subtract(region, this);
  		extent = subtract.extent;
  		rects = subtract.rects;
***************
*** 295,300 ****
--- 301,307 ----
  
  	public void Exclude(Region region)
  	{
+                 rgnData.Exclude( region ) ;
  		Region subtract = Subtract(this, region);
  		extent = subtract.extent;
  		rects = subtract.rects;
***************
*** 321,330 ****
  	}
  
  	// Get the raw region data for this region.
- 	[TODO]
  	public RegionData GetRegionData()
  	{
! 		return null;
  	}
  
  	// Get an array of rectangles that represents this region.
--- 328,336 ----
  	}
  
  	// Get the raw region data for this region.
  	public RegionData GetRegionData()
  	{
! 		return rgnData;
  	}
  
  	// Get an array of rectangles that represents this region.
***************
*** 367,372 ****
--- 373,379 ----
  	
  	public void Intersect(Region region)
  	{
+                 rgnData.Intersect(region);
  		Intersect(this, region);
  	}
  
***************
*** 492,497 ****
--- 499,505 ----
  	// Make this region empty.
  	public void MakeEmpty()
  	{
+                 rgnData.MakeEmpty() ;
  		rects = new RectangleF[0];
  		extent = Rectangle.Empty;
  	}
***************
*** 499,504 ****
--- 507,513 ----
  	// Make this region infinite.
  	public void MakeInfinite()
  	{
+                 rgnData.MakeInfinite() ;
  		const float maxCoord = 4194304; //Math.Pow(2, 22)
  		extent = new RectangleF(-maxCoord, -maxCoord, 2 * maxCoord, 2 * maxCoord);
  		rects = new RectangleF[1] { extent };
***************
*** 508,514 ****
  	[TODO]
  	public void Transform(Matrix matrix)
  	{
! 		// TODO
  	}
  
  	// Translate this matrix by a specific amount.
--- 517,524 ----
  	[TODO]
  	public void Transform(Matrix matrix)
  	{
!                 rgnData.Transform( matrix ) ;
!                 // TODO: other state variables
  	}
  
  	// Translate this matrix by a specific amount.
***************
*** 519,524 ****
--- 529,535 ----
  	
  	public void Translate(float dx, float dy)
  	{
+                 rgnData.Translate( dx, dy ) ;
  		for( int i = 0; i < rects.Length; i++)
  			rects[i].Offset(dx, dy);
  		if (rects.Length>0)
***************
*** 543,548 ****
--- 554,560 ----
  	
  	public void Union(Region region)
  	{
+                 rgnData.Union( region );
  		Union (this, region);
  	}
  
***************
*** 1270,1275 ****
--- 1282,1288 ----
  	
  	public void Xor(Region region)
  	{
+                 rgnData.Xor( region ) ;
  		Region reg1 = Subtract(this, region);
  		Union(reg1, Subtract(region, this));
  		extent = reg1.extent;
Index: System.Drawing/Drawing2D/RegionData.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing/Drawing2D/RegionData.cs,v
retrieving revision 1.1
diff -c -r1.1 RegionData.cs
*** System.Drawing/Drawing2D/RegionData.cs	7 Jun 2003 22:40:58 -0000	1.1
--- System.Drawing/Drawing2D/RegionData.cs	26 Feb 2005 14:57:00 -0000
***************
*** 3,8 ****
--- 3,9 ----
   *			"System.Drawing.Drawing2D.RegionData" class.
   *
   * Copyright (C) 2003  Southern Storm Software, Pty Ltd.
+  * Copyright (C) 2005  Free Software Foundation
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
***************
*** 19,47 ****
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  
  namespace System.Drawing.Drawing2D
  {
  
  public sealed class RegionData
  {
- 	// Internal state.
- 	private byte[] data;
  
! 	// Constructor.
! 	internal RegionData() {}
  
! 	// Get or set the region data.
! 	public byte[] Data
! 			{
! 				get
! 				{
! 					return data;
! 				}
! 				set
! 				{
! 					data = value;
! 				}
! 			}
  
  }; // class RegionData
  
--- 20,805 ----
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  
+ using System.Collections;
+ 
  namespace System.Drawing.Drawing2D
  {
  
  public sealed class RegionData
  {
  
!         // Public interface
!         public byte[] Data
!         {
!                 get
!                 {
!                         return data;
!                 }
!                 set
!                 {
!                         data = value;
!                 }
!         }
!         public RegionData Clone() 
!         {
!                 RegionData rd = new RegionData() ;
!                 if ( data != null )
!                         rd.Data = (byte[]) data.Clone() ;
!                 return rd ;
!         }
! 
!         // Internal state.
!         private byte[] data;
! 
!         /*
!          * Flags & Constants
!          */
!         // Basic regions
!         private const Int32 REG_RECT    	= 0x10000000;
!         private const Int32 REG_PATH    	= 0x10000001;
!         private const Int32 REG_EMPTY   	= 0x10000002;
!         private const Int32 REG_INF     	= 0x10000003;
!         // Operation codes
!         private const Int32 OP_INTERSECT   	= 0x00000001;
!         private const Int32 OP_UNION       	= 0x00000002;
!         private const Int32 OP_XOR         	= 0x00000003;
!         private const Int32 OP_EXCLUDE     	= 0x00000004;
!         private const Int32 OP_COMPLEMENT       = 0x00000005;
!         // Magic number
!         private const Int32  _MAGIC_  	        = unchecked( (Int32) 0xDBC01001 );
!         // Format qualifiers for path data
!         private const Int32 FMT_SHORT   	= 0x00004000;
!         private const Int32 FMT_SINGLE  	= 0x00000000;
!         // Array handling
!         private const Int32 HEADER_SIZE 	= 0x00000010;
!         private const Int32 CAP_MIN     	= 0x00000080;
!         private const Int32 CAP_MAX     	= 0x7FFFFFFF;
!         private const Int32 CAP_INC     	= 0x00000100;
! 
!         /*
!          * Constructors, for internal use ( used by System.Drawing.Region )
!          */
!         // Default constructor
!         internal RegionData() { }
!         // Construct region data for a given rectangle 
!         internal RegionData( RectangleF rect ) 
!         {
!                 InitializeRegionData( rect );
!         }
!         // Construct region data for a given graphic path 
!         internal RegionData( GraphicsPath path ) 
!         {
!                 InitializeRegionData( path );
!         }
! 
!         /*
!            Region Constructor from given RegionData:
!             The region data is parsed 
!             and operations are evaluated
!             on the returned region .
!          */
!         internal Region ConstructRegion ( RegionData other ) 
!         {
!                 return Evaluate( other.Data );
!         }
! 
!         /*
!          * Tests
!          */
!         [TODO]
!                 private void ValidateCheckSum()
!                 {
!                         // TODO: validate check sum
!                         return ;
!                 }
!         // check if we are the infinite region
!         internal bool IsInfinite()
!         {
!                 return ( GetInt32( data, 12 ) == 0 ) && ( GetInt32( data, HEADER_SIZE ) == REG_INF ) ;
!         }
!         // check if we are the empty region
!         internal bool IsEmpty()
!         {
!                 return ( GetInt32( data, 12 ) == 0 ) && ( GetInt32( data, HEADER_SIZE ) == REG_EMPTY ) ;
!         }
! 
!         /*
!          * Creational methods
!          */
!         private void InitializeRegionData( RectangleF rect ) 
!         {
!                 int size =  AddRegionRectangle( rect , StartRegionData() ) ;
!                 WriteHeader( size - 8 , 0 );
!                 Resize( size ) ;
!         }
!         private void InitializeRegionData( GraphicsPath path ) 
!         {
!                 int size =  AddRegionPath( path , StartRegionData() ) ;
!                 WriteHeader( size - 8 , 0 );
!                 Resize( size ) ;
!         }
!         private void InitializeEmptyRegionData()
!         {
!                 int size =  AddRegionEmpty( StartRegionData() ) ;
!                 WriteHeader( size - 8 , 0 );
!                 Resize( size ) ;
!         }
!         private void InitializeInfiniteRegionData()
!         {
!                 int size =  AddRegionInfinite( StartRegionData() ) ;
!                 WriteHeader( size - 8 , 0 );
!                 Resize( size ) ;
!         }
! 
!         /*
!          * Unary Region operations 
!          */
!         internal void MakeEmpty ( )
!         {
!                 InitializeEmptyRegionData() ;
!         }
!         internal void MakeInfinite ( )
!         {
!                 InitializeInfiniteRegionData() ;
!         }
!         internal void Translate ( float dX, float dY ) 
!         {
!                 if ( ( dX == 0.0f) && ( dY == 0.0f ) )
!                         return ; // nothing to do
!                 int size = 8 + GetInt32( data, 0 ) ;
!                 int nrOps2 = GetInt32( data, 12 ) ;
!                 int readPointer = HEADER_SIZE ;
!                 int writePointer = readPointer ;
!                 while ( readPointer < size ) {
!                         Token T = NextToken( data, ref readPointer, false );
!                         Int32 tokenType = GetInt32( T.rawData , 0 );
!                         switch (tokenType) {
!                                 case REG_RECT:
!                                         RectangleF rect = GetRectangle( T.rawData );
!                                         rect.X += dX ; 
!                                         rect.Y += dY ; 
!                                         writePointer = AddRegionRectangle( rect , writePointer ) ;
!                                         break;
!                                 case REG_PATH:
!                                         GraphicsPath path = GetPath( T.rawData );
!                                         for ( int n=0; n<path.PointCount; n++ ) {
!                                                 path.PathPoints[n].X += dX ;
!                                                 path.PathPoints[n].Y += dY ;
!                                         }
!                                         writePointer = AddRegionPath( path , writePointer ) ;
!                                         break;
!                                 default:
!                                         // other tokens are not concerned
!                                         writePointer += T.rawData.Length ;
!                                         break;
!                         }
!                 }
!                 WriteHeader( size - 8 , nrOps2 );
!                 Resize( size ) ;
!         }
!         internal void Transform ( Matrix matrix )
!         {
!                 if ( matrix.IsIdentity )
!                         return ; // bail out
!                 byte[] oldData = this.Clone().Data ;
!                 int oldSize = 8 + GetInt32( oldData, 0 ) ;
!                 int nrOps2 = GetInt32( oldData, 12 ) ;
!                 int readPointer =  StartRegionData() ;
!                 int writePointer = readPointer ;
!                 float m11 = matrix.Elements[0] ; 
!                 float m12 = matrix.Elements[1] ; 
!                 float m21 = matrix.Elements[2] ; 
!                 float m22 = matrix.Elements[3] ; 
!                 float  dX = matrix.Elements[4] ; 
!                 float  dY = matrix.Elements[5] ; 
!                 while ( readPointer < oldSize ) {
!                         Token T = NextToken( oldData, ref readPointer, false );
!                         Int32 tokenType = GetInt32( T.rawData , 0 );
!                         switch (tokenType) {
!                                 case REG_RECT:
!                                         RectangleF rect = GetRectangle( T.rawData );
!                                         if ( ( m12 == 0.0f) && ( m21 == 0.0f ) ) {
!                                                 // in this case, rect transforms to another rectangle
!                                                 rect.X = ( m11 < 0 ) ? m11 * ( rect.X + rect.Width ) : m11 * rect.X ;
!                                                 rect.X += dX ; 
!                                                 // there is actually a BUG in Microsoft's .NET 1.1 implementation:
!                                                 //  for (m22<0) they evaluate rect.Y to be m22*(rect.Y+rect.Height), which
!                                                 //  cannot be possible by simple geometric reasoning...
!                                                 rect.Y = ( m22 < 0 ) ? m22 * ( rect.Y - rect.Height ) : m22 * rect.Y ;
!                                                 rect.Y += dY ; 
!                                                 rect.Width = ( m11 < 0 ) ? -m11 * rect.Width : m11 * rect.Width ;
!                                                 rect.Height = ( m22 < 0 ) ? -m22 * rect.Height : m22 * rect.Height ;
!                                                 writePointer = AddRegionRectangle( rect , writePointer ) ;
!                                         } else {
!                                                 // rectangular shape is not preserved -> use a graphics path
!                                                 GraphicsPath path = new GraphicsPath() ;
!                                                 path.AddRectangle( rect ) ;
!                                                 path.Transform( matrix ) ;
!                                                 writePointer = AddRegionPath( path , writePointer ) ;
!                                         }
!                                         break;
!                                 case REG_PATH:
!                                         GraphicsPath path = GetPath( T.rawData );
!                                         path.Transform( matrix ) ;
!                                         writePointer = AddRegionPath( path , writePointer ) ;
!                                         break;
!                                 default:
!                                         // other tokens are not concerned
!                                         writePointer = AddRawData( T.rawData , writePointer ) ;
!                                         break;
!                         }
!                 }
!                 WriteHeader( writePointer - 8 , nrOps2 );
!                 Resize( writePointer ) ;
!         }
! 
!         /*
!          * Binary Region operations 
!          */
!         internal void Intersect ( RectangleF rect ) {
!                 if ( IsEmpty() )                    // bail out 
!                         return;
!                 else if ( IsInfinite() )            // return the other region 
!                         InitializeRegionData( rect ) ; 
!                 else
!                         RegionOperation( OP_INTERSECT, REG_RECT, rect );
!         }
!         internal void Union ( RectangleF rect ) {
!                 if ( IsEmpty() )                    // return the other region 
!                         InitializeRegionData( rect ) ; 
!                 else if ( IsInfinite() )            // bail out 
!                         return;
!                 else
!                         RegionOperation( OP_UNION, REG_RECT, rect );
!         }
!         internal void Xor ( RectangleF rect ) {
!                 if ( IsEmpty() )                    // return the other region
!                         InitializeRegionData( rect ) ; 
!                 else
!                         RegionOperation( OP_XOR, REG_RECT, rect );
!         }
!         internal void Exclude ( RectangleF rect ) {
!                 if ( IsEmpty() )                    // bail out
!                         return ; 
!                 else
!                         RegionOperation( OP_EXCLUDE, REG_RECT, rect );
!         }
!         internal void Complement ( RectangleF rect ) {
!                 if ( IsEmpty() )                    // return the other region
!                         InitializeRegionData( rect ) ; 
!                 else if ( IsInfinite() )            // return the empty region 
!                         InitializeEmptyRegionData() ;
!                 else 
!                         RegionOperation( OP_COMPLEMENT, REG_RECT, rect );
!         }
!         internal void Intersect ( GraphicsPath path ) {
!                 if ( IsEmpty() )                    // bail out 
!                         return;
!                 else if ( IsInfinite() )            // return the other region 
!                         InitializeRegionData( path ) ; 
!                 else
!                         RegionOperation( OP_INTERSECT, REG_PATH, path );
!         }
!         internal void Union ( GraphicsPath path ) {
!                 if ( IsEmpty() )                    // return the other region 
!                         InitializeRegionData( path ) ; 
!                 else if ( IsInfinite() )            // bail out 
!                         return;
!                 else
!                         RegionOperation( OP_UNION, REG_PATH, path );
!         }
!         internal void Xor ( GraphicsPath path ) {
!                 if ( IsEmpty() )                    // return the other region
!                         InitializeRegionData( path ) ; 
!                 else
!                         RegionOperation( OP_XOR, REG_PATH, path );
!         }
!         internal void Exclude ( GraphicsPath path ) {
!                 if ( IsEmpty() )                    // bail out
!                         return ; 
!                 else
!                         RegionOperation( OP_EXCLUDE, REG_PATH, path );
!         }
!         internal void Complement ( GraphicsPath path ) {
!                 if ( IsEmpty() )                    // return the other region
!                         InitializeRegionData( path ) ; 
!                 else if ( IsInfinite() )            // return the empty region 
!                         InitializeEmptyRegionData() ;
!                 else 
!                         RegionOperation( OP_COMPLEMENT, REG_PATH, path );
!         }
!         internal void Intersect ( Region other ) {
!                 if ( IsEmpty() )                               // bail out 
!                         return;
!                 else if ( other.GetRegionData().IsEmpty() )    // return the empty region 
!                         InitializeEmptyRegionData() ;
!                 else if ( IsInfinite() )                       // return the other region 
!                         data = other.GetRegionData().Data ;
!                 else if ( other.GetRegionData().IsInfinite() ) // bail out
!                         return;
!                 else
!                         RegionOperation( OP_INTERSECT, -1, other );
!         }
!         internal void Union ( Region other ) {
!                 if ( IsEmpty() )                               // return the other region
!                         data = other.GetRegionData().Data ;
!                 else if ( other.GetRegionData().IsEmpty() )    // bail out
!                         return ;
!                 else if ( IsInfinite() )                       // bail out
!                         return ;
!                 else if ( other.GetRegionData().IsInfinite() ) // return the infinite region
!                         InitializeInfiniteRegionData() ;
!                 else
!                         RegionOperation( OP_UNION, -1, other );
!         }
!         internal void Xor ( Region other ) {
!                 if ( IsEmpty() )                               // return the other region
!                         data = other.GetRegionData().Data ;
!                 else if ( other.GetRegionData().IsEmpty() )    // bail out
!                         return ;
!                 else
!                         RegionOperation( OP_XOR, -1, other );
!         }
!         internal void Exclude ( Region other ) {
!                 if ( IsEmpty() )                                // bail out
!                         return ; 
!                 else if ( other.GetRegionData().IsEmpty() )     // bail out
!                         return;
!                 else if ( other.GetRegionData().IsInfinite() )  // return the empty region
!                         InitializeEmptyRegionData() ;
!                 else
!                         RegionOperation( OP_EXCLUDE, -1, other );
!         }
!         internal void Complement ( Region other ) {
!                 if ( IsEmpty() )                              // return the other region
!                         data = other.GetRegionData().Data ;
!                 else if ( other.GetRegionData().IsEmpty() )   // return the empty region
!                         InitializeEmptyRegionData() ;
!                 else if ( IsInfinite() )                      // return the empty region 
!                         InitializeEmptyRegionData() ;
!                 else 
!                         RegionOperation( OP_COMPLEMENT, -1, other );
!         }
!         private void RegionOperation( int opcode, int regtype, Object regionObject )
!         {
!                 // get current twice number of operations 
!                 int nrOps2 =  GetInt32( data, 12 ) ;
!                 // skip header from current data
!                 int size = data.Length - HEADER_SIZE;
!                 byte[] bytes = new byte[size];
!                 Array.Copy( data , HEADER_SIZE, bytes , 0, size );
!                 // create a fresh region data
!                 int index = StartRegionData() ;
!                 // insert the new op code
!                 PutInt32( opcode, index );    
!                 index+=4;
!                 // add old data
!                 EnsureCapacity( index + size ) ;
!                 Array.Copy( bytes, 0, data, index, size );
!                 index+=size;
!                 // insert new data, update twice number of operations 
!                 switch (regtype) {
!                         case REG_RECT:
!                                 index = AddRegionRectangle( (RectangleF) regionObject , index );
!                                 nrOps2 += 2 ;
!                                 break;
!                         case REG_PATH:
!                                 index = AddRegionPath( (GraphicsPath) regionObject , index );
!                                 nrOps2 += 2 ;
!                                 break;
!                         default:
!                                 index = AddRegion( (Region) regionObject ,index );
!                                 nrOps2 += ( 2 + GetInt32( ((Region) regionObject).GetRegionData().Data , 12 ) );
!                                 break;
!                 }
!                 // finish
!                 WriteHeader( index - 8 , nrOps2 ) ;
!                 Resize ( index ) ;
!         }
! 
!         /*
!          * IO for primitive data types
!          */
!         // Put a byte at specified index
!         private void PutByte( Byte value, int index )
!         {
!                 data[index] = value ;
!         }
!         // Read a byte from specified index
!         private static Byte GetByte( byte[] bts, int index )
!         {
!                 return bts[index] ;
!         }
!         // Put an unsigned short at specified index
!         private void PutInt16( Int16 value, int index )
!         {
!                 byte[] bytes = BitConverter.GetBytes( value ) ;
!                 for ( ushort s = 0; s<2 ; s++ )
!                         data[index+s] = bytes[s] ;
!         }
!         // Read an unsigned short from specified index
!         private static Int16 GetInt16( byte[] bts, int index )
!         {
!                 return BitConverter.ToInt16( bts , index ) ;
!         }
!         // Put an unsigned integer at specified index
!         private void PutInt32( Int32 value, int index )
!         {
!                 byte[] bytes = BitConverter.GetBytes( value ) ;
!                 for ( ushort s = 0; s<4 ; s++ )
!                         data[index+s] = bytes[s] ;
!         }
!         // Read an unsigned integer from specified index
!         private static Int32 GetInt32( byte[] bts, int index )
!         {
!                 return BitConverter.ToInt32( bts , index ) ;
!         }
!         // Put a single precision floating point at specified index using
!         //  IEEE floating point standard representation
!         private void PutSingle( Single value, int index )
!         {
!                 byte[] bytes = BitConverter.GetBytes( value ) ;
!                 for ( ushort s = 0; s<4 ; s++ )
!                         data[index+s] = bytes[s] ;
!         }
!         // Read a single precision floating point from specified index 
!         private static Single GetSingle( byte[] bts, int index )
!         {
!                 return BitConverter.ToSingle( bts , index ) ;
!         }
! 
! 
!         /*
!          * Private methods for updating the internal state
!          */
!         [TODO]
!                 private Int32 CheckSum() 
!                 {
!                         // TODO: compute check sum
!                         return unchecked( (Int32) 0xFFFFFFFF );
!                 }
!         /*
!          * Tha data header format:
!          *   index    description                     format
!          *   -----------------------------------------------------
!          *   00-03    size after checksum             Int32
!          *   04-07    checksum ??                     ??      TODO
!          *   08-11    magic number                    Int32
!          *   12-15    2 * (nr. of bin. operations)    Int32
!          */
!         private void WriteHeader( int size, Int32 _2nrOps )
!         {
!                 PutInt32( size        ,  0 ) ;
!                 PutInt32( CheckSum()  ,  4 ) ;
!                 PutInt32( _MAGIC_     ,  8 ) ;
!                 PutInt32( _2nrOps     , 12 ) ;
!         }
!         private void Resize( int size ) 
!         {
!                 if ( size != data.Length ) {
!                         byte[] bytes = new byte[ size ];
!                         Array.Copy( data , bytes , size );
!                         data = bytes ;
!                 }
!         }
!         private void EnsureCapacity( int newsize )
!         {
!                 uint oldcap = (uint) data.Length ;
!                 uint newcap = (uint) newsize + (uint) CAP_INC - (uint) ( newsize % CAP_INC ) ;
!                 if ( newcap <= oldcap )
!                         return;
!                 if ( newcap > CAP_MAX )
!                         throw new OverflowException( "array too large" );
!                 byte[] bytes = new byte[ newcap ];
!                 Array.Copy( data , bytes , oldcap );
!                 data = bytes ;
!         }
!         // Start a new region data.
!         // Returns next free write index.
!         private int StartRegionData()
!         {
!                 data = new byte[CAP_MIN];
!                 return HEADER_SIZE ;
!         }
!         // Add a rectangle region at the given index.
!         // Returns next free write index.
!         private int AddRegionRectangle( RectangleF rect , int index ) 
!         { 
!                 EnsureCapacity( index + 20 );
!                 PutInt32 ( REG_RECT    , index    );
!                 PutSingle( rect.X      , index+=4 );
!                 PutSingle( rect.Y      , index+=4 );
!                 PutSingle( rect.Width  , index+=4 );
!                 PutSingle( rect.Height , index+=4 );
!                 return index+=4 ;
!         }
!         // Add a path region at s given index.
!         // Returns next free write index.
!         private int AddRegionPath( GraphicsPath path , int index ) 
!         { 
!                 bool fmtShort = HasSimpleFormat( path );
!                 int nrPoints = path.PointCount ;
!                 int pathSize = nrPoints * ( fmtShort ? 5 : 9 ) + 12 ;
!                 EnsureCapacity( index + 8 + pathSize );
!                 PutInt32( REG_PATH , index    );
!                 PutInt32( pathSize , index+=4 );
!                 PutInt32( _MAGIC_  , index+=4 );
!                 PutInt32( nrPoints , index+=4 );
!                 PutInt32( fmtShort ? FMT_SHORT : FMT_SINGLE , index+=4 );
!                 if ( fmtShort ) {
!                         index+=2;
!                         for ( int i=0; i<nrPoints; i++ ) {
!                                 PutInt16( (Int16) path.PathPoints[i].X , index+=2 );
!                                 PutInt16( (Int16) path.PathPoints[i].Y , index+=2 );
!                         }
!                         index+=1;
!                 } else {
!                         for ( int i=0; i<nrPoints; i++ ) {
!                                 PutSingle( path.PathPoints[i].X , index+=4 );
!                                 PutSingle( path.PathPoints[i].Y , index+=4 );
!                         }
!                         index+=3;
!                 }
!                 for ( int i=0; i<nrPoints; i++ ) 
!                         PutByte( path.PathTypes[i] , ++index ) ;
!                 return index+=1;
!         }
!         // Add the empty region at a given index.
!         // Returns next free write index.
!         private int AddRegionEmpty( int index ) 
!         { 
!                 EnsureCapacity( index + 4 );
!                 PutInt32( REG_EMPTY , index );
!                 return index + 4 ;
!         }
!         // Add the infinite region at a given index.
!         // Returns next free write index.
!         private int AddRegionInfinite( int index ) 
!         { 
!                 EnsureCapacity( index + 4 );
!                 PutInt32( REG_INF , index );
!                 return index + 4 ;
!         }
!         // Add another region at a given index.
!         // Returns next free write index.
!         private int AddRegion( Region region , int index ) 
!         { 
!                 byte[] other = region.GetRegionData().Data ;
!                 int size = other.Length - HEADER_SIZE ;
!                 EnsureCapacity( index + size );
!                 Array.Copy( other, HEADER_SIZE, data, index, size );
!                 return index + size ;
!         }
!         // Add a chunk of raw data at a given index.
!         // Returns next free write index.
!         private int AddRawData( byte[] raw , int index ) 
!         { 
!                 int size = raw.Length ;
!                 EnsureCapacity( index + size );
!                 Array.Copy( raw, 0, data, index, size ) ;
!                 return index + size ;
!         }
!         // If we can cast all coordinates to short without loosing in precision, 
!         //  then we store points in short format
!         private bool HasSimpleFormat( GraphicsPath path )
!         {
!                 foreach ( PointF p in path.PathPoints ) 
!                         if ( ( p.X != (Int16) p.X ) || ( p.Y != (Int16) p.Y ) )
!                                 return false ;
!                 return true ;
!         }
!         // Returns a basic Region from a given raw byte representation
!         private Region GetRegion( byte[] raw )
!         {
!                 Int32 regtype = GetInt32( raw , 0 );
!                 Region region ;
!                 switch (regtype) {
!                         case REG_RECT:
!                                 region = new Region( GetRectangle( raw ) );
!                                 break;
!                         case REG_PATH:
!                                 region = new Region( GetPath( raw ) );
!                                 break;
!                         case REG_EMPTY:
!                                 region = new Region();
!                                 region.MakeEmpty() ;
!                                 break;
!                         case REG_INF:
!                                 region = new Region();
!                                 region.MakeInfinite() ;
!                                 break;
!                         default:
!                                 // is not a region
!                                 break;
!                 }
!                 return region ;
!         }
!         // Returns a rectangle structure from a given raw byte representation
!         private RectangleF GetRectangle( byte[] raw ) 
!         { 
!                 int index = 0;
!                 Single X = GetSingle( raw, index+=4 );
!                 Single Y = GetSingle( raw, index+=4 );
!                 Single W = GetSingle( raw, index+=4 );
!                 Single H = GetSingle( raw, index+=4 );
!                 return new RectangleF( X, Y, W, H );
!         }
!         // Returns a graphics path from a given raw byte representation
!         private GraphicsPath GetPath( byte[] raw ) 
!         { 
!                 int nrPoints = GetInt32( raw , 12 ) ;
!                 PointF[] points = new PointF[ nrPoints ] ;
!                 byte[] types = new byte[ nrPoints ] ;
!                 int format = GetInt32( raw , 16 ) ;
!                 int index = 16 ;
!                 if ( format == FMT_SHORT )  {
!                         Int16 X , Y ;
!                         index+=2 ;
!                         for ( int n=0; n<nrPoints; n++ ) {
!                                 X = GetInt16( raw , index+=2 ) ;
!                                 Y = GetInt16( raw , index+=2 ) ;
!                                 points[n] = new PointF( (Single) X , (Single) Y );
!                         }
!                         index+=1 ;
!                 } else {
!                         Single X , Y ;
!                         for ( int n=0; n<nrPoints; n++ ) {
!                                 X = GetSingle( raw , index+=4 ) ;
!                                 Y = GetSingle( raw , index+=4 ) ;
!                                 points[n] = new PointF( X , Y ) ;
!                         }
!                         index+=3 ;
!                 }
!                 for ( int n=0; n<nrPoints; n++ )
!                         types[n] = GetByte( raw, index+=1 ) ;
!                 return new GraphicsPath( points , types ) ;
!         }
! 
!         /*
!          * Parses a region data and evaluates all binary operations. 
!          * Returns a region with all operations applied.
!          */
!         private Region Evaluate ( byte[] regData )
!         {
!                 int dataSize = GetInt32( regData, 0 ) + 8 ;
!                 int nrOps = GetInt32( regData, 12 ) / 2 ;
!                 int pointer =  HEADER_SIZE ;
!                 Token T = new Token();
!                 Stack stack = new Stack();
!                 while ( pointer < dataSize ) {
!                         T = NextToken( regData, ref pointer, true );
!                         if ( T.Type == Token.OP )
!                                 stack.Push( T );
!                         else {
!                                 if ( ( stack.Count == 0 ) || ( ((Token) stack.Peek()).Type == Token.OP ) )
!                                         stack.Push( T );
!                                 else {
!                                         while ( ( nrOps > 0 ) &&
!                                                         ( ((Token) stack.Peek()).Type == Token.DATA ) ) {
!                                                 Token S = (Token) stack.Pop() ;
!                                                 Token O = (Token) stack.Pop() ;
!                                                 T = O.Eval( S, T );
!                                                 nrOps-- ;
!                                         }
!                                         stack.Push( T );
!                                 }
!                         }
!                 }
!                 return T.region ;
!         }
!         private class Token 
!         {
!                 public const int OP          = 1;
!                 public const int DATA        = 2;
! 
!                 // Type is OP or DATA
!                 public int Type;
! 
!                 // is an op code for Type=OP;
!                 // is a region data WITHOUT header for Type=DATA
!                 public byte[] rawData;
! 
!                 // associated region, for DATA Token only
!                 public Region region = new Region();
! 
!                 private Int32 GetOpCode()
!                 {
!                         if ( this.Type != Token.OP ) 
!                                 throw new InvalidOperationException();
!                         return GetInt32( this.rawData, 0 );
!                 }
  
!                 public Token Eval( Token A, Token B ) 
!                 {
!                         if ( ! ( ( this.Type == Token.OP ) && ( A.Type == Token.DATA ) && ( B.Type == Token.DATA ) ) )
!                                 throw new InvalidOperationException();
!                         switch ( GetOpCode() ) {
!                                 case OP_INTERSECT   :
!                                         A.region.Intersect( B.region ) ;
!                                         break;
!                                 case OP_UNION       :
!                                         A.region.Union( B.region ) ;
!                                         break;
!                                 case OP_XOR         :
!                                         A.region.Xor( B.region ) ;
!                                         break;
!                                 case OP_EXCLUDE     :
!                                         A.region.Exclude( B.region ) ;
!                                         break;
!                                 case OP_COMPLEMENT  :
!                                         A.region.Complement( B.region ) ;
!                                         break;
!                                 default:
!                                         throw new InvalidOperationException();
!                         }
!                         Token c = new Token();
!                         c.Type = Token.DATA;
!                         c.region = A.region;
!                         int size = GetInt32( A.region.GetRegionData().Data , 0 ) - 8 ;
!                         c.rawData = new byte[size] ;
!                         Array.Copy( A.region.GetRegionData().Data, HEADER_SIZE, c.rawData, 0, size ) ;
!                         return c;
!                 }
!         }
!         // Returns the next token from a raw data stream.
!         // Adjusts the read pointer "ref int index".
!         private Token NextToken( byte[] regdat, ref int index, bool withRegion ) 
!         {
!                 Token tok = new Token();
!                 int size = 4;
!                 Int32 lookahead = GetInt32( regdat, index );
!                 if ( lookahead == OP_INTERSECT )
!                         tok.Type = Token.OP;
!                 else if ( lookahead == OP_UNION )
!                         tok.Type = Token.OP;
!                 else if ( lookahead == OP_XOR )
!                         tok.Type = Token.OP;
!                 else if ( lookahead == OP_EXCLUDE )
!                         tok.Type = Token.OP;
!                 else if ( lookahead == OP_COMPLEMENT )
!                         tok.Type = Token.OP;
!                 else if ( lookahead == REG_RECT ) {
!                         tok.Type = Token.DATA;
!                         size = 20 ;
!                 }
!                 else if ( lookahead == REG_PATH ) {
!                         tok.Type = Token.DATA;
!                         size = 8 + GetInt32( regdat, index+4 );
!                 }
!                 else if ( lookahead == REG_EMPTY ) 
!                         tok.Type = Token.DATA;
!                 else if ( lookahead == REG_INF ) {
!                         tok.Type = Token.DATA;
!                 }
!                 else
!                         throw new ArgumentException( "invalid token" );
!                 tok.rawData = new byte[ size ];
!                 Array.Copy( regdat, index, tok.rawData, 0, size );
!                 if ( withRegion )
!                         tok.region = GetRegion( tok.rawData ) ;
!                 index+=size ;
!                 return tok;
!         }
  
  }; // class RegionData
  
#### End of Patch data ####
