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