Click here to Skip to main content
15,896,557 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.7K   6.5K   93  
An article on a free Flash authoring library.
// SWFMatrix.cpp: implementation of the CSWFMatrix class.
//
//////////////////////////////////////////////////////////////////////

#include "SWFMatrix.h"


CSWFMatrix::CSWFMatrix()
{
	// Init members
	m_SWFStream = NULL;
	m_SWFStreamLength = 0;
	m_SWFMatrix.MatrixFlags = 0;
	m_SWFMatrix.NScaleBits = m_SWFMatrix.NRotateBits = m_SWFMatrix.NTranslateBits = 0;
	m_SWFMatrix.ScaleX = m_SWFMatrix.ScaleY = 0;
	m_SWFMatrix.RotateSkew0 = m_SWFMatrix.RotateSkew1 = 0;
	m_SWFMatrix.TranslateX = m_SWFMatrix.TranslateY = 0;
	memset(&m_Matrix, 0, sizeof(MATRIX_F));
}

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

void CSWFMatrix::SetMatrix(MATRIX_F matrix)
{
	// Copy transformation matrix
	memcpy(&m_Matrix, &matrix, sizeof(MATRIX_F));

	// If matrix has scaling
	if ((matrix.scaleX != 0) || (matrix.scaleY != 0))
	{
		ULONG scaleX = (ULONG)(matrix.scaleX * 65536);
		ULONG scaleY = (ULONG)(matrix.scaleY * 65536);

		int maxValue = __max((int)matrix.scaleX, (int)matrix.scaleY);
		UCHAR scaleBitsNeaded = 0;
		// Calculate scale-bits neaded
		while (pow(2, scaleBitsNeaded) < maxValue)
			scaleBitsNeaded++;
		scaleBitsNeaded += 17;

		m_SWFMatrix.MatrixFlags |= 0x04;
		m_SWFMatrix.NScaleBits = scaleBitsNeaded;
		m_SWFMatrix.ScaleX = MAKELONG(LOWORD(scaleX), HIWORD(scaleX));
		m_SWFMatrix.ScaleY = MAKELONG(LOWORD(scaleY), HIWORD(scaleY));
	}

	// If matrix has rotation
	if ((matrix.rotateSkew0 != 0) || (matrix.rotateSkew1 != 0))
	{
		ULONG rotateSkew0 = (ULONG)(matrix.rotateSkew0 * 65536);
		ULONG rotateSkew1 = (ULONG)(matrix.rotateSkew1 * 65536);

		int maxValue = __max((int)matrix.rotateSkew0, (int)matrix.rotateSkew1);
		UCHAR rotateSkewBitsNeaded = 0;
		// Calculate rotate-skew-bits neaded
		while (pow(2, rotateSkewBitsNeaded) < maxValue)
			rotateSkewBitsNeaded++;
		rotateSkewBitsNeaded += 17;

		m_SWFMatrix.MatrixFlags |= 0x02;
		m_SWFMatrix.NRotateBits = rotateSkewBitsNeaded;
		m_SWFMatrix.RotateSkew0 = MAKELONG(LOWORD(rotateSkew0), HIWORD(rotateSkew0));
		m_SWFMatrix.RotateSkew1 = MAKELONG(LOWORD(rotateSkew1), HIWORD(rotateSkew1));
	}

	// If matrix has translation
	if ((matrix.translateX != 0) || (matrix.translateY != 0))
	{
		m_SWFMatrix.MatrixFlags |= 0x01;
		m_SWFMatrix.TranslateX = (int)(matrix.translateX * 20);
		m_SWFMatrix.TranslateY = (int)(matrix.translateY * 20);

		int maxValue = __max(abs(m_SWFMatrix.TranslateX), abs(m_SWFMatrix.TranslateY));
		UCHAR translateBitsNeaded = 0;
		// Calculate translate-bits neaded
		while (pow(2, translateBitsNeaded) < maxValue)
			translateBitsNeaded++;
		translateBitsNeaded++;

		m_SWFMatrix.NTranslateBits = translateBitsNeaded;
	}
}

