os/graphics/graphicsdeviceinterface/bitgdi/sbit/ELLIPSE.CPP
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/graphicsdeviceinterface/bitgdi/sbit/ELLIPSE.CPP	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,405 @@
     1.4 +// Copyright (c) 1997-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 <bitstd.h>
    1.20 +#include <bitdev.h>
    1.21 +#include "BITPANIC.H"
    1.22 +#include <bitdraw.h>
    1.23 +#include <graphics/fbsrasterizer.h>
    1.24 +
    1.25 +/*
    1.26 + * TEllipse
    1.27 + */
    1.28 + 
    1.29 + /**
    1.30 + Initialises the values of the ellipse so that it conforms to a rectangle entered as a parameter.
    1.31 + @param aRect the rectangle within which the ellipse is drawn
    1.32 + */
    1.33 +EXPORT_C void TEllipse::Construct(const TRect& aRect)
    1.34 +	{
    1.35 +	TInt width=aRect.Width();
    1.36 +	TInt height=aRect.Height();
    1.37 +	iA=(width-1)>>1;
    1.38 +	iB=(height-1)>>1;
    1.39 +	iXAdj=(width+1)&1;
    1.40 +	iYAdj=(height+1)&1;
    1.41 +	iOffset=aRect.iTl;
    1.42 +	iX=0;
    1.43 +	iY=iB;
    1.44 +	iASquared=iA*iA;
    1.45 +	iBSquared=iB*iB;
    1.46 +	iASquBSqu=iASquared*iBSquared;
    1.47 +	iD1=iBSquared-iASquared*iB+(iASquared>>1);
    1.48 +	if(width<=0 || height<=0)
    1.49 +		iStatus=EComplete;
    1.50 +	else if(width<=2 || height<=2)
    1.51 +		iStatus=ELine;
    1.52 +	else if(iA+iXAdj==0 || iB+iYAdj==0)
    1.53 +		iStatus=EComplete;
    1.54 +	else
    1.55 +		iStatus=EInitialised;
    1.56 +	}
    1.57 +
    1.58 +/**
    1.59 +Does the next stage in producing an ellipse by taking four points (the corners of 
    1.60 +the rectangle the ellipse should fill) as parameters. Updates TEllipse status 
    1.61 +accordingly and calls <code>Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight)</code>.
    1.62 +@param aTopLeft Top left corner of rectangle 
    1.63 +@param aTopRight Top right corner of rectangle
    1.64 +@param aBottomLeft Bottom left corner of rectangle
    1.65 +@param aBottomRight Bottom right corner of rectangle
    1.66 +@return TBool ETrue if step completed successfully.
    1.67 +*/
    1.68 +EXPORT_C TBool TEllipse::SingleStep(TPoint& aTopLeft,TPoint& aTopRight,
    1.69 +									TPoint& aBottomLeft,TPoint& aBottomRight)
    1.70 +	{
    1.71 +	TBool ret=EFalse;
    1.72 +	if(iStatus==EFirstSector)
    1.73 +		{
    1.74 +		if(iD1<0)
    1.75 +			iD1+=iBSquared*((iX<<1)+3);
    1.76 +		else if(iY>0)
    1.77 +			{
    1.78 +			iD1+=iBSquared*((iX<<1)+3)+iASquared*(2-(iY<<1));
    1.79 +			iY--;
    1.80 +			}
    1.81 +		iX++;
    1.82 +		ret=Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
    1.83 +		if(iStatus==EComplete && iX<iA)
    1.84 +			{
    1.85 +			iStatus=EFirstSector;
    1.86 +			return(EFalse);
    1.87 +			}
    1.88 +		if(iASquared*iY<=iBSquared*(iX+1) && ret==EFalse)
    1.89 +			{
    1.90 +			iStatus=ESecondSector;
    1.91 +			iD2=-iASquBSqu+iBSquared*iX*iX+iASquared*(iY-1)*(iY-1);
    1.92 +			}
    1.93 +		return(ret);
    1.94 +		}
    1.95 +	if(iStatus==ESecondSector)
    1.96 +		{
    1.97 +		if(iD2<0)
    1.98 +			{
    1.99 +			iD2+=iBSquared*((iX<<1)+2)+iASquared*(3-(iY<<1));
   1.100 +			iX++;
   1.101 +			}
   1.102 +		else
   1.103 +			iD2+=iASquared*(3-(iY<<1));
   1.104 +		iY--;
   1.105 +		return(Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight));
   1.106 +		}
   1.107 +	if(iStatus==ELine)
   1.108 +		{
   1.109 +		ret=Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
   1.110 +		if(iA==0)
   1.111 +			iY--;
   1.112 +		else
   1.113 +			{
   1.114 +			iX++;
   1.115 +			if(iX>iA+iXAdj) ret=ETrue;
   1.116 +			else
   1.117 +				{
   1.118 +				iStatus=ELine;
   1.119 +				ret=EFalse;
   1.120 +				}
   1.121 +			}
   1.122 +		return(ret);
   1.123 +		}
   1.124 +	if(iStatus==EInitialised)
   1.125 +		{
   1.126 +		iStatus=EFirstSector;
   1.127 +		return(Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight));
   1.128 +		}
   1.129 +	Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
   1.130 +	return(ETrue);
   1.131 +	}
   1.132 +
   1.133 +/**
   1.134 +Sets the absolute points that define the ellipse as calculated using its iOffset 
   1.135 +from the origin and using the half width and half height of the rectangle iA and iB.
   1.136 +@param aTopLeft The absolute (x,y) position for the top left point.
   1.137 +@param aTopRight The absolute (x,y) position for the top right point.
   1.138 +@param aBottomLeft The absolute (x,y) position for the bottom left point.
   1.139 +@param aBottomRight The absolute (x,y) position for the bottom right point.
   1.140 +@return TBool ETrue if a valid rectangle is produced, else EFalse. Also sets
   1.141 +iStatus to EComplete.
   1.142 +*/
   1.143 +EXPORT_C TBool TEllipse::Output(TPoint& aTopLeft,TPoint& aTopRight,
   1.144 +								TPoint& aBottomLeft,TPoint& aBottomRight)
   1.145 +	{
   1.146 +	TInt lx=iA-iX+iOffset.iX;
   1.147 +	TInt ty=iB-iY+iOffset.iY;
   1.148 +	TInt rx=iA+iX+iXAdj+iOffset.iX;
   1.149 +	TInt by=iB+iY+iYAdj+iOffset.iY;
   1.150 +	aTopLeft.SetXY(lx,ty);
   1.151 +	aTopRight.SetXY(rx,ty);
   1.152 +	aBottomLeft.SetXY(lx,by);
   1.153 +	aBottomRight.SetXY(rx,by);
   1.154 +	if(iY<=0)
   1.155 +		{
   1.156 +		iStatus=EComplete;
   1.157 +		if(iYAdj==0 || ty>by)
   1.158 +			return(ETrue);
   1.159 +		}
   1.160 +	return(EFalse);
   1.161 +	}
   1.162 +
   1.163 +/**
   1.164 +By analysing the current state of the ellipse the process is taken to the next appropriate step.
   1.165 +If iStatus = EInitialised only one step will be taken, if the ellipse is already semi constructed then 
   1.166 +it will be taken to completion. Takes in four point parameters that defines the rectangle in order to pass to 
   1.167 +SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight).
   1.168 +@param aTopLeft Top left corner of rectangle 
   1.169 +@param aTopRight Top right corner of rectangle
   1.170 +@param aBottomLeft Bottom left corner of rectangle
   1.171 +@param aBottomRight Bottom right corner of rectangle
   1.172 +@return TBool ETrue if a valid rectangle is produced, else EFalse.
   1.173 +*/
   1.174 +EXPORT_C TBool TEllipse::NextStep(TPoint& aTopLeft,TPoint& aTopRight,
   1.175 +								  TPoint& aBottomLeft,TPoint& aBottomRight)
   1.176 +	{
   1.177 +	if(iStatus==EInitialised)
   1.178 +		return(SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight));
   1.179 +	TInt prevlev=iY;
   1.180 +	TBool ret;
   1.181 +	do
   1.182 +		ret=SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
   1.183 +	while(prevlev==iY && ret==EFalse);
   1.184 +	return(ret);
   1.185 +	}
   1.186 +
   1.187 +/**
   1.188 +Constructs an ellipse from the rectangle which it is given and assesses the 
   1.189 +points position with regard to the ellipse and where they intersect. 
   1.190 +@param aRect The rectangle within which the ellipse is drawn.
   1.191 +@param aPoint A point to compare with the ellipse to determine if intersection occurs. 
   1.192 +@return TPoint The point is set to the corner which the intersection is nearest to.
   1.193 +*/
   1.194 +EXPORT_C TPoint TEllipse::Intersection(const TRect& aRect,const TPoint& aPoint)
   1.195 +	{
   1.196 +	Construct(aRect);					//constructs the rect (an elipse object)
   1.197 +	TPoint centre=aRect.Center();		//centre of ellipse
   1.198 +	TPoint ptcpy(aPoint);				
   1.199 +	ptcpy-=iOffset;						//ptcpy = aPoint - iOffset - TPoint(iA,iB)	//radius from centre of ellipse		
   1.200 +	ptcpy-=TPoint(iA,iB);				
   1.201 +	TPoint pt[4],opt[4];			
   1.202 +	TInt mpt[4],ompt[4];
   1.203 +	TInt count=0;
   1.204 +	for(;count<4;count++)
   1.205 +		ompt[count]=KMaxTInt;			//fills ompt 1->4 with KMaxTInt
   1.206 +	while(SingleStep(pt[0],pt[1],pt[2],pt[3])==EFalse) 	//creates a complete ellipse with pts as rect
   1.207 +		for(count=0;count<4;count++)
   1.208 +			{
   1.209 +			mpt[count]=Abs((pt[count].iY-iOffset.iY-iB)*(ptcpy.iX)-(ptcpy.iY)*(pt[count].iX-iOffset.iX-iA));
   1.210 +			if(mpt[count]<ompt[count]) //use the larger number set.
   1.211 +				{
   1.212 +				ompt[count]=mpt[count];
   1.213 +				opt[count]=pt[count];
   1.214 +				}						
   1.215 +			}
   1.216 +	if(pt[0].iY==pt[2].iY)	//if it is horizontal
   1.217 +		for(count=0;count<4;count++)
   1.218 +			{
   1.219 +			mpt[count]=Abs((pt[count].iY-iOffset.iY-iB)*(ptcpy.iX)-(ptcpy.iY)*(pt[count].iX-iOffset.iX-iA));
   1.220 +			if(mpt[count]<ompt[count]) //use the larger number set.
   1.221 +				{
   1.222 +				ompt[count]=mpt[count];
   1.223 +				opt[count]=pt[count];
   1.224 +				}
   1.225 +			}
   1.226 +	if(ptcpy.iX<0 && ptcpy.iY<0)	//if point is further left and higher than centre of rect
   1.227 +		return(opt[0]);
   1.228 +	if(ptcpy.iY<0)			//if point is higher than centre of rect
   1.229 +		return(opt[1]);
   1.230 +	if(ptcpy.iX<0)			//if point is further left than centre of rect
   1.231 +		return(opt[2]);
   1.232 +	if(aPoint.iX<centre.iX && aPoint.iY<centre.iY)	//if point is further left and higher than centre of rect
   1.233 +		return(opt[0]);
   1.234 +	if(aPoint.iY<centre.iY)	//if point is higher than centre of rect
   1.235 +		return(opt[1]);
   1.236 +	if(aPoint.iX<centre.iX)	//if point is further left than centre of rect
   1.237 +		return(opt[2]);
   1.238 +	return(opt[3]);			//else 
   1.239 +	}
   1.240 +
   1.241 +//
   1.242 +// Ellipse drawing
   1.243 +//
   1.244 +
   1.245 +/**
   1.246 +Draws and fills an ellipse.
   1.247 +
   1.248 +The function provides a concrete implementation of the pure virtual
   1.249 +function <code>CGraphicsContext::DrawEllipse()</code>. The function
   1.250 +behaviour is the same as documented in that class.
   1.251 +*/
   1.252 +EXPORT_C void CFbsBitGc::DrawEllipse(const TRect& aRect)
   1.253 +	{
   1.254 +	if(CheckDevice(aRect)) return;
   1.255 +	TRect rcpy(aRect);
   1.256 +	rcpy.Move(iOrigin);
   1.257 +	iDevice->TruncateRect(rcpy);
   1.258 +	TRect clippedRect(rcpy);
   1.259 +	clippedRect.Grow((iPenSize.iWidth>>1)+1,(iPenSize.iHeight>>1)+1);
   1.260 +	if(UserClipRect(clippedRect)) return;
   1.261 +	SetupDevice();
   1.262 +	iDevice->DrawingBegin(&iBrushBitmap);
   1.263 +	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
   1.264 +	if(iBrushStyle!=ENullBrush)
   1.265 +		EllipseFill(rcpy);
   1.266 +	if(iPenStyle!=ENullPen)
   1.267 +		{
   1.268 +		if(iPenSize.iWidth>1 && iPenSize.iHeight>1)
   1.269 +			EllipseOutlineWide(rcpy);
   1.270 +		else
   1.271 +			if(iPenSize.iWidth==1 || iPenSize.iHeight==1)
   1.272 +				EllipseOutline(rcpy);
   1.273 +		}
   1.274 +	if (brushRasterizer)
   1.275 +		{
   1.276 +		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
   1.277 +		}
   1.278 +	iDevice->DrawingEnd(&iBrushBitmap);
   1.279 +	}
   1.280 +
   1.281 +void CFbsBitGc::EllipseOutline(const TRect& aRect)
   1.282 +	{
   1.283 +	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
   1.284 +	TPoint tl,tr,bl,br;
   1.285 +	AddRect(aRect);
   1.286 +#if defined(_DEBUG)
   1.287 +	TRect deviceDestRect;
   1.288 +	drawDevice->GetDrawRect(deviceDestRect);
   1.289 +#endif
   1.290 +	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
   1.291 +		{
   1.292 +		iClipRect=(*iDefaultRegionPtr)[count];
   1.293 +		if(!iClipRect.Intersects(aRect))
   1.294 +			continue;
   1.295 +		iClipRect.Intersection(aRect);
   1.296 +		if(UserClipRect(iClipRect)) continue;
   1.297 +		BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
   1.298 +		BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
   1.299 +		BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
   1.300 +		BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
   1.301 +		TEllipse ellipse;
   1.302 +		ellipse.Construct(aRect);
   1.303 +		TInt pattern=0;
   1.304 +		while(!ellipse.SingleStep(tl,tr,bl,br))
   1.305 +			{
   1.306 +			if(iPenStyle==CGraphicsContext::ESolidPen || (iDotMask&(1<<(pattern%iDotLength))))
   1.307 +				{
   1.308 +				if(tl.iY>=iClipRect.iTl.iY && tl.iY<iClipRect.iBr.iY)
   1.309 +					{
   1.310 +					if(tl.iX>=iClipRect.iTl.iX && tl.iX<iClipRect.iBr.iX)
   1.311 +						drawDevice->WriteRgb(tl.iX,tl.iY,iPenColor,iDrawMode);
   1.312 +					if(tr.iX>=iClipRect.iTl.iX && tr.iX<iClipRect.iBr.iX && tl.iX!=tr.iX)
   1.313 +						drawDevice->WriteRgb(tr.iX,tr.iY,iPenColor,iDrawMode);
   1.314 +					}
   1.315 +				if(bl.iY>=iClipRect.iTl.iY && bl.iY<iClipRect.iBr.iY)
   1.316 +					{
   1.317 +					if(bl.iX>=iClipRect.iTl.iX && bl.iX<iClipRect.iBr.iX)
   1.318 +						drawDevice->WriteRgb(bl.iX,bl.iY,iPenColor,iDrawMode);
   1.319 +					if(br.iX>=iClipRect.iTl.iX && br.iX<iClipRect.iBr.iX && bl.iX!=br.iX)
   1.320 +						drawDevice->WriteRgb(br.iX,br.iY,iPenColor,iDrawMode);
   1.321 +					}
   1.322 +				}
   1.323 +			pattern++;
   1.324 +			}
   1.325 +		if(tl.iY==bl.iY && tl.iY>=iClipRect.iTl.iY && tl.iY<iClipRect.iBr.iY)
   1.326 +			{
   1.327 +			if(tl.iX>=iClipRect.iTl.iX && tl.iX<iClipRect.iBr.iX)
   1.328 +				drawDevice->WriteRgb(tl.iX,tl.iY,iPenColor,iDrawMode);
   1.329 +			if(tr.iX>=iClipRect.iTl.iX && tr.iX<iClipRect.iBr.iX && tl.iX!=tr.iX)
   1.330 +				drawDevice->WriteRgb(tr.iX,tr.iY,iPenColor,iDrawMode);
   1.331 +			}
   1.332 +		drawDevice->UpdateRegion(iClipRect);
   1.333 +		}
   1.334 +	}
   1.335 +
   1.336 +void CFbsBitGc::EllipseOutlineWide(const TRect& aRect)
   1.337 +	{
   1.338 +	TRect rcpy(aRect);
   1.339 +	TPoint tl,tr,bl,br;
   1.340 +	TInt halfpenwidth=(iPenSize.iWidth+1)>>1;
   1.341 +	TInt halfpenheight=(iPenSize.iHeight+1)>>1;
   1.342 +	rcpy.Grow(halfpenwidth,halfpenheight);
   1.343 +	AddRect(rcpy);
   1.344 +	TInt dp=iDotParam;
   1.345 +	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
   1.346 +		{
   1.347 +		iClipRect=(*iDefaultRegionPtr)[count];
   1.348 +		if(!iClipRect.Intersects(rcpy))
   1.349 +			continue;
   1.350 +		iClipRect.Intersection(rcpy);
   1.351 +		if(UserClipRect(iClipRect)) continue;
   1.352 +		TEllipse ellipse;
   1.353 +		ellipse.Construct(aRect);
   1.354 +		iDotParam=Max(iPenSize.iWidth>>1,iPenSize.iHeight>>1);
   1.355 +		while(!ellipse.SingleStep(tl,tr,bl,br))
   1.356 +			{
   1.357 +			PenDrawClipped(tl);
   1.358 +			PenDrawClipped(tr);
   1.359 +			PenDrawClipped(bl);
   1.360 +			PenDrawClipped(br);
   1.361 +			iDotParam+=iDotDirection;
   1.362 +			}
   1.363 +		if(tl.iY==bl.iY)
   1.364 +			{
   1.365 +			PenDrawClipped(tl);
   1.366 +			PenDrawClipped(tr);
   1.367 +			}
   1.368 +		iDevice->iDrawDevice->UpdateRegion(iClipRect);
   1.369 +		}
   1.370 +	iDotParam=dp;
   1.371 +	}
   1.372 +
   1.373 +// if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
   1.374 +void CFbsBitGc::EllipseFill(const TRect& aRect)
   1.375 +	{
   1.376 +	TRect rcpy(aRect);
   1.377 +	if(iPenSize.iWidth==0 || iPenSize.iHeight==0)
   1.378 +		rcpy.Grow(1,1);
   1.379 +	AddRect(aRect);
   1.380 +	TPoint tl,tr,bl,br;
   1.381 +	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
   1.382 +		{
   1.383 +		iClipRect=(*iDefaultRegionPtr)[count];
   1.384 +		if(!iClipRect.Intersects(rcpy))
   1.385 +			continue;
   1.386 +		iClipRect.Intersection(rcpy);
   1.387 +		if(UserClipRect(iClipRect)) continue;
   1.388 +		TEllipse ellipse;
   1.389 +		ellipse.Construct(rcpy);
   1.390 +		while(!ellipse.NextStep(tl,tr,bl,br))
   1.391 +			{
   1.392 +			tl.iX++;
   1.393 +			tr.iX--;
   1.394 +			bl.iX++;
   1.395 +			br.iX--;
   1.396 +			ClipFillLine(tl,tr);
   1.397 +			ClipFillLine(bl,br);
   1.398 +			}
   1.399 +		if(tl.iY==bl.iY)
   1.400 +			{
   1.401 +			tl.iX++;
   1.402 +			tr.iX--;
   1.403 +			ClipFillLine(tl,tr);
   1.404 +			}
   1.405 +		iDevice->iDrawDevice->UpdateRegion(iClipRect);
   1.406 +		}
   1.407 +	}
   1.408 +