os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdigraphics.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200 (2012-06-15)
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2007-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 "directgdiadapter.h"
sl@0
    17
#include "swdirectgdiengine.h"
sl@0
    18
#include "swdirectgdiellipse.h"
sl@0
    19
sl@0
    20
/** 
sl@0
    21
@see MDirectGdiEngine::Clear(const TRect&)
sl@0
    22
*/	
sl@0
    23
void CSwDirectGdiEngine::Clear(const TRect& aRect)
sl@0
    24
	{
sl@0
    25
	TRect rcpy(aRect);
sl@0
    26
	rcpy.Move(iOrigin);	
sl@0
    27
sl@0
    28
	DirectGdi::TBrushStyle tempbrushstyle = iBrushStyle;
sl@0
    29
	iBrushStyle = DirectGdi::ESolidBrush;
sl@0
    30
sl@0
    31
	RectFill(rcpy);	
sl@0
    32
	
sl@0
    33
	iBrushStyle = tempbrushstyle;
sl@0
    34
	}
sl@0
    35
sl@0
    36
/**
sl@0
    37
@see MDirectGdiEngine::Clear()
sl@0
    38
*/
sl@0
    39
void CSwDirectGdiEngine::Clear()
sl@0
    40
	{
sl@0
    41
	TRect deviceRect;
sl@0
    42
	iDrawDevice->GetDrawRect(deviceRect);
sl@0
    43
	if ((iOrigin.iX!=0) || (iOrigin.iY!=0))
sl@0
    44
		{
sl@0
    45
		deviceRect.Move(-iOrigin);
sl@0
    46
		}
sl@0
    47
	Clear(deviceRect);
sl@0
    48
	}
sl@0
    49
sl@0
    50
/**
sl@0
    51
@see MDirectGdiEngine::Plot()
sl@0
    52
*/
sl@0
    53
void CSwDirectGdiEngine::Plot(const TPoint& aPoint)
sl@0
    54
	{
sl@0
    55
	TRect targetRect(aPoint + iOrigin, TSize(1,1));
sl@0
    56
	targetRect.Grow((iPenSize.iWidth >> 1) + 1,(iPenSize.iHeight >> 1) + 1);
sl@0
    57
	DoPlot(aPoint);	
sl@0
    58
	}
sl@0
    59
sl@0
    60
/**
sl@0
    61
Draws a single point.
sl@0
    62
sl@0
    63
@see Plot()
sl@0
    64
sl@0
    65
@param aPoint The location to plot at.
sl@0
    66
@panic DGDIAdapter 1013, if the point being plotted is out of bounds of the target (debug only).
sl@0
    67
 */
sl@0
    68
void CSwDirectGdiEngine::DoPlot(const TPoint& aPoint)
sl@0
    69
	{
sl@0
    70
	const TSize oneByOne(1,1);
sl@0
    71
	const TPoint point(aPoint + iOrigin);
sl@0
    72
sl@0
    73
	TRect temp(point,oneByOne);
sl@0
    74
	if (iPenSize.iWidth > 1 || iPenSize.iHeight > 1)
sl@0
    75
		{
sl@0
    76
		temp.Grow(iPenSize.iWidth >> 1, iPenSize.iHeight >> 1);
sl@0
    77
		}
sl@0
    78
	
sl@0
    79
	const DirectGdi::TPenStyle oldPenStyle = iPenStyle;	
sl@0
    80
	iPenStyle = DirectGdi::ESolidPen;
sl@0
    81
sl@0
    82
#if defined(_DEBUG)
sl@0
    83
	TRect deviceRect;
sl@0
    84
	iDrawDevice->GetDrawRect(deviceRect);
sl@0
    85
#endif
sl@0
    86
sl@0
    87
	TRect clipRect;
sl@0
    88
	const TInt limit = iDefaultRegionPtr->Count();
sl@0
    89
	for (TInt count = 0; count < limit; count++)
sl@0
    90
		{
sl@0
    91
		clipRect = (*iDefaultRegionPtr)[count];
sl@0
    92
		if (!clipRect.Intersects(temp))
sl@0
    93
			{
sl@0
    94
			continue;
sl@0
    95
			}
sl@0
    96
sl@0
    97
		clipRect.Intersection(temp);	
sl@0
    98
		if (iPenSize == oneByOne)
sl@0
    99
			{
sl@0
   100
			if (clipRect.Contains(point))
sl@0
   101
				{
sl@0
   102
				GRAPHICS_ASSERT_DEBUG(point.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds);
sl@0
   103
				GRAPHICS_ASSERT_DEBUG(point.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds);
sl@0
   104
				GRAPHICS_ASSERT_DEBUG(point.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds);
sl@0
   105
				GRAPHICS_ASSERT_DEBUG(point.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds);
sl@0
   106
				
sl@0
   107
				iDrawDevice->WriteRgb(point.iX,point.iY,iPenColor, GcDrawMode(iDrawMode));
sl@0
   108
				}
sl@0
   109
			}
sl@0
   110
		else
sl@0
   111
			{
sl@0
   112
			PenDrawClipped(point, clipRect);
sl@0
   113
			}
sl@0
   114
sl@0
   115
		iDrawDevice->UpdateRegion(clipRect);
sl@0
   116
		}
sl@0
   117
sl@0
   118
	iPenStyle = oldPenStyle;
sl@0
   119
	}
