os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdiellipse.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdiellipse.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,441 @@
     1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include "directgdiadapter.h"
    1.20 +#include "swdirectgdiellipse.h"
    1.21 +#include "swdirectgdiengine.h"
    1.22 +
    1.23 +/*
    1.24 + * TSwDirectGdiEllipse
    1.25 + */
    1.26 + 
    1.27 + /**
    1.28 + Initialises the values of the ellipse so that it conforms to a rectangle entered as a parameter.
    1.29 + @param aRect the rectangle within which the ellipse is drawn
    1.30 + */
    1.31 +void TSwDirectGdiEllipse::Construct(const TRect& aRect)
    1.32 +	{
    1.33 +	TInt width = aRect.Width();
    1.34 +	TInt height = aRect.Height();
    1.35 +	iA = (width-1) >> 1;
    1.36 +	iB = (height-1) >> 1;
    1.37 +	iXAdj = (width+1) & 1;
    1.38 +	iYAdj = (height+1) & 1;
    1.39 +	iOffset = aRect.iTl;
    1.40 +	iX = 0;
    1.41 +	iY = iB;
    1.42 +	iASquared = iA * iA;
    1.43 +	iBSquared = iB * iB;
    1.44 +	iASquBSqu = iASquared * iBSquared;
    1.45 +	iD1 = iBSquared - iASquared * iB + (iASquared>>1);
    1.46 +	if (width<=0 || height<=0)
    1.47 +		{
    1.48 +		iStatus = EComplete;
    1.49 +		}
    1.50 +	else if (width<=2 || height<=2)
    1.51 +		{
    1.52 +		iStatus = ELine;
    1.53 +		}
    1.54 +	else
    1.55 +		{
    1.56 +		iStatus = EInitialised;
    1.57 +		}
    1.58 +	}
    1.59 +
    1.60 +/**
    1.61 +Does the next stage in producing an ellipse by taking four points (the corners of 
    1.62 +the rectangle the ellipse should fill) as parameters. Updates TSwDirectGdiEllipse status 
    1.63 +accordingly and calls Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight).
    1.64 +
    1.65 +@param aTopLeft Top left corner of rectangle. 
    1.66 +@param aTopRight Top right corner of rectangle.
    1.67 +@param aBottomLeft Bottom left corner of rectangle.
    1.68 +@param aBottomRight Bottom right corner of rectangle.
    1.69 +@return TBool ETrue if step completed successfully.
    1.70 +*/
    1.71 +TBool TSwDirectGdiEllipse::SingleStep(TPoint& aTopLeft, TPoint& aTopRight,
    1.72 +									TPoint& aBottomLeft, TPoint& aBottomRight)
    1.73 +	{
    1.74 +	TBool ret = EFalse;
    1.75 +	if (iStatus == EFirstSector)
    1.76 +		{
    1.77 +		if (iD1 < 0)
    1.78 +			{
    1.79 +			iD1 += iBSquared * ((iX<<1)+3);
    1.80 +			}
    1.81 +		else if (iY > 0)
    1.82 +			{
    1.83 +			iD1 += iBSquared * ((iX<<1)+3) + iASquared * (2-(iY<<1));
    1.84 +			iY--;
    1.85 +			}
    1.86 +		iX++;
    1.87 +		ret = Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
    1.88 +		if (iStatus == EComplete && iX<iA)
    1.89 +			{
    1.90 +			iStatus = EFirstSector;
    1.91 +			return EFalse;
    1.92 +			}
    1.93 +		if (iASquared*iY<=iBSquared*(iX+1) && ret==EFalse)
    1.94 +			{
    1.95 +			iStatus = ESecondSector;
    1.96 +			iD2 =- iASquBSqu + iBSquared * iX * iX + iASquared * (iY-1) * (iY-1);
    1.97 +			}
    1.98 +		return ret;
    1.99 +		}
   1.100 +	if (iStatus == ESecondSector)
   1.101 +		{
   1.102 +		if (iD2 < 0)
   1.103 +			{
   1.104 +			iD2 += iBSquared * ((iX<<1)+2) + iASquared * (3-(iY<<1));
   1.105 +			iX++;
   1.106 +			}
   1.107 +		else
   1.108 +			{
   1.109 +			iD2 += iASquared * (3-(iY<<1));
   1.110 +			}
   1.111 +		iY--;
   1.112 +		return Output(aTopLeft, aTopRight, aBottomLeft, aBottomRight);
   1.113 +		}
   1.114 +	if (iStatus == ELine)
   1.115 +		{
   1.116 +		ret = Output(aTopLeft, aTopRight, aBottomLeft, aBottomRight);
   1.117 +		if (iA == 0)
   1.118 +			{
   1.119 +			iY--;
   1.120 +			}
   1.121 +		else
   1.122 +			{
   1.123 +			iX++;
   1.124 +			if (iX > iA+iXAdj) 
   1.125 +				{
   1.126 +				ret = ETrue;
   1.127 +				}
   1.128 +			else
   1.129 +				{
   1.130 +				iStatus = ELine;
   1.131 +				ret = EFalse;
   1.132 +				}
   1.133 +			}
   1.134 +		return ret;
   1.135 +		}
   1.136 +	if (iStatus == EInitialised)
   1.137 +		{
   1.138 +		iStatus = EFirstSector;
   1.139 +		return Output(aTopLeft, aTopRight, aBottomLeft, aBottomRight);
   1.140 +		}
   1.141 +	Output(aTopLeft, aTopRight, aBottomLeft, aBottomRight);
   1.142 +	return ETrue;
   1.143 +	}
   1.144 +
   1.145 +/**
   1.146 +Sets the absolute points that define the ellipse as calculated using its iOffset 
   1.147 +from the origin and using the half width and half height of the rectangle iA and iB.
   1.148 +
   1.149 +@param aTopLeft The absolute (x,y) position for the top left point.
   1.150 +@param aTopRight The absolute (x,y) position for the top right point.
   1.151 +@param aBottomLeft The absolute (x,y) position for the bottom left point.
   1.152 +@param aBottomRight The absolute (x,y) position for the bottom right point.
   1.153 +@return ETrue if a valid rectangle is produced, else EFalse. Also sets
   1.154 +iStatus to EComplete.
   1.155 +*/
   1.156 +TBool TSwDirectGdiEllipse::Output(TPoint& aTopLeft, TPoint& aTopRight,
   1.157 +								TPoint& aBottomLeft, TPoint& aBottomRight)
   1.158 +	{
   1.159 +	TInt lx = iA-iX+iOffset.iX;
   1.160 +	TInt ty = iB-iY+iOffset.iY;
   1.161 +	TInt rx = iA+iX+iXAdj+iOffset.iX;
   1.162 +	TInt by = iB+iY+iYAdj+iOffset.iY;
   1.163 +	aTopLeft.SetXY(lx,ty);
   1.164 +	aTopRight.SetXY(rx,ty);
   1.165 +	aBottomLeft.SetXY(lx,by);
   1.166 +	aBottomRight.SetXY(rx,by);
   1.167 +	if (iY <= 0)
   1.168 +		{
   1.169 +		iStatus = EComplete;
   1.170 +		if (iYAdj==0 || ty>by)
   1.171 +			return ETrue;
   1.172 +		}
   1.173 +	return EFalse;
   1.174 +	}
   1.175 +
   1.176 +/**
   1.177 +By analysing the current state of the ellipse the process is taken to the next appropriate step.
   1.178 +If iStatus = EInitialised only one step will be taken, if the ellipse is already semi constructed then 
   1.179 +it will be taken to completion. Takes in four point parameters that define the rectangle in order to pass to 
   1.180 +SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight).
   1.181 +
   1.182 +@param aTopLeft Top-left corner of rectangle.
   1.183 +@param aTopRight Top-right corner of rectangle.
   1.184 +@param aBottomLeft Bottom-left corner of rectangle.
   1.185 +@param aBottomRight Bottom-right corner of rectangle.
   1.186 +@return ETrue if a valid rectangle is produced, else EFalse.
   1.187 +*/
   1.188 +TBool TSwDirectGdiEllipse::NextStep(TPoint& aTopLeft, TPoint& aTopRight,
   1.189 +								  TPoint& aBottomLeft, TPoint& aBottomRight)
   1.190 +	{
   1.191 +	if(iStatus == EInitialised)
   1.192 +		{
   1.193 +		return(SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight));
   1.194 +		}
   1.195 +	TInt prevlev = iY;
   1.196 +	TBool ret;
   1.197 +	do
   1.198 +		{
   1.199 +		ret = SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
   1.200 +		} 
   1.201 +	while (prevlev==iY && ret==EFalse);	
   1.202 +	return ret;
   1.203 +	}
   1.204 +
   1.205 +/**
   1.206 +Constructs an ellipse from the rectangle that has been added. Assesses the position of 
   1.207 +the points and the places where they intersect the ellipse.
   1.208 + 
   1.209 +@param aRect The rectangle within which the ellipse is drawn.
   1.210 +@param aPoint A point to compare with the ellipse to determine if intersection occurs. 
   1.211 +@return TPoint The point is set to the corner which the intersection is nearest to.
   1.212 +*/
   1.213 +TPoint TSwDirectGdiEllipse::Intersection(const TRect& aRect, const TPoint& aPoint)
   1.214 +	{
   1.215 +	Construct(aRect);					//constructs the rect (an elipse object)
   1.216 +	TPoint centre = aRect.Center();		//centre of ellipse
   1.217 +	TPoint ptcpy(aPoint);				
   1.218 +	ptcpy -= iOffset;						//ptcpy = aPoint - iOffset - TPoint(iA,iB)	//radius from centre of ellipse		
   1.219 +	ptcpy -= TPoint(iA,iB);				
   1.220 +	TPoint pt[4], opt[4];			
   1.221 +	TInt mpt[4], ompt[4];
   1.222 +	TInt count = 0;
   1.223 +	for( ; count < 4; count++)
   1.224 +		{
   1.225 +		ompt[count]=KMaxTInt;			//fills ompt 1->4 with KMaxTInt
   1.226 +		}
   1.227 +	while (SingleStep(pt[0], pt[1], pt[2], pt[3]) == EFalse) 	//creates a complete ellipse with pts as rect
   1.228 +		{
   1.229 +		for (count = 0; count < 4; count++)
   1.230 +			{
   1.231 +			mpt[count] = Abs((pt[count].iY-iOffset.iY-iB)*(ptcpy.iX)-(ptcpy.iY)*(pt[count].iX-iOffset.iX-iA));
   1.232 +			if (mpt[count] < ompt[count]) //use the larger number set.
   1.233 +				{
   1.234 +				ompt[count] = mpt[count];
   1.235 +				opt[count] = pt[count];
   1.236 +				}						
   1.237 +			}
   1.238 +		}
   1.239 +	if (pt[0].iY == pt[2].iY)	//if it is horizontal
   1.240 +		{
   1.241 +		for (count = 0; count < 4; count++)
   1.242 +			{
   1.243 +			mpt[count] = Abs((pt[count].iY-iOffset.iY-iB)*(ptcpy.iX)-(ptcpy.iY)*(pt[count].iX-iOffset.iX-iA));
   1.244 +			if (mpt[count] < ompt[count]) //use the larger number set.
   1.245 +				{
   1.246 +				ompt[count] = mpt[count];
   1.247 +				opt[count] = pt[count];
   1.248 +				}
   1.249 +			}
   1.250 +		}
   1.251 +	if (ptcpy.iX<0 && ptcpy.iY<0)	//if point is further left and higher than centre of rect
   1.252 +		{
   1.253 +		return opt[0];
   1.254 +		}
   1.255 +	if (ptcpy.iY < 0)			//if point is higher than centre of rect
   1.256 +		{
   1.257 +		return opt[1];
   1.258 +		}
   1.259 +	if (ptcpy.iX < 0)			//if point is further left than centre of rect
   1.260 +		{
   1.261 +		return opt[2];
   1.262 +		}
   1.263 +	if (aPoint.iX<centre.iX && aPoint.iY<centre.iY)	//if point is further left and higher than centre of rect
   1.264 +		{
   1.265 +		return opt[0];
   1.266 +		}
   1.267 +	if (aPoint.iY < centre.iY)	//if point is higher than centre of rect
   1.268 +		{
   1.269 +		return opt[1];
   1.270 +		}
   1.271 +	if (aPoint.iX < centre.iX)	//if point is further left than centre of rect
   1.272 +		{
   1.273 +		return opt[2];
   1.274 +		}
   1.275 +	return(opt[3]);			//else 
   1.276 +	}
   1.277 +
   1.278 +//
   1.279 +// Ellipse drawing
   1.280 +//
   1.281 +
   1.282 +/**
   1.283 +@see MDirectGdiEngine::DrawEllipse()
   1.284 +*/
   1.285 +void CSwDirectGdiEngine::DrawEllipse(const TRect& aRect)
   1.286 +	{
   1.287 +	TRect rcpy(aRect);
   1.288 +	rcpy.Move(iOrigin);
   1.289 +	TruncateRect(rcpy);
   1.290 +	iBrushBitmap.BeginDataAccess();
   1.291 +	if(iBrushStyle!=DirectGdi::ENullBrush)
   1.292 +		EllipseFill(rcpy);
   1.293 +	
   1.294 +	if(iPenStyle!=DirectGdi::ENullPen)
   1.295 +		{
   1.296 +		if(iPenSize.iWidth>1 && iPenSize.iHeight>1)
   1.297 +			{
   1.298 +			EllipseOutlineWide(rcpy);
   1.299 +			}
   1.300 +		else if(iPenSize.iWidth==1 || iPenSize.iHeight==1)
   1.301 +			{
   1.302 +			EllipseOutline(rcpy);
   1.303 +			}			
   1.304 +		}
   1.305 +	iBrushBitmap.EndDataAccess(ETrue);
   1.306 +	}
   1.307 +
   1.308 +/**
   1.309 +Draws an ellipse inside the given rectangle. Current pen settings apply.
   1.310 +@param	aRect The rectangle in which to draw the ellipse.
   1.311 +*/
   1.312 +void CSwDirectGdiEngine::EllipseOutline(const TRect& aRect)
   1.313 +	{
   1.314 +	TPoint tl,tr,bl,br;
   1.315 +#if defined(_DEBUG)
   1.316 +	TRect deviceDestRect;
   1.317 +	iDrawDevice->GetDrawRect(deviceDestRect);
   1.318 +#endif
   1.319 +	TRect clipRect(0,0,0,0);
   1.320 +	const CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode);
   1.321 +	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
   1.322 +		{
   1.323 +		clipRect=(*iDefaultRegionPtr)[count];
   1.324 +		if(!clipRect.Intersects(aRect))
   1.325 +			continue;
   1.326 +		clipRect.Intersection(aRect);
   1.327 +		GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iX >= deviceDestRect.iTl.iX, EDirectGdiPanicOutOfBounds);
   1.328 +		GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iY >= deviceDestRect.iTl.iY, EDirectGdiPanicOutOfBounds);
   1.329 +		GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iX <= deviceDestRect.iBr.iX, EDirectGdiPanicOutOfBounds);
   1.330 +		GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iY <= deviceDestRect.iBr.iY, EDirectGdiPanicOutOfBounds);
   1.331 +		TSwDirectGdiEllipse ellipse;
   1.332 +		ellipse.Construct(aRect);
   1.333 +		TInt pattern=0;
   1.334 +		while(!ellipse.SingleStep(tl,tr,bl,br))
   1.335 +			{
   1.336 +			if(iPenStyle==DirectGdi::ESolidPen || (iDotMask&(1<<(pattern%iDotLength))))
   1.337 +				{
   1.338 +				if(tl.iY>=clipRect.iTl.iY && tl.iY<clipRect.iBr.iY)
   1.339 +					{
   1.340 +					if(tl.iX>=clipRect.iTl.iX && tl.iX<clipRect.iBr.iX)
   1.341 +						iDrawDevice->WriteRgb(tl.iX,tl.iY,iPenColor,drawMode);
   1.342 +					if(tr.iX>=clipRect.iTl.iX && tr.iX<clipRect.iBr.iX && tl.iX!=tr.iX)
   1.343 +						iDrawDevice->WriteRgb(tr.iX,tr.iY,iPenColor,drawMode);
   1.344 +					}
   1.345 +				if(bl.iY>=clipRect.iTl.iY && bl.iY<clipRect.iBr.iY)
   1.346 +					{
   1.347 +					if(bl.iX>=clipRect.iTl.iX && bl.iX<clipRect.iBr.iX)
   1.348 +						iDrawDevice->WriteRgb(bl.iX,bl.iY,iPenColor,drawMode);
   1.349 +					if(br.iX>=clipRect.iTl.iX && br.iX<clipRect.iBr.iX && bl.iX!=br.iX)
   1.350 +						iDrawDevice->WriteRgb(br.iX,br.iY,iPenColor,drawMode);
   1.351 +					}
   1.352 +				}
   1.353 +			pattern++;
   1.354 +			}
   1.355 +		if(tl.iY==bl.iY && tl.iY>=clipRect.iTl.iY && tl.iY<clipRect.iBr.iY)
   1.356 +			{
   1.357 +			if(tl.iX>=clipRect.iTl.iX && tl.iX<clipRect.iBr.iX)
   1.358 +				iDrawDevice->WriteRgb(tl.iX,tl.iY,iPenColor,drawMode);
   1.359 +			if(tr.iX>=clipRect.iTl.iX && tr.iX<clipRect.iBr.iX && tl.iX!=tr.iX)
   1.360 +				iDrawDevice->WriteRgb(tr.iX,tr.iY,iPenColor,drawMode);
   1.361 +			}
   1.362 +		iDrawDevice->UpdateRegion(clipRect);
   1.363 +		}
   1.364 +	}
   1.365 +
   1.366 +/**
   1.367 +Draws an ellipse inside the given rectangle. Current pen settings apply.
   1.368 +@param	aRect The rectangle in which to draw the ellipse.
   1.369 +*/
   1.370 +void CSwDirectGdiEngine::EllipseOutlineWide(const TRect& aRect)
   1.371 +	{
   1.372 +	TRect rcpy(aRect);
   1.373 +	TPoint tl,tr,bl,br;
   1.374 +	TInt halfpenwidth=(iPenSize.iWidth+1)>>1;
   1.375 +	TInt halfpenheight=(iPenSize.iHeight+1)>>1;
   1.376 +	rcpy.Grow(halfpenwidth, halfpenheight);
   1.377 +	TInt dp=iDotParam;
   1.378 +	TRect clipRect(0,0,0,0);
   1.379 +	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
   1.380 +		{
   1.381 +		clipRect=(*iDefaultRegionPtr)[count];
   1.382 +		if(!clipRect.Intersects(rcpy))
   1.383 +			continue;
   1.384 +		clipRect.Intersection(rcpy);
   1.385 +		TSwDirectGdiEllipse ellipse;
   1.386 +		ellipse.Construct(aRect);
   1.387 +		iDotParam=Max(iPenSize.iWidth>>1,iPenSize.iHeight>>1);
   1.388 +		while(!ellipse.SingleStep(tl,tr,bl,br))
   1.389 +			{
   1.390 +			PenDrawClipped(tl, clipRect);
   1.391 +			PenDrawClipped(tr, clipRect);
   1.392 +			PenDrawClipped(bl, clipRect);
   1.393 +			PenDrawClipped(br, clipRect);
   1.394 +			iDotParam+=iDotDirection;
   1.395 +			}
   1.396 +		if(tl.iY==bl.iY)
   1.397 +			{
   1.398 +			PenDrawClipped(tl, clipRect);
   1.399 +			PenDrawClipped(tr, clipRect);
   1.400 +			}
   1.401 +		iDrawDevice->UpdateRegion(clipRect);
   1.402 +		}
   1.403 +	iDotParam=dp;
   1.404 +	}
   1.405 +
   1.406 +/**
   1.407 +Fills an ellipse inside the given rectangle. Current brush settings apply.
   1.408 +@param	aRect The rectangle in which to draw the ellipse.
   1.409 +*/
   1.410 +void CSwDirectGdiEngine::EllipseFill(const TRect& aRect)
   1.411 +	{
   1.412 +	TRect rcpy(aRect);
   1.413 +	if(iPenSize.iWidth==0 || iPenSize.iHeight==0)
   1.414 +		{
   1.415 +		rcpy.Grow(1,1);
   1.416 +		}
   1.417 +	TPoint tl,tr,bl,br;
   1.418 +	TRect clipRect(0,0,0,0);
   1.419 +	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
   1.420 +		{
   1.421 +		clipRect=(*iDefaultRegionPtr)[count];
   1.422 +		if(!clipRect.Intersects(rcpy))
   1.423 +			continue;
   1.424 +		clipRect.Intersection(rcpy);
   1.425 +		TSwDirectGdiEllipse ellipse;
   1.426 +		ellipse.Construct(rcpy);
   1.427 +		while(!ellipse.NextStep(tl,tr,bl,br))
   1.428 +			{
   1.429 +			tl.iX++;
   1.430 +			tr.iX--;
   1.431 +			bl.iX++;
   1.432 +			br.iX--;
   1.433 +			ClipFillLine(tl,tr, clipRect);
   1.434 +			ClipFillLine(bl,br, clipRect);
   1.435 +			}
   1.436 +		if(tl.iY==bl.iY)
   1.437 +			{
   1.438 +			tl.iX++;
   1.439 +			tr.iX--;
   1.440 +			ClipFillLine(tl,tr, clipRect);
   1.441 +			}
   1.442 +		iDrawDevice->UpdateRegion(clipRect);
   1.443 +		}
   1.444 +	}