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