www.pudn.com > C++_Flash.rar > SWFMorphShape.cpp


// SWFMorphShape.cpp: implementation of the CSWFMorphShape class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "SWFMorphShape.h" 
 
 
CSWFMorphShape::CSWFMorphShape(USHORT nMorphID, USHORT depth, RECT_F startRect, RECT_F endRect) 
{ 
	// Init members 
	m_ObjectType = SWF_OBJECT_TYPE_MORPH_SHAPE; 
	m_ID = nMorphID; 
	m_Depth = depth; 
	m_SWFStream = NULL; 
	m_SWFStreamLength = 0; 
 
	// Init shape properties 
	m_MorphShape.Header.TagCodeAndLength = (46 << 6) | 0x003F; 
	m_MorphShape.Header.Length = 0; 
	m_MorphShape.CharacterID = nMorphID; 
	memcpy(&m_MorphShape.StartBounds, &startRect, sizeof(RECT_F)); 
	memcpy(&m_MorphShape.EndBounds, &endRect, sizeof(RECT_F)); 
	m_MorphShape.Offset = 0; 
	m_MorphShape.MorphFillStyles.FillStyleCount = 0xFF; 
	m_MorphShape.MorphFillStyles.FillStyleCountExtended = 0; 
	m_MorphShape.MorphFillStyles.FillStyles = NULL; 
	m_MorphShape.MorphLineStyles.LineStyleCount = 0xFF; 
	m_MorphShape.MorphLineStyles.LineStyleCountExtended = 0; 
	m_MorphShape.MorphLineStyles.LineStyles = NULL; 
	m_MorphShape.StartEdges.NumberOfFillAndLineIndexBits = 0; 
	m_MorphShape.StartEdges.ShapeRecords = NULL; 
	m_MorphShape.EndEdges.NumberOfFillAndLineIndexBits = 0; 
	m_MorphShape.EndEdges.ShapeRecords = NULL; 
	memset(&m_TransformationMatrix, 0, sizeof(MATRIX_F)); 
 
	// Init shape counter 
	m_NumberStartShapes = m_NumberEndShapes = 0; 
} 
 
CSWFMorphShape::~CSWFMorphShape() 
{ 
	// Free LineStyleArray 
	if (m_MorphShape.MorphLineStyles.LineStyles != NULL) 
	{ 
		free(m_MorphShape.MorphLineStyles.LineStyles); 
		m_MorphShape.MorphLineStyles.LineStyles = NULL; 
	} 
 
	// Free FillStyleArray 
	if (m_MorphShape.MorphFillStyles.FillStyles != NULL) 
	{ 
		// Free GradientRecordsArray 
		for (int i=0; i 0) && ((gradientFillType == SWF_FILLSTYLETYPE_LINEARGRADIENT) || (gradientFillType == SWF_FILLSTYLETYPE_RADIALGRADIENT))) 
	{ 
		// Define start gradient matrix 
		MATRIX_F startGradientMatrix; 
		memset(&startGradientMatrix, 0, sizeof(MATRIX_F)); 
		startGradientMatrix.scaleX = ((startGradientRect.right-startGradientRect.left)*20) / 32768; 
		startGradientMatrix.scaleY = ((startGradientRect.bottom-startGradientRect.top)*20) / 32768; 
		startGradientMatrix.translateX = (startGradientRect.left+startGradientRect.right) / 2; 
		startGradientMatrix.translateY = (startGradientRect.top+startGradientRect.bottom) / 2; 
 
		// Define end gradient matrix 
		MATRIX_F endGradientMatrix; 
		memset(&endGradientMatrix, 0, sizeof(MATRIX_F)); 
		endGradientMatrix.scaleX = ((endGradientRect.right-endGradientRect.left)*20) / 32768; 
		endGradientMatrix.scaleY = ((endGradientRect.bottom-endGradientRect.top)*20) / 32768; 
		endGradientMatrix.translateX = (endGradientRect.left+endGradientRect.right) / 2; 
		endGradientMatrix.translateY = (endGradientRect.top+endGradientRect.bottom) / 2; 
 
		// Define new FillStyle entry 
		SWF_MORPHFILLSTYLE fillStyleEntry; 
		memset(&fillStyleEntry, 0, sizeof(SWF_MORPHFILLSTYLE)); 
		fillStyleEntry.FillStyleType = gradientFillType; 
		fillStyleEntry.StartGradientMatrix = startGradientMatrix; 
		fillStyleEntry.EndGradientMatrix = endGradientMatrix; 
		fillStyleEntry.Gradient.NumGradients = numRecords; 
		fillStyleEntry.Gradient.GradientRecords = new SWF_MORPHGRADIENTRECORD[numRecords]; 
		memcpy(fillStyleEntry.Gradient.GradientRecords, gradientRecords, numRecords*sizeof(SWF_MORPHGRADIENTRECORD)); 
 
		// Add new FillStyle entry to the FillStyleArray 
		m_MorphShape.MorphFillStyles.FillStyleCountExtended++; 
		if (m_MorphShape.MorphFillStyles.FillStyles == NULL) 
			m_MorphShape.MorphFillStyles.FillStyles = (SWF_MORPHFILLSTYLE*)malloc(sizeof(SWF_MORPHFILLSTYLE)); 
		else 
			m_MorphShape.MorphFillStyles.FillStyles = (SWF_MORPHFILLSTYLE*)realloc(m_MorphShape.MorphFillStyles.FillStyles, m_MorphShape.MorphFillStyles.FillStyleCountExtended*sizeof(SWF_MORPHFILLSTYLE)); 
		memcpy(&m_MorphShape.MorphFillStyles.FillStyles[m_MorphShape.MorphFillStyles.FillStyleCountExtended-1], &fillStyleEntry, sizeof(SWF_MORPHFILLSTYLE)); 
	} 
} 
 
