Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version

SWFLIB - a free Flash authoring library

, 18 Jul 2006 CPOL
An article on a free Flash authoring library.
samplemovie.zip
SampleMovie.swf
swflibreference.zip
SWFLIB - Programmers Reference.pdf
swflib_library.zip
swflib.dsp
swflib.dsw
swflib_reference.zip
SWFLIB - Programmers Reference.pdf
swflib_samplemovies.zip
SWF Sample Movies
Sample1.swf
Sample2.swf
Sample3.swf
Sample4.swf
Sample5.swf
swflib_testproject.zip
SWFLIB TestProject.dsp
SWFLIB TestProject.dsw
res
SWFLIB TestProject.ico
Sample1.swf
Sample2.swf
Sample3.swf
Sample4.swf
Sample5.swf
bm128.jpg
SWFLIB TestProject.clw
// SWFShape.cpp: implementation of the CSWFShape class.
//
//////////////////////////////////////////////////////////////////////

#include "SWFShape.h"


CSWFShape::CSWFShape(USHORT nID, RECT_F rectangle, USHORT depth)
{
	// Init DefineShape struct
	m_ObjectType = SWF_OBJECT_TYPE_SHAPE;
	m_ID = nID;
	m_Depth = depth;
	m_Shape.ShapeID = nID;
	m_Shape.Header.TagCodeAndLength = (32 << 6) | 0x003F;
	m_Shape.Header.Length = 0;

	// Init shape bound rectangle
	m_ShapeRectangle.SetRectangle(rectangle);

	// Init shape properties
	m_Shape.Shapes.NumberOfFillAndLineIndexBits = 0;
	m_Shape.Shapes.LineStyles.LineStyleCount = 0xFF;
	m_Shape.Shapes.LineStyles.LineStyleCountExtended = 0;
	m_Shape.Shapes.LineStyles.LineStyles = NULL;
	m_Shape.Shapes.FillStyles.FillStyleCount = 0xFF;
	m_Shape.Shapes.FillStyles.FillStyleCountExtended = 0;
	m_Shape.Shapes.FillStyles.FillStyles = NULL;
	m_Shape.Shapes.ShapeRecords = NULL;
	memset(&m_TransformationMatrix, 0, sizeof(MATRIX_F));

	// Init shape counter
	m_NumberShapes = 0;

	// Init shape stream properties
	m_SWFStream = NULL;
	m_SWFStreamLength = 0;
}

CSWFShape::~CSWFShape()
{
	// Free LineStyleArray
	if (m_Shape.Shapes.LineStyles.LineStyles != NULL)
	{
		free(m_Shape.Shapes.LineStyles.LineStyles);
		m_Shape.Shapes.LineStyles.LineStyles = NULL;
	}

	// Free FillStyleArray
	if (m_Shape.Shapes.FillStyles.FillStyles != NULL)
	{
		// Free GradientRecordsArray
		for (int i=0; i<m_Shape.Shapes.FillStyles.FillStyleCountExtended; i++)
		{
			if ((m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_LINEARGRADIENT) || 
				(m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_RADIALGRADIENT))
			{
				delete m_Shape.Shapes.FillStyles.FillStyles[i].Gradient.GradientRecords;
				m_Shape.Shapes.FillStyles.FillStyles[i].Gradient.GradientRecords = NULL;
			}
		}
		free(m_Shape.Shapes.FillStyles.FillStyles);
		m_Shape.Shapes.FillStyles.FillStyles = NULL;
	}

	// Free ShapeRecordsArray
	if (m_Shape.Shapes.ShapeRecords != NULL)
	{
		free(m_Shape.Shapes.ShapeRecords);
		m_Shape.Shapes.ShapeRecords = NULL;
	}

	// Free shape stream
	if (m_SWFStream != NULL)
	{
		free(m_SWFStream);
		m_SWFStream = NULL;
	}
}

void CSWFShape::AddLineStyle(int lineWidth, SWF_RGBA lineColor)
{
	// Define new LineStyle entry
	SWF_LINESTYLE lineStyleEntry;
	memset(&lineStyleEntry, 0, sizeof(SWF_LINESTYLE));
	lineStyleEntry.Width = (USHORT)(lineWidth*20);
	memcpy(&lineStyleEntry.Color, &lineColor, sizeof(SWF_RGBA));

	// Add new LineStyle entry to the LineStyleArray
	m_Shape.Shapes.LineStyles.LineStyleCountExtended++;
	if (m_Shape.Shapes.LineStyles.LineStyles == NULL)
		m_Shape.Shapes.LineStyles.LineStyles = (SWF_LINESTYLE*)malloc(sizeof(SWF_LINESTYLE));
	else
		m_Shape.Shapes.LineStyles.LineStyles = (SWF_LINESTYLE*)realloc(m_Shape.Shapes.LineStyles.LineStyles, m_Shape.Shapes.LineStyles.LineStyleCountExtended*sizeof(SWF_LINESTYLE));
	memcpy(&m_Shape.Shapes.LineStyles.LineStyles[m_Shape.Shapes.LineStyles.LineStyleCountExtended-1], &lineStyleEntry, sizeof(SWF_LINESTYLE));
}

void CSWFShape::AddSolidFillStyle(SWF_RGBA fillColor)
{
	// Define new FillStyle entry
	SWF_FILLSTYLE fillStyleEntry;
	memset(&fillStyleEntry, 0, sizeof(SWF_FILLSTYLE));
	fillStyleEntry.FillStyleType = SWF_FILLSTYLETYPE_SOLID;
	memcpy(&fillStyleEntry.Color, &fillColor, sizeof(SWF_RGBA));

	// Add new FillStyle entry to the FillStyleArray
	m_Shape.Shapes.FillStyles.FillStyleCountExtended++;
	if (m_Shape.Shapes.FillStyles.FillStyles == NULL)
		m_Shape.Shapes.FillStyles.FillStyles = (SWF_FILLSTYLE*)malloc(sizeof(SWF_FILLSTYLE));
	else
		m_Shape.Shapes.FillStyles.FillStyles = (SWF_FILLSTYLE*)realloc(m_Shape.Shapes.FillStyles.FillStyles, m_Shape.Shapes.FillStyles.FillStyleCountExtended*sizeof(SWF_FILLSTYLE));
	memcpy(&m_Shape.Shapes.FillStyles.FillStyles[m_Shape.Shapes.FillStyles.FillStyleCountExtended-1], &fillStyleEntry, sizeof(SWF_FILLSTYLE));
}

