// 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<m_MorphShape.MorphFillStyles.FillStyleCountExtended; i++)
{
if ((m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_LINEARGRADIENT) ||
(m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_RADIALGRADIENT))
{
delete m_MorphShape.MorphFillStyles.FillStyles[i].Gradient.GradientRecords;
m_MorphShape.MorphFillStyles.FillStyles[i].Gradient.GradientRecords = NULL;
}
}
free(m_MorphShape.MorphFillStyles.FillStyles);
m_MorphShape.MorphFillStyles.FillStyles = NULL;
}
// Free ShapeRecordsArray
if (m_MorphShape.StartEdges.ShapeRecords != NULL)
{
free(m_MorphShape.StartEdges.ShapeRecords);
m_MorphShape.StartEdges.ShapeRecords = NULL;
}
if (m_MorphShape.EndEdges.ShapeRecords != NULL)
{
free(m_MorphShape.EndEdges.ShapeRecords);
m_MorphShape.EndEdges.ShapeRecords = NULL;
}
if (m_SWFStream != NULL)
{
delete m_SWFStream;
m_SWFStream = NULL;
}
}
void CSWFMorphShape::AddLineStyle(int startWidth, SWF_RGBA startColor, int endWidth, SWF_RGBA endColor)
{
// Define new LineStyle entry
SWF_MORPHLINESTYLE lineStyleEntry;
memset(&lineStyleEntry, 0, sizeof(SWF_MORPHLINESTYLE));
lineStyleEntry.StartWidth = (USHORT)(startWidth*20);
lineStyleEntry.EndWidth = (USHORT)(endWidth*20);
memcpy(&lineStyleEntry.StartColor, &startColor, sizeof(SWF_RGBA));
memcpy(&lineStyleEntry.EndColor, &endColor, sizeof(SWF_RGBA));
// Add new LineStyle entry to the LineStyleArray
m_MorphShape.MorphLineStyles.LineStyleCountExtended++;
if (m_MorphShape.MorphLineStyles.LineStyles == NULL)
m_MorphShape.MorphLineStyles.LineStyles = (SWF_MORPHLINESTYLE*)malloc(sizeof(SWF_MORPHLINESTYLE));
else
m_MorphShape.MorphLineStyles.LineStyles = (SWF_MORPHLINESTYLE*)realloc(m_MorphShape.MorphLineStyles.LineStyles, m_MorphShape.MorphLineStyles.LineStyleCountExtended*sizeof(SWF_MORPHLINESTYLE));
memcpy(&m_MorphShape.MorphLineStyles.LineStyles[m_MorphShape.MorphLineStyles.LineStyleCountExtended-1], &lineStyleEntry, sizeof(SWF_MORPHLINESTYLE));
}
void CSWFMorphShape::AddSolidFillStyle(SWF_RGBA startColor, SWF_RGBA endColor)
{
// Define new FillStyle entry
SWF_MORPHFILLSTYLE fillStyleEntry;
memset(&fillStyleEntry, 0, sizeof(SWF_MORPHFILLSTYLE));
fillStyleEntry.FillStyleType = SWF_FILLSTYLETYPE_SOLID;
memcpy(&fillStyleEntry.StartColor, &startColor, sizeof(SWF_RGBA));
memcpy(&fillStyleEntry.EndColor, &endColor, sizeof(SWF_RGBA));
// 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::AddGradientFillStyle(UCHAR gradientFillType, RECT_F startGradientRect, RECT_F endGradientRect, SWF_MORPHGRADIENTRECORD* gradientRecords, int numRecords)
{
if ((numRecords > 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<m_MorphShape.MorphFillStyles.FillStyleCountExtended; i++)
{
if (m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_SOLID)
fillStyleArraySize += (sizeof(UCHAR) + 2*sizeof(SWF_RGBA));
else if ((m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_LINEARGRADIENT) ||
(m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_RADIALGRADIENT))
{
CSWFMatrix startGradientMatrix, endGradientMatrix;
startGradientMatrix.SetMatrix(m_MorphShape.MorphFillStyles.FillStyles[i].StartGradientMatrix);
endGradientMatrix.SetMatrix(m_MorphShape.MorphFillStyles.FillStyles[i].EndGradientMatrix);
startGradientMatrix.BuildSWFStream();
endGradientMatrix.BuildSWFStream();
fillStyleArraySize += 2*sizeof(UCHAR);
fillStyleArraySize += startGradientMatrix.GetSWFStreamLength();
fillStyleArraySize += endGradientMatrix.GetSWFStreamLength();
fillStyleArraySize += m_MorphShape.MorphFillStyles.FillStyles[i].Gradient.NumGradients*sizeof(SWF_MORPHGRADIENTRECORD);
}
else if ((m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_0) || (m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_1) ||
(m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_2) || (m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_3))
{
CSWFMatrix startBitmapMatrix, endBitmapMatrix;
startBitmapMatrix.SetMatrix(m_MorphShape.MorphFillStyles.FillStyles[i].StartBitmapMatrix);
endBitmapMatrix.SetMatrix(m_MorphShape.MorphFillStyles.FillStyles[i].EndBitmapMatrix);
startBitmapMatrix.BuildSWFStream();
endBitmapMatrix.BuildSWFStream();
fillStyleArraySize += (sizeof(UCHAR) + sizeof(USHORT));
fillStyleArraySize += startBitmapMatrix.GetSWFStreamLength();
fillStyleArraySize += endBitmapMatrix.GetSWFStreamLength();
}
}
m_MorphShape.Header.Length += fillStyleArraySize;
m_MorphShape.Offset += fillStyleArraySize;
}
else
{
m_MorphShape.Header.Length += sizeof(UCHAR);
m_MorphShape.Offset += sizeof(UCHAR);
}
// Length of LineStyleArray
if (m_MorphShape.MorphLineStyles.LineStyleCountExtended != 0)
{
// Calculate NumLineIndexBits
while (pow(2,numStartLineIndexBits) < (m_MorphShape.MorphLineStyles.LineStyleCountExtended+1))
numStartLineIndexBits++;
int lineStyleArraySize = sizeof(UCHAR) + m_MorphShape.MorphLineStyles.LineStyleCountExtended*sizeof(SWF_MORPHLINESTYLE);
if (m_MorphShape.MorphLineStyles.LineStyleCountExtended > 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<m_MorphShape.MorphFillStyles.FillStyleCountExtended; i++)
{
// Write FillStyle to .SWF stream
if (m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_SOLID)
{
newLength = m_SWFStreamLength + sizeof(UCHAR) + 2*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_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType, sizeof(UCHAR));
memcpy(m_SWFStream+m_SWFStreamLength+sizeof(UCHAR), &m_MorphShape.MorphFillStyles.FillStyles[i].StartColor, sizeof(SWF_RGBA));
memcpy(m_SWFStream+m_SWFStreamLength+sizeof(UCHAR)+sizeof(SWF_RGBA), &m_MorphShape.MorphFillStyles.FillStyles[i].EndColor, sizeof(SWF_RGBA));
m_SWFStreamLength = newLength;
}
else if ((m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_LINEARGRADIENT) ||
(m_MorphShape.MorphFillStyles.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_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType, sizeof(UCHAR));
m_SWFStreamLength = newLength;
CSWFMatrix startGradientMatrix, endGradientMatrix;
startGradientMatrix.SetMatrix(m_MorphShape.MorphFillStyles.FillStyles[i].StartGradientMatrix);
UCHAR* pStartGradientMatrixBuffer = startGradientMatrix.BuildSWFStream();
int nStartGradientMatrixLength = startGradientMatrix.GetSWFStreamLength();
endGradientMatrix.SetMatrix(m_MorphShape.MorphFillStyles.FillStyles[i].EndGradientMatrix);
UCHAR* pEndGradientMatrixBuffer = endGradientMatrix.BuildSWFStream();
int nEndGradientMatrixLength = endGradientMatrix.GetSWFStreamLength();
newLength = m_SWFStreamLength + nStartGradientMatrixLength + nEndGradientMatrixLength;
if (m_SWFStreamLength == 0)
m_SWFStream = (BYTE*)malloc(newLength);
else
m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
memcpy(m_SWFStream+m_SWFStreamLength, pStartGradientMatrixBuffer, nStartGradientMatrixLength);
memcpy(m_SWFStream+m_SWFStreamLength+nStartGradientMatrixLength, pEndGradientMatrixBuffer, nEndGradientMatrixLength);
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_MorphShape.MorphFillStyles.FillStyles[i].Gradient.NumGradients, sizeof(UCHAR));
m_SWFStreamLength = newLength;
for (int j=0; j<m_MorphShape.MorphFillStyles.FillStyles[i].Gradient.NumGradients; j++)
{
newLength = m_SWFStreamLength + 2*(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_MorphShape.MorphFillStyles.FillStyles[i].Gradient.GradientRecords[j].StartRatio, sizeof(UCHAR));
memcpy(m_SWFStream+m_SWFStreamLength+sizeof(UCHAR), &m_MorphShape.MorphFillStyles.FillStyles[i].Gradient.GradientRecords[j].StartColor, sizeof(SWF_RGBA));
memcpy(m_SWFStream+m_SWFStreamLength+sizeof(UCHAR)+sizeof(SWF_RGBA), &m_MorphShape.MorphFillStyles.FillStyles[i].Gradient.GradientRecords[j].EndRatio, sizeof(UCHAR));
memcpy(m_SWFStream+m_SWFStreamLength+sizeof(UCHAR)+sizeof(SWF_RGBA)+sizeof(UCHAR), &m_MorphShape.MorphFillStyles.FillStyles[i].Gradient.GradientRecords[j].EndColor, sizeof(SWF_RGBA));
m_SWFStreamLength = newLength;
}
}
else if ((m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_0) || (m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_1) ||
(m_MorphShape.MorphFillStyles.FillStyles[i].FillStyleType == SWF_FILLSTYLETYPE_BITMAP_2) || (m_MorphShape.MorphFillStyles.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_MorphShape.MorphFillStyles.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_MorphShape.MorphFillStyles.FillStyles[i].BitmapID, sizeof(USHORT));
m_SWFStreamLength = newLength;
CSWFMatrix startBitmapMatrix, endBitmapMatrix;
startBitmapMatrix.SetMatrix(m_MorphShape.MorphFillStyles.FillStyles[i].StartBitmapMatrix);
UCHAR* pStartBitmapMatrixBuffer = startBitmapMatrix.BuildSWFStream();
int nStartBitmapMatrixLength = startBitmapMatrix.GetSWFStreamLength();
endBitmapMatrix.SetMatrix(m_MorphShape.MorphFillStyles.FillStyles[i].EndBitmapMatrix);
UCHAR* pEndBitmapMatrixBuffer = endBitmapMatrix.BuildSWFStream();
int nEndBitmapMatrixLength = endBitmapMatrix.GetSWFStreamLength();
newLength = m_SWFStreamLength + nStartBitmapMatrixLength + nEndBitmapMatrixLength;
if (m_SWFStreamLength == 0)
m_SWFStream = (BYTE*)malloc(newLength);
else
m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
memcpy(m_SWFStream+m_SWFStreamLength, pStartBitmapMatrixBuffer, nStartBitmapMatrixLength);
memcpy(m_SWFStream+m_SWFStreamLength+nStartBitmapMatrixLength, pEndBitmapMatrixBuffer, nEndBitmapMatrixLength);
m_SWFStreamLength = newLength;
}
}
}
else
{
// Write empty FillStyleArray to .SWF stream
m_MorphShape.MorphFillStyles.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_MorphShape.MorphFillStyles.FillStyleCount, sizeof(UCHAR));
m_SWFStreamLength = newLength;
}
// Write LineStyleArray to .SWF stream
if (m_MorphShape.MorphLineStyles.LineStyleCountExtended != 0)
{
if (m_MorphShape.MorphLineStyles.LineStyleCountExtended < 255)
m_MorphShape.MorphLineStyles.LineStyleCount = (UCHAR)m_MorphShape.MorphLineStyles.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_MorphShape.MorphLineStyles.LineStyleCount, sizeof(UCHAR));
m_SWFStreamLength = newLength;
if (m_MorphShape.MorphLineStyles.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_MorphShape.MorphLineStyles.LineStyleCountExtended, sizeof(USHORT));
m_SWFStreamLength = newLength;
}
// Write LineStyles to .SWF stream
for (int i=0; i<m_MorphShape.MorphLineStyles.LineStyleCountExtended; i++)
{
// Write LineStyle to .SWF stream
newLength = m_SWFStreamLength + sizeof(SWF_MORPHLINESTYLE);
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.LineStyles[i], sizeof(SWF_MORPHLINESTYLE));
m_SWFStreamLength = newLength;
}
}
else
{
// Write empty LineStyleArray to .SWF stream
m_MorphShape.MorphLineStyles.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_MorphShape.MorphLineStyles.LineStyleCount, sizeof(UCHAR));
m_SWFStreamLength = newLength;
}
// Write NumStartFillAndLineBits to .SWF stream
UCHAR numStartLineAndFillIndexBits = (numStartFillIndexBits<<4) | numStartLineIndexBits;
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, &numStartLineAndFillIndexBits, sizeof(UCHAR));
m_SWFStreamLength = newLength;
// Write StartShapeRecordArray to .SWF stream
if (pStartShapeRecordBuffer != NULL)
{
newLength = m_SWFStreamLength + recordStartStreamLength;
if (m_SWFStreamLength == 0)
m_SWFStream = (BYTE*)malloc(newLength);
else
m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
memcpy(m_SWFStream+m_SWFStreamLength, pStartShapeRecordBuffer, recordStartStreamLength);
m_SWFStreamLength = newLength;
// Free memory
free(pStartShapeRecordBuffer);
}
// Write NumEndFillAndLineBits to .SWF stream
UCHAR numEndLineAndFillIndexBits = (numEndFillIndexBits<<4) | numEndLineIndexBits;
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, &numEndLineAndFillIndexBits, sizeof(UCHAR));
m_SWFStreamLength = newLength;
// Write EndShapeRecordArray to .SWF stream
if (pEndShapeRecordBuffer != NULL)
{
newLength = m_SWFStreamLength + recordEndStreamLength;
if (m_SWFStreamLength == 0)
m_SWFStream = (BYTE*)malloc(newLength);
else
m_SWFStream = (BYTE*)realloc(m_SWFStream, newLength);
memcpy(m_SWFStream+m_SWFStreamLength, pEndShapeRecordBuffer, recordEndStreamLength);
m_SWFStreamLength = newLength;
// Free memory
free(pEndShapeRecordBuffer);
}
return m_SWFStream;
}
int CSWFMorphShape::GetSWFStreamLength()
{
return m_SWFStreamLength;
}
UCHAR* CSWFMorphShape::BuildRecordArraySWFStream(int numLineIndexBits, int numFillIndexBits, int& recordStreamLength, SWF_SHAPERECORD* pRecordArray, int numShapes)
{
UCHAR* pShapeRecordBuffer = NULL;
int numBits=0, bitOffset=0, allocBytes=0;
recordStreamLength = 0;
// Write ShapeRecords to .SWF stream
for (int i=0; i<numShapes; i++)
{
BOOL bEdgeTypeRecord = pRecordArray[i].SWF_ENDSHAPERECORD.ShapeFlags & 0x20;
BOOL bStraightEdge = pRecordArray[i].SWF_ENDSHAPERECORD.ShapeFlags & 0x10;
BOOL bStyleChangeRecord = pRecordArray[i].SWF_ENDSHAPERECORD.ShapeFlags & 0x0F;
// Edge type record (StraightEdgeRecord or CurvedEdgeRecord);
if (bEdgeTypeRecord)
{
// StraightEdgeRecord type
if (bStraightEdge)
{
// ShapeFlags bit-field
numBits += (7 + 2*pRecordArray[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 = 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<pRecordArray[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 = pRecordArray[i].SWF_STRAIGHTEDGERECORD.DeltaY << (32-pRecordArray[i].SWF_STRAIGHTEDGERECORD.NumBits);
ULONG maskDeltaY = 0x80000000;
for (j=0; j<pRecordArray[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*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<pRecordArray[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 = pRecordArray[i].SWF_CURVEDEDGERECORD.ControlDeltaY << (32-pRecordArray[i].SWF_CURVEDEDGERECORD.NumBits);
ULONG maskControlDeltaY = 0x80000000;
for (j=0; j<pRecordArray[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 = pRecordArray[i].SWF_CURVEDEDGERECORD.AnchorDeltaX << (32-pRecordArray[i].SWF_CURVEDEDGERECORD.NumBits);
ULONG maskAnchorDeltaX = 0x80000000;
for (j=0; j<pRecordArray[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 = pRecordArray[i].SWF_CURVEDEDGERECORD.AnchorDeltaY << (32-pRecordArray[i].SWF_CURVEDEDGERECORD.NumBits);
ULONG maskAnchorDeltaY = 0x80000000;
for (j=0; j<pRecordArray[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 (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<pRecordArray[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 = pRecordArray[i].SWF_STYLECHANGERECORD.MoveDeltaY << (32-pRecordArray[i].SWF_STYLECHANGERECORD.MoveBits);
ULONG maskMoveY = 0x80000000;
for (j=0; j<pRecordArray[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 (pRecordArray[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x02)
{
WORD shapeFillStyleBits = pRecordArray[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 (pRecordArray[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x04)
{
WORD shapeFillStyleBits = pRecordArray[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 (pRecordArray[i].SWF_STYLECHANGERECORD.ShapeFlags & 0x08)
{
WORD shapeLineStyleBits = pRecordArray[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 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);
}