void CSWFMorphShape::AddBitmapFillStyle(USHORT bitmapID, UCHAR bitmapFillType, RECT_F bitmapRect, RECT_F startClipRect, RECT_F endClipRect) 
{ 
	if ((bitmapFillType == SWF_FILLSTYLETYPE_BITMAP_0) || (bitmapFillType == SWF_FILLSTYLETYPE_BITMAP_1) || 
		(bitmapFillType == SWF_FILLSTYLETYPE_BITMAP_2) || (bitmapFillType == SWF_FILLSTYLETYPE_BITMAP_3)) 
	{ 
		// Define start bitmap matrix 
		MATRIX_F startBitmapMatrix; 
		memset(&startBitmapMatrix, 0, sizeof(MATRIX_F)); 
		startBitmapMatrix.scaleX = ((startClipRect.right-startClipRect.left)/(bitmapRect.right-bitmapRect.left)) * 20; 
		startBitmapMatrix.scaleY = ((startClipRect.bottom-startClipRect.top)/(bitmapRect.bottom-bitmapRect.top)) * 20; 
		startBitmapMatrix.translateX = startClipRect.left; 
		startBitmapMatrix.translateY = startClipRect.top; 
 
		// Define end bitmap matrix 
		MATRIX_F endBitmapMatrix; 
		memset(&endBitmapMatrix, 0, sizeof(MATRIX_F)); 
		endBitmapMatrix.scaleX = ((endClipRect.right-endClipRect.left)/(bitmapRect.right-bitmapRect.left)) * 20; 
		endBitmapMatrix.scaleY = ((endClipRect.bottom-endClipRect.top)/(bitmapRect.bottom-bitmapRect.top)) * 20; 
		endBitmapMatrix.translateX = endClipRect.left; 
		endBitmapMatrix.translateY = endClipRect.top; 
 
		// Define new FillStyle entry 
		SWF_MORPHFILLSTYLE fillStyleEntry; 
		memset(&fillStyleEntry, 0, sizeof(SWF_MORPHFILLSTYLE)); 
		fillStyleEntry.FillStyleType = bitmapFillType; 
		fillStyleEntry.BitmapID = bitmapID; 
		fillStyleEntry.StartBitmapMatrix = startBitmapMatrix; 
		fillStyleEntry.EndBitmapMatrix = endBitmapMatrix; 
 
		// Add new FillStyle entry to the FillStyleArray 
		m_MorphShape.MorphFillStyles.FillStyleCountExtended++; 
		if (m_MorphShape.MorphFillStyles.FillStyles == NULL) 
			m_MorphShape.MorphFillStyles.FillStyles = (SWF_MORPHFILLSTYLE*)malloc(sizeof(SWF_MORPHFILLSTYLE)); 
		else 
			m_MorphShape.MorphFillStyles.FillStyles = (SWF_MORPHFILLSTYLE*)realloc(m_MorphShape.MorphFillStyles.FillStyles, m_MorphShape.MorphFillStyles.FillStyleCountExtended*sizeof(SWF_MORPHFILLSTYLE)); 
		memcpy(&m_MorphShape.MorphFillStyles.FillStyles[m_MorphShape.MorphFillStyles.FillStyleCountExtended-1], &fillStyleEntry, sizeof(SWF_MORPHFILLSTYLE)); 
	} 
} 
 
