Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
FlashParser.c
////////// |
// |
// File: FlashParser.c |
// |
// Contains: Sample code for . |
// |
// Written by: |
// |
// Copyright: © 1999 by Apple Computer, Inc., all rights reserved. |
// |
// Change History (most recent first): |
// |
////////// |
#include "FlashParser.h" |
/*__________________________________________________________________________________________ |
QuickTime Mouse Event to Flash Mouse Event Mappings: |
kQTEventMouseClick |
bsOverUpToOverDown |
kQTEventMouseClickEnd |
if ( stagDefineButton2:trackAsMenu == false ) |
bsOutDownToIdle |
kQTEventMouseClickEndTriggerButton |
bsOverDownToOverUp |
kQTEventMouseEnter |
bsIdleToOverUp |
if ( stagDefineButton2:trackAsMenu == true ) |
bsIdleToOverDown |
else |
bsOutDownToOverDown |
kQTEventMouseExit |
bsOverUpToIdle |
if ( stagDefineButton2:trackAsMenu == true ) |
bsOverDownToIdle |
else |
bsOverDownToOutDown |
__________________________________________________________________________________________*/ |
FlashParserStruct gFlashParserData; |
/* |
GetByte |
Extract one byte from the data stream |
*/ |
inline U8 GetByte () |
{ |
return gFlashParserData.m_fileBuf [gFlashParserData.m_filePos++]; |
} |
/* |
GetWord |
Extract and byte flip one word from the data stream |
*/ |
inline U16 GetWord () |
{ |
U8 * s = gFlashParserData.m_fileBuf + gFlashParserData.m_filePos; |
gFlashParserData.m_filePos += 2; |
return (U16) s[0] | ((U16) s[1] << 8); |
} |
/* |
GetDWord |
Extract and byte flip one long word from the data stream |
*/ |
inline U32 GetDWord () |
{ |
U8 * s = gFlashParserData.m_fileBuf + gFlashParserData.m_filePos; |
gFlashParserData.m_filePos += 4; |
return (U32) s[0] | ((U32) s[1] << 8) | ((U32) s[2] << 16) | ((U32) s [3] << 24); |
} |
char * GetAString() |
{ |
// Point to the string. |
char *str = (char *) &gFlashParserData.m_fileBuf[gFlashParserData.m_filePos]; |
// Skip over the string. |
while (GetByte()); |
return str; |
} |
/* |
InitBits |
Reset the bit position and buffer. |
*/ |
void InitBits() |
{ |
gFlashParserData.m_bitPos = 0; |
gFlashParserData.m_bitBuf = 0; |
} |
U32 GetBits (S32 n) |
{ |
U32 v = 0; |
for (;;) |
{ |
S32 s = n - gFlashParserData.m_bitPos; |
if (s > 0) |
{ |
// Consume the entire buffer |
v |= gFlashParserData.m_bitBuf << s; |
n -= gFlashParserData.m_bitPos; |
// Get the next buffer |
gFlashParserData.m_bitBuf = GetByte(); |
gFlashParserData.m_bitPos = 8; |
} |
else |
{ |
// Consume a portion of the buffer |
v |= gFlashParserData.m_bitBuf >> -s; |
gFlashParserData.m_bitPos -= n; |
gFlashParserData.m_bitBuf &= 0xff >> (8 - gFlashParserData.m_bitPos); // mask off the consumed bits |
return v; |
} |
} |
} |
/* |
GetSBits |
Get n bits from the string with sign extension. |
*/ |
S32 GetSBits (S32 n) |
{ |
// Get the number as an unsigned value. |
S32 v = (S32) GetBits(n); |
// Is the number negative? |
if (v & (1L << (n - 1))) |
{ |
// Yes. Extend the sign. |
v |= -1L << n; |
} |
return v; |
} |
void GetRect (SRECT * r) |
{ |
int nBits; |
InitBits (); |
nBits = (int) GetBits(5); |
r->xmin = GetSBits(nBits); |
r->xmax = GetSBits(nBits); |
r->ymin = GetSBits(nBits); |
r->ymax = GetSBits(nBits); |
} |
/* |
GetTag |
Extract tag id and tag length from the data stream |
*/ |
U16 GetTag () |
{ |
U16 code; |
U32 len; |
// Save the start of the tag. |
gFlashParserData.m_tagStart = gFlashParserData.m_filePos; |
// Get the combined code and length of the tag. |
code = GetWord (); |
// The length is encoded in the tag. |
len = code & 0x3f; |
// Remove the length from the code. |
code = code >> 6; |
// Determine if another long word must be read to get the length. |
if (len == 0x3f) len = (U32) GetDWord (); |
// Determine the end position of the tag. |
gFlashParserData.m_tagEnd = gFlashParserData.m_filePos + (U32) len; |
gFlashParserData.m_tagLen = (U32) len; |
return code; |
} |
/* |
SetNewHeaderLengthTagLength |
Modifies the tag length portion of button tag to reflect change in size of tag, and stream header filelength |
If the length of the data is greater than a byte, an additional long is required to |
store the data length in the tag. |
*/ |
void SetNewHeaderLengthTagLength (U32 fileDifference, U32 tagDifference) |
{ |
OSErr theErr; |
U16 code, |
newCode; |
U8 * s; |
U32 length, |
fileLength; |
long handleSize; |
Boolean wasDouble = false; |
HLock (gFlashParserData.m_theData); |
s = (U8 *) *gFlashParserData.m_theData + 4; |
fileLength = (U32) s[0] | ((U32) s[1] << 8) | ((U32) s[2] << 16) | ((U32) s [3] << 24); |
fileLength += fileDifference; |
s [0] = (fileLength & 0xFF); |
s [1] = ((fileLength >> 8) & 0xFF); |
s [2] = ((fileLength >> 16) & 0xFF); |
s [3] = ((fileLength >> 24) & 0xFF); |
s = (U8 *) *gFlashParserData.m_theData + gFlashParserData.m_tagStart; |
// Get the combined code and length of the tag. |
code = (U16) s[0] | ((U16) s[1] << 8); |
// The length is encoded in the tag. |
length = code & 0x3f; |
// Remove the length from the code. |
code = code >> 6; |
// Determine if another long word must be read to get the length. |
if (length == 0x3f) |
{ |
s += sizeof (U16); |
length = (U32) s[0] | ((U32) s[1] << 8) | ((U32) s[2] << 16) | ((U32) s [3] << 24); |
wasDouble = true; |
} |
HUnlock (gFlashParserData.m_theData); |
length += tagDifference; |
if (length >= 0x3F) |
{ |
newCode = (code << 6) | 0x3F; |
if (!wasDouble) // need more space |
{ |
handleSize = GetHandleSize (gFlashParserData.m_theData); |
handleSize += sizeof (long); |
SetHandleSize (gFlashParserData.m_theData, handleSize); |
theErr = MemError (); |
if (theErr != noErr) |
goto Bail; |
// now shift the data up |
HLock (gFlashParserData.m_theData); |
BlockMove (*gFlashParserData.m_theData + gFlashParserData.m_tagStart, *gFlashParserData.m_theData + gFlashParserData.m_tagStart + sizeof (long), |
(handleSize - sizeof (long)) - gFlashParserData.m_tagStart); |
HUnlock (gFlashParserData.m_theData); |
fileLength += sizeof (long); |
} |
HLock (gFlashParserData.m_theData); |
s = (U8 *) *gFlashParserData.m_theData + 4; |
s [0] = (fileLength & 0xFF); |
s [1] = ((fileLength >> 8) & 0xFF); |
s [2] = ((fileLength >> 16) & 0xFF); |
s [3] = ((fileLength >> 24) & 0xFF); |
s = (U8 *) *gFlashParserData.m_theData + gFlashParserData.m_tagStart; |
s [0] = (newCode & 0xFF); |
s [1] = ((newCode >> 8) & 0xFF); |
s += sizeof (U16); |
s [0] = (length & 0xFF); |
s [1] = ((length >> 8) & 0xFF); |
s [2] = ((length >> 16) & 0xFF); |
s [3] = ((length >> 24) & 0xFF); |
HUnlock (gFlashParserData.m_theData); |
} |
else |
{ |
newCode = (U16) (code << 6) | (U16) (length & 0x3F); |
if (wasDouble) |
{ |
handleSize = GetHandleSize (gFlashParserData.m_theData); |
handleSize -= sizeof (long); |
// shift the data down |
HLock (gFlashParserData.m_theData); |
BlockMove (*gFlashParserData.m_theData + gFlashParserData.m_tagStart + sizeof (long), *gFlashParserData.m_theData + gFlashParserData.m_tagStart, |
(handleSize - sizeof (long)) - gFlashParserData.m_tagStart); |
HUnlock (gFlashParserData.m_theData); |
SetHandleSize (gFlashParserData.m_theData, handleSize); |
theErr = MemError (); |
if (theErr != noErr) |
goto Bail; |
fileLength -= sizeof (long); |
} |
HLock (gFlashParserData.m_theData); |
s = (U8 *) *gFlashParserData.m_theData + 4; |
s [0] = (fileLength & 0xFF); |
s [1] = ((fileLength >> 8) & 0xFF); |
s [2] = ((fileLength >> 16) & 0xFF); |
s [3] = ((fileLength >> 24) & 0xFF); |
s = (U8 *) *gFlashParserData.m_theData + gFlashParserData.m_tagStart; |
s [0] = (newCode & 0xFF); |
s [1] = ((newCode >> 8) & 0xFF); |
HUnlock (gFlashParserData.m_theData); |
} |
Bail: |
return; |
} |
/* |
ParseTags |
Parses the tags within the file. |
*/ |
void ParseTags (Boolean sprite, long *buttonID) |
{ |
BOOL atEnd; |
U16 code; |
U32 tagEnd; |
if (sprite) |
{ |
U32 tagid = (U32) GetWord (); |
U32 frameCount = (U32) GetWord (); |
} |
else |
{ |
// Set the position to the start position. |
gFlashParserData.m_filePos = gFlashParserData.m_fileStart; |
} |
// Initialize the end of frame flag. |
atEnd = false; |
// Loop through each tag. |
while (!atEnd) |
{ |
// Get the current tag. |
code = GetTag(); |
// Get the tag ending position. |
tagEnd = gFlashParserData.m_tagEnd; |
switch (code) |
{ |
case stagEnd: |
// We reached the end of the file. |
atEnd = true; |
break; |
case stagDefineButton2: |
*buttonID = (U32) GetWord(); |
atEnd = true; |
break; |
case stagDefineSprite: |
ParseTags (true, buttonID); |
break; |
default: |
break; |
} |
// Increment past the tag. |
gFlashParserData.m_filePos = tagEnd; |
} |
} |
/* |
GetOffsetForButton |
Returns offset in data stream of button data of buttonID |
*/ |
U32 GetOffsetForButton (long buttonID) |
{ |
SRECT rect; |
U32 frameRate, |
frameCount; |
BOOL atEnd = false; |
U32 frame = 0, |
tagid; |
gFlashParserData.m_fileBuf = (U8 *) *gFlashParserData.m_theData; |
// Set the file position past the header and size information. |
gFlashParserData.m_filePos = 8; |
GetRect (&rect); |
frameRate = GetWord () >> 8; |
frameCount = GetWord (); |
gFlashParserData.m_fileStart = gFlashParserData.m_filePos; |
// ParseTags (false, 0); |
// Loop through each tag. |
while (!atEnd) |
{ |
// Get the current tag. |
U16 code = GetTag(); |
// Get the tag ending position. |
U32 tagEnd = gFlashParserData.m_tagEnd; |
switch (code) |
{ |
case stagEnd: |
// We reached the end of the file. |
atEnd = true; |
break; |
case stagDefineButton2: |
tagid = (U32) GetWord (); |
if (tagid == buttonID) |
{ |
return gFlashParserData.m_tagStart; |
} |
break; |
default: |
break; |
} |
// Increment past the tag. |
gFlashParserData.m_filePos = tagEnd; |
} |
return 0; |
} |
/* |
GetOffsetForFrame |
Returns offset in data stream of frame of frameID |
Zero based |
*/ |
void GetOffsetForFrame (long frameID, U32 *frameStart, U32 *frameEnd) |
{ |
SRECT rect; |
U32 frameRate, |
frameCount, |
lastFrameFilePos; |
U32 frame = 0; |
// tagid; |
BOOL atEnd = false; |
gFlashParserData.m_fileBuf = (U8 *) *gFlashParserData.m_theData; |
// Set the file position past the header and size information. |
gFlashParserData.m_filePos = 8; |
GetRect (&rect); |
frameRate = GetWord () >> 8; |
frameCount = GetWord (); |
gFlashParserData.m_fileStart = gFlashParserData.m_filePos; |
lastFrameFilePos = gFlashParserData.m_fileStart; |
// Loop through each tag. |
while (!atEnd) |
{ |
// Get the current tag. |
U16 code = GetTag(); |
// Get the tag ending position. |
U32 tagEnd = gFlashParserData.m_tagEnd; |
switch (code) |
{ |
case stagEnd: |
// We reached the end of the file. |
atEnd = true; |
break; |
case stagShowFrame: |
if (frame == frameID) |
{ |
*frameStart = lastFrameFilePos; |
*frameEnd = gFlashParserData.m_tagStart; |
return; |
} |
lastFrameFilePos = gFlashParserData.m_tagStart; |
++frame; |
break; |
default: |
break; |
} |
// Increment past the tag. |
gFlashParserData.m_filePos = tagEnd; |
} |
if (frameCount == 1) |
{ |
*frameStart = gFlashParserData.m_fileStart; |
*frameEnd = gFlashParserData.m_tagStart; |
} |
else |
{ |
*frameStart = 0; |
*frameEnd = 0; |
} |
} |
void Initialize (void) |
{ |
// Initialize the input pointer. |
gFlashParserData.m_fileBuf = NULL; |
// Initialize the file information. |
gFlashParserData.m_filePos = 0; |
gFlashParserData.m_fileSize = 0; |
gFlashParserData.m_fileStart = 0; |
gFlashParserData.m_fileVersion = 0; |
// Initialize the bit position and buffer. |
gFlashParserData.m_bitPos = 0; |
gFlashParserData.m_bitBuf = 0; |
} |
/* |
Locate the first button in the data stream |
*/ |
OSErr LocateFirstButton (Handle theSample, long *buttonID) |
{ |
OSErr theErr = noErr; |
SRECT rect; |
U32 frameRate, |
frameCount; |
*buttonID = 0; |
Initialize (); |
gFlashParserData.m_theData = theSample; |
HLock (theSample); |
gFlashParserData.m_fileBuf = (U8 *) *theSample; |
// Set the file position past the header and size information. |
gFlashParserData.m_filePos = 8; |
GetRect (&rect); |
frameRate = GetWord () >> 8; |
frameCount = GetWord (); |
gFlashParserData.m_fileStart = gFlashParserData.m_filePos; |
ParseTags (false, buttonID); |
HUnlock (theSample); |
return theErr; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-02-25