sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "directgdiadapter.h" sl@0: #include "swdirectgdiellipse.h" sl@0: #include "swdirectgdiengine.h" sl@0: sl@0: /* sl@0: * TSwDirectGdiEllipse sl@0: */ sl@0: sl@0: /** sl@0: Initialises the values of the ellipse so that it conforms to a rectangle entered as a parameter. sl@0: @param aRect the rectangle within which the ellipse is drawn sl@0: */ sl@0: void TSwDirectGdiEllipse::Construct(const TRect& aRect) sl@0: { sl@0: TInt width = aRect.Width(); sl@0: TInt height = aRect.Height(); sl@0: iA = (width-1) >> 1; sl@0: iB = (height-1) >> 1; sl@0: iXAdj = (width+1) & 1; sl@0: iYAdj = (height+1) & 1; sl@0: iOffset = aRect.iTl; sl@0: iX = 0; sl@0: iY = iB; sl@0: iASquared = iA * iA; sl@0: iBSquared = iB * iB; sl@0: iASquBSqu = iASquared * iBSquared; sl@0: iD1 = iBSquared - iASquared * iB + (iASquared>>1); sl@0: if (width<=0 || height<=0) sl@0: { sl@0: iStatus = EComplete; sl@0: } sl@0: else if (width<=2 || height<=2) sl@0: { sl@0: iStatus = ELine; sl@0: } sl@0: else sl@0: { sl@0: iStatus = EInitialised; sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Does the next stage in producing an ellipse by taking four points (the corners of sl@0: the rectangle the ellipse should fill) as parameters. Updates TSwDirectGdiEllipse status sl@0: accordingly and calls Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight). sl@0: sl@0: @param aTopLeft Top left corner of rectangle. sl@0: @param aTopRight Top right corner of rectangle. sl@0: @param aBottomLeft Bottom left corner of rectangle. sl@0: @param aBottomRight Bottom right corner of rectangle. sl@0: @return TBool ETrue if step completed successfully. sl@0: */ sl@0: TBool TSwDirectGdiEllipse::SingleStep(TPoint& aTopLeft, TPoint& aTopRight, sl@0: TPoint& aBottomLeft, TPoint& aBottomRight) sl@0: { sl@0: TBool ret = EFalse; sl@0: if (iStatus == EFirstSector) sl@0: { sl@0: if (iD1 < 0) sl@0: { sl@0: iD1 += iBSquared * ((iX<<1)+3); sl@0: } sl@0: else if (iY > 0) sl@0: { sl@0: iD1 += iBSquared * ((iX<<1)+3) + iASquared * (2-(iY<<1)); sl@0: iY--; sl@0: } sl@0: iX++; sl@0: ret = Output(aTopLeft,aTopRight,aBottomLeft,aBottomRight); sl@0: if (iStatus == EComplete && iX iA+iXAdj) sl@0: { sl@0: ret = ETrue; sl@0: } sl@0: else sl@0: { sl@0: iStatus = ELine; sl@0: ret = EFalse; sl@0: } sl@0: } sl@0: return ret; sl@0: } sl@0: if (iStatus == EInitialised) sl@0: { sl@0: iStatus = EFirstSector; sl@0: return Output(aTopLeft, aTopRight, aBottomLeft, aBottomRight); sl@0: } sl@0: Output(aTopLeft, aTopRight, aBottomLeft, aBottomRight); sl@0: return ETrue; sl@0: } sl@0: sl@0: /** sl@0: Sets the absolute points that define the ellipse as calculated using its iOffset sl@0: from the origin and using the half width and half height of the rectangle iA and iB. sl@0: sl@0: @param aTopLeft The absolute (x,y) position for the top left point. sl@0: @param aTopRight The absolute (x,y) position for the top right point. sl@0: @param aBottomLeft The absolute (x,y) position for the bottom left point. sl@0: @param aBottomRight The absolute (x,y) position for the bottom right point. sl@0: @return ETrue if a valid rectangle is produced, else EFalse. Also sets sl@0: iStatus to EComplete. sl@0: */ sl@0: TBool TSwDirectGdiEllipse::Output(TPoint& aTopLeft, TPoint& aTopRight, sl@0: TPoint& aBottomLeft, TPoint& aBottomRight) sl@0: { sl@0: TInt lx = iA-iX+iOffset.iX; sl@0: TInt ty = iB-iY+iOffset.iY; sl@0: TInt rx = iA+iX+iXAdj+iOffset.iX; sl@0: TInt by = iB+iY+iYAdj+iOffset.iY; sl@0: aTopLeft.SetXY(lx,ty); sl@0: aTopRight.SetXY(rx,ty); sl@0: aBottomLeft.SetXY(lx,by); sl@0: aBottomRight.SetXY(rx,by); sl@0: if (iY <= 0) sl@0: { sl@0: iStatus = EComplete; sl@0: if (iYAdj==0 || ty>by) sl@0: return ETrue; sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: /** sl@0: By analysing the current state of the ellipse the process is taken to the next appropriate step. sl@0: If iStatus = EInitialised only one step will be taken, if the ellipse is already semi constructed then sl@0: it will be taken to completion. Takes in four point parameters that define the rectangle in order to pass to sl@0: SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight). sl@0: sl@0: @param aTopLeft Top-left corner of rectangle. sl@0: @param aTopRight Top-right corner of rectangle. sl@0: @param aBottomLeft Bottom-left corner of rectangle. sl@0: @param aBottomRight Bottom-right corner of rectangle. sl@0: @return ETrue if a valid rectangle is produced, else EFalse. sl@0: */ sl@0: TBool TSwDirectGdiEllipse::NextStep(TPoint& aTopLeft, TPoint& aTopRight, sl@0: TPoint& aBottomLeft, TPoint& aBottomRight) sl@0: { sl@0: if(iStatus == EInitialised) sl@0: { sl@0: return(SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight)); sl@0: } sl@0: TInt prevlev = iY; sl@0: TBool ret; sl@0: do sl@0: { sl@0: ret = SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight); sl@0: } sl@0: while (prevlev==iY && ret==EFalse); sl@0: return ret; sl@0: } sl@0: sl@0: /** sl@0: Constructs an ellipse from the rectangle that has been added. Assesses the position of sl@0: the points and the places where they intersect the ellipse. sl@0: sl@0: @param aRect The rectangle within which the ellipse is drawn. sl@0: @param aPoint A point to compare with the ellipse to determine if intersection occurs. sl@0: @return TPoint The point is set to the corner which the intersection is nearest to. sl@0: */ sl@0: TPoint TSwDirectGdiEllipse::Intersection(const TRect& aRect, const TPoint& aPoint) sl@0: { sl@0: Construct(aRect); //constructs the rect (an elipse object) sl@0: TPoint centre = aRect.Center(); //centre of ellipse sl@0: TPoint ptcpy(aPoint); sl@0: ptcpy -= iOffset; //ptcpy = aPoint - iOffset - TPoint(iA,iB) //radius from centre of ellipse sl@0: ptcpy -= TPoint(iA,iB); sl@0: TPoint pt[4], opt[4]; sl@0: TInt mpt[4], ompt[4]; sl@0: TInt count = 0; sl@0: for( ; count < 4; count++) sl@0: { sl@0: ompt[count]=KMaxTInt; //fills ompt 1->4 with KMaxTInt sl@0: } sl@0: while (SingleStep(pt[0], pt[1], pt[2], pt[3]) == EFalse) //creates a complete ellipse with pts as rect sl@0: { sl@0: for (count = 0; count < 4; count++) sl@0: { sl@0: mpt[count] = Abs((pt[count].iY-iOffset.iY-iB)*(ptcpy.iX)-(ptcpy.iY)*(pt[count].iX-iOffset.iX-iA)); sl@0: if (mpt[count] < ompt[count]) //use the larger number set. sl@0: { sl@0: ompt[count] = mpt[count]; sl@0: opt[count] = pt[count]; sl@0: } sl@0: } sl@0: } sl@0: if (pt[0].iY == pt[2].iY) //if it is horizontal sl@0: { sl@0: for (count = 0; count < 4; count++) sl@0: { sl@0: mpt[count] = Abs((pt[count].iY-iOffset.iY-iB)*(ptcpy.iX)-(ptcpy.iY)*(pt[count].iX-iOffset.iX-iA)); sl@0: if (mpt[count] < ompt[count]) //use the larger number set. sl@0: { sl@0: ompt[count] = mpt[count]; sl@0: opt[count] = pt[count]; sl@0: } sl@0: } sl@0: } sl@0: if (ptcpy.iX<0 && ptcpy.iY<0) //if point is further left and higher than centre of rect sl@0: { sl@0: return opt[0]; sl@0: } sl@0: if (ptcpy.iY < 0) //if point is higher than centre of rect sl@0: { sl@0: return opt[1]; sl@0: } sl@0: if (ptcpy.iX < 0) //if point is further left than centre of rect sl@0: { sl@0: return opt[2]; sl@0: } sl@0: if (aPoint.iX1 && iPenSize.iHeight>1) sl@0: { sl@0: EllipseOutlineWide(rcpy); sl@0: } sl@0: else if(iPenSize.iWidth==1 || iPenSize.iHeight==1) sl@0: { sl@0: EllipseOutline(rcpy); sl@0: } sl@0: } sl@0: iBrushBitmap.EndDataAccess(ETrue); sl@0: } sl@0: sl@0: /** sl@0: Draws an ellipse inside the given rectangle. Current pen settings apply. sl@0: @param aRect The rectangle in which to draw the ellipse. sl@0: */ sl@0: void CSwDirectGdiEngine::EllipseOutline(const TRect& aRect) sl@0: { sl@0: TPoint tl,tr,bl,br; sl@0: #if defined(_DEBUG) sl@0: TRect deviceDestRect; sl@0: iDrawDevice->GetDrawRect(deviceDestRect); sl@0: #endif sl@0: TRect clipRect(0,0,0,0); sl@0: const CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode); sl@0: for(TInt count=0;countCount();count++) sl@0: { sl@0: clipRect=(*iDefaultRegionPtr)[count]; sl@0: if(!clipRect.Intersects(aRect)) sl@0: continue; sl@0: clipRect.Intersection(aRect); sl@0: GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iX >= deviceDestRect.iTl.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iY >= deviceDestRect.iTl.iY, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iX <= deviceDestRect.iBr.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iY <= deviceDestRect.iBr.iY, EDirectGdiPanicOutOfBounds); sl@0: TSwDirectGdiEllipse ellipse; sl@0: ellipse.Construct(aRect); sl@0: TInt pattern=0; sl@0: while(!ellipse.SingleStep(tl,tr,bl,br)) sl@0: { sl@0: if(iPenStyle==DirectGdi::ESolidPen || (iDotMask&(1<<(pattern%iDotLength)))) sl@0: { sl@0: if(tl.iY>=clipRect.iTl.iY && tl.iY=clipRect.iTl.iX && tl.iXWriteRgb(tl.iX,tl.iY,iPenColor,drawMode); sl@0: if(tr.iX>=clipRect.iTl.iX && tr.iXWriteRgb(tr.iX,tr.iY,iPenColor,drawMode); sl@0: } sl@0: if(bl.iY>=clipRect.iTl.iY && bl.iY=clipRect.iTl.iX && bl.iXWriteRgb(bl.iX,bl.iY,iPenColor,drawMode); sl@0: if(br.iX>=clipRect.iTl.iX && br.iXWriteRgb(br.iX,br.iY,iPenColor,drawMode); sl@0: } sl@0: } sl@0: pattern++; sl@0: } sl@0: if(tl.iY==bl.iY && tl.iY>=clipRect.iTl.iY && tl.iY=clipRect.iTl.iX && tl.iXWriteRgb(tl.iX,tl.iY,iPenColor,drawMode); sl@0: if(tr.iX>=clipRect.iTl.iX && tr.iXWriteRgb(tr.iX,tr.iY,iPenColor,drawMode); sl@0: } sl@0: iDrawDevice->UpdateRegion(clipRect); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Draws an ellipse inside the given rectangle. Current pen settings apply. sl@0: @param aRect The rectangle in which to draw the ellipse. sl@0: */ sl@0: void CSwDirectGdiEngine::EllipseOutlineWide(const TRect& aRect) sl@0: { sl@0: TRect rcpy(aRect); sl@0: TPoint tl,tr,bl,br; sl@0: TInt halfpenwidth=(iPenSize.iWidth+1)>>1; sl@0: TInt halfpenheight=(iPenSize.iHeight+1)>>1; sl@0: rcpy.Grow(halfpenwidth, halfpenheight); sl@0: TInt dp=iDotParam; sl@0: TRect clipRect(0,0,0,0); sl@0: for(TInt count=0;countCount();count++) sl@0: { sl@0: clipRect=(*iDefaultRegionPtr)[count]; sl@0: if(!clipRect.Intersects(rcpy)) sl@0: continue; sl@0: clipRect.Intersection(rcpy); sl@0: TSwDirectGdiEllipse ellipse; sl@0: ellipse.Construct(aRect); sl@0: iDotParam=Max(iPenSize.iWidth>>1,iPenSize.iHeight>>1); sl@0: while(!ellipse.SingleStep(tl,tr,bl,br)) sl@0: { sl@0: PenDrawClipped(tl, clipRect); sl@0: PenDrawClipped(tr, clipRect); sl@0: PenDrawClipped(bl, clipRect); sl@0: PenDrawClipped(br, clipRect); sl@0: iDotParam+=iDotDirection; sl@0: } sl@0: if(tl.iY==bl.iY) sl@0: { sl@0: PenDrawClipped(tl, clipRect); sl@0: PenDrawClipped(tr, clipRect); sl@0: } sl@0: iDrawDevice->UpdateRegion(clipRect); sl@0: } sl@0: iDotParam=dp; sl@0: } sl@0: sl@0: /** sl@0: Fills an ellipse inside the given rectangle. Current brush settings apply. sl@0: @param aRect The rectangle in which to draw the ellipse. sl@0: */ sl@0: void CSwDirectGdiEngine::EllipseFill(const TRect& aRect) sl@0: { sl@0: TRect rcpy(aRect); sl@0: if(iPenSize.iWidth==0 || iPenSize.iHeight==0) sl@0: { sl@0: rcpy.Grow(1,1); sl@0: } sl@0: TPoint tl,tr,bl,br; sl@0: TRect clipRect(0,0,0,0); sl@0: for(TInt count=0;countCount();count++) sl@0: { sl@0: clipRect=(*iDefaultRegionPtr)[count]; sl@0: if(!clipRect.Intersects(rcpy)) sl@0: continue; sl@0: clipRect.Intersection(rcpy); sl@0: TSwDirectGdiEllipse ellipse; sl@0: ellipse.Construct(rcpy); sl@0: while(!ellipse.NextStep(tl,tr,bl,br)) sl@0: { sl@0: tl.iX++; sl@0: tr.iX--; sl@0: bl.iX++; sl@0: br.iX--; sl@0: ClipFillLine(tl,tr, clipRect); sl@0: ClipFillLine(bl,br, clipRect); sl@0: } sl@0: if(tl.iY==bl.iY) sl@0: { sl@0: tl.iX++; sl@0: tr.iX--; sl@0: ClipFillLine(tl,tr, clipRect); sl@0: } sl@0: iDrawDevice->UpdateRegion(clipRect); sl@0: } sl@0: }