void CSWFShape::AddGradientFillStyle(UCHAR gradientFillType, RECT_F gradientRect, SWF_GRADIENTRECORD* gradientRecords, int numRecords)
{
	if ((numRecords > 0) && ((gradientFillType == SWF_FILLSTYLETYPE_LINEARGRADIENT) || (gradientFillType == SWF_FILLSTYLETYPE_RADIALGRADIENT)))
	{
		// Define gradient matrix
		MATRIX_F gradientMatrix;
		memset(&gradientMatrix, 0, sizeof(MATRIX_F));
		gradientMatrix.scaleX = ((gradientRect.right-gradientRect.left)*20) / 32768;
		gradientMatrix.scaleY = ((gradientRect.bottom-gradientRect.top)*20) / 32768;
		gradientMatrix.translateX = (gradientRect.left+gradientRect.right) / 2;
		gradientMatrix.translateY = (gradientRect.top+gradientRect.bottom) / 2;

		// Define new FillStyle entry
		SWF_FILLSTYLE fillStyleEntry;
		memset(&fillStyleEntry, 0, sizeof(SWF_FILLSTYLE));
		fillStyleEntry.FillStyleType = gradientFillType;
		fillStyleEntry.GradientMatrix = gradientMatrix;
		fillStyleEntry.Gradient.NumGradients = numRecords;
		fillStyleEntry.Gradient.GradientRecords = new SWF_GRADIENTRECORD[numRecords];
		memcpy(fillStyleEntry.Gradient.GradientRecords, gradientRecords, numRecords*sizeof(SWF_GRADIENTRECORD));

		// Add new FillStyle entry to the FillStyleArray
		m_Shape.Shapes.FillStyles.FillStyleCountExtended++;
		if (m_Shape.Shapes.FillStyles.FillStyles == NULL)
			m_Shape.Shapes.FillStyles.FillStyles = (SWF_FILLSTYLE*)malloc(sizeof(SWF_FILLSTYLE));
		else
			m_Shape.Shapes.FillStyles.FillStyles = (SWF_FILLSTYLE*)realloc(m_Shape.Shapes.FillStyles.FillStyles, m_Shape.Shapes.FillStyles.FillStyleCountExtended*sizeof(SWF_FILLSTYLE));
		memcpy(&m_Shape.Shapes.FillStyles.FillStyles[m_Shape.Shapes.FillStyles.FillStyleCountExtended-1], &fillStyleEntry, sizeof(SWF_FILLSTYLE));
	}
}

void CSWFShape::AddBitmapFillStyle(USHORT bitmapID, UCHAR bitmapFillType, RECT_F bitmapRect, RECT_F clipRect)
{
	if ((bitmapFillType == SWF_FILLSTYLETYPE_BITMAP_0) || (bitmapFillType == SWF_FILLSTYLETYPE_BITMAP_1) ||
		(bitmapFillType == SWF_FILLSTYLETYPE_BITMAP_2) || (bitmapFillType == SWF_FILLSTYLETYPE_BITMAP_3))
	{
		// Define bitmap matrix
		MATRIX_F bitmapMatrix;
		memset(&bitmapMatrix, 0, sizeof(MATRIX_F));
		bitmapMatrix.scaleX = ((clipRect.right-clipRect.left)/(bitmapRect.right-bitmapRect.left)) * 20;
		bitmapMatrix.scaleY = ((clipRect.bottom-clipRect.top)/(bitmapRect.bottom-bitmapRect.top)) * 20;
		bitmapMatrix.translateX = clipRect.left;
		bitmapMatrix.translateY = clipRect.top;

		// Define new FillStyle entry
		SWF_FILLSTYLE fillStyleEntry;
		memset(&fillStyleEntry, 0, sizeof(SWF_FILLSTYLE));
		fillStyleEntry.FillStyleType = bitmapFillType;
		fillStyleEntry.BitmapID = bitmapID;
		fillStyleEntry.BitmapMatrix = bitmapMatrix;

		// Add new FillStyle entry to the FillStyleArray
		m_Shape.Shapes.FillStyles.FillStyleCountExtended++;
		if (m_Shape.Shapes.FillStyles.FillStyles == NULL)
			m_Shape.Shapes.FillStyles.FillStyles = (SWF_FILLSTYLE*)malloc(sizeof(SWF_FILLSTYLE));
		else
			m_Shape.Shapes.FillStyles.FillStyles = (SWF_FILLSTYLE*)realloc(m_Shape.Shapes.FillStyles.FillStyles, m_Shape.Shapes.FillStyles.FillStyleCountExtended*sizeof(SWF_FILLSTYLE));
		memcpy(&m_Shape.Shapes.FillStyles.FillStyles[m_Shape.Shapes.FillStyles.FillStyleCountExtended-1], &fillStyleEntry, sizeof(SWF_FILLSTYLE));
	}
}

