os/kernelhwsrv/kernel/eka/euser/us_regn.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32\euser\us_regn.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
sl@0
    19
#include "us_std.h"
sl@0
    20
sl@0
    21
NONSHARABLE_CLASS(TRectKey) : public TKey
sl@0
    22
	{
sl@0
    23
public:
sl@0
    24
	TRectKey(const TRect *aRectList,const TPoint &aOffset);
sl@0
    25
	virtual TInt Compare(TInt aLeft,TInt aRight) const;
sl@0
    26
private:
sl@0
    27
	const TRect *iRectList;
sl@0
    28
	TBool iDown;
sl@0
    29
	TBool iRight;
sl@0
    30
	};
sl@0
    31
sl@0
    32
NONSHARABLE_CLASS(TRectSwap) : public TSwap
sl@0
    33
	{
sl@0
    34
public:
sl@0
    35
	inline TRectSwap(TRect *aRectList);
sl@0
    36
	virtual void Swap(TInt aLeft,TInt aRight) const;
sl@0
    37
private:
sl@0
    38
	TRect *iRectList;
sl@0
    39
	};
sl@0
    40
sl@0
    41
inline TRectSwap::TRectSwap(TRect *aRectList)
sl@0
    42
	{iRectList=aRectList;}
sl@0
    43
sl@0
    44
enum {ERegionBufSize=8};
sl@0
    45
sl@0
    46
EXPORT_C TRegion::TRegion(TInt aAllocedRects)
sl@0
    47
//
sl@0
    48
// Constructor.
sl@0
    49
//
sl@0
    50
	: iCount(0),iError(EFalse),iAllocedRects(aAllocedRects)
sl@0
    51
	{}
sl@0
    52
sl@0
    53
sl@0
    54
sl@0
    55
sl@0
    56
EXPORT_C TBool TRegion::IsEmpty() const
sl@0
    57
/**
sl@0
    58
Tests whether the region is empty.
sl@0
    59
sl@0
    60
@return True, if the region is empty and its error flag is unset;
sl@0
    61
        false, otherwise.
sl@0
    62
*/
sl@0
    63
	{
sl@0
    64
sl@0
    65
	return(iCount==0 && !iError);
sl@0
    66
	}
sl@0
    67
sl@0
    68
sl@0
    69
sl@0
    70
sl@0
    71
#ifndef __REGIONS_MACHINE_CODED__
sl@0
    72
EXPORT_C TRect TRegion::BoundingRect() const
sl@0
    73
/**
sl@0
    74
Gets the minimal rectangle that bounds the entire region.
sl@0
    75
sl@0
    76
@return The region's minimal bounding rectangle.
sl@0
    77
*/
sl@0
    78
	{
sl@0
    79
sl@0
    80
	TRect bounds;
sl@0
    81
    const TRect *pRect;
sl@0
    82
	const TRect *pEnd;
sl@0
    83
	if (iCount>0)
sl@0
    84
		{
sl@0
    85
		pRect=RectangleList();
sl@0
    86
		bounds=(*pRect++);
sl@0
    87
		for (pEnd=pRect+(iCount-1);pRect<pEnd;pRect++)
sl@0
    88
			{
sl@0
    89
			if (pRect->iTl.iX<bounds.iTl.iX)
sl@0
    90
				bounds.iTl.iX=pRect->iTl.iX;
sl@0
    91
			if (pRect->iTl.iY<bounds.iTl.iY)
sl@0
    92
				bounds.iTl.iY=pRect->iTl.iY;
sl@0
    93
			if (pRect->iBr.iX>bounds.iBr.iX)
sl@0
    94
				bounds.iBr.iX=pRect->iBr.iX;
sl@0
    95
			if (pRect->iBr.iY>bounds.iBr.iY)
sl@0
    96
				bounds.iBr.iY=pRect->iBr.iY;
sl@0
    97
			}
sl@0
    98
		}
sl@0
    99
	return(bounds);
sl@0
   100
	}	
sl@0
   101
#endif
sl@0
   102
sl@0
   103
sl@0
   104
sl@0
   105
sl@0
   106
EXPORT_C const TRect &TRegion::operator[](TInt aIndex) const
sl@0
   107
/**
sl@0
   108
Gets a rectangle from the region.
sl@0
   109
sl@0
   110
@param aIndex The index of a rectangle within the region's array of rectangles. 
sl@0
   111
              Indexes are relative to zero.
sl@0
   112
              
sl@0
   113
@return The specified rectangle.              
sl@0
   114
              
sl@0
   115
@panic USER 81, if aIndex is greater than or equal to the number 
sl@0
   116
                of rectangles in the region.
sl@0
   117
*/
sl@0
   118
	{
sl@0
   119
sl@0
   120
	__ASSERT_ALWAYS((TUint)aIndex<(TUint)iCount,Panic(ETRegionOutOfRange));
sl@0
   121
    return(*(RectangleList()+aIndex));
sl@0
   122
    }
sl@0
   123
sl@0
   124
sl@0
   125
sl@0
   126
sl@0
   127
#ifndef __REGIONS_MACHINE_CODED__
sl@0
   128
EXPORT_C TBool TRegion::IsContainedBy(const TRect &aRect) const
sl@0
   129
/**
sl@0
   130
Tests whether the region is fully enclosed within the specified rectangle.
sl@0
   131
sl@0
   132
@param aRect The specified rectangle.
sl@0
   133
 
sl@0
   134
@return True, if the region is fully enclosed within the rectangle (their sides 
sl@0
   135
        may touch); false, otherwise.
sl@0
   136
*/
sl@0
   137
	{
sl@0
   138
sl@0
   139
    const TRect *pRect1;
sl@0
   140
    const TRect *pEnd1;
sl@0
   141
	for (pRect1=RectangleList(),pEnd1=pRect1+iCount;pRect1<pEnd1;pRect1++)
sl@0
   142
		{
sl@0
   143
		if (pRect1->iTl.iX<aRect.iTl.iX || pRect1->iBr.iX>aRect.iBr.iX || pRect1->iTl.iY<aRect.iTl.iY || pRect1->iBr.iY>aRect.iBr.iY)
sl@0
   144
			return(EFalse);
sl@0
   145
		}
sl@0
   146
	return(ETrue);
sl@0
   147
	}
sl@0
   148
sl@0
   149
sl@0
   150
sl@0
   151
sl@0
   152
EXPORT_C TBool TRegion::Intersects(const TRect &aRect) const
sl@0
   153
/**
sl@0
   154
Tests whether where there is any intersection between this region and the specified rectangle.
sl@0
   155
sl@0
   156
@param aRect The specified rectangle.
sl@0
   157
 
sl@0
   158
@return True, if there is an intersection; false, otherwise.
sl@0
   159
*/
sl@0
   160
	{
sl@0
   161
sl@0
   162
    const TRect *pRect1;
sl@0
   163
    const TRect *pEnd1;
sl@0
   164
	for (pRect1=RectangleList(),pEnd1=pRect1+iCount;pRect1<pEnd1;pRect1++)
sl@0
   165
		{
sl@0
   166
		if (aRect.Intersects(*pRect1))
sl@0
   167
			return ETrue;
sl@0
   168
		}
sl@0
   169
	return EFalse;
sl@0
   170
	}
sl@0
   171
sl@0
   172
sl@0
   173
sl@0
   174
sl@0
   175
EXPORT_C void TRegion::Copy(const TRegion &aRegion)
sl@0
   176
/**
sl@0
   177
Copies another region to this region.
sl@0
   178
sl@0
   179
The state of the specified region's error flag is also copied.
sl@0
   180
sl@0
   181
@param aRegion The region to be copied.
sl@0
   182
*/
sl@0
   183
	{
sl@0
   184
	if (aRegion.iError)
sl@0
   185
		{
sl@0
   186
		ForceError();
sl@0
   187
		}
sl@0
   188
	else
sl@0
   189
		{
sl@0
   190
		const TInt count = aRegion.iCount;
sl@0
   191
		if (count == 0)
sl@0
   192
			{ // release memory
sl@0
   193
			Clear();
sl@0
   194
			}
sl@0
   195
		else
sl@0
   196
			{
sl@0
   197
			if (iError)
sl@0
   198
				{
sl@0
   199
				Clear();
sl@0
   200
				}
sl@0
   201
sl@0
   202
			if (SetListSize(count))
sl@0
   203
				{
sl@0
   204
				iCount = count;
sl@0
   205
				Mem::Copy(RectangleListW(), aRegion.RectangleList(), sizeof(TRect)*count);
sl@0
   206
				}
sl@0
   207
			}
sl@0
   208
		}
sl@0
   209
	}
sl@0
   210
sl@0
   211
sl@0
   212
sl@0
   213
sl@0
   214
EXPORT_C void TRegion::Offset(const TPoint &aOffset)
sl@0
   215
/**
sl@0
   216
Moves the region by adding a TPoint offset to the co-ordinates of its corners.
sl@0
   217
	
sl@0
   218
The size of the region is not changed.
sl@0
   219
	
sl@0
   220
@param aOffset The offset by which the region is moved. The region is moved 
sl@0
   221
               horizontally by aOffset.iX pixels and vertically by aOffset.iY pixels.
sl@0
   222
*/
sl@0
   223
 	{
sl@0
   224
sl@0
   225
	TRect *pR=RectangleListW();
sl@0
   226
	const TRect *pE=pR+iCount;
sl@0
   227
	while (pR<pE)
sl@0
   228
		{
sl@0
   229
		pR->Move(aOffset);
sl@0
   230
		pR++;
sl@0
   231
		}
sl@0
   232
	}
sl@0
   233
sl@0
   234
sl@0
   235
sl@0
   236
sl@0
   237
EXPORT_C void TRegion::Offset(TInt aXoffset,TInt aYoffset)
sl@0
   238
/**
sl@0
   239
Moves the region by adding X and Y offsets to the co-ordinates of its corners.
sl@0
   240
	
sl@0
   241
The size of the region is not changed.
sl@0
   242
	
sl@0
   243
@param aXoffset The number of pixels by which to move the region horizontally. 
sl@0
   244
                If negative, the region moves leftwards. 
sl@0
   245
@param aYoffset The number of pixels by which to move the region vertically. 
sl@0
   246
                If negative, the region moves upwards.
sl@0
   247
*/
sl@0
   248
	{
sl@0
   249
sl@0
   250
	Offset(TPoint(aXoffset,aYoffset));
sl@0
   251
	}
sl@0
   252
sl@0
   253
sl@0
   254
sl@0
   255
sl@0
   256
EXPORT_C TBool TRegion::Contains(const TPoint &aPoint) const
sl@0
   257
/**
sl@0
   258
Tests whether a point is located within the region.
sl@0
   259
sl@0
   260
If the point is located on the top or left hand side of any rectangle in the 
sl@0
   261
region, it is considered to be within that rectangle and within the region. 
sl@0
   262
sl@0
   263
If the point is located on the right hand side or bottom of a rectangle, it 
sl@0
   264
is considered to be outside that rectangle, and may be outside the region.
sl@0
   265
sl@0
   266
@param aPoint The specified point. 
sl@0
   267
sl@0
   268
@return True, if the point is within the region; false, otherwise.
sl@0
   269
*/
sl@0
   270
	{
sl@0
   271
	const TRect *pR=RectangleList();
sl@0
   272
	const TRect *pE=pR+iCount;
sl@0
   273
	while (pR<pE)
sl@0
   274
		{
sl@0
   275
		if (pR->Contains(aPoint))
sl@0
   276
			return(ETrue);
sl@0
   277
		pR++;
sl@0
   278
		}
sl@0
   279
	return(EFalse);
sl@0
   280
	}
sl@0
   281
sl@0
   282
sl@0
   283
sl@0
   284
sl@0
   285
EXPORT_C void TRegion::SubRect(const TRect &aRect,TRegion *aSubtractedRegion)
sl@0
   286
/**
sl@0
   287
Removes a rectangle from this region.
sl@0
   288
sl@0
   289
If there is no intersection between the rectangle and this region, then this 
sl@0
   290
region is unaffected. 
sl@0
   291
sl@0
   292
@param aRect             The rectangular area to be removed from this region. 
sl@0
   293
@param aSubtractedRegion A pointer to a region. If this is supplied, the
sl@0
   294
                         removed rectangle is added to it. By default this
sl@0
   295
                         pointer is NULL.
sl@0
   296
*/
sl@0
   297
	{
sl@0
   298
	if (aRect.IsEmpty())
sl@0
   299
		return;
sl@0
   300
	TRect *prect=RectangleListW();
sl@0
   301
	TInt limit=iCount;
sl@0
   302
	for (TInt index=0;index<limit;)
sl@0
   303
		{
sl@0
   304
		if (prect->iBr.iX>aRect.iTl.iX && prect->iBr.iY>aRect.iTl.iY && prect->iTl.iX<aRect.iBr.iX && prect->iTl.iY<aRect.iBr.iY)
sl@0
   305
			{
sl@0
   306
			TRect rect(*prect);
sl@0
   307
			TRect inter(aRect);
sl@0
   308
			inter.Intersection(*prect);
sl@0
   309
			DeleteRect(prect);
sl@0
   310
			if (inter.iBr.iY!=rect.iBr.iY)
sl@0
   311
				AppendRect(TRect(rect.iTl.iX,inter.iBr.iY,rect.iBr.iX,rect.iBr.iY));
sl@0
   312
			if (inter.iTl.iY!=rect.iTl.iY)
sl@0
   313
				AppendRect(TRect(rect.iTl.iX,rect.iTl.iY,rect.iBr.iX,inter.iTl.iY));
sl@0
   314
			if (inter.iBr.iX!=rect.iBr.iX)
sl@0
   315
				AppendRect(TRect(inter.iBr.iX,inter.iTl.iY,rect.iBr.iX,inter.iBr.iY));
sl@0
   316
			if (inter.iTl.iX!=rect.iTl.iX)
sl@0
   317
				AppendRect(TRect(rect.iTl.iX,inter.iTl.iY,inter.iTl.iX,inter.iBr.iY));
sl@0
   318
			if (iError)
sl@0
   319
				break;
sl@0
   320
			if (aSubtractedRegion!=NULL)
sl@0
   321
				aSubtractedRegion->AddRect(inter);
sl@0
   322
			prect=RectangleListW()+index;		// List might have been re-allocated so re-get the pointer
sl@0
   323
			limit--;
sl@0
   324
			}
sl@0
   325
		else
sl@0
   326
			{
sl@0
   327
			index++;
sl@0
   328
			prect++;
sl@0
   329
			}
sl@0
   330
		}
sl@0
   331
	}
sl@0
   332
sl@0
   333
#endif
sl@0
   334
sl@0
   335
sl@0
   336
sl@0
   337
sl@0
   338
/**
sl@0
   339
Merges a rectangle with this region.
sl@0
   340
sl@0
   341
If requested it looks for a rectangle in the region that covers the new rectangle, if found method returns immediately.
sl@0
   342
Otherwise, or if an enclosing rectangle is not found, the new aRect is subtracted from all intersecting rectangles,
sl@0
   343
and then aRect is appended to the region.
sl@0
   344
sl@0
   345
@param aRect             The rectangular area to be added to this region.
sl@0
   346
@param aCovered          Whether to look for a rectangle in the region that covers the new aRect.
sl@0
   347
*/
sl@0
   348
void TRegion::MergeRect(const TRect &aRect, TBool aCovered)
sl@0
   349
	{
sl@0
   350
	TRect *prect=RectangleListW();
sl@0
   351
	TInt limit=iCount;
sl@0
   352
	TInt index=0;
sl@0
   353
sl@0
   354
	while (aCovered && (index < limit) )
sl@0
   355
		{
sl@0
   356
		if (prect->iBr.iX<=aRect.iTl.iX || prect->iBr.iY<=aRect.iTl.iY || prect->iTl.iX>=aRect.iBr.iX || prect->iTl.iY>=aRect.iBr.iY)
sl@0
   357
			{
sl@0
   358
			index++;
sl@0
   359
			prect++;
sl@0
   360
			}
sl@0
   361
		else
sl@0
   362
			{
sl@0
   363
			if (prect->iBr.iX>=aRect.iBr.iX && prect->iBr.iY>=aRect.iBr.iY && prect->iTl.iX<=aRect.iTl.iX && prect->iTl.iY<=aRect.iTl.iY)
sl@0
   364
				{ // region rectangle covers new aRect
sl@0
   365
				return;
sl@0
   366
				}
sl@0
   367
			break; // let the 2nd loop deal with this intersection
sl@0
   368
			}
sl@0
   369
		}
sl@0
   370
sl@0
   371
	while (index < limit)
sl@0
   372
		{
sl@0
   373
		if (prect->iBr.iX<=aRect.iTl.iX || prect->iBr.iY<=aRect.iTl.iY || prect->iTl.iX>=aRect.iBr.iX || prect->iTl.iY>=aRect.iBr.iY)
sl@0
   374
			{
sl@0
   375
			index++;
sl@0
   376
			prect++;
sl@0
   377
			}
sl@0
   378
		else
sl@0
   379
			{
sl@0
   380
			TRect rect(*prect);
sl@0
   381
			TRect inter(aRect);
sl@0
   382
			inter.Intersection(*prect);
sl@0
   383
			DeleteRect(prect);
sl@0
   384
			if (inter.iBr.iY!=rect.iBr.iY)
sl@0
   385
				AppendRect(TRect(rect.iTl.iX,inter.iBr.iY,rect.iBr.iX,rect.iBr.iY));
sl@0
   386
			if (inter.iTl.iY!=rect.iTl.iY)
sl@0
   387
				AppendRect(TRect(rect.iTl.iX,rect.iTl.iY,rect.iBr.iX,inter.iTl.iY));
sl@0
   388
			if (inter.iBr.iX!=rect.iBr.iX)
sl@0
   389
				AppendRect(TRect(inter.iBr.iX,inter.iTl.iY,rect.iBr.iX,inter.iBr.iY));
sl@0
   390
			if (inter.iTl.iX!=rect.iTl.iX)
sl@0
   391
				AppendRect(TRect(rect.iTl.iX,inter.iTl.iY,inter.iTl.iX,inter.iBr.iY));
sl@0
   392
			if (iError)
sl@0
   393
				return;
sl@0
   394
			prect=RectangleListW()+index;		// List might have been re-allocated so re-get the pointer
sl@0
   395
			limit--;
sl@0
   396
			}
sl@0
   397
		}
sl@0
   398
	AppendRect(aRect);
sl@0
   399
	}
sl@0
   400
sl@0
   401
sl@0
   402
sl@0
   403
EXPORT_C void TRegion::Union(const TRegion &aRegion)
sl@0
   404
/**
sl@0
   405
Replaces this region with the union of it and the specified region.
sl@0
   406
sl@0
   407
Note that if the error flag of either this region or the specified region is
sl@0
   408
set, then this region is cleared and its error flag is set. This frees up
sl@0
   409
allocated memory.
sl@0
   410
sl@0
   411
@param aRegion The region to be joined to this region.
sl@0
   412
*/
sl@0
   413
	{
sl@0
   414
	if (aRegion.iError)
sl@0
   415
		{
sl@0
   416
		ForceError();
sl@0
   417
		}
sl@0
   418
	else if (!iError && (aRegion.iCount != 0))
sl@0
   419
		{
sl@0
   420
		if (iCount == 0)
sl@0
   421
			{
sl@0
   422
			Copy(aRegion);
sl@0
   423
			}
sl@0
   424
		else
sl@0
   425
			{
sl@0
   426
			RRegionBuf<ERegionBufSize> temp;
sl@0
   427
			temp.Copy(aRegion);
sl@0
   428
			if (temp.iCount>iCount)
sl@0
   429
				{
sl@0
   430
				temp.AppendRegion(*this);
sl@0
   431
				Copy(temp);
sl@0
   432
				}
sl@0
   433
			else
sl@0
   434
				{
sl@0
   435
				AppendRegion(temp);
sl@0
   436
				}
sl@0
   437
			temp.Close();
sl@0
   438
			}
sl@0
   439
		}
sl@0
   440
	}
sl@0
   441
sl@0
   442
sl@0
   443
sl@0
   444
sl@0
   445
#ifndef __REGIONS_MACHINE_CODED__
sl@0
   446
EXPORT_C void TRegion::Intersection(const TRegion &aRegion1,const TRegion &aRegion2)
sl@0
   447
/**
sl@0
   448
Replaces this region with the area of intersection between two specified regions.
sl@0
   449
	
sl@0
   450
Notes:
sl@0
   451
	
sl@0
   452
1. If the error flag of either of the two specified regions is set, then this 
sl@0
   453
   region is cleared and its error flag is set. This frees up allocated memory.
sl@0
   454
	
sl@0
   455
2. If this region's error flag is already set, then the function has no effect.
sl@0
   456
	
sl@0
   457
@param aRegion1 The first region. 
sl@0
   458
@param aRegion2 The second region.
sl@0
   459
*/
sl@0
   460
    {
sl@0
   461
	if (aRegion1.iError || aRegion2.iError)
sl@0
   462
		ForceError();
sl@0
   463
	else
sl@0
   464
		{
sl@0
   465
		iCount=0;
sl@0
   466
		const TRect *pRect1,*pEnd1;
sl@0
   467
		const TRect *pRect2,*pEnd2;
sl@0
   468
		for (pRect1=aRegion1.RectangleList(),pEnd1=pRect1+aRegion1.iCount;pRect1<pEnd1;pRect1++)
sl@0
   469
			{
sl@0
   470
			for (pRect2=aRegion2.RectangleList(),pEnd2=pRect2+aRegion2.iCount;pRect2<pEnd2;pRect2++)
sl@0
   471
				{
sl@0
   472
				if (pRect1->iBr.iX>pRect2->iTl.iX && pRect1->iBr.iY>pRect2->iTl.iY && pRect1->iTl.iX<pRect2->iBr.iX && pRect1->iTl.iY<pRect2->iBr.iY)
sl@0
   473
					{
sl@0
   474
					TRect rect(*pRect2);
sl@0
   475
					rect.Intersection(*pRect1);
sl@0
   476
					AppendRect(rect);
sl@0
   477
					}
sl@0
   478
				}
sl@0
   479
			}
sl@0
   480
		}
sl@0
   481
	}
sl@0
   482
#endif
sl@0
   483
sl@0
   484
sl@0
   485
sl@0
   486
sl@0
   487
EXPORT_C void TRegion::Intersect(const TRegion &aRegion)
sl@0
   488
/**
sl@0
   489
Replaces this region with the area of intersection between it and the specified 
sl@0
   490
region.
sl@0
   491
sl@0
   492
Note that if the error flag of either this region or the specified region is
sl@0
   493
set, then this region is cleared and its error flag is set. This frees up
sl@0
   494
allocated memory.
sl@0
   495
sl@0
   496
@param aRegion The region to be intersected with this region.
sl@0
   497
*/
sl@0
   498
	{
sl@0
   499
	if (aRegion.iError)
sl@0
   500
		{
sl@0
   501
		ForceError();
sl@0
   502
		}
sl@0
   503
	else if (!iError && (iCount != 0))
sl@0
   504
		{
sl@0
   505
		if (aRegion.iCount == 0)
sl@0
   506
			{
sl@0
   507
			Clear();
sl@0
   508
			}
sl@0
   509
		else
sl@0
   510
			{
sl@0
   511
			RRegionBuf<ERegionBufSize> temp;
sl@0
   512
			temp.Copy(*this);
sl@0
   513
			Intersection(temp,aRegion);
sl@0
   514
			temp.Close();
sl@0
   515
			}
sl@0
   516
		}
sl@0
   517
	}
sl@0
   518
sl@0
   519
sl@0
   520
sl@0
   521
sl@0
   522
EXPORT_C void TRegion::AddRect(const TRect &aRect)
sl@0
   523
/**
sl@0
   524
Adds a rectangle to this region.
sl@0
   525
sl@0
   526
Notes:
sl@0
   527
sl@0
   528
1. If this region's error flag is already set, this function has no effect.
sl@0
   529
sl@0
   530
2. If the operation causes the capacity of this region to be exceeded, or if 
sl@0
   531
   memory allocation fails, the region is cleared, freeing up any memory which 
sl@0
   532
   has been allocated; its error flag is also set.
sl@0
   533
sl@0
   534
@param aRect The rectangle to be added to this region.
sl@0
   535
*/
sl@0
   536
	{
sl@0
   537
	if (!aRect.IsEmpty() && !iError)
sl@0
   538
		{
sl@0
   539
		TBool doAppend = ETrue;
sl@0
   540
		if (iCount > 0)
sl@0
   541
			{
sl@0
   542
			TRect regRect = BoundingRect();
sl@0
   543
			TRect inter(aRect);
sl@0
   544
			inter.Intersection(regRect);
sl@0
   545
sl@0
   546
			if (!inter.IsEmpty())
sl@0
   547
				{
sl@0
   548
				if ( inter == regRect )
sl@0
   549
					{ // equivalent to IsContainedBy(aRect)
sl@0
   550
					iCount=0;
sl@0
   551
					}
sl@0
   552
				else
sl@0
   553
					{
sl@0
   554
					TBool coversRect = (inter == aRect); // bounding rect of region includes all of aRect?
sl@0
   555
					MergeRect(aRect, coversRect);
sl@0
   556
					doAppend = EFalse;
sl@0
   557
					}
sl@0
   558
				}
sl@0
   559
			}
sl@0
   560
		if (doAppend)
sl@0
   561
			{
sl@0
   562
			AppendRect(aRect);
sl@0
   563
			}
sl@0
   564
sl@0
   565
		// RRegion could have unneeded memory that can be freed
sl@0
   566
		if (!iError && (iAllocedRects > iCount))
sl@0
   567
			{
sl@0
   568
			ShrinkRegion();
sl@0
   569
			}
sl@0
   570
		}
sl@0
   571
	}
sl@0
   572
sl@0
   573
sl@0
   574
sl@0
   575
sl@0
   576
EXPORT_C void TRegion::SubRegion(const TRegion &aRegion,TRegion *aSubtractedRegion)
sl@0
   577
/**
sl@0
   578
Removes a region.
sl@0
   579
sl@0
   580
If there is no area of intersection between the two regions, this region is 
sl@0
   581
unaffected.
sl@0
   582
sl@0
   583
@param aRegion           The region to be removed from this region.
sl@0
   584
                         If aRegion's error flag is set, then this region is
sl@0
   585
                         cleared, freeing up any allocated memory, and the
sl@0
   586
                         error flag is set.
sl@0
   587
@param aSubtractedRegion If specified, then on return contains the area removed 
sl@0
   588
                         from this region.
sl@0
   589
*/
sl@0
   590
	{
sl@0
   591
	SubtractRegion(aRegion, aSubtractedRegion);
sl@0
   592
sl@0
   593
	// RRegion could have unneeded memory that can be freed
sl@0
   594
	if (!iError && (iAllocedRects > iCount))
sl@0
   595
		{
sl@0
   596
		ShrinkRegion();
sl@0
   597
		}
sl@0
   598
	}
sl@0
   599
sl@0
   600
sl@0
   601
/**
sl@0
   602
Removes a region.
sl@0
   603
sl@0
   604
If there is no area of intersection between the two regions, this region is 
sl@0
   605
unaffected.
sl@0
   606
sl@0
   607
@param aRegion           The region to be removed from this region.
sl@0
   608
                         If aRegion's error flag is set, then this region is
sl@0
   609
                         cleared, freeing up any allocated memory, and the
sl@0
   610
                         error flag is set.
sl@0
   611
@param aSubtractedRegion If specified, then on return contains the area removed 
sl@0
   612
                         from this region.
sl@0
   613
*/
sl@0
   614
void TRegion::SubtractRegion(const TRegion &aRegion,TRegion *aSubtractedRegion)
sl@0
   615
	{
sl@0
   616
	if (!iError)
sl@0
   617
		{
sl@0
   618
		if (aRegion.iError)
sl@0
   619
			{
sl@0
   620
			ForceError();
sl@0
   621
			}
sl@0
   622
		else if (iCount != 0)
sl@0
   623
			{
sl@0
   624
			const TRect *pR=aRegion.RectangleList();
sl@0
   625
			const TRect *pE=pR+aRegion.iCount;
sl@0
   626
			while (pR<pE && !iError)
sl@0
   627
				{
sl@0
   628
				SubRect(*pR++, aSubtractedRegion);
sl@0
   629
				}
sl@0
   630
			if (iError && aSubtractedRegion)
sl@0
   631
				{
sl@0
   632
				aSubtractedRegion->ForceError();
sl@0
   633
				}
sl@0
   634
			}
sl@0
   635
		}
sl@0
   636
	}
sl@0
   637
sl@0
   638
sl@0
   639
sl@0
   640
sl@0
   641
#ifndef __REGIONS_MACHINE_CODED__
sl@0
   642
EXPORT_C void TRegion::ClipRect(const TRect &aRect)
sl@0
   643
/**
sl@0
   644
Clips the region to the specified rectangle.
sl@0
   645
sl@0
   646
The resulting region is the area of overlap between the region and the rectangle. 
sl@0
   647
If there is no overlap, all rectangles within this region are deleted and 
sl@0
   648
the resulting region is empty.
sl@0
   649
sl@0
   650
@param aRect The rectangle to which this region is to be clipped.
sl@0
   651
*/
sl@0
   652
	{
sl@0
   653
sl@0
   654
	for (TInt index=0;index<iCount;)
sl@0
   655
		{
sl@0
   656
		TRect *r2=RectangleListW()+index;
sl@0
   657
		if (r2->iTl.iX<aRect.iTl.iX)
sl@0
   658
			r2->iTl.iX=aRect.iTl.iX;
sl@0
   659
		if (r2->iTl.iY<aRect.iTl.iY)
sl@0
   660
			r2->iTl.iY=aRect.iTl.iY;
sl@0
   661
		if (r2->iBr.iX>aRect.iBr.iX)
sl@0
   662
			r2->iBr.iX=aRect.iBr.iX;
sl@0
   663
		if (r2->iBr.iY>aRect.iBr.iY)
sl@0
   664
			r2->iBr.iY=aRect.iBr.iY;
sl@0
   665
		if (r2->IsEmpty())
sl@0
   666
			DeleteRect(r2);
sl@0
   667
		else
sl@0
   668
			index++;
sl@0
   669
		}
sl@0
   670
	}
sl@0
   671
#endif
sl@0
   672
sl@0
   673
sl@0
   674
sl@0
   675
sl@0
   676
EXPORT_C void TRegion::Clear()
sl@0
   677
/**
sl@0
   678
Clears this region.
sl@0
   679
sl@0
   680
This frees up any memory which has been allocated and unsets the error flag.
sl@0
   681
*/
sl@0
   682
	{
sl@0
   683
sl@0
   684
	if (iAllocedRects>=0)
sl@0
   685
		{
sl@0
   686
		User::Free(((RRegion *)this)->iRectangleList);
sl@0
   687
		((RRegion *)this)->iRectangleList=NULL;
sl@0
   688
		iAllocedRects=0;
sl@0
   689
		}
sl@0
   690
	iCount=0;
sl@0
   691
	iError=EFalse;
sl@0
   692
	}
sl@0
   693
sl@0
   694
sl@0
   695
sl@0
   696
sl@0
   697
sl@0
   698
EXPORT_C void TRegion::Tidy()
sl@0
   699
/**
sl@0
   700
Merges all rectangles within this region which share an adjacent edge of the 
sl@0
   701
same length.
sl@0
   702
sl@0
   703
The function subsequently checks for allocated but unused memory, if this memory is
sl@0
   704
at least as large as the granularity it is released to the system.
sl@0
   705
*/
sl@0
   706
	{
sl@0
   707
	TUint doMore = 2; // need 1 pass each of merging vertical & horizontal edges
sl@0
   708
sl@0
   709
	while ( (iCount > 1) && doMore )
sl@0
   710
		{
sl@0
   711
		// make rows
sl@0
   712
		--doMore;
sl@0
   713
			{
sl@0
   714
			TRect* pFirst = RectangleListW();
sl@0
   715
			TRect* pLast = RectangleListW()+iCount-1;
sl@0
   716
			TRect *pRect1 = pLast;
sl@0
   717
			for (;pRect1 > pFirst; pRect1--)
sl@0
   718
				{
sl@0
   719
				TRect *pRect2 = pRect1-1;
sl@0
   720
				const TInt top = pRect1->iTl.iY;
sl@0
   721
				const TInt bottom = pRect1->iBr.iY;
sl@0
   722
				for (;pRect2 >= pFirst; pRect2--)
sl@0
   723
					{
sl@0
   724
					if ( (top == pRect2->iTl.iY) && (bottom == pRect2->iBr.iY) )
sl@0
   725
						{
sl@0
   726
						if (pRect1->iBr.iX == pRect2->iTl.iX)
sl@0
   727
							{
sl@0
   728
							pRect2->iTl.iX = pRect1->iTl.iX;
sl@0
   729
							}
sl@0
   730
						else if (pRect1->iTl.iX == pRect2->iBr.iX)
sl@0
   731
							{
sl@0
   732
							pRect2->iBr.iX = pRect1->iBr.iX;
sl@0
   733
							}
sl@0
   734
						else
sl@0
   735
							{
sl@0
   736
							continue;
sl@0
   737
							}
sl@0
   738
						}
sl@0
   739
					else
sl@0
   740
						{
sl@0
   741
						continue;
sl@0
   742
						}
sl@0
   743
					// remove merged and move last
sl@0
   744
					if (pRect1 != pLast)
sl@0
   745
						{
sl@0
   746
						*pRect1 = *pLast;
sl@0
   747
						}
sl@0
   748
					--iCount;
sl@0
   749
					--pLast;
sl@0
   750
					doMore = 1;
sl@0
   751
					break;
sl@0
   752
					}
sl@0
   753
				}
sl@0
   754
			}
sl@0
   755
sl@0
   756
		// make columns?
sl@0
   757
		if (doMore)
sl@0
   758
			{
sl@0
   759
			--doMore;
sl@0
   760
			TRect* pFirst = RectangleListW();
sl@0
   761
			TRect* pLast = RectangleListW()+iCount-1;
sl@0
   762
			TRect *pRect1 = pLast;
sl@0
   763
			for (;pRect1 > pFirst; pRect1--)
sl@0
   764
				{
sl@0
   765
				TRect *pRect2 = pRect1-1;
sl@0
   766
				const TInt left = pRect1->iTl.iX;
sl@0
   767
				const TInt right = pRect1->iBr.iX;
sl@0
   768
sl@0
   769
				for (;pRect2 >= pFirst; pRect2--)
sl@0
   770
					{
sl@0
   771
					if ( (left == pRect2->iTl.iX) && (right == pRect2->iBr.iX) )
sl@0
   772
						{
sl@0
   773
						if (pRect1->iBr.iY == pRect2->iTl.iY)
sl@0
   774
							{
sl@0
   775
							pRect2->iTl.iY = pRect1->iTl.iY;
sl@0
   776
							}
sl@0
   777
						else if (pRect1->iTl.iY == pRect2->iBr.iY)
sl@0
   778
							{
sl@0
   779
							pRect2->iBr.iY = pRect1->iBr.iY;
sl@0
   780
							}
sl@0
   781
						else
sl@0
   782
							{
sl@0
   783
							continue;
sl@0
   784
							}
sl@0
   785
						}
sl@0
   786
					else
sl@0
   787
						{
sl@0
   788
						continue;
sl@0
   789
						}
sl@0
   790
					// remove merged
sl@0
   791
					if (pRect1 != pLast)
sl@0
   792
						{
sl@0
   793
						*pRect1 = *pLast;
sl@0
   794
						}
sl@0
   795
					--iCount;
sl@0
   796
					--pLast;
sl@0
   797
					doMore = 1;
sl@0
   798
					break;
sl@0
   799
					}
sl@0
   800
				}
sl@0
   801
			}
sl@0
   802
		}
sl@0
   803
sl@0
   804
	// free space
sl@0
   805
	if (iAllocedRects>iCount)
sl@0
   806
		{
sl@0
   807
		ShrinkRegion();
sl@0
   808
		}
sl@0
   809
	}
sl@0
   810
sl@0
   811
sl@0
   812
sl@0
   813
EXPORT_C TInt TRegion::Sort()
sl@0
   814
/**
sl@0
   815
Sorts the region's array of rectangles according to their vertical position 
sl@0
   816
on the screen.
sl@0
   817
sl@0
   818
The sort uses the bottom right hand corner co-ordinates of the rectangles.
sl@0
   819
The co-ordinates of the top and left hand sides are irrelevant 
sl@0
   820
to the sort operation.
sl@0
   821
sl@0
   822
Higher rectangles take precedence over lower ones. For rectangles at the same 
sl@0
   823
vertical position, the leftmost takes priority.
sl@0
   824
sl@0
   825
Note that the sort order may need to be different from the default if, for example, 
sl@0
   826
a region is moved downwards so that lower non-overlapping rectangles need 
sl@0
   827
to be redrawn (and sorted) before higher ones. In this case, use the second 
sl@0
   828
overload of this function.
sl@0
   829
sl@0
   830
@return KErrNone, if the operation is successful; KErrGeneral, otherwise.
sl@0
   831
*/
sl@0
   832
	{
sl@0
   833
sl@0
   834
	return Sort(TPoint(-1,-1));
sl@0
   835
	}
sl@0
   836
sl@0
   837
sl@0
   838
sl@0
   839
sl@0
   840
EXPORT_C TInt TRegion::Sort(const TPoint &aOffset)
sl@0
   841
//
sl@0
   842
// Sort the region for copying to the same display.
sl@0
   843
//
sl@0
   844
/**
sl@0
   845
Sorts the region's array of rectangles according to a specified sort order.
sl@0
   846
sl@0
   847
The sort uses the bottom right hand co-ordinates of the rectangles.
sl@0
   848
The co-ordinates of the top and left hand sides are irrelevant 
sl@0
   849
to the sort operation
sl@0
   850
sl@0
   851
The order of the sort is determined by whether the iX and iY members of aOffset 
sl@0
   852
are positive, or zero or less. If aOffset.iY is greater than zero,
sl@0
   853
lower rectangles take precedence over higher rectangles in the list order.
sl@0
   854
Otherwise, higher rectangles take precedence. For rectangles of equal height,
sl@0
   855
aOffset.iX becomes relevant to the sort.
sl@0
   856
If is greater than zero, rightmost rectangles
sl@0
   857
take precedence. Otherwise, leftmost rectangles take precedence.
sl@0
   858
sl@0
   859
Note that the sort order may need to be different from the default if,
sl@0
   860
for example, a region is moved downwards so that lower non-overlapping
sl@0
   861
rectangles need to be redrawn (and sorted) before higher ones.
sl@0
   862
sl@0
   863
@param aOffset A point whose iX and iY members determine the order of the 
sl@0
   864
               sort. 
sl@0
   865
sl@0
   866
@return KErrNone, if the operation is successful; KErrGeneral, otherwise.
sl@0
   867
*/
sl@0
   868
	{
sl@0
   869
	TRectKey key(RectangleList(),aOffset);
sl@0
   870
	TRectSwap swap(RectangleListW());
sl@0
   871
	return(User::QuickSort(iCount,key,swap));
sl@0
   872
	}
sl@0
   873
sl@0
   874
sl@0
   875
sl@0
   876
sl@0
   877
EXPORT_C TRect *TRegion::RectangleListW()
sl@0
   878
//
sl@0
   879
// Return a writeable rectangle list.
sl@0
   880
//
sl@0
   881
	{
sl@0
   882
	if (iAllocedRects>=0)
sl@0
   883
		return(((RRegion *)this)->iRectangleList);
sl@0
   884
	else if (iAllocedRects&ERRegionBuf)
sl@0
   885
		return((TRect *)(this+1));
sl@0
   886
	return((TRect *)(((RRegion *)this)+1));
sl@0
   887
	}
sl@0
   888
sl@0
   889
sl@0
   890
/** Ensure that the region is big enough to hold aCount rectangles.
sl@0
   891
sl@0
   892
@param aCount number of rectangles the region is expected to hold
sl@0
   893
@return ETrue if region is big enough, EFalse if fixed size region is too small or alloc failed.
sl@0
   894
*/
sl@0
   895
TBool TRegion::SetListSize(TInt aCount)
sl@0
   896
	{
sl@0
   897
	TInt newAlloc = 0;
sl@0
   898
	if (iAllocedRects < 0)
sl@0
   899
		{
sl@0
   900
		if (aCount > (-(iAllocedRects|ERRegionBuf)))
sl@0
   901
			{
sl@0
   902
			if (iAllocedRects & ERRegionBuf)
sl@0
   903
				{ // TRegionFixed
sl@0
   904
				ForceError();
sl@0
   905
				return EFalse;
sl@0
   906
				}
sl@0
   907
			// successful alloc will change RRegionBuf into RRegion
sl@0
   908
			newAlloc = Max(aCount, ((RRegion *)this)->iGranularity);
sl@0
   909
			}
sl@0
   910
		}
sl@0
   911
	else if (aCount > iAllocedRects)
sl@0
   912
		{
sl@0
   913
		newAlloc = Max(aCount, iAllocedRects + ((RRegion *)this)->iGranularity);
sl@0
   914
		}
sl@0
   915
sl@0
   916
	if (newAlloc > 0)
sl@0
   917
		{
sl@0
   918
		TRect *newList = (TRect *)User::ReAlloc(((RRegion *)this)->iRectangleList, newAlloc*sizeof(TRect));
sl@0
   919
		if (newList == NULL)
sl@0
   920
			{
sl@0
   921
			ForceError();
sl@0
   922
			return EFalse;
sl@0
   923
			}
sl@0
   924
		((RRegion *)this)->iRectangleList = newList;
sl@0
   925
		iAllocedRects = newAlloc;
sl@0
   926
		}
sl@0
   927
	return ETrue;
sl@0
   928
	}
sl@0
   929
sl@0
   930
/** Ensure that the region is big enough to hold aCount rectangles.
sl@0
   931
Any allocation increase is for at least the granularity count of rectangles.
sl@0
   932
Similar to SetListSize, but always preserves existing iCount rectangles.
sl@0
   933
sl@0
   934
@param aCount number of rectangles the region is expected to hold
sl@0
   935
@return NULL if region is not big enough, otherwise pointer to the Rect array.
sl@0
   936
*/
sl@0
   937
TRect* TRegion::ExpandRegion(TInt aCount)
sl@0
   938
	{
sl@0
   939
	TRect *prects=NULL;
sl@0
   940
	if (!iError)
sl@0
   941
		{
sl@0
   942
		if (iAllocedRects & ERRegionBuf)
sl@0
   943
			{							// TRegionFix
sl@0
   944
			if (aCount > -iAllocedRects)
sl@0
   945
				{						// Can't expand a TRegionFix
sl@0
   946
				ForceError();
sl@0
   947
				return NULL;
sl@0
   948
				}
sl@0
   949
			prects=(TRect *)(this+1);
sl@0
   950
			}
sl@0
   951
		else if (iAllocedRects < 0)
sl@0
   952
			{							// RRegionBuf
sl@0
   953
			prects = (TRect *)(((RRegion *)this)+1);
sl@0
   954
			if (aCount > (-(iAllocedRects|ERRegionBuf)))
sl@0
   955
				{
sl@0
   956
				RRegion *pr = (RRegion *)this;
sl@0
   957
				TUint newCount = Max(aCount, iCount + pr->iGranularity);
sl@0
   958
				TRect *newList = (TRect *)User::Alloc(newCount * sizeof(TRect));
sl@0
   959
				if (newList == NULL)
sl@0
   960
					{
sl@0
   961
					ForceError();
sl@0
   962
					return NULL;
sl@0
   963
					}
sl@0
   964
				iAllocedRects = newCount;
sl@0
   965
				pr->iRectangleList = newList;
sl@0
   966
				if (iCount > 0)
sl@0
   967
					{
sl@0
   968
					Mem::Copy(pr->iRectangleList, prects, sizeof(TRect)*iCount);
sl@0
   969
					}
sl@0
   970
				prects = pr->iRectangleList;
sl@0
   971
				}
sl@0
   972
			}
sl@0
   973
		else
sl@0
   974
			{
sl@0
   975
			RRegion *pr = (RRegion *)this;
sl@0
   976
			prects = pr->iRectangleList;
sl@0
   977
			if (iAllocedRects < aCount)
sl@0
   978
				{
sl@0
   979
				TUint newCount = Max(aCount, iAllocedRects + pr->iGranularity);
sl@0
   980
				prects=(TRect *)User::ReAlloc(prects, newCount*sizeof(TRect));
sl@0
   981
				if (prects == NULL)
sl@0
   982
					{
sl@0
   983
					ForceError();
sl@0
   984
					return NULL;
sl@0
   985
					}
sl@0
   986
				iAllocedRects = newCount;
sl@0
   987
				pr->iRectangleList = prects;
sl@0
   988
				}
sl@0
   989
			}
sl@0
   990
		}
sl@0
   991
sl@0
   992
	return prects;
sl@0
   993
	}
sl@0
   994
sl@0
   995
sl@0
   996
/**
sl@0
   997
After an RRegion's iCount has reduced try to release some memory.
sl@0
   998
Hysteresis rule: reduce allocated memory to iCount, but only if 
sl@0
   999
the released memory will also be at least the granularity.
sl@0
  1000
*/
sl@0
  1001
void TRegion::ShrinkRegion()
sl@0
  1002
	{
sl@0
  1003
	ASSERT(iAllocedRects > iCount);
sl@0
  1004
	// must be an RRegion
sl@0
  1005
	RRegion *pr=(RRegion *)this;
sl@0
  1006
	if (iAllocedRects >= (iCount + pr->iGranularity) )
sl@0
  1007
		{
sl@0
  1008
		TRect *newList = NULL;
sl@0
  1009
		if (iCount == 0)
sl@0
  1010
			{
sl@0
  1011
			User::Free(pr->iRectangleList);
sl@0
  1012
			}
sl@0
  1013
		else
sl@0
  1014
			{
sl@0
  1015
			newList = (TRect *)User::ReAlloc(pr->iRectangleList, iCount*sizeof(TRect));
sl@0
  1016
			if (newList == NULL)
sl@0
  1017
				{
sl@0
  1018
				ForceError();
sl@0
  1019
				return;
sl@0
  1020
				}
sl@0
  1021
			}
sl@0
  1022
		iAllocedRects = iCount;
sl@0
  1023
		pr->iRectangleList = newList;
sl@0
  1024
		}
sl@0
  1025
	}
sl@0
  1026
sl@0
  1027
sl@0
  1028
void TRegion::AppendRect(const TRect &aRect)
sl@0
  1029
//
sl@0
  1030
// Add a rectangle to the list.
sl@0
  1031
//
sl@0
  1032
	{
sl@0
  1033
	TRect *prects = ExpandRegion(iCount+1);
sl@0
  1034
	if (prects)
sl@0
  1035
		{
sl@0
  1036
		*(prects+iCount)=aRect;
sl@0
  1037
		iCount++;
sl@0
  1038
		}
sl@0
  1039
	}
sl@0
  1040
sl@0
  1041
sl@0
  1042
#ifndef __REGIONS_MACHINE_CODED__
sl@0
  1043
sl@0
  1044
sl@0
  1045
EXPORT_C void TRegion::ForceError()
sl@0
  1046
/**
sl@0
  1047
Sets the error flag, and clears the region.
sl@0
  1048
sl@0
  1049
This frees up memory allocated to the region.
sl@0
  1050
*/
sl@0
  1051
	{
sl@0
  1052
sl@0
  1053
	Clear();
sl@0
  1054
	iError=ETrue;
sl@0
  1055
	}
sl@0
  1056
sl@0
  1057
void TRegion::DeleteRect(TRect *aRect)
sl@0
  1058
//
sl@0
  1059
// Delete a specific rectangle in the list.
sl@0
  1060
//
sl@0
  1061
	{
sl@0
  1062
sl@0
  1063
	iCount--;
sl@0
  1064
	Mem::Copy(aRect,aRect+1,((TUint8 *)(RectangleList()+iCount))-((TUint8 *)aRect));
sl@0
  1065
	}
sl@0
  1066
#endif
sl@0
  1067
sl@0
  1068
void TRegion::AppendRegion(TRegion &aRegion)
sl@0
  1069
//
sl@0
  1070
// Append all the rectangles from aRegion to this.
sl@0
  1071
//
sl@0
  1072
	{
sl@0
  1073
	aRegion.SubtractRegion(*this);
sl@0
  1074
	if (aRegion.iError)
sl@0
  1075
		{
sl@0
  1076
		ForceError();
sl@0
  1077
		}
sl@0
  1078
	else if (aRegion.iCount > 0)
sl@0
  1079
		{
sl@0
  1080
		// alloc enough memory, then memcpy
sl@0
  1081
		const TInt newCount = iCount + aRegion.iCount;
sl@0
  1082
		if (ExpandRegion(newCount))
sl@0
  1083
			{
sl@0
  1084
			TRect* pDest = RectangleListW() + iCount;
sl@0
  1085
			const TRect* pSource = aRegion.RectangleList();
sl@0
  1086
			Mem::Copy(pDest, pSource, aRegion.iCount * sizeof(TRect));
sl@0
  1087
			iCount = newCount;
sl@0
  1088
			}
sl@0
  1089
		}
sl@0
  1090
	}
sl@0
  1091
sl@0
  1092
sl@0
  1093
sl@0
  1094
EXPORT_C RRegion::RRegion()
sl@0
  1095
	: TRegion(0), iGranularity(EDefaultGranularity), iRectangleList(NULL)
sl@0
  1096
/**
sl@0
  1097
Default constructor.
sl@0
  1098
sl@0
  1099
Initialises its granularity to five.
sl@0
  1100
*/
sl@0
  1101
	{}
sl@0
  1102
sl@0
  1103
sl@0
  1104
sl@0
  1105
sl@0
  1106
EXPORT_C RRegion::RRegion(TInt aGran)
sl@0
  1107
	: TRegion(0), iGranularity(aGran), iRectangleList(NULL)
sl@0
  1108
