// SWFMovie.cpp: implementation of the CSWFMovie class.
//
//////////////////////////////////////////////////////////////////////
#include "SWFMovie.h"
CSWFMovie::CSWFMovie()
{
// Init .SWF file header struct
strcpy((char*)m_SWFHeader.Signature, "FWS");
m_SWFHeader.Version = SWF_FILE_VERSION;
m_SWFHeader.FileLength = 0;
RECT_F rectangle = {0, 0, SWF_MOVIE_WIDHT, SWF_MOVIE_HEIGHT};
m_SWFMovieRectangle.SetRectangle(rectangle);
m_SWFHeader.FrameRate = 0x0C00;
m_SWFHeader.FrameCount = 0;
// Init .SWF file descriptor
m_SWFFile = NULL;
// Init .SWF file stream
m_SWFFileStream = NULL;
m_SWFFileStreamLength = 0;
}
CSWFMovie::~CSWFMovie()
{
if (m_SWFFileStream != NULL)
{
free(m_SWFFileStream);
m_SWFFileStreamLength = NULL;
}
}
BOOL CSWFMovie::OpenSWFFile(LPTSTR filename, SIZE_F movieSize, int frameRate)
{
BOOL bResult = TRUE;
if (m_SWFFile == NULL)
{
// Open new .SWF file
m_SWFFile = fopen(filename, "wb");
strcpy(m_SWFFileName, filename);
if (m_SWFFile == NULL)
bResult = FALSE;
else
{
// Set movie info
RECT_F rectangle = {0, 0, movieSize.cx, movieSize.cy};
m_SWFMovieRectangle.SetRectangle(rectangle);
m_SWFHeader.FrameRate = MAKEWORD(0, frameRate);
}
}
else
bResult = FALSE;
return bResult;
}
void CSWFMovie::CloseSWFFile()
{
// Close .SWF file
if (m_SWFFile)
{
// Go to the beginning of the .SWF file
fseek(m_SWFFile, 0, SEEK_SET);
// Write SWF_FILE_HEADER struct to the file
WriteSWFHeaderAndStream();
// Go to the end of the .SWF file
fseek(m_SWFFile, 0, SEEK_END);
// Write End tag
USHORT endTag = 0x0000;
fwrite(&endTag, sizeof(USHORT), 1, m_SWFFile);
fclose(m_SWFFile);
m_SWFFile = NULL;
}
}
void CSWFMovie::WriteSWFHeaderAndStream()
{
// Check if file is opened
if (m_SWFFile)
{
// Check if .SWF file is closing
UCHAR* pBuffer = m_SWFMovieRectangle.BuildSWFStream();
int numBytes = m_SWFMovieRectangle.GetSWFStreamLength();
// Calculate total file size
m_SWFHeader.FileLength = m_SWFFileStreamLength;
m_SWFHeader.FileLength += sizeof(SWF_FILE_HEADER); // .SWF file header size
m_SWFHeader.FileLength += numBytes; // Additional header size
m_SWFHeader.FileLength += sizeof(USHORT); // .SWF End tag size
// Write .SWF file header
fwrite(m_SWFHeader.Signature, sizeof(UCHAR), 3, m_SWFFile);
fwrite(&m_SWFHeader.Version, sizeof(UCHAR), 1, m_SWFFile);
fwrite(&m_SWFHeader.FileLength, sizeof(UINT), 1, m_SWFFile);
fwrite(pBuffer, sizeof(UCHAR), numBytes, m_SWFFile);
fwrite(&m_SWFHeader.FrameRate, sizeof(USHORT), 1, m_SWFFile);
fwrite(&m_SWFHeader.FrameCount, sizeof(USHORT), 1, m_SWFFile);
// Write .SWF file stream
fwrite(m_SWFFileStream, sizeof(UCHAR), m_SWFFileStreamLength, m_SWFFile);
}
}
void CSWFMovie::SetBackgroundColor(SWF_RGB bgColor)
{
// SetBackgroundColor tag
SWF_BGCOLOR bgColorTag;
bgColorTag.Header.TagCodeAndLength = 9;
bgColorTag.Header.TagCodeAndLength = (bgColorTag.Header.TagCodeAndLength << 6) | 3;
memcpy(&bgColorTag.BackgroundColor, &bgColor, sizeof(SWF_RGB));
// Modify total .SWF file size
int newLength = m_SWFFileStreamLength + sizeof(SWF_BGCOLOR);
// Write SetBackgroundColor tag
if (m_SWFFileStreamLength == 0)
m_SWFFileStream = (BYTE*)malloc(newLength);
else
m_SWFFileStream = (BYTE*)realloc(m_SWFFileStream, newLength);
memcpy(m_SWFFileStream+m_SWFFileStreamLength, &bgColorTag, sizeof(SWF_BGCOLOR));
m_SWFFileStreamLength = newLength;
}
void CSWFMovie::SetFrameLabel(UCHAR* frameLabel)
{
// FrameLabel tag
SWF_RECORDHEADER_LONG FrameLabelTag;
FrameLabelTag.TagCodeAndLength = (43 << 6) | 0x003F;
int frameLabelLength = strlen((char*)frameLabel) + 1;
FrameLabelTag.Length = frameLabelLength;
// Modify total .SWF file size
int newLength = m_SWFFileStreamLength + sizeof(SWF_RECORDHEADER_LONG) + frameLabelLength;
// Write FrameLabel tag
if (m_SWFFileStreamLength == 0)
m_SWFFileStream = (BYTE*)malloc(newLength);
else
m_SWFFileStream = (BYTE*)realloc(m_SWFFileStream, newLength);
memcpy(m_SWFFileStream+m_SWFFileStreamLength, &FrameLabelTag, sizeof(SWF_RECORDHEADER_LONG));
memcpy(m_SWFFileStream+m_SWFFileStreamLength+sizeof(SWF_RECORDHEADER_LONG), frameLabel, frameLabelLength);
m_SWFFileStreamLength = newLength;
}
void CSWFMovie::ShowFrame()
{
// ShowFrame tag
USHORT showFrameTage = 0x0040;
// Modify total .SWF file size
int newLength = m_SWFFileStreamLength + sizeof(USHORT);
// Write ShowFrame tag
if (m_SWFFileStreamLength == 0)
m_SWFFileStream = (BYTE*)malloc(newLength);
else
m_SWFFileStream = (BYTE*)realloc(m_SWFFileStream, newLength);
memcpy(m_SWFFileStream+m_SWFFileStreamLength, &showFrameTage, sizeof(USHORT));
m_SWFFileStreamLength = newLength;
// Increment frame counter
m_SWFHeader.FrameCount++;
}
void CSWFMovie::TriggerAction(CSWFAction* pAction)
{
// Write DoAction tag to .SWF stream
if (pAction != NULL)
{
UCHAR* pBuffer = pAction->BuildSWFStream();
// Modify total .SWF file size
int newLength = m_SWFFileStreamLength + pAction->GetSWFStreamLength();
// Write DefineShape tag
if (m_SWFFileStreamLength == 0)
m_SWFFileStream = (BYTE*)malloc(newLength);
else
m_SWFFileStream = (BYTE*)realloc(m_SWFFileStream, newLength);
memcpy(m_SWFFileStream+m_SWFFileStreamLength, pBuffer, pAction->GetSWFStreamLength());
m_SWFFileStreamLength = newLength;
}
}
void CSWFMovie::DefineObject(CSWFObject* pObject, int depth, bool bShow)
{
if (pObject != NULL)
{
// Get sprite SWF stream
UCHAR* pBuffer = pObject->BuildSWFStream();
int objectLength = pObject->GetSWFStreamLength();
int newLength = m_SWFFileStreamLength + objectLength;
if (m_SWFFileStreamLength == 0)
m_SWFFileStream = (BYTE*)malloc(newLength);
else
m_SWFFileStream = (BYTE*)realloc(m_SWFFileStream, newLength);
memcpy(m_SWFFileStream+m_SWFFileStreamLength, pBuffer, objectLength);
m_SWFFileStreamLength = newLength;
// Initial display object
if ((bShow) && (pObject->m_ObjectType != SWF_OBJECT_TYPE_BITMAP))
DisplayObject(pObject, depth, TRUE, NULL, -1);
}
}
void CSWFMovie::AddObject(CSWFObject* pObject, int depth, SWF_COLOR_TRANSFORM* pColorTransform, int ratio, bool bInitialDisplay)
{
if (pObject != NULL)
{
// Display object
DisplayObject(pObject, depth, bInitialDisplay, pColorTransform, ratio);
}
}
void CSWFMovie::UpdateObject(CSWFObject* pObject, int depth, SWF_COLOR_TRANSFORM* pColorTransform, int ratio)
{
if (pObject != NULL)
{
// Display object
DisplayObject(pObject, depth, FALSE, pColorTransform, ratio);
}
}
void CSWFMovie::RemoveObject(int depth)
{
// Format RemoveObject2 tag
SWF_REMOVE_OBJECT2_TAG removeObjectTag;
memset(&removeObjectTag, 0, sizeof(SWF_REMOVE_OBJECT2_TAG));
removeObjectTag.Header.TagCodeAndLength = (28 << 6) | 0x003F;
removeObjectTag.Header.Length = 2;
removeObjectTag.Depth = depth;
// Write RemoveObject2 tag
int newLength = m_SWFFileStreamLength + (removeObjectTag.Header.Length-2) + sizeof(SWF_REMOVE_OBJECT2_TAG);
if (m_SWFFileStreamLength == 0)
m_SWFFileStream = (BYTE*)malloc(newLength);
else
m_SWFFileStream = (BYTE*)realloc(m_SWFFileStream, newLength);
memcpy(m_SWFFileStream+m_SWFFileStreamLength, &removeObjectTag, sizeof(SWF_REMOVE_OBJECT2_TAG));
m_SWFFileStreamLength = newLength;
}
void CSWFMovie::DisplayObject(CSWFObject* pObject, int depth, bool bInitialDisplay, SWF_COLOR_TRANSFORM* pColorTransform, int ratio)
{
if (pObject != NULL)
{
// Format PlaceObject2 tag
SWF_PLACE_OBJECT_TAG placeObjectTag;
memset(&placeObjectTag, 0, sizeof(SWF_PLACE_OBJECT_TAG));
placeObjectTag.Header.TagCodeAndLength = (26 << 6) | 0x003F;
placeObjectTag.Header.Length = 0;
if (bInitialDisplay)
placeObjectTag.CharacterID = pObject->m_ID;
placeObjectTag.Depth = depth;
if (bInitialDisplay)
placeObjectTag.Flags = 0x06;
else
placeObjectTag.Flags = 0x05;
if (pColorTransform != NULL)
placeObjectTag.Flags |= 0x08;
if (pObject->m_ObjectType == SWF_OBJECT_TYPE_MORPH_SHAPE)
placeObjectTag.Flags |= 0x10;
int nameLength = 0;
if (pObject->m_ObjectType == SWF_OBJECT_TYPE_SPRITE)
{
if (((CSWFSprite*)pObject)->m_Name != NULL)
{
nameLength = strlen((char*)((CSWFSprite*)pObject)->m_Name) + 1;
placeObjectTag.Flags |= 0x20;
}
}
// Get transformation matrix
UCHAR* pTransformationMatrix = NULL;
int transformationMatrixLength = 0;
switch (pObject->m_ObjectType)
{
case SWF_OBJECT_TYPE_SHAPE:
{
pTransformationMatrix = ((CSWFShape*)pObject)->m_TransformationMatrix.BuildSWFStream();
transformationMatrixLength = ((CSWFShape*)pObject)->m_TransformationMatrix.GetSWFStreamLength();
}
break;
case SWF_OBJECT_TYPE_MORPH_SHAPE:
{
pTransformationMatrix = ((CSWFMorphShape*)pObject)->m_TransformationMatrix.BuildSWFStream();
transformationMatrixLength = ((CSWFMorphShape*)pObject)->m_TransformationMatrix.GetSWFStreamLength();
}
break;
case SWF_OBJECT_TYPE_BUTTON:
{
pTransformationMatrix = ((CSWFButton*)pObject)->m_TransformationMatrix.BuildSWFStream();
transformationMatrixLength = ((CSWFButton*)pObject)->m_TransformationMatrix.GetSWFStreamLength();
}
break;
case SWF_OBJECT_TYPE_SPRITE:
{
pTransformationMatrix = ((CSWFSprite*)pObject)->m_TransformationMatrix.BuildSWFStream();
transformationMatrixLength = ((CSWFSprite*)pObject)->m_TransformationMatrix.GetSWFStreamLength();
}
break;
}
// Get color transformation
CSWFColorTransform colorTranform(pColorTransform);
UCHAR* pColorTransformBuffer = colorTranform.BuildSWFStream();
int colorTransformLength = colorTranform.GetSWFStreamLength();
// Calculate tag length
placeObjectTag.Header.Length += sizeof(UCHAR); // sizeof Flags
placeObjectTag.Header.Length += sizeof(USHORT); // sizeof Depth
if (bInitialDisplay)
placeObjectTag.Header.Length += sizeof(USHORT); // sizeof CharacterID
placeObjectTag.Header.Length += transformationMatrixLength; // sizeof TransformationMatrix
if (pColorTransform != NULL)
placeObjectTag.Header.Length += colorTransformLength; // sizeof ColorTransformation
if (pObject->m_ObjectType == SWF_OBJECT_TYPE_MORPH_SHAPE)
placeObjectTag.Header.Length += sizeof(USHORT); // sizeof Ratio
if (pObject->m_ObjectType == SWF_OBJECT_TYPE_SPRITE) // sizeof Name
{
if (nameLength != 0)
placeObjectTag.Header.Length += strlen((char*)((CSWFSprite*)pObject)->m_Name) + 1;
}
// Write PlaceObject2 tag
int newLength = m_SWFFileStreamLength + placeObjectTag.Header.Length + sizeof(SWF_RECORDHEADER_LONG);
if (m_SWFFileStreamLength == 0)
m_SWFFileStream = (BYTE*)malloc(newLength);
else
m_SWFFileStream = (BYTE*)realloc(m_SWFFileStream, newLength);
// Write PlaceObject2 tag
newLength = m_SWFFileStreamLength + sizeof(SWF_RECORDHEADER_LONG) + sizeof(UCHAR) + sizeof(USHORT);
memcpy(m_SWFFileStream+m_SWFFileStreamLength, &placeObjectTag.Header, sizeof(SWF_RECORDHEADER_LONG));
memcpy(m_SWFFileStream+m_SWFFileStreamLength+sizeof(SWF_RECORDHEADER_LONG), &placeObjectTag.Flags, sizeof(UCHAR));
memcpy(m_SWFFileStream+m_SWFFileStreamLength+sizeof(SWF_RECORDHEADER_LONG)+sizeof(UCHAR), &placeObjectTag.Depth, sizeof(USHORT));
m_SWFFileStreamLength = newLength;
// Write CharacterID
if (bInitialDisplay)
{
newLength = m_SWFFileStreamLength + sizeof(USHORT);
memcpy(m_SWFFileStream+m_SWFFileStreamLength, &placeObjectTag.CharacterID, sizeof(USHORT));
m_SWFFileStreamLength = newLength;
}
// Write Matrix
newLength = m_SWFFileStreamLength + transformationMatrixLength;
memcpy(m_SWFFileStream+m_SWFFileStreamLength, pTransformationMatrix, transformationMatrixLength);
m_SWFFileStreamLength = newLength;
// Write ColorTransform
if (pColorTransform != NULL)
{
newLength = m_SWFFileStreamLength + colorTransformLength;
memcpy(m_SWFFileStream+m_SWFFileStreamLength, pColorTransformBuffer, colorTransformLength);
m_SWFFileStreamLength = newLength;
}
// Write Ratio
if (pObject->m_ObjectType == SWF_OBJECT_TYPE_MORPH_SHAPE)
{
newLength = m_SWFFileStreamLength + sizeof(USHORT);
memcpy(m_SWFFileStream+m_SWFFileStreamLength, &ratio, sizeof(USHORT));
m_SWFFileStreamLength = newLength;
}
// Write Name
if (pObject->m_ObjectType == SWF_OBJECT_TYPE_SPRITE)
{
if (nameLength != 0)
{
newLength = m_SWFFileStreamLength + nameLength;
memcpy(m_SWFFileStream+m_SWFFileStreamLength, ((CSWFSprite*)pObject)->m_Name, nameLength);
m_SWFFileStreamLength = newLength;
}
}
}
}