symport/e32/euser/us_regn.cpp
changeset 1 0a7b44b10206
child 2 806186ab5e14
equal deleted inserted replaced
0:c55016431358 1:0a7b44b10206
       
     1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\euser\us_regn.cpp
       
    15 // Optimisation note, it may well be worth machine coding the SubRect() function
       
    16 // this is at the heart of nearly all complex region calculations.
       
    17 // 
       
    18 //
       
    19 
       
    20 
       
    21 #include "us_std.h"
       
    22 
       
    23 NONSHARABLE_CLASS(TRectKey) : public TKey
       
    24 	{
       
    25 public:
       
    26 	TRectKey(const TRect *aRectList,const TPoint &aOffset);
       
    27 	virtual TInt Compare(TInt aLeft,TInt aRight) const;
       
    28 private:
       
    29 	const TRect *iRectList;
       
    30 	TBool iDown;
       
    31 	TBool iRight;
       
    32 	};
       
    33 
       
    34 NONSHARABLE_CLASS(TRectSwap) : public TSwap
       
    35 	{
       
    36 public:
       
    37 	inline TRectSwap(TRect *aRectList);
       
    38 	virtual void Swap(TInt aLeft,TInt aRight) const;
       
    39 private:
       
    40 	TRect *iRectList;
       
    41 	};
       
    42 
       
    43 inline TRectSwap::TRectSwap(TRect *aRectList)
       
    44 	{iRectList=aRectList;}
       
    45 
       
    46 enum {ERegionBufSize=8};
       
    47 
       
    48 EXPORT_C TRegion::TRegion(TInt aAllocedRects)
       
    49 //
       
    50 // Constructor.
       
    51 //
       
    52 	: iCount(0),iError(EFalse),iAllocedRects(aAllocedRects)
       
    53 	{}
       
    54 
       
    55 
       
    56 
       
    57 
       
    58 EXPORT_C TBool TRegion::IsEmpty() const
       
    59 /**
       
    60 Tests whether the region is empty.
       
    61 
       
    62 @return True, if the region is empty and its error flag is unset;
       
    63         false, otherwise.
       
    64 */
       
    65 	{
       
    66 
       
    67 	return(iCount==0 && !iError);
       
    68 	}
       
    69 
       
    70 
       
    71 
       
    72 
       
    73 #ifndef __REGIONS_MACHINE_CODED__
       
    74 EXPORT_C TRect TRegion::BoundingRect() const
       
    75 /**
       
    76 Gets the minimal rectangle that bounds the entire region.
       
    77 
       
    78 @return The region's minimal bounding rectangle.
       
    79 */
       
    80 	{
       
    81 
       
    82 	TRect bounds;
       
    83     const TRect *pRect;
       
    84 	const TRect *pEnd;
       
    85 	if (iCount>0)
       
    86 		{
       
    87 		pRect=RectangleList();
       
    88 		bounds=(*pRect++);
       
    89 		for (pEnd=pRect+(iCount-1);pRect<pEnd;pRect++)
       
    90 			{
       
    91 			if (pRect->iTl.iX<bounds.iTl.iX)
       
    92 				bounds.iTl.iX=pRect->iTl.iX;
       
    93 			if (pRect->iTl.iY<bounds.iTl.iY)
       
    94 				bounds.iTl.iY=pRect->iTl.iY;
       
    95 			if (pRect->iBr.iX>bounds.iBr.iX)
       
    96 				bounds.iBr.iX=pRect->iBr.iX;
       
    97 			if (pRect->iBr.iY>bounds.iBr.iY)
       
    98 				bounds.iBr.iY=pRect->iBr.iY;
       
    99 			}
       
   100 		}
       
   101 	return(bounds);
       
   102 	}	
       
   103 #endif
       
   104 
       
   105 
       
   106 
       
   107 
       
   108 EXPORT_C const TRect &TRegion::operator[](TInt aIndex) const
       
   109 /**
       
   110 Gets a rectangle from the region.
       
   111 
       
   112 @param aIndex The index of a rectangle within the region's array of rectangles. 
       
   113               Indexes are relative to zero.
       
   114               
       
   115 @return The specified rectangle.              
       
   116               
       
   117 @panic USER 81, if aIndex is greater than or equal to the number 
       
   118                 of rectangles in the region.
       
   119 */
       
   120 	{
       
   121 
       
   122 	__ASSERT_ALWAYS((TUint)aIndex<(TUint)iCount,Panic(ETRegionOutOfRange));
       
   123     return(*(RectangleList()+aIndex));
       
   124     }
       
   125 
       
   126 
       
   127 
       
   128 
       
   129 #ifndef __REGIONS_MACHINE_CODED__
       
   130 EXPORT_C TBool TRegion::IsContainedBy(const TRect &aRect) const
       
   131 /**
       
   132 Tests whether the region is fully enclosed within the specified rectangle.
       
   133 
       
   134 @param aRect The specified rectangle.
       
   135  
       
   136 @return True, if the region is fully enclosed within the rectangle (their sides 
       
   137         may touch); false, otherwise.
       
   138 */
       
   139 	{
       
   140 
       
   141     const TRect *pRect1;
       
   142     const TRect *pEnd1;
       
   143 	for (pRect1=RectangleList(),pEnd1=pRect1+iCount;pRect1<pEnd1;pRect1++)
       
   144 		{
       
   145 		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)
       
   146 			return(EFalse);
       
   147 		}
       
   148 	return(ETrue);
       
   149 	}
       
   150 
       
   151 
       
   152 
       
   153 
       
   154 EXPORT_C TBool TRegion::Intersects(const TRect &aRect) const
       
   155 /**
       
   156 Tests whether where there is any intersection between this region and the specified rectangle.
       
   157 
       
   158 @param aRect The specified rectangle.
       
   159  
       
   160 @return True, if there is an intersection; false, otherwise.
       
   161 */
       
   162 	{
       
   163 
       
   164     const TRect *pRect1;
       
   165     const TRect *pEnd1;
       
   166 	for (pRect1=RectangleList(),pEnd1=pRect1+iCount;pRect1<pEnd1;pRect1++)
       
   167 		{
       
   168 		if (aRect.Intersects(*pRect1))
       
   169 			return ETrue;
       
   170 		}
       
   171 	return EFalse;
       
   172 	}
       
   173 
       
   174 
       
   175 
       
   176 
       
   177 EXPORT_C void TRegion::Copy(const TRegion &aRegion)
       
   178 /**
       
   179 Copies another region to this region.
       
   180 
       
   181 The state of the specified region's error flag is also copied.
       
   182 
       
   183 @param aRegion The region to be copied.
       
   184 */
       
   185 	{
       
   186 
       
   187 	if (aRegion.iError)
       
   188 		ForceError();
       
   189 	else
       
   190 		{
       
   191 		if (iError)
       
   192 			Clear();
       
   193 		if (SetListSize(aRegion.iCount))
       
   194 			{
       
   195 			iCount=aRegion.iCount;
       
   196 			Mem::Copy(RectangleListW(), aRegion.RectangleList(), sizeof(TRect)*aRegion.iCount);
       
   197 			}
       
   198 		}
       
   199 	}
       
   200 
       
   201 
       
   202 
       
   203 
       
   204 EXPORT_C void TRegion::Offset(const TPoint &aOffset)
       
   205 /**
       
   206 Moves the region by adding a TPoint offset to the co-ordinates of its corners.
       
   207 	
       
   208 The size of the region is not changed.
       
   209 	
       
   210 @param aOffset The offset by which the region is moved. The region is moved 
       
   211                horizontally by aOffset.iX pixels and vertically by aOffset.iY pixels.
       
   212 */
       
   213  	{
       
   214 
       
   215 	TRect *pR=RectangleListW();
       
   216 	const TRect *pE=pR+iCount;
       
   217 	while (pR<pE)
       
   218 		{
       
   219 		pR->Move(aOffset);
       
   220 		pR++;
       
   221 		}
       
   222 	}
       
   223 
       
   224 
       
   225 
       
   226 
       
   227 EXPORT_C void TRegion::Offset(TInt aXoffset,TInt aYoffset)
       
   228 /**
       
   229 Moves the region by adding X and Y offsets to the co-ordinates of its corners.
       
   230 	
       
   231 The size of the region is not changed.
       
   232 	
       
   233 @param aXoffset The number of pixels by which to move the region horizontally. 
       
   234                 If negative, the region moves leftwards. 
       
   235 @param aYoffset The number of pixels by which to move the region vertically. 
       
   236                 If negative, the region moves upwards.
       
   237 */
       
   238 	{
       
   239 
       
   240 	Offset(TPoint(aXoffset,aYoffset));
       
   241 	}
       
   242 
       
   243 
       
   244 
       
   245 
       
   246 EXPORT_C TBool TRegion::Contains(const TPoint &aPoint) const
       
   247 /**
       
   248 Tests whether a point is located within the region.
       
   249 
       
   250 If the point is located on the top or left hand side of any rectangle in the 
       
   251 region, it is considered to be within that rectangle and within the region. 
       
   252 
       
   253 If the point is located on the right hand side or bottom of a rectangle, it 
       
   254 is considered to be outside that rectangle, and may be outside the region.
       
   255 
       
   256 @param aPoint The specified point. 
       
   257 
       
   258 @return True, if the point is within the region; false, otherwise.
       
   259 */
       
   260 	{
       
   261 	const TRect *pR=RectangleList();
       
   262 	const TRect *pE=pR+iCount;
       
   263 	while (pR<pE)
       
   264 		{
       
   265 		if (pR->Contains(aPoint))
       
   266 			return(ETrue);
       
   267 		pR++;
       
   268 		}
       
   269 	return(EFalse);
       
   270 	}
       
   271 
       
   272 
       
   273 
       
   274 
       
   275 EXPORT_C void TRegion::SubRect(const TRect &aRect,TRegion *aSubtractedRegion)
       
   276 /**
       
   277 Removes a rectangle from this region.
       
   278 
       
   279 If there is no intersection between the rectangle and this region, then this 
       
   280 region is unaffected. 
       
   281 
       
   282 @param aRect             The rectangular area to be removed from this region. 
       
   283 @param aSubtractedRegion A pointer to a region. If this is supplied, the
       
   284                          removed rectangle is added to it. By default this
       
   285                          pointer is NULL.
       
   286 */
       
   287 	{
       
   288 	if (aRect.IsEmpty())
       
   289 		return;
       
   290 	TRect *prect=RectangleListW();
       
   291 	TInt limit=iCount;
       
   292 	for (TInt index=0;index<limit;)
       
   293 		{
       
   294 		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)
       
   295 			{
       
   296 			TRect rect(*prect);
       
   297 			TRect inter(aRect);
       
   298 			inter.Intersection(*prect);
       
   299 			DeleteRect(prect);
       
   300 			if (inter.iBr.iY!=rect.iBr.iY)
       
   301 				AppendRect(TRect(rect.iTl.iX,inter.iBr.iY,rect.iBr.iX,rect.iBr.iY));
       
   302 			if (inter.iTl.iY!=rect.iTl.iY)
       
   303 				AppendRect(TRect(rect.iTl.iX,rect.iTl.iY,rect.iBr.iX,inter.iTl.iY));
       
   304 			if (inter.iBr.iX!=rect.iBr.iX)
       
   305 				AppendRect(TRect(inter.iBr.iX,inter.iTl.iY,rect.iBr.iX,inter.iBr.iY));
       
   306 			if (inter.iTl.iX!=rect.iTl.iX)
       
   307 				AppendRect(TRect(rect.iTl.iX,inter.iTl.iY,inter.iTl.iX,inter.iBr.iY));
       
   308 			if (iError)
       
   309 				break;
       
   310 			if (aSubtractedRegion!=NULL)
       
   311 				aSubtractedRegion->AddRect(inter);
       
   312 			prect=RectangleListW()+index;		// List might have been re-allocated so re-get the pointer
       
   313 			limit--;
       
   314 			}
       
   315 		else
       
   316 			{
       
   317 			index++;
       
   318 			prect++;
       
   319 			}
       
   320 		}
       
   321 	}
       
   322 #endif
       
   323 
       
   324 
       
   325 
       
   326 
       
   327 EXPORT_C void TRegion::Union(const TRegion &aRegion)
       
   328 /**
       
   329 Replaces this region with the union of it and the specified region.
       
   330 
       
   331 Note that if the error flag of either this region or the specified region is
       
   332 set, then this region is cleared and its error flag is set. This frees up
       
   333 allocated memory.
       
   334 
       
   335 @param aRegion The region to be joined to this region.
       
   336 */
       
   337 	{
       
   338 	RRegionBuf<ERegionBufSize> temp;
       
   339 	temp.Copy(aRegion);
       
   340 	if (temp.iCount>iCount)
       
   341 		{
       
   342 		temp.AppendRegion(*this);
       
   343 		Copy(temp);
       
   344 		}
       
   345 	else
       
   346 		AppendRegion(temp);
       
   347 	temp.Close();
       
   348 	}
       
   349 
       
   350 
       
   351 
       
   352 
       
   353 #ifndef __REGIONS_MACHINE_CODED__
       
   354 EXPORT_C void TRegion::Intersection(const TRegion &aRegion1,const TRegion &aRegion2)
       
   355 /**
       
   356 Replaces this region with the area of intersection between two specified regions.
       
   357 	
       
   358 Notes:
       
   359 	
       
   360 1. If the error flag of either of the two specified regions is set, then this 
       
   361    region is cleared and its error flag is set. This frees up allocated memory.
       
   362 	
       
   363 2. If this region's error flag is already set, then the function has no effect.
       
   364 	
       
   365 @param aRegion1 The first region. 
       
   366 @param aRegion2 The second region.
       
   367 */
       
   368     {
       
   369 	if (aRegion1.iError || aRegion2.iError)
       
   370 		ForceError();
       
   371 	else
       
   372 		{
       
   373 		iCount=0;
       
   374 		const TRect *pRect1,*pEnd1;
       
   375 		const TRect *pRect2,*pEnd2;
       
   376 		for (pRect1=aRegion1.RectangleList(),pEnd1=pRect1+aRegion1.iCount;pRect1<pEnd1;pRect1++)
       
   377 			{
       
   378 			for (pRect2=aRegion2.RectangleList(),pEnd2=pRect2+aRegion2.iCount;pRect2<pEnd2;pRect2++)
       
   379 				{
       
   380 				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)
       
   381 					{
       
   382 					TRect rect(*pRect2);
       
   383 					rect.Intersection(*pRect1);
       
   384 					AppendRect(rect);
       
   385 					}
       
   386 				}
       
   387 			}
       
   388 		}
       
   389 	}
       
   390 #endif
       
   391 
       
   392 
       
   393 
       
   394 
       
   395 EXPORT_C void TRegion::Intersect(const TRegion &aRegion)
       
   396 /**
       
   397 Replaces this region with the area of intersection between it and the specified 
       
   398 region.
       
   399 
       
   400 Note that if the error flag of either this region or the specified region is
       
   401 set, then this region is cleared and its error flag is set. This frees up
       
   402 allocated memory.
       
   403 
       
   404 @param aRegion The region to be intersected with this region.
       
   405 */
       
   406 	{
       
   407 	if (iCount!=0)
       
   408 		{
       
   409 		RRegionBuf<ERegionBufSize> temp;
       
   410 		temp.Copy(*this);
       
   411 		Intersection(temp,aRegion);
       
   412 		temp.Close();
       
   413 		}
       
   414 	}
       
   415 
       
   416 
       
   417 
       
   418 
       
   419 EXPORT_C void TRegion::AddRect(const TRect &aRect)
       
   420 /**
       
   421 Adds a rectangle to this region.
       
   422 
       
   423 Notes:
       
   424 
       
   425 1. If this region's error flag is already set, this function has no effect.
       
   426 
       
   427 2. If the operation causes the capacity of this region to be exceeded, or if 
       
   428    memory allocation fails, the region is cleared, freeing up any memory which 
       
   429    has been allocated; its error flag is also set.
       
   430 
       
   431 @param aRect The rectangle to be added to this region.
       
   432 */
       
   433 	{
       
   434 
       
   435 	if (!aRect.IsEmpty() && !iError)
       
   436 		{
       
   437 		if (IsContainedBy(aRect))
       
   438 			{
       
   439 			iCount=0;
       
   440 			AppendRect(aRect);
       
   441 			}
       
   442 		else
       
   443 			{
       
   444 			RRegionBuf<ERegionBufSize> temp(aRect);
       
   445 			AppendRegion(temp);
       
   446 			temp.Close();
       
   447 			}
       
   448 		}
       
   449 	}
       
   450 
       
   451 
       
   452 
       
   453 
       
   454 EXPORT_C void TRegion::SubRegion(const TRegion &aRegion,TRegion *aSubtractedRegion)
       
   455 /**
       
   456 Removes a region.
       
   457 
       
   458 If there is no area of intersection between the two regions, this region is 
       
   459 unaffected.
       
   460 
       
   461 @param aRegion           The region to be removed from this region.
       
   462                          If aRegion's error flag is set, then this region is
       
   463                          cleared, freeing up any allocated memory, and the
       
   464                          error flag is set.
       
   465 @param aSubtractedRegion If specified, then on return contains the area removed 
       
   466                          from this region.
       
   467 */
       
   468 	{
       
   469 	if (iCount!=0)
       
   470 		{
       
   471 		if (aRegion.iError)
       
   472 			ForceError();
       
   473 		else
       
   474 			{
       
   475 			const TRect *pR=aRegion.RectangleList();
       
   476 			const TRect *pE=pR+aRegion.iCount;
       
   477 			while (pR<pE && !iError)
       
   478 				SubRect(*pR++,aSubtractedRegion);
       
   479 			if (iError && aSubtractedRegion)
       
   480 				aSubtractedRegion->ForceError();
       
   481 			}
       
   482 		}
       
   483 	}
       
   484 
       
   485 
       
   486 
       
   487 
       
   488 #ifndef __REGIONS_MACHINE_CODED__
       
   489 EXPORT_C void TRegion::ClipRect(const TRect &aRect)
       
   490 /**
       
   491 Clips the region to the specified rectangle.
       
   492 
       
   493 The resulting region is the area of overlap between the region and the rectangle. 
       
   494 If there is no overlap, all rectangles within this region are deleted and 
       
   495 the resulting region is empty.
       
   496 
       
   497 @param aRect The rectangle to which this region is to be clipped.
       
   498 */
       
   499 	{
       
   500 
       
   501 	for (TInt index=0;index<iCount;)
       
   502 		{
       
   503 		TRect *r2=RectangleListW()+index;
       
   504 		if (r2->iTl.iX<aRect.iTl.iX)
       
   505 			r2->iTl.iX=aRect.iTl.iX;
       
   506 		if (r2->iTl.iY<aRect.iTl.iY)
       
   507 			r2->iTl.iY=aRect.iTl.iY;
       
   508 		if (r2->iBr.iX>aRect.iBr.iX)
       
   509 			r2->iBr.iX=aRect.iBr.iX;
       
   510 		if (r2->iBr.iY>aRect.iBr.iY)
       
   511 			r2->iBr.iY=aRect.iBr.iY;
       
   512 		if (r2->IsEmpty())
       
   513 			DeleteRect(r2);
       
   514 		else
       
   515 			index++;
       
   516 		}
       
   517 	}
       
   518 #endif
       
   519 
       
   520 
       
   521 
       
   522 
       
   523 EXPORT_C void TRegion::Clear()
       
   524 /**
       
   525 Clears this region.
       
   526 
       
   527 This frees up any memory which has been allocated and unsets the error flag.
       
   528 */
       
   529 	{
       
   530 
       
   531 	if (iAllocedRects>=0)
       
   532 		{
       
   533 		User::Free(((RRegion *)this)->iRectangleList);
       
   534 		((RRegion *)this)->iRectangleList=NULL;
       
   535 		iAllocedRects=0;
       
   536 		}
       
   537 	iCount=0;
       
   538 	iError=EFalse;
       
   539 	}
       
   540 
       
   541 
       
   542 
       
   543 
       
   544 
       
   545 #ifndef __REGIONS_MACHINE_CODED__
       
   546 EXPORT_C void TRegion::Tidy()
       
   547 /**
       
   548 Merges all rectangles within this region which share an adjacent edge of the 
       
   549 same length.
       
   550 
       
   551 The function subsequently frees up any allocated but unused memory.
       
   552 */
       
   553 	{
       
   554 restart:
       
   555 	if (iCount>1)
       
   556 		{
       
   557 		const TRect *pEnd1=RectangleList()+iCount-1;
       
   558 		const TRect *pEnd2=RectangleList()+iCount;
       
   559 		TRect *pRect1=RectangleListW();
       
   560 		for (;pRect1<pEnd1;pRect1++)
       
   561 			{
       
   562 			TRect *pRect2=pRect1+1;
       
   563 			for (;pRect2<pEnd2;pRect2++)
       
   564 				{
       
   565 				if (pRect1->iTl.iX==pRect2->iTl.iX && pRect1->iBr.iX==pRect2->iBr.iX)
       
   566 					{
       
   567 					if (pRect1->iBr.iY==pRect2->iTl.iY)
       
   568 						pRect1->iBr.iY=pRect2->iBr.iY;
       
   569 					else if (pRect1->iTl.iY==pRect2->iBr.iY)
       
   570 						pRect1->iTl.iY=pRect2->iTl.iY;
       
   571 					else
       
   572 						continue;
       
   573 					}
       
   574 				else if (pRect1->iTl.iY==pRect2->iTl.iY && pRect1->iBr.iY==pRect2->iBr.iY)
       
   575 					{
       
   576 					if (pRect1->iBr.iX==pRect2->iTl.iX)
       
   577 						pRect1->iBr.iX=pRect2->iBr.iX;
       
   578 					else if (pRect1->iTl.iX==pRect2->iBr.iX)
       
   579 						pRect1->iTl.iX=pRect2->iTl.iX;
       
   580 					else
       
   581 						continue;
       
   582 					}
       
   583 				else
       
   584 					continue;
       
   585 				DeleteRect(pRect2);
       
   586 				goto restart;
       
   587 				}
       
   588 			}
       
   589 		}
       
   590 	if (iAllocedRects>iCount)
       
   591 		{
       
   592 		TRect *newList=(TRect *)User::ReAlloc(((RRegion *)this)->iRectangleList,iCount*sizeof(TRect));
       
   593 		if (newList!=NULL)
       
   594 			{
       
   595 			iAllocedRects=iCount;
       
   596 			((RRegion *)this)->iRectangleList=newList;
       
   597 			}
       
   598 		}
       
   599 	}
       
   600 #endif
       
   601 
       
   602 
       
   603 
       
   604 
       
   605 EXPORT_C TInt TRegion::Sort()
       
   606 /**
       
   607 Sorts the region's array of rectangles according to their vertical position 
       
   608 on the screen.
       
   609 
       
   610 The sort uses the bottom right hand corner co-ordinates of the rectangles.
       
   611 The co-ordinates of the top and left hand sides are irrelevant 
       
   612 to the sort operation.
       
   613 
       
   614 Higher rectangles take precedence over lower ones. For rectangles at the same 
       
   615 vertical position, the leftmost takes priority.
       
   616 
       
   617 Note that the sort order may need to be different from the default if, for example, 
       
   618 a region is moved downwards so that lower non-overlapping rectangles need 
       
   619 to be redrawn (and sorted) before higher ones. In this case, use the second 
       
   620 overload of this function.
       
   621 
       
   622 @return KErrNone, if the operation is successful; KErrGeneral, otherwise.
       
   623 */
       
   624 	{
       
   625 
       
   626 	return Sort(TPoint(-1,-1));
       
   627 	}
       
   628 
       
   629 
       
   630 
       
   631 
       
   632 EXPORT_C TInt TRegion::Sort(const TPoint &aOffset)
       
   633 //
       
   634 // Sort the region for copying to the same display.
       
   635 //
       
   636 /**
       
   637 Sorts the region's array of rectangles according to a specified sort order.
       
   638 
       
   639 The sort uses the bottom right hand co-ordinates of the rectangles.
       
   640 The co-ordinates of the top and left hand sides are irrelevant 
       
   641 to the sort operation
       
   642 
       
   643 The order of the sort is determined by whether the iX and iY members of aOffset 
       
   644 are positive, or zero or less. If aOffset.iY is greater than zero,
       
   645 lower rectangles take precedence over higher rectangles in the list order.
       
   646 Otherwise, higher rectangles take precedence. For rectangles of equal height,
       
   647 aOffset.iX becomes relevant to the sort.
       
   648 If is greater than zero, rightmost rectangles
       
   649 take precedence. Otherwise, leftmost rectangles take precedence.
       
   650 
       
   651 Note that the sort order may need to be different from the default if,
       
   652 for example, a region is moved downwards so that lower non-overlapping
       
   653 rectangles need to be redrawn (and sorted) before higher ones.
       
   654 
       
   655 @param aOffset A point whose iX and iY members determine the order of the 
       
   656                sort. 
       
   657 
       
   658 @return KErrNone, if the operation is successful; KErrGeneral, otherwise.
       
   659 */
       
   660 	{
       
   661 	TRectKey key(RectangleList(),aOffset);
       
   662 	TRectSwap swap(RectangleListW());
       
   663 	return(User::QuickSort(iCount,key,swap));
       
   664 	}
       
   665 
       
   666 
       
   667 
       
   668 
       
   669 EXPORT_C TRect *TRegion::RectangleListW()
       
   670 //
       
   671 // Return a writeable rectangle list.
       
   672 //
       
   673 	{
       
   674 	if (iAllocedRects>=0)
       
   675 		return(((RRegion *)this)->iRectangleList);
       
   676 	else if (iAllocedRects&ERRegionBuf)
       
   677 		return((TRect *)(this+1));
       
   678 	return((TRect *)(((RRegion *)this)+1));
       
   679 	}
       
   680 
       
   681 TBool TRegion::SetListSize(TInt aCount)
       
   682 	{
       
   683 	if (iAllocedRects<0)
       
   684 		{
       
   685 		if (aCount>(-(iAllocedRects|ERRegionBuf)))
       
   686 			{
       
   687 			if ((iAllocedRects&ERRegionBuf) ||
       
   688 				(((RRegion *)this)->iRectangleList=
       
   689 				(TRect *)User::Alloc(aCount*sizeof(TRect)))==NULL)
       
   690 				{
       
   691 				ForceError();
       
   692 				return(EFalse);
       
   693 				}
       
   694 			iAllocedRects=aCount;
       
   695 			}
       
   696 		}
       
   697 	else if (iAllocedRects<aCount)
       
   698 		{
       
   699 		TRect *newList=(TRect *)User::ReAlloc(((RRegion *)this)->iRectangleList,aCount*sizeof(TRect));
       
   700 		if (newList==NULL)
       
   701 			{
       
   702 			ForceError();
       
   703 			return(EFalse);
       
   704 			}
       
   705 		((RRegion *)this)->iRectangleList=newList;
       
   706 		iAllocedRects=aCount;
       
   707 		}
       
   708 	return(ETrue);
       
   709 	}
       
   710 
       
   711 #ifndef __REGIONS_MACHINE_CODED__
       
   712 
       
   713 EXPORT_C void TRegion::ForceError()
       
   714 /**
       
   715 Sets the error flag, and clears the region.
       
   716 
       
   717 This frees up memory allocated to the region.
       
   718 */
       
   719 	{
       
   720 
       
   721 	Clear();
       
   722 	iError=ETrue;
       
   723 	}
       
   724 
       
   725 void TRegion::AppendRect(const TRect &aRect)
       
   726 //
       
   727 // Add a rectangle to the list.
       
   728 //
       
   729 	{
       
   730 	if (!iError)
       
   731 		{
       
   732 		TRect *prects=NULL;
       
   733 		if (iAllocedRects&ERRegionBuf)
       
   734 			{							// TRegionFix
       
   735 			if (iCount==-iAllocedRects)
       
   736 				{						// Can't expand a TRegionFix
       
   737 				ForceError();
       
   738 				return;
       
   739 				}
       
   740 			prects=(TRect *)(this+1);
       
   741 			}
       
   742 		else if (iAllocedRects<0)
       
   743 			{							// RRegionBuf
       
   744 			prects=(TRect *)(((RRegion *)this)+1);
       
   745 			if (iCount==(-(iAllocedRects|ERRegionBuf)))
       
   746 				{
       
   747 				iAllocedRects=iCount+((RRegion *)this)->iGranularity;
       
   748 				if ((((RRegion *)this)->iRectangleList=(TRect *)User::Alloc(iAllocedRects*sizeof(TRect)))==NULL)
       
   749 					{
       
   750 					ForceError();
       
   751 					return;
       
   752 					}
       
   753 				Mem::Copy(((RRegion *)this)->iRectangleList, prects, sizeof(TRect)*((RRegion *)this)->iGranularity);
       
   754 				prects=((RRegion *)this)->iRectangleList;
       
   755 				}
       
   756 			}
       
   757 		else
       
   758 			{
       
   759 			RRegion *pr=(RRegion *)this;
       
   760 			prects=pr->iRectangleList;
       
   761 			if (iAllocedRects==iCount)
       
   762 				{
       
   763 				iAllocedRects+=pr->iGranularity;
       
   764 				prects=(TRect *)User::ReAlloc(prects, iAllocedRects*sizeof(TRect));
       
   765 				if (prects==NULL)
       
   766 					{
       
   767 					ForceError();
       
   768 					return;
       
   769 					}
       
   770 				pr->iRectangleList=prects;
       
   771 				}
       
   772 			}
       
   773 		*(prects+iCount)=aRect;
       
   774 		iCount++;
       
   775 		}
       
   776 	}
       
   777 
       
   778 void TRegion::DeleteRect(TRect *aRect)
       
   779 //
       
   780 // Delete a specific rectangle in the list.
       
   781 //
       
   782 	{
       
   783 
       
   784 	iCount--;
       
   785 	Mem::Copy(aRect,aRect+1,((TUint8 *)(RectangleList()+iCount))-((TUint8 *)aRect));
       
   786 	}
       
   787 #endif
       
   788 
       
   789 void TRegion::AppendRegion(TRegion &aRegion)
       
   790 //
       
   791 // Append all the rectangles from aRegion to this.
       
   792 //
       
   793 	{
       
   794 
       
   795 	if (aRegion.iError)
       
   796 		ForceError();
       
   797 	else
       
   798 		{
       
   799 		aRegion.SubRegion(*this);
       
   800 		const TRect *pR=aRegion.RectangleList();
       
   801 		const TRect *pE=pR+aRegion.iCount;
       
   802 		while (pR<pE)
       
   803 			AppendRect(*pR++);
       
   804 		}
       
   805 	}
       
   806 
       
   807 
       
   808 
       
   809 EXPORT_C RRegion::RRegion()
       
   810 	: TRegion(0), iGranularity(EDefaultGranularity), iRectangleList(NULL)
       
   811 /**
       
   812 Default constructor.
       
   813 
       
   814 Initialises its granularity to five.
       
   815 */
       
   816 	{}
       
   817 
       
   818 
       
   819 
       
   820 
       
   821 EXPORT_C RRegion::RRegion(TInt aGran)
       
   822 	: TRegion(0), iGranularity(aGran), iRectangleList(NULL)
       
   823 /**
       
   824 Constructs the object with the specified granularity.
       
   825 
       
   826 @param aGran The initial value for the region's granularity.
       
   827              This value must not be negative.
       
   828 */
       
   829 	{}
       
   830 
       
   831 
       
   832 
       
   833 
       
   834 EXPORT_C RRegion::RRegion(const TRect &aRect, TInt aGran)
       
   835 	: TRegion(0), iGranularity(aGran), iRectangleList(NULL)
       
   836 /**
       
   837 Constructs the object with the specified rectangle and granularity.
       
   838 
       
   839 The resulting region consists of the specified single rectangle.
       
   840 
       
   841 @param aRect The single rectangle with which to initialise the region 
       
   842 @param aGran The initial value for the region's granularity. By default, 
       
   843              this is five.
       
   844 */
       
   845 	{
       
   846 
       
   847 	if (!aRect.IsEmpty())
       
   848 		AppendRect(aRect);
       
   849 	}
       
   850 
       
   851 
       
   852 
       
   853 
       
   854 EXPORT_C RRegion::RRegion(const RRegion &aRegion)
       
   855 /**
       
   856 Copy constructor.
       
   857 
       
   858 Constructs a new region from an existing one by performing a bit-wise copy.  Both the new and
       
   859 existing regions are left containing pointers to the same data, so Close() must only be called on
       
   860 one of them.
       
   861 
       
   862 Use of this method is not reccomended.
       
   863 
       
   864 @param aRegion The region to be copied.
       
   865 */
       
   866 	{
       
   867 
       
   868 	*this=aRegion;
       
   869 	}
       
   870 
       
   871 
       
   872 
       
   873 
       
   874 EXPORT_C RRegion::RRegion(TInt aBuf, TInt aGran)
       
   875 //
       
   876 // Constructor.
       
   877 //
       
   878 	: TRegion(aBuf), iGranularity(aGran), iRectangleList(NULL)
       
   879 	{}
       
   880 
       
   881 
       
   882 
       
   883 
       
   884 EXPORT_C RRegion::RRegion(TInt aCount,TRect* aRectangleList,TInt aGran/*=EDefaultGranularity*/)
       
   885 /**
       
   886 Constructor that takes ownership of an already created rectangle list.
       
   887 
       
   888 @param aCount         The number of rectangles in the region.
       
   889 @param aRectangleList A pointer to the set of rectangles.
       
   890 @param aGran          The region's granularity.
       
   891 */
       
   892 	: TRegion(aCount), iGranularity(aGran), iRectangleList(aRectangleList)
       
   893 	{
       
   894 	iCount=aCount;
       
   895 	}
       
   896 
       
   897 
       
   898 
       
   899 
       
   900 EXPORT_C void RRegion::Close()
       
   901 /**
       
   902 Closes the region.
       
   903 
       
   904 Frees up any memory which has been allocated, and unsets the error flag, if 
       
   905 set. 
       
   906 
       
   907 The region can be re-used after calling this method.  Its granularity is preserved.
       
   908 */
       
   909 	{
       
   910 
       
   911 	Clear();
       
   912 	}
       
   913 
       
   914 
       
   915 
       
   916 
       
   917 EXPORT_C void RRegion::Destroy()
       
   918 //
       
   919 // Destroy
       
   920 //
       
   921 /**
       
   922 Deletes the region.
       
   923 
       
   924 Frees all memory.
       
   925 
       
   926 Note this method will delete the RRegion object and therefore it should not be 
       
   927 invoked on RRegion objects that are not allocated on the heap.  RRegion::Close()
       
   928 should be used for RRegion objects stored on the stack.
       
   929 
       
   930 @panic USER 42 if the RRegion object is stored on the stack.
       
   931 */
       
   932 	{
       
   933 
       
   934 	Clear();
       
   935 	delete this;
       
   936 	}
       
   937 
       
   938 
       
   939 
       
   940 
       
   941 TInt TRectKey::Compare(TInt aLeft,TInt aRight) const
       
   942 //
       
   943 // Compares two rectangles for partial ordering.
       
   944 //
       
   945 	{
       
   946 
       
   947 	if (aLeft==aRight)
       
   948 		return(0);
       
   949 	const TRect *r1=&iRectList[aLeft];
       
   950 	const TRect *r2=&iRectList[aRight];
       
   951 	if (r2->iBr.iY<=r1->iTl.iY)
       
   952 		return(iDown ? -1 : 1);
       
   953 	if (r1->iBr.iY<=r2->iTl.iY)
       
   954 		return(iDown ? 1 : -1);
       
   955 	if (r2->iBr.iX<=r1->iTl.iX)
       
   956 		return(iRight ? -1 : 1);
       
   957 	__ASSERT_DEBUG(r1->iBr.iX<=r2->iTl.iX,Panic(ETRegionInvalidRegionInSort));
       
   958 	return(iRight ? 1 : -1);
       
   959 	}
       
   960 
       
   961 void TRectSwap::Swap(TInt aLeft,TInt aRight) const
       
   962 //
       
   963 // Swap two rectangles.
       
   964 //
       
   965 	{
       
   966 
       
   967 	TRect tmp(iRectList[aLeft]);
       
   968 	iRectList[aLeft]=iRectList[aRight];
       
   969 	iRectList[aRight]=tmp;
       
   970 	}
       
   971 
       
   972 TRectKey::TRectKey(const TRect *aRectList,const TPoint &aOffset)
       
   973 //
       
   974 // Rectangle key constructor
       
   975 //
       
   976 	{
       
   977 
       
   978 	iRectList=aRectList;
       
   979 	if(aOffset.iX>0)
       
   980 		iRight=ETrue;
       
   981 	else
       
   982 		iRight=EFalse;
       
   983 	if(aOffset.iY>0)
       
   984 		iDown=ETrue;
       
   985 	else
       
   986 		iDown=EFalse;
       
   987 	}