1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/windowing/windowserver/test/tdynamicres/src/surfaceutility.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1544 @@
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 +/**
1.20 + @file
1.21 +*/
1.22 +
1.23 +#include <e32std.h>
1.24 +#include <imageconversion.h>
1.25 +#include "surfaceutility.h"
1.26 +
1.27 +CSurfaceUtility::CSurfaceUtility(CSurfaceUtility* aClone/*=NULL*/)
1.28 + : iSurfaces(aClone?&(aClone->iSurfaces):NULL)
1.29 + {
1.30 + }
1.31 +
1.32 +CSurfaceUtility* CSurfaceUtility::NewL(CSurfaceUtility* aClone/*=NULL*/)
1.33 + {
1.34 + CSurfaceUtility* utility = new (ELeave)CSurfaceUtility(aClone);
1.35 + CleanupStack::PushL(utility);
1.36 + utility->ConstructL();
1.37 + CleanupStack::Pop(utility);
1.38 + return utility;
1.39 + }
1.40 +
1.41 +void CSurfaceUtility::ConstructL()
1.42 + {
1.43 + TInt r = iManager.Open();
1.44 + if (r != KErrNone)
1.45 + {
1.46 + LOG(("Surface manager failed to open: %d", r));
1.47 + User::Leave(r);
1.48 + }
1.49 +
1.50 + r = iSurfaceUpdateSession.Connect();
1.51 + if (r != KErrNone)
1.52 + {
1.53 + LOG(("Failed to connect to update server: %d", r));
1.54 + User::Leave(r);
1.55 + }
1.56 + }
1.57 +
1.58 +CSurfaceUtility::~CSurfaceUtility()
1.59 + {
1.60 + DestroyAll();
1.61 +
1.62 + iSurfaces.Close();
1.63 +
1.64 + iManager.Close();
1.65 +
1.66 + iSurfaceUpdateSession.Close();
1.67 + }
1.68 +
1.69 +TBool CSurfaceUtility::DestroyAll()
1.70 + {
1.71 + TInt err = KErrNone;
1.72 + TInt jj = iSurfaces.Count() - 1;
1.73 + if (jj<0)
1.74 + return EFalse;
1.75 + for (; jj >= 0; jj--)
1.76 + {
1.77 + err = iManager.CloseSurface(iSurfaces[jj]);
1.78 + if (err!=KErrNone)
1.79 + {
1.80 + LOG(("Error closing surface: 0x%X\n", err));
1.81 + }
1.82 + }
1.83 + iSurfaces.Reset();
1.84 + return ETrue;
1.85 + }
1.86 +
1.87 +/***************************************
1.88 + * The aim of the THeapSurfaceArray is to locally switch in the specified heap for any array operation
1.89 + ***************************************/
1.90 +
1.91 +CSurfaceUtility::RHeapSurfaceArray::RHeapSurfaceArray(RHeapSurfaceArray* aUseExternalArray)
1.92 + : iUseArray(aUseExternalArray?aUseExternalArray->iUseArray:&this->iLocalArray),
1.93 + iExternalHeapRef(aUseExternalArray?aUseExternalArray->iExternalHeapRef:User::Heap())
1.94 + {
1.95 +
1.96 + }
1.97 +/************************************
1.98 + * The following methods have been used by the surfaceutility... some require the heap wrapping, and some don't
1.99 + * I actually need three different startegies (count em) for 7 methods...
1.100 + * Some methods only read the existing objects, so don't need a heap swap at all
1.101 + * Leaving methods have to use PopAndDestroy strategy to restore the heap on leaving or success
1.102 + * Non-leaving methods must not call PushL, so directly make SwitchHeap calls!
1.103 + ************************************/
1.104 +
1.105 +// PopAndDestroy method to restore the heap
1.106 +/*static*/ void CSurfaceUtility::RHeapSurfaceArray::PopHeap(void* aHeapPtr)
1.107 + {
1.108 + RHeap* heapPtr=(RHeap*)aHeapPtr;
1.109 + User::SwitchHeap(heapPtr);
1.110 + }
1.111 +
1.112 +// Switches and pushes the previous heap so it can be restored with PopAndDestroy
1.113 +/*static*/ void CSurfaceUtility::RHeapSurfaceArray::SwitchHeapLC(RHeap* aNewHeap)
1.114 + {
1.115 + CleanupStack::PushL(TCleanupItem(PopHeap,NULL));
1.116 + CleanupStack::PushL(TCleanupItem(PopHeap,NULL));
1.117 + CleanupStack::PushL(TCleanupItem(PopHeap,NULL));
1.118 + CleanupStack::Pop(3);
1.119 + RHeap* oldHeap=User::SwitchHeap(aNewHeap);
1.120 + delete new char;
1.121 + CleanupStack::PushL(TCleanupItem(PopHeap,oldHeap));
1.122 + }
1.123 +
1.124 +
1.125 +TSurfaceId& CSurfaceUtility::RHeapSurfaceArray::operator[](TUint aIndex)
1.126 + {
1.127 + return iUseArray->operator[](aIndex);
1.128 + }
1.129 +// Close only closes the local array, while Reset resets the active array (may be external)
1.130 +void CSurfaceUtility::RHeapSurfaceArray::Close()
1.131 + {
1.132 + RHeap* oldHeap=User::SwitchHeap(&iExternalHeapRef);
1.133 + iLocalArray.Close();
1.134 + User::SwitchHeap(oldHeap);
1.135 + }
1.136 +TInt CSurfaceUtility::RHeapSurfaceArray::Count() const
1.137 + {
1.138 + return iUseArray->Count();
1.139 + }
1.140 +// Close only closes the local array, while Reset resets the active array (may be external)
1.141 +inline void CSurfaceUtility::RHeapSurfaceArray::Reset()
1.142 + {
1.143 + RHeap* oldHeap=User::SwitchHeap(&iExternalHeapRef);
1.144 + iUseArray->Reset();
1.145 + User::SwitchHeap(oldHeap);
1.146 + }
1.147 +void CSurfaceUtility::RHeapSurfaceArray::AppendL(const TSurfaceId &anEntry)
1.148 + {
1.149 + SwitchHeapLC(&iExternalHeapRef);
1.150 + iUseArray->AppendL(anEntry);
1.151 + CleanupStack::PopAndDestroy();
1.152 + }
1.153 +TInt CSurfaceUtility::RHeapSurfaceArray::Find(const TSurfaceId &anEntry) const
1.154 + {
1.155 + return iUseArray->Find(anEntry);
1.156 + }
1.157 +void CSurfaceUtility::RHeapSurfaceArray::Remove(TInt anIndex)
1.158 + {
1.159 + RHeap* oldHeap=User::SwitchHeap(&iExternalHeapRef);
1.160 + iUseArray->Remove(anIndex);
1.161 + User::SwitchHeap(oldHeap);
1.162 + }
1.163 +
1.164 +
1.165 +
1.166 +
1.167 +/**
1.168 +Cleanup stack helper object, holding references to both utility and surface, so
1.169 +that the standard Close() semantics can be used.
1.170 +*/
1.171 +class TSurfaceCleanup
1.172 + {
1.173 +public:
1.174 + TSurfaceCleanup(CSurfaceUtility& aUtility, TSurfaceId& aSurface)
1.175 + : iUtility(aUtility), iSurface(aSurface)
1.176 + {}
1.177 + void Close()
1.178 + {
1.179 + // Removes the surface from the list of surfaces to clean up, and closes
1.180 + // the surface reference.
1.181 + iUtility.DestroySurface(iSurface);
1.182 + }
1.183 +private:
1.184 + CSurfaceUtility& iUtility;
1.185 + TSurfaceId& iSurface;
1.186 + };
1.187 +
1.188 +/**
1.189 +Read the given image file into a new surface.
1.190 +
1.191 +@param aFileName The name of the image file.
1.192 +@param aSurface Filled with the surface ID for the surface containing the pixels.
1.193 +*/
1.194 +void CSurfaceUtility::CreateSurfaceFromFileL(const TDesC& aFileName, TSurfaceId& aSurface)
1.195 + {
1.196 + RFs fs;
1.197 +
1.198 + User::LeaveIfError(fs.Connect());
1.199 + CleanupClosePushL(fs);
1.200 + CImageDecoder* decoder = CImageDecoder::FileNewL(fs, aFileName, CImageDecoder::EOptionAlwaysThread);
1.201 + CleanupStack::PushL(decoder);
1.202 +
1.203 + const TFrameInfo& info = decoder->FrameInfo();
1.204 +
1.205 + TSize size = info.iOverallSizeInPixels;
1.206 + TInt stride = size.iWidth << 2; // Default to four bytes per pixel
1.207 + TDisplayMode bmpFormat = info.iFrameDisplayMode;
1.208 + TUidPixelFormat pixelFormat = EUidPixelFormatUnknown;
1.209 +
1.210 + switch (bmpFormat)
1.211 + {
1.212 + case EGray2:
1.213 + case EGray4:
1.214 + case EGray16:
1.215 + case EGray256:
1.216 + case EColor16:
1.217 + case EColor256:
1.218 + case EColor16M:
1.219 + case EColor16MU:
1.220 + {
1.221 + bmpFormat = EColor16MU;
1.222 + pixelFormat = EUidPixelFormatXRGB_8888;
1.223 + break;
1.224 + }
1.225 + case EColor4K:
1.226 + {
1.227 + stride = size.iWidth << 1;
1.228 + pixelFormat = EUidPixelFormatXRGB_4444;
1.229 + break;
1.230 + }
1.231 + case EColor64K:
1.232 + {
1.233 + stride = size.iWidth << 1;
1.234 + pixelFormat = EUidPixelFormatRGB_565;
1.235 + break;
1.236 + }
1.237 + case EColor16MA:
1.238 + {
1.239 + pixelFormat = EUidPixelFormatARGB_8888;
1.240 + break;
1.241 + }
1.242 + case EColor16MAP:
1.243 + {
1.244 + pixelFormat = EUidPixelFormatARGB_8888_PRE;
1.245 + break;
1.246 + }
1.247 + default:
1.248 + {
1.249 + LOG(("Unsupported display mode: %d", bmpFormat));
1.250 + User::Leave(KErrNotSupported);
1.251 + break;
1.252 + }
1.253 + }
1.254 +
1.255 + // Create an intermediary bitmap for decoding into
1.256 + CFbsBitmap* bitmap = new (ELeave) CFbsBitmap();
1.257 + CleanupStack::PushL(bitmap);
1.258 + User::LeaveIfError(bitmap->Create(size, info.iFrameDisplayMode));
1.259 +
1.260 + // Create the final surface.
1.261 + aSurface = CreateSurfaceL(size, pixelFormat, stride);
1.262 + TSurfaceCleanup surfaceCleanup(*this, aSurface);
1.263 + CleanupClosePushL(surfaceCleanup);
1.264 +
1.265 + RChunk chunk;
1.266 + User::LeaveIfError(iManager.MapSurface(aSurface, chunk));
1.267 + CleanupClosePushL(chunk);
1.268 +
1.269 + // Convert the image file into a Symbian bitmap
1.270 + TRequestStatus status;
1.271 + decoder->Convert(&status, *bitmap);
1.272 + User::WaitForRequest(status);
1.273 + User::LeaveIfError(status.Int());
1.274 +
1.275 + TInt offsetToFirstBuffer;
1.276 + User::LeaveIfError(iManager.GetBufferOffset(aSurface, 0, offsetToFirstBuffer));
1.277 +
1.278 + // Copy the data from the bitmap into the surface.
1.279 + TPoint start;
1.280 + TUint8 *pSurfStart = chunk.Base() + offsetToFirstBuffer;
1.281 + for (start.iY = 0; start.iY < size.iHeight; start.iY++)
1.282 + {
1.283 + // Set up a descriptor for the current line in the surface and get pixels.
1.284 + TPtr8 ptr(pSurfStart + start.iY * stride, stride);
1.285 + bitmap->GetScanLine(ptr, start, size.iWidth, bmpFormat);
1.286 + }
1.287 +
1.288 + CleanupStack::PopAndDestroy(/* chunk */);
1.289 + CleanupStack::Pop(/* surfaceCleanup */);
1.290 + CleanupStack::PopAndDestroy(bitmap);
1.291 + CleanupStack::PopAndDestroy(decoder);
1.292 + CleanupStack::PopAndDestroy(/* fs */);
1.293 + }
1.294 +
1.295 +void CSurfaceUtility::CopyBitmapSurfaceL(const CFbsBitmap* aBitmap, TSurfaceId& aSurface)
1.296 + {
1.297 + RChunk chunk;
1.298 + User::LeaveIfError(iManager.MapSurface(aSurface, chunk));
1.299 + CleanupClosePushL(chunk);
1.300 + TSize bitmapSize = aBitmap->SizeInPixels();
1.301 + TSize size = SurfaceSize(aSurface);
1.302 + TInt stride = size.iWidth*4; // Default to four bytes per pixel
1.303 +
1.304 + TInt offsetToFirstBuffer;
1.305 + User::LeaveIfError(iManager.GetBufferOffset(aSurface, 0, offsetToFirstBuffer));
1.306 +
1.307 + // Copy the data from the bitmap into the surface.
1.308 + TPoint start;
1.309 + TUint8 *pSurfStart = chunk.Base() + offsetToFirstBuffer;
1.310 + for (start.iY = 0; start.iY < bitmapSize.iHeight; start.iY++)
1.311 + {
1.312 + // Set up a descriptor for the current line in the surface and get pixels.
1.313 + TPtr8 ptr(pSurfStart + start.iY * stride, stride);
1.314 + aBitmap->GetScanLine(ptr, start, bitmapSize.iWidth, EColor16MU);
1.315 + }
1.316 + CleanupStack::PopAndDestroy(/* chunk */);
1.317 +
1.318 + }
1.319 +/**
1.320 +Copy the bitmap from a file to a surface.
1.321 +
1.322 +@param aFileName The name of the image file.
1.323 +@param aSurface Filled with the surface ID for the surface containing the pixels.
1.324 +*/
1.325 +void CSurfaceUtility::CopyBitmapFromFileToSurfaceL(const TDesC& aFileName, TSurfaceId& aSurface)
1.326 + {
1.327 + RFs fs;
1.328 +
1.329 + User::LeaveIfError(fs.Connect());
1.330 + CleanupClosePushL(fs);
1.331 + CImageDecoder* decoder = CImageDecoder::FileNewL(fs, aFileName, CImageDecoder::EOptionAlwaysThread);
1.332 + CleanupStack::PushL(decoder);
1.333 +
1.334 + const TFrameInfo& info = decoder->FrameInfo();
1.335 +
1.336 + RSurfaceManager::TInfoBuf infoBuf;
1.337 + RSurfaceManager::TSurfaceInfoV01& infoSurf = infoBuf();
1.338 + User::LeaveIfError(iManager.SurfaceInfo(aSurface, infoBuf));
1.339 +
1.340 + TSize size = infoSurf.iSize;
1.341 + TDisplayMode bmpFormat = info.iFrameDisplayMode;
1.342 + TInt stride = size.iWidth << 2; // Default to four bytes per pixel
1.343 +
1.344 + // Create an intermediary bitmap for decoding into
1.345 + CFbsBitmap* bitmap = new (ELeave) CFbsBitmap();
1.346 + CleanupStack::PushL(bitmap);
1.347 + User::LeaveIfError(bitmap->Create(size, info.iFrameDisplayMode));
1.348 +
1.349 + RChunk chunk;
1.350 + User::LeaveIfError(iManager.MapSurface(aSurface, chunk));
1.351 + CleanupClosePushL(chunk);
1.352 +
1.353 + // Convert the image file into a Symbian bitmap
1.354 + TRequestStatus status;
1.355 + decoder->Convert(&status, *bitmap);
1.356 + User::WaitForRequest(status);
1.357 + User::LeaveIfError(status.Int());
1.358 +
1.359 + TInt offsetToFirstBuffer;
1.360 + User::LeaveIfError(iManager.GetBufferOffset(aSurface, 0, offsetToFirstBuffer));
1.361 +
1.362 + // Copy the data from the bitmap into the surface.
1.363 + TPoint start;
1.364 + TUint8 *pSurfStart = chunk.Base() + offsetToFirstBuffer;
1.365 + for (start.iY = 0; start.iY < size.iHeight; start.iY++)
1.366 + {
1.367 + // Set up a descriptor for the current line in the surface and get pixels.
1.368 + TPtr8 ptr(pSurfStart + start.iY * stride, stride);
1.369 + bitmap->GetScanLine(ptr, start, size.iWidth, bmpFormat);
1.370 + }
1.371 +
1.372 + CleanupStack::PopAndDestroy(/* chunk */);
1.373 + CleanupStack::PopAndDestroy(bitmap);
1.374 + CleanupStack::PopAndDestroy(decoder);
1.375 + CleanupStack::PopAndDestroy(/* fs */);
1.376 + }
1.377 +/**
1.378 +Get the size of a surface.
1.379 +
1.380 +@param aSurface The surface to get the size for.
1.381 +@return The size in pixels, or empty on failure.
1.382 +*/
1.383 +TSize CSurfaceUtility::SurfaceSize(const TSurfaceId& aSurface)
1.384 + {
1.385 + RSurfaceManager::TInfoBuf infoBuf;
1.386 + RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
1.387 +
1.388 + if (iManager.SurfaceInfo(aSurface, infoBuf) == KErrNone)
1.389 + {
1.390 + return info.iSize;
1.391 + }
1.392 +
1.393 + return TSize();
1.394 + }
1.395 +
1.396 +
1.397 +/**
1.398 +Create a surface using the surface manager.
1.399 +
1.400 +Stores the ID for tear down, as well as returning it.
1.401 +
1.402 +@param aSize Dimensions of the surface.
1.403 +@param aPixelFormat UID of the pixel format.
1.404 +@param aStride Stride value for the surface (usually bytes per pixel * width)
1.405 +@leave May leave due to lack of memory.
1.406 +@return New surface's ID.
1.407 +*/
1.408 +TSurfaceId CSurfaceUtility::CreateSurfaceL(const TSize& aSize, TUidPixelFormat aPixelFormat, TInt aStride, TInt aBuffers)
1.409 + {
1.410 + RSurfaceManager::TSurfaceCreationAttributesBuf bf;
1.411 + RSurfaceManager::TSurfaceCreationAttributes& b = bf();
1.412 +
1.413 + b.iSize.iWidth = aSize.iWidth;
1.414 + b.iSize.iHeight = aSize.iHeight;
1.415 + b.iBuffers = aBuffers; // number of buffers in the surface
1.416 + b.iPixelFormat = aPixelFormat;
1.417 + b.iStride = aStride; // Number of bytes between start of one line and start of next
1.418 + b.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
1.419 + b.iAlignment = 4; // alignment, 1,2,4,8 byte aligned
1.420 + b.iContiguous = EFalse;
1.421 + b.iMappable = ETrue;
1.422 +
1.423 + TSurfaceId surface = TSurfaceId::CreateNullId();
1.424 +
1.425 + User::LeaveIfError(iManager.CreateSurface(bf, surface));
1.426 + iSurfaces.AppendL(surface);
1.427 + return surface;
1.428 + }
1.429 +
1.430 +/**
1.431 +A helper function that returns the bytes per pixel for a given pixel format uid
1.432 +
1.433 +@param aPixelFormat Pixel format UID to convert
1.434 +@return The bytes per pixel
1.435 +*/
1.436 +TInt CSurfaceUtility::BytesPerPixelL(TUidPixelFormat aPixelFormat)
1.437 + {
1.438 + TInt bytesPerPixel = 0;
1.439 + switch (aPixelFormat)
1.440 + {
1.441 + case EUidPixelFormatXRGB_8888:
1.442 + case EUidPixelFormatARGB_8888:
1.443 + case EUidPixelFormatARGB_8888_PRE:
1.444 + {
1.445 + bytesPerPixel = 4;
1.446 + break;
1.447 + }
1.448 + case EUidPixelFormatXRGB_4444:
1.449 + case EUidPixelFormatARGB_4444:
1.450 + case EUidPixelFormatRGB_565:
1.451 + {
1.452 + bytesPerPixel = 2;
1.453 + break;
1.454 + }
1.455 + default:
1.456 + {
1.457 + User::Leave(KErrNotSupported);
1.458 + break;
1.459 + }
1.460 + }
1.461 + return bytesPerPixel;
1.462 + }
1.463 +
1.464 +/**
1.465 +Fill the given surface with a color.
1.466 +
1.467 +@param aSurface The surface to be filled.
1.468 +@param aColor The color to fill it with.
1.469 +*/
1.470 +void CSurfaceUtility::FillSurfaceL(TSurfaceId& aSurface, const TRgb& aColor)
1.471 + {
1.472 + RSurfaceManager::TInfoBuf infoBuf;
1.473 + RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
1.474 +
1.475 + User::LeaveIfError(iManager.SurfaceInfo(aSurface, infoBuf));
1.476 + TUint32 color = 0;
1.477 + TBool use16 = EFalse;
1.478 +
1.479 + if (info.iSize.iHeight<0 || info.iSize.iWidth<0 || info.iStride<0)
1.480 + {
1.481 + User::Leave(KErrCorrupt);
1.482 + }
1.483 + if (info.iSize.iHeight==0 || info.iSize.iWidth==0 || info.iStride==0)
1.484 + {
1.485 + User::Leave(KErrNotReady);
1.486 + }
1.487 +
1.488 + switch (info.iPixelFormat)
1.489 + {
1.490 + case EUidPixelFormatXRGB_8888:
1.491 + {
1.492 + color = aColor.Color16MU();
1.493 +#ifdef ALPHA_FIX_24BIT
1.494 + color |= ((ALPHA_FIX_24BIT)&0xff)<<24;
1.495 +#endif
1.496 + break;
1.497 + }
1.498 + case EUidPixelFormatARGB_8888:
1.499 + {
1.500 + color = aColor.Color16MA();
1.501 + break;
1.502 + }
1.503 + case EUidPixelFormatARGB_8888_PRE:
1.504 + {
1.505 + color = aColor.Color16MAP();
1.506 + break;
1.507 + }
1.508 + case EUidPixelFormatXRGB_4444:
1.509 + case EUidPixelFormatARGB_4444:
1.510 + {
1.511 + color = aColor.Color4K();
1.512 + use16 = ETrue;
1.513 + break;
1.514 + }
1.515 + case EUidPixelFormatRGB_565:
1.516 + {
1.517 + color = aColor.Color64K();
1.518 + use16 = ETrue;
1.519 + break;
1.520 + }
1.521 + default:
1.522 + {
1.523 + User::Leave(KErrNotSupported);
1.524 + break;
1.525 + }
1.526 + }
1.527 +
1.528 + RChunk chunk;
1.529 + User::LeaveIfError(iManager.MapSurface(aSurface, chunk));
1.530 + CleanupClosePushL(chunk);
1.531 +
1.532 + TInt offsetToFirstBuffer;
1.533 + User::LeaveIfError(iManager.GetBufferOffset(aSurface, 0, offsetToFirstBuffer));
1.534 + TUint8* surfacePtr = chunk.Base() + offsetToFirstBuffer;
1.535 + TUint8* linePtr = surfacePtr;
1.536 +
1.537 + if (use16)
1.538 + {
1.539 + if ( info.iSize.iWidth*2>info.iStride)
1.540 + {
1.541 + User::Leave(KErrOverflow);
1.542 + }
1.543 + TUint16* ptr = reinterpret_cast<TUint16*>(surfacePtr);
1.544 +
1.545 + // Fill first line
1.546 + for (TInt xx = 0; xx < info.iSize.iWidth; xx++)
1.547 + {
1.548 + ptr[xx] = (TUint16)color;
1.549 + }
1.550 + }
1.551 + else
1.552 + {
1.553 + if ( info.iSize.iWidth*4>info.iStride)
1.554 + {
1.555 + User::Leave(KErrOverflow);
1.556 + }
1.557 + TUint32* ptr = reinterpret_cast<TUint32*>(surfacePtr);
1.558 +
1.559 + // Fill first line
1.560 + for (TInt xx = 0; xx < info.iSize.iWidth; xx++)
1.561 + {
1.562 + ptr[xx] = color;
1.563 + }
1.564 + }
1.565 +
1.566 + // Now copy that to the other lines
1.567 + for (TInt yy = 1; yy < info.iSize.iHeight; yy++)
1.568 + {
1.569 + linePtr += info.iStride;
1.570 + Mem::Copy(linePtr, surfacePtr, info.iSize.iWidth * BytesPerPixelL(info.iPixelFormat));
1.571 + }
1.572 +
1.573 + TInt err = iSurfaceUpdateSession.SubmitUpdate(KAllScreens, aSurface, 0, NULL);
1.574 + if (err!=KErrNone)
1.575 + LOG(("Error submitting update: 0x%X\n", err));
1.576 +
1.577 + CleanupStack::PopAndDestroy(/* chunk */);
1.578 + }
1.579 +
1.580 +/**
1.581 +Fill the given memory chunk with a color.
1.582 +
1.583 +@param aSurface The surface to be filled.
1.584 +@param aChunk The surface to be filled.
1.585 +@param aColor The color to fill it with.
1.586 +*/
1.587 +void CSurfaceUtility::FillChunkL(TSurfaceId& aSurface, RChunk& aChunk, const TRgb& aColor, TInt aBufferNumber)
1.588 + {
1.589 + RSurfaceManager::TInfoBuf infoBuf;
1.590 + RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
1.591 +
1.592 + User::LeaveIfError(iManager.SurfaceInfo(aSurface, infoBuf));
1.593 + TUint32 color = 0;
1.594 + TBool use16 = EFalse;
1.595 +
1.596 + if (info.iSize.iHeight<0 || info.iSize.iWidth<0 || info.iStride<0)
1.597 + {
1.598 + User::Leave(KErrCorrupt);
1.599 + }
1.600 + if (info.iSize.iHeight==0 || info.iSize.iWidth==0 || info.iStride==0)
1.601 + {
1.602 + User::Leave(KErrNotReady);
1.603 + }
1.604 +
1.605 + switch (info.iPixelFormat)
1.606 + {
1.607 + case EUidPixelFormatXRGB_8888:
1.608 + {
1.609 + color = aColor.Color16MU();
1.610 +#ifdef ALPHA_FIX_24BIT
1.611 + color |= ((ALPHA_FIX_24BIT)&0xff)<<24;
1.612 +#endif
1.613 + break;
1.614 + }
1.615 + case EUidPixelFormatARGB_8888:
1.616 + {
1.617 + color = aColor.Color16MA();
1.618 + break;
1.619 + }
1.620 + case EUidPixelFormatARGB_8888_PRE:
1.621 + {
1.622 + color = aColor.Color16MAP();
1.623 + break;
1.624 + }
1.625 + case EUidPixelFormatXRGB_4444:
1.626 + case EUidPixelFormatARGB_4444:
1.627 + {
1.628 + color = aColor.Color4K();
1.629 + use16 = ETrue;
1.630 + break;
1.631 + }
1.632 + case EUidPixelFormatRGB_565:
1.633 + {
1.634 + color = aColor.Color64K();
1.635 + use16 = ETrue;
1.636 + break;
1.637 + }
1.638 + default:
1.639 + {
1.640 + User::Leave(KErrNotSupported);
1.641 + break;
1.642 + }
1.643 + }
1.644 +
1.645 + User::LeaveIfError(iManager.MapSurface(aSurface, aChunk));
1.646 +
1.647 + TInt offsetToFirstBuffer;
1.648 + User::LeaveIfError(iManager.GetBufferOffset(aSurface, 0, offsetToFirstBuffer));
1.649 + TInt offsetToBufferNumber;
1.650 + User::LeaveIfError(iManager.GetBufferOffset(aSurface, aBufferNumber, offsetToBufferNumber));
1.651 +
1.652 + TUint8* chunkPtr = aChunk.Base() + offsetToFirstBuffer;
1.653 + TUint8* linePtr = aChunk.Base() + offsetToBufferNumber;
1.654 + TUint8* surfPlanePtr = linePtr;
1.655 +
1.656 + if (use16)
1.657 + {
1.658 + if ( info.iSize.iWidth*2>info.iStride)
1.659 + {
1.660 + aChunk.Close();
1.661 + User::Leave(KErrOverflow);
1.662 + }
1.663 + TUint16* ptr = reinterpret_cast<TUint16*>(surfPlanePtr);
1.664 +
1.665 + // Fill first line
1.666 + for (TInt xx = 0; xx < info.iSize.iWidth; xx++)
1.667 + {
1.668 + ptr[xx] = (TUint16)color;
1.669 + }
1.670 + }
1.671 + else
1.672 + {
1.673 + if ( info.iSize.iWidth*4>info.iStride)
1.674 + {
1.675 + aChunk.Close();
1.676 + User::Leave(KErrOverflow);
1.677 + }
1.678 + TUint32* ptr = reinterpret_cast<TUint32*>(surfPlanePtr);
1.679 +
1.680 + // Fill first line
1.681 + for (TInt xx = 0; xx < info.iSize.iWidth; xx++)
1.682 + {
1.683 + ptr[xx] = color;
1.684 + }
1.685 + }
1.686 +
1.687 + // Now copy that to the other lines
1.688 + for (TInt yy = 1; yy < info.iSize.iHeight; yy++)
1.689 + {
1.690 + linePtr += info.iStride;
1.691 + Mem::Copy(linePtr, surfPlanePtr, info.iSize.iWidth * BytesPerPixelL(info.iPixelFormat));
1.692 + }
1.693 +
1.694 + aChunk.Close();
1.695 + }
1.696 +
1.697 +/**
1.698 +Fill a rectangle on the given surface.
1.699 +
1.700 +@param aSurface The surface to be filled.
1.701 +@param aStartPos Where to place the rectangle.
1.702 +@param aSize Size of the rectangle.
1.703 +@param aColor The colour to fill it with.
1.704 +*/
1.705 +void CSurfaceUtility::FillRectangleL(TSurfaceId& aSurface, const TPoint& aStartPos, const TSize& aSize, const TRgb& aColor)
1.706 + {
1.707 + FillRectangleNoUpdateL(aSurface, aStartPos, aSize, aColor);
1.708 +
1.709 + TInt err = iSurfaceUpdateSession.SubmitUpdate(KAllScreens, aSurface, 0, NULL);
1.710 + if (err!=KErrNone)
1.711 + LOG(("Error submitting update: 0x%X\n", err));
1.712 + }
1.713 +
1.714 +/**
1.715 +Fill a rectangle on the given surface - does not submit update.
1.716 +
1.717 +@param aSurface The surface to be filled.
1.718 +@param aStartPos Where to place the rectangle.
1.719 +@param aSize Size of the rectangle.
1.720 +@param aColor The colour to fill it with.
1.721 +*/
1.722 +void CSurfaceUtility::FillRectangleNoUpdateL(TSurfaceId& aSurface, const TPoint& aStartPos, const TSize& aSize, const TRgb& aColor)
1.723 + {
1.724 + RSurfaceManager::TInfoBuf infoBuf;
1.725 + RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
1.726 +
1.727 + User::LeaveIfError(iManager.SurfaceInfo(aSurface, infoBuf));
1.728 + TUint32 color = 0;
1.729 + TBool use16 = EFalse;
1.730 +
1.731 + if (info.iSize.iHeight<0 || info.iSize.iWidth<0 || info.iStride<0)
1.732 + {
1.733 + User::Leave(KErrCorrupt);
1.734 + }
1.735 + if (info.iSize.iHeight==0 || info.iSize.iWidth==0 || info.iStride==0)
1.736 + {
1.737 + User::Leave(KErrNotReady);
1.738 + }
1.739 +
1.740 + switch (info.iPixelFormat)
1.741 + {
1.742 + case EUidPixelFormatXRGB_8888:
1.743 + {
1.744 + color = aColor.Color16MU();
1.745 +#ifdef ALPHA_FIX_24BIT
1.746 + color |= ((ALPHA_FIX_24BIT)&0xff)<<24;
1.747 +#endif
1.748 + break;
1.749 + }
1.750 + case EUidPixelFormatARGB_8888:
1.751 + {
1.752 + color = aColor.Color16MA();
1.753 + break;
1.754 + }
1.755 + case EUidPixelFormatARGB_8888_PRE:
1.756 + {
1.757 + color = aColor.Color16MAP();
1.758 + break;
1.759 + }
1.760 + case EUidPixelFormatXRGB_4444:
1.761 + case EUidPixelFormatARGB_4444:
1.762 + {
1.763 + color = aColor.Color4K();
1.764 + use16 = ETrue;
1.765 + break;
1.766 + }
1.767 + case EUidPixelFormatRGB_565:
1.768 + {
1.769 + color = aColor.Color64K();
1.770 + use16 = ETrue;
1.771 + break;
1.772 + }
1.773 + default:
1.774 + {
1.775 + User::Leave(KErrNotSupported);
1.776 + break;
1.777 + }
1.778 + }
1.779 +
1.780 + RChunk chunk;
1.781 + User::LeaveIfError(iManager.MapSurface(aSurface, chunk));
1.782 + CleanupClosePushL(chunk);
1.783 +
1.784 + TInt offsetToFirstBuffer;
1.785 + User::LeaveIfError(iManager.GetBufferOffset(aSurface, 0, offsetToFirstBuffer));
1.786 + TUint8* surfacePtr = chunk.Base() + offsetToFirstBuffer;
1.787 +
1.788 + // Check for out of bounds
1.789 + TBool validRect = ETrue;
1.790 + TInt surfaceWidth = info.iSize.iWidth;
1.791 + TInt surfaceHeight = info.iSize.iHeight;
1.792 +
1.793 + // Width and Height
1.794 + if ((aStartPos.iX + aSize.iWidth) > surfaceWidth)
1.795 + validRect = EFalse;
1.796 +
1.797 + if ((aStartPos.iY + aSize.iHeight) > surfaceHeight)
1.798 + validRect = EFalse;
1.799 +
1.800 + // Starting position
1.801 + if ((aStartPos.iX < 0) || (aStartPos.iY < 0))
1.802 + validRect = EFalse;
1.803 +
1.804 + if (!validRect)
1.805 + User::Leave(KErrOverflow);
1.806 +
1.807 + if (use16)
1.808 + {
1.809 + if ( info.iSize.iWidth*2>info.iStride)
1.810 + {
1.811 + User::Leave(KErrOverflow);
1.812 + }
1.813 +
1.814 + TUint16* ptr = reinterpret_cast<TUint16*>(surfacePtr);
1.815 +
1.816 + // Fill the rectangle
1.817 + TInt yPos = aStartPos.iY;
1.818 + TInt xPos = aStartPos.iX;
1.819 + for (TInt yy = 0; yy < aSize.iHeight; ++yy)
1.820 + {
1.821 + ptr = reinterpret_cast<TUint16*>(surfacePtr+(yPos*info.iStride));
1.822 + for (TInt xx = 0; xx < aSize.iWidth; ++xx)
1.823 + {
1.824 + ptr[xPos] = color;
1.825 + xPos++;
1.826 + }
1.827 + xPos = aStartPos.iX;
1.828 + yPos++;
1.829 + }
1.830 + }
1.831 + else
1.832 + {
1.833 + if ( info.iSize.iWidth*4>info.iStride)
1.834 + {
1.835 + User::Leave(KErrOverflow);
1.836 + }
1.837 +
1.838 + TUint32* ptr = reinterpret_cast<TUint32*>(surfacePtr);
1.839 +
1.840 + // Fill the rectangle
1.841 + TInt yPos = aStartPos.iY;
1.842 + TInt xPos = aStartPos.iX;
1.843 + for (TInt yy = 0; yy < aSize.iHeight; ++yy)
1.844 + {
1.845 + ptr = reinterpret_cast<TUint32*>(surfacePtr+(yPos*info.iStride));
1.846 + for (TInt xx = 0; xx < aSize.iWidth; ++xx)
1.847 + {
1.848 + ptr[xPos] = color;
1.849 + xPos++;
1.850 + }
1.851 + xPos = aStartPos.iX;
1.852 + yPos++;
1.853 + }
1.854 + }
1.855 +
1.856 + CleanupStack::PopAndDestroy(/* chunk */);
1.857 + }
1.858 +
1.859 +/**
1.860 +Fill the given surface with a grid over a solid color.
1.861 +
1.862 +Similar to FillSurfaceL(), but with a grid overlayed. The pitch of the grid is
1.863 +eight pixels.
1.864 +
1.865 +@param aSurface The surface to be filled.
1.866 +@param aColor The color to fill it with.
1.867 +@param aLines The color of the grid lines.
1.868 +*/
1.869 +void CSurfaceUtility::GridFillSurfaceL(TSurfaceId& aSurface, const TRgb& aColor, const TRgb& aLines)
1.870 + {
1.871 + RSurfaceManager::TInfoBuf infoBuf;
1.872 + RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
1.873 +
1.874 + User::LeaveIfError(iManager.SurfaceInfo(aSurface, infoBuf));
1.875 + TUint32 color = 0;
1.876 + TUint32 lines = 0;
1.877 + TBool use16 = EFalse;
1.878 +
1.879 + if (info.iSize.iHeight<0 || info.iSize.iWidth<0 || info.iStride<0)
1.880 + {
1.881 + User::Leave(KErrCorrupt);
1.882 + }
1.883 + if (info.iSize.iHeight==0 || info.iSize.iWidth==0 || info.iStride==0)
1.884 + {
1.885 + User::Leave(KErrNotReady);
1.886 + }
1.887 +
1.888 + switch (info.iPixelFormat)
1.889 + {
1.890 + case EUidPixelFormatXRGB_8888:
1.891 + {
1.892 + color = aColor.Color16MU();
1.893 + lines = aLines.Color16MU();
1.894 +#ifdef ALPHA_FIX_24BIT
1.895 + color |= ((ALPHA_FIX_24BIT)&0xff)<<24;
1.896 + lines |= ((ALPHA_FIX_24BIT)&0xff)<<24;
1.897 +#endif
1.898 + break;
1.899 + }
1.900 + case EUidPixelFormatARGB_8888:
1.901 + {
1.902 + color = aColor.Color16MA();
1.903 + lines = aLines.Color16MA();
1.904 + break;
1.905 + }
1.906 + case EUidPixelFormatARGB_8888_PRE:
1.907 + {
1.908 + color = aColor.Color16MAP();
1.909 + lines = aLines.Color16MAP();
1.910 + break;
1.911 + }
1.912 + case EUidPixelFormatXRGB_4444:
1.913 + case EUidPixelFormatARGB_4444:
1.914 + {
1.915 + color = aColor.Color4K();
1.916 + lines = aLines.Color4K();
1.917 + use16 = ETrue;
1.918 + break;
1.919 + }
1.920 + case EUidPixelFormatRGB_565:
1.921 + {
1.922 + color = aColor.Color64K();
1.923 + lines = aLines.Color64K();
1.924 + use16 = ETrue;
1.925 + break;
1.926 + }
1.927 + default:
1.928 + {
1.929 + User::Leave(KErrNotSupported);
1.930 + break;
1.931 + }
1.932 + }
1.933 +
1.934 + RChunk chunk;
1.935 + User::LeaveIfError(iManager.MapSurface(aSurface, chunk));
1.936 + CleanupClosePushL(chunk);
1.937 +
1.938 + TInt offsetToFirstBuffer;
1.939 + User::LeaveIfError(iManager.GetBufferOffset(aSurface, 0, offsetToFirstBuffer));
1.940 + TUint8* surfacePtr = chunk.Base() + offsetToFirstBuffer;
1.941 + TUint8* linePtr = surfacePtr;
1.942 +
1.943 + if (use16)
1.944 + {
1.945 + if ( info.iSize.iWidth*2>info.iStride)
1.946 + {
1.947 + User::Leave(KErrOverflow);
1.948 + }
1.949 + TUint16* ptr = reinterpret_cast<TUint16*>(surfacePtr);
1.950 +
1.951 + // Fill first line
1.952 + for (TInt xx1 = 0; xx1 < info.iSize.iWidth; xx1++)
1.953 + {
1.954 + ptr[xx1] = (TUint16)lines;
1.955 + }
1.956 +
1.957 + // Fill second line
1.958 + ptr = reinterpret_cast<TUint16*>(surfacePtr + info.iStride);
1.959 + for (TInt xx2 = 0; xx2 < info.iSize.iWidth; xx2++)
1.960 + {
1.961 + // Vertical line every 8 pixels across
1.962 + ptr[xx2] = (TUint16)((xx2 & 7) ? color : lines);
1.963 + }
1.964 + }
1.965 + else
1.966 + {
1.967 + if ( info.iSize.iWidth*4>info.iStride)
1.968 + {
1.969 + User::Leave(KErrOverflow);
1.970 + }
1.971 + TUint32* ptr = reinterpret_cast<TUint32*>(surfacePtr);
1.972 +
1.973 + // Fill first line
1.974 + for (TInt xx3 = 0; xx3 < info.iSize.iWidth; xx3++)
1.975 + {
1.976 + ptr[xx3] = lines;
1.977 + }
1.978 +
1.979 + // Fill second line
1.980 + ptr = reinterpret_cast<TUint32*>(surfacePtr + info.iStride);
1.981 + for (TInt xx4 = 0; xx4 < info.iSize.iWidth; xx4++)
1.982 + {
1.983 + // Vertical line every 8 pixels across
1.984 + ptr[xx4] = (xx4 & 7) ? color : lines;
1.985 + }
1.986 + }
1.987 + linePtr += info.iStride;
1.988 +
1.989 + // Now copy that to the other lines
1.990 + for (TInt yy = 2; yy < info.iSize.iHeight; yy++)
1.991 + {
1.992 + linePtr += info.iStride;
1.993 + if (yy & 7)
1.994 + {
1.995 + // Copy second line
1.996 + Mem::Copy(linePtr, surfacePtr + info.iStride, info.iSize.iWidth * BytesPerPixelL(info.iPixelFormat));
1.997 + }
1.998 + else
1.999 + {
1.1000 + // Copy first line
1.1001 + Mem::Copy(linePtr, surfacePtr, info.iSize.iWidth * BytesPerPixelL(info.iPixelFormat));
1.1002 + }
1.1003 + }
1.1004 +
1.1005 + TInt err =iSurfaceUpdateSession.SubmitUpdate(KAllScreens, aSurface, 0, NULL);
1.1006 + if (err!=KErrNone)
1.1007 + LOG(("Error submitting update: 0x%X\n", err));
1.1008 +
1.1009 + CleanupStack::PopAndDestroy(/* chunk */);
1.1010 + }
1.1011 +
1.1012 +
1.1013 +/**
1.1014 +Fill the given surface with a pattern suitable for automated testing.
1.1015 +
1.1016 +@param aSurface The surface to be filled.
1.1017 +*/
1.1018 +void CSurfaceUtility::PatternFillSurfaceL(TSurfaceId& aSurface)
1.1019 + {
1.1020 + RSurfaceManager::TInfoBuf infoBuf;
1.1021 + RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
1.1022 +
1.1023 + User::LeaveIfError(iManager.SurfaceInfo(aSurface, infoBuf));
1.1024 +
1.1025 + // Fill the background
1.1026 + FillSurfaceL(aSurface, TRgb(0x00000000));
1.1027 +
1.1028 + TInt surfaceWidth = info.iSize.iWidth;
1.1029 + TInt surfaceHeight = info.iSize.iHeight;
1.1030 +
1.1031 + // Create the 4 rectangles in the corners
1.1032 + TPoint startPos(0,0);
1.1033 + TSize size(15,15);
1.1034 + TInt rectWidth = size.iWidth;
1.1035 + TInt rectHeight = size.iHeight;
1.1036 + // Top left
1.1037 + FillRectangleL(aSurface, startPos, size, TRgb(0x0000ff));
1.1038 +
1.1039 + // Top right
1.1040 + startPos.iX = surfaceWidth - rectWidth;
1.1041 + startPos.iY = 0;
1.1042 + FillRectangleL(aSurface, startPos, size, TRgb(0x00ff00));
1.1043 +
1.1044 + // Bottom left
1.1045 + startPos.iX = 0;
1.1046 + startPos.iY = surfaceHeight - rectHeight;
1.1047 + FillRectangleL(aSurface, startPos, size, TRgb(0x00ffff));
1.1048 +
1.1049 + // Bottom right
1.1050 + startPos.iX = surfaceWidth - rectWidth;
1.1051 + startPos.iY = surfaceHeight - rectHeight;
1.1052 + FillRectangleL(aSurface, startPos, size, TRgb(0xffffff));
1.1053 +
1.1054 + // Create the 4 side bars
1.1055 + startPos.iX = 0;
1.1056 + startPos.iY = 6;
1.1057 + size.iWidth = 5;
1.1058 + size.iHeight = surfaceHeight - 12;
1.1059 + // Left
1.1060 + FillRectangleL(aSurface, startPos, size, TRgb(0x808000));
1.1061 +
1.1062 + startPos.iX = surfaceWidth - size.iWidth;
1.1063 + startPos.iY = 6;
1.1064 + // Right
1.1065 + FillRectangleL(aSurface, startPos, size, TRgb(0xff00ff));
1.1066 +
1.1067 + startPos.iX = 6;
1.1068 + startPos.iY = surfaceHeight - size.iWidth;
1.1069 + size.iWidth = surfaceWidth - 12;
1.1070 + size.iHeight = 5;
1.1071 + // Top
1.1072 + FillRectangleL(aSurface, startPos, size, TRgb(0xaaaaaa));
1.1073 +
1.1074 + startPos.iX = 6;
1.1075 + startPos.iY = 0;
1.1076 + // Bottom
1.1077 + FillRectangleL(aSurface, startPos, size, TRgb(0x000080));
1.1078 + }
1.1079 +
1.1080 +
1.1081 +template <class TIntType> void
1.1082 +DdaLine(TUint aX1, TUint aY1,TUint aX2,TUint aY2, TUint aPixPerScan, TIntType* aBuffer, TIntType aColor)
1.1083 + {
1.1084 + TInt dx=aX2-aX1;
1.1085 + TInt dy=aY2-aY1;
1.1086 + TInt adx=dx,sdx=1;
1.1087 + if (adx<0)
1.1088 + { adx=-adx; sdx=-1; }
1.1089 + TInt ady=dy,sdy=aPixPerScan;
1.1090 + if (ady<0)
1.1091 + { ady=-ady; sdy=-aPixPerScan; }
1.1092 + //This is simplistic integert DDA.
1.1093 + //The vertical cases are handled by this 1/2 accumulator:
1.1094 + // If adx is zero then we step in sdy indefinitely
1.1095 + // If ady is zero then we step in sdx indefinitely
1.1096 + TInt accum=adx/2;
1.1097 +
1.1098 + TIntType* bufferend=aBuffer+aX2+aY2*aPixPerScan;
1.1099 + aBuffer+=aX1+aY1*aPixPerScan;
1.1100 + *aBuffer=aColor;
1.1101 + while (aBuffer!=bufferend)
1.1102 + {
1.1103 + if (accum>0)
1.1104 + {
1.1105 + accum-=ady;
1.1106 + aBuffer+=sdx;
1.1107 + }
1.1108 + else
1.1109 + {
1.1110 + accum+=adx;
1.1111 + aBuffer+=sdy;
1.1112 + }
1.1113 + *aBuffer=aColor;
1.1114 + }
1.1115 +
1.1116 +
1.1117 + }
1.1118 +template <class TIntType> void
1.1119 +FanFill(const TPoint& aInnerXY,TUint aPixPerScan, TIntType* aSurfacePtr, TIntType aLinesTL,
1.1120 + TIntType aLinesBR, TIntType aLinesTR, TIntType aLinesBL)
1.1121 + {
1.1122 +
1.1123 + DdaLine(aInnerXY.iX,0,aInnerXY.iX-aInnerXY.iX*180/1024,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesTR);
1.1124 + DdaLine(aInnerXY.iX,0,aInnerXY.iX-aInnerXY.iX*372/1024,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesTR);
1.1125 + DdaLine(aInnerXY.iX,0,aInnerXY.iX-aInnerXY.iX*591/1024,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesTR);
1.1126 + DdaLine(aInnerXY.iX,0,aInnerXY.iX-aInnerXY.iX*859/1024,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesTR);
1.1127 +
1.1128 + DdaLine(aInnerXY.iX,0,0,aInnerXY.iY*180/1024,aPixPerScan,aSurfacePtr,aLinesTR);
1.1129 + DdaLine(aInnerXY.iX,0,0,aInnerXY.iY*372/1024,aPixPerScan,aSurfacePtr,aLinesTR);
1.1130 + DdaLine(aInnerXY.iX,0,0,aInnerXY.iY*591/1024,aPixPerScan,aSurfacePtr,aLinesTR);
1.1131 + DdaLine(aInnerXY.iX,0,0,aInnerXY.iY*859/1024,aPixPerScan,aSurfacePtr,aLinesTR);
1.1132 +
1.1133 + DdaLine(0,aInnerXY.iY,aInnerXY.iX*180/1024,0,aPixPerScan,aSurfacePtr,aLinesBL);
1.1134 + DdaLine(0,aInnerXY.iY,aInnerXY.iX*372/1024,0,aPixPerScan,aSurfacePtr,aLinesBL);
1.1135 + DdaLine(0,aInnerXY.iY,aInnerXY.iX*591/1024,0,aPixPerScan,aSurfacePtr,aLinesBL);
1.1136 + DdaLine(0,aInnerXY.iY,aInnerXY.iX*859/1024,0,aPixPerScan,aSurfacePtr,aLinesBL);
1.1137 +
1.1138 + DdaLine(0,aInnerXY.iY,aInnerXY.iX,aInnerXY.iY-aInnerXY.iY*180/1024,aPixPerScan,aSurfacePtr,aLinesBL);
1.1139 + DdaLine(0,aInnerXY.iY,aInnerXY.iX,aInnerXY.iY-aInnerXY.iY*372/1024,aPixPerScan,aSurfacePtr,aLinesBL);
1.1140 + DdaLine(0,aInnerXY.iY,aInnerXY.iX,aInnerXY.iY-aInnerXY.iY*591/1024,aPixPerScan,aSurfacePtr,aLinesBL);
1.1141 + DdaLine(0,aInnerXY.iY,aInnerXY.iX,aInnerXY.iY-aInnerXY.iY*859/1024,aPixPerScan,aSurfacePtr,aLinesBL);
1.1142 +
1.1143 + DdaLine(0,0,aInnerXY.iX*180/1024,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesTL);
1.1144 + DdaLine(0,0,aInnerXY.iX*372/1024,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesTL);
1.1145 + DdaLine(0,0,aInnerXY.iX*591/1024,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesTL);
1.1146 + DdaLine(0,0,aInnerXY.iX*859/1024,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesTL);
1.1147 +
1.1148 + DdaLine(0,0,aInnerXY.iX,aInnerXY.iY*180/1024,aPixPerScan,aSurfacePtr,aLinesTL);
1.1149 + DdaLine(0,0,aInnerXY.iX,aInnerXY.iY*372/1024,aPixPerScan,aSurfacePtr,aLinesTL);
1.1150 + DdaLine(0,0,aInnerXY.iX,aInnerXY.iY*591/1024,aPixPerScan,aSurfacePtr,aLinesTL);
1.1151 + DdaLine(0,0,aInnerXY.iX,aInnerXY.iY*859/1024,aPixPerScan,aSurfacePtr,aLinesTL);
1.1152 +
1.1153 + DdaLine(0,aInnerXY.iY-aInnerXY.iY*180/1024,aInnerXY.iX,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesBR);
1.1154 + DdaLine(0,aInnerXY.iY-aInnerXY.iY*372/1024,aInnerXY.iX,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesBR);
1.1155 + DdaLine(0,aInnerXY.iY-aInnerXY.iY*591/1024,aInnerXY.iX,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesBR);
1.1156 + DdaLine(0,aInnerXY.iY-aInnerXY.iY*859/1024,aInnerXY.iX,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesBR);
1.1157 +
1.1158 + DdaLine(aInnerXY.iX-aInnerXY.iX*180/1024,0,aInnerXY.iX,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesBR);
1.1159 + DdaLine(aInnerXY.iX-aInnerXY.iX*372/1024,0,aInnerXY.iX,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesBR);
1.1160 + DdaLine(aInnerXY.iX-aInnerXY.iX*591/1024,0,aInnerXY.iX,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesBR);
1.1161 + DdaLine(aInnerXY.iX-aInnerXY.iX*859/1024,0,aInnerXY.iX,aInnerXY.iY,aPixPerScan,aSurfacePtr,aLinesBR);
1.1162 +
1.1163 + }
1.1164 +/**
1.1165 +Fill the given surface with a fan of lines over a solid color.
1.1166 +
1.1167 +Similar to FillSurfaceL(), but with a fan of lines overlayed.
1.1168 +One fan is drawn about the top-left, and second fan at bottom-right.
1.1169 +The fan contains 8 segments.
1.1170 +
1.1171 +@param aSurface The surface to be filled.
1.1172 +@param aColor The color to fill it with.
1.1173 +@param aLines The color of the grid lines.
1.1174 +*/
1.1175 +void CSurfaceUtility::FanFillSurfaceL(TSurfaceId& aSurface, const TRgb& aColor, const TRgb& aLinesTL, const TRgb& aLinesBR)
1.1176 + {
1.1177 + FillSurfaceL(aSurface,aColor);
1.1178 + RSurfaceManager::TInfoBuf infoBuf;
1.1179 + RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
1.1180 +
1.1181 + User::LeaveIfError(iManager.SurfaceInfo(aSurface, infoBuf));
1.1182 + TUint32 linesTL = 0;
1.1183 + TUint32 linesBR = 0;
1.1184 + TUint32 linesTR = 0;
1.1185 + TUint32 linesBL = 0;
1.1186 + TBool use16 = EFalse;
1.1187 + TRgb rgbLinesTR(0,0,0);
1.1188 + TRgb rgbLinesBL(255,255,255);
1.1189 +
1.1190 + switch (info.iPixelFormat)
1.1191 + {
1.1192 + case EUidPixelFormatXRGB_8888:
1.1193 + {
1.1194 + linesBR = aLinesBR.Color16MU();
1.1195 + linesTL = aLinesTL.Color16MU();
1.1196 + linesTR = rgbLinesTR.Color16MU();
1.1197 + linesBL = rgbLinesBL.Color16MU();
1.1198 +#ifdef ALPHA_FIX_24BIT
1.1199 + linesBR |= ((ALPHA_FIX_24BIT)&0xff)<<24;
1.1200 + linesTL |= ((ALPHA_FIX_24BIT)&0xff)<<24;
1.1201 + linesTR |= ((ALPHA_FIX_24BIT)&0xff)<<24;
1.1202 + linesBL |= ((ALPHA_FIX_24BIT)&0xff)<<24;
1.1203 +#endif
1.1204 + break;
1.1205 + }
1.1206 + case EUidPixelFormatARGB_8888:
1.1207 + {
1.1208 + linesBR = aLinesBR.Color16MA();
1.1209 + linesTL = aLinesTL.Color16MA();
1.1210 + linesTR = rgbLinesTR.Color16MA();
1.1211 + linesBL = rgbLinesBL.Color16MA();
1.1212 + break;
1.1213 + }
1.1214 + case EUidPixelFormatARGB_8888_PRE:
1.1215 + {
1.1216 + linesBR = aLinesBR.Color16MAP();
1.1217 + linesTL = aLinesTL.Color16MAP();
1.1218 + linesTR = rgbLinesTR.Color16MAP();
1.1219 + linesBL = rgbLinesBL.Color16MAP();
1.1220 + break;
1.1221 + }
1.1222 + case EUidPixelFormatXRGB_4444:
1.1223 + case EUidPixelFormatARGB_4444:
1.1224 + {
1.1225 + linesBR = aLinesBR.Color4K();
1.1226 + linesTL = aLinesTL.Color4K();
1.1227 + linesTR = rgbLinesTR.Color4K();
1.1228 + linesBL = rgbLinesBL.Color4K();
1.1229 + use16 = ETrue;
1.1230 + break;
1.1231 + }
1.1232 + case EUidPixelFormatRGB_565:
1.1233 + {
1.1234 + linesBR = aLinesBR.Color64K();
1.1235 + linesTL = aLinesTL.Color64K();
1.1236 + linesTR = rgbLinesTR.Color64K();
1.1237 + linesBL = rgbLinesBL.Color64K();
1.1238 + use16 = ETrue;
1.1239 + break;
1.1240 + }
1.1241 + default:
1.1242 + {
1.1243 + User::Leave(KErrNotSupported);
1.1244 + break;
1.1245 + }
1.1246 + }
1.1247 + if (info.iSize.iHeight<0 || info.iSize.iWidth<0 || info.iStride<0)
1.1248 + {
1.1249 + User::Leave(KErrCorrupt);
1.1250 + }
1.1251 + if (info.iSize.iHeight==0 || info.iSize.iWidth==0 || info.iStride==0)
1.1252 + {
1.1253 + User::Leave(KErrNotReady);
1.1254 + }
1.1255 + RChunk chunk;
1.1256 + User::LeaveIfError(iManager.MapSurface(aSurface, chunk));
1.1257 + CleanupClosePushL(chunk);
1.1258 +
1.1259 + TInt offsetToFirstBuffer;
1.1260 + User::LeaveIfError(iManager.GetBufferOffset(aSurface, 0, offsetToFirstBuffer));
1.1261 + TUint8* surfacePtr = chunk.Base() + offsetToFirstBuffer;
1.1262 + TPoint innerXY(info.iSize.iWidth-1,info.iSize.iHeight-1);
1.1263 + if (use16)
1.1264 + {
1.1265 + if ( info.iSize.iWidth*2>info.iStride)
1.1266 + {
1.1267 + User::Leave(KErrOverflow);
1.1268 + }
1.1269 + FanFill<TUint16>(innerXY,info.iStride/2,(TUint16*)surfacePtr,linesTL,linesBR,linesBL,linesTR);
1.1270 + }
1.1271 + else
1.1272 + {
1.1273 + if ( info.iSize.iWidth*4>info.iStride)
1.1274 + {
1.1275 + User::Leave(KErrOverflow);
1.1276 + }
1.1277 + FanFill<TUint>(innerXY,info.iStride/4,(TUint*)surfacePtr,linesTL,linesBR,linesBL,linesTR);
1.1278 + }
1.1279 +
1.1280 + iSurfaceUpdateSession.SubmitUpdate(KAllScreens, aSurface, 0, NULL);
1.1281 +
1.1282 + CleanupStack::PopAndDestroy(/* chunk */);
1.1283 + }
1.1284 +/**
1.1285 +Fill the given surface with vertical line at the given position
1.1286 +
1.1287 +Similar to FillSurfaceL(), but with a vertical line overlayed.
1.1288 +The position along the surface is given as a percentage from the left
1.1289 +
1.1290 +@param aSurface The surface to be filled.
1.1291 +@param aColor The color to fill it with.
1.1292 +@param aLine The color of the line.
1.1293 +@param aPosition Position of the vertical line given as a percentage across the surface from the left edge
1.1294 +*/
1.1295 +void CSurfaceUtility::LineFillSurfaceL(TSurfaceId& aSurface, const TRgb& aBackColor, const TRgb& aLineColor, TInt aPosition)
1.1296 + {
1.1297 + if (aPosition<0 || aPosition>100)
1.1298 + {
1.1299 + aPosition=0;
1.1300 + }
1.1301 + FillSurfaceL(aSurface,aBackColor);
1.1302 + RSurfaceManager::TInfoBuf infoBuf;
1.1303 + RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
1.1304 +
1.1305 + User::LeaveIfError(iManager.SurfaceInfo(aSurface, infoBuf));
1.1306 + TUint32 lineColor = 0;
1.1307 + TBool use16 = EFalse;
1.1308 +
1.1309 + switch (info.iPixelFormat)
1.1310 + {
1.1311 + case EUidPixelFormatXRGB_8888:
1.1312 + {
1.1313 + lineColor = aLineColor.Color16MU();
1.1314 +#ifdef ALPHA_FIX_24BIT
1.1315 + lineColor |= ((ALPHA_FIX_24BIT)&0xff)<<24;
1.1316 +#endif
1.1317 + break;
1.1318 + }
1.1319 + case EUidPixelFormatARGB_8888:
1.1320 + {
1.1321 + lineColor = aLineColor.Color16MA();
1.1322 + break;
1.1323 + }
1.1324 + case EUidPixelFormatARGB_8888_PRE:
1.1325 + {
1.1326 + lineColor = aLineColor.Color16MAP();
1.1327 + break;
1.1328 + }
1.1329 + case EUidPixelFormatXRGB_4444:
1.1330 + case EUidPixelFormatARGB_4444:
1.1331 + {
1.1332 + lineColor = aLineColor.Color4K();
1.1333 + use16 = ETrue;
1.1334 + break;
1.1335 + }
1.1336 + case EUidPixelFormatRGB_565:
1.1337 + {
1.1338 + lineColor = aLineColor.Color64K();
1.1339 + use16 = ETrue;
1.1340 + break;
1.1341 + }
1.1342 + default:
1.1343 + {
1.1344 + User::Leave(KErrNotSupported);
1.1345 + break;
1.1346 + }
1.1347 + }
1.1348 + RChunk chunk;
1.1349 + User::LeaveIfError(iManager.MapSurface(aSurface, chunk));
1.1350 +
1.1351 + TInt offsetToFirstBuffer;
1.1352 + User::LeaveIfError(iManager.GetBufferOffset(aSurface, 0, offsetToFirstBuffer));
1.1353 + TUint8* surfacePtr = chunk.Base() + offsetToFirstBuffer;
1.1354 + if (use16)
1.1355 + {
1.1356 + DdaLine<TUint16>((info.iSize.iWidth*aPosition)/100,0,(info.iSize.iWidth*aPosition)/100,
1.1357 + info.iSize.iHeight-1,info.iStride/2,(TUint16*)surfacePtr,lineColor);
1.1358 + }
1.1359 + else
1.1360 + {
1.1361 + DdaLine<TUint>((info.iSize.iWidth*aPosition)/100,0,(info.iSize.iWidth*aPosition)/100,
1.1362 + info.iSize.iHeight-1,info.iStride/4,(TUint*)surfacePtr,lineColor);
1.1363 + }
1.1364 +
1.1365 + chunk.Close();
1.1366 +
1.1367 + iSurfaceUpdateSession.SubmitUpdate(KAllScreens, aSurface, 0, NULL);
1.1368 + }
1.1369 +/**
1.1370 + * Generates a bitmap equivalent to the surface.
1.1371 + * Can reuse an existing bitmap or create a new bitmap.
1.1372 + * The existing bitmap must be an exact match (eg previously generated by this method)
1.1373 + **/
1.1374 +CFbsBitmap* CSurfaceUtility::EquivalentBitmapL(TSurfaceId& aSurface,CFbsBitmap* aCopyToMayBeNull)
1.1375 + {
1.1376 + RSurfaceManager::TInfoBuf infoBuf;
1.1377 + RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
1.1378 +
1.1379 + User::LeaveIfError(iManager.SurfaceInfo(aSurface, infoBuf));
1.1380 + TInt bytesPerPixel=0;
1.1381 + TDisplayMode bitmapMode = ENone;
1.1382 + switch (info.iPixelFormat)
1.1383 + {
1.1384 + case EUidPixelFormatXRGB_8888:
1.1385 + {
1.1386 + bitmapMode = EColor16MU;
1.1387 + bytesPerPixel = 4;
1.1388 + break;
1.1389 + }
1.1390 + case EUidPixelFormatARGB_8888:
1.1391 + {
1.1392 + bitmapMode=EColor16MA;
1.1393 + bytesPerPixel = 4;
1.1394 + break;
1.1395 + }
1.1396 + case EUidPixelFormatARGB_8888_PRE:
1.1397 + {
1.1398 + bitmapMode=EColor16MAP;
1.1399 + bytesPerPixel = 4;
1.1400 + break;
1.1401 + }
1.1402 + case EUidPixelFormatXRGB_4444:
1.1403 + case EUidPixelFormatARGB_4444:
1.1404 + {
1.1405 + bitmapMode=EColor4K;
1.1406 + bytesPerPixel = 2;
1.1407 + break;
1.1408 + }
1.1409 + case EUidPixelFormatRGB_565:
1.1410 + {
1.1411 + bitmapMode=EColor64K;
1.1412 + bytesPerPixel = 2;
1.1413 + break;
1.1414 + }
1.1415 + default:
1.1416 + {
1.1417 + User::Leave(KErrNotSupported);
1.1418 + break;
1.1419 + }
1.1420 + }
1.1421 + CFbsBitmap* retVal=NULL;
1.1422 + if (aCopyToMayBeNull)
1.1423 + {
1.1424 + retVal=aCopyToMayBeNull;
1.1425 + if (retVal->SizeInPixels()!=info.iSize)
1.1426 + User::Leave(KErrCorrupt);
1.1427 + if (retVal->DisplayMode()!=bitmapMode)
1.1428 + User::Leave(KErrCorrupt);
1.1429 + }
1.1430 + else
1.1431 + {
1.1432 + retVal=new CFbsBitmap;
1.1433 + CleanupStack::PushL(retVal);
1.1434 + User::LeaveIfError(retVal->Create(info.iSize,bitmapMode));
1.1435 + }
1.1436 + RChunk chunk;
1.1437 + CleanupClosePushL(chunk);
1.1438 + User::LeaveIfError(iManager.MapSurface(aSurface, chunk));
1.1439 + TInt offsetToFirstBuffer;
1.1440 + User::LeaveIfError(iManager.GetBufferOffset(aSurface, 0, offsetToFirstBuffer));
1.1441 + TUint8* surfacePtr = chunk.Base() + offsetToFirstBuffer;
1.1442 + TUint8* bitmapPtr = (TUint8*)retVal->DataAddress();
1.1443 + TInt copyBytes=info.iSize.iWidth*bytesPerPixel;
1.1444 + for (TInt y=0;y<info.iSize.iHeight;y++)
1.1445 + {
1.1446 + Mem::Copy(bitmapPtr,surfacePtr,copyBytes);
1.1447 + surfacePtr+=info.iStride;
1.1448 + bitmapPtr+=retVal->DataStride();
1.1449 + }
1.1450 + CleanupStack::PopAndDestroy(&chunk);
1.1451 + if (!aCopyToMayBeNull)
1.1452 + CleanupStack::Pop(retVal);
1.1453 + return retVal;
1.1454 + }
1.1455 +
1.1456 +/**
1.1457 +Destroy a surface.
1.1458 +
1.1459 +As well as destroying the surface, it is removed from the set held for
1.1460 +destruction during tear down.
1.1461 +
1.1462 +@param aSurface The surface to be destroyed.
1.1463 +*/
1.1464 +void CSurfaceUtility::DestroySurface(TSurfaceId& aSurface)
1.1465 + {
1.1466 + TInt index = iSurfaces.Find(aSurface);
1.1467 +
1.1468 + if (index != KErrNotFound)
1.1469 + {
1.1470 + iSurfaces.Remove(index);
1.1471 + }
1.1472 +
1.1473 + TInt err = iManager.CloseSurface(aSurface);
1.1474 + if (err!=KErrNone)
1.1475 + LOG(("Error closing surfaces: 0x%X\n", err));
1.1476 + }
1.1477 +
1.1478 +
1.1479 +/**
1.1480 +Submit an update to a surface to the update server.
1.1481 +
1.1482 +@param aScreenNumber The screen to be updated where the surface is shown.
1.1483 +@param aSurface The surface which has been updated.
1.1484 +@param aRegion The area of the surface affected, or NULL for all of it.*/
1.1485 +void CSurfaceUtility::SubmitUpdate(TInt /* aScreenNumber */, const TSurfaceId& aSurface, const TRegion* aRegion,TInt aBufferNumber)
1.1486 + {
1.1487 + TInt err =iSurfaceUpdateSession.SubmitUpdate(KAllScreens, aSurface, aBufferNumber, aRegion);
1.1488 + if (err!=KErrNone)
1.1489 + LOG(("Error submitting update: 0x%X\n", err));
1.1490 + }
1.1491 +
1.1492 +/**
1.1493 +Map and submit an update to a surface to the update server.
1.1494 +
1.1495 +@param aChunk The chunk of memory to be mapped
1.1496 +@param aScreenNumber The screen to be updated where the surface is shown.
1.1497 +@param aSurface The surface which has been updated.
1.1498 +@param aRegion The area of the surface affected, or NULL for all of it.*/
1.1499 +void CSurfaceUtility::MapAndSubmitUpdateL(RChunk& aChunk,
1.1500 + TInt /* aScreenNumber */,
1.1501 + const TSurfaceId& aSurface,
1.1502 + const TRegion* aRegion)
1.1503 + {
1.1504 + User::LeaveIfError(iManager.MapSurface(aSurface, aChunk));
1.1505 + aChunk.Close();
1.1506 + TInt err =iSurfaceUpdateSession.SubmitUpdate(KAllScreens, aSurface, 0, aRegion);
1.1507 + if (err!=KErrNone)
1.1508 + LOG(("Error submitting update: 0x%X\n", err));
1.1509 + }
1.1510 +
1.1511 +void CSurfaceUtility::MapSurfaceL(const TSurfaceId& aSurface, RChunk& aChunk)
1.1512 + {
1.1513 + User::LeaveIfError(iManager.MapSurface(aSurface, aChunk));
1.1514 + }
1.1515 +
1.1516 +void CSurfaceUtility::CopyBitmapToSurfaceL(TSurfaceId& aSurface, const CFbsBitmap& aBitmap)
1.1517 + {
1.1518 + TSize size = SurfaceSize(aSurface);
1.1519 +
1.1520 + TDisplayMode bmpFormat = aBitmap.DisplayMode();
1.1521 + TInt stride = size.iWidth * 4; // Default to four bytes per pixel
1.1522 +
1.1523 + RChunk chunk;
1.1524 + User::LeaveIfError(iManager.MapSurface(aSurface, chunk));
1.1525 + CleanupClosePushL(chunk);
1.1526 +
1.1527 + TInt offsetToFirstBuffer;
1.1528 + User::LeaveIfError(iManager.GetBufferOffset(aSurface, 0, offsetToFirstBuffer));
1.1529 +
1.1530 + // Copy the data from the bitmap into the surface.
1.1531 + TPoint start;
1.1532 + TUint8 *pSurfStart = chunk.Base() + offsetToFirstBuffer;
1.1533 + for (start.iY = 0; start.iY < size.iHeight; start.iY++)
1.1534 + {
1.1535 + // Set up a descriptor for the current line in the surface and get pixels.
1.1536 + TPtr8 ptr(pSurfStart + start.iY * stride, stride);
1.1537 + aBitmap.GetScanLine(ptr, start, size.iWidth, bmpFormat);
1.1538 + }
1.1539 +
1.1540 + TInt err =iSurfaceUpdateSession.SubmitUpdate(KAllScreens, aSurface, 0, NULL);
1.1541 + if (err!=KErrNone)
1.1542 + {
1.1543 + LOG(("Error submitting update: 0x%X\n", err));
1.1544 + }
1.1545 +
1.1546 + CleanupStack::PopAndDestroy(/* chunk */);
1.1547 + }