diff -r 6a20128ce557 -r ebfee66fde93 messagingapp/msgutils/unidatautils/unidatamodel/src/UniSmilModel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingapp/msgutils/unidatautils/unidatamodel/src/UniSmilModel.cpp Fri Jun 04 10:25:39 2010 +0100 @@ -0,0 +1,2578 @@ +/* +* Copyright (c) 2005 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: +* CUniSmilModel, Storage for Smil presentation data. +* +* +*/ + + +// ========== INCLUDE FILES ================================ + + +#include +#include +#include // CopyFile + +#include // for CBaseMtm +#include // for TMsvId +#include // for KMsvTempIndexEntryId +#include +#include +#include +#include + +#include // NearestLanguageFile + +#include + +// LAF +/* +#include +#include +#include +#include +*/ + +// DOM +#include +#include +#include + +// MsgMedia +#include +#include +#include +#include +#include + + +// MsgDataUTILS +#include // Viewer/Editor Mimetype strings +#include "UniModelConst.h" // Definitions and enums +#include "UniDataUtils.h" +#include "UniSmilSlide.h" +#include "UniSmilModel.h" +#include "UniObjectList.h" +#include "UniObject.h" +#include "UniTextObject.h" +#include "UniMimeInfo.h" +#include "UniSmilUtils.h" +#include "UniSmilParams.h" + +#include "fileprotectionresolver.h" // EFileProtDrm2 +#include "MsgMimeTypes.h" + +// Logging +//#include "//MsgDataUTILSLOGGing.h" + + +// ========== EXTERNAL DATA STRUCTURES ===================== + +// ========== EXTERNAL FUNCTION PROTOTYPES ================= + +// ========== CONSTANTS ==================================== + +// ========== MACROS ======================================= + +// ========== LOCAL CONSTANTS AND MACROS =================== + +_LIT( KSmilIntFormat, "%d" ); +_LIT( KSmilMsecFormat, "%dms" ); +const TUint KSlideArrayGranularity( 16 ); + +// SMIL size estimates +const TInt KSizeMandatorySmilTags = 148; +const TInt KSizeHeadOneRegion = 85; +const TInt KSizeHeadTwoRegions = 170; +const TInt KSizeEmptyPar = 27; +const TInt KSizeNonEmptyPar = 41; +const TInt KSizeAudioTag = 38; +const TInt KSizeImageTag = 52; +const TInt KSizeTextTag = 51; +const TInt KSizeVideoTag = 53; + +const TInt KSizeLowResHeight = 208; +const TInt KSizeLowResWidth = 176; + +// ========== MODULE DATA STRUCTURES ======================= + +// ========== LOCAL FUNCTION PROTOTYPES ==================== + +// ========== LOCAL FUNCTIONS ============================== + +// ========== MEMBER FUNCTIONS ============================= + + +// --------------------------------------------------------- +// CUniSmilModel::NewL +// +// Factory method. +// --------------------------------------------------------- +// +EXPORT_C CUniSmilModel* CUniSmilModel::NewLC( RFs& aFs, + CBaseMtm& aMtm, + CUniDataUtils& aData, + CUniObjectList& aObjectList ) + { + CUniSmilModel* self = new ( ELeave ) + CUniSmilModel( aFs, aMtm, aData, aObjectList ); + + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + + +// --------------------------------------------------------- +// CUniSmilModel::NewL +// +// Factory method. +// --------------------------------------------------------- +// +EXPORT_C CUniSmilModel* CUniSmilModel::NewL( RFs& aFs, + CBaseMtm& aMtm, + CUniDataUtils& aData, + CUniObjectList& aObjectList ) + { + CUniSmilModel* self = NewLC( aFs, aMtm, aData, aObjectList ); + CleanupStack::Pop( self ); + return self; + } + + +// --------------------------------------------------------- +// CUniSmilModel::CUniSmilModel +// +// Constructor. +// --------------------------------------------------------- +// +CUniSmilModel::CUniSmilModel( RFs& aFs, + CBaseMtm& aMtm, + CUniDataUtils& aData, + CUniObjectList& aObjectList ) : + iFs( aFs ), + iMtm( aMtm ), + iData( aData ), + iObjectList( aObjectList ), + iSlideLayout( EUniUndefinedLayout ), + iSmilParams( 0 ), + iScreenSize( 0, 0 ), + iSizeEstimateUpToDate( EFalse ), + iSizeEstimate( 0 ) + { + } + +// --------------------------------------------------------- +// CUniSmilModel::~CUniSmilModel +// +// Destructor. +// --------------------------------------------------------- +// +CUniSmilModel::~CUniSmilModel() + { + if (iSlideArray) + { + iSlideArray->ResetAndDestroy(); + } + delete iSlideArray; + delete iSmilParams; + } + +// --------------------------------------------------------- +// CUniSmilModel::ParseL +// +// --------------------------------------------------------- +// +EXPORT_C TInt CUniSmilModel::ParseL( CMDXMLDocument* aDom ) + { + //MsgDataUTILSLOGGER_ENTERFN( "CUniSmilModel::ParseL()" ); + + Reset(); + + if ( aDom ) + { + TRAPD( error, DoPresentationFromDomL( aDom ) ); + if ( error ) + { + Reset(); + User::Leave( error ); + } + else + { + iParseResult |= EParsedFromSmil; + } + } + else + { + // No SMIL -> Do presentation from object list + if ( IsMessageSlide() ) + { + // Determine layout. Make slide. + DoNoSmilOneSlideL(); + } + else + { + // Do slide for each media object + DoNoSmilManySlideL(); + } + iParseResult |= EParsedFromList; + } + + return iParseResult; + } + + +//********************************************************** +//* +//* SMIL COMPOSING FUNCTIONS +//* +//********************************************************** + + +// --------------------------------------------------------- +// CUniSmilModel::¨ComposeL +// +// --------------------------------------------------------- +// +EXPORT_C CMDXMLDocument* CUniSmilModel::ComposeL() + { + //MsgDataUTILSLOGGER_ENTERFN( "CUniSmilModel::ComposeL()" ); + + // Reset region id's + iTextRegionId.Set( KNullDesC ); + iImageRegionId.Set( KNullDesC ); + + // Read default smil parameters + if( !iSmilParams ) + { + //MsgDataUTILSLOGGER_WRITE( "CUniSmilModel: Creating smil parameter structures." ); + iSmilParams = CUniSmilParams::NewL( iFs ); + } + + //MsgDataUTILSLOGGER_WRITE( "CUniSmilModel: Creating new DOM." ); + //delete iDom; + //iDom = 0; + CMDXMLDocument* dom = CMDXMLDocument::NewLC(); + + // Create smil node + TPtrC name( KSMILWREleSmil ); + CMDXMLElement* root = CMDXMLElement::NewLC( ETrue, dom, name ); + // Append + dom->DocumentElement()->AppendChild( root ); // Ownership to dom + CleanupStack::Pop( root ); + + // Create Head + CreateHeadL( dom, root ); + + // Create Body + CreateBodyL( dom, root ); + + // TODO: Move to Document and to use smil list + //iObjectList.CreateSmilAttachmentL( smilAttaId, iDom, iFs ); + CleanupStack::Pop( dom ); + return dom; + } + + + +// --------------------------------------------------------- +// CUniSmilModel::RemoveEmptySlides +// +// +// --------------------------------------------------------- +// +EXPORT_C void CUniSmilModel::RemoveEmptySlides() + { + TInt count = iSlideArray->Count(); + // Must be done from end to beginning because + // slides might be removed. + while ( count-- ) + { + if ( !iSlideArray->At( count )->ObjectCount() ) + { + RemoveSlide( count ); + } + } + } + + +// --------------------------------------------------------- +// CUniSmilModel::AddSlideL +// +// +// --------------------------------------------------------- +// +EXPORT_C void CUniSmilModel::AddSlideL( TInt aSlideNum ) + { + DoAddSlideL( aSlideNum ); + } + +// --------------------------------------------------------- +// CUniSmilModel::RemoveSlide +// +// +// --------------------------------------------------------- +// +EXPORT_C void CUniSmilModel::RemoveSlide( TInt aSlideNum ) + { + if ( !IsSlide( aSlideNum ) ) + { + //__ASSERT_DEBUG( EFalse, DataUtilsPanic( EMmsNotASlide ) ); + return; + } + CUniSmilSlide* slide = iSlideArray->At( aSlideNum ); + if ( slide->ObjectCount() ) + { + //__ASSERT_DEBUG( EFalse, DataUtilsPanic( EMmsSlideNotEmpty ) ); + return; + } + + iSlideArray->Delete( aSlideNum ); + delete slide; + //MsgDataUTILSLOGGER_WRITE( "CUniSmilModel: Empty slide removed." ); + iSizeEstimateUpToDate = EFalse; + } + +// --------------------------------------------------------- +// CUniSmilModel::MoveSlideL +// +// +// --------------------------------------------------------- +// +EXPORT_C void CUniSmilModel::MoveSlideL( TInt aSlideToMove, TInt aPlaceToMove ) + { + TInt slideCount = iSlideArray->Count(); + if ( !slideCount + || aSlideToMove < 0 + || aSlideToMove >= slideCount + || aSlideToMove == aPlaceToMove ) + { + return; + } + TInt place = Min( Max( 0, aPlaceToMove ), slideCount - 1 ); + CUniSmilSlide* slide = iSlideArray->At( aSlideToMove ); + + iSlideArray->Delete( aSlideToMove ); + iSlideArray->InsertL( place, slide ); + iSizeEstimateUpToDate = EFalse; + } + +// --------------------------------------------------------- +// SortSlidesL +// +// Sorts slides accoring to a separate comparison function +// called SortSlidesCompare(). +// +// Insertion sort algorithm. +// +// Notice! Intended to be used with SendAs when there +// are multiple slides - each slide containing only +// one object +// --------------------------------------------------------- +EXPORT_C void CUniSmilModel::SortSlidesL() + { + TInt i = 1; // index 1, i.e. second slide + TInt count = SlideCount(); + while ( i < count ) + { + CUniSmilSlide* slide1 = iSlideArray->At( i ); + TInt j = i - 1; + while ( j >= 0 ) + { + CUniSmilSlide* slide2 = iSlideArray->At( j ); + if ( SortSlidesCompare( slide1, slide2 ) > 0 ) + { + break; + } + j--; + } + j++; + if ( j < i ) + { + // slide1 was not in the right place + iSlideArray->Delete( i ); + iSlideArray->InsertL( j, slide1 ); + } + i++; + } + iSizeEstimateUpToDate = EFalse; + } + + +// --------------------------------------------------------- +// SortSlidesCompare +// +// Compares slides according to time. Most recent is greatest. +// +// Empty slides are greater than non-empty slides. +// If aSlide1 "is greater than" aSlide2 returns positive value. +// If aSlide1 "is smaller than" aSlide2 returns negative value. +// If aSlide1 and aSlide2 "are equal" returns zero. +// --------------------------------------------------------- +// +TInt CUniSmilModel::SortSlidesCompare( CUniSmilSlide* aSlide1, + CUniSmilSlide* aSlide2 ) + { + if ( !aSlide1->ObjectCount() ) + { + //if both are empty returns 0 + //if slide2 is non-empty -> slide1 "is greater" + return aSlide2->ObjectCount(); + } + else if ( !aSlide2->ObjectCount() ) + { + //empty slide is always "greatest" + return -1; + } + else + { + TTime time1; + TTime time2; + aSlide1->GetObjectByIndex( 0 )->MediaInfo()->ModificationTime( time1 ); + aSlide2->GetObjectByIndex( 0 )->MediaInfo()->ModificationTime( time2 ); + if ( time1 < time2 ) + { + return -1; + } + else if ( time1 == time2 ) + { + return 0; + } + else + { + return 1; + } + } + } + +// --------------------------------------------------------- +// CUniSmilModel::IsSlide +// +// +// --------------------------------------------------------- +// +EXPORT_C TBool CUniSmilModel::IsSlide( TInt aSlideNum ) const + { + if( aSlideNum >= 0 && + aSlideNum < iSlideArray->Count() ) + { + return ETrue; + } + return EFalse; + } + +// --------------------------------------------------------- +// CUniSmilModel::AddTextObjectL +// +// --------------------------------------------------------- +// +EXPORT_C CUniTextObject* CUniSmilModel::AddTextObjectL( + TInt aSlideNum, + CEikRichTextEditor* aText ) + { + CUniTextObject* obj = CUniTextObject::NewLC( iFs, iMtm, iData, aText ); + iObjectList.AddObjectL( obj ); + CleanupStack::Pop( obj ); + iSlideArray->At(aSlideNum)->AddObjectL( obj ); + iSizeEstimateUpToDate = EFalse; + return obj; + } + +// --------------------------------------------------------- +// CUniSmilModel::AddTempObjectL +// +// --------------------------------------------------------- +// +/* +EXPORT_C CUniObject* CUniSmilModel::AddTempObjectL( TInt aSlideNum, + CMsgMediaInfo* aMedia ) + { + if ( !IsSlide( aSlideNum ) ) + { + User::Leave( KErrArgument ); + } + + CUniObject* obj = CUniObject::NewLC( iFs, iMtm, iData, aMedia ); + + // Update model + iObjectList.AddObjectL( obj ); + CleanupStack::Pop( obj ); + iSlideArray->At( aSlideNum )->AddObjectL( obj ); + SetLayoutFromObjectTypeL( obj->MediaType() ); + iSizeEstimateUpToDate = EFalse; + return obj; + } +*/ + +// --------------------------------------------------------- +// CUniSmilModel::AddObjectL +// +// --------------------------------------------------------- +// +EXPORT_C CUniObject* CUniSmilModel::AddObjectL( MUniObjectSaveObserver& aObserver, + TInt aSlideNum, + CMsgMediaInfo* aMedia ) + { + if ( !IsSlide( aSlideNum ) ) + { + User::Leave( KErrArgument ); + } + + CUniObject* obj = CUniObject::NewLC( iFs, iMtm, iData, aMedia ); + + // Update model + iObjectList.AddObjectL( obj ); + CleanupStack::Pop( obj ); + obj->Save( aObserver, CMsvAttachment::EMsvLinkedFile ); + iSlideArray->At(aSlideNum)->AddObjectL( obj ); + iSizeEstimateUpToDate = EFalse; + return obj; + } + +// --------------------------------------------------------- +// CUniSmilModel::AddStoredObjectL +// +// --------------------------------------------------------- +// +EXPORT_C CUniObject* CUniSmilModel::AddStoredObjectL( TInt aSlideNum, + TMsvAttachmentId aAttachmentId, + CMsgMediaInfo* aMedia ) + { + if ( !IsSlide( aSlideNum ) ) + { + User::Leave( KErrArgument ); + } + + CMsvStore* store = iMtm.Entry().EditStoreL(); + CleanupStack::PushL( store ); + MMsvAttachmentManager& manager = store->AttachmentManagerL(); + MMsvAttachmentManagerSync& managerSync = store->AttachmentManagerExtensionsL(); + CMsvAttachment* attachment = manager.GetAttachmentInfoL( aAttachmentId ); + CleanupStack::PushL( attachment ); + + CUniObject* obj = NULL; + + if ( aMedia && + aMedia->MediaType() == EMsgMediaText ) + { + CMsgTextInfo* textInfo = static_cast( aMedia ); + obj = CUniTextObject::NewLC( iFs, iMtm, iData, textInfo, manager, *attachment ); + } + else + { + obj = CUniObject::NewLC( iFs, iMtm, iData, aMedia, manager, *attachment ); + } + managerSync.ModifyAttachmentInfoL( attachment ); + CleanupStack::Pop( 2, attachment ); //obj, attachment + CleanupStack::PushL( obj ); + store->CommitL(); + + // Update model + iObjectList.AddObjectL( obj ); + CleanupStack::Pop( obj ); + CleanupStack::PopAndDestroy( store ); + iSlideArray->At(aSlideNum)->AddObjectL( obj ); + iSizeEstimateUpToDate = EFalse; + return obj; + } + +// --------------------------------------------------------- +// CUniSmilModel::RemoveObjectL +// +// +// --------------------------------------------------------- +// +EXPORT_C void CUniSmilModel::RemoveObjectL( TInt aSlideNum, + CUniObject* aObject, + TBool aLeaveToStore/* = EFalse*/ ) + { + if ( !IsSlide( aSlideNum ) || + !iSlideArray->At( aSlideNum )->IsObject( aObject ) ) + { + return; + } + // TODO: Check that object exists on the slide. + + //if ( !IsObject( aSlideNum, aObjectType ) ) + // { + // return; + // } + DoRemoveObjectL( aSlideNum, aObject, aLeaveToStore ); + } + +// --------------------------------------------------------- +// CUniSmilModel::RemoveObjectByIndexL +// +// +// --------------------------------------------------------- +// +EXPORT_C void CUniSmilModel::RemoveObjectByIndexL( TInt aSlideNum, TInt aObjectNum ) + { + if ( !IsSlide( aSlideNum ) ) + { + return; + } + CUniObject* obj = iSlideArray->At( aSlideNum )->GetObjectByIndex( aObjectNum ); + DoRemoveObjectL( aSlideNum, obj ); + } + +// --------------------------------------------------------- +// CUniSmilModel::DoRemoveObjectL +// +// +// --------------------------------------------------------- +// +void CUniSmilModel::DoRemoveObjectL( TInt aSlideNum, CUniObject* aObject, TBool aLeaveToStore/* = EFalse*/ ) + { + //MsgDataUTILSLOGGER_ENTERFN( "CUniSmilModel : DoRemoveObjectL()" ); + + TBool removeObj = ( aObject->ReferenceCount() - 1 <= 0 ); + //if last reference was (will be) removed, remove from + //attachment list (and msg store) + if ( removeObj ) + { + //MsgDataUTILSLOGGER_WRITE( "CUniSmilModel: Removing from atta list and store." ); + iObjectList.RemoveObjectL( aObject, !aLeaveToStore ); + } + + CUniSmilSlide* slide = iSlideArray->At( aSlideNum ); + slide->RemoveObject( aObject ); + iSizeEstimateUpToDate = EFalse; + + if ( removeObj ) + { + delete aObject; + } + + //MsgDataUTILSLOGGER_LEAVEFN( "CUniSmilModel : DoRemoveObjectL()" ); + } + +// --------------------------------------------------------- +// CUniSmilModel::GetObject +// +// +// --------------------------------------------------------- +// +EXPORT_C CUniObject* CUniSmilModel::GetObjectByIndex( TInt aSlideNum, + TInt aObjectNum ) const + { + if( !IsSlide( aSlideNum ) ) + { + return NULL; + } + return iSlideArray->At( aSlideNum )->GetObjectByIndex( aObjectNum ); + } + +// --------------------------------------------------------- +// CUniSmilModel::GetObject +// +// +// --------------------------------------------------------- +// +EXPORT_C CUniObject* CUniSmilModel::GetObject( TInt aSlideNum, + TUniRegion aRegion ) const + { + if( !IsSlide( aSlideNum ) ) + { + return NULL; + } + return iSlideArray->At( aSlideNum )->GetObject( aRegion ); + } + +// --------------------------------------------------------- +// CUniSmilModel::SetLayoutL +// +// Mutator. +// --------------------------------------------------------- +// +EXPORT_C void CUniSmilModel::SetLayoutL( TUniLayout aNewLayout ) + { + iSlideLayout = aNewLayout; + TUint slideCnt = iSlideArray->Count(); + for (TUint i = 0; i < slideCnt; i++ ) + { + iSlideArray->At(i)->UpdateLayoutL( iSlideLayout ); + } + iSizeEstimateUpToDate = EFalse; + } + +// --------------------------------------------------------- +// CUniSmilModel::SmilComposeSize() +// +// Total size +// --------------------------------------------------------- +// +EXPORT_C TInt CUniSmilModel::SmilComposeSize() + { + TInt slideCount = iSlideArray->Count(); + if ( !slideCount ) + { + return 0; + } + if ( !iSizeEstimateUpToDate ) + { + iSizeEstimate = SmilComposeSize( + slideCount, + iSlideArray->At( slideCount - 1 )->ObjectCount() ); + iSizeEstimateUpToDate = ETrue; + } + return iSizeEstimate; + } + + +// --------------------------------------------------------- +// CUniSmilModel::SmilComposeSize() +// +// Size from beginning +// --------------------------------------------------------- +// +EXPORT_C TInt CUniSmilModel::SmilComposeSize( TInt aToSlideNum, TInt aToObjectNum ) + { + //__ASSERT_DEBUG( + // ( aToSlideNum > 0 && aToSlideNum <= iSlideArray->Count() ), + // DataUtilsPanic( EMmsIllegalSlide ) ); + //__ASSERT_DEBUG( + // ( aToObjectNum <= iSlideArray->At( aToSlideNum - 1 )->ObjectCount() ), + // DataUtilsPanic( EMmsIllegalObject ) ); + + TInt size( KSizeMandatorySmilTags ); + TBool imageRegion = EFalse; + TBool textRegion = EFalse; + + for ( TInt i = 0; i < aToSlideNum; ++i ) + { + CUniSmilSlide* slide = iSlideArray->At( i ); + TInt toObj = slide->ObjectCount(); + if ( i == aToSlideNum - 1 ) + { + toObj = aToObjectNum; + } + if ( !toObj ) + { + //No objects on the slide + size += KSizeEmptyPar; + } + else + { + //One or more objects + size += KSizeNonEmptyPar; + } + for ( TInt ii = 0; ii < toObj; ++ii ) + { + CUniObject* obj = slide->GetObjectByIndex( ii ); + switch ( obj->MediaType() ) + { + case EMsgMediaAudio: + size += KSizeAudioTag; + break; + case EMsgMediaImage: + case EMsgMediaSvg: + size += KSizeImageTag; + imageRegion = ETrue; + break; + case EMsgMediaText: + case EMsgMediaXhtml: + size += KSizeTextTag; + textRegion = ETrue; + break; + case EMsgMediaVideo: + size += KSizeVideoTag; + imageRegion = ETrue; + break; + default: + //Should never come here + //Don't increase size + break; + } + } + } + + TInt regions = 0; + if ( imageRegion ) + { + regions++; + } + if ( textRegion ) + { + regions++; + } + switch ( regions ) + { + case 1: + size += KSizeHeadOneRegion; + break; + case 2: + size += KSizeHeadTwoRegions; + break; + default: + //Should be zero + //Don't increase size + break; + } + return size; + } + + +// --------------------------------------------------------- +// CUniSmilModel::ObjectCount +// +// Accessor +// --------------------------------------------------------- +// +EXPORT_C TInt CUniSmilModel::ObjectCount() const + { + TInt objCnt(0); + + for ( TInt i = iSlideArray->Count(); --i >= 0 ;) + { + objCnt += iSlideArray->At(i)->ObjectCount(); + } + + return objCnt; + } + + +// --------------------------------------------------------- +// CUniSmilModel::SlideObjectCount +// +// Accessor +// --------------------------------------------------------- +// +EXPORT_C TInt CUniSmilModel::SlideObjectCount(TInt aSlideNum) const + { + if ( !IsSlide(aSlideNum) ) + { + return 0; + } + + return iSlideArray->At( aSlideNum )->ObjectCount(); + } + +//********************************************************** +//* +//* CONTRUCTION FUNCTIONS +//* +//********************************************************** + + +// --------------------------------------------------------- +// CUniSmilModel::ConstructL +// +// 2nd phase constructor. +// --------------------------------------------------------- +// +void CUniSmilModel::ConstructL() + { + iSlideArray = new ( ELeave ) CSmilSlideArray( KSlideArrayGranularity ); + iTextRegionId.Set( KNullDesC ); + iImageRegionId.Set( KNullDesC ); + + // Set default layout to "Text first" + iSlideLayout = EUniTextFirst; + + // Fix for NSIA-6CKFJA. Sets same screen size that SMIL Player is using. MH +/* + TRect appWindowRect; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EApplicationWindow, appWindowRect ); + + TAknLayoutRect mainPane; + mainPane.LayoutRect( appWindowRect, AknLayoutScalable_Avkon::main_pane( 0 ) ); + + TAknLayoutRect mainSmilPane; + mainSmilPane.LayoutRect( mainPane.Rect(), AknLayoutScalable_Apps::main_smil_pane() ); + + iScreenSize = mainSmilPane.Rect().Size(); +*/ + } + +// --------------------------------------------------------- +// CUniSmilModel::Reset +// +// +// --------------------------------------------------------- +// +void CUniSmilModel::Reset() + { + iParseResult = 0; + iSlideLayout = EUniTextFirst; + iTextRegionId.Set( KNullDesC ); + iImageRegionId.Set( KNullDesC ); + if ( iSlideArray ) + { + // Reset slide array + iSlideArray->ResetAndDestroy(); + } + TInt objCount = iObjectList.Count(); + while ( objCount-- ) + { + iObjectList.GetByIndex( objCount )->SetReferenceCount( 0 ); + } + } + +// --------------------------------------------------------- +// CUniSmilModel::DoPresentationFromDomL +// +// When this functios is called DOM should be validated as MMS SMIL. +// --------------------------------------------------------- +// +void CUniSmilModel::DoPresentationFromDomL( CMDXMLDocument* aDom ) + { + RemoveMetaTagsAndComments( aDom ); + // Resolve layout of the slide + iSlideLayout = GetMmsSmilLayout( aDom ); + + CMDXMLNode* node = GetNode( aDom, KSMILWREleBody ); + + if ( node && node->FirstChild() ) + { + // Only one slide in the message since no tag found + if ( node->FirstChild()->NodeName().Compare( KSMILWRElePar ) != 0 ) + { + // Add slide - the one and only + AddSlideFromDomL( node ); + } + + // Other node types than not possible as this is MMS SMIL. + else + { + // Traverse through every page + CMDXMLNode* page = node->FirstChild(); + while ( page ) + { + AddSlideFromDomL( page ); + // Go to next page. + page = page->NextSibling(); + } + } + } + } + +// --------------------------------------------------------- +// CUniSmilModel::AddSlideFromDomL +// +// --------------------------------------------------------- +// +void CUniSmilModel::AddSlideFromDomL( CMDXMLNode* aPage ) + { + CUniObject* obj = NULL; + CUniSmilSlide* slide = DoAddSlideL(); + CMDXMLNode* node = aPage->FirstChild(); + + // Traverse through every object in page. + while ( node ) + { + if ( UniSmilUtils::IsMediaElem( node ) ) + { + obj = iObjectList.GetByNodeL( node ); + if ( obj ) + { + if ( slide ) + { + obj->SetMediaTypeBySmilTag( UniSmilUtils::MediaElemType( node ) ); + AddObjectFromDomL( + slide, + obj, + GetRegionType( node ) ); + } + else + { + iObjectList.RemoveObjectL( obj, ETrue ); + delete obj; + iParseResult |= EObjectRemoved; + } + } + } + node = node->NextSibling(); + } + } + + +// --------------------------------------------------------- +// CUniSmilModel::AddObjectFromDomL +// +// --------------------------------------------------------- +// +void CUniSmilModel::AddObjectFromDomL( CUniSmilSlide* aSlide, + CUniObject* aObj, + TUniRegion aRegion ) + { + if ( !aObj ) + { + // Smil presentation refers to attachment that's not in the message + iParseResult |= EMissingObjects; + // Not actually error that should prevent message viewing. + return; + } + + TMsgMediaType mediaBySmilTag = aObj->MediaTypeBySmilTag(); + TMsgMediaType media = aObj->MediaType(); + + if ( media == EMsgMediaSvg ) + { + // SVG considered an image. + // (...because "image" tag is used for SVG while composing SMIL.) + media = EMsgMediaImage; + } + + if ( media == EMsgMediaXhtml ) + { + // XHTML is considered as a text. + // (...because "text" tag is used for xhtml while composing SMIL.) + media = EMsgMediaText; + } + + if ( !( media == EMsgMediaText || + media == EMsgMediaImage || + media == EMsgMediaAudio || + media == EMsgMediaVideo ) ) + { + // Unsupported format + //MsgDataUTILSLOGGER_WRITE( "CUniSmilModel: Parsing: Message has unsupported objects." ); + iParseResult |= EUnsupportedObjects; + // Not actually error that should prevent message viewing. + } + + // NOTE: Smil standard allows references, but conformance + // Data forbids these. + if ( media != EMsgMediaUnknown && //Unknown matches anything + mediaBySmilTag != EMsgMediaRef && // matches anything + media != mediaBySmilTag ) + { + // SMIL does not describe content as it should + //MsgDataUTILSLOGGER_WRITE( "CUniSmilModel: Parsing: Smil object type differs from message object type." ); + iParseResult |= EBadlyReferencedObjects; + } + + TUniRegion regionBySmilTag = EUniRegionUnresolved; + switch ( mediaBySmilTag ) + { + case EMsgMediaAudio: + { + regionBySmilTag = EUniRegionAudio; + break; + } + case EMsgMediaImage: + case EMsgMediaVideo: + { + regionBySmilTag = EUniRegionImage; + break; + } + case EMsgMediaText: + { + regionBySmilTag = EUniRegionText; + break; + } + default: + break; + } + + TUniRegion regionByMediaType = EUniRegionUnresolved; + switch ( media ) + { + case EMsgMediaAudio: + { + regionByMediaType = EUniRegionAudio; + break; + } + case EMsgMediaImage: + case EMsgMediaVideo: + { + regionByMediaType = EUniRegionImage; + break; + } + case EMsgMediaText: + { + regionByMediaType = EUniRegionText; + break; + } + default: + break; + } + + // Check that region type matches object media type + if ( aRegion != EUniRegionUnresolved && + regionByMediaType != EUniRegionUnresolved && + aRegion != regionByMediaType ) + { + iParseResult |= ERegionMediaTypeMismatch; + aRegion = regionByMediaType; + } + else if ( regionByMediaType == EUniRegionUnresolved && + aRegion == EUniRegionText ) + { + // do not put every possible content into text reqion + iParseResult |= ERegionMediaTypeMismatch; + aRegion = EUniRegionUnresolved; + } + else if ( aRegion == EUniRegionUnresolved ) + { + // If region couldn't be resolved from the region tag + // follow the media type. If that's not possible follow + // the smil media tag name. If everything fails + // "aRegion" will remain "unresolved". + aRegion = ( regionByMediaType != EUniRegionUnresolved ) + ? regionByMediaType + : regionBySmilTag; + } + + CMsgMediaInfo* mediaInfo = aObj->MediaInfo(); + // DRM2 must be put into object view in the viewer + if ( mediaInfo && + ( /*mediaInfo->HandlerApplicationUid().iUid == 0 ||*/ + aObj->MediaInfo()->Protection() & EFileProtDrm2 ) ) + { + aRegion = EUniRegionUnresolved; + } + // else - should not occur + + if ( aRegion != EUniRegionUnresolved ) + { + aSlide->AddObjectL( aObj, aRegion ); + iSizeEstimateUpToDate = EFalse; + } + else + { + iParseResult |= EBadlyReferencedObjects; + // -> Something unknown in the SMIL. + // -> Don't add. Will be handled as an attachment. + } + } + +// --------------------------------------------------------- +// CUniSmilModel::IsMessageSlide +// +// --------------------------------------------------------- +// +TBool CUniSmilModel::IsMessageSlide() + { + TInt imageCnt( 0 ); + TInt audioCnt( 0 ); + TInt textCnt( 0 ); + + for ( TInt i = iObjectList.Count(); --i >= 0 ; ) + { + switch( iObjectList.GetByIndex(i)->MediaType() ) + { + case EMsgMediaSvg: + case EMsgMediaImage: + imageCnt++; + break; + + case EMsgMediaAudio: + audioCnt++; + break; + + case EMsgMediaText: + case EMsgMediaXhtml: + textCnt++; + break; + + case EMsgMediaVideo: + //always consider video as image + audio + imageCnt++; + audioCnt++; + break; + + case EMsgMediaUnknown: + default: + // Unsupported objects will be put into attachment list + // in FindAttachmentsL() + break; + } // switch + } // for + + if ( imageCnt > 1 || audioCnt > 1 || textCnt > 1 ) + { + return EFalse; + } + + return ETrue; + } + +// --------------------------------------------------------- +// DoNoSmilOneSlideL +// +// NOTE: Message should be a valid slide at this point. +// --------------------------------------------------------- +// +void CUniSmilModel::DoNoSmilOneSlideL() + { + CUniSmilSlide* slide = NULL; + + for ( TInt i = 0; i < iObjectList.Count(); ++i ) + { + CUniObject* obj = iObjectList.GetByIndex(i); + TMsgMediaType media = obj->MediaType(); + CMsgMediaInfo* mediaInfo = obj->MediaInfo(); + + // DRM2 must be put into objects view in the viewer + if ( ( media == EMsgMediaText || + media == EMsgMediaXhtml || + media == EMsgMediaImage || + media == EMsgMediaSvg || + media == EMsgMediaAudio || + media == EMsgMediaVideo ) && + mediaInfo && + /*mediaInfo->HandlerApplicationUid().iUid &&*/ + !( obj->MediaInfo()->Protection() & EFileProtDrm2 ) ) + { + if ( !slide ) + { + // Add slide + slide = DoAddSlideL(); + } + slide->AddObjectL( obj ); + } + } + } + +// --------------------------------------------------------- +// DoNoSmilManySlideL +// +// +// --------------------------------------------------------- +// +void CUniSmilModel::DoNoSmilManySlideL() + { + for ( TInt i = 0; i < iObjectList.Count(); ++i ) + { + CUniObject* obj = iObjectList.GetByIndex(i); + if (obj == NULL) + return; + + TMsgMediaType media = obj->MediaType(); + CMsgMediaInfo* mediaInfo = obj->MediaInfo(); + + // DRM2 must be put into objects view in the viewer + if ( ( media == EMsgMediaText || + media == EMsgMediaXhtml || + media == EMsgMediaImage || + media == EMsgMediaSvg || + media == EMsgMediaAudio || + media == EMsgMediaVideo ) && + mediaInfo && + /*mediaInfo->HandlerApplicationUid().iUid &&*/ + !( obj->MediaInfo()->Protection() & EFileProtDrm2 ) ) + { + CUniSmilSlide* slide = DoAddSlideL(); + if ( slide ) + { + slide->AddObjectL( obj ); + } + else + { + iObjectList.RemoveObjectL( obj, ETrue ); + delete obj; + iParseResult |= EObjectRemoved; + i--; + } + } + } + } + +// --------------------------------------------------------- +// DoAddSlideL +// +// --------------------------------------------------------- +// +CUniSmilSlide* CUniSmilModel::DoAddSlideL( TInt aSlideNum /*= -1*/ ) + { + CUniSmilSlide* newSlide = NULL; + if ( iMaxSlideCount == 0 || + iSlideArray->Count() < iMaxSlideCount ) + { + newSlide = CUniSmilSlide::NewLC( iSlideLayout ); + if ( aSlideNum == -1 || aSlideNum >= iSlideArray->Count() ) + { + // Add to end of array + iSlideArray->AppendL( newSlide ); + } + else + { + iSlideArray->InsertL( aSlideNum, newSlide ); + } + CleanupStack::Pop( newSlide ); // newSlide + iSizeEstimateUpToDate = EFalse; + } + return newSlide; + } + +// --------------------------------------------------------- +// CUniSmilModel::CreateHeadL +// +// --------------------------------------------------------- +void CUniSmilModel::CreateHeadL( CMDXMLDocument* aDom, CMDXMLElement* aRoot ) + { + + TPtrC name( KSMILWREleHead ); + // Create Head node + CMDXMLElement* ele = CMDXMLElement::NewLC( ETrue, aDom, name ); + // Append Head in Root node + aRoot->AppendChild( ele ); + + // Create Layout + CreateLayoutL( aDom, ele ); + CleanupStack::Pop( ele ); + } + +// --------------------------------------------------------- +// CUniSmilModel::ChangeLayoutL +// +// --------------------------------------------------------- +EXPORT_C TBool CUniSmilModel::ChangeLayoutL( CMDXMLDocument* aDom ) + { + TBool retVal = EFalse; + if ( aDom ) + { + CMDXMLElement* layout = (CMDXMLElement*) GetNode( aDom, KSMILWREleLayout ); + if ( !layout ) + { + // No layout. Nothing to do without composing + // SMIL from scratch. + return EFalse; + } + CMDXMLElement* head = (CMDXMLElement*) layout->ParentNode(); + + // Read default smil parameters + if( !iSmilParams ) + { + iSmilParams = CUniSmilParams::NewL( iFs ); + } + CMDXMLElement* rootLayout = NULL; + CMDXMLElement* textRegion = NULL; + CMDXMLElement* imageRegion = NULL; + + GetLayoutElements( + layout, + rootLayout, + textRegion, + imageRegion ); + + if ( rootLayout ) + { + rootLayout->RemoveAttribute( KSMILWRParaWidth ); + rootLayout->RemoveAttribute( KSMILWRParaHeight ); + } + + if ( textRegion ) + { + textRegion->RemoveAttribute( KSMILWRParaFit ); + textRegion->RemoveAttribute( KSMILWRParaTop ); + textRegion->RemoveAttribute( KSMILWRParaLeft ); + textRegion->RemoveAttribute( KSMILWRParaBottom ); + textRegion->RemoveAttribute( KSMILWRParaRight ); + textRegion->RemoveAttribute( KSMILWRParaHeight ); + textRegion->RemoveAttribute( KSMILWRParaWidth ); + } + if ( imageRegion ) + { + imageRegion->RemoveAttribute( KSMILWRParaFit ); + imageRegion->RemoveAttribute( KSMILWRParaTop ); + imageRegion->RemoveAttribute( KSMILWRParaLeft ); + imageRegion->RemoveAttribute( KSMILWRParaBottom ); + imageRegion->RemoveAttribute( KSMILWRParaRight ); + imageRegion->RemoveAttribute( KSMILWRParaHeight ); + imageRegion->RemoveAttribute( KSMILWRParaWidth ); + } + + CreateLayoutL( aDom, head, rootLayout, layout, textRegion, imageRegion ); + retVal = ETrue; + } + return retVal; + } + +// --------------------------------------------------------- +// CUniSmilModel::CorrectTimingL +// +// --------------------------------------------------------- +EXPORT_C TBool CUniSmilModel::CorrectTimingL( CMDXMLDocument* aDom ) + { + if ( aDom ) + { + CMDXMLElement* body = static_cast( GetNode( aDom, KSMILWREleBody ) ); + if ( !body ) + { + // No body. Nothing to do without composing + // SMIL from scratch. + return EFalse; + } + + if ( body && body->FirstChild() ) + { + // Only one slide in the message since no tag found + if ( body->FirstChild()->NodeName().Compare( KSMILWRElePar ) != 0 && + !body->FirstChild()->NextSibling() ) + { + // Correct slide timing to the one and only slide + CorrectSlideTimingL( body ); + } + // Other node types than not possible as this is MMS SMIL. + else + { + // Traverse through every page + CMDXMLNode* page = body->FirstChild(); + + while ( page != NULL ) + { + if ( page->NodeName().Compare( KSMILWRElePar ) == 0 && + page->NodeType() == CMDXMLNode::EElementNode ) + { + CMDXMLElement* pageElement = static_cast( page ); + if ( !TimingSpecified( pageElement ) ) + { + CorrectSlideTimingL( pageElement ); + } + } + // Go to next page. + page = page->NextSibling(); + } + } + } + } + + return ETrue; + } + +// --------------------------------------------------------- +// CUniSmilModel::IsSupportedMediaType +// +// --------------------------------------------------------- +EXPORT_C TBool CUniSmilModel::IsSupportedMediaType( TMsgMediaType aMediaType ) const + { + if ( aMediaType == EMsgMediaAudio || + aMediaType == EMsgMediaImage || + aMediaType == EMsgMediaSvg || + aMediaType == EMsgMediaXhtml || + aMediaType == EMsgMediaVideo || + aMediaType == EMsgMediaText ) + { + return ETrue; + } + else + { + return EFalse; + } + } + + +// --------------------------------------------------------- +// CUniSmilModel::CreateLayoutL +// +// --------------------------------------------------------- +void CUniSmilModel::CreateLayoutL( CMDXMLDocument* aDom, + CMDXMLElement* aRoot, + CMDXMLElement* aRootLayout, + CMDXMLElement* aLayout, + CMDXMLElement* aTextRegion, + CMDXMLElement* aImageRegion ) + { + + TPtrC name( KSMILWREleLayout ); + // Create Layout node + if ( !aLayout ) + { + aLayout = CMDXMLElement::NewLC( ETrue, aDom, name ); + // Append Layout in Head + aRoot->InsertBefore( NULL, aLayout ); + CleanupStack::Pop(); // layout + } + + // Do we have images and text-objects on a slide with other media objects and + // do we have any video + TInt hasVideo( 0 ); + TInt hasImage( 0 ); + TInt hasText( 0 ); + + // Do we have media, which is alone on a slide? Also calculate how medias are alone on a slide. + // Video overrides any image region, it is not needed + TInt hasImageOneAndOnly( 0 ); + TInt hasTextOneAndOnly( 0 ); + + for( TInt i = 0; i < iSlideArray->Count(); ++i ) + { + CUniSmilSlide* s = iSlideArray->At( i ); + TBool hasVideoOnThisSlide = EFalse; + TBool hasImageOnThisSlide = EFalse; + TBool hasTextOnThisSlide = EFalse; + + CUniObject* imageRegionObj = s->GetObject( EUniRegionImage ); + if ( imageRegionObj ) + { + if ( imageRegionObj->MediaType() == EMsgMediaVideo ) + { + hasVideoOnThisSlide = ETrue; + hasVideo++; + } + else + { + hasImageOnThisSlide = ETrue; + hasImage++; + } + } + if ( s->GetObject( EUniRegionText ) ) + { + hasTextOnThisSlide = ETrue; + hasText++; + } + + if ( !hasVideoOnThisSlide + && hasImageOnThisSlide + && !hasTextOnThisSlide ) + { + hasImageOneAndOnly++; + } + if ( !hasVideoOnThisSlide + && !hasImageOnThisSlide + && hasTextOnThisSlide ) + { + hasTextOneAndOnly++; + } + } + + // we know: + // how many media objects of each type there are totally in the message and + // whether some regions have alone on a slide + // we conclude: + // if a media object has been alone on the slide and there is + // only one media object in the whole message + // or if there are several images without other content or several texts on several slides + // without other content then the media object is alone on a slide + // and is only one of its type in the message + // but: video is exception. It handling is ignored here. Following big if() statement handles it + // by handling video before exception case resolved + if ( hasImageOneAndOnly == hasImage ) + { + // image does not occur with some other region + hasImage = 0; + } + else + { + // image occurs with some other region on some slide + hasImageOneAndOnly = 0; + } + + if ( hasTextOneAndOnly == hasText ) + { + // text does not occur with some other region + hasText = 0; + } + else + { + // text occurs with some other region on some slide + hasTextOneAndOnly = 0; + } + +/* + TBool isLandscape( Layout_Meta_Data::IsLandscapeOrientation() ); + TBool useSubQCIF( EFalse); + + TRect appWin; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EApplicationWindow, appWin ); + TAknLayoutRect mainPane; + + if ( isLandscape ) + { + mainPane.LayoutRect( + appWin, + AknLayoutScalable_Apps::main_pane( 4 ).LayoutLine() ); + } + else + { + mainPane.LayoutRect( + appWin, + AknLayoutScalable_Apps::main_pane( 6 ).LayoutLine() ); + } + + if ( isLandscape && + appWin.Height() == KSizeLowResWidth && + appWin.Width() == KSizeLowResHeight ) + { + useSubQCIF = ETrue; + } + + TAknLayoutRect smilLayout; + smilLayout.LayoutRect( + mainPane.Rect(), + AknLayoutScalable_Apps::main_smil2_pane().LayoutLine() ); + + TAknLayoutRect rootLayout; + TAknLayoutRect textLayout; + TAknLayoutRect imageLayout; + TAknLayoutRect videoLayout; + + // For reader about notation: + // x + y == x and y are on the different slide + // x,y == x and y are on the same slide + // { } item can occur 0 or more times + if ( hasText && hasImage && !hasVideo ) // text, image - no video + { + if ( isLandscape ) // landscape text & image + { + if ( iSlideLayout == EUniTextFirst ) + { + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 4 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 4 ).LayoutLine() ); + imageLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_image_pane( 3 ).LayoutLine() ); + } + else + { + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 2 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 2 ).LayoutLine() ); + imageLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_image_pane( 1 ).LayoutLine() ); + } + } + else // portrait text & image + { + if ( iSlideLayout == EUniTextFirst ) + { + // Option 3 in the layout spec + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 3 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 3 ).LayoutLine() ); + imageLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_image_pane( 2 ).LayoutLine() ); + } + else + { + // Option 1 + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 1 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 1 ).LayoutLine() ); + imageLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_image_pane( 0 ).LayoutLine() ); + } + } + } + else if ( hasText && hasVideo ) // text, video or text, image + video + { + if ( isLandscape && useSubQCIF ) // landscape subQCIF text & video + { + if ( iSlideLayout == EUniTextFirst ) + { + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 13 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 10 ).LayoutLine() ); + videoLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_video_pane( 7 ).LayoutLine() ); + } + else + { + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 12 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 9 ).LayoutLine() ); + videoLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_video_pane( 6 ).LayoutLine() ); + } + } + else if ( isLandscape && !useSubQCIF ) // landscape QCIF text & video + { + if ( iSlideLayout == EUniTextFirst ) + { + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 10 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 8 ).LayoutLine() ); + videoLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_video_pane( 4 ).LayoutLine() ); + } + else + { + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 9 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 7 ).LayoutLine() ); + videoLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_video_pane( 3 ).LayoutLine() ); + } + } + else // portrait QCIF text & video + { + if ( iSlideLayout == EUniTextFirst ) + { + // Option 8 + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 8 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 6 ).LayoutLine() ); + videoLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_video_pane( 2 ).LayoutLine() ); + } + else + { + // Option 6 + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 6 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 5 ).LayoutLine() ); + videoLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_video_pane( 0 ).LayoutLine() ); + } + } + } + // cases left: + // - 1) text {+ text} + // - 2) text {+ text} + video + // - 3) text {+ text} + image { + image } + // - 4) image {+ image} + video, no text + // - 5) image {+ image} + // - 6) video + // - no visual media content + else if ( hasVideo ) + { + // 2) 'text {+ text} + video', 4) 'image {+ image} + video, no text' or 6) 'video' + if ( isLandscape ) + { + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 11 ).LayoutLine() ); + videoLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_video_pane( 5 ).LayoutLine() ); + } + else + { + // Option 7 + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 7 ).LayoutLine() ); + videoLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_video_pane( 1 ).LayoutLine() ); + } + + if ( hasTextOneAndOnly ) // + text + { + // Option 0 + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 0 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 0 ).LayoutLine() ); + } + + } + else if ( hasTextOneAndOnly + || hasImageOneAndOnly ) + { + // 1) text {+ text}, 3) text {+ text} + image { + image ), 5) image {+ image} + if ( hasTextOneAndOnly ) // text + { + // Option 0 + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 0 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 0 ).LayoutLine() ); + } + + // no else - rootLayouts are same + if ( hasImageOneAndOnly ) // image + { + // Option 5 + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 5 ).LayoutLine() ); + imageLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_image_pane( 4 ).LayoutLine() ); + } + } + else // empty + { + rootLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_root_pane( 0 ).LayoutLine() ); + textLayout.LayoutRect( + smilLayout.Rect(), + AknLayoutScalable_Apps::smil2_text_pane( 0 ).LayoutLine() ); + } + + iSmilParams->iComposeParams->iDisplayHeight = rootLayout.Rect().Height(); + iSmilParams->iComposeParams->iDisplayWidth = rootLayout.Rect().Width(); + + // it does not matter anymore whether object is alone on the slide. + // Use one variable only in the if() statements + if ( hasImage || hasImageOneAndOnly ) + { + hasImage = 1; + } + if ( hasText || hasTextOneAndOnly ) + { + hasText = 1; + } + + if ( hasText ) + { + iSmilParams->iTextRegionParams->iSize = textLayout.Rect().Size(); + iSmilParams->iTextRegionParams->iTopLeft = + textLayout.Rect().iTl - rootLayout.Rect().iTl; + } + if ( hasImage || hasVideo ) + { + if ( hasVideo ) + { + iSmilParams->iImageRegionParams->iSize = videoLayout.Rect().Size(); + iSmilParams->iImageRegionParams->iTopLeft = + videoLayout.Rect().iTl - rootLayout.Rect().iTl; + } + else + { + iSmilParams->iImageRegionParams->iSize = imageLayout.Rect().Size(); + iSmilParams->iImageRegionParams->iTopLeft = + imageLayout.Rect().iTl - rootLayout.Rect().iTl; + } + } + +*/ + + // Set Region IDs to defaults + if ( !iImageRegionId.Length() ) + { + iImageRegionId.Set( KSMILWRRegIDImage ); + } + if ( !iTextRegionId.Length() ) + { + iTextRegionId.Set( KSMILWRRegIDText ); + } + + // Create root layout + name.Set( KSMILWREleRoot_layout ); + TBool rlPop = EFalse; + if ( !aRootLayout ) + { + aRootLayout = CMDXMLElement::NewLC( EFalse, aDom, name ); + rlPop = ETrue; + } + // Set root layout parameters (attributes) + TBuf16<20> val; + val.Zero(); + val.Format( KSmilIntFormat, iSmilParams->iComposeParams->iDisplayWidth ); + aRootLayout->SetAttributeL( KSMILWRParaWidth,val ); + val.Zero(); + val.Format( KSmilIntFormat, iSmilParams->iComposeParams->iDisplayHeight ); + aRootLayout->SetAttributeL( KSMILWRParaHeight, val ); + if ( rlPop ) + { + // Append root layout in Layout + aLayout->AppendChild( aRootLayout ); + CleanupStack::Pop( aRootLayout ); + } + + // Create Image region (if needed) + name.Set( KSMILWREleRegion ); + if ( hasImage || hasVideo ) + { + TBool imgPop = EFalse; + if ( !aImageRegion ) + { + aImageRegion = CMDXMLElement::NewLC( EFalse, aDom, name ); + imgPop = ETrue; + } + // Set Image region attributes + aImageRegion->SetAttributeL( KSMILWRParaId, iImageRegionId ); + val.Zero(); + val.Format( KSmilIntFormat, iSmilParams->iImageRegionParams->Width() ); + aImageRegion->SetAttributeL( KSMILWRParaWidth, val ); + val.Zero(); + val.Format( KSmilIntFormat, iSmilParams->iImageRegionParams->Height() ); + aImageRegion->SetAttributeL( KSMILWRParaHeight, val ); + val.Zero(); + val.Format( KSmilIntFormat, iSmilParams->iImageRegionParams->Top() ); + aImageRegion->SetAttributeL( KSMILWRParaTop, val ); + val.Zero(); + val.Format( KSmilIntFormat, iSmilParams->iImageRegionParams->Left() ); + aImageRegion->SetAttributeL( KSMILWRParaLeft, val ); + aImageRegion->SetAttributeL( KSMILWRParaFit, iSmilParams->iImageRegionParams->iFit->Des() ); + if ( imgPop ) + { + // Append region in Layout + aLayout->AppendChild( aImageRegion ); // Ownership to dom + CleanupStack::Pop( aImageRegion ); + } + } + + // Create Text region (if needed) + if ( hasText ) + { + TBool txtPop = EFalse; + if ( !aTextRegion ) + { + aTextRegion = CMDXMLElement::NewLC( EFalse, aDom, name ); + txtPop = ETrue; + } + // Set Text region attributes + aTextRegion->SetAttributeL( KSMILWRParaId, iTextRegionId ); + val.Zero(); + val.Format( KSmilIntFormat, iSmilParams->iTextRegionParams->Width() ); + aTextRegion->SetAttributeL( KSMILWRParaWidth, val ); + val.Zero(); + val.Format( KSmilIntFormat, iSmilParams->iTextRegionParams->Height() ); + aTextRegion->SetAttributeL( KSMILWRParaHeight, val ); + val.Zero(); + val.Format( KSmilIntFormat, iSmilParams->iTextRegionParams->Top() ); + aTextRegion->SetAttributeL( KSMILWRParaTop, val ); + val.Zero(); + val.Format( KSmilIntFormat, iSmilParams->iTextRegionParams->Left() ); + aTextRegion->SetAttributeL( KSMILWRParaLeft, val ); + aTextRegion->SetAttributeL( KSMILWRParaFit, iSmilParams->iTextRegionParams->iFit->Des() ); + if ( txtPop ) + { + // Append region in Layout + aLayout->AppendChild( aTextRegion ); // Ownership to dom + CleanupStack::Pop( aTextRegion ); + } + } + } + +// --------------------------------------------------------- +// CUniSmilModel::CreateBodyL +// +// --------------------------------------------------------- +void CUniSmilModel::CreateBodyL( CMDXMLDocument* aDom, CMDXMLElement* aRoot ) + { + TPtrC name( KSMILWREleBody ); + // Create Body node + CMDXMLElement* body = CMDXMLElement::NewLC( ETrue, aDom, name ); + // Append + aRoot->AppendChild( body ); + CleanupStack::Pop( body ); + + // For each slide + for( TInt slide = 0; slide < iSlideArray->Count(); ++slide ) + { + // Create par + CreateParL( aDom, body, slide ); + } + + } + +// --------------------------------------------------------- +// CUniSmilModel::CreateParL +// +// --------------------------------------------------------- +void CUniSmilModel::CreateParL( CMDXMLDocument* aDom, CMDXMLElement* aRoot, TInt aSlide ) + { + TPtrC name( KSMILWRElePar ); + // Create par node + CMDXMLElement* ele = CMDXMLElement::NewLC( ETrue, aDom, name ); + // Append + + // Get default page duration. + TInt slideDur = iSmilParams->iComposeParams->iSlideDuration; + TInt objDur = 0; + TBool unresolvedDur = EFalse; + + CUniSmilSlide* s = iSlideArray->At( aSlide ); + + // For each object in slide + for ( TInt i = s->ObjectCount(); --i >= 0; ) + { + // Create Item + CUniObject* obj = s->GetObjectByIndex( i ); + objDur = CreateItemL( aDom, ele, obj ); + if ( !obj->MediaInfo()->Parsed() && + ( obj->MediaType() == EMsgMediaAudio || + obj->MediaType() == EMsgMediaVideo ) ) + { + unresolvedDur = ETrue; + } + else + { + slideDur = Max( slideDur, objDur ); + } + } + + if ( !unresolvedDur ) + { + TBuf16<20> val; + val.Zero(); + val.Format( KSmilMsecFormat, slideDur ); + + // Set par attributes + ele->SetAttributeL( KSMILWRParaDur, val ); + } + aRoot->AppendChild( ele ); // Ownership to dom + CleanupStack::Pop( ele ); + } + +// --------------------------------------------------------- +// CUniSmilModel::CreateItemL +// +// --------------------------------------------------------- +TInt CUniSmilModel::CreateItemL( CMDXMLDocument* aDom, CMDXMLElement* aRoot, CUniObject* aObj ) + { + CMDXMLElement* ele = NULL; + TPtrC name( KNullDesC ); + + // Create mediaobject node + switch ( aObj->Region() ) + { + case EUniRegionImage: + { + if ( aObj->MediaType() == EMsgMediaVideo ) + { + name.Set( KSMILWREleVideo ); + ele = CMDXMLElement::NewLC( EFalse, aDom, name ); + ele->SetAttributeL( KSMILWRParaRegion, KSMILWRRegIDImage ); + } + else + { + // Considered an image - includes also SVG + name.Set( KSMILWREleImg ); + ele = CMDXMLElement::NewLC( EFalse, aDom, name ); + ele->SetAttributeL( KSMILWRParaRegion, KSMILWRRegIDImage ); + } + } + break; + case EUniRegionText: + { + name.Set( KSMILWREleText ); + ele = CMDXMLElement::NewLC( EFalse, aDom, name ); + ele->SetAttributeL( KSMILWRParaRegion, KSMILWRRegIDText ); + } + break; + case EUniRegionAudio: + { + name.Set( KSMILWREleAudio ); + ele = CMDXMLElement::NewLC( EFalse, aDom, name ); + } + break; + default: + { + User::Leave( KErrNotSupported ); + } + } + + // Set MediaObject node attributes + ele->SetAttributeL( KSMILWRParaSrc, aObj->MimeInfo()->ContentLocation() ); + + // Append + aRoot->AppendChild( ele ); // Ownership to dom + CleanupStack::Pop( ele ); + + return aObj->MediaInfo()->Duration(); + } + +// --------------------------------------------------------- +// CUniSmilModel::GetMediaElemRegionIDs +// +// --------------------------------------------------------- +void CUniSmilModel::GetMediaElemRegionIDs( CMDXMLNode* aPage ) + { + CMDXMLNode* txtEle = NULL; + CMDXMLNode* imgEle = NULL; + CMDXMLNode* obj = aPage->FirstChild(); + + // Traverse through every object in page. + while ( obj ) + { + if( UniSmilUtils::IsMediaElem( obj ) ) + { + TMsgMediaType type = UniSmilUtils::MediaElemType( obj ); + switch ( type ) + { + case EMsgMediaImage: + case EMsgMediaVideo: + imgEle = obj; + break; + + case EMsgMediaText: + case EMsgMediaXhtml: + txtEle = obj; + break; + + // TODO: REF + default: + break; + } + } + obj = obj->NextSibling(); + } + + // Resolve ID:s + if ( !iTextRegionId.Length() && txtEle ) + { + UniSmilUtils::GetRegionId( txtEle, iTextRegionId ); + } + if ( !iImageRegionId.Length() && imgEle ) + { + UniSmilUtils::GetRegionId( imgEle, iImageRegionId ); + } + } + +// --------------------------------------------------------- +// CUniSmilModel::GetLayoutElements +// +// --------------------------------------------------------- +void CUniSmilModel::GetLayoutElements( CMDXMLNode* aLayout, + CMDXMLElement*& aRlEle, + CMDXMLElement*& aTxtEle, + CMDXMLElement*& aImgEle ) + { + if ( !aLayout ) + { + return; + } + + TPtrC value( KNullDesC ); + CMDXMLNode* node = aLayout->FirstChild(); + + // Search REGIONS & RootLayout + while ( node ) + { + // REGION PARAMETERS + if ( node->NodeName().CompareF( KSMILWREleRegion ) == 0 ) + { + + //UniSmilUtils::GetRegionId( node, value ); + if( ((CMDXMLElement*) node)->IsAttributeSpecified( KSMILWRParaId ) ) + { + ((CMDXMLElement*) node)->GetAttribute( KSMILWRParaId, value ); + } + else + { + value.Set( KNullDesC ); + } + + // IMAGE REGION + if ( value.CompareF( iImageRegionId ) == 0 ) + { + aImgEle = (CMDXMLElement*) node; + } + + // TEXT REGION + else if ( value.CompareF( iTextRegionId ) == 0 ) + { + aTxtEle = (CMDXMLElement*) node; + } + + } + else if ( node->NodeName().CompareF( KSMILWREleRoot_layout ) == 0 ) + { + aRlEle = (CMDXMLElement*) node; + } + + node = node->NextSibling(); + + } + } + +// --------------------------------------------------------- +// CUniSmilModel::GetMmsSmilLayout +// +// --------------------------------------------------------- +TUniLayout CUniSmilModel::GetMmsSmilLayout( CMDXMLDocument* aDom ) + { + TUniLayout rval = EUniUndefinedLayout; + + iTextRegionId.Set( KNullDesC ); + iImageRegionId.Set( KNullDesC ); + + // -------------------------------------------- + // Resolve region IDs used in media elements + // -------------------------------------------- + CMDXMLNode* node = GetNode( aDom, KSMILWREleBody ); + if ( !node ) + { + return rval; + } + + // Only one slide in the message since no tag found + // Other node types than not possible as this is MMS SMIL. + if ( node->FirstChild() ) + { + if ( node->FirstChild()->NodeName().CompareF( KSMILWRElePar ) != 0 ) + { + GetMediaElemRegionIDs( node ); + } + else + { + CMDXMLNode* page = node->FirstChild(); + while ( page ) + { + GetMediaElemRegionIDs( page ); + + // Go to next page. + page = page->NextSibling(); + } + } + } + + // ------------------------------------- + // Search layout elements + // ------------------------------------- + node = GetNode( aDom, KSMILWREleLayout ); + CMDXMLElement* rootLayout = NULL; + CMDXMLElement* textRegion = NULL; + CMDXMLElement* imageRegion = NULL; + GetLayoutElements( node, rootLayout, textRegion, imageRegion ); + + // ------------------------------ + // Resolve Root Layout + // ------------------------------ + TSize rootSize( 0, 0 ); + GetRootLayoutSize( rootLayout, rootSize ); + + // ------------------------------------ + // Resolve region parameters + // ------------------------------------ + TRect imgRect( 0, 0, 0, 0 ); + TRect txtRect( 0, 0, 0, 0 ); + GetRegionRect( imageRegion, rootSize, imgRect ); + GetRegionRect( textRegion, rootSize, txtRect ); + + // ------------------------------------ + // Layout decision + // ------------------------------------ + if ( textRegion && imageRegion ) + { + if( imgRect.iTl.iY < txtRect.iTl.iY ) + { + rval = EUniImageFirst; + } + else if ( imgRect.iTl.iY > txtRect.iTl.iY ) + { + rval = EUniTextFirst; + } + else + { + if ( imgRect.iTl.iX <= txtRect.iTl.iX ) + { + rval = EUniImageFirst; + } + else + { + rval = EUniTextFirst; + } + } + } + else if ( textRegion ) + { + rval = EUniTextFirst; + } + else // if ( iImgEle ) or none + { + rval = EUniImageFirst; + } + + return rval; + + } + +// --------------------------------------------------------- +// CUniSmilModel::GetRootLayoutSize +// +// --------------------------------------------------------- + +void CUniSmilModel::GetRootLayoutSize( CMDXMLElement* aRl, TSize& aSize ) + { + TPtrC value( KNullDesC ); + + if ( aRl ) + { + if( aRl->IsAttributeSpecified( KSMILWRParaWidth ) ) + { + aRl->GetAttribute( KSMILWRParaWidth, value ); + aSize.iWidth = UniSmilUtils::StringToIntValue( value, 0 ); + } + else + { + aSize.iWidth = iScreenSize.iWidth; + } + + if( aRl->IsAttributeSpecified( KSMILWRParaHeight ) ) + { + aRl->GetAttribute( KSMILWRParaHeight, value ); + aSize.iHeight = UniSmilUtils::StringToIntValue( value, 0 ); + } + else + { + aSize.iHeight = iScreenSize.iHeight; + } + } + else + { + aSize = iScreenSize; + } + } + +// --------------------------------------------------------- +// CUniSmilModel::GetRegionRect +// +// --------------------------------------------------------- + +void CUniSmilModel::GetRegionRect( CMDXMLElement* aRegion, TSize aRoot, TRect& aRect ) + { + TPtrC value; + + TInt width = 0; + TInt height = 0; + + if ( aRegion ) + { + if( aRegion->IsAttributeSpecified( KSMILWRParaWidth ) ) + { + aRegion->GetAttribute( KSMILWRParaWidth, value ); + width = UniSmilUtils::StringToIntValue( value, 0 ) ; + if ( value.Locate( '%' ) != KErrNotFound ) + { + width = width * aRoot.iWidth / 100; + } + } + + if( aRegion->IsAttributeSpecified( KSMILWRParaHeight ) ) + { + aRegion->GetAttribute( KSMILWRParaHeight, value ); + height = UniSmilUtils::StringToIntValue( value, 0 ) ; + if ( value.Locate( '%' ) != KErrNotFound ) + { + height = height * aRoot.iHeight / 100; + } + } + + if( aRegion->IsAttributeSpecified( KSMILWRParaTop ) ) + { + aRegion->GetAttribute( KSMILWRParaTop, value ); + aRect.iTl.iY = UniSmilUtils::StringToIntValue( value, 0 ); + if ( value.Locate( '%' ) != KErrNotFound ) + { + aRect.iTl.iY = aRect.iTl.iY * aRoot.iHeight / 100; + } + } + else + { + aRect.iTl.iY = 0; + } + + if( aRegion->IsAttributeSpecified( KSMILWRParaLeft ) ) + { + aRegion->GetAttribute( KSMILWRParaLeft, value ); + aRect.iTl.iX = UniSmilUtils::StringToIntValue( value, 0 ); + if ( value.Locate( '%' ) != KErrNotFound ) + { + aRect.iTl.iX = aRect.iTl.iX * aRoot.iWidth / 100; + } + } + else + { + aRect.iTl.iX = 0; + } + + aRect.iBr.iY = aRect.iTl.iY + height; + aRect.iBr.iX = aRect.iTl.iX + width; + + } + else + { + aRect = TRect( 0, 0, 0, 0 ); + } + } + +// --------------------------------------------------------- +// CUniSmilModel::GetRegionType +// --------------------------------------------------------- +// +TUniRegion CUniSmilModel::GetRegionType( CMDXMLNode* aNodePtr ) + { + if ( iImageRegionId.CompareF( iTextRegionId ) == 0 ) + { + // Image and text regions are the same! + // Literally taken this is agains MMS SMIL, but + // we should still tolerate it. + iParseResult |= ETextAndImageRegionsSame; + return EUniRegionUnresolved; + } + TPtrC regId; + TInt err = UniSmilUtils::GetRegionId( aNodePtr, regId ); + if ( !err ) + { + if ( regId.CompareF( iImageRegionId ) == 0 ) + { + return EUniRegionImage; + } + else if ( regId.CompareF( iTextRegionId ) == 0 ) + { + return EUniRegionText; + } + else + { + return EUniRegionUnresolved; + } + } + else + { + return EUniRegionUnresolved; + } + } + + +// --------------------------------------------------------- +// CUniSmilModel::GetNode +// +// --------------------------------------------------------- +CMDXMLNode* CUniSmilModel::GetNode( CMDXMLDocument* aDom, const TDesC& aName ) + { + CMDXMLNode* node = aDom->DocumentElement()->FirstChild(); + while ( node ) + { + if ( node->NodeName().CompareF( aName ) == 0 ) + { + break; + } + else + { + node = UniSmilUtils::NextNode( node ); + } + } + return node; + } + +// --------------------------------------------------------- +// CUniSmilModel::RemoveMetaTagsAndComments +// +// --------------------------------------------------------- +void CUniSmilModel::RemoveMetaTagsAndComments( CMDXMLDocument* aDom ) + { + CMDXMLNode* node = aDom->DocumentElement()->FirstChild(); + while ( node ) + { + if ( node->NodeType() == CMDXMLNode::ECommentNode || + node->NodeName().CompareF( KSMILWREleMeta ) == 0 ) + { + CMDXMLNode* removeNode = node; + node = removeNode->ParentNode(); + /*TInt ignore =*/ node->RemoveChild( removeNode ); + delete removeNode; + } + node = UniSmilUtils::NextNode( node ); + } + } + +// --------------------------------------------------------- +// CUniSmilModel::CorrectSlideTimingL +// +// --------------------------------------------------------- +void CUniSmilModel::CorrectSlideTimingL( CMDXMLElement* aPage ) + { + CMDXMLNode* node = aPage->FirstChild(); + + // Traverse through every object in page. + while ( node != NULL ) + { + if ( UniSmilUtils::IsMediaElem( node ) ) + { + CMDXMLElement* nodeElement = static_cast( node ); + + CUniObject* obj = iObjectList.GetByNodeL( node ); + + if( !obj || + !obj->MediaInfo() || + obj->MediaInfo()->Duration() != 0 || + TimingSpecified( nodeElement ) ) + { + // Return as non-static media was found from the page. + return; + } + else if ( nodeElement->IsAttributeSpecified( KSMILWRParaBegin ) ) + { + // Remove invalid Begin element since no End or Dur attributes is specified. + nodeElement->RemoveAttribute( KSMILWRParaBegin ); + } + else if ( nodeElement->IsAttributeSpecified( KSMILWRParaEnd ) ) + { + // Remove invalid End element since no Begin or Dur attributes is specified. + nodeElement->RemoveAttribute( KSMILWRParaEnd ); + } + } + + node = node->NextSibling(); + } + + // Read default smil parameters + if ( !iSmilParams ) + { + iSmilParams = CUniSmilParams::NewL( iFs ); + } + + TBuf16<20> defaultVal; + defaultVal.Zero(); + defaultVal.Format( KSmilMsecFormat, iSmilParams->iComposeParams->iSlideDuration ); + + aPage->SetAttributeL( KSMILWRParaDur, defaultVal ); + } + +// --------------------------------------------------------- +// CUniSmilModel::TimingSpecified +// +// --------------------------------------------------------- +TBool CUniSmilModel::TimingSpecified( CMDXMLElement* aNodePrt ) + { + TBool result( EFalse ); + + // Timing is set if dur or begin & end parameters are found + if ( aNodePrt && + ( aNodePrt->IsAttributeSpecified( KSMILWRParaDur ) || + ( aNodePrt->IsAttributeSpecified( KSMILWRParaBegin ) && + aNodePrt->IsAttributeSpecified( KSMILWRParaEnd ) ) ) ) + { + result = ETrue; + } + + return result; + } + +// End of file