os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdirect.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdirect.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,416 @@
     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 "swdirectgdiengine.h"
    1.21 +
    1.22 +/** 
    1.23 +@see MDirectGdiEngine::CopyRect()
    1.24 +*/
    1.25 +void CSwDirectGdiEngine::CopyRect(const TPoint& aOffset, const TRect& aRect)
    1.26 +	{	
    1.27 +	TRect deviceRect;
    1.28 +	iDrawDevice->GetDrawRect(deviceRect);
    1.29 +	const TPoint back(TPoint(0,0) - aOffset);
    1.30 +	TRect rcpy(aRect);
    1.31 +	rcpy.Move(iOrigin);
    1.32 +	rcpy.Intersection(deviceRect);
    1.33 +	((TRegion*)iDefaultRegionPtr)->Sort(aOffset);
    1.34 +	
    1.35 +	TRect targetRect(rcpy);
    1.36 +	targetRect.Move(aOffset);
    1.37 +	targetRect.BoundingRect(rcpy);
    1.38 +	
    1.39 +	TRect clipRect(0,0,0,0);
    1.40 +	const TInt limit = iDefaultRegionPtr->Count();
    1.41 +	for(TInt count = 0; count < limit; count++)
    1.42 +		{
    1.43 +		clipRect = (*iDefaultRegionPtr)[count];
    1.44 +		
    1.45 +		clipRect.Move(back);
    1.46 +		if (!clipRect.Intersects(rcpy))
    1.47 +			{
    1.48 +			continue;
    1.49 +			}
    1.50 +		
    1.51 +		clipRect.Intersection(rcpy);
    1.52 +		DirectGdi::TDrawMode drawMode = iDrawMode;
    1.53 +		iDrawMode = DirectGdi::EDrawModeWriteAlpha;
    1.54 +		DoCopyRect(aOffset, clipRect);
    1.55 +		iDrawMode = drawMode; // restore the previous draw mode
    1.56 +		clipRect.Move(aOffset);
    1.57 +		iDrawDevice->UpdateRegion(clipRect);
    1.58 +		}
    1.59 +	}
    1.60 +
    1.61 +/**
    1.62 +@see CopyRect()
    1.63 +@panic DGDIAdapter 1013, if aRect or aOffset are outside of the destination bounds (debug only).
    1.64 + */ 
    1.65 +void CSwDirectGdiEngine::DoCopyRect(const TPoint& aOffset, const TRect& aRect)
    1.66 +	{
    1.67 +#ifdef _DEBUG
    1.68 +	TRect deviceRect;
    1.69 +	iDrawDevice->GetDrawRect(deviceRect);
    1.70 +#endif
    1.71 +	GRAPHICS_ASSERT_DEBUG(aRect.iTl.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds);
    1.72 +	GRAPHICS_ASSERT_DEBUG(aRect.iTl.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds);
    1.73 +	GRAPHICS_ASSERT_DEBUG(aRect.iBr.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds);
    1.74 +	GRAPHICS_ASSERT_DEBUG(aRect.iBr.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds);
    1.75 +
    1.76 +	TRect offsetRect(aRect);
    1.77 +	offsetRect.Move(aOffset);
    1.78 +
    1.79 +	GRAPHICS_ASSERT_DEBUG(offsetRect.iTl.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds);
    1.80 +	GRAPHICS_ASSERT_DEBUG(offsetRect.iTl.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds);
    1.81 +	GRAPHICS_ASSERT_DEBUG(offsetRect.iBr.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds);
    1.82 +	GRAPHICS_ASSERT_DEBUG(offsetRect.iBr.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds);
    1.83 +
    1.84 +	TInt y1 = aRect.iTl.iY;
    1.85 +	TInt y2 = aRect.iBr.iY; 
    1.86 +	TInt yinc = 1; // default y2>y1
    1.87 +	if (aOffset.iY > 0)	// y1>y2
    1.88 +		{
    1.89 +		y1 = aRect.iBr.iY - 1;
    1.90 +		y2 = aRect.iTl.iY - 1;
    1.91 +		yinc = -1;
    1.92 +		}
    1.93 +
    1.94 +	const TInt width = aRect.Width();
    1.95 +	const TInt xoffset = aRect.iTl.iX + aOffset.iX;
    1.96 +	const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice);
    1.97 +	TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer();
    1.98 +
    1.99 +	for (TInt row = y1; row != y2; row += yinc)
   1.100 +		{
   1.101 +		iDrawDevice->ReadLine(aRect.iTl.iX, row, width, scanLineBuffer, dispMode);
   1.102 +		iDrawDevice->WriteLine(xoffset, row + aOffset.iY, width, scanLineBuffer, GcDrawMode(iDrawMode));
   1.103 +		}
   1.104 +	}
   1.105 +
   1.106 +/** 
   1.107 +@see MDirectGdiEngine::DrawRect()
   1.108 +*/
   1.109 +void CSwDirectGdiEngine::DrawRect(const TRect& aRect)
   1.110 +	{
   1.111 +	TRect rcpy(aRect);
   1.112 +
   1.113 +	iBrushBitmap.BeginDataAccess();
   1.114 +	
   1.115 +	if ((iPenSize.iWidth == 1) && (iPenSize.iHeight == 1) && iPenStyle != DirectGdi::ENullPen)
   1.116 +		{
   1.117 +		const TInt width = rcpy.Width();
   1.118 +		const TInt height = rcpy.Height();
   1.119 +		const TPoint currentLinePosition = iLinePosition;
   1.120 +
   1.121 +		if (iPenStyle != DirectGdi::ESolidPen)
   1.122 +			{
   1.123 +			iDotParam = 0;
   1.124 +			}
   1.125 +
   1.126 +		DoDrawLine(rcpy.iTl,TPoint(rcpy.iBr.iX,rcpy.iTl.iY),ETrue); // top
   1.127 +
   1.128 +		if (height > 2 && width > 1)
   1.129 +			{
   1.130 +			DoDrawLine(TPoint(rcpy.iBr.iX-1,rcpy.iTl.iY+1),TPoint(rcpy.iBr.iX-1,rcpy.iBr.iY-1),ETrue); // right
   1.131 +			}
   1.132 +
   1.133 +		if (height > 1)
   1.134 +			{
   1.135 +			DoDrawLine(TPoint(rcpy.iBr.iX-1,rcpy.iBr.iY-1),TPoint(rcpy.iTl.iX-1,rcpy.iBr.iY-1),ETrue); // bottom
   1.136 +			}
   1.137 +
   1.138 +		if (height > 2)
   1.139 +			{
   1.140 +			DoDrawLine(TPoint(rcpy.iTl.iX,rcpy.iBr.iY-2),rcpy.iTl,ETrue); // left
   1.141 +			}
   1.142 +		
   1.143 +		// Restore internal line position in case it has been modified by DoDrawLine().
   1.144 +		// DrawRect() should not be modifying it.
   1.145 +		iLinePosition = currentLinePosition;
   1.146 +
   1.147 +		if (width < 3 || height < 3)
   1.148 +			{
   1.149 +			goto nofill;
   1.150 +			}
   1.151 +
   1.152 +		rcpy.Shrink(1,1);
   1.153 +		rcpy.Move(iOrigin);
   1.154 +		}
   1.155 +	else if ((iPenStyle != DirectGdi::ENullPen) && (iPenSize.iWidth >= 1 && iPenSize.iHeight >= 1))
   1.156 +		{
   1.157 +		rcpy.Move(iOrigin);
   1.158 +
   1.159 +		const DirectGdi::TBrushStyle tempbrushstyle = iBrushStyle;
   1.160 +		const TRgb tempbrushColor = iBrushColor;
   1.161 +		const DirectGdi::TDrawMode tempdrawmode = iDrawMode;
   1.162 +				
   1.163 +		const TInt halfpenwidth = (iPenSize.iWidth - 1) >> 1;
   1.164 +		const TInt halfpenheight = (iPenSize.iHeight - 1) >> 1;
   1.165 +		const TInt otherhalfwidth = (iPenSize.iWidth >> 1) + 1;
   1.166 +		const TInt otherhalfheight = (iPenSize.iHeight >> 1) + 1;
   1.167 +
   1.168 +		rcpy.iBr.iX--;
   1.169 +		rcpy.iBr.iY--;
   1.170 +
   1.171 +		if (((rcpy.iBr.iY - rcpy.iTl.iY) <= (iPenSize.iHeight + 1)) || ((rcpy.iBr.iX - rcpy.iTl.iX) <= (iPenSize.iWidth + 1)))
   1.172 +			{
   1.173 +			iBrushColor = iPenColor;
   1.174 +			iBrushStyle = DirectGdi::ESolidBrush;
   1.175 +			if(iDrawMode != DirectGdi::EDrawModeWriteAlpha)
   1.176 +				{			
   1.177 +				iDrawMode = DirectGdi::EDrawModePEN;
   1.178 +				}
   1.179 +						
   1.180 +			rcpy.iTl.iX -= halfpenwidth;
   1.181 +			rcpy.iTl.iY -= halfpenheight;
   1.182 +			rcpy.iBr.iX += otherhalfwidth;
   1.183 +			rcpy.iBr.iY += otherhalfheight;			
   1.184 +			RectFill(rcpy);
   1.185 +			}
   1.186 +		else
   1.187 +			{
   1.188 +			// In the event the pen outline is semi-transparent, we must do the fill first so that the
   1.189 +			// outline is blended over the top.
   1.190 +			RectFill(rcpy);
   1.191 +			
   1.192 +			iBrushColor = iPenColor;
   1.193 +			iBrushStyle = DirectGdi::ESolidBrush;
   1.194 +			if(iDrawMode != DirectGdi::EDrawModeWriteAlpha)
   1.195 +				{			
   1.196 +				iDrawMode = DirectGdi::EDrawModePEN;
   1.197 +				}
   1.198 +			RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iTl.iY - halfpenheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iTl.iY + otherhalfheight)); // top
   1.199 +			RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iTl.iY + otherhalfheight,rcpy.iTl.iX + otherhalfwidth,rcpy.iBr.iY - halfpenheight)); // left
   1.200 +			RectFill(TRect(rcpy.iBr.iX - halfpenwidth,rcpy.iTl.iY + otherhalfheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iBr.iY - halfpenheight)); // right
   1.201 +			RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iBr.iY - halfpenheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iBr.iY + otherhalfheight)); // bottom
   1.202 +			}
   1.203 +		
   1.204 +		iBrushStyle = tempbrushstyle;
   1.205 +		iBrushColor = tempbrushColor;
   1.206 +		iDrawMode = tempdrawmode;
   1.207 +		goto nofill;
   1.208 +		}
   1.209 +	else
   1.210 +		{
   1.211 +		rcpy.Move(iOrigin);
   1.212 +		}
   1.213 +
   1.214 +	RectFill(rcpy);
   1.215 +
   1.216 +nofill:
   1.217 +	iBrushBitmap.EndDataAccess(ETrue);
   1.218 +	}
   1.219 +
   1.220 +/**
   1.221 +Fills the given area using the current brush.
   1.222 +
   1.223 +@param aRect The area to fill.
   1.224 +@panic DGDIAdapter 1013, if the a clipping rectangle is fully outside of the destination bounds (debug only).
   1.225 +@panic DGDIAdapter 7, if using EPatternedBrush with no brush pattern bitmap.
   1.226 + */ 
   1.227 +void CSwDirectGdiEngine::RectFill(const TRect& aRect)
   1.228 +	{	
   1.229 +	if (aRect.IsEmpty() || iBrushStyle == DirectGdi::ENullBrush)
   1.230 +		{
   1.231 +		return;
   1.232 +		}
   1.233 +	
   1.234 +	const TPoint origin = iOrigin + iBrushOrigin;
   1.235 +	const TInt limit = iDefaultRegionPtr->Count();
   1.236 +	TRect clipRect(0,0,0,0);
   1.237 +	for (TInt count = 0; count < limit; count++)
   1.238 +		{
   1.239 +		clipRect = (*iDefaultRegionPtr)[count];
   1.240 +		if (!clipRect.Intersects(aRect))
   1.241 +			{
   1.242 +			continue;
   1.243 +			}
   1.244 +		
   1.245 +		clipRect.Intersection(aRect);	
   1.246 +		
   1.247 +#ifdef _DEBUG
   1.248 +		TRect deviceRect;
   1.249 +		iDrawDevice->GetDrawRect(deviceRect);
   1.250 +		GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds);
   1.251 +		GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds);
   1.252 +		GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds);
   1.253 +		GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds);
   1.254 +#endif
   1.255 +
   1.256 +		TInt xcoord = clipRect.iTl.iX;
   1.257 +		TInt ycoord = clipRect.iTl.iY;
   1.258 +		const CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode);
   1.259 +		
   1.260 +		switch(iBrushStyle)
   1.261 +		{
   1.262 +		case DirectGdi::ESolidBrush:
   1.263 +			iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
   1.264 +							clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
   1.265 +			break;
   1.266 +		case DirectGdi::EPatternedBrush:
   1.267 +			{
   1.268 +			iBrushBitmap.BeginDataAccess();
   1.269 +			CBitwiseBitmap* brushbitmap = iBrushBitmap.Address();
   1.270 +			
   1.271 +			GRAPHICS_ASSERT_ALWAYS(brushbitmap != NULL, EDirectGdiPanicInvalidBitmap);
   1.272 +			
   1.273 +			TRect sourcerect(clipRect);
   1.274 +			sourcerect.Move(-origin);
   1.275 +						
   1.276 +			DoBitBlt(clipRect.iTl,brushbitmap,iBrushBitmap.DataAddress(),iBrushBitmap.DataStride(),sourcerect);
   1.277 +			iBrushBitmap.EndDataAccess(ETrue);
   1.278 +			break;
   1.279 +			}
   1.280 +		case DirectGdi::EHorizontalHatchBrush:
   1.281 +			iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
   1.282 +					clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
   1.283 +			while (Abs((ycoord - origin.iY) % 3) != 2)
   1.284 +				{
   1.285 +				ycoord++;
   1.286 +				}
   1.287 +			for (; ycoord < clipRect.iBr.iY; ycoord += 3)
   1.288 +				{
   1.289 +				iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,ycoord,clipRect.Width(),1,iPenColor,drawMode);
   1.290 +				}
   1.291 +				break;
   1.292 +			case DirectGdi::EVerticalHatchBrush:
   1.293 +				iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
   1.294 +						clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
   1.295 +				while (Abs((xcoord - origin.iX) % 3) != 2)
   1.296 +					{
   1.297 +					xcoord++;
   1.298 +					}
   1.299 +				for (; xcoord < clipRect.iBr.iX; xcoord += 3)
   1.300 +					{
   1.301 +					iDrawDevice->WriteRgbMulti(xcoord,clipRect.iTl.iY,1,clipRect.Height(),iPenColor,drawMode);
   1.302 +					}
   1.303 +				break;
   1.304 +			case DirectGdi::ESquareCrossHatchBrush:
   1.305 +				iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
   1.306 +						clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
   1.307 +				while (Abs((ycoord - origin.iY) % 3) != 2)
   1.308 +					{
   1.309 +					ycoord++;
   1.310 +					}
   1.311 +				for (; ycoord < clipRect.iBr.iY; ycoord += 3) // horizontal lines
   1.312 +					{
   1.313 +					iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,ycoord,clipRect.Width(),1,iPenColor,drawMode);
   1.314 +					}
   1.315 +
   1.316 +				ycoord = clipRect.iTl.iY;
   1.317 +				while (Abs((ycoord - origin.iY) % 3) != 2 && ycoord < clipRect.iBr.iY) // above the top horizontal line
   1.318 +					{
   1.319 +					xcoord = clipRect.iTl.iX;
   1.320 +					while (Abs((xcoord - origin.iX) % 3) != 2)
   1.321 +						{
   1.322 +						xcoord++;
   1.323 +						}
   1.324 +					for (; xcoord < clipRect.iBr.iX; xcoord += 3)
   1.325 +						{
   1.326 +						iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
   1.327 +						}
   1.328 +					ycoord++;
   1.329 +					}
   1.330 +				ycoord += 3;
   1.331 +				for (; ycoord < clipRect.iBr.iY; ycoord += 3) // between the top and bottom horizontals
   1.332 +					{
   1.333 +					xcoord = clipRect.iTl.iX;
   1.334 +					while (Abs((xcoord - origin.iX) % 3) != 2)
   1.335 +						{
   1.336 +						xcoord++;
   1.337 +						}
   1.338 +					for (; xcoord < clipRect.iBr.iX; xcoord += 3)
   1.339 +						{
   1.340 +						iDrawDevice->WriteRgbMulti(xcoord,ycoord - 2,1,2,iPenColor,drawMode);
   1.341 +						}
   1.342 +					}
   1.343 +
   1.344 +				ycoord -= 3;
   1.345 +				while (ycoord < clipRect.iBr.iY) // below the bottom horizontal
   1.346 +					{
   1.347 +					xcoord = clipRect.iTl.iX;
   1.348 +					while (Abs((xcoord - origin.iX) % 3) != 2)
   1.349 +						{
   1.350 +						xcoord++;
   1.351 +						}
   1.352 +					for (; xcoord < clipRect.iBr.iX; xcoord += 3)
   1.353 +						{
   1.354 +						iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
   1.355 +						}
   1.356 +					ycoord++;
   1.357 +					}
   1.358 +				break;
   1.359 +			case DirectGdi::EForwardDiagonalHatchBrush:
   1.360 +				iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
   1.361 +						clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
   1.362 +				for (; ycoord < clipRect.iBr.iY; ycoord++)
   1.363 +					{
   1.364 +					xcoord = clipRect.iTl.iX;
   1.365 +					TInt diff = (origin.iX + origin.iY - xcoord - ycoord) % 3;
   1.366 +					if (diff < 0)
   1.367 +						{
   1.368 +						diff += 3;
   1.369 +						}
   1.370 +					xcoord += diff;
   1.371 +					for (; xcoord < clipRect.iBr.iX; xcoord += 3)
   1.372 +						{
   1.373 +						iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
   1.374 +						}
   1.375 +					}
   1.376 +				break;
   1.377 +			case DirectGdi::ERearwardDiagonalHatchBrush:
   1.378 +				iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
   1.379 +						clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
   1.380 +				for (; ycoord < clipRect.iBr.iY; ycoord++)
   1.381 +					{
   1.382 +					xcoord = clipRect.iTl.iX;
   1.383 +					TInt diff = (origin.iX - origin.iY - xcoord + ycoord) % 3;
   1.384 +					if (diff < 0)
   1.385 +						{
   1.386 +						diff += 3;
   1.387 +						}
   1.388 +					xcoord += diff;
   1.389 +					for (; xcoord < clipRect.iBr.iX; xcoord += 3)
   1.390 +						{
   1.391 +						iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
   1.392 +						}
   1.393 +					}
   1.394 +				break;
   1.395 +			case DirectGdi::EDiamondCrossHatchBrush:
   1.396 +				{
   1.397 +				iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
   1.398 +						clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
   1.399 +				TInt sum = xcoord + ycoord - origin.iX - origin.iY;
   1.400 +				for (; ycoord < clipRect.iBr.iY; ycoord++,sum++)
   1.401 +					{
   1.402 +					TInt currentsum = sum;
   1.403 +					for (xcoord = clipRect.iTl.iX; xcoord < clipRect.iBr.iX; xcoord++,currentsum++)
   1.404 +						{
   1.405 +						if((currentsum & 1) == 0 && ((currentsum & 3) != 0 || ((xcoord-origin.iX) & 1) == 1))
   1.406 +							{
   1.407 +							iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
   1.408 +							}
   1.409 +						}
   1.410 +					}
   1.411 +				break;
   1.412 +				}
   1.413 +			default:
   1.414 +				return;
   1.415 +				}
   1.416 +
   1.417 +			iDrawDevice->UpdateRegion(clipRect);
   1.418 +			}		
   1.419 +	}