--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/htiui/HtiServicePlugins/HtiScreenshotServicePlugin/src/HtiScreenshotServicePlugin.cpp Tue Feb 02 00:17:27 2010 +0200
@@ -0,0 +1,2274 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: SysInfoPlugin implementation
+*
+*/
+
+
+// INCLUDE FILES
+#include "HtiScreenshotServicePlugin.h"
+#include <HtiDispatcherInterface.h>
+#include <HTILogging.h>
+
+#include <ImageConversion.h>
+#include <EZCompressor.h>
+#include <hal.h>
+
+// CONSTANTS
+const static TUid KScreenshotServiceUid = {0x1020DEC3};
+
+enum TScreenCommands
+ {
+ // Normal screencapture
+ ECmdScreen = 0x01,
+ ECmdScreenRegion = 0x02,
+ ECmdScreenZip = 0x03,
+ ECmdScreenRegionZip = 0x04,
+
+ // Text recognition
+ ECmdTextRcg = 0x10,
+ ECmdTextRcg_u = 0x11,
+
+ // Text bitmap
+ ECmdTextBitmap = 0x12,
+ ECmdTextBitmap_u = 0x13,
+
+ // Screencapture in series
+ ECmdScreenSeries = 0x21,
+ ECmdScreenRegionSeries = 0x22,
+ ECmdScreenZipSeries = 0x23,
+ ECmdScreenRegionZipSeries = 0x24,
+
+ // Selects the screen to use
+ ECmdSelectScreen = 0x30,
+
+ // Gets the current screen size and orientation
+ ECmdScreenMode = 0x3A,
+
+ // Screencapture on updated part of screen only
+ ECmdDeltaCaptureMask = 0x80,
+ ECmdDeltaScreen = 0x81,
+ ECmdDeltaScreenRegion = 0x82,
+ ECmdDeltaScreenZip = 0x83,
+ ECmdDeltaScreenRegionZip = 0x84,
+ ECmdDeltaScreenReset = 0x85
+ //ECmdDeltaScreenSeries = 0xA1,
+ //ECmdDeltaScreenRegionSeries = 0xA2,
+ //ECmdDeltaScreenZipSeries = 0xA3,
+ //ECmdDeltaScreenRegionZipSeries = 0xA4
+ };
+
+enum TScreenResponse
+ {
+ ERspOk = 0xF0,
+ ERspNotFound = 0xF1
+ };
+
+enum THtiFontAttributes
+ {
+ EHtiFontAttBold = 0x01,
+ EHtiFontAttItalic = 0x02,
+ EHtiFontAttNotAA = 0x04,
+ EHtiFontAttPrintPositionFlag = 0x08,
+ EHtiFontAttPrintPositionValue = 0x10
+ };
+
+const static TInt KHtiFontAttSuperscriptValue = 0;
+const static TInt KHtiFontAttSubscriptValue = 1;
+
+//1 byte for cmd and 2*4 for 4 coordinates
+const static TInt KMinScreenRegionCmdLength = 9;
+const static TInt KScreenDisplayOffset = 1;
+const static TInt KScreenMIMEOffset = KScreenDisplayOffset + 1;
+const static TInt KRegionDisplayOffset = KMinScreenRegionCmdLength;
+const static TInt KRegionMIMEOffset = KRegionDisplayOffset + 1;
+
+
+const static TInt KSeriesDurationOffset = 1;
+const static TInt KSeriesIntervalOffset = KSeriesDurationOffset + 4;
+const static TInt KSeriesDisplayOffset = KSeriesIntervalOffset + 4;
+const static TInt KSeriesMIMEOffset = KSeriesDisplayOffset + 1;
+const static TInt KMinSeriesCmdLength = KSeriesMIMEOffset;
+
+const static TInt KRegionSeriesTlX = KSeriesDisplayOffset + 1;
+const static TInt KRegionSeriesTlY = KRegionSeriesTlX + 2;
+const static TInt KRegionSeriesBlX = KRegionSeriesTlY + 2;
+const static TInt KRegionSeriesBlY = KRegionSeriesBlX + 2;
+const static TInt KRegionSeriesMIMEOffset = KRegionSeriesBlY + 2;
+const static TInt KMinRegionSeriesCmdLength = KRegionSeriesMIMEOffset;
+
+const static TInt KDeltaResetCmdLength = 1;
+const static TInt KScreenModeCmdLength = 1;
+
+const static TInt KScreenNrOffset = 1;
+const static TInt KSelectScreenCmdLength = 2;
+
+_LIT( KSeriesShotPath, "c:\\Hti\\SeriesShot\\" );
+
+//errors' descriptions
+_LIT8( KErrDescrInvalid, "invalid arguments" );
+_LIT8( KErrDescrInvalidMode, "invalid color mode" );
+_LIT8( KErrDescrRegiontEmpty, "region is empty" );
+_LIT8( KErrDescrRegionNotNormailized, "region is not normalized" );
+_LIT8( KErrDescrRegionOutOfScreen, "region is out of screen" );
+_LIT8( KErrDescrUnknownCommand, "unknown command" );
+_LIT8( KErrDescrFailedConvert, "failed to convert to image format" );
+_LIT8( KErrDescrFailedCompress, "failed to compress" );
+_LIT8( KErrDescrMIMENotSupported, "MIME type not supported" );
+_LIT8( KErrDescrScreenNotSupported, "screen not supported" );
+
+_LIT( KScreenshotPanic, "Screenshot plug-in invalid state" );
+
+//_LIT(KS60Sans, "Series 60 Sans");
+//_LIT(KS60SansTitleBold, "Series 60 Sans TitleSmBd");
+
+//const TInt KFonHeighMin = 110;
+//const TInt KFonHeighMax = 190;
+/*
+// ----------------------------------------------------------------------------
+void CHtiScreenshotServicePlugin::InitFontCache()
+ {
+ //temporary
+ //just put harcoded data
+ //should be either external file or auto-defined based on logical fonts
+ //or some test app
+ TFontSpec fs;
+ fs.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
+ //primary font
+ fs.iTypeface.iName = KS60Sans;
+ fs.iHeight = 161;
+ fs.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
+ iFontCache.Append(fs);
+
+ fs.iFontStyle.SetStrokeWeight(EStrokeWeightNormal);
+
+ //Series 60 Sans TitleSmBd, 183
+ fs.iTypeface.iName = KS60SansTitleBold;
+ fs.iHeight = 183;
+ iFontCache.Append(fs);
+
+ //Series 60 Sans TitleSmBd, 172
+ fs.iTypeface.iName = KS60SansTitleBold;
+ fs.iHeight = 172;
+ iFontCache.Append(fs);
+
+ //Series 60 Sans, 122
+ fs.iTypeface.iName = KS60Sans;
+ fs.iHeight = 122;
+ iFontCache.Append(fs);
+ //Series 60 Sans, 116
+ fs.iTypeface.iName = KS60Sans;
+ fs.iHeight = 116;
+ iFontCache.Append(fs);
+
+ //Series 60 Sans TitleSmBd, 138
+ fs.iTypeface.iName = KS60SansTitleBold;
+ fs.iHeight = 138;
+ iFontCache.Append(fs);
+ }
+*/
+
+// ----------------------------------------------------------------------------
+TInt ImageDifferenceL( CFbsBitmap* aImage1, CFbsBitmap* aImage2,
+ CFbsBitmap* &aResult, TRect &aRect )
+ {
+ HTI_LOG_TEXT( "ImageDifferenceL()" );
+
+ // By default return coordinates of the full image
+ aRect = TRect( 0, 0, aImage2->SizeInPixels().iWidth,
+ aImage2->SizeInPixels().iHeight );
+
+//1. check that aImage1 and aImage2 are valid and can be compared
+ if ( aImage1 == NULL || aImage2 == NULL )
+ {
+ HTI_LOG_TEXT( "return KErrArgument" );
+ return KErrArgument;
+ }
+
+ if ( aImage1->SizeInPixels() != aImage2->SizeInPixels() )
+ {
+ HTI_LOG_TEXT( "return KErrGeneral (size)" );
+ return KErrGeneral;
+ }
+
+ if ( aImage1->DisplayMode() != aImage2->DisplayMode() )
+ {
+ HTI_LOG_TEXT( "return KErrGeneral (displaymode)" );
+ return KErrGeneral;
+ }
+
+
+//2. iterate through images from each border and compare to findout outline for diff region
+ TSize orgSize = aImage1->SizeInPixels();
+
+ TBitmapUtil srcBmpIterator1( aImage1 );
+ TBitmapUtil srcBmpIterator2( aImage2 );
+
+ srcBmpIterator1.Begin( TPoint( 0, 0 ) );
+ srcBmpIterator2.Begin( TPoint( 0, 0 ), srcBmpIterator1 );
+
+ TRect diffOutline = TRect( -1, -1, -1, -1 );
+
+ //2.1 top border iteration
+ TPoint c( 0,0 );
+ for ( ; c.iY < orgSize.iHeight && diffOutline.iTl.iY == -1; ++c.iY )
+ {
+ c.iX = 0;
+ srcBmpIterator1.SetPos( c );
+ srcBmpIterator2.SetPos( c );
+ for ( ; c.iX < orgSize.iWidth && diffOutline.iTl.iY == -1; ++c.iX )
+ {
+ if ( srcBmpIterator1.GetPixel() != srcBmpIterator2.GetPixel() )
+ {
+ diffOutline.iTl.iY = c.iY;
+ }
+
+ srcBmpIterator1.IncXPos();
+ srcBmpIterator2.IncXPos();
+ }
+ }
+
+ //2.2 bottom iteration
+ c.SetXY( 0, orgSize.iHeight - 1 );
+ for ( ; c.iY >= diffOutline.iTl.iY && diffOutline.iBr.iY == -1; --c.iY )
+ {
+ c.iX = 0;
+ srcBmpIterator1.SetPos( c );
+ srcBmpIterator2.SetPos( c );
+ for (; c.iX < orgSize.iWidth && diffOutline.iBr.iY == -1; ++c.iX )
+ {
+ if ( srcBmpIterator1.GetPixel() != srcBmpIterator2.GetPixel() )
+ {
+ diffOutline.iBr.iY = c.iY;
+ }
+
+ srcBmpIterator1.IncXPos();
+ srcBmpIterator2.IncXPos();
+ }
+ }
+
+ //2.3 left, goes in vertical lines
+ c.SetXY( 0, diffOutline.iTl.iY );
+ for ( ; c.iX < orgSize.iWidth && diffOutline.iTl.iX == -1; ++c.iX )
+ {
+ c.iY = diffOutline.iTl.iY;
+ srcBmpIterator1.SetPos( c );
+ srcBmpIterator2.SetPos( c );
+ for ( ; c.iY <= diffOutline.iBr.iY && diffOutline.iTl.iX == -1; ++c.iY )
+
+ {
+ if ( srcBmpIterator1.GetPixel() != srcBmpIterator2.GetPixel() )
+ {
+ diffOutline.iTl.iX = c.iX;
+ }
+
+ srcBmpIterator1.IncYPos();
+ srcBmpIterator2.IncYPos();
+ }
+ }
+ //2.4 right, goes in vertical lines
+ c.SetXY( orgSize.iWidth - 1, diffOutline.iTl.iY );
+ for ( ; c.iX >= diffOutline.iTl.iX && diffOutline.iBr.iX == -1; --c.iX )
+ {
+ c.iY = diffOutline.iTl.iY;
+ srcBmpIterator1.SetPos( c );
+ srcBmpIterator2.SetPos( c );
+ for ( ; c.iY <= diffOutline.iBr.iY && diffOutline.iBr.iX == -1; ++c.iY )
+
+ {
+ if ( srcBmpIterator1.GetPixel() != srcBmpIterator2.GetPixel() )
+ {
+ diffOutline.iBr.iX = c.iX;
+ }
+
+ srcBmpIterator1.IncYPos();
+ srcBmpIterator2.IncYPos();
+ }
+ }
+ srcBmpIterator2.End();
+ srcBmpIterator1.End();
+
+ //3. if there is some diff create CFbsBitmap in aResult and copy outlined image from aImage2
+ if ( diffOutline.iTl.iX == -1 &&
+ diffOutline.iTl.iY == -1 &&
+ diffOutline.iBr.iX == -1 &&
+ diffOutline.iBr.iY == -1 )
+ {
+ // No difference found
+ aRect = TRect( 0, 0, 0, 0 );
+ HTI_LOG_TEXT( "return KErrNotFound" );
+ return KErrNotFound;
+ }
+
+ aRect = diffOutline;
+
+ HTI_LOG_FORMAT( "Tlx - %d", aRect.iTl.iX );
+ HTI_LOG_FORMAT( "Tly - %d", aRect.iTl.iY );
+ HTI_LOG_FORMAT( "Bty - %d", aRect.iBr.iX );
+ HTI_LOG_FORMAT( "Bry - %d", aRect.iBr.iY );
+
+ // The bottom right co-ordinate is not included in the rectange
+ // (see TRect documentation) so we need to stretch the rectange
+ // for BitBlt to get the correct sized image.
+
+ TRect captureRect( diffOutline.iTl.iX, diffOutline.iTl.iY,
+ diffOutline.iBr.iX + 1, diffOutline.iBr.iY + 1 );
+
+ aResult = new (ELeave) CFbsBitmap();
+ User::LeaveIfError( aResult->Create( captureRect.Size(), aImage2->DisplayMode() ) );
+ CleanupStack::PushL( aResult );
+
+ CFbsBitmapDevice* bmpDevice = CFbsBitmapDevice::NewL( aResult );
+ CleanupStack::PushL( bmpDevice );
+
+ CFbsBitGc* bmpCtx;
+ bmpDevice->CreateContext( bmpCtx );
+ bmpCtx->BitBlt( TPoint( 0, 0 ), aImage2, captureRect );
+
+ delete bmpCtx;
+ bmpCtx = NULL;
+
+ CleanupStack::PopAndDestroy(); // bmpDevice
+ CleanupStack::Pop(); // aResult
+
+ HTI_LOG_TEXT( "return KErrNone" );
+ return KErrNone;
+ }
+
+// ----------------------------------------------------------------------------
+CICLHandler::CICLHandler( CImageEncoder* aService, MICLObserver* anObserver ):
+ CActive( EPriorityStandard ),
+ iObserver( anObserver ),
+ iService( aService )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+// ----------------------------------------------------------------------------
+CICLHandler::~CICLHandler()
+ {
+ Cancel();
+ }
+
+// ----------------------------------------------------------------------------
+void CICLHandler::Start()
+ {
+ SetActive();
+ }
+
+// ----------------------------------------------------------------------------
+void CICLHandler::RunL()
+ {
+ iObserver->ICLComplete( iStatus.Int() );
+ }
+
+// ----------------------------------------------------------------------------
+void CICLHandler::DoCancel()
+ {
+ iService->Cancel();
+ }
+
+/*
+// ----------------------------------------------------------------------------
+TInt CICLHandler::RunError(TInt aError)
+ {
+
+ }
+*/
+
+// ----------------------------------------------------------------------------
+// Create instance of concrete ECOM interface implementation
+CHtiScreenshotServicePlugin* CHtiScreenshotServicePlugin::NewL()
+ {
+ CHtiScreenshotServicePlugin* self = new (ELeave) CHtiScreenshotServicePlugin;
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// Constructor
+CHtiScreenshotServicePlugin::CHtiScreenshotServicePlugin():
+ iScreen( NULL ),
+ iEncodedBitmap( NULL ),
+ iScreenDevice( NULL ),
+ iBitmapEncoder( NULL ),
+ iICLHandler( NULL ),
+ iCompress( EFalse ),
+ iDeltaCapture( EFalse ),
+ iPreviousBitmap( NULL )
+ {
+ }
+
+// ----------------------------------------------------------------------------
+CHtiScreenshotServicePlugin::~CHtiScreenshotServicePlugin()
+ {
+ HTI_LOG_FUNC_IN( "~CHtiScreenshotServicePlugin" );
+
+ iFontCache.Close();
+
+ delete iScreen;
+ delete iEncodedBitmap;
+
+ delete iICLHandler;
+ delete iBitmapEncoder;
+
+ delete iScreenDevice;
+
+ delete iSeriesShot;
+
+ if ( iPreviousBitmap )
+ delete iPreviousBitmap;
+
+ iWs.Close();
+ HTI_LOG_FUNC_OUT( "~CHtiScreenshotServicePlugin" );
+ }
+
+// ----------------------------------------------------------------------------
+// Second phase construction.
+void CHtiScreenshotServicePlugin::ConstructL()
+ {
+ HTI_LOG_FUNC_IN( "CHtiScreenshotServicePlugin::ConstructL" );
+ User::LeaveIfError( iWs.Connect() );
+
+ iScreenDevice = new ( ELeave ) CWsScreenDevice( iWs );
+ User::LeaveIfError( iScreenDevice->Construct() );
+
+ //InitFontCache();
+
+ iSeriesShot = CSeriesShot::NewL( this );
+
+ iPreviousBitmap = new ( ELeave ) CFbsBitmap;
+
+ //SelectEncoder( KImageTypeBMPUid );
+ HTI_LOG_FUNC_OUT( "CHtiScreenshotServicePlugin::ConstructL" );
+ }
+
+// ----------------------------------------------------------------------------
+TBool CHtiScreenshotServicePlugin::IsBusy()
+ {
+ if ( iICLHandler )
+ {
+ return iICLHandler->IsActive();
+ }
+
+ if ( iSeriesShot->IsOngoing() )
+ {
+ return ETrue;
+ }
+
+ return iEncodedBitmap != NULL;
+ }
+
+// ----------------------------------------------------------------------------
+inline TInt CHtiScreenshotServicePlugin::ParseInt16( const TUint8* aStart )
+ {
+ return aStart[0] + (aStart[1]<<8);
+ }
+
+// ----------------------------------------------------------------------------
+inline TInt CHtiScreenshotServicePlugin::ParseInt32( const TUint8* aStart )
+ {
+ return aStart[0] + (aStart[1]<<8) + (aStart[2]<<16) + (aStart[3]<<24);
+ }
+
+// ----------------------------------------------------------------------------
+void CHtiScreenshotServicePlugin::SendTextRecgReplyL(
+ const TBool aResult,
+ const TRect& aLocation,
+ const TInt aFontIndex)
+ {
+ HTI_LOG_FUNC_IN( "SendTextRecgReplyL" );
+ HBufC8* sendMsg = HBufC8::NewL( 10 );
+ CleanupStack::PushL( sendMsg );
+ if ( aResult )
+ {
+ sendMsg->Des().Append( ERspOk );
+ TUint16 co = aLocation.iTl.iX;
+ sendMsg->Des().Append( (TUint8*)(&co), 2 );
+ co = aLocation.iTl.iY;
+ sendMsg->Des().Append( (TUint8*)(&co), 2 );
+ co = aLocation.iBr.iX;
+ sendMsg->Des().Append( (TUint8*)(&co), 2 );
+ co = aLocation.iBr.iY;
+ sendMsg->Des().Append( (TUint8*)(&co), 2 );
+ sendMsg->Des().Append( (TUint8)aFontIndex );
+ }
+ else
+ {
+ sendMsg->Des().Append( ERspNotFound );
+ sendMsg->Des().AppendFill( 0, 5 );
+ }
+
+ User::LeaveIfError( iDispatcher->DispatchOutgoingMessage(
+ sendMsg,
+ KScreenshotServiceUid) );
+
+ CleanupStack::Pop();
+ HTI_LOG_FUNC_OUT( "SendTextRecgReplyL" );
+ }
+
+// ----------------------------------------------------------------------------
+void CHtiScreenshotServicePlugin::CopyUnicode( TDes & aTo, const TDesC8& aFrom )
+{
+ HTI_LOG_FUNC_IN( "CHtiScreenshotServicePlugin::CopyUnicode" );
+ //aTo.Copy( reinterpret_cast<const TUint16*>(aFrom.Ptr()), aFrom.Length() );
+ TInt len = aFrom.Length()>>1;
+ aTo.SetLength( len );
+ for ( TInt i = 0; i < len; ++i )
+ {
+ aTo[i] = (TUint16)aFrom[i<<1] + (((TUint16)aFrom[(i<<1)+1])<<8);
+ }
+ HTI_LOG_FUNC_OUT( "CHtiScreenshotServicePlugin::CopyUnicode" );
+}
+
+// ----------------------------------------------------------------------------
+TInt CHtiScreenshotServicePlugin::ParseString( const TDesC8& aRequest,
+ TInt anOffset,
+ TBool aUnicode,
+ TDes& aResult)
+ {
+ HTI_LOG_FUNC_IN( "CHtiScreenshotServicePlugin::ParseString" );
+ //validate parameters
+ //if offset outside the string return empty string
+ if ( anOffset >= aRequest.Size() )
+ {
+ return anOffset;
+ }
+
+ TInt len = aRequest[ anOffset ];
+ HTI_LOG_FORMAT( "len %d", len );
+
+ if ( len> aResult.MaxLength() )
+ {
+ return KErrBadDescriptor;
+ }
+
+ TInt nextOffset = ( aUnicode ? len * 2 : len ) + anOffset + 1;
+ HTI_LOG_FORMAT( "nextOffset %d", nextOffset );
+ HTI_LOG_FORMAT( "reqSize %d", aRequest.Size() );
+ if ( nextOffset > aRequest.Size() )
+ {
+ return KErrArgument;
+ }
+
+ if ( aUnicode )
+ {
+ //const TUint8* ptr = aRequest.Mid( anOffset + 1, len * 2 ).Ptr();
+ //aResult.Copy( (const TUint16*)ptr, len );
+ CopyUnicode( aResult, aRequest.Mid( anOffset + 1, len * 2 ) );
+ }
+ else
+ {
+ aResult.Copy( aRequest.Mid( anOffset + 1, len ) );
+ }
+
+ HTI_LOG_FUNC_OUT( "CHtiScreenshotServicePlugin::ParseString" );
+ return nextOffset;
+ }
+
+// ----------------------------------------------------------------------------
+TInt CHtiScreenshotServicePlugin::ParseFontSpec( const TDesC8& aRequest,
+ TInt anOffset,
+ TBool aUnicode,
+ TFontSpec& aResult)
+ {
+ if ( anOffset >= aRequest.Size() )
+ {
+ return KErrArgument;
+ }
+
+ //get font name
+ TPtr tn = aResult.iTypeface.iName.Des();
+ TInt offset = ParseString( aRequest,
+ anOffset,
+ aUnicode,
+ tn );
+
+ if ( offset > anOffset )
+ {
+ HTI_LOG_DES(aResult.iTypeface.iName);
+ //check that we have valid descr
+ if ( offset + 2 <= aRequest.Size() )
+ {
+ aResult.iHeight = ParseInt16( aRequest.Ptr() + offset );
+ HTI_LOG_FORMAT( "font height %d", aResult.iHeight );
+ //check style byte
+ TUint8 style = aRequest[ offset + 2 ];
+ HTI_LOG_FORMAT( "style %d", style );
+
+ //stroke bit
+ if ( style & EHtiFontAttBold )
+ {
+ aResult.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
+ }
+ else
+ {
+ aResult.iFontStyle.SetStrokeWeight(EStrokeWeightNormal);
+ }
+ //posture
+ if ( style & EHtiFontAttItalic )
+ {
+ aResult.iFontStyle.SetPosture(EPostureItalic);
+ }
+ else
+ {
+ aResult.iFontStyle.SetPosture(EPostureUpright);
+ }
+ //bitmap glyph type
+ if ( style & EHtiFontAttNotAA )
+ {
+ aResult.iFontStyle.SetBitmapType( EMonochromeGlyphBitmap );
+ }
+ else
+ {
+ aResult.iFontStyle.SetBitmapType( EAntiAliasedGlyphBitmap );
+ }
+ //print position
+ if ( style & EHtiFontAttPrintPositionFlag )
+ {
+ TInt printPos = style & EHtiFontAttPrintPositionValue;
+ if ( printPos == KHtiFontAttSuperscriptValue )
+ {
+ aResult.iFontStyle.SetPrintPosition( EPrintPosSuperscript );
+ }
+ else if ( printPos == KHtiFontAttSubscriptValue )
+ {
+ aResult.iFontStyle.SetPrintPosition( EPrintPosSubscript );
+ }
+ }
+ else
+ {
+ aResult.iFontStyle.SetPrintPosition( EPrintPosNormal );
+ }
+ return offset + 3;
+ }
+ else
+ {
+ return KErrArgument;
+ }
+ }
+ else
+ {
+ return offset<0?offset:KErrArgument;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+void CHtiScreenshotServicePlugin::ProcessTextRcgMessageL(
+ const TDesC8& aMessage)
+ {
+ HTI_LOG_FUNC_IN( "CHtiScreenshotServicePlugin::ProcessTextRcgMessageL" );
+ TBool unicode = aMessage[0] & 0x1;
+
+ TBuf<0xFF> text;
+
+ TInt offset = ParseString(aMessage, 1, unicode, text);
+
+ HTI_LOG_FORMAT( "offset %d ", offset );
+ if ( offset > 1 )
+ {
+ HTI_LOG_DES(text);
+
+ if ( offset + 1 < aMessage.Size() )
+ {
+ TInt numOfFonts = aMessage[ offset ];
+ HTI_LOG_FORMAT( "num of fonts %d", numOfFonts );
+ iFontCache.Reset();
+ TInt nextOffset = offset + 1;
+ for ( TInt i = 0; i < numOfFonts; ++i )
+ {
+ TFontSpec fontSpec;
+ nextOffset = ParseFontSpec(aMessage,
+ nextOffset,
+ unicode,
+ fontSpec);
+ if ( nextOffset < 0 )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ nextOffset,
+ KErrDescrInvalid,
+ KScreenshotServiceUid);
+ return;
+ }
+ else
+ {
+ iFontCache.Append( fontSpec );
+ }
+ }
+
+ //parameters parsing END
+ //get screenshot
+ TRect empty;
+ CreateBitmapL( empty, ENone );
+
+ //call text rcg routines
+ TInt fontIndex;
+ TRect resultRect;
+
+ //recognize text using fonts from iFontCache
+ TBool result = RecognizeTextL( text, resultRect, fontIndex );
+
+ SendTextRecgReplyL( result, resultRect, fontIndex );
+
+ delete iScreen;
+ iScreen = NULL;
+ }
+ else
+ {
+ //no fonts data
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalid,
+ KScreenshotServiceUid);
+
+ }
+ }
+ else if ( offset == 1 )
+ {
+ //empty text
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalid,
+ KScreenshotServiceUid);
+ }
+ else
+ {
+ //error
+ iDispatcher->DispatchOutgoingErrorMessage(
+ offset,
+ KErrDescrInvalid,
+ KScreenshotServiceUid);
+ }
+ HTI_LOG_FUNC_OUT( "CHtiScreenshotServicePlugin::ProcessTextRcgMessageL" );
+ }
+
+// ----------------------------------------------------------------------------
+void CHtiScreenshotServicePlugin::ProcessTextBitmapMessageL(
+ const TDesC8& aMessage)
+ {
+ HTI_LOG_FUNC_IN( "CHtiScreenshotServicePlugin::ProcessTextBitmapMessageL" );
+ TBool unicode = aMessage[0] & 0x1;
+
+ TDisplayMode displayMode = ENone;
+ //check display
+ if ( aMessage.Size() > KScreenDisplayOffset )
+ {
+ displayMode = (TDisplayMode)aMessage[KScreenDisplayOffset];
+ if ( displayMode >= EColorLast )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalidMode,
+ KScreenshotServiceUid);
+ return;
+ }
+ }
+
+ //check mime
+ TPtrC8 mime;
+ if ( aMessage[KScreenMIMEOffset] > 0 &&
+ ( aMessage[KScreenMIMEOffset] + KScreenMIMEOffset+1 ) < aMessage.Size() )
+ {
+ mime.Set( aMessage.Mid(KScreenMIMEOffset+1, aMessage[KScreenMIMEOffset] ) );
+ if ( !IsMIMETypeSupported( mime ) )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrMIMENotSupported,
+ KScreenshotServiceUid);
+ return;
+ }
+ }
+ else if ( aMessage[KScreenMIMEOffset] != 0 )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalidMode,
+ KScreenshotServiceUid);
+ return;
+ }
+
+ TBuf<0xFF> text;
+ TInt preTextOffset = KScreenMIMEOffset + aMessage[KScreenMIMEOffset] + 1;
+ TInt offset = ParseString( aMessage, preTextOffset, unicode, text );
+
+ HTI_LOG_FORMAT( "offset %d ", offset );
+ if ( offset == preTextOffset )
+ {
+ //empty text
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalid,
+ KScreenshotServiceUid);
+ }
+ else if ( offset < preTextOffset )
+ {
+ //error
+ iDispatcher->DispatchOutgoingErrorMessage(
+ offset,
+ KErrDescrInvalid,
+ KScreenshotServiceUid);
+ }
+
+ HTI_LOG_DES(text);
+ TFontSpec fontSpec;
+ offset = ParseFontSpec(aMessage,
+ offset,
+ unicode,
+ fontSpec);
+ if ( offset < 0 )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ offset,
+ KErrDescrInvalid,
+ KScreenshotServiceUid);
+
+ return;
+ }
+
+ //check colors
+ HTI_LOG_TEXT( "check colors" );
+ if ( offset + 2*4 != aMessage.Size() )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ offset,
+ KErrDescrInvalid,
+ KScreenshotServiceUid);
+ return;
+ }
+
+ //extract colors
+ TUint32 fgColor = ParseInt32( aMessage.Ptr() + offset );
+ TUint32 bgColor = ParseInt32( aMessage.Ptr() + offset + 4 );
+ HTI_LOG_FORMAT( "FG color %d", fgColor );
+ HTI_LOG_FORMAT( "BG color %d", bgColor );
+
+ //END parsing
+ //generate and return bitmap
+ CFont* useFont;
+
+ User::LeaveIfError( iScreenDevice->GetNearestFontToDesignHeightInPixels(
+ useFont, fontSpec ) );
+
+ TDisplayMode dm = displayMode==ENone || displayMode==0?
+ iScreenDevice->DisplayMode():
+ displayMode;
+
+
+ delete iScreen;
+ iScreen = NULL;
+ iScreen = CHtiTextRcg::GetTextBitmapL(
+ text,
+ useFont,
+ TRgb( fgColor ),
+ TRgb( bgColor ),
+ dm );
+
+ iScreenDevice->ReleaseFont( useFont );
+
+ //Encode iBitmap
+ iCompress = EFalse;
+ if ( mime.Length() == 0 )
+ {
+ EncodeBitmapL(); //use default encoder BMP
+ }
+ else
+ {
+ HTI_LOG_DES( mime );
+ EncodeBitmapL( mime );
+ }
+
+ HTI_LOG_FUNC_OUT( "CHtiScreenshotServicePlugin::ProcessTextBitmapMessageL" );
+ }
+
+/*
+// ----------------------------------------------------------------------------
+TBool CHtiScreenshotServicePlugin::RecognizeTextAllL(
+ const TDesC& aText,
+ TPoint& aResult)
+ {
+ HTI_LOG_FUNC_IN( "CHtiScreenshotServicePlugin::RecognizeTextAllL" );
+
+ TSize screenRect = iScreenDevice->SizeInPixels();
+ TInt nofTF = iScreenDevice->NumTypefaces();
+ HTI_LOG_FORMAT( "Number of typefaces %d", nofTF );
+ TBool returnValue = EFalse;
+ for ( TInt i = 0; i < nofTF; ++i )
+ {
+ TTypefaceSupport tf;
+ iScreenDevice->TypefaceSupport(tf, i);
+
+ HTI_LOG_DES(tf.iTypeface.iName);
+
+ if ( tf.iIsScalable )
+ {
+ //iterate throuh heighes
+
+ HTI_LOG_FORMAT( "num of heighs %d", tf.iNumHeights );
+ HTI_LOG_FORMAT( "min h in tw %d", tf.iMinHeightInTwips );
+ HTI_LOG_FORMAT( "max h in tw %d", tf.iMaxHeightInTwips );
+ HTI_LOG_FORMAT( "scalable %d", tf.iIsScalable );
+
+ HTI_LOG_TEXT( "-----------------------" );
+
+ TInt minHeight = Max(tf.iMinHeightInTwips, KFonHeighMin );
+ TInt maxHeight = Min(tf.iMaxHeightInTwips, KFonHeighMax );
+
+ if ( minHeight > maxHeight )
+ {
+ continue;
+ }
+
+ for ( TInt v = 0; v < 2; ++v )
+ {
+ TInt lastFontHeight = 0;
+ for ( TInt fh = minHeight; fh <= maxHeight; ++fh )
+ {
+ TFontSpec fs( tf.iTypeface.iName, fh );
+ fs.iFontStyle.SetBitmapType( EAntiAliasedGlyphBitmap );
+ switch ( v )
+ {
+ case 1:
+ {
+ fs.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
+ HTI_LOG_TEXT( "BOLD" );
+ }
+ break;
+ default:
+ {
+ HTI_LOG_TEXT( "DEFAULT" );
+ }
+ }
+ HTI_LOG_FORMAT( "hh %d", fh );
+
+ CFont* useFont = NULL;
+
+ iScreenDevice->GetNearestFontToDesignHeightInTwips(useFont, fs);
+
+ if ( screenRect.iHeight < useFont->HeightInPixels() ||
+ screenRect.iWidth < useFont->MaxNormalCharWidthInPixels()
+ )
+ {
+ break;
+ }
+
+ if ( useFont->HeightInPixels() == lastFontHeight )
+ {
+ continue;
+ }
+
+
+ lastFontHeight = useFont->HeightInPixels();
+
+ returnValue = iTextRcg.RecognizeTextL(
+ iScreen,
+ aText,
+ useFont,
+ aResult);
+ //HTI_LOG_TEXT( "ReleaseFont" );
+ iScreenDevice->ReleaseFont(useFont);
+
+ if ( returnValue )
+ {
+ HTI_LOG_TEXT( "Found" );
+ HTI_LOG_DES( aText );
+ HTI_LOG_DES( tf.iTypeface.iName );
+ HTI_LOG_FORMAT( "Font height in twips %d", fh );
+ HTI_LOG_FORMAT( "X %d", aResult.iX );
+ HTI_LOG_FORMAT( "Y %d", aResult.iY );
+ return returnValue;
+ }
+ }
+ }
+ }
+ else
+ {//non scal. font
+ TFontSpec fs( tf.iTypeface.iName,0 ); //height doesn't matter for
+ //not scalable font
+
+ CFont* useFont = NULL;
+ //HTI_LOG_TEXT( "GetFont" );
+ iScreenDevice->GetNearestFontToDesignHeightInTwips( useFont, fs );
+
+ returnValue = iTextRcg.RecognizeTextL(
+ iScreen,
+ aText,
+ useFont,
+ aResult );
+ //HTI_LOG_TEXT( "ReleaseFont" );
+ iScreenDevice->ReleaseFont( useFont );
+
+ if ( returnValue )
+ {
+ HTI_LOG_TEXT( "Found" );
+ HTI_LOG_DES( aText );
+ HTI_LOG_DES(tf.iTypeface.iName );
+ HTI_LOG_FORMAT( "X %d", aResult.iX );
+ HTI_LOG_FORMAT( "Y %d", aResult.iY );
+ return returnValue;
+ }
+ }
+ }
+
+ //
+
+ HTI_LOG_FUNC_OUT( "CHtiScreenshotServicePlugin::RecognizeTextAllL" );
+ //return returnValue;
+ return EFalse;
+ }
+*/
+
+// ----------------------------------------------------------------------------
+TBool CHtiScreenshotServicePlugin::RecognizeTextL(
+ const TDesC& aText,
+ TRect& aResult,
+ TInt& aFontIndex)
+ {
+ HTI_LOG_FUNC_IN( "CHtiScreenshotServicePlugin::RecognizeTextL" );
+
+ TSize screenRect = iScreenDevice->SizeInPixels();
+ TInt cacheSize = iFontCache.Count();
+ HTI_LOG_FORMAT( "Cache size %d", cacheSize );
+
+ TBool returnValue = EFalse;
+ for ( TInt i = 0; i < cacheSize; ++i )
+ {
+ CFont* useFont = NULL;
+
+ User::LeaveIfError(iScreenDevice->GetNearestFontToDesignHeightInPixels(
+ useFont, iFontCache[i] ) );
+ if ( iFontCache[i].iFontStyle.BitmapType()==EAntiAliasedGlyphBitmap )
+ {
+ iTextRcg.SetHint( EHintEdge );
+ }
+ else
+ {
+ iTextRcg.SetHint( EHintNone );
+ }
+
+ //check that font in valid size
+ if ( screenRect.iHeight < useFont->HeightInPixels() ||
+ screenRect.iWidth < useFont->MaxNormalCharWidthInPixels()
+ )
+ {
+ break;
+ }
+
+ returnValue = iTextRcg.RecognizeTextL( iScreen, aText, useFont,
+ aResult );
+
+ iScreenDevice->ReleaseFont( useFont );
+
+ if ( returnValue )
+ {
+ HTI_LOG_FORMAT( "Found! fontIndex %d", i );
+ HTI_LOG_DES( aText );
+ HTI_LOG_DES( iFontCache[i].iTypeface.iName );
+ HTI_LOG_FORMAT( "TL X %d", aResult.iTl.iX );
+ HTI_LOG_FORMAT( "TL Y %d", aResult.iTl.iY );
+ HTI_LOG_FORMAT( "BR X %d", aResult.iBr.iX );
+ HTI_LOG_FORMAT( "BR Y %d", aResult.iBr.iY );
+ aFontIndex = i;
+ return returnValue;
+ }
+ }
+
+ HTI_LOG_FUNC_OUT( "CHtiScreenshotServicePlugin::RecognizeTextL" );
+ return EFalse;
+ }
+
+/*
+TBool CHtiScreenshotServicePlugin::RecognizeTextL(
+ const TDesC& aText,
+ const TDesC& aTypeface,
+ TPoint& aResult)
+ {
+ HTI_LOG_FUNC_IN( "RecognizeTextL typeface" );
+ //const CFont* fontUsed = NULL;// AknLayoutUtils::FontFromName(aTypeface);
+ CFont* useFont = NULL;
+ TFontSpec fs(aTypeface, 0);
+
+ iScreenDevice->GetNearestFontInTwips(useFont, fs);
+
+ TBool returnValue = iTextRcg.RecognizeTextL(iScreen, aText, useFont, aResult);
+
+HTI_LOG_FUNC_OUT( "RecognizeTextL" );
+ return returnValue;
+}
+*/
+
+// ----------------------------------------------------------------------------
+void CHtiScreenshotServicePlugin::ProcessMessageL(const TDesC8& aMessage,
+ THtiMessagePriority /*aPriority*/)
+ {
+ HTI_LOG_FUNC_IN( "CHtiScreenshotServicePlugin::ProcessMessage");
+
+ if ( iICLHandler )
+ {
+ if ( iICLHandler->IsActive() || iEncodedBitmap)
+ {
+ User::Leave( KErrInUse );
+ }
+ }
+
+ if ( iSeriesShot->IsOngoing() )
+ User::Leave( KErrInUse );
+
+ // update the current screen mode
+ TPixelsAndRotation currentPixelsAndRotation;
+ iScreenDevice->GetScreenModeSizeAndRotation(
+ iScreenDevice->CurrentScreenMode(), currentPixelsAndRotation );
+ iScreenDevice->SetScreenSizeAndRotation( currentPixelsAndRotation );
+
+ if ( aMessage.Length() > 0 )
+ {
+ // set/reset delta capture status
+ iDeltaCapture = ( aMessage[0] & ECmdDeltaCaptureMask ) ? ETrue : EFalse;
+ if ( iDeltaCapture )
+ {
+ HTI_LOG_TEXT( "DeltaCapture ETrue" );
+ }
+
+ //if text recogn call separate handler
+ if ( aMessage[0] == ECmdTextRcg ||
+ aMessage[0] == ECmdTextRcg_u )
+ {
+ ProcessTextRcgMessageL( aMessage );
+ return;
+ }
+ else if ( aMessage[0] == ECmdTextBitmap ||
+ aMessage[0] == ECmdTextBitmap_u )
+ {
+ ProcessTextBitmapMessageL( aMessage );
+ return;
+ }
+
+ iCompress = ( aMessage[0] == ECmdScreenZip ) ||
+ ( aMessage[0] == ECmdScreenRegionZip ) ||
+ ( aMessage[0] == ECmdScreenZipSeries ) ||
+ ( aMessage[0] == ECmdScreenRegionZipSeries ) ||
+ ( aMessage[0] == ECmdDeltaScreenZip ) ||
+ ( aMessage[0] == ECmdDeltaScreenRegionZip );
+
+ HTI_LOG_FORMAT( "cmd 0x%x", aMessage[0] );
+ TPtrC8 mime;
+
+ switch ( aMessage[0] )
+ {
+ case ECmdScreen:
+ case ECmdScreenZip:
+ case ECmdDeltaScreen:
+ case ECmdDeltaScreenZip:
+ {
+ TRect empty;
+ TDisplayMode displayMode = ENone;
+ //check display
+ if ( aMessage.Length() > KScreenDisplayOffset )
+ {
+ displayMode = ( TDisplayMode ) aMessage[KScreenDisplayOffset];
+ if ( displayMode >= EColorLast )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalidMode,
+ KScreenshotServiceUid );
+ return;
+ }
+ }
+
+ CreateBitmapL( empty, displayMode );
+ //check mime
+ if ( aMessage.Length() > KScreenMIMEOffset )
+ {
+ mime.Set( aMessage.Mid( KScreenMIMEOffset ) );
+ if ( !IsMIMETypeSupported( mime ) )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrMIMENotSupported,
+ KScreenshotServiceUid );
+ return;
+ }
+ }
+ }
+ break;
+
+ case ECmdScreenRegion:
+ case ECmdScreenRegionZip:
+ case ECmdDeltaScreenRegion:
+ case ECmdDeltaScreenRegionZip:
+ {
+ if ( aMessage.Length() >= KMinScreenRegionCmdLength )
+ {
+ TRect region;
+ const TUint8* ptr = aMessage.Ptr();
+ region.iTl.iX = ParseInt16( ptr + 1 );
+ region.iTl.iY = ParseInt16( ptr + 3 );
+ region.iBr.iX = ParseInt16( ptr + 5 );
+ region.iBr.iY = ParseInt16( ptr + 7 );
+
+ //check empty and normmalizaed
+ if ( !region.IsNormalized() )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrRegionNotNormailized,
+ KScreenshotServiceUid );
+ return;
+ }
+
+ if ( region.IsEmpty() )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrRegiontEmpty,
+ KScreenshotServiceUid );
+ return;
+ }
+
+ TRect screenRect;
+ screenRect.iBr = iScreenDevice->SizeInPixels().AsPoint();
+ screenRect.iBr.iX++; //TRect::Contains() omitts
+ screenRect.iBr.iY++; //right bottom rows
+
+ TDisplayMode displayMode = ENone;
+ if ( aMessage.Length() > KRegionDisplayOffset )
+ {
+ displayMode = ( TDisplayMode ) aMessage[KRegionDisplayOffset];
+ if ( displayMode >= EColorLast )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalidMode,
+ KScreenshotServiceUid );
+ return;
+ }
+ }
+
+ if ( screenRect.Contains( region.iTl ) &&
+ screenRect.Contains( region.iBr ) )
+ {
+ CreateBitmapL( region, displayMode );
+ }
+ else
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrRegionOutOfScreen,
+ KScreenshotServiceUid );
+ return;
+ }
+
+ //check mime
+ if ( aMessage.Length() > KRegionMIMEOffset )
+ {
+ mime.Set( aMessage.Mid( KRegionMIMEOffset ) );
+ if ( !IsMIMETypeSupported( mime ) )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrMIMENotSupported,
+ KScreenshotServiceUid );
+ return;
+ }
+ }
+ }
+ else
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalid,
+ KScreenshotServiceUid );
+ return;
+ }
+ }
+ break;
+
+ case ECmdScreenSeries:
+ case ECmdScreenZipSeries:
+ {
+ if ( aMessage.Length() < KMinSeriesCmdLength )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalid,
+ KScreenshotServiceUid );
+ return;
+ }
+ TInt duration = ParseInt32( aMessage.Ptr() + KSeriesDurationOffset );
+ TInt interval = ParseInt32( aMessage.Ptr() + KSeriesIntervalOffset );
+
+ TDisplayMode displayMode = ( TDisplayMode ) aMessage[KSeriesDisplayOffset];
+ if ( displayMode >= EColorLast )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalidMode,
+ KScreenshotServiceUid );
+ return;
+ }
+
+ if ( aMessage.Length() > KSeriesMIMEOffset )
+ {
+ mime.Set( aMessage.Mid( KSeriesMIMEOffset ) );
+ if ( !IsMIMETypeSupported( mime ) )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrMIMENotSupported,
+ KScreenshotServiceUid );
+ return;
+ }
+ }
+
+ TRect empty;
+ iSeriesShot->StartL( duration, interval, displayMode, empty, mime );
+ }
+ return;
+
+ case ECmdScreenRegionSeries:
+ case ECmdScreenRegionZipSeries:
+ {
+ if ( aMessage.Length() < KMinRegionSeriesCmdLength )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalid,
+ KScreenshotServiceUid);
+ return;
+ }
+ TInt duration = ParseInt32( aMessage.Ptr() + KSeriesDurationOffset );
+ TInt interval = ParseInt32( aMessage.Ptr() + KSeriesIntervalOffset );
+
+ TDisplayMode displayMode = ( TDisplayMode ) aMessage[KSeriesDisplayOffset];
+ if ( displayMode >= EColorLast )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalidMode,
+ KScreenshotServiceUid );
+ return;
+ }
+
+ TRect region;
+ const TUint8* ptr = aMessage.Ptr();
+ region.iTl.iX = ParseInt16( ptr + KRegionSeriesTlX );
+ region.iTl.iY = ParseInt16( ptr + KRegionSeriesTlY );
+ region.iBr.iX = ParseInt16( ptr + KRegionSeriesBlX );
+ region.iBr.iY = ParseInt16( ptr + KRegionSeriesBlY );
+
+ //check empty and normmalizaed
+ if ( !region.IsNormalized() )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrRegionNotNormailized,
+ KScreenshotServiceUid );
+ return;
+ }
+
+ if ( region.IsEmpty() )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrRegiontEmpty,
+ KScreenshotServiceUid );
+ return;
+ }
+
+ TRect screenRect;
+ screenRect.iBr = iScreenDevice->SizeInPixels().AsPoint();
+ screenRect.iBr.iX++; //TRect::Contains() omitts
+ screenRect.iBr.iY++; //right bottom rows
+
+ if ( !screenRect.Contains( region.iTl ) ||
+ !screenRect.Contains( region.iBr ) )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrRegionOutOfScreen,
+ KScreenshotServiceUid );
+ return;
+ }
+
+ if ( aMessage.Length() > KRegionSeriesMIMEOffset )
+ {
+ mime.Set( aMessage.Mid( KRegionSeriesMIMEOffset ) );
+ if ( !IsMIMETypeSupported( mime ) )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrMIMENotSupported,
+ KScreenshotServiceUid );
+ return;
+ }
+ }
+
+ iSeriesShot->StartL( duration, interval, displayMode, region, mime );
+ }
+ return;
+
+ case ECmdSelectScreen:
+ {
+ if ( aMessage.Length() != KSelectScreenCmdLength )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalid,
+ KScreenshotServiceUid );
+ return;
+ }
+
+ TInt screenNr = aMessage[KScreenNrOffset];
+
+ TInt screens;
+ TInt ret=HAL::Get( HAL::EDisplayNumberOfScreens, screens );
+ if ( ret )
+ {
+ HTI_LOG_FORMAT( "HAL::Get failed %d", ret );
+ User::Leave( ret );
+ }
+
+
+ if ( ( screenNr > screens - 1 ) || ( screenNr < 0 ) )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrScreenNotSupported,
+ KScreenshotServiceUid );
+ return;
+ }
+
+
+ HTI_LOG_FORMAT( "Number of screens %d", screens );
+ HTI_LOG_FORMAT( "Setting to screen index %d", screenNr );
+
+ // Clear the previous delta bitmap to avoid error
+ iPreviousBitmap->Reset();
+
+ // delete old screendevice and create a new one
+ delete iScreenDevice;
+ iScreenDevice = NULL;
+ iScreenDevice = new ( ELeave ) CWsScreenDevice( iWs );
+ User::LeaveIfError( iScreenDevice->Construct( screenNr ) );
+
+ TBuf8<1> okMsg;
+ okMsg.Append( ECmdSelectScreen );
+ iDispatcher->DispatchOutgoingMessage(
+ okMsg.AllocL(), KScreenshotServiceUid );
+ }
+ return;
+
+ case ECmdDeltaScreenReset:
+ {
+ if ( aMessage.Length() != KDeltaResetCmdLength )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalid,
+ KScreenshotServiceUid );
+ return;
+ }
+
+ iPreviousBitmap->Reset();
+ TBuf8<1> okMsg;
+ okMsg.Append( ECmdDeltaScreenReset );
+ iDispatcher->DispatchOutgoingMessage(
+ okMsg.AllocL(), KScreenshotServiceUid );
+ }
+ return;
+
+ case ECmdScreenMode:
+ {
+ if ( aMessage.Length() != KScreenModeCmdLength )
+ {
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrInvalid,
+ KScreenshotServiceUid );
+ return;
+ }
+
+ TInt focusScreen = iWs.GetFocusScreen();
+ TPixelsAndRotation sizeAndRotation;
+ TDisplayMode mode = ENone;
+ TInt thisScreen = iScreenDevice->GetScreenNumber();
+ iScreenDevice->GetDefaultScreenSizeAndRotation( sizeAndRotation );
+ mode = iScreenDevice->DisplayMode();
+
+ HTI_LOG_FORMAT( "This screen = %d", thisScreen );
+ HTI_LOG_FORMAT( "Screen width = %d", sizeAndRotation.iPixelSize.iWidth );
+ HTI_LOG_FORMAT( "Screen height = %d", sizeAndRotation.iPixelSize.iHeight );
+ HTI_LOG_FORMAT( "Rotation = %d", sizeAndRotation.iRotation );
+ HTI_LOG_FORMAT( "Display mode = %d", mode );
+ HTI_LOG_FORMAT( "Focus screen = %d", focusScreen );
+ TBuf8<8> respMsg;
+ respMsg.Append( thisScreen );
+ respMsg.Append( ( TUint8* )( &( sizeAndRotation.iPixelSize.iWidth ) ), 2 );
+ respMsg.Append( ( TUint8* )( &( sizeAndRotation.iPixelSize.iHeight ) ), 2 );
+ respMsg.Append( sizeAndRotation.iRotation );
+ respMsg.Append( mode );
+ respMsg.Append( focusScreen );
+ iDispatcher->DispatchOutgoingMessage(
+ respMsg.AllocL(), KScreenshotServiceUid );
+ }
+ return;
+
+ default:
+ //Error: unknown command
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrUnknownCommand,
+ KScreenshotServiceUid );
+ return;
+ } // switch
+
+ //Encode iBitmap
+ if ( mime.Length() == 0 )
+ {
+ EncodeBitmapL(); //use default encoder BMP
+ }
+ else
+ {
+ HTI_LOG_DES( mime );
+ EncodeBitmapL( mime );
+ }
+ }
+ else
+ {
+ //error: empty request
+ iDispatcher->DispatchOutgoingErrorMessage(
+ KErrArgument,
+ KErrDescrUnknownCommand,
+ KScreenshotServiceUid );
+ }
+
+ HTI_LOG_FUNC_OUT( "HtiScreenshotServicePlugin::ProcessMessage" );
+ }
+
+
+// ----------------------------------------------------------------------------
+void CHtiScreenshotServicePlugin::CreateBitmapL( TRect& aRegion,
+ TDisplayMode aMode )
+ {
+ HTI_LOG_FUNC_IN( "CreateBitmapL" );
+ //create bitmap
+ TSize imageSize = aRegion.IsEmpty() ? iScreenDevice->SizeInPixels() :
+ aRegion.Size();
+
+ TDisplayMode displayMode = aMode == ENone ?
+ iScreenDevice->DisplayMode() : aMode;
+
+ delete iScreen;//in case ICLComplete was not called
+ iScreen = NULL;
+ iScreen = new( ELeave ) CFbsBitmap;
+ User::LeaveIfError( iScreen->Create( imageSize, displayMode ) );
+
+ if ( aRegion.IsEmpty() )
+ {
+ iScreenDevice->CopyScreenToBitmap( iScreen );
+ }
+ else
+ {
+ iScreenDevice->CopyScreenToBitmap( iScreen, aRegion );
+ }
+
+
+ if ( iDeltaCapture )
+ {
+ HTI_LOG_TEXT( "DeltaCapture enabled" );
+
+
+ CFbsBitmap* differenceBitmap = NULL;
+ TInt err = ImageDifferenceL( iPreviousBitmap,
+ iScreen,
+ differenceBitmap,
+ iDeltaRect );
+
+ iPreviousBitmap->Reset();
+ iPreviousBitmap->Duplicate( iScreen->Handle() );
+
+ if ( err == KErrNone )
+ {
+ delete iScreen;
+ iScreen = differenceBitmap;
+ }
+ else if ( err == KErrNotFound )
+ {
+ delete iScreen;
+ iScreen = NULL;
+
+ if ( !iSeriesShot->IsOngoing() )
+ {
+ // Nothing has changed on the screen.
+ // Send just iDeltaRect coordidates
+ HBufC8* buf = HBufC8::NewL( 4 * 2 ); // 2 bytes for each coordinate
+ buf->Des().SetLength( 4 * 2 );
+ TUint16* ptr = (TUint16*) buf->Des().Ptr();
+ ptr[0] = (TUint16) iDeltaRect.iTl.iX;
+ ptr[1] = (TUint16) iDeltaRect.iTl.iY;
+ ptr[2] = (TUint16) iDeltaRect.iBr.iX;
+ ptr[3] = (TUint16) iDeltaRect.iBr.iY;
+ // Response also sent in ICLComplete
+ iDispatcher->DispatchOutgoingMessage( buf, KScreenshotServiceUid );
+ }
+ }
+ }
+
+ HTI_LOG_FUNC_OUT( "CreateBitmapL" );
+ }
+/*
+
+// ----------------------------------------------------------------------------
+void CleanupRArray( TAny* object )
+ {
+ ((RImageTypeDescriptionArray*)object)->ResetAndDestroy();
+ }
+
+// ----------------------------------------------------------------------------
+void CHtiScreenshotServicePlugin::SelectEncoder( const TUid aEncoderUid )
+ {
+ //select encoder
+ RImageTypeDescriptionArray imageTypeArray;
+ CImageEncoder::GetImageTypesL( imageTypeArray );
+ CleanupStack::PushL( TCleanupItem(CleanupRArray, &imageTypeArray) );
+
+ //select specified encoder
+ TBool found = EFalse;
+ for ( TInt i = 0; i < imageTypeArray.Count(); ++i )
+ {
+ if ( imageTypeArray[i]->ImageType() == aEncoderUid )
+ {
+ iImageEncoderType = imageTypeArray[i]->ImageType();
+ iImageEncoderSubtype = imageTypeArray[i]->SubType();
+ found = ETrue;
+ }
+ }
+
+ if ( !found )
+ {
+ User::Leave( KErrNotFound );
+ }
+ CleanupStack::PopAndDestroy(); //imageTypeArray
+ }
+*/
+
+// ----------------------------------------------------------------------------
+TBool CHtiScreenshotServicePlugin::IsMIMETypeSupported(TDesC8 &aMime)
+ {
+ HTI_LOG_DES(aMime);
+ RFileExtensionMIMETypeArray array;
+ CImageEncoder::GetFileTypesL(array);
+ for ( TInt i = 0; i < array.Count(); i++ )
+ {
+ if ( array[i]->MIMEType() == aMime )
+ {
+ HTI_LOG_TEXT( "MIME supported" );
+ array.ResetAndDestroy();
+ return ETrue;
+ }
+ }
+ HTI_LOG_TEXT( "MIME not supported" );
+ array.ResetAndDestroy();
+ return EFalse;
+ }
+
+
+// ----------------------------------------------------------------------------
+void CHtiScreenshotServicePlugin::EncodeBitmapL(const TDesC8& aImageTypeMIME )
+ {
+ HTI_LOG_FUNC_IN( "EncodeBitmapL" );
+ delete iBitmapEncoder;
+ iBitmapEncoder = NULL;
+ delete iICLHandler;
+ iICLHandler = NULL;
+
+ if ( iScreen )
+ {
+ HTI_LOG_TEXT( "create encoder" );
+ if ( aImageTypeMIME == KNullDesC8 )
+ {
+ iBitmapEncoder = CImageEncoder::DataNewL( iEncodedBitmap,
+ CImageEncoder::EOptionNone,
+ KImageTypeBMPUid);//,
+ //iImageEncoderSubtype);
+ }
+ else
+ {
+ iBitmapEncoder = CImageEncoder::DataNewL( iEncodedBitmap,
+ aImageTypeMIME);
+ }
+
+ HTI_LOG_TEXT( "create CICLHandler" );
+ iICLHandler = new(ELeave) CICLHandler( iBitmapEncoder, this );
+ iBitmapEncoder->Convert( &(iICLHandler->iStatus), *iScreen );
+
+ HTI_LOG_TEXT( "CICLHandler start");
+ iICLHandler->Start();
+ }
+ else
+ {
+ HTI_LOG_TEXT( "Nothing to encode" );
+ }
+
+ HTI_LOG_FUNC_OUT( "EncodeBitmapL" );
+ }
+
+// ----------------------------------------------------------------------------
+TInt CHtiScreenshotServicePlugin::Compress()
+ {
+ __ASSERT_ALWAYS(iEncodedBitmap!=NULL,User::Panic(KScreenshotPanic, KErrGeneral));
+ TInt err = KErrNone;
+ HBufC8* zippedTemp = NULL;
+
+ HTI_LOG_FORMAT( "image size %d", iEncodedBitmap->Size() );
+ TInt numOfSteps = 4;
+ TInt comprBufferIncrease = iEncodedBitmap->Size()/numOfSteps;
+
+ //straight way to handle cases
+ //when compressed data larger than uncompressed
+ //try until buffer for compr. data twice bigger than original data
+ for ( TInt i = 0; i < numOfSteps; ++i )
+ {
+ delete zippedTemp;
+ TRAP( err, zippedTemp = HBufC8::NewL( iEncodedBitmap->Size() +
+ i*comprBufferIncrease ) );
+ if ( err == KErrNone )
+ {
+ //try to zip
+ HTI_LOG_TEXT( "try to zip" );
+ TPtr8 zippedTempPtr = zippedTemp->Des();
+ TRAP( err, CEZCompressor::CompressL( zippedTempPtr,
+ *iEncodedBitmap ) );
+ if ( err == KErrNone || err != KEZlibErrBuf )
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if ( err == KErrNone )
+ {
+ delete iEncodedBitmap;
+ iEncodedBitmap = zippedTemp;
+ }
+ else
+ {
+ HTI_LOG_FORMAT( "compre error %d", err );
+ delete zippedTemp;
+ }
+
+ return err;
+ }
+
+// ----------------------------------------------------------------------------
+void CHtiScreenshotServicePlugin::ICLComplete( TInt anError)
+ {
+ HTI_LOG_FUNC_IN( "ICLComplete" );
+
+ //delete what we dont need right away
+ delete iBitmapEncoder;
+ iBitmapEncoder = NULL;
+ delete iICLHandler;
+ iICLHandler = NULL;
+
+
+ if ( anError==KErrNone )
+ {
+ TInt err = KErrNone;
+
+
+ //compress
+ if ( iCompress )
+ {
+ HTI_LOG_TEXT( "compress" );
+ err = Compress();
+ }
+
+ //send
+ if ( err == KErrNone )
+ {
+
+ if ( !iSeriesShot->IsOngoing() )
+ {
+ // Not a series shot
+
+ if ( iDeltaCapture )
+ {
+ // DeltaCapture on
+
+ // If we have encoded the bitmap then we
+ // also have some difference in the bitmap
+
+ HTI_LOG_TEXT( "Sending image with coordinates..." );
+
+ HBufC8* buf = HBufC8::NewL( (4*2) + iEncodedBitmap->Size() );
+ buf->Des().SetLength(4*2);
+ TUint16* ptr = (TUint16*) buf->Des().Ptr();
+ ptr[0] = (TUint16) iDeltaRect.iTl.iX;
+ ptr[1] = (TUint16) iDeltaRect.iTl.iY;
+ ptr[2] = (TUint16) iDeltaRect.iBr.iX;
+ ptr[3] = (TUint16) iDeltaRect.iBr.iY;
+
+ buf->Des().Append(*iEncodedBitmap);
+
+ delete iEncodedBitmap;
+ iEncodedBitmap = NULL;
+
+ // Response also sent in CreateBitmapL
+ err = iDispatcher->DispatchOutgoingMessage(buf,
+ KScreenshotServiceUid);
+ }
+ else
+ {
+ // Normal case
+ HTI_LOG_TEXT( "Sending image..." );
+ err = iDispatcher->DispatchOutgoingMessage(iEncodedBitmap,
+ KScreenshotServiceUid);
+ }
+
+ if ( err == KErrNoMemory )
+ {
+ HTI_LOG_TEXT( "wait for memory" );
+ iDispatcher->AddMemoryObserver( this );
+ }
+ else if ( err == KErrNone )
+ {
+ iEncodedBitmap = NULL;
+ }
+ else //just drop
+ {
+ HTI_LOG_TEXT( "ERROR: Impossible to send image" );
+ delete iEncodedBitmap;
+ iEncodedBitmap = NULL;
+ }
+ }
+ }
+ else
+ {
+ iSeriesShot->Cancel();
+ iDispatcher->DispatchOutgoingErrorMessage(
+ err,
+ KErrDescrFailedCompress,
+ KScreenshotServiceUid);
+ delete iEncodedBitmap;
+ iEncodedBitmap = NULL;
+ }
+ }
+ else
+ {
+ iSeriesShot->Cancel();
+ iDispatcher->DispatchOutgoingErrorMessage(
+ anError,
+ KErrDescrFailedConvert,
+ KScreenshotServiceUid);
+ delete iEncodedBitmap;
+ iEncodedBitmap = NULL;
+ }
+
+ if ( iSeriesShot->IsOngoing() )
+ {
+ iSeriesShot->SaveImage( iEncodedBitmap, iCompress );
+ delete iEncodedBitmap;
+ iEncodedBitmap = NULL;
+
+ // Check if there's still more to do
+ if ( iSeriesShot->IsOngoing() )
+ {
+ iSeriesShot->TriggerNewShot();
+ }
+ else
+ {
+ // - No, timer still active
+ // SeriesShot can complete here and in CSeriesShot::TimerExpired
+ SeriesShotCompletedL(iSeriesShot->ConstructCompletedMessageL());
+ }
+ }
+
+ HTI_LOG_FUNC_OUT( "ICLComplete" );
+ }
+
+// ----------------------------------------------------------------------------
+void CHtiScreenshotServicePlugin::NotifyMemoryChange( TInt aAvailableMemory )
+ {
+ if ( iEncodedBitmap )
+ {
+ if ( aAvailableMemory>= iEncodedBitmap->Size() )
+ {
+ TInt err = iDispatcher->DispatchOutgoingMessage(iEncodedBitmap,
+ KScreenshotServiceUid);
+
+ if ( err == KErrNone)
+ {
+ iEncodedBitmap = NULL;
+ iDispatcher->RemoveMemoryObserver( this );
+ }
+ else if ( err != KErrNoMemory )
+ {
+ delete iEncodedBitmap;
+ iEncodedBitmap = NULL;
+ iDispatcher->RemoveMemoryObserver( this );
+ }
+ }
+ }
+ else
+ {
+ //some error, should not be called
+ iDispatcher->RemoveMemoryObserver(this);
+ }
+ }
+
+// ----------------------------------------------------------------------------
+void CHtiScreenshotServicePlugin::SeriesShotCompletedL(HBufC8* aMsg)
+ {
+ HTI_LOG_FUNC_IN( "CHtiScreenshotServicePlugin::SeriesShotCompletedL" );
+ User::LeaveIfError( iDispatcher->DispatchOutgoingMessage(
+ aMsg,
+ KScreenshotServiceUid) );
+ HTI_LOG_FUNC_OUT( "CHtiScreenshotServicePlugin::SeriesShotCompletedL" );
+ }
+
+// ----------------------------------------------------------------------------
+TBool CHtiScreenshotServicePlugin::StartShotL(TRect aRegion, TDisplayMode aDisplayMode, TDesC8 &aMimeType)
+ {
+ HTI_LOG_FUNC_IN( "CHtiScreenshotServicePlugin::StartShot" );
+ CreateBitmapL( aRegion, aDisplayMode );
+
+ if ( aMimeType.Length()==0 )
+ EncodeBitmapL(); //use default encoder BMP
+ else
+ EncodeBitmapL( aMimeType );
+
+ HTI_LOG_FUNC_OUT( "CHtiScreenshotServicePlugin::StartShot" );
+ return iScreen ? ETrue : EFalse;
+ }
+
+// ----------------------------------------------------------------------------
+CSeriesShot* CSeriesShot::NewL( MSeriesShotObserver* aServicePlugin )
+ {
+ HTI_LOG_FUNC_IN( "CSeriesShot::NewL" );
+ CSeriesShot* self = new (ELeave) CSeriesShot( aServicePlugin );
+ CleanupStack::PushL (self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ HTI_LOG_FUNC_OUT( "CSeriesShot::NewL" );
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+void CSeriesShot::ConstructL()
+ {
+ User::LeaveIfError(iFs.Connect());
+ }
+
+// ----------------------------------------------------------------------------
+CSeriesShot::CSeriesShot( MSeriesShotObserver* aServicePluginObserver ):
+ iServicePluginObserver( aServicePluginObserver ),
+ iDurationTimer( NULL ),
+ iIntervalTimer( NULL ),
+ isEncoding( EFalse )
+ {
+ }
+
+// ----------------------------------------------------------------------------
+CSeriesShot::~CSeriesShot()
+ {
+ Cancel();
+ iFs.Close();
+ }
+
+// ----------------------------------------------------------------------------
+void CSeriesShot::ClearShots()
+ {
+ HTI_LOG_FUNC_IN( "CSeriesShot::ClearShots" );
+
+ iFs.MkDirAll( KSeriesShotPath );
+
+ // Delete all files
+ TFileName files;
+ files.Append( KSeriesShotPath );
+ files.Append( _L( "*.*" ) );
+ HTI_LOG_DES(files);
+
+
+ CFileMan *fileman = CFileMan::NewL( iFs );
+ TInt err = fileman->Delete( files );
+ HTI_LOG_FORMAT( "delete %d", err );
+ if ( err != KErrNotFound )
+ User::LeaveIfError( err );
+ delete fileman;
+
+
+ HTI_LOG_FUNC_OUT( "CSeriesShot::ClearShots" );
+ }
+
+// ----------------------------------------------------------------------------
+void CSeriesShot::StartL( TTimeIntervalMicroSeconds32 aDuration,
+ TTimeIntervalMicroSeconds32 aInterval,
+ TDisplayMode aDisplayMode,
+ TRect aRegion,
+ TPtrC8 aMime )
+ {
+ HTI_LOG_FUNC_IN( "CSeriesShot::StartL" );
+ HTI_LOG_FORMAT( "Duration : %d microseconds", aDuration.Int() );
+ HTI_LOG_FORMAT( "Interval : %d microseconds", aInterval.Int() );
+ HTI_LOG_FORMAT( "Displaymode : %d", aDisplayMode );
+ HTI_LOG_FORMAT( "TopLeft X : %d", aRegion.iTl.iX );
+ HTI_LOG_FORMAT( "TopLeft Y : %d", aRegion.iTl.iY );
+ HTI_LOG_FORMAT( "BottomRight X : %d", aRegion.iBr.iX );
+ HTI_LOG_FORMAT( "BottomRight Y : %d", aRegion.iBr.iY );
+
+ iDisplayMode = aDisplayMode;
+ iRegion = aRegion;
+ iIndex = 0;
+
+ iMimeType.Zero();
+ iMimeType.Append( aMime );
+ HTI_LOG_DES( iMimeType );
+
+#ifdef __ENABLE_LOGGING__
+ HTI_LOG_TEXT( "Supported MIME types:" );
+ RFileExtensionMIMETypeArray array;
+ CImageEncoder::GetFileTypesL( array );
+ for ( TInt i = 0; i < array.Count(); i++ )
+ HTI_LOG_DES( array[i]->MIMEType() );
+ array.ResetAndDestroy();
+#endif
+
+ iExtension.Zero();
+ if ( iMimeType.Length() == 0 )
+ iExtension.Append( _L( ".bmp" ) );
+ else
+ GetMIMEExtension( iMimeType, iExtension );
+
+ ClearShots();
+
+ iDurationTimer = CSeriesShotTimer::NewL( this, EDuration, aDuration );
+ iIntervalTimer = CSeriesShotTimer::NewL( this, EInterval, aInterval );
+ iDurationTimer->Start();
+ TimerExpired( EInterval ); // trigger first shot immidietly
+
+ HTI_LOG_FUNC_OUT( "CSeriesShot::StartL" );
+ }
+
+void CSeriesShot::TimerExpired( TInt aId )
+ {
+ HTI_LOG_FUNC_IN( "CSeriesShot::TimerExpired" );
+ switch ( aId )
+ {
+ case EDuration:
+ HTI_LOG_TEXT( "EDuration" );
+
+ delete iDurationTimer;
+ iDurationTimer = NULL;
+
+ if ( iIntervalTimer ) // I'm paranoid
+ {
+ delete iIntervalTimer;
+ iIntervalTimer = NULL;
+ }
+ // SeriesShot can complete here and in CHtiScreenshotServicePlugin::ICLComplete
+ if ( isEncoding == EFalse )
+ iServicePluginObserver->SeriesShotCompletedL( ConstructCompletedMessageL() );
+
+ break;
+
+ case EInterval:
+ HTI_LOG_TEXT( "EInterval" );
+
+ isEncoding = iServicePluginObserver->StartShotL( iRegion, iDisplayMode, iMimeType );
+
+ break;
+
+ default:
+ break;
+ }
+ HTI_LOG_FUNC_OUT( "CSeriesShot::TimerExpired" );
+ }
+
+// ----------------------------------------------------------------------------
+TBool CSeriesShot::IsOngoing()
+ {
+ // It still might be encoding when duration timer has expired
+ return ( iDurationTimer || isEncoding ) ? ETrue : EFalse;
+ }
+
+// ----------------------------------------------------------------------------
+void CSeriesShot::SaveImage( TDesC8* aImage, TBool isCompressed )
+ {
+ HTI_LOG_FUNC_IN( "CSeriesShot::SaveImage" );
+
+ isEncoding = EFalse;
+
+ TFileName filename( KSeriesShotPath );
+ filename.AppendFormat( _L( "%04d" ), iIndex );
+ iIndex++;
+ filename.Append( iExtension );
+ if ( isCompressed )
+ filename.Append( _L( "z" ) );
+ HTI_LOG_DES( filename );
+
+ RFile file;
+ User::LeaveIfError( file.Create( iFs, filename, EFileWrite ) );
+ User::LeaveIfError( file.Write( *aImage ) );
+ file.Close();
+
+ HTI_LOG_FUNC_IN( "CSeriesShot::SaveImage" );
+ }
+
+// ----------------------------------------------------------------------------
+void CSeriesShot::TriggerNewShot()
+ {
+ if ( iDurationTimer )
+ iIntervalTimer->Start();
+ }
+
+// ----------------------------------------------------------------------------
+void CSeriesShot::Cancel()
+ {
+ if ( iDurationTimer )
+ {
+ delete iDurationTimer;
+ iDurationTimer = NULL;
+ }
+ if ( iIntervalTimer )
+ {
+ delete iIntervalTimer;
+ iIntervalTimer = NULL;
+ }
+ ClearShots();
+ }
+
+// ----------------------------------------------------------------------------
+void CSeriesShot::EncodeCompleted()
+ {
+ isEncoding = EFalse;
+ }
+
+// ----------------------------------------------------------------------------
+void CSeriesShot::GetMIMEExtension( TDesC8 &aMime, TDes &aExt )
+ {
+ RFileExtensionMIMETypeArray array;
+ CImageEncoder::GetFileTypesL( array );
+ for ( TInt i = 0; i < array.Count(); i++ )
+ {
+ if ( array[i]->MIMEType() == aMime )
+ aExt.Append( array[i]->FileExtension() );
+ }
+ array.ResetAndDestroy();
+
+ if ( aExt == KNullDesC ) // should not happen
+ aExt.Append( _L( ".xxx" ) );
+ }
+
+// ----------------------------------------------------------------------------
+HBufC8* CSeriesShot::ConstructCompletedMessageL()
+ {
+ HTI_LOG_FUNC_IN( "CSeriesShot::ConstructCompletedMessageL" );
+ // Serialshot completed send ok message.
+
+ CDir* dir = NULL;
+ User::LeaveIfError( iFs.GetDir(
+ KSeriesShotPath, KEntryAttNormal, ESortByName, dir ) );
+
+ TInt msgSize = 0;
+
+ if ( dir->Count() == 0 )
+ {
+ HTI_LOG_TEXT( "No shots found! Leaving..." );
+ User::Leave( KErrNotFound );
+ }
+
+ for ( TInt i = 0; i < dir->Count(); i++ )
+ {
+ msgSize += 1; // for length field
+ msgSize += KSeriesShotPath().Length();
+ msgSize += (*dir)[i].iName.Length();
+ }
+
+ HBufC8* msg = HBufC8::NewL( msgSize );
+
+ for ( TInt i = 0; i < dir->Count(); i++ )
+ {
+ msg->Des().Append( KSeriesShotPath().Length() + (*dir)[i].iName.Length() );
+ msg->Des().Append( KSeriesShotPath );
+ msg->Des().Append( (*dir)[i].iName );
+ }
+
+ delete dir;
+
+ HTI_LOG_FUNC_OUT( "CSeriesShot::ConstructCompletedMessageL" );
+ return msg;
+ }
+
+// ----------------------------------------------------------------------------
+CSeriesShotTimer* CSeriesShotTimer::NewL( MSeriesShotTimerObserver* aObserver,
+ TInt aId,
+ TTimeIntervalMicroSeconds32 aTime )
+ {
+ HTI_LOG_FUNC_IN( "CSeriesShotTimer::NewL" );
+ CSeriesShotTimer* self = new (ELeave) CSeriesShotTimer( aObserver, aId, aTime );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop();
+ HTI_LOG_FUNC_OUT( "CSeriesShotTimer::NewL" );
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+void CSeriesShotTimer::ConstructL()
+ {
+ HTI_LOG_FUNC_IN( "CSeriesShotTimer::ConstructL" );
+ CTimer::ConstructL();
+ if ( !IsAdded() ) // CTimer should add it but it seems that it does NOT!
+ {
+ CActiveScheduler::Add( this );
+ }
+ HTI_LOG_FUNC_OUT( "CSeriesShotTimer::ConstructL" );
+ }
+
+// ----------------------------------------------------------------------------
+CSeriesShotTimer::CSeriesShotTimer( MSeriesShotTimerObserver* aObserver,
+ TInt aId,
+ TTimeIntervalMicroSeconds32 aTime ):
+ CTimer( EPriorityStandard ),
+ iObserver( aObserver ),
+ iId( aId ),
+ iTime( aTime )
+ {
+ }
+
+// ----------------------------------------------------------------------------
+CSeriesShotTimer::~CSeriesShotTimer()
+ {
+ }
+
+// ----------------------------------------------------------------------------
+void CSeriesShotTimer::RunL()
+ {
+ iObserver->TimerExpired( iId );
+ }
+
+// ----------------------------------------------------------------------------
+void CSeriesShotTimer::Start()
+ {
+ HTI_LOG_FORMAT( "Start CSeriesShotTimer : %d microseconds", iTime.Int() );
+ After( iTime );
+ }