os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdigraphics.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.
     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 	}