void CSWFShape::ChangeStyle(int lineStyleIndex, int fillStyleIndex0, int fillStyleIndex1, POINT_F* newPosition)
{
	// Define new StyleChange entry
	SWF_SHAPERECORD styleChangeEntry;
	memset(&styleChangeEntry, 0, sizeof(SWF_SHAPERECORD));

	// StateLineStyle bit
	styleChangeEntry.SWF_STYLECHANGERECORD.ShapeFlags |= 0x08;
	styleChangeEntry.SWF_STYLECHANGERECORD.LineStyle = (SHORT)lineStyleIndex;

	// StateFillStyle1 bit
	styleChangeEntry.SWF_STYLECHANGERECORD.ShapeFlags |= 0x04;
	styleChangeEntry.SWF_STYLECHANGERECORD.FillStyle1 = (SHORT)fillStyleIndex1;

	// StateFillStyle0 bit
	styleChangeEntry.SWF_STYLECHANGERECORD.ShapeFlags |= 0x02;
	styleChangeEntry.SWF_STYLECHANGERECORD.FillStyle0 = (SHORT)fillStyleIndex0;

	// StateMoveTo bit
	if (newPosition != NULL)
	{
		styleChangeEntry.SWF_STYLECHANGERECORD.ShapeFlags |= 0x01;
		styleChangeEntry.SWF_STYLECHANGERECORD.MoveDeltaX = (LONG)(newPosition->x * 20);
		styleChangeEntry.SWF_STYLECHANGERECORD.MoveDeltaY = (LONG)(newPosition->y * 20);

		// Calculate MoveBits
		int maxValue = max(abs(styleChangeEntry.SWF_STYLECHANGERECORD.MoveDeltaX), abs(styleChangeEntry.SWF_STYLECHANGERECORD.MoveDeltaY));
		BYTE numMoveBits = 0;
		while (pow(2,numMoveBits) < maxValue)
			numMoveBits++;
		numMoveBits++;
		styleChangeEntry.SWF_STYLECHANGERECORD.MoveBits = numMoveBits;
	}

	// Add new StyleChange to the ShapeRecordsArray
	m_NumberShapes++;
	if (m_Shape.Shapes.ShapeRecords == NULL)
		m_Shape.Shapes.ShapeRecords = (SWF_SHAPERECORD*)malloc(sizeof(SWF_SHAPERECORD));
	else
		m_Shape.Shapes.ShapeRecords = (SWF_SHAPERECORD*)realloc(m_Shape.Shapes.ShapeRecords, m_NumberShapes*sizeof(SWF_SHAPERECORD));
	memcpy(&m_Shape.Shapes.ShapeRecords[m_NumberShapes-1], &styleChangeEntry, sizeof(SWF_SHAPERECORD));
}

void CSWFShape::AddLineSegment(POINT_F offsetPoint)
{
	// Define new StraightEdge entry
	SWF_SHAPERECORD straightEdgeEntry;
	memset(&straightEdgeEntry, 0, sizeof(SWF_SHAPERECORD));
	straightEdgeEntry.SWF_STRAIGHTEDGERECORD.ShapeFlags = 0x30;
	straightEdgeEntry.SWF_STRAIGHTEDGERECORD.DeltaX = (int)(offsetPoint.x * 20);
	straightEdgeEntry.SWF_STRAIGHTEDGERECORD.DeltaY = (int)(offsetPoint.y * 20);

	// Calculate NumBits
	int maxValue = max(abs(straightEdgeEntry.SWF_STRAIGHTEDGERECORD.DeltaX), abs(straightEdgeEntry.SWF_STRAIGHTEDGERECORD.DeltaY));
	BYTE numBits = 0;
	while (pow(2,numBits) < maxValue)
		numBits++;
	numBits++;
	straightEdgeEntry.SWF_STRAIGHTEDGERECORD.NumBits = numBits;
	straightEdgeEntry.SWF_STRAIGHTEDGERECORD.ShapeFlags |= ((straightEdgeEntry.SWF_STRAIGHTEDGERECORD.NumBits-2) & 0x0F);
	straightEdgeEntry.SWF_STRAIGHTEDGERECORD.ShapeFlags = (straightEdgeEntry.SWF_STRAIGHTEDGERECORD.ShapeFlags << 1) | 0x01;

	// Add new StraightEdge to the ShapeRecordsArray
	m_NumberShapes++;
	if (m_Shape.Shapes.ShapeRecords == NULL)
		m_Shape.Shapes.ShapeRecords = (SWF_SHAPERECORD*)malloc(sizeof(SWF_SHAPERECORD));
	else
		m_Shape.Shapes.ShapeRecords = (SWF_SHAPERECORD*)realloc(m_Shape.Shapes.ShapeRecords, m_NumberShapes*sizeof(SWF_SHAPERECORD));
	memcpy(&m_Shape.Shapes.ShapeRecords[m_NumberShapes-1], &straightEdgeEntry, sizeof(SWF_SHAPERECORD));
}

void CSWFShape::AddLineSegment(float xOffset, float yOffset)
{
	// Add new StraightEdge to the ShapeRecordsArray
	POINT_F newPosition = {xOffset, yOffset};
	AddLineSegment(newPosition);
}

void CSWFShape::AddCurveSegment(POINT_F controlPoint, POINT_F anchorPoint)
{
	// Define new CurvedEdge entry
	SWF_SHAPERECORD curvedEdgeEntry;
	memset(&curvedEdgeEntry, 0, sizeof(SWF_SHAPERECORD));
	curvedEdgeEntry.SWF_CURVEDEDGERECORD.ShapeFlags = 0x20;
	curvedEdgeEntry.SWF_CURVEDEDGERECORD.ControlDeltaX = (int)(controlPoint.x * 20);
	curvedEdgeEntry.SWF_CURVEDEDGERECORD.ControlDeltaY = (int)(controlPoint.y * 20);
	curvedEdgeEntry.SWF_CURVEDEDGERECORD.AnchorDeltaX = (int)(anchorPoint.x * 20);
	curvedEdgeEntry.SWF_CURVEDEDGERECORD.AnchorDeltaY = (int)(anchorPoint.y * 20);

	// Calculate NumBits
	int maxControlValue = max(abs(curvedEdgeEntry.SWF_CURVEDEDGERECORD.ControlDeltaX), abs(curvedEdgeEntry.SWF_CURVEDEDGERECORD.ControlDeltaY));
	int maxDeltaValue = max(abs(curvedEdgeEntry.SWF_CURVEDEDGERECORD.AnchorDeltaX), abs(curvedEdgeEntry.SWF_CURVEDEDGERECORD.AnchorDeltaY));
	int maxValue = max(maxControlValue, maxDeltaValue);
	BYTE numBits = 0;
	while (pow(2,numBits) < maxValue)
		numBits++;
	numBits++;
	curvedEdgeEntry.SWF_CURVEDEDGERECORD.NumBits = numBits;
	curvedEdgeEntry.SWF_CURVEDEDGERECORD.ShapeFlags |= ((curvedEdgeEntry.SWF_CURVEDEDGERECORD.NumBits-2) & 0x0F);

	// Add new CurvedEdge to the ShapeRecordsArray
	m_NumberShapes++;
	if (m_Shape.Shapes.ShapeRecords == NULL)
		m_Shape.Shapes.ShapeRecords = (SWF_SHAPERECORD*)malloc(sizeof(SWF_SHAPERECORD));
	else
		m_Shape.Shapes.ShapeRecords = (SWF_SHAPERECORD*)realloc(m_Shape.Shapes.ShapeRecords, m_NumberShapes*sizeof(SWF_SHAPERECORD));
	memcpy(&m_Shape.Shapes.ShapeRecords[m_NumberShapes-1], &curvedEdgeEntry, sizeof(SWF_SHAPERECORD));
}