void CSWFMorphShape::ChangeStyle(int lineStyleIndex, int fillStyleIndex0, int fillStyleIndex1, POINT_F* newPosition, bool bStart) 
{ 
	// 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 
	if (bStart) 
	{ 
		m_NumberStartShapes++; 
		if (m_MorphShape.StartEdges.ShapeRecords == NULL) 
			m_MorphShape.StartEdges.ShapeRecords = (SWF_SHAPERECORD*)malloc(sizeof(SWF_SHAPERECORD)); 
		else 
			m_MorphShape.StartEdges.ShapeRecords = (SWF_SHAPERECORD*)realloc(m_MorphShape.StartEdges.ShapeRecords, m_NumberStartShapes*sizeof(SWF_SHAPERECORD)); 
		memcpy(&m_MorphShape.StartEdges.ShapeRecords[m_NumberStartShapes-1], &styleChangeEntry, sizeof(SWF_SHAPERECORD)); 
	} 
	else 
	{ 
		m_NumberEndShapes++; 
		if (m_MorphShape.EndEdges.ShapeRecords == NULL) 
			m_MorphShape.EndEdges.ShapeRecords = (SWF_SHAPERECORD*)malloc(sizeof(SWF_SHAPERECORD)); 
		else 
			m_MorphShape.EndEdges.ShapeRecords = (SWF_SHAPERECORD*)realloc(m_MorphShape.EndEdges.ShapeRecords, m_NumberEndShapes*sizeof(SWF_SHAPERECORD)); 
		memcpy(&m_MorphShape.EndEdges.ShapeRecords[m_NumberEndShapes-1], &styleChangeEntry, sizeof(SWF_SHAPERECORD)); 
	} 
} 
 
void CSWFMorphShape::AddLineSegment(POINT_F offsetPoint, bool bStart) 
{ 
	// 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 
	if (bStart) 
	{ 
		m_NumberStartShapes++; 
		if (m_MorphShape.StartEdges.ShapeRecords == NULL) 
			m_MorphShape.StartEdges.ShapeRecords = (SWF_SHAPERECORD*)malloc(sizeof(SWF_SHAPERECORD)); 
		else 
			m_MorphShape.StartEdges.ShapeRecords = (SWF_SHAPERECORD*)realloc(m_MorphShape.StartEdges.ShapeRecords, m_NumberStartShapes*sizeof(SWF_SHAPERECORD)); 
		memcpy(&m_MorphShape.StartEdges.ShapeRecords[m_NumberStartShapes-1], &straightEdgeEntry, sizeof(SWF_SHAPERECORD)); 
	} 
	else 
	{ 
		m_NumberEndShapes++; 
		if (m_MorphShape.EndEdges.ShapeRecords == NULL) 
			m_MorphShape.EndEdges.ShapeRecords = (SWF_SHAPERECORD*)malloc(sizeof(SWF_SHAPERECORD)); 
		else 
			m_MorphShape.EndEdges.ShapeRecords = (SWF_SHAPERECORD*)realloc(m_MorphShape.EndEdges.ShapeRecords, m_NumberEndShapes*sizeof(SWF_SHAPERECORD)); 
		memcpy(&m_MorphShape.EndEdges.ShapeRecords[m_NumberEndShapes-1], &straightEdgeEntry, sizeof(SWF_SHAPERECORD)); 
	} 
} 
 
void CSWFMorphShape::AddLineSegment(float xOffset, float yOffset, bool bStart) 
{ 
	// Add new StraightEdge to the ShapeRecordsArray 
	POINT_F newPosition = {xOffset, yOffset}; 
	AddLineSegment(newPosition, bStart); 
} 
 
