os/graphics/graphicsdeviceinterface/bitgdi/sbit/ELLIPSE.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include <bitstd.h>
sl@0
    17
#include <bitdev.h>
sl@0
    18
#include "BITPANIC.H"
sl@0
    19
#include <bitdraw.h>
sl@0
    20
#include <graphics/fbsrasterizer.h>
sl@0
    21
sl@0
    22
/*
sl@0
    23
 * TEllipse
sl@0
    24
 */
sl@0
    25
 
sl@0
    26
 /**
sl@0
    27
 Initialises the values of the ellipse so that it conforms to a rectangle entered as a parameter.
sl@0
    28
 @param aRect the rectangle within which the ellipse is drawn
sl@0
    29
 */
sl@0
    30
EXPORT_C void TEllipse::Construct(const TRect& aRect)
sl@0
    31
	{
sl@0
    32
	TInt width=aRect.Width();
sl@0
    33
	TInt height=aRect.Height();
sl@0
    34
	iA=(width-1)>>1;
sl@0
    35
	iB=(height-1)>>1;
sl@0
    36
	iXAdj=(width+1)&1;
sl@0
    37
	iYAdj=(height+1)&1;
sl@0
    38
	iOffset=aRect.iTl;
sl@0
    39
	iX=0;
sl@0
    40
	iY=iB;
sl@0
    41
	iASquared=iA*iA;
sl@0
    42
	iBSquared=iB*iB;
sl@0
    43
	iASquBSqu=iASquared*iBSquared;
sl@0
    44
	iD1=iBSquared-iASquared*iB+(iASquared>>1);
sl@0
    45
	if(width<=0 || height<=0)
sl@0
    46
		iStatus=EComplete;
sl@0
    47
	else if(width<=2 || height<=2)
sl@0
    48
		iStatus=ELine;
sl@0
    49
	else if(iA+iXAdj==0 || iB+iYAdj==0)
sl@0
    50
		iStatus=EComplete;
sl@0
    51
	else
sl@0
    52
		iStatus=EInitialised;
sl@0
    53
	}
sl@0
    54
sl@0
    55
/**
sl@0
    56
Does the next stage in producing an ellipse by taking four points (the corners of 
sl@0
    57
the rectangle the ellipse should fill) as parameters. Updates TEllipse status 
sl@0
    58
accordingly and calls <code>Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight)</code>.
sl@0
    59
@param aTopLeft Top left corner of rectangle 
sl@0
    60
@param aTopRight Top right corner of rectangle
sl@0
    61
@param aBottomLeft Bottom left corner of rectangle
sl@0
    62
@param aBottomRight Bottom right corner of rectangle
sl@0
    63
@return TBool ETrue if step completed successfully.
sl@0
    64
*/
sl@0
    65
EXPORT_C TBool TEllipse::SingleStep(TPoint& aTopLeft,TPoint& aTopRight,
sl@0
    66
									TPoint& aBottomLeft,TPoint& aBottomRight)
sl@0
    67
	{
sl@0
    68
	TBool ret=EFalse;
sl@0
    69
	if(iStatus==EFirstSector)
sl@0
    70
		{
sl@0
    71
		if(iD1<0)
sl@0
    72
			iD1+=iBSquared*((iX<<1)+3);
sl@0
    73
		else if(iY>0)
sl@0
    74
			{
sl@0
    75
			iD1+=iBSquared*((iX<<1)+3)+iASquared*(2-(iY<<1));
sl@0
    76
			iY--;
sl@0
    77
			}
sl@0
    78
		iX++;
sl@0
    79
		ret=Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
sl@0
    80
		if(iStatus==EComplete && iX<iA)
sl@0
    81
			{
sl@0
    82
			iStatus=EFirstSector;
sl@0
    83
			return(EFalse);
sl@0
    84
			}
sl@0
    85
		if(iASquared*iY<=iBSquared*(iX+1) && ret==EFalse)
sl@0
    86
			{
sl@0
    87
			iStatus=ESecondSector;
sl@0
    88
			iD2=-iASquBSqu+iBSquared*iX*iX+iASquared*(iY-1)*(iY-1);
sl@0
    89
			}
sl@0
    90
		return(ret);
sl@0
    91
		}
sl@0
    92
	if(iStatus==ESecondSector)
sl@0
    93
		{
sl@0
    94
		if(iD2<0)
sl@0
    95
			{
sl@0
    96
			iD2+=iBSquared*((iX<<1)+2)+iASquared*(3-(iY<<1));
sl@0
    97
			iX++;
sl@0
    98
			}
sl@0
    99
		else
sl@0
   100
			iD2+=iASquared*(3-(iY<<1));
sl@0
   101
		iY--;
sl@0
   102
		return(Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight));
sl@0
   103
		}