void CSWFShape::AddCurveSegment(float controlPointX, float controlPointY, float anchorPointX, float anchorPointY)
{
	POINT_F controlPoint = {controlPointX, controlPointY};
	POINT_F anchorPoint = {anchorPointX, anchorPointY};
	AddCurveSegment(controlPoint, anchorPoint);
}

UCHAR* CSWFShape::BuildSWFStream()
{
	int newLength;
	BYTE numFillIndexBits=0, numLineIndexBits=0;
	UCHAR* pShapeRecordBuffer = NULL;
	int recordStreamLength = 0;

	// Free shape stream
	if (m_SWFStream != NULL)
	{
		free(m_SWFStream);
		m_SWFStream = NULL;
	}

	// Add new EndShapeRecord to the ShapeRecordArray
	SWF_SHAPERECORD endShapeRecord;
	memset(&endShapeRecord, 0, sizeof(SWF_SHAPERECORD));
	m_NumberShapes++;
	if (m_Shape.Shapes.ShapeRecords == NULL)
		m_Shape.Shapes.ShapeRecords = (SWF_SHAPERECORD*)malloc(sizeof(SWF_SHAPERECORD));
	else
		m_Shape.Shapes.ShapeRecords = (SWF_SHAPERECORD*)realloc(m_Shape.Shapes.ShapeRecords, m_NumberShapes*sizeof(SWF_SHAPERECORD));
	memcpy(&m_Shape.Shapes.ShapeRecords[m_NumberShapes-1], &endShapeRecord, sizeof(SWF_SHAPERECORD));

	// Build shape bounds rectangle .SWF stream
	UCHAR* pBuffer = m_ShapeRectangle.BuildSWFStream();

	// Calculate total shape tag length
	m_Shape.Header.Length += m_ShapeRectangle.GetSWFStreamLength();			// Length of ShapeBounds rectangle
	m_Shape.Header.Length += sizeof(USHORT);								// Length of ShapeID
	m_Shape.Header.Length += sizeof(UCHAR);									// Length of NumLineAndFillBits field
	// Length of FillStyleArray
	if (m_Shape.Shapes.FillStyles.FillStyleCountExtended != 0)
	{
		// Calculate NumFillIndexBits
		while (pow(2,numFillIndexBits) < (m_Shape.Shapes.FillStyles.FillStyleCountExtended+1))
			numFillIndexBits++;
		int fillStyleArraySize = sizeof(UCHAR);
		if (m_Shape.Shapes.FillStyles.FillStyleCountExtended > 255)
			fillStyleArraySize += sizeof(USHORT);
		for (int i=0; i<m_Shape.Shapes.FillStyles.FillStyleCountExtended; i++)
		{
			if (m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_SOLID)
				fillStyleArraySize += (sizeof(UCHAR) + sizeof(SWF_RGBA));
			else if ((m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_LINEARGRADIENT) || 
				(m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_RADIALGRADIENT))
			{
				CSWFMatrix gradientMatrix;
				gradientMatrix.SetMatrix(m_Shape.Shapes.FillStyles.FillStyles[i].GradientMatrix);
				gradientMatrix.BuildSWFStream();
				fillStyleArraySize += 2*sizeof(UCHAR);
				fillStyleArraySize += gradientMatrix.GetSWFStreamLength();
				fillStyleArraySize += m_Shape.Shapes.FillStyles.FillStyles[i].Gradient.NumGradients*sizeof(SWF_GRADIENTRECORD);
			}
			else if ((m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_0) || (m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_1) || 
				(m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_2) || (m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_3))
			{
				CSWFMatrix bitmapMatrix;
				bitmapMatrix.SetMatrix(m_Shape.Shapes.FillStyles.FillStyles[i].BitmapMatrix);
				bitmapMatrix.BuildSWFStream();
				fillStyleArraySize += (sizeof(UCHAR) + sizeof(USHORT));
				fillStyleArraySize += bitmapMatrix.GetSWFStreamLength();
			}
		}
		m_Shape.Header.Length += fillStyleArraySize;
	}
	else
		m_Shape.Header.Length += sizeof(UCHAR);

	// Length of LineStyleArray
	if (m_Shape.Shapes.LineStyles.LineStyleCountExtended != 0)
	{
		// Calculate NumLineIndexBits
		while (pow(2,numLineIndexBits) < (m_Shape.Shapes.LineStyles.LineStyleCountExtended+1))
			numLineIndexBits++;
		int lineStyleArraySize = sizeof(UCHAR) + m_Shape.Shapes.LineStyles.LineStyleCountExtended*sizeof(SWF_LINESTYLE);
		if (m_Shape.Shapes.LineStyles.LineStyleCountExtended > 255)
			lineStyleArraySize += sizeof(USHORT);
		m_Shape.Header.Length += lineStyleArraySize;
	}
	else
		m_Shape.Header.Length += sizeof(UCHAR);
	// Length of ShapeRecordArray
	if (m_NumberShapes != 0)
	{
		// Build RecordArray .SWF stream
		pShapeRecordBuffer = BuildRecordArraySWFStream(numLineIndexBits, numFillIndexBits, recordStreamLength);
		m_Shape.Header.Length += recordStreamLength;
	}
	else
		m_Shape.Header.Length += sizeof(UCHAR);

	// Write RecordHeader tag to .SWF stream
	newLength = m_SWFStreamLength + sizeof(SWF_RECORDHEADER_LONG);
	if (m_SWFStreamLength == 0)
		m_SWFStream = (BYTE*)malloc(newLength);
	else
		m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
	memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Header, sizeof(SWF_RECORDHEADER_LONG));
	m_SWFStreamLength = newLength;

	// Write ShapeID to .SWF stream
	newLength = m_SWFStreamLength + sizeof(USHORT);
	if (m_SWFStreamLength == 0)
		m_SWFStream = (BYTE*)malloc(newLength);
	else
		m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
	memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.ShapeID, sizeof(USHORT));
	m_SWFStreamLength = newLength;

	// Write ShapeBounds tag to .SWF stream
	newLength = m_SWFStreamLength + m_ShapeRectangle.GetSWFStreamLength();
	if (m_SWFStreamLength == 0)
		m_SWFStream = (BYTE*)malloc(newLength);
	else
		m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
	memcpy(m_SWFStream+m_SWFStreamLength, pBuffer, m_ShapeRectangle.GetSWFStreamLength());
	m_SWFStreamLength = newLength;

	// Write FillStyleArray to .SWF stream
	if (m_Shape.Shapes.FillStyles.FillStyleCountExtended != 0)
	{
		if (m_Shape.Shapes.FillStyles.FillStyleCountExtended < 255)
			m_Shape.Shapes.FillStyles.FillStyleCount = (UCHAR)m_Shape.Shapes.FillStyles.FillStyleCountExtended;

		// Write FillStyleCount to .SWF stream
		newLength = m_SWFStreamLength + sizeof(UCHAR);
		if (m_SWFStreamLength == 0)
			m_SWFStream = (BYTE*)malloc(newLength);
		else
			m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
		memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.FillStyles.FillStyleCount, sizeof(UCHAR));
		m_SWFStreamLength = newLength;

		if (m_Shape.Shapes.FillStyles.FillStyleCountExtended > 255)
		{
			// Write FillStyleCountExtended to .SWF stream
			newLength = m_SWFStreamLength + sizeof(USHORT);
			if (m_SWFStreamLength == 0)
				m_SWFStream = (BYTE*)malloc(newLength);
			else
				m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
			memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.FillStyles.FillStyleCountExtended, sizeof(USHORT));
			m_SWFStreamLength = newLength;
		}

		// Write FillStyles to .SWF stream
		for (int i=0; i<m_Shape.Shapes.FillStyles.FillStyleCountExtended; i++)
		{
			// Write FillStyle to .SWF stream
			if (m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_SOLID)
			{
				newLength = m_SWFStreamLength + sizeof(UCHAR) + sizeof(SWF_RGBA);
				if (m_SWFStreamLength == 0)
					m_SWFStream = (BYTE*)malloc(newLength);
				else
					m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
				memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType, sizeof(UCHAR));
				memcpy(m_SWFStream+m_SWFStreamLength+sizeof(UCHAR), &m_Shape.Shapes.FillStyles.FillStyles[i].Color, sizeof(SWF_RGBA));
				m_SWFStreamLength = newLength;
			}
			else if ((m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_LINEARGRADIENT) || 
				(m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_RADIALGRADIENT))
			{
				newLength = m_SWFStreamLength + sizeof(UCHAR);
				if (m_SWFStreamLength == 0)
					m_SWFStream = (BYTE*)malloc(newLength);
				else
					m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
				memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType, sizeof(UCHAR));
				m_SWFStreamLength = newLength;

				CSWFMatrix gradientMatrix;
				gradientMatrix.SetMatrix(m_Shape.Shapes.FillStyles.FillStyles[i].GradientMatrix);
				UCHAR* pGradientMatrixBuffer = gradientMatrix.BuildSWFStream();
				int nGradientMatrixLength = gradientMatrix.GetSWFStreamLength();

				newLength = m_SWFStreamLength + nGradientMatrixLength;
				if (m_SWFStreamLength == 0)
					m_SWFStream = (BYTE*)malloc(newLength);
				else
					m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
				memcpy(m_SWFStream+m_SWFStreamLength, pGradientMatrixBuffer, nGradientMatrixLength);
				m_SWFStreamLength = newLength;

				newLength = m_SWFStreamLength + sizeof(UCHAR);
				if (m_SWFStreamLength == 0)
					m_SWFStream = (BYTE*)malloc(newLength);
				else
					m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
				memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.FillStyles.FillStyles[i].Gradient.NumGradients, sizeof(UCHAR));
				m_SWFStreamLength = newLength;

				for (int j=0; j<m_Shape.Shapes.FillStyles.FillStyles[i].Gradient.NumGradients; j++)
				{
					newLength = m_SWFStreamLength + sizeof(UCHAR) + sizeof(SWF_RGBA);
					if (m_SWFStreamLength == 0)
						m_SWFStream = (BYTE*)malloc(newLength);
					else
						m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
					memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.FillStyles.FillStyles[i].Gradient.GradientRecords[j].Ratio, sizeof(UCHAR));
					memcpy(m_SWFStream+m_SWFStreamLength+sizeof(UCHAR), &m_Shape.Shapes.FillStyles.FillStyles[i].Gradient.GradientRecords[j].Color, sizeof(SWF_RGBA));
					m_SWFStreamLength = newLength;
				}
			}
			else if ((m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_0) || (m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_1) || 
				(m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_2) || (m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_3))
			{
				newLength = m_SWFStreamLength + sizeof(UCHAR);
				if (m_SWFStreamLength == 0)
					m_SWFStream = (BYTE*)malloc(newLength);
				else
					m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
				memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.FillStyles.FillStyles[i].FillStyleType, sizeof(UCHAR));
				m_SWFStreamLength = newLength;

				newLength = m_SWFStreamLength + sizeof(USHORT);
				if (m_SWFStreamLength == 0)
					m_SWFStream = (BYTE*)malloc(newLength);
				else
					m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
				memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.FillStyles.FillStyles[i].BitmapID, sizeof(USHORT));
				m_SWFStreamLength = newLength;

				CSWFMatrix bitmapMatrix;
				bitmapMatrix.SetMatrix(m_Shape.Shapes.FillStyles.FillStyles[i].BitmapMatrix);
				UCHAR* pBitmapMatrixBuffer = bitmapMatrix.BuildSWFStream();
				int nBitmapMatrixLength = bitmapMatrix.GetSWFStreamLength();

				newLength = m_SWFStreamLength + nBitmapMatrixLength;
				if (m_SWFStreamLength == 0)
					m_SWFStream = (BYTE*)malloc(newLength);
				else
					m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
				memcpy(m_SWFStream+m_SWFStreamLength, pBitmapMatrixBuffer, nBitmapMatrixLength);
				m_SWFStreamLength = newLength;
			}
		}
	}
	else
	{
		// Write empty FillStyleArray to .SWF stream
		m_Shape.Shapes.FillStyles.FillStyleCount = 0;
		newLength = m_SWFStreamLength + sizeof(UCHAR);
		if (m_SWFStreamLength == 0)
			m_SWFStream = (BYTE*)malloc(newLength);
		else
			m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
		memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.FillStyles.FillStyleCount, sizeof(UCHAR));
		m_SWFStreamLength = newLength;
	}

	// Write LineStyleArray to .SWF stream
	if (m_Shape.Shapes.LineStyles.LineStyleCountExtended != 0)
	{
		if (m_Shape.Shapes.LineStyles.LineStyleCountExtended < 255)
			m_Shape.Shapes.LineStyles.LineStyleCount = (UCHAR)m_Shape.Shapes.LineStyles.LineStyleCountExtended;

		// Write LineStyleCount to .SWF stream
		newLength = m_SWFStreamLength + sizeof(UCHAR);
		if (m_SWFStreamLength == 0)
			m_SWFStream = (BYTE*)malloc(newLength);
		else
			m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
		memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.LineStyles.LineStyleCount, sizeof(UCHAR));
		m_SWFStreamLength = newLength;
		
		if (m_Shape.Shapes.LineStyles.LineStyleCountExtended > 255)
		{
			// Write LineStyleCountExtended to .SWF stream
			newLength = m_SWFStreamLength + sizeof(USHORT);
			if (m_SWFStreamLength == 0)
				m_SWFStream = (BYTE*)malloc(newLength);
			else
				m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
			memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.LineStyles.LineStyleCountExtended, sizeof(USHORT));
			m_SWFStreamLength = newLength;
		}

		// Write LineStyles to .SWF stream
		for (int i=0; i<m_Shape.Shapes.LineStyles.LineStyleCountExtended; i++)
		{
			// Write LineStyle to .SWF stream
			newLength = m_SWFStreamLength + sizeof(SWF_LINESTYLE);
			if (m_SWFStreamLength == 0)
				m_SWFStream = (BYTE*)malloc(newLength);
			else
				m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
			memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.LineStyles.LineStyles[i], sizeof(SWF_LINESTYLE));
			m_SWFStreamLength = newLength;
		}
	}
	else
	{
		// Write empty LineStyleArray to .SWF stream
		m_Shape.Shapes.LineStyles.LineStyleCount = 0;
		newLength = m_SWFStreamLength + sizeof(UCHAR);
		if (m_SWFStreamLength == 0)
			m_SWFStream = (BYTE*)malloc(newLength);
		else
			m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
		memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.LineStyles.LineStyleCount, sizeof(UCHAR));
		m_SWFStreamLength = newLength;
	}

	// Write NumFillAndLineBits to .SWF stream
	m_Shape.Shapes.NumberOfFillAndLineIndexBits = (numFillIndexBits<<4) | numLineIndexBits;
	newLength = m_SWFStreamLength + sizeof(UCHAR);
	if (m_SWFStreamLength == 0)
		m_SWFStream = (BYTE*)malloc(newLength);
	else
		m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
	memcpy(m_SWFStream+m_SWFStreamLength, &m_Shape.Shapes.NumberOfFillAndLineIndexBits, sizeof(UCHAR));
	m_SWFStreamLength = newLength;

	// Write ShapeRecordArray to .SWF stream
	if (pShapeRecordBuffer != NULL)
	{
		newLength = m_SWFStreamLength + recordStreamLength;
		if (m_SWFStreamLength == 0)
			m_SWFStream = (BYTE*)malloc(newLength);
		else
			m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
		memcpy(m_SWFStream+m_SWFStreamLength, pShapeRecordBuffer, recordStreamLength);
		m_SWFStreamLength = newLength;

		// Free memory
		free(pShapeRecordBuffer);
	}

	return m_SWFStream;
}

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

UCHAR* CSWFShape::BuildRecordArraySWFStream(int numLineIndexBits, int numFillIndexBits, int& recordStreamLength)
{
	UCHAR* pShapeRecordBuffer = NULL;
	int numBits=0, bitOffset=0, allocBytes=0;
	recordStreamLength = 0;

	// Write ShapeRecords to .SWF stream
	for (int i=0; i<m_NumberShapes; i++)
	{
		BOOL bEdgeTypeRecord = m_Shape.Shapes.ShapeRecords[i].SWF_ENDSHAPERECORD.ShapeFlags & 0x20;
		BOOL bStraightEdge = m_Shape.Shapes.ShapeRecords[i].SWF_ENDSHAPERECORD.ShapeFlags & 0x10;
		BOOL bStyleChangeRecord = m_Shape.Shapes.ShapeRecords[i].SWF_ENDSHAPERECORD.ShapeFlags & 0x0F;
		
		// Edge type record (StraightEdgeRecord or CurvedEdgeRecord);
		if (bEdgeTypeRecord)
		{
			// StraightEdgeRecord type
			if (bStraightEdge)
			{
				// ShapeFlags bit-field
				numBits += (7 + 2*m_Shape.Shapes.ShapeRecords[i].SWF_STRAIGHTEDGERECORD.NumBits);

				// Allocate memory
				if (numBits > (allocBytes*8))
				{
					int oldAllocBytes = allocBytes;
					allocBytes = numBits / 8;
					if ((numBits % 8) != 0)
						allocBytes++;
					if (pShapeRecordBuffer == NULL)
					{
						pShapeRecordBuffer = (UCHAR*)malloc(allocBytes*sizeof(UCHAR));
						memset(pShapeRecordBuffer, 0, allocBytes);
					}
					else
					{
						UCHAR* pTempBuffer = (UCHAR*)malloc(oldAllocBytes*sizeof(UCHAR));
						memcpy(pTempBuffer, pShapeRecordBuffer, oldAllocBytes);
						pShapeRecordBuffer = (UCHAR*)realloc(pShapeRecordBuffer, allocBytes*sizeof(UCHAR));
						memset(pShapeRecordBuffer, 0, allocBytes);
						memcpy(pShapeRecordBuffer, pTempBuffer, oldAllocBytes);
						free(pTempBuffer);
					}
				}

				// Write ShapeFlags bit-field
				int currentByte = bitOffset / 8;
				BYTE shapeFlags = m_Shape.Shapes.ShapeRecords[i].SWF_STRAIGHTEDGERECORD.ShapeFlags << 1;
				BYTE mask = 0x80;
				for (int j=0; j<7; j++)
				{
					pShapeRecordBuffer[currentByte] |= (((shapeFlags & mask) >> (7-j)) << ((currentByte+1)*8-bitOffset-1));

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

					mask = mask >> 1;
				}

				// Write DeltaX bit-field
				ULONG deltaX = m_Shape.Shapes.ShapeRecords[i].SWF_STRAIGHTEDGERECORD.DeltaX << (32-m_Shape.Shapes.ShapeRecords[i].SWF_STRAIGHTEDGERECORD.NumBits);
				ULONG maskDeltaX = 0x80000000;
				for (j=0; j<m_Shape.Shapes.ShapeRecords[i].SWF_STRAIGHTEDGERECORD.NumBits; j++)
				{
					pShapeRecordBuffer[currentByte] |= LOBYTE(((deltaX & maskDeltaX) >> (31-j)) << ((currentByte+1)*8-bitOffset-1));

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

					maskDeltaX = maskDeltaX >> 1;
				}

				// Write DeltaY bit-field
				ULONG deltaY = m_Shape.Shapes.ShapeRecords[i].SWF_STRAIGHTEDGERECORD.DeltaY << (32-m_Shape.Shapes.ShapeRecords[i].SWF_STRAIGHTEDGERECORD.NumBits);
				ULONG maskDeltaY = 0x80000000;
				for (j=0; j<m_Shape.Shapes.ShapeRecords[i].SWF_STRAIGHTEDGERECORD.NumBits; j++)
				{
					pShapeRecordBuffer[currentByte] |= LOBYTE(((deltaY & maskDeltaY) >> (31-j)) << ((currentByte+1)*8-bitOffset-1));

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

					maskDeltaY = maskDeltaY >> 1;
				}
			}
			// CurvedEdgeRecord type
			else
			{
				// ShapeFlags bit-field
				numBits += (6 + 4*m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.NumBits);

				// Allocate memory
				if (numBits > (allocBytes*8))
				{
					int oldAllocBytes = allocBytes;
					allocBytes = numBits / 8;
					if ((numBits % 8) != 0)
						allocBytes++;
					if (pShapeRecordBuffer == NULL)
					{
						pShapeRecordBuffer = (UCHAR*)malloc(allocBytes*sizeof(UCHAR));
						memset(pShapeRecordBuffer, 0, allocBytes);
					}
					else
					{
						UCHAR* pTempBuffer = (UCHAR*)malloc(oldAllocBytes*sizeof(UCHAR));
						memcpy(pTempBuffer, pShapeRecordBuffer, oldAllocBytes);
						pShapeRecordBuffer = (UCHAR*)realloc(pShapeRecordBuffer, allocBytes*sizeof(UCHAR));
						memset(pShapeRecordBuffer, 0, allocBytes);
						memcpy(pShapeRecordBuffer, pTempBuffer, oldAllocBytes);
						free(pTempBuffer);
					}
				}

				// Write ShapeFlags bit-field
				int currentByte = bitOffset / 8;
				BYTE shapeFlags = m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.ShapeFlags << 2;
				BYTE mask = 0x80;
				for (int j=0; j<6; j++)
				{
					pShapeRecordBuffer[currentByte] |= (((shapeFlags & mask) >> (7-j)) << ((currentByte+1)*8-bitOffset-1));

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

					mask = mask >> 1;
				}

				// Write ControlDeltaX bit-field
				ULONG controlDeltaX = m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.ControlDeltaX << (32-m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.NumBits);
				ULONG maskControlDeltaX = 0x80000000;
				for (j=0; j<m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.NumBits; j++)
				{
					pShapeRecordBuffer[currentByte] |= LOBYTE(((controlDeltaX & maskControlDeltaX) >> (31-j)) << ((currentByte+1)*8-bitOffset-1));

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

					maskControlDeltaX = maskControlDeltaX >> 1;
				}

				// Write ControlDeltaY bit-field
				ULONG controlDeltaY = m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.ControlDeltaY << (32-m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.NumBits);
				ULONG maskControlDeltaY = 0x80000000;
				for (j=0; j<m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.NumBits; j++)
				{
					pShapeRecordBuffer[currentByte] |= LOBYTE(((controlDeltaY & maskControlDeltaY) >> (31-j)) << ((currentByte+1)*8-bitOffset-1));

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

					maskControlDeltaY = maskControlDeltaY >> 1;
				}

				// Write AnchorDeltaX bit-field
				ULONG anchorDeltaX = m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.AnchorDeltaX << (32-m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.NumBits);
				ULONG maskAnchorDeltaX = 0x80000000;
				for (j=0; j<m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.NumBits; j++)
				{
					pShapeRecordBuffer[currentByte] |= LOBYTE(((anchorDeltaX & maskAnchorDeltaX) >> (31-j)) << ((currentByte+1)*8-bitOffset-1));

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

					maskAnchorDeltaX = maskAnchorDeltaX >> 1;
				}

				// Write AnchorDeltaY bit-field
				ULONG anchorDeltaY = m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.AnchorDeltaY << (32-m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.NumBits);
				ULONG maskAnchorDeltaY = 0x80000000;
				for (j=0; j<m_Shape.Shapes.ShapeRecords[i].SWF_CURVEDEDGERECORD.NumBits; j++)
				{
					pShapeRecordBuffer[currentByte] |= LOBYTE(((anchorDeltaY & maskAnchorDeltaY) >> (31-j)) << ((currentByte+1)*8-bitOffset-1));

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

					maskAnchorDeltaY = maskAnchorDeltaY >> 1;
				}
			}
		}
		// Non-edge type record (EndShapeRecord or StyleChangeRecord)
		else
		{
			// StyleChangeRecord type
			if (bStyleChangeRecord)
			{
				// ShapeFlags bit-field
				numBits += 6;

				// StateMoveTo bit-field
				if (m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x01)
					numBits += (5 + 2*m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.MoveBits);

				// StateFillStyle0 bit-field
				if (m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x02)
					numBits += numFillIndexBits;

				// StateFillStyle1 bit-field
				if (m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x04)
					numBits += numFillIndexBits;

				// StateLineStyle bit-field
				if (m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x08)
					numBits += numLineIndexBits;

				// Allocate memory
				if (numBits > (allocBytes*8))
				{
					int oldAllocBytes = allocBytes;
					allocBytes = numBits / 8;
					if ((numBits % 8) != 0)
						allocBytes++;
					if (pShapeRecordBuffer == NULL)
					{
						pShapeRecordBuffer = (UCHAR*)malloc(allocBytes*sizeof(UCHAR));
						memset(pShapeRecordBuffer, 0, allocBytes);
					}
					else
					{
						UCHAR* pTempBuffer = (UCHAR*)malloc(oldAllocBytes*sizeof(UCHAR));
						memcpy(pTempBuffer, pShapeRecordBuffer, oldAllocBytes);
						pShapeRecordBuffer = (UCHAR*)realloc(pShapeRecordBuffer, allocBytes*sizeof(UCHAR));
						memset(pShapeRecordBuffer, 0, allocBytes);
						memcpy(pShapeRecordBuffer, pTempBuffer, oldAllocBytes);
						free(pTempBuffer);
					}
				}

				// Write ShapeFlags bit-field
				int currentByte = bitOffset / 8;
				BYTE shapeFlags = m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.ShapeFlags << 2;
				BYTE mask = 0x80;
				for (int j=0; j<6; j++)
				{
					pShapeRecordBuffer[currentByte] |= (((shapeFlags & mask) >> (7-j)) << ((currentByte+1)*8-bitOffset-1));

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

					mask = mask >> 1;
				}

				// Write StateMoveTo bit-field
				if (m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x01)
				{
					int j;
					BYTE shapeMoveBits = m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.MoveBits << 3;
					BYTE mask = 0x80;
					for (j=0; j<5; j++)
					{
						pShapeRecordBuffer[currentByte] |= LOBYTE(((shapeMoveBits & mask) >> (7-j)) << ((currentByte+1)*8-bitOffset-1));

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

						mask = mask >> 1;
					}

					// Write MoveDeltaX bit-field
					ULONG moveDeltaX = m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.MoveDeltaX << (32-m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.MoveBits);
					ULONG maskMoveX = 0x80000000;
					for (j=0; j<m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.MoveBits; j++)
					{
						pShapeRecordBuffer[currentByte] |= LOBYTE(((moveDeltaX & maskMoveX) >> (31-j)) << ((currentByte+1)*8-bitOffset-1));

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

						maskMoveX = maskMoveX >> 1;
					}

					// Write MoveDeltaY bit-field
					ULONG moveDeltaY = m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.MoveDeltaY << (32-m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.MoveBits);
					ULONG maskMoveY = 0x80000000;
					for (j=0; j<m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.MoveBits; j++)
					{
						pShapeRecordBuffer[currentByte] |= LOBYTE(((moveDeltaY & maskMoveY) >> (31-j)) << ((currentByte+1)*8-bitOffset-1));

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

						maskMoveY = maskMoveY >> 1;
					}
				}

				// Write StateFillStyle0 bit-field
				if (m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x02)
				{
					WORD shapeFillStyleBits = m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.FillStyle0 << (16-numFillIndexBits);
					WORD mask = 0x8000;
					for (int j=0; j<numFillIndexBits; j++)
					{
						pShapeRecordBuffer[currentByte] |= LOBYTE(((shapeFillStyleBits & mask) >> (15-j)) << ((currentByte+1)*8-bitOffset-1));

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

						mask = mask >> 1;
					}
				}

				// Write StateFillStyle1 bit-field
				if (m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x04)
				{
					WORD shapeFillStyleBits = m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.FillStyle1 << (16-numFillIndexBits);
					WORD mask = 0x8000;
					for (int j=0; j<numFillIndexBits; j++)
					{
						pShapeRecordBuffer[currentByte] |= LOBYTE(((shapeFillStyleBits & mask) >> (15-j)) << ((currentByte+1)*8-bitOffset-1));

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

						mask = mask >> 1;
					}
				}

				// Write StateLineStyle bit-field
				if (m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x08)
				{
					WORD shapeLineStyleBits = m_Shape.Shapes.ShapeRecords[i].SWF_STYLECHANGERECORD.LineStyle << (16-numLineIndexBits);
					WORD mask = 0x8000;
					for (int j=0; j<numLineIndexBits; j++)
					{
						pShapeRecordBuffer[currentByte] |= LOBYTE(((shapeLineStyleBits & mask) >> (15-j)) << ((currentByte+1)*8-bitOffset-1));

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

						mask = mask >> 1;
					}
				}
			}
			// EndShapeRecord type
			else
			{
				// ShapeFlags bit-field
				numBits += 6;

				// Allocate memory
				if ((allocBytes*8 - bitOffset) < 6)
				{
					int oldAllocBytes = allocBytes;
					allocBytes++;
					if (pShapeRecordBuffer == NULL)
					{
						pShapeRecordBuffer = (UCHAR*)malloc(allocBytes*sizeof(UCHAR));
						memset(pShapeRecordBuffer, 0, allocBytes);
					}
					else
					{
						UCHAR* pTempBuffer = (UCHAR*)malloc(oldAllocBytes*sizeof(UCHAR));
						memcpy(pTempBuffer, pShapeRecordBuffer, oldAllocBytes);
						pShapeRecordBuffer = (UCHAR*)realloc(pShapeRecordBuffer, allocBytes*sizeof(UCHAR));
						memset(pShapeRecordBuffer, 0, allocBytes);
						memcpy(pShapeRecordBuffer, pTempBuffer, oldAllocBytes);
						free(pTempBuffer);
					}
				}
			}
		}
	}

	// Set new RecordShapeArray length
	recordStreamLength = allocBytes;

	return pShapeRecordBuffer;
}

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

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

	m_TransformationMatrix.SetMatrix(matrix);
}

void CSWFShape::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 CSWFShape::Translate(float translateX, float translateY)
{
	MATRIX_F matrix;
	m_TransformationMatrix.GetMatrix(matrix);

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

	m_TransformationMatrix.SetMatrix(matrix);
}

void CSWFShape::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.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411023.1 | Last Updated 18 Jul 2006
Article Copyright 2006 by darkoman
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid