skins/AknSkins/sdcsrc/SDCBinOutput.cpp
changeset 0 05e9090e2422
child 32 d9c996538b26
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/skins/AknSkins/sdcsrc/SDCBinOutput.cpp	Thu Dec 17 09:14:12 2009 +0200
@@ -0,0 +1,1203 @@
+/*
+* Copyright (c) 2003-2008 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:  Binary output.
+*
+*/
+
+#include <windows.h>
+
+#include "SDCGlobals.h"
+#include "SDCBinOutput.h"
+#include "AknsConstants.hrh"
+#include "SDCException.h"
+
+// Make std namespace available for compatibility
+namespace std {}
+using namespace std;
+
+// CLASS DECLARATION
+
+class TPos
+    {
+    public:
+        TPos( CSDCBinOutput* aBinOutput )
+            {
+            iPosition = aBinOutput->iOutputPos;
+            }
+
+        void Go( CSDCBinOutput* aBinOutput )
+            {
+            iOriginalPosition = aBinOutput->iOutputPos;
+            aBinOutput->iOutputPos = iPosition;
+            }
+
+        void Back( CSDCBinOutput* aBinOutput )
+            {
+            aBinOutput->iOutputPos = iOriginalPosition;
+            }
+
+        int BackwardsDelta()
+             {
+             return iOriginalPosition-iPosition;
+             }
+
+    public:
+        int iPosition;
+        int iOriginalPosition;
+    };
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CSDCBinOutput::CSDCBinOutput()
+    {
+    iOutputPos = 0;
+    }
+
+CSDCBinOutput::~CSDCBinOutput()
+    {
+    }
+
+//////////////////////////////////////////////////////////////////////
+// Other methods
+//////////////////////////////////////////////////////////////////////
+
+void CSDCBinOutput::Output( CSDCData* aData, const char* aBaseName, const char* aBinFilename, const bool aStubOnly )
+    {
+    iData = aData;
+    strcpy( iBaseName, aBaseName );
+
+    PrepareSkinDescriptor( aStubOnly );
+
+    if( iOutputPos != iOutputVector.size() ) throw CSDCException( ESDCUnknownError, "Internal binary output size does not match" );
+
+    FILE* file = fopen( aBinFilename, "wb" );
+    if( !file ) throw CSDCException( ESDCFileOpenError, "Can not open target binary file for writing" );
+    int i;
+    for( i=0; i<iOutputVector.size(); i++ )
+        {
+        fputc( iOutputVector[i], file );
+        }
+    fclose( file );
+    }
+
+void CSDCBinOutput::PrepareSkinDescriptor( const bool aStubOnly )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 0 );           // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 3*4 + 1*2 + 2*4 );
+    WriteInt( iData->iPid.iPID1 );      // SkinPID1
+    WriteInt( iData->iPid.iPID2 );      // SkinPID2
+    WriteInt( 0 );                      // SkinCF
+    WriteUint16( (unsigned short int)iData->iSkinType ); // SkinType
+    WriteInt( iData->iPalettePid.iPID1 ); // ColorSchemePID1
+    WriteInt( iData->iPalettePid.iPID2 ); // ColorSchemePID2
+
+    AppendBytes( 1*1 );                 // Protection
+    if( iData->iProtection == 1 )
+        {
+        WriteByte( 0x01 );
+        }
+    else
+        {
+        WriteByte( 0x00 );
+        }
+
+    AppendBytes( 1*1 );                 // ContentFlags
+    if( (iData->iAppIconDefVector.size()>0) && (!iData->IsScalable()) )
+        {
+        WriteByte( 1 );
+        }
+    else
+        {
+        WriteByte( 0 );
+        }
+    AppendBytes( 1*2 + 1*4 );
+    WriteUint16( 0 );                   // Reserved2
+    WriteInt( 0 );                      // Reserved3
+
+    int chunksN = 0;
+    AppendBytes( 1*4 );
+    TPos chunksNPos( this );
+    WriteInt( 0 );              // ChunksN
+
+    PrepareInformation();
+    chunksN++;
+
+    int i;
+
+    for( i=0; i<iData->iTargetDeviceVector.size(); i++ )
+        {
+        TSDCTargetDeviceEntry* entry = iData->iTargetDeviceVector[i];
+        PrepareTargetDevice( entry->iDeviceName );
+        chunksN++;
+        }
+
+    for( i=0; i<iData->iNameVector.size(); i++ )
+        {
+        TSDCNameEntry* entry = iData->iNameVector[i];
+        PrepareName( entry->iLanguageID, entry->iName );
+        chunksN++;
+        }
+
+    if( (iData->iAHOverridePid.iPID1!=0) && (iData->iAHOverridePid.iPID2!=0) )
+        {
+        PrepareLanguageOverride( 0x01, iData->iAHOverridePid );
+        chunksN++;
+        }
+
+    if( !iData->IsScalable() )
+        {
+        for( i=0; i<iData->iBitmapDefVector.size(); i++ )
+            {
+            TSDCBitmapDef* entry = iData->iBitmapDefVector[i];
+            if( (entry->iIID.iMajor == EAknsMajorSkin) &&
+                (entry->iIID.iMinor == EAknsMinorWallpaper) )
+                {
+                PrepareWallpaper( 0x00, entry );
+                chunksN++;
+                PrepareWallpaper( 0x01, entry );
+                chunksN++;
+                }
+            if( (entry->iIID.iMajor == EAknsMajorPinboard) &&
+                (entry->iIID.iMinor == EAknsMinorQsnFrPinbCenterWp) )
+                {
+                PrepareWallpaper( 0x02, entry );
+                chunksN++;
+                }
+            }
+        }
+
+    if( !aStubOnly )
+        {
+        char buf[512];
+        strcpy( buf, iBaseName );
+        strcat( buf, ".mbm" );
+        PrepareFilename( 0, buf );
+        chunksN++;
+
+        if( iData->IsScalable() )
+            {
+            strcpy( buf, iBaseName );
+            strcat( buf, ".mif" );
+            PrepareFilename( 1, buf );
+            chunksN++;
+            }
+
+        PrepareNormalClass( 0 );
+        chunksN++;
+
+        if( !iData->IsScalable() )
+            {
+            PrepareAppIconClass();
+            chunksN++;
+            }
+
+        // Release 2.6 specifics
+        PrepareEncapsulatedNormalClass( 0x0206 );
+        chunksN++;
+
+        // Release 2.7 specifics
+        PrepareEncapsulatedNormalClass( 0x0207 );
+        chunksN++;
+
+        // Release 2.8 specifics
+        PrepareEncapsulatedNormalClass( 0x0208 );
+        chunksN++;
+
+        // Release 3.0 specifics
+        PrepareEncapsulatedNormalClass( 0x0300 );
+        chunksN++;
+
+        // Non-mirrored
+        PrepareEncapsulatedNormalClass( 0x00010000 );
+        chunksN++;
+
+        // Mirrored
+        PrepareEncapsulatedNormalClass( 0x00020000 );
+        chunksN++;
+
+        for (int count = 0;count < iData->iLanguageVector.size(); count++)
+            {
+            // Language
+            PrepareEncapsulatedNormalClass( iData->iLanguageVector[count] );
+            chunksN++;
+            }
+        }
+
+    chunksNPos.Go( this );
+    WriteInt( chunksN );
+    chunksNPos.Back( this );
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareTargetDevice( const wchar_t* aDeviceName )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 14 );          // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 1*2 );
+    WriteUint16( wcslen( aDeviceName ) );
+
+    for( int i=0; i<wcslen( aDeviceName ); i++ )
+        {
+        AppendBytes( 2 );
+        WriteUint16( aDeviceName[i] );
+        }
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareName( const short int aLanguage, const wchar_t* aName )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 1 );           // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 2*2 );
+    WriteInt16( aLanguage );
+    WriteUint16( wcslen( aName ) );
+
+    for( int i=0; i<wcslen( aName ); i++ )
+        {
+        AppendBytes( 2 );
+        WriteUint16( aName[i] );
+        }
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareInformation()
+    {
+    TPos startPos( this );
+    int i;
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 11 );          // Type
+    WriteUint16( 2 );           // Version
+
+    AppendBytes( 2*4 );
+    SYSTEMTIME sysTime;
+    GetSystemTime( &sysTime );
+    FILETIME fileTime;
+    SystemTimeToFileTime( &sysTime, &fileTime );
+    WriteInt( fileTime.dwHighDateTime );
+    WriteInt( fileTime.dwLowDateTime );
+
+    AppendBytes( 2*4 );
+    WriteInt( (gVersionMajor<<16) | gVersionMinor );
+    WriteInt( 0 );
+
+    AppendBytes( 1*2 );
+    WriteUint16( wcslen( iData->iAuthor ) );
+    for( i=0; i<wcslen( iData->iAuthor ); i++ )
+        {
+        AppendBytes( 2 );
+        WriteUint16( iData->iAuthor[i] );
+        }
+
+    AppendBytes( 1*2 );
+    WriteUint16( wcslen( iData->iCopyright ) );
+    for( i=0; i<wcslen( iData->iCopyright ); i++ )
+        {
+        AppendBytes( 2 );
+        WriteUint16( iData->iCopyright[i] );
+        }
+
+    AppendBytes( 2*1 );
+    WriteByte( gPlatformMajor );
+    WriteByte( gPlatformMinor );
+
+    AppendBytes( 1*2 );
+    WriteUint16( wcslen( iData->iTool ) );
+    for( i=0; i<wcslen( iData->iTool ); i++ )
+        {
+        AppendBytes( 2 );
+        WriteUint16( iData->iTool[i] );
+        }
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareLanguageOverride( const unsigned char aOverrideType, const TSDCPID aOverridePid )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 9 );           // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 1*1 + 2*4 );
+    WriteByte( aOverrideType );
+    WriteInt( aOverridePid.iPID1 );
+    WriteInt( aOverridePid.iPID2 );
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareWallpaper( const unsigned char aWpType, const TSDCBitmapDef* aBitmapDef )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 10 );          // Type
+    WriteUint16( 1 );           // Version
+
+    char buf[512];
+    strcpy( buf, iBaseName );
+    strcat( buf, ".mbm" );
+
+    AppendBytes( 1*1 + 1*2 );
+    WriteByte( aWpType );
+    WriteUint16( strlen( buf ) );
+
+    for( int i=0; i<strlen( buf ); i++ )
+        {
+        AppendBytes( 2 );
+        WriteUint16( (short int)buf[i] );
+        }
+
+    AppendBytes( 1*4 );
+    WriteInt( aBitmapDef->iMBMIndex );
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareFilename( const int aId, const char* aFilename )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 2 );           // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 1*4 + 1*2 );
+    WriteInt( aId );
+    WriteUint16( strlen( aFilename ) );
+
+    for( int i=0; i<strlen( aFilename ); i++ )
+        {
+        AppendBytes( 2 );
+        WriteUint16( (short int)aFilename[i] );
+        }
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareEncapsulatedNormalClass( const int aRestriction )
+    {
+    TPos restStartPos( this );
+    if( aRestriction )
+        {
+        AppendBytes( 1*4 + 2*2 );
+        WriteUint( 0 );             // Length
+
+        if( aRestriction==0x0206 )
+            {
+            // 2.6 release restriction
+            WriteUint16( 13 );          // Type
+            WriteUint16( 1 );           // Version
+
+            AppendBytes( 2*1 );
+            WriteByte( (aRestriction&0xff00) >> 8 );    // PlatformMajor
+            WriteByte( aRestriction&0xff );             // PlatformMinor
+            }
+        else if( aRestriction<0x0010000 )
+            {
+            // Only generic release restriction
+            WriteUint16( 18 );          // Type
+            WriteUint16( 1 );           // Version
+
+            AppendBytes( 2*1 );
+            WriteByte( (aRestriction&0xff00) >> 8 );    // PlatformMajor
+            WriteByte( aRestriction&0xff );             // PlatformMinor
+
+            AppendBytes( 2*4 );
+            WriteInt( 0 );      // Reserved1
+            WriteInt( 0 );      // Reserved2
+            }
+        else if (aRestriction>=0x30000)
+            {
+            // language restriction
+            WriteUint16( 15 );          // Type
+            WriteUint16( 1 );           // Version
+
+            AppendBytes( 2*2 );
+            WriteUint16( 0 ) ; // GeneralR
+            WriteUint16( aRestriction&0xffff );         // LanguageR
+            }
+        else
+            {
+            // Layout restriction
+            WriteUint16( 15 );          // Type
+            WriteUint16( 1 );           // Version
+
+            AppendBytes( 2*2 );
+            WriteUint16( (aRestriction&0xffff0000) >> 16 ); // GeneralR
+            WriteUint16( 0 );                               // LanguageR
+            }
+
+        AppendBytes( 1*4 );
+        WriteInt( 1 );              // ChunksN
+        }
+
+    PrepareNormalClass( aRestriction );
+
+    if( aRestriction )
+        {
+        AppendBytes( 1*1 );
+        WriteByte( 0xf5 );
+
+        restStartPos.Go( this );
+        WriteUint( restStartPos.BackwardsDelta() );
+        restStartPos.Back( this );
+        }
+    }
+
+void CSDCBinOutput::PrepareNormalClass( const int aRestriction )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 3 );           // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 1*1 );
+    WriteByte( 0 );             // Class
+
+    int chunksN = 0;
+    AppendBytes( 1*4 );
+    TPos chunksNPos( this );
+    WriteInt( 0 );              // ChunksN
+
+    int i;
+    for( i=0; i<iData->iBitmapDefVector.size(); i++ )
+        {
+        if( iData->iBitmapDefVector[i]->iRestriction != aRestriction ) continue;
+
+        if( (iData->iBitmapDefVector[i]->iAppIconBitmap==false) || iData->IsScalable() )
+            {
+            PrepareBitmap( iData->iBitmapDefVector[i] );
+            chunksN++;
+            }
+        }
+    if( iData->IsScalable() ) for( i=0; i<iData->iAppIconDefVector.size(); i++ )
+        {
+        TSDCAppIconDef* entry = iData->iAppIconDefVector[i];
+
+        if( entry->iRestriction != aRestriction ) continue;
+
+        TSDCImageAttributes attributes;
+        attributes.iAttributeFlags = ESDCImageAttributeNone;
+        attributes.iAlignmentFlags = ESDCImageAlignNone;
+        attributes.iCoordX = 0;
+        attributes.iCoordY = 0;
+        attributes.iSizeW = 0;
+        attributes.iSizeH = 0;
+        PrepareImageTable( entry->iIID, entry->iIcons, attributes );
+        chunksN++;
+        }
+    for( i=0; i<iData->iFrameDefVector.size(); i++ )
+        {
+        TSDCFrameDef* entry = iData->iFrameDefVector[i];
+
+        if( entry->iRestriction != aRestriction ) continue;
+
+        TSDCImageAttributes attributes;
+        attributes.iAttributeFlags = ESDCImageAttributeNone;
+        attributes.iAlignmentFlags = ESDCImageAlignNone;
+        attributes.iCoordX = 0;
+        attributes.iCoordY = 0;
+        attributes.iSizeW = 0;
+        attributes.iSizeH = 0;
+        PrepareImageTable( entry->iIID, entry->iElements, attributes );
+        chunksN++;
+        }
+    for( i=0; i<iData->iColorTableDefVector.size(); i++ )
+        {
+        if( iData->iColorTableDefVector[i]->iRestriction != aRestriction ) continue;
+
+        PrepareColorTable( iData->iColorTableDefVector[i] );
+        chunksN++;
+        }
+    for( i=0; i<iData->iBmpAnimDefVector.size(); i++ )
+        {
+        if( iData->iBmpAnimDefVector[i]->iRestriction != aRestriction ) continue;
+
+        TSDCImageAttributes attributes;
+        attributes.iAttributeFlags = ESDCImageAttributeNone;
+        attributes.iAlignmentFlags = ESDCImageAlignNone;
+        attributes.iCoordX = 0;
+        attributes.iCoordY = 0;
+        attributes.iSizeW = 0;
+        attributes.iSizeH = 0;
+        PrepareBmpAnim( iData->iBmpAnimDefVector[i], attributes );
+        chunksN++;
+        }
+    for( i=0; i<iData->iStringDefVector.size(); i++ )
+        {
+        if( iData->iStringDefVector[i]->iRestriction != aRestriction ) continue;
+
+        PrepareString( iData->iStringDefVector[i] );
+        chunksN++;
+        }
+    if( iData->IsScalable() ) for( i=0; i<iData->iScalableItemDefVector.size(); i++ )
+        {
+        if( iData->iScalableItemDefVector[i]->iRestriction != aRestriction ) continue;
+
+        PrepareScalableItem( iData->iScalableItemDefVector[i] );
+        chunksN++;
+        }
+    if( iData->IsScalable() ) for( i=0; i<iData->iAnimationDefVector.size(); i++ )
+        {
+        if( iData->iAnimationDefVector[i]->iRestriction != aRestriction ) continue;
+
+        PrepareAnimation( iData->iAnimationDefVector[i] );
+        chunksN++;
+        }
+
+    chunksNPos.Go( this );
+    WriteInt( chunksN );
+    chunksNPos.Back( this );
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareAppIconClass()
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 3 );           // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 1*1 );
+    WriteByte( 1 );             // Class
+
+    int chunksN = 0;
+    AppendBytes( 1*4 );
+    TPos chunksNPos( this );
+    WriteInt( 0 );              // ChunksN
+
+    int i;
+    for( i=0; i<iData->iBitmapDefVector.size(); i++ )
+        {
+        if( iData->iBitmapDefVector[i]->iAppIconBitmap == true )
+            {
+            if( iData->iBitmapDefVector[i]->iRestriction )
+                throw CSDCException( ESDCContentError, "Application icon bitmap contains restrictions" );
+            PrepareBitmap( iData->iBitmapDefVector[i] );
+            chunksN++;
+            }
+        }
+    for( i=0; i<iData->iAppIconDefVector.size(); i++ )
+        {
+        TSDCAppIconDef* entry = iData->iAppIconDefVector[i];
+        if( entry->iRestriction )
+            throw CSDCException( ESDCContentError, "Application icon contains restrictions" );
+        TSDCImageAttributes attributes;
+        attributes.iAttributeFlags = ESDCImageAttributeNone;
+        attributes.iAlignmentFlags = ESDCImageAlignNone;
+        attributes.iCoordX = 0;
+        attributes.iCoordY = 0;
+        attributes.iSizeW = 0;
+        attributes.iSizeH = 0;
+        PrepareImageTable( entry->iIID, entry->iIcons, attributes );
+        chunksN++;
+        }
+
+    chunksNPos.Go( this );
+    WriteInt( chunksN );
+    chunksNPos.Back( this );
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareBitmap( const TSDCBitmapDef* aBitmapDef )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 4 );           // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 5*4 );
+    WriteInt( aBitmapDef->iIID.iMajor );
+    WriteInt( aBitmapDef->iIID.iMinor );
+    if( aBitmapDef->iMBMIndex>=16384 )
+        {
+        WriteInt( 1 );              // FilenameID
+        }
+    else
+        {
+        WriteInt( 0 );              // FilenameID
+        }
+    WriteInt( aBitmapDef->iMBMIndex );
+    WriteInt( aBitmapDef->iMaskMBMIndex );
+
+    PrepareAttributes( aBitmapDef->iAttributes );
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareColorTable( const TSDCColorTableDef* aColorTableDef )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 5 );           // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 2*4 + 1*1 );
+    WriteInt( aColorTableDef->iIID.iMajor );
+    WriteInt( aColorTableDef->iIID.iMinor );
+    WriteByte( aColorTableDef->iColors.size() );
+
+    for( int i=0; i<aColorTableDef->iColors.size(); i++ )
+        {
+        AppendBytes( 1*2 + 1*4 );
+        WriteInt16( (short int)aColorTableDef->iColors[i].iIndex );
+        WriteUint( aColorTableDef->iColors[i].iRgb );
+        }
+
+    TSDCImageAttributes attributes;
+    attributes.iAttributeFlags = ESDCImageAttributeNone;
+    if( iData->IsScalable() ) {
+        attributes.iAttributeFlags |= ESDCImageAttributeNBC;
+        }
+    attributes.iAlignmentFlags = ESDCImageAlignNone;
+    attributes.iCoordX = 0;
+    attributes.iCoordY = 0;
+    attributes.iSizeW = 0;
+    attributes.iSizeH = 0;
+    PrepareAttributes( attributes );
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareBmpAnim( const TSDCBmpAnimDef* aBmpAnimDef, const TSDCImageAttributes& aAttributes )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 8 );           // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 2*4 + 1*2 + 3*1 );
+    WriteInt( aBmpAnimDef->iIID.iMajor );
+    WriteInt( aBmpAnimDef->iIID.iMinor );
+    WriteInt16( (short int)aBmpAnimDef->iInterval );
+    WriteByte( (unsigned char)aBmpAnimDef->iPlayMode );
+    WriteByte( (unsigned char)aBmpAnimDef->iFlash );
+    WriteByte( (unsigned char)aBmpAnimDef->iFrames.size() );
+
+    for( int i=0; i<aBmpAnimDef->iFrames.size(); i++ )
+        {
+        AppendBytes( 2*4 + 3*2 );
+        WriteInt( aBmpAnimDef->iFrames[i].iIID.iMajor );
+        WriteInt( aBmpAnimDef->iFrames[i].iIID.iMinor );
+        WriteInt16( (short int)aBmpAnimDef->iFrames[i].iTime );
+        WriteInt16( (short int)aBmpAnimDef->iFrames[i].iPosX );
+        WriteInt16( (short int)aBmpAnimDef->iFrames[i].iPosY );
+        }
+
+    PrepareAttributes( aAttributes );
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareString( const TSDCStringDef* aStringDef )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 12 );          // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 2*4 + 1*2 );
+    WriteInt( aStringDef->iIID.iMajor );
+    WriteInt( aStringDef->iIID.iMinor );
+    WriteUint16( wcslen( aStringDef->iString ) );
+
+    for( int i=0; i<wcslen( aStringDef->iString ); i++ )
+        {
+        AppendBytes( 2 );
+        WriteUint16( aStringDef->iString[i] );
+        }
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareScalableItem( const TSDCScalableItemDef* aItemDef )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 16 );          // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 2*4 );
+    WriteInt( aItemDef->iIID.iMajor );
+    WriteInt( aItemDef->iIID.iMinor );
+
+    AppendBytes( 2*4 );
+    WriteInt( aItemDef->iRefIID.iMajor );
+    WriteInt( aItemDef->iRefIID.iMinor );
+
+    AppendBytes( 2*1 );
+    WriteByte( (aItemDef->iInput&0xff00) >> 8 );
+    WriteByte( aItemDef->iInput&0xff );
+
+    AppendBytes( 2*1 );
+    WriteByte( (aItemDef->iOutput&0xff00) >> 8 );
+    WriteByte( aItemDef->iOutput&0xff );
+
+    AppendBytes( 1*4 );
+    WriteUint( 0 );             // Reserved
+
+    AppendBytes( 1*2 );
+    WriteUint16( aItemDef->iCommands.size() );
+
+    for( int i=0; i<aItemDef->iCommands.size(); i++ )
+        {
+        PrepareEffectCommand( aItemDef->iCommands[i] );
+        }
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareAnimation( const TSDCAnimationDef* aItemDef )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 19 );          // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 2*4 );
+    WriteInt( aItemDef->iIID.iMajor );
+    WriteInt( aItemDef->iIID.iMinor );
+
+    AppendBytes( 2*4 );
+    if( aItemDef->iMorphing )
+        {
+        WriteByte( 1 );
+        }
+    else
+        {
+        WriteByte( 0 );
+        }
+    WriteByte( 0 );             // Reserved
+    WriteUint16( 0 );           // Reserved
+    WriteInt( 0 );              // Reserved
+
+    AppendBytes( 2*1 );
+    WriteByte( (aItemDef->iInput&0xff00) >> 8 );
+    WriteByte( aItemDef->iInput&0xff );
+
+    AppendBytes( 2*1 );
+    WriteByte( (aItemDef->iOutput&0xff00) >> 8 );
+    WriteByte( aItemDef->iOutput&0xff );
+
+    AppendBytes( 1*4 );
+    WriteUint( aItemDef->iMinInterval );
+
+    AppendBytes( 1*2 );
+    WriteUint16( aItemDef->iPreprocessCommands.size() );
+    int i;
+    for( i=0; i<aItemDef->iPreprocessCommands.size(); i++ )
+        {
+        PrepareEffectCommand( aItemDef->iPreprocessCommands[i] );
+        }
+
+    AppendBytes( 1*2 );
+    WriteUint16( aItemDef->iAnimCommands.size() );
+    for( i=0; i<aItemDef->iAnimCommands.size(); i++ )
+        {
+        PrepareEffectCommand( aItemDef->iAnimCommands[i] );
+        }
+
+    AppendBytes( 1*2 );
+    WriteUint16( aItemDef->iValues.size() );
+    for( i=0; i<aItemDef->iValues.size(); i++ )
+        {
+        PrepareAnimParamGroup( aItemDef->iValues[i] );
+        }
+
+    AppendBytes( 1*2 );
+    WriteUint16( aItemDef->iTimingModels.size() );
+    for( i=0; i<aItemDef->iTimingModels.size(); i++ )
+        {
+        PrepareAnimParamGroup( aItemDef->iTimingModels[i] );
+        }
+
+    AppendBytes( 1*2 );
+    WriteUint16( aItemDef->iSizeBoundParams.size() );
+    for( i=0; i<aItemDef->iSizeBoundParams.size(); i++ )
+        {
+        PrepareAnimParamGroup( aItemDef->iSizeBoundParams[i] );
+        }
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareImageTable( const TSDCIID& aIID, const vector<TSDCIID> aImages, const TSDCImageAttributes& aAttributes )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 6 );           // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 2*4 + 1*1 );
+    WriteInt( aIID.iMajor );
+    WriteInt( aIID.iMinor );
+    WriteByte( (unsigned char)aImages.size() );
+
+    for( int i=0; i<aImages.size(); i++ )
+        {
+        AppendBytes( 2*4 );
+        WriteInt( aImages[i].iMajor );
+        WriteInt( aImages[i].iMinor );
+        }
+
+    PrepareAttributes( aAttributes );
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareAttributes( const TSDCImageAttributes& aAttributes )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 7 );           // Type
+    WriteUint16( 2 );           // Version
+
+    AppendBytes( 2*1 + 4*2 );
+    WriteByte( (unsigned char)(aAttributes.iAttributeFlags&0xff) );
+    WriteByte( (unsigned char)(aAttributes.iAlignmentFlags&0xff) );
+    WriteInt16( (short int)aAttributes.iCoordX );
+    WriteInt16( (short int)aAttributes.iCoordY );
+    WriteInt16( (short int)aAttributes.iSizeW );
+    WriteInt16( (short int)aAttributes.iSizeH );
+
+    AppendBytes( 1*2 + 1*4 );
+    WriteUint16( (unsigned short)((aAttributes.iAttributeFlags&0xffff00)>>8) );
+    WriteUint( 0 );             // Reserved
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareParamVector( const vector<TSDCEffectParameter>& aParameters )
+    {
+    for( int i=0; i<aParameters.size(); i++ )
+        {
+        int type = aParameters[i].iType;
+
+        TPos paramPos( this );
+
+        AppendBytes( 1*2 + 1*1 );
+        WriteUint16( 0 );   // ParamLength
+        WriteByte( 0 );     // Reserved
+
+        if( type == 0 || type == 3 )
+            {
+            AppendBytes( 1*1 );
+            WriteByte( type );  // ParamType
+            }
+        else if( type == 1 || type == 4 ) // String or raw data
+            {
+            AppendBytes( 1*1 );
+            WriteByte( 1 );     // ParamType
+            }
+        else if( type == 2 )
+            {
+            AppendBytes( 1*1 );
+            WriteByte( 2 );     // ParamType
+            }
+        else
+            {
+            throw CSDCException( ESDCContentError, "Unknown parameter type in scalable item effect" );
+            }
+
+        AppendBytes( 1*2 );
+        WriteUint16( wcslen(aParameters[i].iName) ); // ParamNameLen
+
+        for( int b=0; b<wcslen(aParameters[i].iName); b++ )
+            {
+            AppendBytes( 1*2 );
+            WriteUint16( aParameters[i].iName[b] );
+            }
+
+        if( type == 0 || type == 3 ) // Number or named reference
+            {
+            AppendBytes( 1*4 );
+            WriteInt( aParameters[i].iNumber );
+            }
+        else if( type == 1 ) // String
+            {
+            AppendBytes( 1*2 );
+            WriteUint16( wcslen(aParameters[i].iString) );
+
+            for( int a=0; a<wcslen(aParameters[i].iString); a++ )
+                {
+                AppendBytes( 1*2 );
+                WriteUint16( aParameters[i].iString[a] );
+                }
+            }
+        else if( type == 2 ) // Graphics
+            {
+            AppendBytes( 3*4 );
+            WriteInt( aParameters[i].iBmpIndex );
+            WriteInt( aParameters[i].iMaskIndex );
+            if( aParameters[i].iBmpIndex>=16384 )
+                {
+                WriteInt( 1 );      // FilenameID
+                }
+            else
+                {
+                WriteInt( 0 );      // FilenameID
+                }
+            }
+        else if( type == 4 ) // Raw data
+            {
+            AppendBytes( 1*2 );
+            WriteUint16( aParameters[i].iRawDataCount );
+
+            for( int a=0; a<aParameters[i].iRawDataCount; a++ )
+                {
+                AppendBytes( 1*2 );
+                WriteUint16( aParameters[i].iString[a] );
+                }
+            }
+
+        paramPos.Go( this );
+        WriteUint16( paramPos.BackwardsDelta() );
+        paramPos.Back( this );
+        }
+    }
+
+void CSDCBinOutput::PrepareEffectCommand( const TSDCEffectCommand& aCommand )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 17 );          // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 1*4 );
+    WriteInt( aCommand.iUid );
+
+    AppendBytes( 6*1 );
+    WriteByte( (aCommand.iInputA&0xff00) >> 8 );
+    WriteByte( aCommand.iInputA&0xff );
+    WriteByte( (aCommand.iInputB&0xff00) >> 8 );
+    WriteByte( aCommand.iInputB&0xff );
+    WriteByte( (aCommand.iOutput&0xff00) >> 8 );
+    WriteByte( aCommand.iOutput&0xff );
+
+    AppendBytes( 1*2 );
+    WriteUint16( aCommand.iParameters.size() );
+
+    PrepareParamVector( aCommand.iParameters );
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::PrepareAnimParamGroup( const TSDCAnimParamGroup& aParamGroup )
+    {
+    TPos startPos( this );
+
+    AppendBytes( 1*4 + 2*2 );
+    WriteUint( 0 );             // Length
+    WriteUint16( 20 );          // Type
+    WriteUint16( 1 );           // Version
+
+    AppendBytes( 1*4 );
+    WriteUint( aParamGroup.iValueA );
+
+    AppendBytes( 1*4 );
+    WriteUint( aParamGroup.iValueB );
+
+    AppendBytes( 1*2 );
+    WriteUint16( aParamGroup.iParameters.size() );
+
+    PrepareParamVector( aParamGroup.iParameters );
+
+    AppendBytes( 1*1 );
+    WriteByte( 0xf5 );
+
+    startPos.Go( this );
+    WriteUint( startPos.BackwardsDelta() );
+    startPos.Back( this );
+    }
+
+void CSDCBinOutput::AppendBytes( const int aNumberOfBytes )
+    {
+    for( int i=0; i<aNumberOfBytes; i++ )
+        iOutputVector.push_back(0);
+    }
+
+void CSDCBinOutput::WriteByte( const unsigned char aByte )
+    {
+    iOutputVector.at(iOutputPos++) = aByte;
+    }
+
+void CSDCBinOutput::WriteInt( const int aInt )
+    {
+    WriteUint( (unsigned int)aInt );
+    }
+
+void CSDCBinOutput::WriteUint( const unsigned int aUint )
+    {
+    unsigned char* p = (unsigned char*)(&aUint);
+    iOutputVector.at(iOutputPos++) = p[0];
+    iOutputVector.at(iOutputPos++) = p[1];
+    iOutputVector.at(iOutputPos++) = p[2];
+    iOutputVector.at(iOutputPos++) = p[3];
+    }
+
+void CSDCBinOutput::WriteInt16( const short int aInt )
+    {
+    WriteUint16( (unsigned short int)aInt );
+    }
+
+void CSDCBinOutput::WriteUint16( const short unsigned int aUint )
+    {
+    unsigned char* p = (unsigned char*)(&aUint);
+    iOutputVector.at(iOutputPos++) = p[0];
+    iOutputVector.at(iOutputPos++) = p[1];
+    }
+
+// End of file