sl@0
   104
	if(iStatus==ELine)
sl@0
   105
		{
sl@0
   106
		ret=Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
sl@0
   107
		if(iA==0)
sl@0
   108
			iY--;
sl@0
   109
		else
sl@0
   110
			{
sl@0
   111
			iX++;
sl@0
   112
			if(iX>iA+iXAdj) ret=ETrue;
sl@0
   113
			else
sl@0
   114
				{
sl@0
   115
				iStatus=ELine;
sl@0
   116
				ret=EFalse;
sl@0
   117
				}
sl@0
   118
			}
sl@0
   119
		return(ret);
sl@0
   120
		}
sl@0
   121
	if(iStatus==EInitialised)
sl@0
   122
		{
sl@0
   123
		iStatus=EFirstSector;
sl@0
   124
		return(Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight));
sl@0
   125
		}
sl@0
   126
	Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
sl@0
   127
	return(ETrue);
sl@0
   128
	}
sl@0
   129
sl@0
   130
/**
sl@0
   131
Sets the absolute points that define the ellipse as calculated using its iOffset 
sl@0
   132
from the origin and using the half width and half height of the rectangle iA and iB.
sl@0
   133
@param aTopLeft The absolute (x,y) position for the top left point.
sl@0
   134
@param aTopRight The absolute (x,y) position for the top right point.
sl@0
   135
@param aBottomLeft The absolute (x,y) position for the bottom left point.
sl@0
   136
@param aBottomRight The absolute (x,y) position for the bottom right point.
sl@0
   137
@return TBool ETrue if a valid rectangle is produced, else EFalse. Also sets
sl@0
   138
iStatus to EComplete.
sl@0
   139
*/
sl@0
   140
EXPORT_C TBool TEllipse::Output(TPoint& aTopLeft,TPoint& aTopRight,
sl@0
   141
								TPoint& aBottomLeft,TPoint& aBottomRight)
sl@0
   142
	{
sl@0
   143
	TInt lx=iA-iX+iOffset.iX;
sl@0
   144
	TInt ty=iB-iY+iOffset.iY;
sl@0
   145
	TInt rx=iA+iX+iXAdj+iOffset.iX;
sl@0
   146
	TInt by=iB+iY+iYAdj+iOffset.iY;
sl@0
   147
	aTopLeft.SetXY(lx,ty);
sl@0
   148
	aTopRight.SetXY(rx,ty);
sl@0
   149
	aBottomLeft.SetXY(lx,by);
sl@0
   150
	aBottomRight.SetXY(rx,by);
sl@0
   151
	if(iY<=0)
sl@0
   152
		{
sl@0
   153
		iStatus=EComplete;
sl@0
   154
		if(iYAdj==0 || ty>by)
sl@0
   155
			return(ETrue);
sl@0
   156
		}
sl@0
   157
	return(EFalse);
sl@0
   158
	}
sl@0
   159
sl@0
   160
/**
sl@0
   161
By analysing the current state of the ellipse the process is taken to the next appropriate step.
sl@0
   162
If iStatus = EInitialised only one step will be taken, if the ellipse is already semi constructed then 
sl@0
   163
it will be taken to completion. Takes in four point parameters that defines the rectangle in order to pass to 
sl@0
   164
SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight).
sl@0
   165
@param aTopLeft Top left corner of rectangle 
sl@0
   166
@param aTopRight Top right corner of rectangle
sl@0
   167
@param aBottomLeft Bottom left corner of rectangle
sl@0
   168
@param aBottomRight Bottom right corner of rectangle
sl@0
   169
@return TBool ETrue if a valid rectangle is produced, else EFalse.
sl@0
   170
*/
sl@0
   171
EXPORT_C TBool TEllipse::NextStep(TPoint& aTopLeft,TPoint& aTopRight,
sl@0
   172
								  TPoint& aBottomLeft,TPoint& aBottomRight)
sl@0
   173
	{
sl@0
   174
	if(iStatus==EInitialised)
sl@0
   175
		return(SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight));
sl@0
   176
	TInt prevlev=iY;
sl@0
   177
	TBool ret;
sl@0
   178
	do
sl@0
   179
		ret=SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
sl@0
   180
	while(prevlev==iY && ret==EFalse);
sl@0
   181
	return(ret);
sl@0
   182
	}
sl@0
   183
sl@0
   184
/**
sl@0
   185
Constructs an ellipse from the rectangle which it is given and assesses the 
sl@0
   186
points position with regard to the ellipse and where they intersect. 
sl@0
   187
@param aRect The rectangle within which the ellipse is drawn.
sl@0
   188
@param aPoint A point to compare with the ellipse to determine if intersection occurs. 
sl@0
   189
@return TPoint The point is set to the corner which the intersection is nearest to.
sl@0
   190
*/
sl@0
   191
EXPORT_C TPoint TEllipse::Intersection(const TRect& aRect,const TPoint& aPoint)
sl@0
   192
	{
sl@0
   193
	Construct(aRect);					//constructs the rect (an elipse object)
sl@0
   194
	TPoint centre=aRect.Center();		//centre of ellipse
sl@0
   195
	TPoint ptcpy(aPoint);				
sl@0
   196
	ptcpy-=iOffset;						//ptcpy = aPoint - iOffset - TPoint(iA,iB)	//radius from centre of ellipse		
sl@0
   197
	ptcpy-=TPoint(iA,iB);				
sl@0
   198
	TPoint pt[4],opt[4];			
sl@0
   199
	TInt mpt[4],ompt[4];
sl@0
   200
	TInt count=0;
sl@0
   201
	for(;count<4;count++)
sl@0
   202
		ompt[count]=KMaxTInt;			//fills ompt 1->4 with KMaxTInt
sl@0
   203
	while(SingleStep(pt[0],pt[1],pt[2],pt[3])==EFalse) 	//creates a complete ellipse with pts as rect
sl@0
   204
		for(count=0;count<4;count++)
sl@0
   205
			{
sl@0
   206
			mpt[count]=Abs((pt[count].iY-iOffset.iY-iB)*(ptcpy.iX)-(ptcpy.iY)*(pt[count].iX-iOffset.iX-iA));
sl@0
   207
			if(mpt[count]<ompt[count]) //use the larger number set.
sl@0
   208
				{
sl@0
   209
				ompt[count]=mpt[count];
sl@0
   210
				opt[count]=pt[count];
sl@0
   211
				}						
sl@0
   212
			}
sl@0
   213
	if(pt[0].iY==pt[2].iY)	//if it is horizontal
sl@0
   214
		for(count=0;count<4;count++)
sl@0
   215
			{
sl@0
   216
			mpt[count]=Abs((pt[count].iY-iOffset.iY-iB)*(ptcpy.iX)-(ptcpy.iY)*(pt[count].iX-iOffset.iX-iA));
sl@0
   217
			if(mpt[count]<ompt[count]) //use the larger number set.
sl@0
   218
				{
sl@0
   219
				ompt[count]=mpt[count];
sl@0
   220
				opt[count]=pt[count];
sl@0
   221
				}
sl@0
   222
			}
sl@0
   223
	if(ptcpy.iX<0 && ptcpy.iY<0)	//if point is further left and higher than centre of rect
sl@0
   224
		return(opt[0]);
sl@0
   225
	if(ptcpy.iY<0)			//if point is higher than centre of rect
sl@0
   226
		return(opt[1]);
sl@0
   227
	if(ptcpy.iX<0)			//if point is further left than centre of rect
sl@0
   228
		return(opt[2]);
sl@0
   229
	if(aPoint.iX<centre.iX && aPoint.iY<centre.iY)	//if point is further left and higher than centre of rect
sl@0
   230
		return(opt[0]);
sl@0
   231
	if(aPoint.iY<centre.iY)	//if point is higher than centre of rect
sl@0
   232
		return(opt[1]);
sl@0
   233
	if(aPoint.iX<centre.iX)	//if point is further left than centre of rect
sl@0
   234
		return(opt[2]);
sl@0
   235
	return(opt[3]);			//else 
sl@0
   236
	}
sl@0
   237
sl@0
   238
//
sl@0
   239
// Ellipse drawing
sl@0
   240
//
sl@0
   241
sl@0
   242
/**
sl@0
   243
Draws and fills an ellipse.
sl@0
   244
sl@0
   245
The function provides a concrete implementation of the pure virtual
sl@0
   246
function <code>CGraphicsContext::DrawEllipse()</code>. The function
sl@0
   247
behaviour is the same as documented in that class.
sl@0
   248
*/
sl@0
   249
