Click here to Skip to main content
12,445,916 members (59,807 online)
Click here to Skip to main content

Stats

137.5K views
6K downloads
92 bookmarked
Posted

SWFLIB - a free Flash authoring library

, 18 Jul 2006 CPOL
An article on a free Flash authoring library.
// SWFSprite.cpp: implementation of the CSWFSprite class.
//
//////////////////////////////////////////////////////////////////////

#include "SWFSprite.h"


CSWFSprite::CSWFSprite(USHORT nID, UCHAR* pName, USHORT depth)
{
	// Init members
	m_ObjectType = SWF_OBJECT_TYPE_SPRITE;
	m_SWFStream = NULL;
	m_SWFStreamLength = 0;
	m_ID = nID;
	m_Depth = depth;
	m_Sprite.Header.TagCodeAndLength = (39 << 6) | 0x003F;
	m_Sprite.Header.Length = 0;
	m_Sprite.SpriteID = nID;
	m_Sprite.FrameCount = 0;

	if (pName != NULL)
	{
		int nameLength = strlen((char*)pName) + 1;
		m_Name = (UCHAR*)malloc(nameLength*sizeof(UCHAR));
		memcpy(m_Name, pName, nameLength-1);
		m_Name[nameLength-1] = '\0';
	}
	else
		m_Name = NULL;
}

CSWFSprite::~CSWFSprite()
{
	if (m_SWFStream != NULL)
	{
		delete m_SWFStream;
		m_SWFStream = NULL;
	}

	if (m_Name != NULL)
	{
		free(m_Name);
		m_Name = NULL;
	}
}

void CSWFSprite::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_SWFStreamLength + sizeof(SWF_RECORDHEADER_LONG) + frameLabelLength;

	// Write FrameLabel tag
	if (m_SWFStreamLength == 0)
		m_SWFStream = (BYTE*)malloc(newLength);
	else
		m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
	memcpy(m_SWFStream+m_SWFStreamLength, &FrameLabelTag, sizeof(SWF_RECORDHEADER_LONG));
	memcpy(m_SWFStream+m_SWFStreamLength+sizeof(SWF_RECORDHEADER_LONG), frameLabel, frameLabelLength);
	m_SWFStreamLength = newLength;
}

void CSWFSprite::ShowFrame()
{
	// ShowFrame tag
	USHORT showFrameTage = 0x0040;

	// Modify total .SWF file size
	int newLength = m_SWFStreamLength + sizeof(USHORT);

	// Write ShowFrame tag
	if (m_SWFStreamLength == 0)
		m_SWFStream = (BYTE*)malloc(newLength);
	else
		m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
	memcpy(m_SWFStream+m_SWFStreamLength, &showFrameTage, sizeof(USHORT));
	m_SWFStreamLength = newLength;

	// Increment frame counter
	m_Sprite.FrameCount++;
}

void CSWFSprite::TriggerAction(CSWFAction* pAction)
{
	// Write DoAction tag to .SWF stream
	if (pAction != NULL)
	{
		UCHAR* pBuffer = pAction->BuildSWFStream();

		// Modify total .SWF file size
		int newLength = m_SWFStreamLength + pAction->GetSWFStreamLength();

		// Write DefineShape tag
		if (m_SWFStreamLength == 0)
			m_SWFStream = (BYTE*)malloc(newLength);
		else
			m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
		memcpy(m_SWFStream+m_SWFStreamLength, pBuffer, pAction->GetSWFStreamLength());
		m_SWFStreamLength = newLength;
	}
}

void CSWFSprite::DefineObject(CSWFObject* pObject, int depth, bool bShow)
{
	if ((pObject != NULL) && (pObject->m_ObjectType == SWF_OBJECT_TYPE_SPRITE))
	{
		// Get sprite SWF stream
		UCHAR* pBuffer = pObject->BuildSWFStream();
		int objectLength = pObject->GetSWFStreamLength();

		int newLength = m_SWFStreamLength + objectLength;
		if (m_SWFStreamLength == 0)
			m_SWFStream = (BYTE*)malloc(newLength);
		else
			m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
		memcpy(m_SWFStream+m_SWFStreamLength, pBuffer, objectLength);
		m_SWFStreamLength = newLength;

		// Initial display object
		if (bShow)
			DisplayObject(pObject, depth, TRUE, NULL, -1);
	}
}

void CSWFSprite::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 CSWFSprite::UpdateObject(CSWFObject* pObject, int depth, SWF_COLOR_TRANSFORM* pColorTransform, int ratio)
{
	if (pObject != NULL)
	{
		// Display object
		DisplayObject(pObject, depth, FALSE, pColorTransform, ratio);
	}
}

void CSWFSprite::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_SWFStreamLength + (removeObjectTag.Header.Length-2) + sizeof(SWF_REMOVE_OBJECT2_TAG);
	if (m_SWFStreamLength == 0)
		m_SWFStream = (BYTE*)malloc(newLength);
	else
		m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
	memcpy(m_SWFStream+m_SWFStreamLength, &removeObjectTag, sizeof(SWF_REMOVE_OBJECT2_TAG));
	m_SWFStreamLength = newLength;
}

void CSWFSprite::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_SWFStreamLength + placeObjectTag.Header.Length + sizeof(SWF_RECORDHEADER_LONG);
		if (m_SWFStreamLength == 0)
			m_SWFStream = (BYTE*)malloc(newLength);
		else
			m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);

		// Write PlaceObject2 tag
		newLength = m_SWFStreamLength + sizeof(SWF_RECORDHEADER_LONG) + sizeof(UCHAR) + sizeof(USHORT);
		memcpy(m_SWFStream+m_SWFStreamLength, &placeObjectTag.Header, sizeof(SWF_RECORDHEADER_LONG));
		memcpy(m_SWFStream+m_SWFStreamLength+sizeof(SWF_RECORDHEADER_LONG), &placeObjectTag.Flags, sizeof(UCHAR));
		memcpy(m_SWFStream+m_SWFStreamLength+sizeof(SWF_RECORDHEADER_LONG)+sizeof(UCHAR), &placeObjectTag.Depth, sizeof(USHORT));
		m_SWFStreamLength = newLength;

		// Write CharacterID
		if (bInitialDisplay)
		{
			newLength = m_SWFStreamLength + sizeof(USHORT);
			memcpy(m_SWFStream+m_SWFStreamLength, &placeObjectTag.CharacterID, sizeof(USHORT));
			m_SWFStreamLength = newLength;
		}

		// Write Matrix
		newLength = m_SWFStreamLength + transformationMatrixLength;
		memcpy(m_SWFStream+m_SWFStreamLength, pTransformationMatrix, transformationMatrixLength);
		m_SWFStreamLength = newLength;

		// Write ColorTransform
		if (pColorTransform != NULL)
		{
			newLength = m_SWFStreamLength + colorTransformLength;
			memcpy(m_SWFStream+m_SWFStreamLength, pColorTransformBuffer, colorTransformLength);
			m_SWFStreamLength = newLength;
		}

		// Write Ratio
		if (pObject->m_ObjectType == SWF_OBJECT_TYPE_MORPH_SHAPE)
		{
			newLength = m_SWFStreamLength + sizeof(USHORT);
			memcpy(m_SWFStream+m_SWFStreamLength, &ratio, sizeof(USHORT));
			m_SWFStreamLength = newLength;
		}

		// Write Name
		if (pObject->m_ObjectType == SWF_OBJECT_TYPE_SPRITE)
		{
			if (nameLength != 0)
			{
				newLength = m_SWFStreamLength + nameLength;
				memcpy(m_SWFStream+m_SWFStreamLength, ((CSWFSprite*)pObject)->m_Name, nameLength);
				m_SWFStreamLength = newLength;
			}
		}
	}
}

UCHAR* CSWFSprite::BuildSWFStream()
{
	UCHAR* pTempBuffer = NULL;

	if (m_SWFStreamLength != 0)
	{
		pTempBuffer = new UCHAR[m_SWFStreamLength];
		memcpy(pTempBuffer, m_SWFStream, m_SWFStreamLength);
	}

	// Write DefineSprite tag
	int newLength = m_SWFStreamLength + sizeof(SWF_DEFINE_SPRITE_TAG) + sizeof(USHORT);
	if (m_SWFStreamLength == 0)
		m_SWFStream = (BYTE*)malloc(newLength);
	else
		m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);

	m_Sprite.Header.Length = m_SWFStreamLength + 3*sizeof(USHORT);

	memcpy(m_SWFStream, &m_Sprite.Header, sizeof(SWF_RECORDHEADER_LONG));
	memcpy(m_SWFStream+sizeof(SWF_RECORDHEADER_LONG), &m_Sprite.SpriteID, sizeof(USHORT));
	memcpy(m_SWFStream+sizeof(SWF_RECORDHEADER_LONG)+sizeof(USHORT), &m_Sprite.FrameCount, sizeof(USHORT));
	if (m_SWFStreamLength != 0)
		memcpy(m_SWFStream+sizeof(SWF_RECORDHEADER_LONG)+2*sizeof(USHORT), pTempBuffer, m_SWFStreamLength);
	USHORT endTag = 0x0000;
	memcpy(m_SWFStream+m_SWFStreamLength+sizeof(SWF_RECORDHEADER_LONG)+2*sizeof(USHORT), &endTag, sizeof(USHORT));

	if (m_SWFStreamLength != 0)
		delete pTempBuffer;

	m_SWFStreamLength = newLength;

	return m_SWFStream;
}

int CSWFSprite::GetSWFStreamLength()
{
	return m_SWFStreamLength;
}

void CSWFSprite::Scale(float scaleX, float scaleY)
{
	MATRIX_F matrix;
	m_TransformationMatrix.GetMatrix(matrix);

	matrix.scaleX = scaleX;
	matrix.scaleY = scaleY;

	m_TransformationMatrix.SetMatrix(matrix);
}

void CSWFSprite::Rotate(float angle)
{
	MATRIX_F matrix;
	m_TransformationMatrix.GetMatrix(matrix);

	if (((int)angle % 90) == 0)
		angle += 0.05f;

	double a = PI / 180;
	matrix.scaleX = (float)cos(angle*a);
	matrix.scaleY = (float)cos(angle*a);
	matrix.rotateSkew0 = (float)sin(angle*a);
	matrix.rotateSkew1 = -(float)sin(angle*a);

	m_TransformationMatrix.SetMatrix(matrix);
}

void CSWFSprite::Translate(float translateX, float translateY)
{
	MATRIX_F matrix;
	m_TransformationMatrix.GetMatrix(matrix);

	matrix.translateX = translateX;
	matrix.translateY = translateY;

	m_TransformationMatrix.SetMatrix(matrix);
}

void CSWFSprite::Shear(float shearX, float shearY)
{
	MATRIX_F matrix;
	m_TransformationMatrix.GetMatrix(matrix);

	matrix.rotateSkew0 = shearX;
	matrix.rotateSkew1 = shearY;

	m_TransformationMatrix.SetMatrix(matrix);
}

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)

Share

About the Author

darkoman
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.

You may also be interested in...

Pro
Pro
| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.160811.3 | Last Updated 18 Jul 2006
Article Copyright 2006 by darkoman
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid