Click here to Skip to main content
15,893,486 members
Articles / Desktop Programming / MFC

SWFLIB - a free Flash authoring library

Rate me:
Please Sign up or sign in to vote.
4.75/5 (26 votes)
18 Jul 2006CPOL2 min read 169.6K   6.5K   93  
An article on a free Flash authoring library.
// 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;
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Elektromehanika d.o.o. Nis
Serbia Serbia
He has a master degree in Computer Science at Faculty of Electronics in Nis (Serbia), and works as a C++/C# application developer for Windows platforms since 2001. He likes traveling, reading and meeting new people and cultures.

Comments and Discussions