/**
sl@0
  1109
Constructs the object with the specified granularity.
sl@0
  1110
sl@0
  1111
@param aGran The initial value for the region's granularity.
sl@0
  1112
             This value must not be negative.
sl@0
  1113
*/
sl@0
  1114
	{}
sl@0
  1115
sl@0
  1116
sl@0
  1117
sl@0
  1118
sl@0
  1119
EXPORT_C RRegion::RRegion(const TRect &aRect, TInt aGran)
sl@0
  1120
	: TRegion(0), iGranularity(aGran), iRectangleList(NULL)
sl@0
  1121
/**
sl@0
  1122
Constructs the object with the specified rectangle and granularity.
sl@0
  1123
sl@0
  1124
The resulting region consists of the specified single rectangle.
sl@0
  1125
sl@0
  1126
@param aRect The single rectangle with which to initialise the region 
sl@0
  1127
@param aGran The initial value for the region's granularity. By default, 
sl@0
  1128
             this is five.
sl@0
  1129
*/
sl@0
  1130
	{
sl@0
  1131
sl@0
  1132
	if (!aRect.IsEmpty())
sl@0
  1133
		AppendRect(aRect);
sl@0
  1134
	}
sl@0
  1135
sl@0
  1136
sl@0
  1137
sl@0
  1138
sl@0
  1139
EXPORT_C RRegion::RRegion(const RRegion &aRegion)
sl@0
  1140
/**
sl@0
  1141
Copy constructor.
sl@0
  1142
sl@0
  1143
Constructs a new region from an existing one by performing a bit-wise copy.  Both the new and
sl@0
  1144
existing regions are left containing pointers to the same data, so Close() must only be called on
sl@0
  1145
one of them.
sl@0
  1146
sl@0
  1147
Use of this method is not recommended.
sl@0
  1148
sl@0
  1149
@param aRegion The region to be copied.
sl@0
  1150
*/
sl@0
  1151
	{
sl@0
  1152
	*this=aRegion;
sl@0
  1153
	}
sl@0
  1154
sl@0
  1155
sl@0
  1156
sl@0
  1157
sl@0
  1158
EXPORT_C RRegion::RRegion(TInt aBuf, TInt aGran)
sl@0
  1159
//
sl@0
  1160
// Constructor.
sl@0
  1161
//
sl@0
  1162
	: TRegion(aBuf), iGranularity(aGran), iRectangleList(NULL)
sl@0
  1163
	{}
sl@0
  1164
sl@0
  1165
sl@0
  1166
sl@0
  1167
sl@0
  1168
EXPORT_C RRegion::RRegion(TInt aCount,TRect* aRectangleList,TInt aGran/*=EDefaultGranularity*/)
sl@0
  1169
/**
sl@0
  1170
Constructor that takes ownership of an already created rectangle list.
sl@0
  1171
sl@0
  1172
@param aCount         The number of rectangles in the region.
sl@0
  1173
@param aRectangleList A pointer to the set of rectangles.
sl@0
  1174
@param aGran          The region's granularity.
sl@0
  1175
*/
sl@0
  1176
	: TRegion(aCount), iGranularity(aGran), iRectangleList(aRectangleList)
sl@0
  1177
	{
sl@0
  1178
	iCount=aCount;
sl@0
  1179
	}
sl@0
  1180
sl@0
  1181
sl@0
  1182
sl@0
  1183
sl@0
  1184
EXPORT_C void RRegion::Close()
sl@0
  1185
/**
sl@0
  1186
Closes the region.
sl@0
  1187
sl@0
  1188
Frees up any memory which has been allocated, and unsets the error flag, if 
sl@0
  1189
set. 
sl@0
  1190
sl@0
  1191
The region can be re-used after calling this method.  Its granularity is preserved.
sl@0
  1192
*/
sl@0
  1193
	{
sl@0
  1194
sl@0
  1195
	Clear();
sl@0
  1196
	}
sl@0
  1197
sl@0
  1198
sl@0
  1199
sl@0
  1200
sl@0
  1201
EXPORT_C void RRegion::Destroy()
sl@0
  1202
//
sl@0
  1203
// Destroy
sl@0
  1204
//
sl@0
  1205
/**
sl@0
  1206
Deletes the region.
sl@0
  1207
sl@0
  1208
Frees all memory.
sl@0
  1209
sl@0
  1210
Note this method will delete the RRegion object and therefore it should not be 
sl@0
  1211
invoked on RRegion objects that are not allocated on the heap.  RRegion::Close()
sl@0
  1212
should be used for RRegion objects stored on the stack.
sl@0
  1213
sl@0
  1214
@panic USER 42 if the RRegion object is stored on the stack.
sl@0
  1215
*/
sl@0
  1216
	{
sl@0
  1217
sl@0
  1218
	Clear();
sl@0
  1219
	delete this;
sl@0
  1220
	}
sl@0
  1221
sl@0
  1222
sl@0
  1223
sl@0
  1224
sl@0
  1225
TInt TRectKey::Compare(TInt aLeft,TInt aRight) const
sl@0
  1226
//
sl@0
  1227
// Compares two rectangles for partial ordering.
sl@0
  1228
//
sl@0
  1229
	{
sl@0
  1230
sl@0
  1231
	if (aLeft==aRight)
sl@0
  1232
		return(0);
sl@0
  1233
	const TRect *r1=&iRectList[aLeft];
sl@0
  1234
	const TRect *r2=&iRectList[aRight];
sl@0
  1235
	if (r2->iBr.iY<=r1->iTl.iY)
sl@0
  1236
		return(iDown ? -1 : 1);
sl@0
  1237
	if (r1->iBr.iY<=r2->iTl.iY)
sl@0
  1238
		return(iDown ? 1 : -1);
sl@0
  1239
	if (r2->iBr.iX<=r1->iTl.iX)
sl@0
  1240
		return(iRight ? -1 : 1);
sl@0
  1241
	__ASSERT_DEBUG(r1->iBr.iX<=r2->iTl.iX,Panic(ETRegionInvalidRegionInSort));
sl@0
  1242
	return(iRight ? 1 : -1);
sl@0
  1243
	}
sl@0
  1244
sl@0
  1245
void TRectSwap::Swap(TInt aLeft,TInt aRight) const
sl@0
  1246
//
sl@0
  1247
// Swap two rectangles.
sl@0
  1248
//
sl@0
  1249
	{
sl@0
  1250
sl@0
  1251
	TRect tmp(iRectList[aLeft]);
sl@0
  1252
	iRectList[aLeft]=iRectList[aRight];
sl@0
  1253
	iRectList[aRight]=tmp;
sl@0
  1254
	}
sl@0
  1255
sl@0
  1256
TRectKey::TRectKey(const TRect *aRectList,const TPoint &aOffset)
sl@0
  1257
//
sl@0
  1258
// Rectangle key constructor
sl@0
  1259
//
sl@0
  1260
	{
sl@0
  1261
sl@0
  1262
	iRectList=aRectList;
sl@0
  1263
	if(aOffset.iX>0)
sl@0
  1264
		iRight=ETrue;
sl@0
  1265
	else
sl@0
  1266
		iRight=EFalse;
sl@0
  1267
	if(aOffset.iY>0)
sl@0
  1268
		iDown=ETrue;
sl@0
  1269
	else
sl@0
  1270
		iDown=EFalse;
sl@0
  1271
	}