void CSWFMorphShape::AddCurveSegment(POINT_F controlPoint, POINT_F anchorPoint, bool bStart) 
{ 
	// 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 
	if (bStart) 
	{ 
		m_NumberStartShapes++; 
		if (m_MorphShape.StartEdges.ShapeRecords == NULL) 
			m_MorphShape.StartEdges.ShapeRecords = (SWF_SHAPERECORD*)malloc(sizeof(SWF_SHAPERECORD)); 
		else 
			m_MorphShape.StartEdges.ShapeRecords = (SWF_SHAPERECORD*)realloc(m_MorphShape.StartEdges.ShapeRecords, m_NumberStartShapes*sizeof(SWF_SHAPERECORD)); 
		memcpy(&m_MorphShape.StartEdges.ShapeRecords[m_NumberStartShapes-1], &curvedEdgeEntry, sizeof(SWF_SHAPERECORD)); 
	} 
	else 
	{ 
		m_NumberEndShapes++; 
		if (m_MorphShape.EndEdges.ShapeRecords == NULL) 
			m_MorphShape.EndEdges.ShapeRecords = (SWF_SHAPERECORD*)malloc(sizeof(SWF_SHAPERECORD)); 
		else 
			m_MorphShape.EndEdges.ShapeRecords = (SWF_SHAPERECORD*)realloc(m_MorphShape.EndEdges.ShapeRecords, m_NumberEndShapes*sizeof(SWF_SHAPERECORD)); 
		memcpy(&m_MorphShape.EndEdges.ShapeRecords[m_NumberEndShapes-1], &curvedEdgeEntry, sizeof(SWF_SHAPERECORD)); 
	} 
} 
 
void CSWFMorphShape::AddCurveSegment(float controlPointX, float controlPointY, float anchorPointX, float anchorPointY, bool bStart) 
{ 
	POINT_F controlPoint = {controlPointX, controlPointY}; 
	POINT_F anchorPoint = {anchorPointX, anchorPointY}; 
	AddCurveSegment(controlPoint, anchorPoint, bStart); 
} 
 
UCHAR* CSWFMorphShape::BuildSWFStream() 
{ 
	int newLength; 
	UCHAR numStartFillIndexBits=0, numStartLineIndexBits=0, numEndFillIndexBits=0, numEndLineIndexBits=0; 
	UCHAR *pStartShapeRecordBuffer=NULL, *pEndShapeRecordBuffer=NULL; 
	int recordStartStreamLength=0, recordEndStreamLength=0; 
 
	// Free shape stream 
	if (m_SWFStream != NULL) 
	{ 
		free(m_SWFStream); 
		m_SWFStream = NULL; 
	} 
 
	// Define EndShapeRecord tag 
	SWF_SHAPERECORD endShapeRecord; 
	memset(&endShapeRecord, 0, sizeof(SWF_SHAPERECORD)); 
 
	// Add EndShapeRecord to the StartShapeRecordArray 
	m_NumberStartShapes++; 
	if (m_MorphShape.StartEdges.ShapeRecords == NULL) 
		m_MorphShape.StartEdges.ShapeRecords = (SWF_SHAPERECORD*)malloc(sizeof(SWF_SHAPERECORD)); 
	else 
		m_MorphShape.StartEdges.ShapeRecords = (SWF_SHAPERECORD*)realloc(m_MorphShape.StartEdges.ShapeRecords, m_NumberStartShapes*sizeof(SWF_SHAPERECORD)); 
	memcpy(&m_MorphShape.StartEdges.ShapeRecords[m_NumberStartShapes-1], &endShapeRecord, sizeof(SWF_SHAPERECORD)); 
 
	// Add EndShapeRecord to the EndShapeRecordArray 
	m_NumberEndShapes++; 
	if (m_MorphShape.EndEdges.ShapeRecords == NULL) 
		m_MorphShape.EndEdges.ShapeRecords = (SWF_SHAPERECORD*)malloc(sizeof(SWF_SHAPERECORD)); 
	else 
		m_MorphShape.EndEdges.ShapeRecords = (SWF_SHAPERECORD*)realloc(m_MorphShape.EndEdges.ShapeRecords, m_NumberEndShapes*sizeof(SWF_SHAPERECORD)); 
	memcpy(&m_MorphShape.EndEdges.ShapeRecords[m_NumberEndShapes-1], &endShapeRecord, sizeof(SWF_SHAPERECORD)); 
 
	// Build shape bounds rectangle .SWF stream 
	CSWFRectangle startRectangle, endRectangle; 
	startRectangle.SetRectangle(m_MorphShape.StartBounds); 
	endRectangle.SetRectangle(m_MorphShape.EndBounds); 
	UCHAR* pStartRectangleBuffer = startRectangle.BuildSWFStream(); 
	UCHAR* pEndRectangleBuffer = endRectangle.BuildSWFStream(); 
 
	// Calculate total shape tag length 
	m_MorphShape.Header.Length += sizeof(USHORT);							// Length of CharacterID 
	m_MorphShape.Header.Length += startRectangle.GetSWFStreamLength();		// Length of StartBounds rectangle 
	m_MorphShape.Header.Length += endRectangle.GetSWFStreamLength();		// Length of EndBounds rectangle 
	m_MorphShape.Header.Length += sizeof(ULONG);							// Length of Offset field 
	m_MorphShape.Header.Length += 2*sizeof(UCHAR);							// Length of NumLineAndFillBits field 
 
	// Length of FillStyleArray 
	if (m_MorphShape.MorphFillStyles.FillStyleCountExtended != 0) 
	{ 
		// Calculate NumFillIndexBits 
		while (pow(2,numStartFillIndexBits) < (m_MorphShape.MorphFillStyles.FillStyleCountExtended+1)) 
			numStartFillIndexBits++; 
		int fillStyleArraySize = sizeof(UCHAR); 
		if (m_MorphShape.MorphFillStyles.FillStyleCountExtended > 255) 
			fillStyleArraySize += sizeof(USHORT); 
		for (int i=0; i 255) 
			lineStyleArraySize += sizeof(USHORT); 
		m_MorphShape.Header.Length += lineStyleArraySize; 
		m_MorphShape.Offset += lineStyleArraySize; 
	} 
	else 
	{ 
		m_MorphShape.Header.Length += sizeof(UCHAR); 
		m_MorphShape.Offset += sizeof(UCHAR); 
	} 
 
	// Length of StartShapeRecordArray 
	if (m_NumberStartShapes != 0) 
	{ 
		// Build StartRecordArray .SWF stream 
		pStartShapeRecordBuffer = BuildRecordArraySWFStream(numStartLineIndexBits, numStartFillIndexBits, recordStartStreamLength, m_MorphShape.StartEdges.ShapeRecords, m_NumberStartShapes); 
		m_MorphShape.Header.Length += recordStartStreamLength; 
		m_MorphShape.Offset += recordStartStreamLength; 
	} 
	else 
	{ 
		m_MorphShape.Header.Length += sizeof(UCHAR); 
		m_MorphShape.Offset += sizeof(UCHAR); 
	} 
 
	// Length of EndShapeRecordArray 
	if (m_NumberEndShapes != 0) 
	{ 
		// Build EndRecordArray .SWF stream 
		pEndShapeRecordBuffer = BuildRecordArraySWFStream(numEndLineIndexBits, numEndFillIndexBits, recordEndStreamLength, m_MorphShape.EndEdges.ShapeRecords, m_NumberEndShapes); 
		m_MorphShape.Header.Length += recordEndStreamLength; 
	} 
	else 
		m_MorphShape.Header.Length += sizeof(UCHAR); 
	m_MorphShape.Offset++; 
 
	// 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_MorphShape.Header, sizeof(SWF_RECORDHEADER_LONG)); 
	m_SWFStreamLength = newLength; 
 
	// Write CharacterID 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_MorphShape.CharacterID, sizeof(USHORT)); 
	m_SWFStreamLength = newLength; 
 
	// Write StartBounds to .SWF stream 
	newLength = m_SWFStreamLength + startRectangle.GetSWFStreamLength(); 
	if (m_SWFStreamLength == 0) 
		m_SWFStream = (BYTE*)malloc(newLength); 
	else 
		m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength); 
	memcpy(m_SWFStream+m_SWFStreamLength, pStartRectangleBuffer, startRectangle.GetSWFStreamLength()); 
	m_SWFStreamLength = newLength; 
 
	// Write EndBounds to .SWF stream 
	newLength = m_SWFStreamLength + endRectangle.GetSWFStreamLength(); 
	if (m_SWFStreamLength == 0) 
		m_SWFStream = (BYTE*)malloc(newLength); 
	else 
		m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength); 
	memcpy(m_SWFStream+m_SWFStreamLength, pEndRectangleBuffer, endRectangle.GetSWFStreamLength()); 
	m_SWFStreamLength = newLength; 
 
	// Write Offset to .SWF stream 
	newLength = m_SWFStreamLength + sizeof(ULONG); 
	if (m_SWFStreamLength == 0) 
		m_SWFStream = (BYTE*)malloc(newLength); 
	else 
		m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength); 
	memcpy(m_SWFStream+m_SWFStreamLength, &m_MorphShape.Offset, sizeof(ULONG)); 
	m_SWFStreamLength = newLength; 
 
	// Write FillStyleArray to .SWF stream 
	if (m_MorphShape.MorphFillStyles.FillStyleCountExtended != 0) 
	{ 
		if (m_MorphShape.MorphFillStyles.FillStyleCountExtended < 255) 
			m_MorphShape.MorphFillStyles.FillStyleCount = (UCHAR)m_MorphShape.MorphFillStyles.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_MorphShape.MorphFillStyles.FillStyleCount, sizeof(UCHAR)); 
		m_SWFStreamLength = newLength; 
 
		if (m_MorphShape.MorphFillStyles.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_MorphShape.MorphFillStyles.FillStyleCountExtended, sizeof(USHORT)); 
			m_SWFStreamLength = newLength; 
		} 
 
		// Write FillStyles to .SWF stream 
		for (int i=0; i 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_MorphShape.MorphLineStyles.LineStyleCountExtended, sizeof(USHORT)); 
			m_SWFStreamLength = newLength; 
		} 
 
		// Write LineStyles to .SWF stream 
		for (int i=0; i (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 = pRecordArray[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 = pRecordArray[i].SWF_STRAIGHTEDGERECORD.DeltaX << (32-pRecordArray[i].SWF_STRAIGHTEDGERECORD.NumBits); 
				ULONG maskDeltaX = 0x80000000; 
				for (j=0; j> (31-j)) << ((currentByte+1)*8-bitOffset-1)); 
 
					bitOffset++; 
					if ((bitOffset != 0) && (bitOffset % 8) == 0) 
						currentByte++; 
 
					maskDeltaX = maskDeltaX >> 1; 
				} 
 
				// Write DeltaY bit-field 
				ULONG deltaY = pRecordArray[i].SWF_STRAIGHTEDGERECORD.DeltaY << (32-pRecordArray[i].SWF_STRAIGHTEDGERECORD.NumBits); 
				ULONG maskDeltaY = 0x80000000; 
				for (j=0; j> (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*pRecordArray[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 = pRecordArray[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 = pRecordArray[i].SWF_CURVEDEDGERECORD.ControlDeltaX << (32-pRecordArray[i].SWF_CURVEDEDGERECORD.NumBits); 
				ULONG maskControlDeltaX = 0x80000000; 
				for (j=0; j> (31-j)) << ((currentByte+1)*8-bitOffset-1)); 
 
					bitOffset++; 
					if ((bitOffset != 0) && (bitOffset % 8) == 0) 
						currentByte++; 
 
					maskControlDeltaX = maskControlDeltaX >> 1; 
				} 
 
				// Write ControlDeltaY bit-field 
				ULONG controlDeltaY = pRecordArray[i].SWF_CURVEDEDGERECORD.ControlDeltaY << (32-pRecordArray[i].SWF_CURVEDEDGERECORD.NumBits); 
				ULONG maskControlDeltaY = 0x80000000; 
				for (j=0; j> (31-j)) << ((currentByte+1)*8-bitOffset-1)); 
 
					bitOffset++; 
					if ((bitOffset != 0) && (bitOffset % 8) == 0) 
						currentByte++; 
 
					maskControlDeltaY = maskControlDeltaY >> 1; 
				} 
 
				// Write AnchorDeltaX bit-field 
				ULONG anchorDeltaX = pRecordArray[i].SWF_CURVEDEDGERECORD.AnchorDeltaX << (32-pRecordArray[i].SWF_CURVEDEDGERECORD.NumBits); 
				ULONG maskAnchorDeltaX = 0x80000000; 
				for (j=0; j> (31-j)) << ((currentByte+1)*8-bitOffset-1)); 
 
					bitOffset++; 
					if ((bitOffset != 0) && (bitOffset % 8) == 0) 
						currentByte++; 
 
					maskAnchorDeltaX = maskAnchorDeltaX >> 1; 
				} 
 
				// Write AnchorDeltaY bit-field 
				ULONG anchorDeltaY = pRecordArray[i].SWF_CURVEDEDGERECORD.AnchorDeltaY << (32-pRecordArray[i].SWF_CURVEDEDGERECORD.NumBits); 
				ULONG maskAnchorDeltaY = 0x80000000; 
				for (j=0; j> (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 (pRecordArray[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x01) 
					numBits += (5 + 2*pRecordArray[i].SWF_STYLECHANGERECORD.MoveBits); 
 
				// StateFillStyle0 bit-field 
				if (pRecordArray[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x02) 
					numBits += numFillIndexBits; 
 
				// StateFillStyle1 bit-field 
				if (pRecordArray[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x04) 
					numBits += numFillIndexBits; 
 
				// StateLineStyle bit-field 
				if (pRecordArray[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 = pRecordArray[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 (pRecordArray[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x01) 
				{ 
					int j; 
					BYTE shapeMoveBits = pRecordArray[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 = pRecordArray[i].SWF_STYLECHANGERECORD.MoveDeltaX << (32-pRecordArray[i].SWF_STYLECHANGERECORD.MoveBits); 
					ULONG maskMoveX = 0x80000000; 
					for (j=0; j> (31-j)) << ((currentByte+1)*8-bitOffset-1)); 
 
						bitOffset++; 
						if ((bitOffset != 0) && (bitOffset % 8) == 0) 
							currentByte++; 
 
						maskMoveX = maskMoveX >> 1; 
					} 
 
					// Write MoveDeltaY bit-field 
					ULONG moveDeltaY = pRecordArray[i].SWF_STYLECHANGERECORD.MoveDeltaY << (32-pRecordArray[i].SWF_STYLECHANGERECORD.MoveBits); 
					ULONG maskMoveY = 0x80000000; 
					for (j=0; j> (31-j)) << ((currentByte+1)*8-bitOffset-1)); 
 
						bitOffset++; 
						if ((bitOffset != 0) && (bitOffset % 8) == 0) 
							currentByte++; 
 
						maskMoveY = maskMoveY >> 1; 
					} 
				} 
 
				// Write StateFillStyle0 bit-field 
				if (pRecordArray[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x02) 
				{ 
					WORD shapeFillStyleBits = pRecordArray[i].SWF_STYLECHANGERECORD.FillStyle0 << (16-numFillIndexBits); 
					WORD mask = 0x8000; 
					for (int j=0; j> (15-j)) << ((currentByte+1)*8-bitOffset-1)); 
 
						bitOffset++; 
						if ((bitOffset != 0) && (bitOffset % 8) == 0) 
							currentByte++; 
 
						mask = mask >> 1; 
					} 
				} 
 
				// Write StateFillStyle1 bit-field 
				if (pRecordArray[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x04) 
				{ 
					WORD shapeFillStyleBits = pRecordArray[i].SWF_STYLECHANGERECORD.FillStyle1 << (16-numFillIndexBits); 
					WORD mask = 0x8000; 
					for (int j=0; j> (15-j)) << ((currentByte+1)*8-bitOffset-1)); 
 
						bitOffset++; 
						if ((bitOffset != 0) && (bitOffset % 8) == 0) 
							currentByte++; 
 
						mask = mask >> 1; 
					} 
				} 
 
				// Write StateLineStyle bit-field 
				if (pRecordArray[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x08) 
				{ 
					WORD shapeLineStyleBits = pRecordArray[i].SWF_STYLECHANGERECORD.LineStyle << (16-numLineIndexBits); 
					WORD mask = 0x8000; 
					for (int j=0; j> (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 CSWFMorphShape::Scale(float scaleX, float scaleY) 
{ 
	MATRIX_F matrix; 
	m_TransformationMatrix.GetMatrix(matrix); 
 
	matrix.scaleX = scaleX; 
	matrix.scaleY = scaleY; 
 
	m_TransformationMatrix.SetMatrix(matrix); 
} 
 
void CSWFMorphShape::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 CSWFMorphShape::Translate(float translateX, float translateY) 
{ 
	MATRIX_F matrix; 
	m_TransformationMatrix.GetMatrix(matrix); 
 
	matrix.translateX = translateX; 
	matrix.translateY = translateY; 
 
	m_TransformationMatrix.SetMatrix(matrix); 
} 
 
void CSWFMorphShape::Shear(float shearX, float shearY) 
{ 
	MATRIX_F matrix; 
	m_TransformationMatrix.GetMatrix(matrix); 
 
	matrix.rotateSkew0 = shearX; 
	matrix.rotateSkew1 = shearY; 
 
	m_TransformationMatrix.SetMatrix(matrix); 
}