graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdiellipse.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 2007-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 "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 //
       
    15 
       
    16 #include "directgdiadapter.h"
       
    17 #include "swdirectgdiellipse.h"
       
    18 #include "swdirectgdiengine.h"
       
    19 
       
    20 /*
       
    21  * TSwDirectGdiEllipse
       
    22  */
       
    23  
       
    24  /**
       
    25  Initialises the values of the ellipse so that it conforms to a rectangle entered as a parameter.
       
    26  @param aRect the rectangle within which the ellipse is drawn
       
    27  */
       
    28 void TSwDirectGdiEllipse::Construct(const TRect& aRect)
       
    29 	{
       
    30 	TInt width = aRect.Width();
       
    31 	TInt height = aRect.Height();
       
    32 	iA = (width-1) >> 1;
       
    33 	iB = (height-1) >> 1;
       
    34 	iXAdj = (width+1) & 1;
       
    35 	iYAdj = (height+1) & 1;
       
    36 	iOffset = aRect.iTl;
       
    37 	iX = 0;
       
    38 	iY = iB;
       
    39 	iASquared = iA * iA;
       
    40 	iBSquared = iB * iB;
       
    41 	iASquBSqu = iASquared * iBSquared;
       
    42 	iD1 = iBSquared - iASquared * iB + (iASquared>>1);
       
    43 	if (width<=0 || height<=0)
       
    44 		{
       
    45 		iStatus = EComplete;
       
    46 		}
       
    47 	else if (width<=2 || height<=2)
       
    48 		{
       
    49 		iStatus = ELine;
       
    50 		}
       
    51 	else
       
    52 		{
       
    53 		iStatus = EInitialised;
       
    54 		}
       
    55 	}
       
    56 
       
    57 /**
       
    58 Does the next stage in producing an ellipse by taking four points (the corners of 
       
    59 the rectangle the ellipse should fill) as parameters. Updates TSwDirectGdiEllipse status 
       
    60 accordingly and calls Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight).
       
    61 
       
    62 @param aTopLeft Top left corner of rectangle. 
       
    63 @param aTopRight Top right corner of rectangle.
       
    64 @param aBottomLeft Bottom left corner of rectangle.
       
    65 @param aBottomRight Bottom right corner of rectangle.
       
    66 @return TBool ETrue if step completed successfully.
       
    67 */
       
    68 TBool TSwDirectGdiEllipse::SingleStep(TPoint& aTopLeft, TPoint& aTopRight,
       
    69 									TPoint& aBottomLeft, TPoint& aBottomRight)
       
    70 	{
       
    71 	TBool ret = EFalse;
       
    72 	if (iStatus == EFirstSector)
       
    73 		{
       
    74 		if (iD1 < 0)
       
    75 			{
       
    76 			iD1 += iBSquared * ((iX<<1)+3);
       
    77 			}
       
    78 		else if (iY > 0)
       
    79 			{
       
    80 			iD1 += iBSquared * ((iX<<1)+3) + iASquared * (2-(iY<<1));
       
    81 			iY--;
       
    82 			}
       
    83 		iX++;
       
    84 		ret = Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
       
    85 		if (iStatus == EComplete && iX<iA)
       
    86 			{
       
    87 			iStatus = EFirstSector;
       
    88 			return EFalse;
       
    89 			}
       
    90 		if (iASquared*iY<=iBSquared*(iX+1) && ret==EFalse)
       
    91 			{
       
    92 			iStatus = ESecondSector;
       
    93 			iD2 =- iASquBSqu + iBSquared * iX * iX + iASquared * (iY-1) * (iY-1);
       
    94 			}
       
    95 		return ret;
       
    96 		}
       
    97 	if (iStatus == ESecondSector)
       
    98 		{
       
    99 		if (iD2 < 0)
       
   100 			{
       
   101 			iD2 += iBSquared * ((iX<<1)+2) + iASquared * (3-(iY<<1));
       
   102 			iX++;
       
   103 			}
       
   104 		else
       
   105 			{
       
   106 			iD2 += iASquared * (3-(iY<<1));
       
   107 			}
       
   108 		iY--;
       
   109 		return Output(aTopLeft, aTopRight, aBottomLeft, aBottomRight);
       
   110 		}
       
   111 	if (iStatus == ELine)
       
   112 		{
       
   113 		ret = Output(aTopLeft, aTopRight, aBottomLeft, aBottomRight);
       
   114 		if (iA == 0)
       
   115 			{
       
   116 			iY--;
       
   117 			}
       
   118 		else
       
   119 			{
       
   120 			iX++;
       
   121 			if (iX > iA+iXAdj) 
       
   122 				{
       
   123 				ret = ETrue;
       
   124 				}
       
   125 			else
       
   126 				{
       
   127 				iStatus = ELine;
       
   128 				ret = EFalse;
       
   129 				}
       
   130 			}
       
   131 		return ret;
       
   132 		}
       
   133 	if (iStatus == EInitialised)
       
   134 		{
       
   135 		iStatus = EFirstSector;
       
   136 		return Output(aTopLeft, aTopRight, aBottomLeft, aBottomRight);
       
   137 		}
       
   138 	Output(aTopLeft, aTopRight, aBottomLeft, aBottomRight);
       
   139 	return ETrue;
       
   140 	}
       
   141 
       
   142 /**
       
   143 Sets the absolute points that define the ellipse as calculated using its iOffset 
       
   144 from the origin and using the half width and half height of the rectangle iA and iB.
       
   145 
       
   146 @param aTopLeft The absolute (x,y) position for the top left point.
       
   147 @param aTopRight The absolute (x,y) position for the top right point.
       
   148 @param aBottomLeft The absolute (x,y) position for the bottom left point.
       
   149 @param aBottomRight The absolute (x,y) position for the bottom right point.
       
   150 @return ETrue if a valid rectangle is produced, else EFalse. Also sets
       
   151 iStatus to EComplete.
       
   152 */
       
   153 TBool TSwDirectGdiEllipse::Output(TPoint& aTopLeft, TPoint& aTopRight,
       
   154 								TPoint& aBottomLeft, TPoint& aBottomRight)
       
   155 	{
       
   156 	TInt lx = iA-iX+iOffset.iX;
       
   157 	TInt ty = iB-iY+iOffset.iY;
       
   158 	TInt rx = iA+iX+iXAdj+iOffset.iX;
       
   159 	TInt by = iB+iY+iYAdj+iOffset.iY;
       
   160 	aTopLeft.SetXY(lx,ty);
       
   161 	aTopRight.SetXY(rx,ty);
       
   162 	aBottomLeft.SetXY(lx,by);
       
   163 	aBottomRight.SetXY(rx,by);
       
   164 	if (iY <= 0)
       
   165 		{
       
   166 		iStatus = EComplete;
       
   167 		if (iYAdj==0 || ty>by)
       
   168 			return ETrue;
       
   169 		}
       
   170 	return EFalse;
       
   171 	}
       
   172 
       
   173 /**
       
   174 By analysing the current state of the ellipse the process is taken to the next appropriate step.
       
   175 If iStatus = EInitialised only one step will be taken, if the ellipse is already semi constructed then 
       
   176 it will be taken to completion. Takes in four point parameters that define the rectangle in order to pass to 
       
   177 SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight).
       
   178 
       
   179 @param aTopLeft Top-left corner of rectangle.
       
   180 @param aTopRight Top-right corner of rectangle.
       
   181 @param aBottomLeft Bottom-left corner of rectangle.
       
   182 @param aBottomRight Bottom-right corner of rectangle.
       
   183 @return ETrue if a valid rectangle is produced, else EFalse.
       
   184 */
       
   185 TBool TSwDirectGdiEllipse::NextStep(TPoint& aTopLeft, TPoint& aTopRight,
       
   186 								  TPoint& aBottomLeft, TPoint& aBottomRight)
       
   187 	{
       
   188 	if(iStatus == EInitialised)
       
   189 		{
       
   190 		return(SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight));
       
   191 		}
       
   192 	TInt prevlev = iY;
       
   193 	TBool ret;
       
   194 	do
       
   195 		{
       
   196 		ret = SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
       
   197 		} 
       
   198 	while (prevlev==iY && ret==EFalse);	
       
   199 	return ret;
       
   200 	}
       
   201 
       
   202 /**
       
   203 Constructs an ellipse from the rectangle that has been added. Assesses the position of 
       
   204 the points and the places where they intersect the ellipse.
       
   205  
       
   206 @param aRect The rectangle within which the ellipse is drawn.
       
   207 @param aPoint A point to compare with the ellipse to determine if intersection occurs. 
       
   208 @return TPoint The point is set to the corner which the intersection is nearest to.
       
   209 */
       
   210 TPoint TSwDirectGdiEllipse::Intersection(const TRect& aRect, const TPoint& aPoint)
       
   211 	{
       
   212 	Construct(aRect);					//constructs the rect (an elipse object)
       
   213 	TPoint centre = aRect.Center();		//centre of ellipse
       
   214 	TPoint ptcpy(aPoint);				
       
   215 	ptcpy -= iOffset;						//ptcpy = aPoint - iOffset - TPoint(iA,iB)	//radius from centre of ellipse		
       
   216 	ptcpy -= TPoint(iA,iB);				
       
   217 	TPoint pt[4], opt[4];			
       
   218 	TInt mpt[4], ompt[4];
       
   219 	TInt count = 0;
       
   220 	for( ; count < 4; count++)
       
   221 		{
       
   222 		ompt[count]=KMaxTInt;			//fills ompt 1->4 with KMaxTInt
       
   223 		}
       
   224 	while (SingleStep(pt[0], pt[1], pt[2], pt[3]) == EFalse) 	//creates a complete ellipse with pts as rect
       
   225 		{
       
   226 		for (count = 0; count < 4; count++)
       
   227 			{
       
   228 			mpt[count] = Abs((pt[count].iY-iOffset.iY-iB)*(ptcpy.iX)-(ptcpy.iY)*(pt[count].iX-iOffset.iX-iA));
       
   229 			if (mpt[count] < ompt[count]) //use the larger number set.
       
   230 				{
       
   231 				ompt[count] = mpt[count];
       
   232 				opt[count] = pt[count];
       
   233 				}						
       
   234 			}
       
   235 		}
       
   236 	if (pt[0].iY == pt[2].iY)	//if it is horizontal
       
   237 		{
       
   238 		for (count = 0; count < 4; count++)
       
   239 			{
       
   240 			mpt[count] = Abs((pt[count].iY-iOffset.iY-iB)*(ptcpy.iX)-(ptcpy.iY)*(pt[count].iX-iOffset.iX-iA));
       
   241 			if (mpt[count] < ompt[count]) //use the larger number set.
       
   242 				{
       
   243 				ompt[count] = mpt[count];
       
   244 				opt[count] = pt[count];
       
   245 				}
       
   246 			}
       
   247 		}
       
   248 	if (ptcpy.iX<0 && ptcpy.iY<0)	//if point is further left and higher than centre of rect
       
   249 		{
       
   250 		return opt[0];
       
   251 		}
       
   252 	if (ptcpy.iY < 0)			//if point is higher than centre of rect
       
   253 		{
       
   254 		return opt[1];
       
   255 		}
       
   256 	if (ptcpy.iX < 0)			//if point is further left than centre of rect
       
   257 		{
       
   258 		return opt[2];
       
   259 		}
       
   260 	if (aPoint.iX<centre.iX && aPoint.iY<centre.iY)	//if point is further left and higher than centre of rect
       
   261 		{
       
   262 		return opt[0];
       
   263 		}
       
   264 	if (aPoint.iY < centre.iY)	//if point is higher than centre of rect
       
   265 		{
       
   266 		return opt[1];
       
   267 		}
       
   268 	if (aPoint.iX < centre.iX)	//if point is further left than centre of rect
       
   269 		{
       
   270 		return opt[2];
       
   271 		}
       
   272 	return(opt[3]);			//else 
       
   273 	}
       
   274 
       
   275 //
       
   276 // Ellipse drawing
       
   277 //
       
   278 
       
   279 /**
       
   280 @see MDirectGdiEngine::DrawEllipse()
       
   281 */
       
   282 void CSwDirectGdiEngine::DrawEllipse(const TRect& aRect)
       
   283 	{
       
   284 	TRect rcpy(aRect);
       
   285 	rcpy.Move(iOrigin);
       
   286 	TruncateRect(rcpy);
       
   287 	iBrushBitmap.BeginDataAccess();
       
   288 	if(iBrushStyle!=DirectGdi::ENullBrush)
       
   289 		EllipseFill(rcpy);
       
   290 	
       
   291 	if(iPenStyle!=DirectGdi::ENullPen)
       
   292 		{
       
   293 		if(iPenSize.iWidth>1 && iPenSize.iHeight>1)
       
   294 			{
       
   295 			EllipseOutlineWide(rcpy);
       
   296 			}
       
   297 		else if(iPenSize.iWidth==1 || iPenSize.iHeight==1)
       
   298 			{
       
   299 			EllipseOutline(rcpy);
       
   300 			}			
       
   301 		}
       
   302 	iBrushBitmap.EndDataAccess(ETrue);
       
   303 	}
       
   304 
       
   305 /**
       
   306 Draws an ellipse inside the given rectangle. Current pen settings apply.
       
   307 @param	aRect The rectangle in which to draw the ellipse.
       
   308 */
       
   309 void CSwDirectGdiEngine::EllipseOutline(const TRect& aRect)
       
   310 	{
       
   311 	TPoint tl,tr,bl,br;
       
   312 #if defined(_DEBUG)
       
   313 	TRect deviceDestRect;
       
   314 	iDrawDevice->GetDrawRect(deviceDestRect);
       
   315 #endif
       
   316 	TRect clipRect(0,0,0,0);
       
   317 	const CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode);
       
   318 	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
       
   319 		{
       
   320 		clipRect=(*iDefaultRegionPtr)[count];
       
   321 		if(!clipRect.Intersects(aRect))
       
   322 			continue;
       
   323 		clipRect.Intersection(aRect);
       
   324 		GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iX >= deviceDestRect.iTl.iX, EDirectGdiPanicOutOfBounds);
       
   325 		GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iY >= deviceDestRect.iTl.iY, EDirectGdiPanicOutOfBounds);
       
   326 		GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iX <= deviceDestRect.iBr.iX, EDirectGdiPanicOutOfBounds);
       
   327 		GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iY <= deviceDestRect.iBr.iY, EDirectGdiPanicOutOfBounds);
       
   328 		TSwDirectGdiEllipse ellipse;
       
   329 		ellipse.Construct(aRect);
       
   330 		TInt pattern=0;
       
   331 		while(!ellipse.SingleStep(tl,tr,bl,br))
       
   332 			{
       
   333 			if(iPenStyle==DirectGdi::ESolidPen || (iDotMask&(1<<(pattern%iDotLength))))
       
   334 				{
       
   335 				if(tl.iY>=clipRect.iTl.iY && tl.iY<clipRect.iBr.iY)
       
   336 					{
       
   337 					if(tl.iX>=clipRect.iTl.iX && tl.iX<clipRect.iBr.iX)
       
   338 						iDrawDevice->WriteRgb(tl.iX,tl.iY,iPenColor,drawMode);
       
   339 					if(tr.iX>=clipRect.iTl.iX && tr.iX<clipRect.iBr.iX && tl.iX!=tr.iX)
       
   340 						iDrawDevice->WriteRgb(tr.iX,tr.iY,iPenColor,drawMode);
       
   341 					}
       
   342 				if(bl.iY>=clipRect.iTl.iY && bl.iY<clipRect.iBr.iY)
       
   343 					{
       
   344 					if(bl.iX>=clipRect.iTl.iX && bl.iX<clipRect.iBr.iX)
       
   345 						iDrawDevice->WriteRgb(bl.iX,bl.iY,iPenColor,drawMode);
       
   346 					if(br.iX>=clipRect.iTl.iX && br.iX<clipRect.iBr.iX && bl.iX!=br.iX)
       
   347 						iDrawDevice->WriteRgb(br.iX,br.iY,iPenColor,drawMode);
       
   348 					}
       
   349 				}
       
   350 			pattern++;
       
   351 			}
       
   352 		if(tl.iY==bl.iY && tl.iY>=clipRect.iTl.iY && tl.iY<clipRect.iBr.iY)
       
   353 			{
       
   354 			if(tl.iX>=clipRect.iTl.iX && tl.iX<clipRect.iBr.iX)
       
   355 				iDrawDevice->WriteRgb(tl.iX,tl.iY,iPenColor,drawMode);
       
   356 			if(tr.iX>=clipRect.iTl.iX && tr.iX<clipRect.iBr.iX && tl.iX!=tr.iX)
       
   357 				iDrawDevice->WriteRgb(tr.iX,tr.iY,iPenColor,drawMode);
       
   358 			}
       
   359 		iDrawDevice->UpdateRegion(clipRect);
       
   360 		}
       
   361 	}
       
   362 
       
   363 /**
       
   364 Draws an ellipse inside the given rectangle. Current pen settings apply.
       
   365 @param	aRect The rectangle in which to draw the ellipse.
       
   366 */
       
   367 void CSwDirectGdiEngine::EllipseOutlineWide(const TRect& aRect)
       
   368 	{
       
   369 	TRect rcpy(aRect);
       
   370 	TPoint tl,tr,bl,br;
       
   371 	TInt halfpenwidth=(iPenSize.iWidth+1)>>1;
       
   372 	TInt halfpenheight=(iPenSize.iHeight+1)>>1;
       
   373 	rcpy.Grow(halfpenwidth, halfpenheight);
       
   374 	TInt dp=iDotParam;
       
   375 	TRect clipRect(0,0,0,0);
       
   376 	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
       
   377 		{
       
   378 		clipRect=(*iDefaultRegionPtr)[count];
       
   379 		if(!clipRect.Intersects(rcpy))
       
   380 			continue;
       
   381 		clipRect.Intersection(rcpy);
       
   382 		TSwDirectGdiEllipse ellipse;
       
   383 		ellipse.Construct(aRect);
       
   384 		iDotParam=Max(iPenSize.iWidth>>1,iPenSize.iHeight>>1);
       
   385 		while(!ellipse.SingleStep(tl,tr,bl,br))
       
   386 			{
       
   387 			PenDrawClipped(tl, clipRect);
       
   388 			PenDrawClipped(tr, clipRect);
       
   389 			PenDrawClipped(bl, clipRect);
       
   390 			PenDrawClipped(br, clipRect);
       
   391 			iDotParam+=iDotDirection;
       
   392 			}
       
   393 		if(tl.iY==bl.iY)
       
   394 			{
       
   395 			PenDrawClipped(tl, clipRect);
       
   396 			PenDrawClipped(tr, clipRect);
       
   397 			}
       
   398 		iDrawDevice->UpdateRegion(clipRect);
       
   399 		}
       
   400 	iDotParam=dp;
       
   401 	}
       
   402 
       
   403 /**
       
   404 Fills an ellipse inside the given rectangle. Current brush settings apply.
       
   405 @param	aRect The rectangle in which to draw the ellipse.
       
   406 */
       
   407 void CSwDirectGdiEngine::EllipseFill(const TRect& aRect)
       
   408 	{
       
   409 	TRect rcpy(aRect);
       
   410 	if(iPenSize.iWidth==0 || iPenSize.iHeight==0)
       
   411 		{
       
   412 		rcpy.Grow(1,1);
       
   413 		}
       
   414 	TPoint tl,tr,bl,br;
       
   415 	TRect clipRect(0,0,0,0);
       
   416 	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
       
   417 		{
       
   418 		clipRect=(*iDefaultRegionPtr)[count];
       
   419 		if(!clipRect.Intersects(rcpy))
       
   420 			continue;
       
   421 		clipRect.Intersection(rcpy);
       
   422 		TSwDirectGdiEllipse ellipse;
       
   423 		ellipse.Construct(rcpy);
       
   424 		while(!ellipse.NextStep(tl,tr,bl,br))
       
   425 			{
       
   426 			tl.iX++;
       
   427 			tr.iX--;
       
   428 			bl.iX++;
       
   429 			br.iX--;
       
   430 			ClipFillLine(tl,tr, clipRect);
       
   431 			ClipFillLine(bl,br, clipRect);
       
   432 			}
       
   433 		if(tl.iY==bl.iY)
       
   434 			{
       
   435 			tl.iX++;
       
   436 			tr.iX--;
       
   437 			ClipFillLine(tl,tr, clipRect);
       
   438 			}
       
   439 		iDrawDevice->UpdateRegion(clipRect);
       
   440 		}
       
   441 	}