sl@0
   120
sl@0
   121
/**
sl@0
   122
Clips the horizontal drawing of a line between two points.
sl@0
   123
The vertical location must be inside the clip rect.
sl@0
   124
sl@0
   125
@param aLeft The left hand side coordinate.
sl@0
   126
@param aRight The right hand side coordinate.
sl@0
   127
@param aClipRect The rectangle to which the line is clipped.
sl@0
   128
 */
sl@0
   129
void CSwDirectGdiEngine::ClipFillLine(TPoint aLeft,TPoint aRight, TRect aClipRect)
sl@0
   130
	{
sl@0
   131
	if (aLeft.iY < aClipRect.iTl.iY || aLeft.iY >= aClipRect.iBr.iY)
sl@0
   132
		return;
sl@0
   133
sl@0
   134
	aLeft.iX = Max(aLeft.iX,aClipRect.iTl.iX);
sl@0
   135
	aRight.iX = Min(aRight.iX,aClipRect.iBr.iX-1);
sl@0
   136
	if (aLeft.iX > aRight.iX)
sl@0
   137
		{
sl@0
   138
		return;
sl@0
   139
		}
sl@0
   140
sl@0
   141
	TInt xcoord = aLeft.iX;
sl@0
   142
	TInt length = aRight.iX - aLeft.iX + 1;
sl@0
   143
	TPoint origin(iOrigin + iBrushOrigin);
sl@0
   144
	const CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode);
sl@0
   145
sl@0
   146
	switch(iBrushStyle)
sl@0
   147
		{
sl@0
   148
	case DirectGdi::ESolidBrush:
sl@0
   149
		iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode);
sl@0
   150
		return;
sl@0
   151
	case DirectGdi::EPatternedBrush:
sl@0
   152
		{
sl@0
   153
		iBrushBitmap.BeginDataAccess();
sl@0
   154
		CBitwiseBitmap* brushBitmap = iBrushBitmap.Address();
sl@0
   155
		if (brushBitmap)
sl@0
   156
			{
sl@0
   157
			TRect sourcerect(aLeft,TSize(length,1));
sl@0
   158
			sourcerect.Move(-origin);
sl@0
   159
			DoBitBlt(aLeft,brushBitmap,iBrushBitmap.DataAddress(),iBrushBitmap.DataStride(),sourcerect);
sl@0
   160
			}
sl@0
   161
		iBrushBitmap.EndDataAccess(ETrue);
sl@0
   162
		return;
sl@0
   163
		}
sl@0
   164
	case DirectGdi::EHorizontalHatchBrush:
sl@0
   165
		iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode);
sl@0
   166
		if (Abs((aLeft.iY - origin.iY) % 3) == 2)
sl@0
   167
			iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iPenColor,drawMode);
sl@0
   168
		return;
sl@0
   169
	case DirectGdi::EVerticalHatchBrush:
sl@0
   170
		iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode);
sl@0
   171
		while (Abs((xcoord - origin.iX) % 3) != 2)
sl@0
   172
			xcoord++;
sl@0
   173
		for (; xcoord < aLeft.iX + length; xcoord += 3)
sl@0
   174
			iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode);
sl@0
   175
		return;
sl@0
   176
	case DirectGdi::ESquareCrossHatchBrush:
sl@0
   177
		iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode);
sl@0
   178
		if (Abs((aLeft.iY - origin.iY) % 3) == 2)
sl@0
   179
			iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iPenColor,drawMode);
sl@0
   180
		else
sl@0
   181
			{
sl@0
   182
			while (Abs((xcoord - origin.iX) % 3) != 2)
sl@0
   183
				xcoord++;
sl@0
   184
			for (; xcoord < aLeft.iX + length; xcoord += 3)
sl@0
   185
				iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode);
sl@0
   186
			}
sl@0
   187
		return;
sl@0
   188
	case DirectGdi::EForwardDiagonalHatchBrush:
sl@0
   189
		{
sl@0
   190
		iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode);
sl@0
   191
		TInt diff = (origin.iX + origin.iY - aLeft.iX - aLeft.iY) % 3;
sl@0
   192
		if (diff < 0)
sl@0
   193
			diff += 3;
sl@0
   194
		xcoord += diff;
sl@0
   195
		for (; xcoord < aLeft.iX + length; xcoord += 3)
sl@0
   196
			iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode);
sl@0
   197
		}
sl@0
   198
		return;
sl@0
   199
	case DirectGdi::ERearwardDiagonalHatchBrush:
sl@0
   200
		{
sl@0
   201
		iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode);
sl@0
   202
		TInt diff = (origin.iX - origin.iY - aLeft.iX + aLeft.iY) % 3;
sl@0
   203
		if (diff < 0)
sl@0
   204
			diff += 3;
sl@0
   205
		xcoord += diff;
sl@0
   206
		for (; xcoord < aLeft.iX + length; xcoord += 3)
sl@0
   207
			iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode);
sl@0
   208
		}
sl@0
   209
		return;
sl@0
   210
	case DirectGdi::EDiamondCrossHatchBrush:
sl@0
   211
		{
sl@0
   212
		iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode);
sl@0
   213
		TInt sum = aLeft.iX + aLeft.iY - origin.iX - origin.iY;
sl@0
   214
		for (; xcoord < aLeft.iX + length; xcoord++,sum++)
sl@0
   215
			if ((sum & 1) == 0 && ((sum & 3) != 0 || ((xcoord-origin.iX) & 1) == 1))
sl@0
   216
				iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode);
sl@0
   217
		}
sl@0
   218
		return;
sl@0
   219
	default:
sl@0
   220
		return;
sl@0
   221
		}
sl@0
   222
	}
sl@0
   223
sl@0
   224
/**
sl@0
   225
Creates the pen using the current pen size.
sl@0
   226
sl@0
   227
@return KErrNoMermory if memory could not be allocated, KErrNone otherwise.
sl@0
   228
*/ 
sl@0
   229
TInt CSwDirectGdiEngine::PenAllocate()
sl@0
   230
	{		
sl@0
   231
	ResetPenArray();
sl@0
   232
	
sl@0
   233
	if (iPenSize.iWidth == 1 && iPenSize.iHeight == 1)
sl@0
   234
		{
sl@0
   235
		return KErrNone;
sl@0
   236
		}
sl@0
   237
sl@0
   238
	const TInt doublePenHeight = iPenSize.iHeight << 1;
sl@0
   239
sl@0
   240
	TInt* penArray = new TInt[doublePenHeight];
sl@0
   241
	if (penArray == NULL)
sl@0
   242
		{
sl@0
   243
		return KErrNoMemory;
sl@0
   244
		}
sl@0
   245
sl@0
   246
	SetPenArray(penArray);
sl@0
   247
sl@0
   248
	if (iPenSize.iWidth == 1 || iPenSize.iWidth == 2 || iPenSize.iHeight == 1 || iPenSize.iHeight == 2)
sl@0
   249
		{				
sl@0
   250
		for (TInt count = 0; count < iPenSize.iHeight; count += 2)
sl@0
   251
			{
sl@0
   252
			iPenArray[doublePenHeight - count - 2] = 0;
sl@0
   253
			iPenArray[doublePenHeight - count - 1] = iPenSize.iWidth - 1;
sl@0
   254
			iPenArray[count] = 0;
sl@0
   255
			iPenArray[count + 1] = iPenSize.iWidth - 1;
sl@0
   256
			}
sl@0
   257
		}
sl@0
   258
	else
sl@0
   259
		{
sl@0
   260
		TPoint tl,tr,bl,br;
sl@0
   261
		TSwDirectGdiEllipse ellipse;
sl@0
   262
		ellipse.Construct(TRect(iPenSize));		
sl@0
   263
		for (TInt count = 0; count < iPenSize.iHeight; count += 2)
sl@0
   264
			{
sl@0
   265
			//coverity[check_return]
sl@0
   266
			//coverity[unchecked_value]
sl@0
   267
			ellipse.NextStep(tl,tr,bl,br);
sl@0
   268
			iPenArray[doublePenHeight - count - 2] = bl.iX;
sl@0
   269
			iPenArray[doublePenHeight - count - 1] = br.iX;
sl@0
   270
			iPenArray[count] = tl.iX;
sl@0
   271
			iPenArray[count + 1] = tr.iX;
sl@0
   272
			}
sl@0
   273
		}	
sl@0
   274
	
sl@0
   275
	return KErrNone;
sl@0
   276
	}
sl@0
   277
sl@0
   278
/**
sl@0
   279
Draws at a given point using the current settings, if within clipping rectangle.
sl@0
   280
sl@0
   281
@pre The pen size is greater than one.
sl@0
   282
 
sl@0
   283
@param aPoint The location to draw at.
sl@0
   284
@param aClipRect The clipping rectangle.
sl@0
   285
@panic DGDIAdapter 1016, if the current pen size is zero (debug only).
sl@0
   286
*/ 
sl@0
   287
void CSwDirectGdiEngine::PenDrawClipped(TPoint aPoint, const TRect& aClipRect)
sl@0
   288
	{	
sl@0
   289
	GRAPHICS_ASSERT_DEBUG(iPenSize.iWidth > 0,EDirectGdiPanicZeroLength);
sl@0
   290
	GRAPHICS_ASSERT_DEBUG(iPenSize.iHeight > 0,EDirectGdiPanicZeroLength);
sl@0
   291
sl@0
   292
	aPoint.iX -= ((iPenSize.iWidth - 1) >> 1);
sl@0
   293
	aPoint.iY -= ((iPenSize.iHeight - 1) >> 1);
sl@0
   294
sl@0
   295
	if (iPenSize.iWidth == 1 && iPenSize.iHeight == 1)
sl@0
   296
		{
sl@0
   297
		if ( (iPenStyle == DirectGdi::ESolidPen || (iDotMask & (1 << (iDotParam % iDotLength)))) &&
sl@0
   298
		      aClipRect.Contains(aPoint) )
sl@0
   299
			{
sl@0
   300
			iDrawDevice->WriteRgb(aPoint.iX, aPoint.iY, iPenColor, GcDrawMode(iDrawMode));		
sl@0
   301
			}				
sl@0
   302
		}
sl@0
   303
	else if (iPenArray != NULL)
sl@0
   304
		{
sl@0
   305
		TInt yCoord = aPoint.iY;
sl@0
   306
		const TInt maxdim = Max(iPenSize.iWidth,iPenSize.iHeight);
sl@0
   307
		const TInt doublePenHeight = iPenSize.iHeight << 1;
sl@0
   308
sl@0
   309
		if (iPenStyle == DirectGdi::ESolidPen || (iDotMask & (1 << ((iDotParam / maxdim) % iDotLength))))
sl@0
   310
			{
sl@0
   311
			for (TInt ix = 0; ix < doublePenHeight; yCoord++, ix += 2)
sl@0
   312
				{
sl@0
   313
				if (yCoord >= aClipRect.iTl.iY && yCoord < aClipRect.iBr.iY)
sl@0
   314
					{
sl@0
   315
					TInt left = aPoint.iX + iPenArray[ix];
sl@0
   316
					TInt right = aPoint.iX + iPenArray[ix+1];
sl@0
   317
					if (left < aClipRect.iTl.iX)
sl@0
   318
						{
sl@0
   319
						left = aClipRect.iTl.iX;
sl@0
   320
						}
sl@0
   321
					if (right >= aClipRect.iBr.iX)
sl@0
   322
						{
sl@0
   323
						right = aClipRect.iBr.iX - 1;
sl@0
   324
						}
sl@0
   325
					if (left <= right)
sl@0
   326
						{
sl@0
   327
						iDrawDevice->WriteRgbMulti(left, yCoord, right - left + 1, 1, iPenColor, CGraphicsContext::EDrawModePEN);
sl@0
   328
						}
sl@0
   329
					}
sl@0
   330
				}
sl@0
   331
			}
sl@0
   332
		}
sl@0
   333
	else
sl@0
   334
		{
sl@0
   335
		TPoint tl,tr,bl,br;
sl@0
   336
		TSwDirectGdiEllipse ellipse;
sl@0
   337
		ellipse.Construct(TRect(aPoint,iPenSize));
sl@0
   338
		while (!ellipse.NextStep(tl,tr,bl,br))
sl@0
   339
			{
sl@0
   340
			if (tl.iY >= aClipRect.iTl.iY && tl.iY < aClipRect.iBr.iY)
sl@0
   341
				{
sl@0
   342
				if (tl.iX < aClipRect.iTl.iX)
sl@0
   343
					{
sl@0
   344
					tl.iX = aClipRect.iTl.iX;
sl@0
   345
					}
sl@0
   346
				if (tr.iX >= aClipRect.iBr.iX)
sl@0
   347
					{
sl@0
   348
					tr.iX = aClipRect.iBr.iX-1;
sl@0
   349
					}
sl@0
   350
				if (tl.iX <= tr.iX)
sl@0
   351
					{
sl@0
   352
					iDrawDevice->WriteRgbMulti(tl.iX,tl.iY,tr.iX - tl.iX + 1,1,iPenColor,CGraphicsContext::EDrawModePEN);
sl@0
   353
					}
sl@0
   354
				}
sl@0
   355
			if (bl.iY >= aClipRect.iTl.iY && bl.iY < aClipRect.iBr.iY)
sl@0
   356
				{
sl@0
   357
				if (bl.iX < aClipRect.iTl.iX)
sl@0
   358
					{
sl@0
   359
					bl.iX = aClipRect.iTl.iX;
sl@0
   360
					}
sl@0
   361
				if (br.iX >= aClipRect.iBr.iX)
sl@0
   362
					{
sl@0
   363
					br.iX = aClipRect.iBr.iX - 1;
sl@0
   364
					}
sl@0
   365
				if (bl.iX <= br.iX)
sl@0
   366
					{
sl@0
   367
					iDrawDevice->WriteRgbMulti(bl.iX,bl.iY,br.iX - bl.iX + 1,1,iPenColor,CGraphicsContext::EDrawModePEN);
sl@0
   368
					}
sl@0
   369
				}
sl@0
   370
			}
sl@0
   371
sl@0
   372
		if (tl.iY == bl.iY && tl.iY >= aClipRect.iTl.iY && tl.iY < aClipRect.iBr.iY)
sl@0
   373
			{
sl@0
   374
			if (tl.iX < aClipRect.iTl.iX)
sl@0
   375
				{
sl@0
   376
				tl.iX = aClipRect.iTl.iX;
sl@0
   377
				}
sl@0
   378
			if (tr.iX >= aClipRect.iBr.iX)
sl@0
   379
				{
sl@0
   380
				tr.iX = aClipRect.iBr.iX - 1;
sl@0
   381
				}
sl@0
   382
			if (tl.iX <= tr.iX)
sl@0
   383
				{
sl@0
   384
				iDrawDevice->WriteRgbMulti(tl.iX,tl.iY,tr.iX - tl.iX + 1,1, iPenColor, CGraphicsContext::EDrawModePEN);
sl@0
   385
				}
sl@0
   386
			}
sl@0
   387
		}
sl@0
   388
	}