void CSWFMatrix::GetMatrix(MATRIX_F& matrix)
{
	// Copy transformation matrix
	memcpy(&matrix, &m_Matrix, sizeof(MATRIX_F));
}

UCHAR* CSWFMatrix::BuildSWFStream()
{
	UCHAR bitsNeaded = 2;
	int byteIndex=0, bitOffset=0, i;

	// Calculate total bits neaded
	if (m_SWFMatrix.MatrixFlags & 0x04)
		bitsNeaded += (5 + 2*m_SWFMatrix.NScaleBits);
	if (m_SWFMatrix.MatrixFlags & 0x02)
		bitsNeaded += (5 + 2*m_SWFMatrix.NRotateBits);
	bitsNeaded += (5 + 2*m_SWFMatrix.NTranslateBits);

	// Create byte field
	m_SWFStreamLength = bitsNeaded / 8;
	if ((bitsNeaded%8) != 0)
		m_SWFStreamLength++;
	if (m_SWFStream != NULL)
		delete m_SWFStream;
	m_SWFStream = new UCHAR[m_SWFStreamLength];
	memset(m_SWFStream, 0, m_SWFStreamLength);

	// Write scale bit-field to .SWF stream
	if (m_SWFMatrix.MatrixFlags & 0x04)
	{
		m_SWFStream[byteIndex] |= 0x80;
		bitOffset++;

		// Write nScaleBits bit-field to .SWF stream
		UCHAR nScaleBits = m_SWFMatrix.NScaleBits << 3;
		UCHAR maskNScaleBits = 0x80;
		for (i=0; i<5; i++)
		{
			m_SWFStream[byteIndex] |= (((nScaleBits & maskNScaleBits) >> (7-i)) << ((byteIndex+1)*8-bitOffset-1));

			bitOffset++;
			if ((bitOffset != 0) && (bitOffset % 8) == 0)
				byteIndex++;

			maskNScaleBits = maskNScaleBits >> 1;
		}

		// Write scaleX bit-field to .SWF stream
		ULONG scaleX = m_SWFMatrix.ScaleX << (32-m_SWFMatrix.NScaleBits);
		ULONG maskScaleX = 0x80000000;
		for (i=0; i<m_SWFMatrix.NScaleBits; i++)
		{
			m_SWFStream[byteIndex] |= (((scaleX & maskScaleX) >> (31-i)) << ((byteIndex+1)*8-bitOffset-1));

			bitOffset++;
			if ((bitOffset != 0) && (bitOffset % 8) == 0)
				byteIndex++;

			maskScaleX = maskScaleX >> 1;
		}

		// Write scaleY bit-field to .SWF stream
		ULONG scaleY = m_SWFMatrix.ScaleY << (32-m_SWFMatrix.NScaleBits);
		ULONG maskScaleY = 0x80000000;
		for (i=0; i<m_SWFMatrix.NScaleBits; i++)
		{
			m_SWFStream[byteIndex] |= (((scaleY & maskScaleY) >> (31-i)) << ((byteIndex+1)*8-bitOffset-1));

			bitOffset++;
			if ((bitOffset != 0) && (bitOffset % 8) == 0)
				byteIndex++;

			maskScaleY = maskScaleY >> 1;
		}
	}
	else
		bitOffset++;

	// Write rotate bit-field to .SWF stream
	if (m_SWFMatrix.MatrixFlags & 0x02)
	{
		// Write rotateFlag to .SWF stream
		m_SWFStream[byteIndex] |= (0x01 << ((byteIndex+1)*8-bitOffset-1));
		bitOffset++;
		if ((bitOffset != 0) && (bitOffset % 8) == 0)
			byteIndex++;

		// Write nRotateBits bit-field to .SWF stream
		UCHAR nRotateBits = m_SWFMatrix.NRotateBits << 3;
		UCHAR maskNRotateBits = 0x80;
		for (i=0; i<5; i++)
		{
			m_SWFStream[byteIndex] |= (((nRotateBits & maskNRotateBits) >> (7-i)) << ((byteIndex+1)*8-bitOffset-1));

			bitOffset++;
			if ((bitOffset != 0) && (bitOffset % 8) == 0)
				byteIndex++;

			maskNRotateBits = maskNRotateBits >> 1;
		}

		// Write rotateSkew0 bit-field to .SWF stream
		ULONG rotateSkew0 = m_SWFMatrix.RotateSkew0 << (32-m_SWFMatrix.NRotateBits);
		ULONG maskRotateSkew0 = 0x80000000;
		for (i=0; i<m_SWFMatrix.NRotateBits; i++)
		{
			m_SWFStream[byteIndex] |= (((rotateSkew0 & maskRotateSkew0) >> (31-i)) << ((byteIndex+1)*8-bitOffset-1));

			bitOffset++;
			if ((bitOffset != 0) && (bitOffset % 8) == 0)
				byteIndex++;

			maskRotateSkew0 = maskRotateSkew0 >> 1;
		}

		// Write rotateSkew1 bit-field to .SWF stream
		ULONG rotateSkew1 = m_SWFMatrix.RotateSkew1 << (32-m_SWFMatrix.NRotateBits);
		ULONG maskRotateSkew1 = 0x80000000;
		for (i=0; i<m_SWFMatrix.NRotateBits; i++)
		{
			m_SWFStream[byteIndex] |= (((rotateSkew1 & maskRotateSkew1) >> (31-i)) << ((byteIndex+1)*8-bitOffset-1));

			bitOffset++;
			if ((bitOffset != 0) && (bitOffset % 8) == 0)
				byteIndex++;

			maskRotateSkew1 = maskRotateSkew1 >> 1;
		}
	}
	else
	{
		bitOffset++;
		if ((bitOffset != 0) && (bitOffset % 8) == 0)
			byteIndex++;
	}

	// Write nTranslateBits bit-field to .SWF stream
	UCHAR nTranslateBits = m_SWFMatrix.NTranslateBits << 3;
	UCHAR maskNTranslateBits = 0x80;
	for (i=0; i<5; i++)
	{
		m_SWFStream[byteIndex] |= (((nTranslateBits & maskNTranslateBits) >> (7-i)) << ((byteIndex+1)*8-bitOffset-1));

		bitOffset++;
		if ((bitOffset != 0) && (bitOffset % 8) == 0)
			byteIndex++;

		maskNTranslateBits = maskNTranslateBits >> 1;
	}

	// Write translateX bit-field to .SWF stream
	ULONG translateX = m_SWFMatrix.TranslateX << (32-m_SWFMatrix.NTranslateBits);
	ULONG maskTranslateX = 0x80000000;
	for (i=0; i<m_SWFMatrix.NTranslateBits; i++)
	{
		m_SWFStream[byteIndex] |= (((translateX & maskTranslateX) >> (31-i)) << ((byteIndex+1)*8-bitOffset-1));

		bitOffset++;
		if ((bitOffset != 0) && (bitOffset % 8) == 0)
			byteIndex++;

		maskTranslateX = maskTranslateX >> 1;
	}

	// Write translateY bit-field to .SWF stream
	ULONG translateY = m_SWFMatrix.TranslateY << (32-m_SWFMatrix.NTranslateBits);
	ULONG maskTranslateY = 0x80000000;
	for (i=0; i<m_SWFMatrix.NTranslateBits; i++)
	{
		m_SWFStream[byteIndex] |= (((translateY & maskTranslateY) >> (31-i)) << ((byteIndex+1)*8-bitOffset-1));

		bitOffset++;
		if ((bitOffset != 0) && (bitOffset % 8) == 0)
			byteIndex++;

		maskTranslateY = maskTranslateY >> 1;
	}

	return m_SWFStream;
}

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

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