EXPORT_C void CFbsBitGc::DrawEllipse(const TRect& aRect)
sl@0
   250
	{
sl@0
   251
	if(CheckDevice(aRect)) return;
sl@0
   252
	TRect rcpy(aRect);
sl@0
   253
	rcpy.Move(iOrigin);
sl@0
   254
	iDevice->TruncateRect(rcpy);
sl@0
   255
	TRect clippedRect(rcpy);
sl@0
   256
	clippedRect.Grow((iPenSize.iWidth>>1)+1,(iPenSize.iHeight>>1)+1);
sl@0
   257
	if(UserClipRect(clippedRect)) return;
sl@0
   258
	SetupDevice();
sl@0
   259
	iDevice->DrawingBegin(&iBrushBitmap);
sl@0
   260
	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
sl@0
   261
	if(iBrushStyle!=ENullBrush)
sl@0
   262
		EllipseFill(rcpy);
sl@0
   263
	if(iPenStyle!=ENullPen)
sl@0
   264
		{
sl@0
   265
		if(iPenSize.iWidth>1 && iPenSize.iHeight>1)
sl@0
   266
			EllipseOutlineWide(rcpy);
sl@0
   267
		else
sl@0
   268
			if(iPenSize.iWidth==1 || iPenSize.iHeight==1)
sl@0
   269
				EllipseOutline(rcpy);
sl@0
   270
		}
sl@0
   271
	if (brushRasterizer)
sl@0
   272
		{
sl@0
   273
		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
sl@0
   274
		}
sl@0
   275
	iDevice->DrawingEnd(&iBrushBitmap);
sl@0
   276
	}
sl@0
   277
sl@0
   278
void CFbsBitGc::EllipseOutline(const TRect& aRect)
sl@0
   279
	{
sl@0
   280
	CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
sl@0
   281
	TPoint tl,tr,bl,br;
sl@0
   282
	AddRect(aRect);
sl@0
   283
#if defined(_DEBUG)
sl@0
   284
	TRect deviceDestRect;
sl@0
   285
	drawDevice->GetDrawRect(deviceDestRect);
sl@0
   286
#endif
sl@0
   287
	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
sl@0
   288
		{
sl@0
   289
		iClipRect=(*iDefaultRegionPtr)[count];
sl@0
   290
		if(!iClipRect.Intersects(aRect))
sl@0
   291
			continue;
sl@0
   292
		iClipRect.Intersection(aRect);
sl@0
   293
		if(UserClipRect(iClipRect)) continue;
sl@0
   294
		BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
sl@0
   295
		BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
sl@0
   296
		BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
sl@0
   297
		BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
sl@0
   298
		TEllipse ellipse;
sl@0
   299
		ellipse.Construct(aRect);
sl@0
   300
		TInt pattern=0;
sl@0
   301
		while(!ellipse.SingleStep(tl,tr,bl,br))
sl@0
   302
			{
sl@0
   303
			if(iPenStyle==CGraphicsContext::ESolidPen || (iDotMask&(1<<(pattern%iDotLength))))
sl@0
   304
				{
sl@0
   305
				if(tl.iY>=iClipRect.iTl.iY && tl.iY<iClipRect.iBr.iY)
sl@0
   306
					{
sl@0
   307
					if(tl.iX>=iClipRect.iTl.iX && tl.iX<iClipRect.iBr.iX)
sl@0
   308
						drawDevice->WriteRgb(tl.iX,tl.iY,iPenColor,iDrawMode);
sl@0
   309
					if(tr.iX>=iClipRect.iTl.iX && tr.iX<iClipRect.iBr.iX && tl.iX!=tr.iX)
sl@0
   310
						drawDevice->WriteRgb(tr.iX,tr.iY,iPenColor,iDrawMode);
sl@0
   311
					}
sl@0
   312
				if(bl.iY>=iClipRect.iTl.iY && bl.iY<iClipRect.iBr.iY)
sl@0
   313
					{
sl@0
   314
					if(bl.iX>=iClipRect.iTl.iX && bl.iX<iClipRect.iBr.iX)
sl@0
   315
						drawDevice->WriteRgb(bl.iX,bl.iY,iPenColor,iDrawMode);
sl@0
   316
					if(br.iX>=iClipRect.iTl.iX && br.iX<iClipRect.iBr.iX && bl.iX!=br.iX)
sl@0
   317
						drawDevice->WriteRgb(br.iX,br.iY,iPenColor,iDrawMode);
sl@0
   318
					}
sl@0
   319
				}
sl@0
   320
			pattern++;
sl@0
   321
			}
sl@0
   322
		if(tl.iY==bl.iY && tl.iY>=iClipRect.iTl.iY && tl.iY<iClipRect.iBr.iY)
sl@0
   323
			{
sl@0
   324
			if(tl.iX>=iClipRect.iTl.iX && tl.iX<iClipRect.iBr.iX)
sl@0
   325
				drawDevice->WriteRgb(tl.iX,tl.iY,iPenColor,iDrawMode);
sl@0
   326
			if(tr.iX>=iClipRect.iTl.iX && tr.iX<iClipRect.iBr.iX && tl.iX!=tr.iX)
sl@0
   327
				drawDevice->WriteRgb(tr.iX,tr.iY,iPenColor,iDrawMode);
sl@0
   328
			}
sl@0
   329
		drawDevice->UpdateRegion(iClipRect);
sl@0
   330
		}
sl@0
   331
	}
sl@0
   332
sl@0
   333
void CFbsBitGc::EllipseOutlineWide(const TRect& aRect)
sl@0
   334
	{
sl@0
   335
	TRect rcpy(aRect);
sl@0
   336
	TPoint tl,tr,bl,br;
sl@0
   337
	TInt halfpenwidth=(iPenSize.iWidth+1)>>1;
sl@0
   338
	TInt halfpenheight=(iPenSize.iHeight+1)>>1;
sl@0
   339
	rcpy.Grow(halfpenwidth,halfpenheight);
sl@0
   340
	AddRect(rcpy);
sl@0
   341
	TInt dp=iDotParam;
sl@0
   342
	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
sl@0
   343
		{
sl@0
   344
		iClipRect=(*iDefaultRegionPtr)[count];
sl@0
   345
		if(!iClipRect.Intersects(rcpy))
sl@0
   346
			continue;
sl@0
   347
		iClipRect.Intersection(rcpy);
sl@0
   348
		if(UserClipRect(iClipRect)) continue;
sl@0
   349
		TEllipse ellipse;
sl@0
   350
		ellipse.Construct(aRect);
sl@0
   351
		iDotParam=Max(iPenSize.iWidth>>1,iPenSize.iHeight>>1);
sl@0
   352
		while(!ellipse.SingleStep(tl,tr,bl,br))
sl@0
   353
			{
sl@0
   354
			PenDrawClipped(tl);
sl@0
   355
			PenDrawClipped(tr);
sl@0
   356
			PenDrawClipped(bl);
sl@0
   357
			PenDrawClipped(br);
sl@0
   358
			iDotParam+=iDotDirection;
sl@0
   359
			}
sl@0
   360
		if(tl.iY==bl.iY)
sl@0
   361
			{
sl@0
   362
			PenDrawClipped(tl);
sl@0
   363
			PenDrawClipped(tr);
sl@0
   364
			}
sl@0
   365
		iDevice->iDrawDevice->UpdateRegion(iClipRect);
sl@0
   366
		}
sl@0
   367
	iDotParam=dp;
sl@0
   368
	}
sl@0
   369
sl@0
   370
// if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
sl@0
   371
void CFbsBitGc::EllipseFill(const TRect& aRect)
sl@0
   372
	{
sl@0
   373
	TRect rcpy(aRect);
sl@0
   374
	if(iPenSize.iWidth==0 || iPenSize.iHeight==0)
sl@0
   375
		rcpy.Grow(1,1);
sl@0
   376
	AddRect(aRect);
sl@0
   377
	TPoint tl,tr,bl,br;
sl@0
   378
	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
sl@0
   379
		{
sl@0
   380
		iClipRect=(*iDefaultRegionPtr)[count];
sl@0
   381
		if(!iClipRect.Intersects(rcpy))
sl@0
   382
			continue;
sl@0
   383
		iClipRect.Intersection(rcpy);
sl@0
   384
		if(UserClipRect(iClipRect)) continue;
sl@0
   385
		TEllipse ellipse;
sl@0
   386
		ellipse.Construct(rcpy);
sl@0
   387
		while(!ellipse.NextStep(tl,tr,bl,br))
sl@0
   388
			{
sl@0
   389
			tl.iX++;
sl@0
   390
			tr.iX--;
sl@0
   391
			bl.iX++;
sl@0
   392
			br.iX--;
sl@0
   393
			ClipFillLine(tl,tr);
sl@0
   394
			ClipFillLine(bl,br);
sl@0
   395
			}
sl@0
   396
		if(tl.iY==bl.iY)
sl@0
   397
			{
sl@0
   398
			tl.iX++;
sl@0
   399
			tr.iX--;
sl@0
   400
			ClipFillLine(tl,tr);
sl@0
   401
			}
sl@0
   402
		iDevice->iDrawDevice->UpdateRegion(iClipRect);
sl@0
   403
		}
sl@0
   404
	}
sl@0
   405