sl@0
   389
sl@0
   390
/**
sl@0
   391
@panic DGDIAdapter 1016, if the current pen size is zero (debug only).
sl@0
   392
*/
sl@0
   393
void CSwDirectGdiEngine::PenDrawDeferred(TPoint aPoint,TInt* aArray, TInt aFirstElement)
sl@0
   394
	{
sl@0
   395
	GRAPHICS_ASSERT_DEBUG(iPenArray,EDirectGdiPanicZeroLength);
sl@0
   396
	GRAPHICS_ASSERT_DEBUG(iPenSize.iWidth > 0,EDirectGdiPanicZeroLength);
sl@0
   397
	GRAPHICS_ASSERT_DEBUG(iPenSize.iHeight > 0,EDirectGdiPanicZeroLength);
sl@0
   398
sl@0
   399
	aPoint.iX -= ((iPenSize.iWidth - 1) >> 1);
sl@0
   400
	const TInt doublepenheight = iPenSize.iHeight << 1;
sl@0
   401
sl@0
   402
	for (TInt ix = 0; ix < doublepenheight; ix++,aFirstElement++)
sl@0
   403
		{
sl@0
   404
		if (aFirstElement == doublepenheight)
sl@0
   405
			{
sl@0
   406
			aFirstElement = 0;
sl@0
   407
			}
sl@0
   408
		TInt newval = aPoint.iX + iPenArray[ix];
sl@0
   409
		if (newval < aArray[aFirstElement])
sl@0
   410
			{
sl@0
   411
			aArray[aFirstElement] = newval;
sl@0
   412
			}
sl@0
   413
sl@0
   414
		ix++;
sl@0
   415
		aFirstElement++;
sl@0
   416
		newval = aPoint.iX + iPenArray[ix];
sl@0
   417
		if (newval > aArray[aFirstElement])
sl@0
   418
			{
sl@0
   419
			aArray[aFirstElement] = newval;
sl@0
   420
			}
sl@0
   421
		}
sl@0
   422
	}