swfexpdc.cpp

Go to the documentation of this file.
00001 // $Id: swfexpdc.cpp 1314 2006-06-14 08:58:56Z builder1 $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 #include <math.h>
00099 #include <string.h>
00100 
00101 #include "camtypes.h"
00102 
00103 #include "camelot.h"
00104 #include "colormgr.h"
00105 //#include "colmodel.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 #include "bevtrap.h"
00108 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 #include "fillramp.h"
00110 //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 //#include "attr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 //#include "pathtype.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "pathutil.h"
00114 
00115 //#include "ccfile.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00116 //#include "docrect.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00117 //#include "doccolor.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00118 //#include "zstream.h"
00119 
00120 #include "fontman.h"
00121 //#include "app.h"          // For FONTMANAGER - in camtypes.h [AUTOMATICALLY REMOVED]
00122 
00123 //#include "filters.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00124 #include "prvwflt.h"
00125 #include "pngfiltr.h"
00126 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00127 #include "swfrndr.h"
00128 #include "kerneldc.h"
00129 #include "swfexpdc.h"
00130 
00131 #define new CAM_DEBUG_NEW
00132 
00133 /********************************************************************************************
00134 
00135 >   FlashExportDC::FlashExportDC( Filter *Parent )
00136 
00137     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00138     Created:    15/12/99
00139     Purpose:    Default constructor: Creates a DC for exporting Flash files.
00140     SeeAlso:    ExportDC::ExportDC
00141 
00142 ********************************************************************************************/
00143 
00144 FlashExportDC::FlashExportDC () : ExportDC ( NULL )
00145 {
00146     // Set the output variables to their correct setting.
00147     m_bOutput = 0;
00148     m_bCurrentBit = 7;
00149     mDepth = 1;
00150     pFilter = NULL;
00151 
00152     mLowCorner.x = mLowCorner.y = 0;
00153 }
00154 
00155 /********************************************************************************************
00156 
00157 >   FlashExportDC::FlashExportDC( Filter *Parent )
00158 
00159     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00160     Created:    26/8/99
00161     Purpose:    Constructor: Creates a DC for exporting Flash files.
00162     SeeAlso:    ExportDC::ExportDC
00163 
00164 ********************************************************************************************/
00165 
00166 FlashExportDC::FlashExportDC ( Filter *Parent ) : ExportDC ( Parent )
00167 {
00168     // Set the output variables to their correct setting.
00169     m_bOutput = 0;
00170     m_bCurrentBit = 7;
00171     mDepth = 1;
00172     pFilter = Parent;
00173 
00174     mLowCorner.x = mLowCorner.y = 0;
00175 }
00176 
00177 /********************************************************************************************
00178 
00179 >   FlashExportDC::~FlashExportDC ( void )
00180 
00181     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00182     Created:    26/8/99
00183     Purpose:    Destructor. I'm not sure if this is needed, since export files are cleaned
00184                 up for me elsewhere.
00185     SeeAlso:    ExportDC::ExportDC
00186 
00187 ********************************************************************************************/
00188 
00189 FlashExportDC::~FlashExportDC( void )
00190 {
00191     // Any flash specific stuff will go in here.
00192 }
00193 
00194 /********************************************************************************************
00195 
00196 >   FlashExportDC::Init ( CCLexFile *pFile )
00197 
00198     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00199     Created:    26/8/99
00200     Purpose:    Calls ExportDC::Init ().
00201     SeeAlso:    ExportDC::ExportDC
00202 
00203 ********************************************************************************************/
00204 
00205 
00206 BOOL FlashExportDC::Init ( CCLexFile *pFile )
00207 {
00208     if ( pFile == NULL )
00209     {
00210         return FALSE;
00211     }
00212 
00213     return ExportDC::Init ( pFile );
00214 }
00215 
00216 /********************************************************************************************
00217 
00218 >   FlashExportDC::CreateHeader ( DocColour Background,
00219                                   DocRect *PageRect )
00220 
00221     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00222     Created:    26/8/99
00223     Purpose:    Creates a Flash file header.
00224     SeeAlso:    -
00225 
00226 ********************************************************************************************/
00227 
00228 BOOL FlashExportDC::CreateHeader ( DocColour Background,
00229                                    DocRect ImageBounds )
00230 {
00231     // Calculate the size of the image. To save complications, I've moved the image to
00232     // 0,0, rather than from whatever bounds Camelot uses.
00233     mLowCorner.x = ImageBounds.lo.x / FLASH_SCALE;
00234     mLowCorner.y = ImageBounds.hi.y / FLASH_SCALE;
00235 
00236     Transform ( &ImageBounds );
00237 
00238     // Write the header for the Flash file.
00239     Write ( "FWS", 3 );                     // File ID tag.
00240     WriteByte ( 4 );                        // Version number.
00241     WriteLong ( 0 );                        // Space for file size.
00242     WriteBoundingBox ( ImageBounds );       // Bounding rectangle for image.
00243     WriteByte ( 0 );                        // Frames per second. (Decimal part.)
00244     WriteByte ( 12 );                       // Frames per second. (Integer part.)
00245     WriteWord ( 1 );                        // Number of frames.
00246     WriteBackgroundColour ( Background );   // Background colour.
00247 
00248     return TRUE;
00249 }
00250 
00251 /********************************************************************************************
00252 
00253 >   FlashExportDC::EndFile ( void )
00254 
00255     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00256     Created:    26/8/99
00257     Purpose:    Tidies up the file..
00258     SeeAlso:    -
00259 
00260 ********************************************************************************************/
00261 
00262 BOOL FlashExportDC::EndFile ( void )
00263 {
00264     // Write show frame.
00265     WriteHeader ( FLASH_SHOW_FRAME_TAG, 0 );
00266 
00267     // Write end of file.
00268     WriteHeader ( FLASH_END_FILE_TAG, 0 );
00269 
00270     // Rewind, and add the file size.
00271     ExportFile->seekIn ( 4 );
00272     WriteLong ( (INT32) ExportFile->Size() );
00273 
00274     return TRUE;
00275 }
00276 
00277 /********************************************************************************************
00278 
00279 >   FlashExportDC::BoundingBox ( DocRect *Bounds )
00280 
00281     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00282     Created:    27/8/99
00283     Purpose:    Create a bounding box, and write it into a file.
00284     SeeAlso:    -
00285 
00286 ********************************************************************************************/
00287 
00288 BOOL FlashExportDC::WriteBoundingBox ( DocRect Bounds )
00289 {
00290     // Calculate the number of significant bits needed to store the co-ordinates.
00291     UINT32 Bits = CountBits ( Max ( Absol ( Bounds.lo.x ),
00292                                   Absol ( Bounds.lo.y ),
00293                                   Absol ( Bounds.hi.x ),
00294                                   Absol ( Bounds.hi.y ) ) );
00295 
00296     // Write the bounding box to a file.
00297     if ( WriteBits ( Bits, 5 ) &&
00298          WriteBits ( Bounds.lo.x, Bits ) &&
00299          WriteBits ( Bounds.hi.x, Bits ) &&
00300          WriteBits ( Bounds.lo.y, Bits ) &&
00301          WriteBits ( Bounds.hi.y, Bits ) )
00302     {
00303         ByteAlign ();
00304         return TRUE;
00305     }
00306     else
00307         return FALSE;
00308 }
00309 
00310 /********************************************************************************************
00311 
00312 >   UINT32 FlashExportDC::CountBits ( INT32 Value,
00313                                     BOOL IsSigned = TRUE )
00314 
00315     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00316     Created:    1/9/99
00317     Purpose:    Counts the number of significant bits in a value.
00318     Returns:    Number of significant bits.
00319     SeeAlso:    -
00320 
00321 ********************************************************************************************/
00322 
00323 UINT32 FlashExportDC::CountBits ( INT32 Value,
00324                                 BOOL IsSigned )
00325 {
00326     UINT32 BitCount = 0;
00327     
00328     // Add an extra bit in for negative values.
00329     if ( IsSigned )
00330         BitCount = 1;
00331 
00332     while ( Value )
00333     {
00334         Value >>= 1;
00335         BitCount ++;
00336     }
00337 
00338     return BitCount;
00339 }
00340 
00341 /********************************************************************************************
00342 
00343 >   BOOL FlashExportDC::WriteBits ( INT32 Value )
00344 
00345     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00346     Created:    1/9/99
00347     Purpose:    Writes individual bits to the output file.
00348     Returns:    TRUE if success.
00349     SeeAlso:    -
00350 
00351 ********************************************************************************************/
00352 
00353 BOOL FlashExportDC::WriteBits ( INT32 Value,
00354                                 UINT32 Bits )
00355 {
00356     BOOL    Result = TRUE;
00357 
00358     // CompareBit is bitwise ANDed with the current value. If the result is non-zero, then
00359     // that bit has been set, and is written to the file. CompareBit is decreased with
00360     // every iteration through the loop, until it equals zero, and no further bits are to
00361     // be compared.
00362 
00363     // If a zero bit bitfield is attempted to be written, don't do anything. Otherwise
00364     // write out the bits.
00365     if ( Bits > 0 )
00366     {
00367         INT32 CompareBit = 1 << ( Bits - 1 );
00368 
00369         while ( CompareBit )
00370         {
00371             // If that bit is set, write it to the file.
00372             if ( CompareBit & Value )
00373                 m_bOutput += 1 << m_bCurrentBit;
00374 
00375             CompareBit >>= 1;
00376             m_bCurrentBit --;
00377 
00378             // Write out the value once the byte is full, and reset all variables.
00379             if ( m_bCurrentBit < 0 )
00380             {
00381                 // Write bitfield value to a file.
00382                 Result = Write ( &m_bOutput, 1 );
00383 
00384                 // Reset the appropriate variables.
00385                 m_bOutput = 0;
00386                 m_bCurrentBit = 7;
00387             }
00388         }
00389     }
00390     return Result;
00391 }
00392 
00393 /********************************************************************************************
00394 
00395 >   BOOL FlashExportDC::WriteBackgroundColour ( DocColour dCol )
00396 
00397     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00398     Created:    1/9/99
00399     Purpose:    Writes the background colour to the file.
00400     Returns:    TRUE if success.
00401     SeeAlso:    -
00402 
00403 ********************************************************************************************/
00404 
00405 BOOL FlashExportDC::WriteBackgroundColour ( DocColour Background )
00406 {
00407     // Write the Flash tag and background colour.
00408     WriteHeader ( FLASH_BACKGROUND_TAG, 3 );
00409 
00410     WriteColour ( Background );
00411 
00412     return TRUE;
00413 }
00414     INT32 lRed, lGreen, lBlue;
00415 
00416 /********************************************************************************************
00417 
00418 >   BOOL FlashExportDC::WriteColour ( DocColour Col )
00419 
00420     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00421     Created:    2/12/99
00422     Purpose:    Writes a DocColour to the file in the flash format.
00423     Returns:    TRUE if success.
00424     SeeAlso:    -
00425 
00426 ********************************************************************************************/
00427 
00428 BOOL FlashExportDC::WriteColour ( DocColour Col )
00429 {
00430     INT32 lRed, lGreen, lBlue;
00431 
00432     // Extract the colour value from DocColour.
00433     Col.GetRGBValue ( &lRed, &lGreen, &lBlue );
00434 
00435     WriteByte ( (BYTE) lRed );
00436     WriteByte ( (BYTE) lGreen );
00437     WriteByte ( (BYTE) lBlue );
00438 
00439     return TRUE;
00440 }
00441 
00442 /********************************************************************************************
00443 
00444 >   BOOL FlashExportDC::WriteColour ( FlashColour Col )
00445 
00446     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00447     Created:    20/10/99
00448     Purpose:    Writes the colour to the file.
00449     Returns:    TRUE if success.
00450     SeeAlso:    -
00451 
00452 ********************************************************************************************/
00453 
00454 BOOL FlashExportDC::WriteColour ( FlashColour Col )
00455 {
00456     WriteByte ( Col.Red );
00457     WriteByte ( Col.Green );
00458     WriteByte ( Col.Blue );
00459     WriteByte ( Col.Alpha );
00460 
00461     return TRUE;
00462 }
00463 
00464 /********************************************************************************************
00465 
00466 >   BOOL FlashExportDC::WriteHeader ( UINT8 sTag,
00467                                       UINT32 lSize )
00468 
00469     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00470     Created:    1/9/99
00471     Purpose:    Writes a section header to the file.
00472     Returns:    TRUE if success.
00473     SeeAlso:    -
00474 
00475 ********************************************************************************************/
00476 
00477 BOOL FlashExportDC::WriteHeader ( UINT8 sTag,
00478                                   UINT32 lSize )
00479 {
00480     BOOL Result = FALSE;
00481     UINT8 sHeader = 0;
00482 
00483     ByteAlign ();   // Ensure that everything is in order.
00484 
00485     // Headers in a SWF file come in a long form, and a short form. The short form contains
00486     // a file size of up to 62 bytes, and the ID tag in one sixteen bit entry...
00487     if ( lSize < FLASH_MAX_SHORT )
00488     {
00489         sHeader = ( UINT8) lSize + ( sTag << 6 );
00490         Result = Write ( &sHeader, 2 );
00491     }
00492     // ... whilst the longer version has a successive 32 bit value giving its length.
00493     else
00494     {
00495         sHeader = FLASH_MAX_SHORT + ( sTag << 6 );
00496         if ( Write ( &sHeader, 2 ) &&
00497              Write ( &lSize, 4 ) )
00498         {
00499             Result = TRUE;
00500         }
00501     }
00502 
00503     return Result;
00504 }
00505 
00506 /********************************************************************************************
00507 
00508 >   FilePos FlashExportDC::WriteHeader ( UINT8 sTag,
00509                                          UINT32 lSize,
00510                                          WORD ID )
00511 
00512     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00513     Created:    1/12/99
00514     Purpose:    Writes a section header to the file, along with the ID tag.
00515     Returns:    The file position at the end of the header.
00516     SeeAlso:    -
00517 
00518 ********************************************************************************************/
00519 
00520 FilePos FlashExportDC::WriteHeader ( UINT8 sTag,
00521                                      UINT32 lSize,
00522                                      WORD ID )
00523 {
00524     FilePos EndOfHeader = 0;
00525 
00526     WriteHeader ( sTag, lSize );        // Call the original WriteHeader method.
00527     EndOfHeader = ExportFile->tell();   // Get the start position of the file.
00528     WriteWord ( ID );                   // Write the tag's ID out.
00529     return EndOfHeader;
00530 }
00531 
00532 /********************************************************************************************
00533 
00534 >   BOOL FlashExportDC::ByteAlign ()
00535 
00536     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00537     Created:    1/9/99
00538     Purpose:    Aligns bitwise values to byte boundaries..
00539     Returns:    TRUE if success.
00540     SeeAlso:    -
00541 
00542 ********************************************************************************************/
00543 
00544 BOOL FlashExportDC::ByteAlign ( void )
00545 {
00546     BOOL Result = TRUE;
00547 
00548     if ( m_bCurrentBit != 7 )
00549         Result = WriteBits ( 0, m_bCurrentBit + 1 );
00550 
00551     return Result;
00552 }
00553 
00554 /********************************************************************************************
00555 
00556 >   BOOL FlashExportDC::Write ( const void *Value,
00557                                 UINT32 Size )
00558 
00559     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00560     Created:    1/9/99
00561     Purpose:    Forms a wrapper around all disk writes, with a small degree of error
00562                 checking.
00563     Returns:    TRUE if success.
00564     SeeAlso:    -
00565 
00566 ********************************************************************************************/
00567 
00568 BOOL FlashExportDC::Write ( const void *Value,
00569                             UINT32 Size )
00570 {
00571     // I'm assuming that CCFile will return a NULL pointer if it fails, and this can be
00572     // caught by this code.
00573     if ( ExportFile->write ( Value, Size ) == NULL )
00574         return FALSE;
00575     else
00576         return TRUE;
00577 }
00578 
00579 /********************************************************************************************
00580 
00581 >   BOOL FlashExportDC::WriteByte ( BYTE Value )
00582 
00583     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00584     Created:    7/9/99
00585     Purpose:    Writes a BYTE value to the disk file.
00586     Returns:    TRUE if success.
00587     SeeAlso:    -
00588 
00589 ********************************************************************************************/
00590 
00591 BOOL FlashExportDC::WriteByte ( BYTE Value )
00592 {
00593     return Write ( &Value, 1 );
00594 }
00595 
00596 /********************************************************************************************
00597 
00598 >   BOOL FlashExportDC::WriteWord ( WORD Value )
00599 
00600     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00601     Created:    7/9/99
00602     Purpose:    Writes a short value (16 bits) to the disk file.
00603     Returns:    TRUE if success.
00604     SeeAlso:    -
00605 
00606 ********************************************************************************************/
00607 
00608 BOOL FlashExportDC::WriteWord ( WORD Value )
00609 {
00610     return Write ( &Value, 2 );
00611 }
00612 
00613 /********************************************************************************************
00614 
00615 >   BOOL FlashExportDC::WriteLong ( INT32 Value )
00616 
00617     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00618     Created:    7/9/99
00619     Purpose:    Writes an INT32 value (32 bits) to the disk file.
00620     Returns:    TRUE if success.
00621     SeeAlso:    -
00622 
00623 ********************************************************************************************/
00624 
00625 BOOL FlashExportDC::WriteLong ( INT32 Value )
00626 {
00627     return Write ( &Value, 4 );
00628 }
00629 
00630 /********************************************************************************************
00631 
00632 >   BOOL FlashExportDC::WritePath ( FlashShapeRecord *pPath )
00633 
00634     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00635     Created:    6/9/99
00636     Purpose:    Converts and writes a path to a Flash file.
00637     Returns:    TRUE if success.
00638     SeeAlso:    -
00639 
00640 ********************************************************************************************/
00641 
00642 BOOL FlashExportDC::WritePath ( FlashShapeRecord *pPath )
00643 {
00644     // Extract the variables from the FlashPathRecord.
00645     DocCoord    *Coords     = pPath->GetCoords ();
00646     INT32           NumCoords   = pPath->GetNumberCoords ();
00647     PathVerb    *Verb       = pPath->GetVerbs ();
00648     DocRect     Bounds      = pPath->GetBoundingBox ();
00649     INT32           Fills       = 0;    
00650     INT32           Lines       = 0;
00651     FilePos     StartPos    = 0;
00652     WORD        ID          = FLASH_FIRST_ID + FlashPlaceObject::GetBitmapCount () +
00653                               FlashPlaceObject::GetFontCount () +
00654                               FlashPlaceObject::GetTextCount () + pPath->GetShapeID ();
00655     DocCoord    MoveTo      ( Bounds.lo.x, Bounds.hi.y );
00656     double      Tolerance   = 100.0f;
00657     FlashColour LineColour  = pPath->GetLineColour ();
00658     WORD        LineWidth   = pPath->GetLineWidth ();
00659 
00660     Transform ( &MoveTo, &mLowCorner );         // Create the position for the low BB corner.
00661     Transform ( &Bounds );                      // Put the bounds into Flash coordinates.
00662 
00663     MoveTo.x += mLowCorner.x;
00664     MoveTo.y = mLowCorner.y - MoveTo.y;
00665 
00666     // Write a header. We'll assume that the size is 64 bytes to begin with.
00667     // Check that transparency isn't needed:
00668     // Use DefineShape3, which includes support for transparency.
00669     StartPos = WriteHeader ( FLASH_SHAPE3_TAG, FLASH_MAX_SHORT, ID );
00670 
00671     // Write the bounding box to the file.
00672     WriteBoundingBox ( Bounds );
00673 
00674     // Write a shape record.
00675 
00676     // Fill style first.
00677     if ( pPath->GetFill () != FLASH_NO_FILL )
00678     {
00679         Fills = 1;
00680         ProcessFill ( pPath, &MoveTo );
00681     }
00682     else
00683     {
00684         // The shape is unfilled, therefore has no fill styles.
00685         WriteByte ( 0 );                        // No fill styles.
00686     }
00687 
00688     // And now define the line style:
00689     if ( LineColour.Alpha == 0 || LineWidth == 0 )
00690     {
00691         WriteByte ( 0 );
00692     }
00693     else
00694     {
00695         WriteByte ( 1 );                        // Number of line styles in LINESTYLEARRAY.
00696         WriteWord ( pPath->GetLineWidth () );   // Width.
00697         WriteColour ( pPath->GetLineColour () );// Line colour.
00698         Lines = 1;
00699     }
00700 
00701     // Write the numbers of index bits.
00702     WriteBits ( Fills, 4 );                     // Number of fill style index bits.
00703     WriteBits ( Lines, 4 );                     // Number of line style index bits.
00704 
00705     // Calculate the difference between the original curve and the generated curve. This
00706     // creates it as 5% of the diagonal of the bounding box.
00707     Tolerance = ( sqrt ( double( Bounds.hi.x * Bounds.hi.x ) + double( Bounds.hi.y * Bounds.hi.y ) ) ) / 20;
00708 
00709     // Write the edge record.
00710     WriteEdgeRecord ( Coords, &MoveTo, Verb, NumCoords, Lines, Fills, 0,
00711                       Tolerance, TRUE );
00712 
00713     // Go back, and fill in the number of bytes written.
00714     WriteTagSize ( StartPos );
00715 
00716     // Export the edge record.
00717     return TRUE;
00718 }
00719 
00720 /********************************************************************************************
00721 
00722 >   BOOL FlashExportDC::WriteEdgeRecord ( DocCoord *Coords,
00723                                           DocCoord *MoveTo,
00724                                           PathVerb *Verb,
00725                                           INT32 NumCoords,
00726                                           UINT32 LineStyle,
00727                                           UINT32 Fill0,
00728                                           UINT32 Fill1,
00729                                           double Tolerance = 100.0f,
00730                                           BOOL IsCircular = FALSE )
00731 
00732     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00733     Created:    1/10/99
00734     Purpose:    Writes out a Flash edge record.
00735     Returns:    TRUE if success.
00736     SeeAlso:    -
00737 
00738 ********************************************************************************************/
00739 
00740 BOOL FlashExportDC::WriteEdgeRecord ( DocCoord *Coords,
00741                                       DocCoord *MoveTo,
00742                                       PathVerb *Verb,
00743                                       INT32 NumCoords,
00744                                       UINT32 LineStyle,
00745                                       UINT32 Fill0,
00746                                       UINT32 Fill1,
00747                                       double Tolerance,
00748                                       BOOL IsCircular )
00749 {
00750     // Transform all of the co-ordinates first.
00751     for ( INT32 i = 0; i < NumCoords; i++ )
00752     {
00753         Transform ( &Coords [i], MoveTo );
00754     }
00755 
00756     // Write the initial move to, which includes the change of style.
00757     WriteMoveTo ( Coords [0], LineStyle, Fill0, Fill1 );
00758 
00759     // Determine which kind of edge record to write.
00760     for ( INT32 j = 1; j < NumCoords; j++ )
00761     {
00762         // Is it a move to?
00763         if ( ( Verb[j] == PT_MOVETO ) || ( Verb[j] == PT_MOVETO + PT_CLOSEFIGURE ) )
00764         {
00765             WriteMoveTo ( Coords [j], 0, 0, 0 );
00766         }
00767 
00768         // Is it a Bezier curve?
00769         else if ( ( Verb[j] == PT_BEZIERTO ) || ( Verb[j] == PT_BEZIERTO + PT_CLOSEFIGURE ) )
00770         {
00771              if ( IsCircular )
00772              {
00773                 // Split the curve in half, and render each half separately.
00774                 PathVerb OutVerbs [6];      // Unused.
00775                 DocCoord OutCoords [7];
00776                 UINT32 Points;
00777 
00778                 if ( PathUtil::SplitCurve ( 0.5f, &Coords[j-1], &Points, OutVerbs,
00779                      OutCoords + 1 ) )
00780                 {
00781                     OutCoords [0] = Coords[j-1];
00782 
00783                     // Split curve, so recursively call ExportCurve.
00784                     ExportCurve ( OutCoords [0], OutCoords [1],
00785                                   OutCoords [2], OutCoords [3],
00786                                   Tolerance );
00787 
00788                     ExportCurve ( OutCoords [3], OutCoords [4],
00789                                   OutCoords [5], OutCoords [6],
00790                                   Tolerance );
00791                 }
00792                 else
00793                 {
00794                     // There's been a problem, so write a line between the start and
00795                     // end points, and continue.
00796                     WriteLineTo ( Coords [j-1], Coords [j+2] );
00797                 }
00798             }
00799             else
00800             {
00801                 // Render as normal.
00802                 ExportCurve ( Coords[j-1], Coords[j],
00803                               Coords[j+1], Coords[j+2],
00804                               Tolerance );
00805             }
00806 
00807             // Move j on past the Bezier record, which contains three elements.
00808             j += 2;
00809         }
00810 
00811         // Default: Treat it as a line.
00812         else
00813         {
00814             // Treat as a line to.
00815             WriteLineTo ( Coords[j-1], Coords[j] ); 
00816         }
00817     }
00818 
00819     // End of shape.
00820     WriteBits  ( 0, 6 );
00821     ByteAlign ( );          // Align bits to byte boundary.
00822 
00823     return TRUE;
00824 }
00825 
00826 /********************************************************************************************
00827 
00828 >   BOOL FlashExportDC::WritePlaceObject ( FlashPlaceObject *pPlace )
00829 
00830     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00831     Created:    22/12/99
00832     Purpose:    It's a wrapper around the other WritePlaceObject () function, using the
00833                 member variable mDepth to determine the "depth" in the image that the
00834                 shape is to be rendered.
00835     Returns:    TRUE if success.
00836     SeeAlso:    -
00837 
00838 ********************************************************************************************/
00839 
00840 BOOL FlashExportDC::WritePlaceObject ( FlashPlaceObject *pPlace )
00841 {
00842     WritePlaceObject ( pPlace, mDepth );        // Call the other WritePlaceObject function.
00843     mDepth ++;                                  // Increment the value of mDepth.
00844     return TRUE;                                // Indicate success.
00845 }
00846 
00847 /********************************************************************************************
00848 
00849 >   BOOL FlashExportDC::WritePlaceObject ( FlashPlaceObject *pPlace,
00850                                            WORD Depth )
00851 
00852     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00853     Created:    7/9/99
00854     Purpose:    Writes a place object tag using the data contained in pPlace, and with an
00855                 image depth of Depth.
00856     Returns:    TRUE if success.
00857     SeeAlso:    -
00858 
00859 ********************************************************************************************/
00860 
00861 BOOL FlashExportDC::WritePlaceObject ( FlashPlaceObject *pPlace,
00862                                        WORD Depth )
00863 {
00864     DocCoord    Position    = pPlace->GetPosition ();
00865     FilePos     StartPos    = 0;
00866 
00867     // Step 1:  Write a space in the file where the header should be written.
00868     WriteWord ( 0 );                            // Place-holder value.
00869     StartPos = ExportFile->tell();              // Get the start position of the file.
00870 
00871     // Step 2:  Fill in the relevant details pertaining to the PlaceObject tag.
00872 
00873     // Flags.
00874     WriteBits ( 0, 2 );                         // Reserved flags. Always 0
00875     WriteBits ( 0, 1 );                         // Does the object have a name? Unused.
00876     WriteBits ( 0, 1 );                         // Does the object have a ratio? Unused.
00877     WriteBits ( 0, 1 );                         // Does the object have a colour transform?
00878     WriteBits ( 1, 1 );                         // Does the object have a matrix? Always 1.
00879     WriteBits ( 1, 1 );                         // Does the object have an ID? Always 1.
00880     WriteBits ( 0, 1 );                         // Does the object move? Unused.
00881 
00882     // The depth, and ID.
00883     WriteWord ( Depth );                        // The depth in the image.
00884     WriteWord ( pPlace->GetID () );             // The ID number of the object to be placed.
00885 
00886     // Step 2a: Add a matrix to the PlaceObject record.
00887     if ( pPlace->GetDoTransform () )
00888         Transform ( &Position, &mLowCorner );   // Get position in Flash space.
00889 
00890     WriteMatrix ( Position );                   // Write the matrix out.
00891 
00892     // Step 3:  Go back to the start of the record, and fill in the record size.
00893     FilePos EndPos = ExportFile->tell ();       // Get the file position.
00894     ExportFile->seekIn ( ( StartPos - 2 ) );    // Go back to the start of the header.
00895     WriteHeader ( FLASH_PLACE_OBJECT_TAG,       // Write the initial header.
00896                   EndPos - StartPos );
00897     ExportFile->seekIn ( EndPos );              // Run to the end of the file.
00898 
00899     return TRUE;
00900 }
00901 
00902 /********************************************************************************************
00903 
00904 >   BOOL FlashExportDC::WriteMoveTo ( DocCoord Position,
00905                                       INT32 ShapeY,
00906                                       UINT32 ChangeLine,
00907                                       UINT32 ChangeFill0,
00908                                       UINT32 ChangeFill1 )
00909 
00910     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00911     Created:    10/9/99
00912     Purpose:    Writes a Flash Move To edge record.
00913     Returns:    TRUE if written succesfully.
00914     SeeAlso:    -
00915 
00916 ********************************************************************************************/
00917 
00918 BOOL FlashExportDC::WriteMoveTo ( DocCoord Position,
00919                                   UINT32 ChangeLine,
00920                                   UINT32 ChangeFill0,
00921                                   UINT32 ChangeFill1 )
00922 {
00923     // Calculate the number of bits required for the Delta fields.
00924     UINT32 MoveSize = CountBits ( Max ( Absol ( Position.x ), Absol ( Position.y ) ) );
00925 
00926     // Declare segment header.
00927     WriteBits ( 0, 1 );                 // Is a shape record.
00928     WriteBits ( 0, 1 );                 // Unused by DefineShape1.
00929     WriteBits ( ChangeLine, 1 );        // Change Line style.
00930     WriteBits ( ChangeFill0, 1 );       // Change Fill0 style.
00931     WriteBits ( ChangeFill1, 1 );       // Change Fill1 style.
00932 
00933     // Details for MoveTo.
00934     WriteBits ( 1, 1 );                 // Is a move to.
00935     WriteBits ( MoveSize, 5 );          // Number of bits for move value.
00936     
00937     // Set control points.
00938     WriteBits ( Position.x, MoveSize );
00939     WriteBits ( Position.y, MoveSize );
00940 
00941     if ( ChangeLine )
00942         WriteBits ( ChangeLine, 1 );    // Line style.
00943 
00944     if ( ChangeFill0 )
00945         WriteBits ( ChangeFill0, 1 );   // Fill0 style.
00946 
00947     if ( ChangeFill1 )                  // Fill1 style.
00948         WriteBits ( ChangeFill1, 1 );
00949 
00950     return TRUE;
00951 }
00952 
00953 /********************************************************************************************
00954 
00955 >   BOOL FlashExportDC::WriteLineTo ( DocCoord Start,
00956                                       DocCoord End )
00957 
00958     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00959     Created:    10/9/99
00960     Purpose:    Writes a Flash Line To edge record.
00961     Returns:    TRUE if written succesfully.
00962     SeeAlso:    -
00963 
00964 ********************************************************************************************/
00965 
00966 BOOL FlashExportDC::WriteLineTo ( DocCoord Start,
00967                                   DocCoord End )
00968 {
00969     // Calculate the distance moved.
00970     DocCoord Delta  = End - Start;
00971 
00972     if ( Delta.x == 0 && Delta.y == 0 )
00973         return TRUE;                    // Zero length line - so don't bother.
00974 
00975     // Calculate how many bits are needed to store the result.
00976     UINT32 DeltaSize = CountBits ( Max ( Absol ( Delta.x ), Absol ( Delta.y ) ) );
00977 
00978     // Declare segment header...
00979     WriteBits ( 1, 1 );                 // Is an edge record.
00980     WriteBits ( 1, 1 );                 // Is a straight edge.
00981     WriteBits ( ( DeltaSize - 2 ), 4 ); // Number of bits ( -2 ) per value.
00982 
00983     if ( Delta.x == 0 )
00984     {
00985         // Write a vertical line.
00986         WriteBits ( 0, 1 );             // Not a general line.
00987         WriteBits ( 1, 1 );             // Is a vertical line.
00988         WriteBits ( Delta.y, DeltaSize );
00989     }
00990     else if ( Delta.y == 0 )
00991     {
00992         // Write a vertical line.
00993         WriteBits ( 0, 1 );             // Not a general line.
00994         WriteBits ( 0, 1 );             // Is a horizontal line.
00995         WriteBits ( Delta.x, DeltaSize );
00996     }
00997     else
00998     {
00999         WriteBits ( 1, 1 );             // Is a general line.
01000 
01001         // Set control points.
01002         WriteBits ( Delta.x, DeltaSize );
01003         WriteBits ( Delta.y, DeltaSize );
01004     }
01005 
01006     return TRUE;
01007 }
01008 
01009 /********************************************************************************************
01010 
01011 >   BOOL FlashExportDC::WriteCurveTo ( DocCoord Start,
01012                                        DocCoord Control,
01013                                        DocCoord End )
01014 
01015     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01016     Created:    10/9/99
01017     Purpose:    Writes a Flash Curve To edge record.
01018     Returns:    TRUE if written succesfully.
01019     SeeAlso:    -
01020 
01021 ********************************************************************************************/
01022 
01023 BOOL FlashExportDC::WriteCurveTo ( DocCoord Start,
01024                                    DocCoord Control,
01025                                    DocCoord End )
01026 {
01027     // Convert to Flash co-ordinates.
01028     DocCoord ToControl = Control - Start;
01029     DocCoord ToAnchor = End - Control;
01030 
01031     UINT32 BezierSize = CountBits ( Max ( Absol ( ToAnchor.x ),
01032                                         Absol ( ToAnchor.y ),
01033                                         Absol ( ToControl.x ),
01034                                         Absol ( ToControl.y ) ) );
01035 
01036     // Declare segment header...
01037     WriteBits ( 1, 1 );                     // Is an edge record.
01038     WriteBits ( 0, 1 );                     // Is not a straight edge.
01039     WriteBits ( ( BezierSize - 2 ), 4 );    // Number of bits ( -2 ) per value.
01040 
01041     // Write the anchor and control points to the file.
01042     WriteBits ( ToControl.x, BezierSize );
01043     WriteBits ( ToControl.y, BezierSize );
01044     WriteBits ( ToAnchor.x, BezierSize );
01045     WriteBits ( ToAnchor.y, BezierSize );
01046 
01047     return TRUE;
01048 }
01049 
01050 /********************************************************************************************
01051 
01052 >   DocCoord FlashExportDC::ExportCurve ( DocCoord &Start,
01053                                           DocCoord &Control1,
01054                                           DocCoord &Control2,
01055                                           DocCoord &End,
01056                                           double Tolerance )
01057 
01058     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01059     Created:    13/9/99
01060     Purpose:    Prepares a Bezier for export to a Flash file by converting it into a
01061                 quadratic, and splitting the curve where necessary.
01062     Returns:    TRUE if success
01063     SeeAlso:    -
01064 
01065 ********************************************************************************************/
01066 
01067 BOOL FlashExportDC::ExportCurve ( DocCoord &Start,
01068                                   DocCoord &Control1,
01069                                   DocCoord &Control2,
01070                                   DocCoord &End,
01071                                   double Tolerance )
01072 {
01073     // Calculate the point of intersection between the lines created between each
01074     // anchor point, and its nearest control point. This then acts as the control point
01075     // for the quadratic form of the Bezier.
01076     INT32       Length  = CalculateLongLength ( End - Start );
01077     DocCoord    Control;
01078 
01079     // Write subpixel lines out as a line.
01080     if ( Length < 20 )
01081     {
01082         return WriteLineTo ( Start, End );
01083     }
01084     // Otherwise calculate the control point, and render as a quadratic curve.
01085     else if ( CalculateIntersection ( Start, Control1, End, Control2, Control ) )
01086     {
01087         // Now compare the midpoints of the quadratic and cubic forms of the Beziers.
01088         // This algorithm is based on a divide and conquer method of curve rendering,
01089         // and can be found in Ken Joy's online computer graphics notes at:
01090         // http://graphics.cs.ucdavis.edu/GraphicsNotes/Graphics-Notes.html
01091 
01092         // The technique is to first calculate the midpoints between the start and
01093         // control points of a quadratic bezier, and then the midpoint between the
01094         // midpoints. This point lies in the middle of the curve.
01095 
01096         DocCoord MidStartControl = CalculateMidpoint ( Start, Control );
01097         DocCoord MidControlEnd = CalculateMidpoint ( Control, End );
01098 
01099         DocCoord QuadMidpoint = CalculateMidpoint ( MidStartControl, MidControlEnd );
01100 
01101         // Then process the cubic bezer using the method from PathUtil:
01102         DocCoord CubicMidpoint = PathUtil::PointOnCurve ( 0.5f, &Start );
01103 
01104         // Compare the values:
01105         DocCoord Difference = CubicMidpoint - QuadMidpoint;
01106 
01107         // Originally I was using CalculateLength here, but there were some problems
01108         // with it, so I've effectively inlined the code from that function, and now
01109         // it seems to be running properly. I suspect that the problem was that when
01110         // an indefinate value is returned, the INT32 would be set as a strange value,
01111         // which caused problems for the if... statement below.
01112         double Distance = sqrt ( double( Difference.x * Difference.x )
01113                                  + double( Difference.y * Difference.y ) );
01114 
01115         // I've been having trouble with values of Distance where it's an infinite value,
01116         // which Visual C stores as -1.#IND. This should keep it under control
01117         if ( ( Distance < Tolerance ) && ( Distance >= 0 ) )
01118         {
01119             WriteCurveTo ( Start, Control, End );
01120             return TRUE;
01121         }
01122     }
01123 
01124     // If you get here, there's been a problem with rendering the curve. Therefore
01125     // split it in half, and attempt to write each half out to a flash file.
01126     PathVerb OutVerbs [6];      // Unused.
01127     DocCoord OutCoords [7];
01128     UINT32 Points;
01129 
01130     if ( PathUtil::SplitCurve ( 0.5f, &Start, &Points, OutVerbs, OutCoords + 1 ) )
01131     {       
01132         // Since I'm using references, I need to make a copy of Start for the
01133         // recursive call to work. Otherwise the program spins into an
01134         // infinite loop.
01135         OutCoords [0] = Start;
01136 
01137         // Split curve, so recursively call ExportCurve.
01138         ExportCurve ( OutCoords [0], OutCoords [1],
01139                       OutCoords [2], OutCoords [3],
01140                       Tolerance );
01141 
01142         ExportCurve ( OutCoords [3], OutCoords [4],
01143                       OutCoords [5], OutCoords [6],
01144                       Tolerance );
01145     }
01146     else
01147     {
01148         // We've got a problem! Render the curve as a straight line.
01149         WriteLineTo ( Start, End );
01150     }
01151 
01152     return TRUE;
01153 }
01154 
01155 /********************************************************************************************
01156 
01157 >   BOOL FlashExportDC::CalculateIntersection ( DocCoord &Start1,
01158                                                 DocCoord &End1,
01159                                                 DocCoord &Start2,
01160                                                 DocCoord &End2
01161                                                 DocCoord &Intersection )
01162 
01163     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01164     Created:    13/9/99
01165     Purpose:    Calculates the point of intersection between two lines with defined by
01166                 a pair of points lying on each one.
01167     Returns:    DocCoord containing the point of intersection.
01168     SeeAlso:    CCreateBevelTrapezoids::CalculateIntersection
01169 
01170 ********************************************************************************************/
01171 
01172 BOOL FlashExportDC::CalculateIntersection ( DocCoord &Start1,
01173                                             DocCoord &End1,
01174                                             DocCoord &Start2,
01175                                             DocCoord &End2,
01176                                             DocCoord &Intersection )
01177 {
01178     double p, q;        // Unused values describing where the lines meet.
01179     BOOL Result;        // Return value.
01180 
01181     // Calculate the vectors describing the direction of the two lines.
01182     NormCoord Dir1 ( End1.x - Start1.x, End1.y - Start1.y );
01183     NormCoord Dir2 ( End2.x - Start2.x, End2.y - Start2.y );
01184 
01185     // Now normalise them, so that they are unit vectors.
01186     Dir1.Normalise ();
01187     Dir2.Normalise ();
01188 
01189     // Calculate the point of intersection between the lines created between each
01190     // anchor point, and its nearest control point.
01191     Result = CCreateBevelTrapezoids::CalculateIntersection ( &Start1, &Dir1,
01192                                                              &Start2, &Dir2,
01193                                                              &Intersection,
01194                                                              &p, &q );
01195 
01196     return Result;
01197 }
01198 
01199 /********************************************************************************************
01200 
01201 >   DocCoord FlashExportDC::CalculateMidpoint ( DocCoord Point1,
01202                                                 DocCoord Point2 )
01203 
01204     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01205     Created:    13/9/99
01206     Purpose:    Calculates the point of intersection between two lines with defined by
01207                 a pair of points lying on each one.
01208     Returns:    DocCoord containing the midpoint.
01209     SeeAlso:    CCreateBevelTrapezoids::CalculateIntersection
01210 
01211 ********************************************************************************************/
01212 
01213 DocCoord FlashExportDC::CalculateMidpoint ( DocCoord Point1,
01214                                             DocCoord Point2 )
01215 {
01216     DocCoord Midpoint;
01217 
01218     Midpoint.x = Point1.x + ( ( Point2.x - Point1.x ) / 2 );
01219     Midpoint.y = Point1.y + ( ( Point2.y - Point1.y ) / 2 );
01220 
01221     return Midpoint;
01222 }
01223 
01224 /********************************************************************************************
01225 
01226 >   BOOL FlashExportDC::ProcessFill ( FlashShapeRecord *pShape,
01227                                       DocCoord *MoveTo )
01228 
01229     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01230     Created:    25/11/99
01231     Purpose:    Determines which kind of fill is being used, and takes appropriate action.
01232     Returns:    TRUE if success.
01233     SeeAlso:    WriteGradientFill, WriteBitmapFill
01234 
01235 ********************************************************************************************/
01236 
01237 BOOL FlashExportDC::ProcessFill ( FlashShapeRecord *pShape,
01238                                   DocCoord *MoveTo )
01239 {
01240     BYTE Fill = pShape->GetFill ();
01241 
01242     // Write in the fill type.
01243     WriteByte ( 1 );                    // The number of fills.
01244     WriteByte ( Fill );                 // The fill style.
01245 
01246     // Use a switch to determine the correct fill processing routine to use.
01247     switch ( Fill )
01248     {
01249     case FLASH_LINEAR_FILL: case FLASH_RADIAL_FILL:
01250         WriteGradientFill ( pShape, MoveTo );
01251         break;
01252 
01253     case FLASH_TILED_BITMAP: case  FLASH_CLIPPED_BITMAP:
01254         WriteBitmapFill ( pShape, MoveTo );
01255         break;
01256 
01257     default:
01258         // Process as a linear fill.
01259         WriteColour ( pShape->GetColour ( 0 ) );
01260         break;
01261     }
01262 
01263     return TRUE;
01264 }
01265 
01266 /********************************************************************************************
01267 
01268 >   void FlashExportDC::Transform ( DocCoord *Point,
01269                                     DocCoord *MoveTo = NULL )
01270 
01271     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01272     Created:    22/9/99
01273     Purpose:    Transforms the co-ordinates of Point from Camelot space into Flash space.
01274                 It's really a hack to replace the transformation matrix, until I work out
01275                 how to initialise that properly.
01276     Returns:    Void.
01277     SeeAlso:    FlashExportDC::PointOnCubic
01278 
01279 ********************************************************************************************/
01280 
01281 void FlashExportDC::Transform ( DocCoord *Point,
01282                                 DocCoord *MoveTo )
01283 {
01284     // Catch rounding errors.
01285     if ( ( Point->x % FLASH_SCALE ) > ( FLASH_SCALE / 2 ) )
01286     {
01287         Point->x = ( Point->x / FLASH_SCALE ) + 1;
01288     }
01289     else
01290     {
01291         Point->x = ( Point->x / FLASH_SCALE );
01292     }
01293 
01294     if ( ( Point->y % FLASH_SCALE ) > ( FLASH_SCALE / 2 ) )
01295     {
01296         Point->y = - ( Point->y / FLASH_SCALE ) - 1;
01297     }
01298     else
01299     {
01300         Point->y = - ( Point->y / FLASH_SCALE );
01301     }
01302 
01303     // If any transforms have been passed in...
01304     if ( MoveTo != NULL )
01305     {
01306         Point->x -= MoveTo->x;
01307         Point->y += MoveTo->y;
01308     }
01309 }
01310 
01311 /********************************************************************************************
01312 
01313 >   void FlashExportDC::Transform ( DocRect *Bounds )
01314 
01315     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01316     Created:    22/9/99
01317     Purpose:    Transforms the co-ordinates of Bounds from Camelot space into Flash space.
01318                 The rectangle is resized so that lo is (0,0).
01319     Returns:    Void.
01320     SeeAlso:    FlashExportDC::Transform ( DocCoord *Point )
01321 
01322 ********************************************************************************************/
01323 
01324 void FlashExportDC::Transform ( DocRect *Bounds )
01325 {
01326     // Calculate the new hi co-ordinates for the bounding box.
01327     INT32 HiX;
01328     INT32 HiY;
01329     INT32 dX = Bounds->hi.x - Bounds->lo.x;
01330     INT32 dY = Bounds->hi.y - Bounds->lo.y;
01331     
01332     // Catch rounding errors.
01333     if ( ( dX % FLASH_SCALE ) > ( FLASH_SCALE / 2 ) )
01334     {
01335         HiX= ( dX / FLASH_SCALE ) + 1;
01336     }
01337     else
01338     {
01339         HiX= dX / FLASH_SCALE;
01340     }
01341 
01342     if ( ( dY % FLASH_SCALE ) > ( FLASH_SCALE / 2 ) )
01343     {
01344         HiY= ( dY / FLASH_SCALE ) + 1;
01345     }
01346     else
01347     {
01348         HiY= dY / FLASH_SCALE;
01349     }
01350 
01351     // And write them into the data structure.
01352     Bounds->lo.x = 0;
01353     Bounds->lo.y = 0;
01354     Bounds->hi.x = HiX;
01355     Bounds->hi.y = HiY;
01356 }
01357 
01358 /********************************************************************************************
01359 
01360 >   BOOL FlashExportDC::WriteMatrix ( DocCoord &Translate,
01361                                       INT32 ScaleX = FLASH_FIXED_ONE,
01362                                       INT32 ScaleY = FLASH_FIXED_ONE,
01363                                       INT32 SkewX = 0,
01364                                       INT32 SkewY = 0 )
01365 
01366     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01367     Created:    22/9/99
01368     Purpose:    Writes a Flash format matrix to the output file. Flash takes these values,
01369                 and uses them to compose a matrix with this format:
01370                 | ScaleX    SkewY       Translate.x |
01371                 | SkewX     ScaleY      Translate.y |
01372     Returns:    Void.
01373     SeeAlso:    -
01374 
01375 ********************************************************************************************/
01376 
01377 BOOL FlashExportDC::WriteMatrix ( DocCoord &Translate,
01378                                   INT32 ScaleX,
01379                                   INT32 ScaleY,
01380                                   INT32 SkewX,
01381                                   INT32 SkewY )
01382 {
01383     // Write scale field. First check whether to write scale field.
01384     if ( ScaleX == FLASH_FIXED_ONE && ScaleY == FLASH_FIXED_ONE )
01385     {
01386         WriteBits ( 0, 1 );                 // Matrix has no scale terms.
01387     }
01388     else
01389     {
01390         // Calculate the size of the bitfield.
01391         UINT32 ScaleBits = CountBits ( Max ( Absol ( ScaleX ), Absol ( ScaleY ) ) );
01392         
01393         WriteBits ( 1, 1 );                 // Matrix has scale.
01394         WriteBits ( ScaleBits, 5 );         // Size of scale value.
01395         WriteBits ( ScaleX, ScaleBits );    // Write scale along the X axis.
01396         WriteBits ( ScaleY, ScaleBits );    // Write scale along the Y axis.
01397     }
01398 
01399     // Process the rotate / skew fields of the matrix.
01400     if ( SkewY == 0 && SkewX == 0 )         // Check whether to write skew field.
01401     {
01402         WriteBits ( 0, 1 );                 // Matrix has no rotate terms.
01403     }
01404     else
01405     {
01406         // Calculate the size of the bitfield.
01407         UINT32 SkewBits = CountBits ( Max ( Absol ( SkewY ), Absol ( SkewX ) ) );
01408         
01409         WriteBits ( 1, 1 );                 // Matrix has rotate / skew.
01410         WriteBits ( SkewBits, 5 );          // Size of the bitfield.
01411         WriteBits ( SkewY, SkewBits );      // Value for SkewY.
01412         WriteBits ( SkewX, SkewBits );      // Value for SkewX.
01413     }
01414 
01415     // Define values for translation part of the matrix.
01416 
01417     // If no translation, don't reserve any bits.
01418     if ( Translate.x == 0 && Translate.y == 0 )
01419     {
01420         WriteBits ( 0, 5 );
01421     }
01422     // Otherwise write in the record.
01423     else
01424     {
01425         UINT32 TransBits = CountBits ( Max ( Absol ( Translate.x ), Absol ( Translate.y ) ) );
01426         WriteBits ( TransBits, 5 );         // Size of translation value.
01427         WriteBits ( Translate.x, TransBits );
01428         WriteBits ( Translate.y, TransBits );
01429     }
01430 
01431     ByteAlign ();
01432 
01433     return TRUE;
01434 }
01435 
01436 /********************************************************************************************
01437 
01438 >   BOOL FlashExportDC::WriteRotationMatrix ( DocCoord &Translate,
01439                                               INT32 ScaleX = FLASH_FIXED_ONE,
01440                                               INT32 ScaleY = FLASH_FIXED_ONE,
01441                                               double SinTheta = 0,
01442                                               double CosTheta = 1.0f )
01443 
01444     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01445     Created:    22/9/99
01446     Purpose:    This is a wrapper around the WriteMatrix method (above), except that it
01447                 takes a cosine and sine, and assembles the appropriate rotation matrix.
01448     Returns:    TRUE if successful.
01449     SeeAlso:    FlashExportDC::WriteRotationMatrix
01450 
01451 ********************************************************************************************/
01452 
01453 BOOL FlashExportDC::WriteRotationMatrix ( DocCoord &Translate,
01454                                           INT32 ScaleX,
01455                                           INT32 ScaleY,
01456                                           double SinTheta,
01457                                           double CosTheta )
01458 {
01459     // Multiply the values together to generate the appropriate values for the matrix.
01460     double dScaleX = ScaleX * CosTheta;
01461     double dScaleY = ScaleY * CosTheta;
01462     double dSkewX = -ScaleY * SinTheta;
01463     double dSkewY =  ScaleX * SinTheta;
01464 
01465     // Write the values to the matrix.
01466     return WriteMatrix ( Translate, ( INT32 ) dScaleX, ( INT32 ) dScaleY,
01467                          ( INT32 ) dSkewX, ( INT32 ) dSkewY );
01468 }
01469 
01470 /********************************************************************************************
01471 
01472 >   static double FlashExportDC::CalculateLength ( DocCoord Delta )
01473 
01474     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01475     Created:    22/9/99
01476     Purpose:    Calculates the length of a line between two points.
01477     Returns:    The length, as a double.
01478     SeeAlso:    FlashExportDC::WriteRotationMatrix
01479 
01480 ********************************************************************************************/
01481 
01482 double FlashExportDC::CalculateLength ( DocCoord Delta )
01483 {
01484     // Convert the co-ordinates from longs to doubles. This prevents the variables over
01485     // flowing.
01486     double xSquared = ( ( double ) Delta.x ) * ( ( double ) Delta.x );
01487     double ySquared = ( ( double ) Delta.y ) * ( ( double ) Delta.y );
01488 
01489     // Calculate the distance.
01490     double Result   = sqrt ( xSquared + ySquared );
01491 
01492     // And return it.
01493     return Result;
01494 }
01495 
01496 /********************************************************************************************
01497 
01498 >   static INT32 FlashExportDC::CalculateLongLength ( DocCoord Delta )
01499 
01500     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01501     Created:    22/9/99
01502     Purpose:    Calculates the length of a line between two points.
01503     Returns:    The length, as an INT32.
01504     SeeAlso:    FlashExportDC::WriteRotationMatrix
01505 
01506 ********************************************************************************************/
01507 
01508 INT32 FlashExportDC::CalculateLongLength ( DocCoord Delta )
01509 {
01510     // Call the other CalculateLength function.
01511     return ( INT32 ) CalculateLength ( Delta );
01512 }
01513 
01514 /********************************************************************************************
01515 
01516 >   INT32 FlashExportDC::CalculateTrigValues ( DocCoord &StartPoint,
01517                                               DocCoord &EndPoint,
01518                                               INT32 &Length,
01519                                               double &SinTheta,
01520                                               double &CosTheta )
01521 
01522     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01523     Created:    23/9/99
01524     Purpose:    Takes two points, and calculates the length, and the sine and cosine values
01525                 for the angle of rotation from the x-axis.
01526     Returns:    Void.
01527     SeeAlso:    -
01528 
01529 ********************************************************************************************/
01530 
01531 void FlashExportDC::CalculateTrigValues ( DocCoord &StartPoint,
01532                                           DocCoord &EndPoint,
01533                                           INT32 &Length,
01534                                           double &SinTheta,
01535                                           double &CosTheta )
01536 {
01537     DocCoord Delta = EndPoint - StartPoint;
01538     Length = CalculateLongLength ( Delta );
01539 
01540     // Check that the length of the vector isn't zero, and thus avoid any nasty divide by
01541     // zero errors.
01542     if ( Length == 0 )
01543     {
01544         // Set the angle to be 0 radians, and load the variables with the appropriate
01545         // values.
01546         SinTheta = 0;
01547         CosTheta = 1;
01548     }
01549     else
01550     {
01551         // Calculate the trignometric functions using the lengths of the sides of a
01552         // triangle.
01553         SinTheta = ( double ) Delta.y / ( double )Length;
01554         CosTheta = ( double ) Delta.x / ( double )Length;
01555     }
01556 }
01557 
01558 /********************************************************************************************
01559 
01560 >   BOOL FlashExportDC::WriteGradientFill ( FlashShapeRecord *pShape,
01561                                             DocCoord *MoveTo )
01562 
01563     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01564     Created:    25/11/99
01565     Purpose:    Writes out a gradient fill to disk.
01566     Returns:    TRUE if success.
01567     SeeAlso:    ProcessFill
01568 
01569 ********************************************************************************************/
01570 
01571 BOOL FlashExportDC::WriteGradientFill ( FlashShapeRecord *pShape,
01572                                         DocCoord *MoveTo )
01573 {
01574     // This covers both circular and linear fills.
01575     BYTE        Colours     = pShape->GetNumberColours ();
01576     DocCoord    StartPoint  = pShape->GetStartPoint ();
01577     DocCoord    EndPoint    = pShape->GetEndPoint ();
01578     DocCoord    EndPoint2   = pShape->GetEndPoint2 ();
01579     double      CosTheta    = 0;
01580     double      SinTheta    = 0;
01581     INT32       ScaleX      = 0;
01582 
01583     // The first order of business is to get the start and end points of the first
01584     // fill vector:
01585     Transform ( &StartPoint, MoveTo );
01586     Transform ( &EndPoint, MoveTo );
01587     Transform ( &EndPoint2, MoveTo );
01588 
01589     CalculateTrigValues ( StartPoint, EndPoint, ScaleX, SinTheta, CosTheta );
01590 
01591     // Build the scale values to resize the colour ramp to fit onto the shape being
01592     // rendered. The value comes about from the following equation:
01593     // Scale = ( Width of Shape / Width of Ramp ) << 16.
01594     // The left shift converts the INT32 value into a fixed bit number, of the form
01595     // 16.16, which is used extensively by Flash.
01596     // Since the size of the Flash colour ramp is 2^15, or 1 << 15, then the pair
01597     // of shifts can be cancelled out, and replaced by a single times two.
01598     if ( pShape->GetFill () == FLASH_LINEAR_FILL )
01599     {
01600         ScaleX *= 2;
01601         StartPoint = CalculateMidpoint ( StartPoint, EndPoint );
01602 
01603         // Use a basic scaling matrix.
01604         WriteRotationMatrix ( StartPoint, ScaleX, ScaleX, SinTheta, CosTheta );
01605     }
01606 
01607     // Again a piece of inexplicable maths, and again it is a simplification of
01608     // Length / Size of colour ramp, which is being converted to a 16 bit fixed
01609     // value.
01610     else
01611     {
01612         INT32 ScaleY = CalculateLongLength ( EndPoint2 - StartPoint );
01613 
01614         ScaleX *= 4;
01615         ScaleY *= 4;
01616 
01617         // Check to see whether the lengths of the vectors are identical. If they
01618         // are, then the fill is a circular fill by another name, and we can make
01619         // our resulting file smaller.
01620         if ( ScaleX != ScaleY )
01621         {
01622             // Write the values out into a matrix.
01623             WriteRotationMatrix ( StartPoint, ScaleX, ScaleY, SinTheta, CosTheta );
01624         }
01625         else
01626         {
01627             // It's a circular fill, so use the circular fill matrix.
01628             WriteMatrix ( StartPoint, ScaleX, ScaleX );
01629         }
01630     }
01631 
01632     // Write out the colour record.
01633     WriteByte ( Colours );                          // Number of colours in the gradient.
01634 
01635     for ( BYTE i = 0; i < Colours; i++ )
01636     {
01637         WriteByte ( pShape->GetRatio (i) );         // Ratio for this colour.
01638         WriteColour ( pShape->GetColour (i) );      // The actual colour value.
01639     }
01640 
01641     return TRUE;
01642 }
01643 
01644 /********************************************************************************************
01645 
01646 >   BOOL FlashExportDC::WriteBitmapFill ( FlashShapeRecord *pShape,
01647                                           DocCoord *MoveTo )
01648 
01649     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01650     Created:    25/11/99
01651     Purpose:    Writes out a bitmap fill to disk.
01652     Returns:    TRUE if success.
01653     SeeAlso:    ProcessFill
01654 
01655 ********************************************************************************************/
01656 
01657 BOOL FlashExportDC::WriteBitmapFill ( FlashShapeRecord *pShape,
01658                                       DocCoord *MoveTo )
01659 {
01660     // Step 1:  Extract the start and end points of the fill from the shape record, and
01661     //          transform them into Flash co-ordinates.
01662     DocCoord    Start       = pShape->GetStartPoint ();     // Low corner of the bitmap.
01663     DocCoord    End1        = pShape->GetEndPoint ();       // Max X corner.
01664     DocCoord    End2        = pShape->GetEndPoint2 ();      // Max Y corner.
01665 
01666     INT32       BMPWidth    = pShape->GetBitmapWidth ();    // The width of the bitmap.
01667     INT32       BMPHeight   = pShape->GetBitmapHeight ();   // The height of the bitmap.
01668 
01669     // Catch BMPWidth or BMPHeight set to zero. This shouldn't happen...
01670     if ( BMPWidth == 0 )
01671         BMPWidth = 1;
01672 
01673     if ( BMPHeight == 0 )
01674         BMPHeight = 1;
01675 
01676     Transform ( &Start, MoveTo );                           // Transform low corner.
01677     Transform ( &End1, MoveTo );                            // Transform max x, min y.
01678     Transform ( &End2, MoveTo );                            // Transform min x, max y.
01679 
01680     // Step 2:  Calculate the normalised dot product of the two vectors, and this forms
01681     //          the cosine of their internal angle.
01682     DocCoord    WidthVect   = End1 - Start;
01683     DocCoord    HeightVect  = End2 - Start;
01684     double      Width       = CalculateLength ( WidthVect );
01685     double      Height      = CalculateLength ( HeightVect );
01686 
01687     // The dot product calculation.
01688     double      DotProduct  = ( double ) ( ( WidthVect.x * HeightVect.x ) +
01689                               ( HeightVect.y * WidthVect.y ) ) / ( Height * Width );
01690     double      DotSine     = sqrt ( 1 - ( DotProduct * DotProduct ) );
01691 
01692     // Set DotSine to be something if it equals zero to prevent zero divide errors.
01693     if ( DotSine == 0 )
01694     {
01695         DotSine = 0.01f;
01696     }
01697 
01698     // The cross product, when applied to a 3D vector, gives the direction of this
01699     // vector. In the case of a 2D vector, only one of the three elements evaluates
01700     // to a non-zero term, and we use this to determine the sign of DotSine.
01701     if ( ( ( WidthVect.x * HeightVect.y ) - ( HeightVect.x * WidthVect.y ) ) > 0 )
01702     {
01703         DotSine = - DotSine;
01704     }
01705 
01706     // Step 3:  Calculate the angle of rotation.
01707     double      WidthCosine = ( double ) ( WidthVect.x * FLASH_FIXED_ONE ) / Width;
01708     double      WidthSine   = ( double ) ( WidthVect.y * FLASH_FIXED_ONE ) / Width;
01709 
01710     // Step 4:  Set all the values, and write them to the matrix.
01711     double      ScaleX      = ( Width * FLASH_FIXED_ONE ) / BMPWidth;
01712     double      ScaleY      = ( DotSine * Height * FLASH_FIXED_ONE ) / BMPHeight;
01713     double      SkewX       = - ( DotProduct / DotSine ) * ScaleY;
01714 
01715     //  Step 5: Write the details of the bitmap fill into the file.
01716     WriteWord ( FLASH_FIRST_ID + pShape->GetBitmapID () );              // Bitmap ID.
01717 
01718     WriteComplexRotation ( End2, ( INT32 ) ScaleX, ( INT32 ) ScaleY,        // Bitmap matrix.
01719                            ( INT32 ) SkewX, 0, End2,
01720                            ( INT32 ) WidthSine, ( INT32 ) WidthCosine );
01721 
01722     return TRUE;
01723 }
01724 
01725 /********************************************************************************************
01726 
01727 >   BOOL FlashExportDC::WritePNG ( OILBitmap    *pBitmap,
01728                                    WORD         BitmapID,
01729                                    UINT32           Alpha,
01730                                    BOOL         IsContoned )
01731 
01732     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01733     Created:    27/9/99
01734     Purpose:    Writes a DIB into a Flash file as a PNG.
01735     Returns:    TRUE if success.
01736     SeeAlso:    -
01737 
01738 ********************************************************************************************/
01739 
01740 BOOL FlashExportDC::WritePNG ( OILBitmap    *pBitmap,
01741                                WORD         BitmapID,
01742                                UINT32           Alpha,
01743                                BOOL         IsContoned )
01744 {
01745     // Local variable definitions.
01746     UINT32          BPP         = pBitmap->GetBPP ();
01747 
01748     // Find out the colour depths for the bitmap, and store Flash code.
01749 
01750     // Use a switch to process the values that need to be written to the file itself.
01751     if ( BPP == 8 || IsContoned)
01752     {
01753         return Write8BitBitmap ( pBitmap, BitmapID, Alpha, IsContoned );
01754     }
01755     else
01756     {
01757         return Write32BitBitmap ( pBitmap, BitmapID, Alpha );
01758     }
01759 }
01760 
01761 /********************************************************************************************
01762 
01763 >   BOOL FlashExportDC::Write32BitBitmap ( OILBitmap    *pBitmap,
01764                                            WORD         BitmapID,
01765                                            UINT32           Alpha )
01766 
01767     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01768     Created:    7/10/99
01769     Inputs:     pBitmap - A pointer a true colour kernel bitmap.
01770     Returns:    TRUE if success, FALSE otherwise.
01771     Purpose:    Writes out a Zlib compressed bitmap record to the Flash file.
01772 
01773 ********************************************************************************************/
01774 
01775 BOOL FlashExportDC::Write32BitBitmap ( OILBitmap    *pBitmap,
01776                                        WORD         BitmapID,
01777                                        UINT32           Alpha )
01778 {
01779     UINT32      Width       = pBitmap->GetWidth ();
01780     UINT32      Height      = pBitmap->GetHeight ();
01781     FilePos     StartPos    = 0;
01782     BOOL        Transparent = FALSE;
01783 
01784     // Currently the alpha channel support for bitmaps is disabled. To re-enable it,
01785     // replace FLASH_BITS_TAG with FLASH_BITS2_TAG. The reasons for this are described
01786     // in swfexpdc.h, method FlashRenderRegion::ProcessTransp ().
01787     StartPos = WriteHeader ( FLASH_BITS_TAG, FLASH_MAX_SHORT, BitmapID + FLASH_FIRST_ID );
01788     WriteByte ( 5 );
01789 
01790     // Height and width of the bitmap image.
01791     WriteWord ( ( WORD ) Width );
01792     WriteWord ( ( WORD ) Height );
01793 
01794     // First initialise the file...
01795     ExportFile->InitCompression ( TRUE );
01796     ExportFile->SetCompression  ( TRUE );
01797 
01798     // Browse through the image, extract the pixel colour values as 32 bit values, and
01799     // store them in the bitmap buffer.
01800     for ( INT32 y = ( Height - 1 ) ; y >= 0; y-- )
01801     {
01802         for ( UINT32 x = 0; x < Width; x++ )
01803         {
01804             // Get the colour. It's necessary to create the value for the alpha channel as a
01805             // UINT32 first before scaling it down to a BYTE to prevent rendering artefacts due
01806             // to overflows. (I do the same thing with the shadow code.)
01807             Pixel32bpp  Colour      = pBitmap->ReadPixel32bpp ( x, y );
01808             BYTE        BitmapAlpha = ~static_cast <BYTE>   ( Colour.Alpha );
01809             BYTE        ByteAlpha   = static_cast <BYTE>    ( Alpha );
01810             UINT32      ActualAlpha = ( BitmapAlpha * ByteAlpha ) / 255;
01811 
01812             // Check the written byte. If it comes out as 255 for every pixel then the bitmap
01813             // is opaque, and it can be stored as a non-transparent bitmap record. The Flash
01814             // player has trouble with too many overlapping transparencies, so keeping the
01815             // number used down will result in better image quality.
01816             if ( ActualAlpha != 255 )
01817             {
01818                 Transparent = TRUE;
01819             }
01820 
01821             // And store it. The first line blends any transparency set on the bitmap, with
01822             // its own alpha channel.
01823             WriteByte ( static_cast <BYTE> ( ActualAlpha ) );
01824             WriteByte ( Colour.Red );
01825             WriteByte ( Colour.Green );
01826             WriteByte ( Colour.Blue );
01827         }
01828     }
01829 
01830     // Finally close down GZipFile.
01831     ExportFile->SetCompression ( FALSE );
01832 
01833     // If the file contains a transparent bitmap, go back and fill in the header.
01834     if ( Transparent )
01835     {
01836         // Set up the endpoint of the file.
01837         FilePos EndPos = ExportFile->tell ();
01838 
01839         // Go back to the beginning of the header.
01840         ExportFile->seekIn ( ( StartPos - 6 ) );
01841 
01842         // The header for a transparent bitmap record. This needs to be done manually to
01843         // prevent a defualt value for the size being written in.
01844         WriteHeader ( FLASH_BITS2_TAG, FLASH_MAX_SHORT );
01845 
01846         // Return to the end of the file.
01847         ExportFile->seekIn ( EndPos );
01848     }
01849 
01850     // Go back, and fill in the number of bytes written.
01851     WriteTagSize ( StartPos );
01852 
01853     return TRUE;
01854 }
01855 
01856 /********************************************************************************************
01857 
01858 >   BOOL FlashExportDC::Write8BitBitmap ( OILBitmap *pBitmap,
01859                                           WORD      BitmapID,
01860                                           BOOL      IsContoned,
01861                                           UINT32        Alpha )
01862 
01863     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01864     Created:    1/12/99
01865     Inputs:     pBitmap         - A pointer a 256 colour kernel bitmap.
01866                 BitmapID        - The ID for this bitmap.
01867                 IsContoned      - Is the bitmap contoned.
01868                 Transparency    - The transparency value for the bitmap.
01869     Returns:    TRUE if success, FALSE otherwise.
01870     Purpose:    Writes out a Zlib compressed bitmap record to the Flash file.
01871 
01872 ********************************************************************************************/
01873 
01874 BOOL FlashExportDC::Write8BitBitmap ( OILBitmap *pBitmap,
01875                                       WORD      BitmapID,
01876                                       UINT32        Alpha,
01877                                       BOOL      IsContoned )
01878 {
01879     // Set up the local variables.
01880     UINT32  NumColours  = pBitmap->GetNumPaletteEntries ();         // Number of colours.
01881     BOOL    Transparent = Alpha != 255;
01882     FilePos StartPos    = Write8BitHeader ( pBitmap, BitmapID, NumColours - 1, Transparent );
01883     BYTE    ByteAlpha   = static_cast <BYTE> ( Alpha );
01884 
01885     // And then write out the palette entries themselves.
01886     if ( IsContoned )
01887     {
01888         for ( UINT32 i = 0; i < NumColours; i++ )
01889         {
01890             // Write the colour out as a contoned palette entry.
01891             WriteColour ( pBitmap->GetContonePaletteEntry ( i ) );
01892 
01893             // Only write out the alpha channel if the bitmap is transparent.
01894             if ( Transparent )
01895             {
01896                 WriteByte   ( ByteAlpha );
01897             }
01898         }
01899     }
01900     else
01901     {
01902         LPRGBQUAD   pPalette    = pBitmap->GetPaletteForBitmap ();  // Pointer to palette.
01903 
01904         for ( UINT32 i = 0; i < NumColours; i++ )
01905         {
01906             // I'm writing them out individually to ensure that they're saved to the file
01907             // in the correct bit and byte order.
01908             WriteByte ( pPalette[i].rgbRed );
01909             WriteByte ( pPalette[i].rgbGreen );
01910             WriteByte ( pPalette[i].rgbBlue );
01911 
01912             // Only write out the alpha channel if the bitmap is transparent.
01913             if ( Transparent )
01914             {
01915                 WriteByte   ( ByteAlpha );
01916             }
01917         }
01918     }
01919 
01920     // Write out the body of the bitmap itself.
01921     return Write8BitBody ( pBitmap, StartPos );
01922 }
01923 
01924 /********************************************************************************************
01925 
01926 >   BOOL FlashExportDC::WriteTransparentBitmap ( OILBitmap  *pBitmap,
01927                                                  WORD       BitmapID,
01928                                                  DocColour  Colour )
01929 
01930     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01931     Created:    3/12/99
01932     Inputs:     pBitmap     - A pointer a 256 colour OIL bitmap.
01933                 BitmapID    - The ID number for the bitmap.
01934                 Colour      - The colour of the transparency.
01935     Returns:    TRUE if success, FALSE otherwise.
01936     Purpose:    Writes out a Zlib compressed bitmap record to the Flash file. This contains
01937                 a transparent Camelot fill.
01938 
01939 ********************************************************************************************/
01940 
01941 BOOL FlashExportDC::WriteTransparentBitmap ( OILBitmap  *pBitmap,
01942                                              WORD       BitmapID,
01943                                              DocColour  Colour )
01944 {
01945     // Generate the header for the bitmap tag.
01946     FilePos StartPos = Write8BitHeader ( pBitmap, BitmapID, 255, TRUE );
01947 
01948     // Write out the palette.
01949     for ( UINT32 i = 0; i < 256; i++ )
01950     {
01951         // I'm writing them out individually to ensure that they're saved to the file
01952         // in the correct bit and byte order.
01953         WriteColour ( Colour );
01954         WriteByte   ( ~static_cast <BYTE> ( i ) );
01955     }
01956 
01957     // Write out the body of the bitmap itself.
01958     return Write8BitBody ( pBitmap, StartPos );
01959 }
01960 
01961 /********************************************************************************************
01962 
01963 >   BOOL FlashExportDC::WriteShadowBitmap ( OILBitmap   *pBitmap,
01964                                             WORD        BitmapID,
01965                                             DocColour   Colour,
01966                                             UINT32      Darkness )
01967 
01968     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01969     Created:    19/11/00
01970     Inputs:     pBitmap     - A pointer a 256 colour OIL bitmap.
01971                 BitmapID    - The ID number for the bitmap.
01972                 Colour      - The colour of the transparency.
01973                 Darkenss    - The darkness of the shadow.
01974     Returns:    TRUE if success, FALSE otherwise.
01975     Purpose:    Writes out a Zlib compressed bitmap record to the Flash file. This contains
01976                 a transparent bitmap representing the shadow.
01977 
01978 ********************************************************************************************/
01979 
01980 BOOL FlashExportDC::WriteShadowBitmap ( OILBitmap   *pBitmap,
01981                                         WORD        BitmapID,
01982                                         DocColour   Colour,
01983                                         UINT32      Darkness )
01984 {
01985     // Generate the header for the bitmap tag.
01986     FilePos StartPos = Write8BitHeader ( pBitmap, BitmapID, 255, TRUE );
01987 
01988     // Write out the palette.
01989     for ( UINT32 i = 0; i < 256; i++ )
01990     {
01991         // Calculate the darkness of the shadow.
01992         BYTE NotI       = ~static_cast <BYTE> ( i );
01993         BYTE NotDark    = ~static_cast <BYTE> ( Darkness );
01994         UINT32 Alpha        = ( NotI  * NotDark ) / 255;
01995 
01996         // I'm writing them out individually to ensure that they're saved to the file
01997         // in the correct bit and byte order.
01998         WriteColour ( Colour );
01999         WriteByte   ( static_cast <BYTE> ( Alpha ) );
02000     }
02001 
02002     // Write out the body of the bitmap itself.
02003     return Write8BitBody ( pBitmap, StartPos );
02004 }
02005 
02006 /********************************************************************************************
02007 
02008 >   BOOL FlashExportDC::Write8BitHeader ( OILBitmap *pBitmap,
02009                                           WORD      BitmapID,
02010                                           UINT32        NumColours,
02011                                           BOOL      Transparent )
02012 
02013     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02014     Created:    19/11/00
02015     Inputs:     pBitmap     - A pointer a 256 colour OIL bitmap.
02016                 BitmapID    - The ID number for the bitmap.
02017     Returns:    StartPos    - The position of the start of this Flash tag.
02018     Purpose:    Writes out the header for a 256 colour bitmap.
02019 
02020 ********************************************************************************************/
02021 
02022 FilePos FlashExportDC::Write8BitHeader ( OILBitmap  *pBitmap,
02023                                          WORD       BitmapID,
02024                                          UINT32     NumColours,
02025                                          BOOL       Transparent )
02026 {
02027     // Write out a DefineBitsLossless2 header.
02028     FilePos StartPos = 0;
02029     
02030     // Is it a transparent bitmap?
02031     if ( Transparent )
02032     {
02033         // Yes, write out a transparent bitmap header.
02034         StartPos = WriteHeader ( FLASH_BITS2_TAG, FLASH_MAX_SHORT,
02035                                  BitmapID + FLASH_FIRST_ID );
02036     }
02037 
02038     else
02039     {
02040         // No, write out an opaque bitmap header.
02041         StartPos = WriteHeader ( FLASH_BITS_TAG, FLASH_MAX_SHORT,
02042                                  BitmapID + FLASH_FIRST_ID );
02043     }
02044 
02045     // Colour depth. (3 = 8 bits per pixel.)
02046     WriteByte ( 3 );
02047 
02048     // Height and width of the bitmap image.
02049     WriteWord ( static_cast <WORD> ( pBitmap->GetWidth () ) );
02050     WriteWord ( static_cast <WORD> ( pBitmap->GetHeight () ) );
02051 
02052     // Write the number of colours to the file.
02053     WriteByte ( static_cast <BYTE> ( NumColours ) );
02054 
02055     // First initialise the file...
02056     ExportFile->InitCompression ( TRUE );
02057     ExportFile->SetCompression  ( TRUE );
02058 
02059     // Return the start position of the file.
02060     return StartPos;
02061 }
02062 
02063 /********************************************************************************************
02064 
02065 >   BOOL FlashExportDC::Write8BitBody ( OILBitmap   *pBitmap,
02066                                         FilePos     StartPos )
02067 
02068     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02069     Created:    19/11/00
02070     Inputs:     pBitmap     - A pointer a 256 colour OIL bitmap.
02071             :   StartPos    - The position of the start of this Flash tag.
02072     Returns:    TRUE if success, FALSE otherwise.
02073     Purpose:    Writes out the header for a 256 colour bitmap.
02074 
02075 ********************************************************************************************/
02076 
02077 BOOL FlashExportDC::Write8BitBody ( OILBitmap   *pBitmap,
02078                                     FilePos     StartPos )
02079 {
02080     UINT32  Width   = pBitmap->GetWidth ();                 // The bitmap's width.
02081     UINT32  Height  = pBitmap->GetHeight ();                // The bitmap's height.
02082     INT32       Offset  = ( 4 - ( Width % 4 ) ) % 4;            // To align the bitmap.
02083 
02084     // Browse through the image, extract the pixel colour values as 32 bit values, and
02085     // store them in the bitmap buffer.
02086     for ( INT32 y = ( Height - 1 ) ; y >= 0; y-- )
02087     {
02088         for ( UINT32 x = 0; x < Width; x++ )
02089         {
02090             // Write the colour out.
02091             WriteByte   ( static_cast < BYTE > ( pBitmap->ReturnPaletteIndexUsed ( x, y ) ) );
02092         }
02093 
02094         // Flash bitmaps have to be aligned to a 32 bit boundary along their
02095         // width. This adds in the padding.
02096         for ( INT32 i = 0; i < Offset; i++ )
02097         {
02098             WriteByte ( 0 );
02099         }
02100     }
02101 
02102     // Finally close down GZipFile.
02103     ExportFile->SetCompression ( FALSE );
02104 
02105     // Go back, and fill in the number of bytes written.
02106     WriteTagSize ( StartPos );
02107 
02108     return TRUE;
02109 }
02110 
02111 /********************************************************************************************
02112 
02113 >   BOOL FlashExportDC::WriteDefineFont ( FlashFontRecord *pRecord )
02114 
02115     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02116     Created:    7/10/99
02117     Inputs:     pRecord - A pointer to the head of a FlashFontRecord linked list.
02118     Returns:    TRUE if success, FALSE otherwise.
02119     Purpose:    Writes out a string DefineFont records.
02120 
02121 ********************************************************************************************/
02122 
02123 BOOL FlashExportDC::WriteDefineFont ( FlashFontRecord *pRecord )
02124 {
02125     // Declare and define all local variables.
02126     WCHAR       *pChars     = pRecord->GetGlyphs ();
02127     UINT32      i           = 0;
02128     UINT32      j           = 0;
02129     FilePos     StartPos    = 0;
02130     FilePos     OffsetPos   = 0;
02131     FilePos     Counter     = 0;
02132     WORD        ID          = pRecord->GetFontID () + FlashPlaceObject::GetBitmapCount ()
02133                               + FLASH_FIRST_ID;
02134 
02135     // Write the Flash file header.
02136     StartPos = WriteHeader ( FLASH_FONT_TAG, FLASH_MAX_SHORT, ID );
02137     
02138     // Write the font data segment.
02139 
02140     // Set offset return point.
02141     OffsetPos = ExportFile->tell();
02142 
02143     // Offset table
02144 
02145     // There are as many offsets as there are glyphs, therefore I'm counting the
02146     // number of entries in the glyph string. Since it's terminated by a zero, it's
02147     // easy to spot the end.
02148     while ( pChars [i] )
02149     {
02150         WriteWord ( 0 );
02151         i++;
02152     }
02153 
02154     // Set up an index variable, and a pointer to the path handles in the FlashTextRecord.
02155 
02156     while ( pChars [j] )
02157     {
02158         // Scoped variables.
02159         FilePos     CurrentPos  = 0;
02160         Path        **pPath     = pRecord->GetPaths ();
02161         DocCoord    *Coords     = NULL;
02162 
02163         // Jump back to offset table, and fill in offset.
02164         CurrentPos = ExportFile->tell ();
02165 
02166         ExportFile->seekIn ( OffsetPos + Counter);          // Go back to the offset table.
02167         WriteWord ( ( WORD ) ( CurrentPos - OffsetPos ) );  // Write in the appropriate size.
02168         ExportFile->seekIn ( CurrentPos );                  // Return to the end of the file.
02169 
02170         // Write out the paths, ignoring NULL paths.
02171         if ( pPath [j] != NULL )
02172         {
02173             Coords = pPath [j]->GetCoordArray ();
02174         }
02175 
02176         // Write a font style definition.
02177         WriteBits ( 1, 4 );     // One bit for Fill...
02178         WriteBits ( 0, 4 );     // ... and nothing for Line Style.
02179 
02180         // Only write a path out if there's a path stored with the glyph. Otherwise do an
02181         // empty edge record (which is how Flash deals with spaces).
02182         if ( Coords != NULL )
02183         {
02184             // Write the edge record.
02185             WriteEdgeRecord ( Coords, NULL, pPath [j]->GetVerbArray(),
02186                               pPath [j]->GetNumCoords (), 0, 1, 0);
02187         }
02188         else
02189         {
02190             // End of shape.
02191             WriteBits  ( 0, 6 );
02192             ByteAlign ( );          // Align bits to byte boundary.
02193         }
02194 
02195         j++;                        // Increment the character that's being pointed to.
02196         Counter += 2;               // Increment the counter to the offsets by 2 bytes.
02197     }
02198 
02199     // Write in the size of the DefineFontInfo record after everything's been done.
02200     WriteTagSize ( StartPos );
02201 
02202     // Call WriteDefineFontInfo directly, to ensure that the records are in order.
02203     return WriteDefineFontInfo ( pRecord );
02204 }
02205 
02206 /********************************************************************************************
02207 
02208 >   BOOL FlashExportDC::WriteDefineFontInfo ( FlashFontRecord *pRecord )
02209 
02210     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02211     Created:    7/10/99
02212     Inputs:     pRecord - A pointer to the head of a FlashFontRecord linked list.
02213     Returns:    TRUE if success, FALSE otherwise.
02214     Purpose:    Writes out a string DefineFontInfo records.
02215 
02216 ********************************************************************************************/
02217 
02218 BOOL FlashExportDC::WriteDefineFontInfo ( FlashFontRecord *pRecord )
02219 {
02220     WORD        Typeface    = pRecord->GetTypeface ();
02221     WORD        FontID      = pRecord->GetFontID ();
02222     WORD        ID          = FontID + FlashPlaceObject::GetBitmapCount () + FLASH_FIRST_ID;
02223     FilePos     StartPos    = 0;
02224     TCHAR       *pFontName  = NULL;
02225     String_64   FontName;
02226 
02227     // Now add the DefineFontInfo structure that is needed to glue this thing together.
02228     StartPos = WriteHeader ( FLASH_FONT_INFO_TAG, FLASH_MAX_SHORT, ID );
02229 
02230     // Check that the font handle is valid.
02231     if ( !( FONTMANAGER->IsFontValid ( Typeface ) ) )
02232     { 
02233         // Force the program to use Times New Roman.
02234         Typeface = DEFAULTHANDLE;
02235     }
02236 
02237     // Extract the font name from the font manager class.
02238     FONTMANAGER->GetFontName ( Typeface, FontName );
02239 
02240     pFontName = ( TCHAR* ) FontName;
02241     WriteByte ( ( BYTE ) FontName.Length () );
02242 
02243     // Write the font name to the file.
02244     while ( *pFontName )
02245     {
02246         WriteByte ( ( BYTE ) *pFontName );
02247         pFontName ++;
02248     }
02249 
02250     // Write the definition flags to the file.
02251     WriteBits ( 0, 2 );                         // Reserved flags.
02252     WriteBits ( 0, 1 );                         // Unicode format.
02253     WriteBits ( 0, 1 );                         // Shift-JIS character codes.
02254     WriteBits ( 0, 1 );                         // ANSI character codes.
02255     WriteBits ( pRecord->GetIsItalic (), 1 );   // Italic.
02256     WriteBits ( pRecord->GetIsBold (), 1 );     // Bold.
02257     WriteBits ( 0, 1 );                         // Using 8-bit character codes.
02258 
02259     // Write a list of the characters used. These must be in the same order as the paths
02260     // that are written in the DefineFont record.
02261     WCHAR *pGlyphs = pRecord->GetGlyphs ();
02262 
02263     // Find the size of the array.
02264     UINT32 Size = wcslen ( pGlyphs );
02265 
02266     // Create an array to store the characters in.
02267 #if 0
02268     char ASCIIChars [FLASH_TEXT_ARRAY_SIZE];
02269 
02270     // Convert the unicode characters into ASCII characters.
02271     if ( WideCharToMultiByte ( CP_ACP, 0, pGlyphs, Size, ASCIIChars, FLASH_TEXT_ARRAY_SIZE,
02272                                NULL, NULL ) )
02273     {
02274         // Write the string out to disk.
02275         Write ( ASCIIChars, Size );
02276     }
02277 #else
02278     // Bodge using wx
02279     wxString temp(pGlyphs);
02280     Write (temp.mb_str(), Size);
02281 
02282 #endif
02283     
02284 
02285     WriteTagSize ( StartPos );
02286 
02287     return TRUE;
02288 }
02289 
02290 /********************************************************************************************
02291 
02292 >   BOOL FlashExportDC::WriteText ( FlashTextRecord *pText )
02293 
02294     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02295     Created:    20/10/99
02296     Inputs:     pText - A pointer to a FlashTextRecord containing the string.
02297     Returns:    TRUE if success, FALSE otherwise.
02298     Purpose:    Writes the contents of the FlashTextRecord into a file in the correct
02299                 format for a Flash file.
02300 
02301 ********************************************************************************************/
02302 
02303 BOOL FlashExportDC::WriteText ( FlashTextRecord *pText )
02304 {
02305     // Calculate the text ID.
02306     WORD        TextID      = FLASH_FIRST_ID + FlashPlaceObject::GetBitmapCount () +
02307                               FlashPlaceObject::GetFontCount () + pText->GetTextID ();
02308     FilePos     StartPos    = 0;
02309     DocRect     Bounds      = pText->GetBounds ();
02310 
02311     // Now add the DefineText structure that is needed to glue this thing together.
02312     StartPos = WriteHeader ( FLASH_TEXT_TAG, FLASH_MAX_SHORT, TextID );
02313 
02314     // Do the Text export here.
02315     Transform ( &Bounds );
02316 
02317     // Write the bounding box and matrix.
02318     WriteBoundingBox ( Bounds );            // Write the bounding box.
02319 
02320     WriteTextMatrix ( pText->GetScaleX (),  // Create and write the text matrix.
02321                       pText->GetScaleY (),
02322                       pText->GetSkewX (),
02323                       pText->GetSkewY (),
02324                       pText->GetAspect () );
02325 
02326     WriteTextRecord ( pText );
02327 
02328     WriteTagSize ( StartPos );
02329 
02330     return TRUE;
02331 }
02332 
02333 /********************************************************************************************
02334 
02335 >   BOOL FlashExportDC::WriteTextMatrix ( INT32 ScaleX,
02336                                           INT32 ScaleY,
02337                                           INT32 SkewX,
02338                                           INT32 SkewY,
02339                                           FIXED16 Aspect )
02340 
02341     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02342     Created:    23/11/99
02343     Inputs:     Aspect - The font's aspect ratio.
02344                 ScaleX, ScaleY, SkewY, SkewX - Components of the rotation matrix.
02345     Returns:    TRUE if success.
02346     Purpose:    Creates and writes the correct matrix for the current text string to the
02347                 file.
02348 
02349 ********************************************************************************************/
02350 
02351 BOOL FlashExportDC::WriteTextMatrix ( INT32 ScaleX,
02352                                       INT32 ScaleY,
02353                                       INT32 SkewX,
02354                                       INT32 SkewY,
02355                                       const FIXED16 &Aspect )
02356 {
02357     // Convert the aspect to a double for extra accuracy. (52 bits, as opposed to 32 bits.)
02358     double      dAspect     = ( ( double ) Aspect.GetRawLong () ) / FLASH_FIXED_ONE;
02359 
02360     // Multiply in the aspect ratio value as the new variables are declared.
02361     double      dScaleX     = ( ( double ) ScaleX * dAspect );
02362     double      dSkewY      = ( ( double ) SkewY * dAspect );
02363 
02364     // And set the position.
02365     DocCoord    Position    ( 0, 0 );
02366 
02367     // Finally, write the matrix to the file.
02368     return WriteMatrix ( Position, ( INT32 ) dScaleX, ScaleY, SkewX, ( INT32 ) dSkewY );
02369 }
02370 
02371 /********************************************************************************************
02372 
02373 >   BOOL FlashExportDC::WriteTextRecord ( FlashTextRecord *pText )
02374 
02375     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02376     Created:    23/11/99
02377     Inputs:     pText - A pointer to the current FlashTextRecord.
02378     Returns:    TRUE if success.
02379     Purpose:    Writes the DefineText's text record into the file.
02380 
02381 ********************************************************************************************/
02382 
02383 BOOL FlashExportDC::WriteTextRecord ( FlashTextRecord *pText )
02384 {
02385     // Count the number of bits in the offsets and glyph indicies, and store these.
02386     INT32           *Text       = pText->GetString ();      // Pointer to the text string.
02387     INT32       *Advances   = pText->GetAdvances ();    // The advance values for the font.
02388     WORD        *Styles     = pText->GetFontStyles ();  // An array of styles.
02389     WORD        *Sizes      = pText->GetSizes ();       // The sizes for the text items.
02390     FlashColour *Colours    = pText->GetColours ();     // The colours of the letters.
02391     INT8        *Offsets    = pText->GetOffsets ();     // The Y offsets.
02392     INT32           MaxText     = 0;                        // The largest text identifier.
02393     UINT32      TextBits    = 0;                        // Bits required for text ID.
02394     INT32       MaxAdvance  = 0;                        // The largest text advance value.
02395     UINT32      AdvanceBits = 0;                        // Bits required for advance.
02396     FilePos     StartGlyphs = 0;
02397     BYTE        GlyphCount  = 0;
02398 
02399     // Calculate the aspect ratio.
02400     double      Aspect      = ( ( double ) ( pText->GetAspect () ).GetRawLong() )
02401                                 / FLASH_FIXED_ONE;
02402 
02403     // Count the number of bits required to store the text, and the Advances.
02404     for ( INT32 i = 0; i < pText->GetCount (); i++ )
02405     {
02406         // Adjust the advances so that they take the aspect ratio into account.
02407         Advances [i] = ( INT32 ) ( ( double ) Advances [i] / Aspect );
02408 
02409         // Compare the raw text code with the maximum value encountered so far.
02410         if ( Text [i] > MaxText )
02411             MaxText = Text [i];
02412 
02413         // And also compare the Advance values.
02414         if ( Advances [i] > MaxAdvance )
02415             MaxAdvance = Advances [i];
02416     }
02417 
02418     TextBits    = CountBits ( MaxText , FALSE );        // Calculate the number of text bits.
02419     AdvanceBits = CountBits ( MaxAdvance, TRUE );       // And for the Advances.
02420 
02421     WriteByte ( ( BYTE ) TextBits );                    // Now write the text value to the file.
02422     WriteByte ( ( BYTE ) AdvanceBits );                 // And then the Advance values.
02423 
02424     // This for loop does most of the work in this loop. The algorithm is:
02425     // - Write a define text style record for the current character style.
02426     // - Write a glyph record header.
02427     // - Cycle through the fonts, whilst the style remains identical, and
02428     //   write them to the file.
02429     // - If a new style is required, 
02430     for ( INT32 j = 0; j < pText->GetCount (); j++ )
02431     {
02432         // Determine whether either the size, font style, or colour have
02433         // been changed. The code relies on the fact that the binary
02434         // operators return 1 iff true, otherwise they return 0. Thus
02435         // HasFont and HasColour have values of either 1 or 0.
02436         UINT32 HasFont  = 1;
02437         UINT32 HasColour    = 1;
02438         UINT32 HasYOffset   = 1;
02439 
02440         // Ignore any offsets that are 0.
02441         if ( Offsets [j] == 0 )
02442             HasYOffset = 0;
02443 
02444         // Determine whether or not the text style has changed.
02445         if ( j > 0 )
02446         {
02447             HasFont     = ( Styles [j] != Styles [j-1] ) ||
02448                           ( Sizes [j] != Sizes [j-1] );
02449 
02450             HasColour   = ( Colours [j].Red != Colours [j-1].Red ) ||
02451                           ( Colours [j].Green != Colours [j-1].Green ) ||
02452                           ( Colours [j].Blue != Colours [j-1].Blue ) ||
02453                           ( Colours [j].Alpha != Colours [j-1].Alpha );
02454 
02455             HasYOffset  = ( Offsets [j] != Offsets [j-1] );
02456         }
02457 
02458         // If a change has been made, write a record to encode the changes.
02459         if ( HasFont || HasColour || HasYOffset )
02460         {
02461             if ( j > 0 )
02462             {
02463                 WriteGlyphHeader ( StartGlyphs, GlyphCount );
02464                 GlyphCount = 0;
02465             }
02466 
02467             // Write a new Glyph Type.
02468             StartGlyphs = WriteChangeText ( Colours [j], Sizes [j], Styles [j], Offsets [j],
02469                                             HasColour, HasFont, HasYOffset );
02470         }
02471 
02472         // Write out the font.
02473         WriteBits ( Text [j], TextBits );
02474 
02475         // Write out the advances, correcting for the current aspect ratio.
02476         // WriteBits ( ( INT32 ) ( ( double ) Advances [j] * dInvAsp ), AdvanceBits );
02477         WriteBits ( Advances [j], AdvanceBits );
02478 
02479         GlyphCount ++;
02480     }
02481 
02482     // Complete the file record.
02483     WriteGlyphHeader ( StartGlyphs, GlyphCount );
02484     WriteByte ( 0 );
02485 
02486     return TRUE;
02487 }
02488 
02489 /********************************************************************************************
02490 
02491 >   FilePos FlashExportDC::WriteChangeText ( const FlashColour &Colour,
02492                                              WORD Size,
02493                                              WORD Style,
02494                                              INT8 YOffset,
02495                                              UINT32 HasColour,
02496                                              UINT32 HasFont,
02497                                              UINT32 HasYOffset )
02498 
02499     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02500     Created:    28/10/99
02501     Inputs:     FlashColour - The current colour of the text.
02502                 Size        - The size of the typeface of the current character.
02503                 Style       - The typeface being used.
02504                 YOffset     - The current y offset value.
02505                 HasColour   - Does the font have a colour value set?
02506                 HasFont     - Has the font style changed, or has it been resized?
02507                 HasYOffset  - Has the offset of the font been changed?
02508     Returns:    filepos     - The position of the start of the new glyph record.
02509     Purpose:    Writes a record to the file to change the font style being used.
02510 
02511 ********************************************************************************************/
02512 
02513 FilePos FlashExportDC::WriteChangeText ( const FlashColour &TextColour,
02514                                          WORD Size,
02515                                          WORD Style,
02516                                          INT8 YOffset,
02517                                          UINT32 HasColour,
02518                                          UINT32 HasFont,
02519                                          UINT32 HasYOffset )
02520 {
02521     FilePos NewRecord = 0;              // Return value.
02522 
02523     // Write a new Glyph Type.
02524     WriteBits ( 1, 1 );                 // Is a TextRecord Type 1.
02525     WriteBits ( 0, 3 );                 // Reserved flags.
02526     WriteBits ( HasFont, 1 );           // Is the font style changed?
02527     WriteBits ( HasColour, 1 );         // Has the colour changed?
02528     WriteBits ( HasYOffset, 1 );        // Has the font got a Y offset?
02529     WriteBits ( 0, 1 );                 // Has the font got an X offset?
02530 
02531     // Write the typeface style.
02532     if ( HasFont )
02533     {
02534         WriteWord ( Style + FlashPlaceObject::GetBitmapCount ()
02535                     + FLASH_FIRST_ID );
02536     }
02537 
02538     // Write the font's colour.
02539     if ( HasColour )
02540     {
02541         WriteColour ( TextColour );
02542     }
02543 
02544     // Write the current Y offset value.
02545     if ( HasYOffset )
02546     {
02547         WriteWord ( YOffset );
02548     }
02549 
02550     // Write the font's size.
02551     if ( HasFont )
02552     {
02553         WriteWord ( ( Size ) );
02554     }
02555 
02556     NewRecord = ExportFile->tell ();    // Get the start of the next record.
02557     WriteByte ( 0 );                    // Placeholder value.
02558 
02559     return NewRecord;
02560 }
02561 
02562 /********************************************************************************************
02563 
02564 >   BOOL FlashExportDC::WriteGlyphHeader ( FilePos Start,
02565                                            BYTE GlyphCount )
02566 
02567     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02568     Created:    28/10/99
02569                 Start       - The start of the glyph record.
02570     Inputs:     GlyphCount  - The number of glyphs used.
02571     Returns:    TRUE if success.
02572     Purpose:    Fills in the number of glyphs used.
02573 
02574 ********************************************************************************************/
02575 
02576 BOOL FlashExportDC::WriteGlyphHeader ( FilePos Start,
02577                                        BYTE GlyphCount )
02578 {
02579     FilePos EndOfFile;
02580 
02581     ByteAlign ();                   // Align the bits to nearest byte boundary.
02582 
02583     EndOfFile = ExportFile->tell ();
02584     // Go back to the start of the last glyph record.
02585     ExportFile->seekIn ( Start );
02586 
02587     WriteBits ( 0, 1 );             // Is a TextRecord Type 0.
02588     WriteBits ( GlyphCount, 7 );    // The number of glyphs used.
02589 
02590     ExportFile->seekIn ( EndOfFile );
02591 
02592     return TRUE;
02593 }
02594 
02595 /********************************************************************************************
02596 
02597 >   BOOL FlashExportDC::WriteTagSize ( FilePos StartPos )
02598 
02599     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02600     Created:    28/10/99
02601     Inputs:     StartPos    - The file position at the start of the tag.
02602     Returns:    TRUE if success.
02603     Purpose:    Fills in the number of byte used by the tag.
02604 
02605 ********************************************************************************************/
02606 
02607 BOOL FlashExportDC::WriteTagSize ( FilePos StartPos )
02608 {
02609     // Go back to the start of the tag, and write in the size of the Flash record.
02610     FilePos EndPos = ExportFile->tell ();       // Get the current position in the file.
02611 
02612     ExportFile->seekIn ( ( StartPos - 4 ) );    // Go back to the start of the tag's header.
02613     WriteLong ( (INT32)EndPos-(INT32)StartPos );    // Write in the appropriate size value.
02614     ExportFile->seekIn ( EndPos );              // Run to the end of the file.
02615 
02616     return TRUE;
02617 }
02618 
02619 /********************************************************************************************
02620 
02621 >   BOOL FlashExportDC::BuildComplexRotation ( DocCoord &Position,
02622                                                INT32 &ScaleX,
02623                                                INT32 &ScaleY,
02624                                                INT32 &SkewX,
02625                                                INT32 &SkewY,
02626                                                const DocCoord &Centre,
02627                                                INT32 SinTheta,
02628                                                INT32 CosTheta )
02629 
02630     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02631     Created:    28/11/99
02632     Inputs:     Position    - The x and y translation values in the original matrix.
02633                 ScaleX      - The scale value for the x axis.
02634                 ScaleY      - The scale value for the y axis.
02635                 SkewY       - First skew value.
02636                 SkewX       - Second skew value.
02637                 ( The above correspond to the basic Flash matrix values. )
02638                 Centre      - The centre of the rotation.
02639                 SinTheta    - The sine of the rotation.
02640                 CosTheta    - The cosine of the rotation.
02641     Returns:    TRUE if success.
02642     Purpose:    Creates a matrix which combines the the transformation in the passed
02643                 in matrix, with the rotation described by CosTheta and SinTheta around
02644                 the point Center. The inputted values (ScaleX, ScaleY, SkewY, SkewX,
02645                 Position) are then reassigned the new matrix values, and since
02646                 they're passed in as references, they return these to the calling
02647                 function.
02648 
02649 ********************************************************************************************/
02650 
02651 void FlashExportDC::BuildComplexRotation ( DocCoord &Position,
02652                                            INT32 &ScaleX,
02653                                            INT32 &ScaleY,
02654                                            INT32 &SkewX,
02655                                            INT32 &SkewY,
02656                                            const DocCoord &Centre,
02657                                            INT32 SinTheta,
02658                                            INT32 CosTheta )
02659 {
02660     // Reassign the variables to a series of doubles (as usual for extra precision),
02661     // and multiply the two matrices together in the process. The composition of this
02662     // new matrix is:
02663     //
02664     // | dScaleX    dSkewX      dPositionX |
02665     // | dSkewY     dScaleY     dPositionY |
02666     // | 0          0           1          |
02667     //
02668     // dShiftX and dShiftY are the values from the rotation matrix. Basically, you
02669     // shift the image so that it's centred around (0, 0), rotate it, and put it
02670     // back where it was. Effectively this involves compositing three matrices, and
02671     // the net result is identical to the usual rotation matrix, with the exception
02672     // of the translation values.
02673     double dShiftX      = ( ( ( ( double ) - CosTheta * ( double ) Centre.x ) +
02674                           ( ( double ) SinTheta * ( double ) Centre.y ) ) / FLASH_FIXED_ONE )
02675                           + ( double ) Centre.x;
02676 
02677     double dShiftY      = ( ( ( ( double ) - SinTheta * ( double ) Centre.x ) -
02678                           ( ( double ) CosTheta * ( double ) Centre.y ) ) / FLASH_FIXED_ONE )
02679                           + ( double ) Centre.y;
02680 
02681     // Now calculate the body of the matrix.
02682     double dScaleX      = ( ( ( double ) ScaleX * ( double ) CosTheta ) -
02683                           ( ( double ) SkewY * ( double ) SinTheta ) ) /
02684                           FLASH_FIXED_ONE;
02685 
02686     double dScaleY      = ( ( ( double ) SkewX * ( double ) SinTheta ) +
02687                           ( ( double ) ScaleY * ( double ) CosTheta ) ) /
02688                           FLASH_FIXED_ONE;
02689 
02690     double dSkewX       = ( ( ( double ) SkewX * ( double ) CosTheta ) -
02691                           ( ( double ) ScaleY * ( double ) SinTheta ) ) /
02692                           FLASH_FIXED_ONE;
02693 
02694     double dSkewY       = ( ( ( double ) ScaleX * ( double ) SinTheta ) +
02695                           ( ( double ) SkewY * ( double ) CosTheta ) ) /
02696                           FLASH_FIXED_ONE;
02697 
02698     double dPositionX   = ( ( ( ( double ) Position.x * ( double ) CosTheta ) -
02699                           ( ( double ) Position.y * ( double ) SinTheta ) ) / FLASH_FIXED_ONE ) +
02700                           dShiftX;
02701 
02702     double dPositionY   = ( ( ( ( double ) Position.x * ( double ) SinTheta ) +
02703                           ( ( double ) Position.y * ( double ) CosTheta ) ) / FLASH_FIXED_ONE ) +
02704                           dShiftY;
02705 
02706     // Cast the values back into longs, and the function is complete.
02707     ScaleX      = ( INT32 ) dScaleX;
02708     ScaleY      = ( INT32 ) dScaleY;
02709     SkewX       = ( INT32 ) dSkewX;
02710     SkewY       = ( INT32 ) dSkewY;
02711     Position.x  = ( INT32 ) dPositionX;
02712     Position.y  = ( INT32 ) dPositionY;
02713 }
02714 
02715 /********************************************************************************************
02716 
02717 >   BOOL FlashExportDC::WriteComplexRotation ( DocCoord Position,
02718                                                INT32 ScaleX,
02719                                                INT32 ScaleY,
02720                                                INT32 SkewX,
02721                                                INT32 SkewY,
02722                                                const DocCoord &Centre,
02723                                                INT32 SinTheta,
02724                                                INT32 CosTheta )
02725 
02726     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02727     Created:    28/11/99
02728     Inputs:     Position    - The x and y translation values in the original matrix.
02729                 ScaleX      - The scale value for the x axis.
02730                 ScaleY      - The scale value for the y axis.
02731                 SkewY       - First skew value.
02732                 SkewX       - Second skew value.
02733                 ( The above correspond to the basic Flash matrix values. )
02734                 Centre      - The centre of the rotation.
02735                 SinTheta    - The sine of the rotation.
02736                 CosTheta    - The cosine of the rotation.
02737     Returns:    TRUE if success.
02738     Purpose:    Creates a matrix (using the BuildComplexRotation methord), and
02739                 writes it out the the Flash file being created.
02740 
02741 ********************************************************************************************/
02742 
02743 BOOL FlashExportDC::WriteComplexRotation ( DocCoord Position,
02744                                            INT32 ScaleX,
02745                                            INT32 ScaleY,
02746                                            INT32 SkewX,
02747                                            INT32 SkewY,
02748                                            const DocCoord &Centre,
02749                                            INT32 SinTheta,
02750                                            INT32 CosTheta )
02751 {
02752     // Create the complete rotation matrix.
02753     BuildComplexRotation ( Position, ScaleX, ScaleY, SkewX, SkewY, Centre,
02754                            SinTheta, CosTheta );
02755 
02756     // And write it.
02757     return WriteMatrix ( Position, ScaleX, ScaleY, SkewX, SkewY );
02758 }
02759 
02760 /********************************************************************************************
02761 
02762 >   BOOL FlashExportDC::WriteURLScript ( FlashButtonRecord *pButton )
02763 
02764     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02765     Created:    8/12/99
02766     Inputs:     pButton - A record of the button that invokes the URL.
02767     Returns:    TRUE if success.
02768     Purpose:    Creates a Flash button from the details stored in the FlashButtonRecord.
02769                 This allows the file to call other URLs by clicking on any shape designated
02770                 as a button.
02771 
02772 ********************************************************************************************/
02773 
02774 BOOL FlashExportDC::WriteURLScript ( FlashButtonRecord *pButton )
02775 {
02776     // Step 1:  Initialise local variables.
02777     FilePos     StartPos    = 0;
02778     WORD        ButtonID    = FLASH_FIRST_ID + FlashPlaceObject::GetBitmapCount () +
02779                               FlashPlaceObject::GetFontCount () +
02780                               FlashPlaceObject::GetTextCount () +
02781                               FlashPlaceObject::GetShapeCount () +
02782                               FlashPlaceObject::GetSpriteCount () +
02783                               pButton->GetButtonID ();
02784 
02785     // Step 2:  Write the header and declaration for the record.
02786     StartPos = WriteHeader ( FLASH_BUTTON_TAG, FLASH_MAX_SHORT, ButtonID );
02787 
02788     // Step 3:  Write out the button records.
02789     WriteButtonRecord ( pButton->GetHitID (),   // Create a record for the hit state.
02790                         FLASH_BUTTON_HIT,
02791                         pButton->GetHitPosition (),
02792                         pButton->GetTransformHit () );
02793 
02794     WriteButtonRecord ( pButton->GetDownID (),  // Create a record for the down state.
02795                         FLASH_BUTTON_DOWN,
02796                         pButton->GetDownPosition (),
02797                         pButton->GetTransformDown () );
02798 
02799     WriteButtonRecord ( pButton->GetOverID (),  // Create a record for the over state.
02800                         FLASH_BUTTON_OVER,
02801                         pButton->GetOverPosition (),
02802                         pButton->GetTransformOver () );
02803 
02804     WriteButtonRecord ( pButton->GetUpID (),    // Create a record for the up state.
02805                         FLASH_BUTTON_UP,
02806                         pButton->GetUpPosition (),
02807                         pButton->GetTransformUp () );
02808 
02809     WriteByte ( 0 );                            // End of button record.
02810 
02811     // Step 4:  Write out the action records.
02812     WriteGetURL ( pButton );                    // Create a record of the actions invoked.
02813     WriteByte ( 0 );                            // End of action record.
02814 
02815     // Step 5:  Rewind to the start of the record, and fill in the details of its size.
02816     WriteTagSize ( StartPos );
02817 
02818     return TRUE;
02819 }
02820 
02821 /********************************************************************************************
02822 
02823 >   BOOL FlashExportDC::WriteButtonRecord ( WORD ObjectID,
02824                                             BYTE State,
02825                                             DocCoord Position,
02826                                             BOOL DoTransform )
02827 
02828     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02829     Created:    8/12/99
02830     Inputs:     ObjectID    - The ID of the object to be used for this state.
02831                 State       - The state to be used.
02832     Returns:    TRUE if success.
02833     Purpose:    Links a Flash shape record with the button, and sets this to be one of the
02834                 states in use.
02835 
02836 ********************************************************************************************/
02837 
02838 BOOL FlashExportDC::WriteButtonRecord ( WORD ObjectID,
02839                                         BYTE State,
02840                                         DocCoord Position,
02841                                         BOOL DoTransform )
02842 {
02843     WriteBits ( 0, 4 );                         // Reserved flags.
02844     WriteBits ( State, 4 );                     // State flags.
02845     WriteWord ( ObjectID );                     // ID of button character.
02846     WriteWord ( 1 );                            // Layer ID.
02847 
02848     if ( DoTransform )                          // Transform co-ordinates to Flash space.
02849         Transform ( &Position, &mLowCorner );   // ( Only if necessary! )
02850 
02851     WriteMatrix ( Position );                   // Position matrix.
02852 
02853     return TRUE;
02854 }
02855 
02856 /********************************************************************************************
02857 
02858 >   BOOL FlashExportDC::WriteGetURL ( FlashButtonRecord *pButton )
02859 
02860     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02861     Created:    8/12/99
02862     Inputs:     pButton - A pointer to a record containing the URL of the web page.
02863     Returns:    TRUE if success.
02864     Purpose:    Creates an action script within the Flash file that fetches the URL (pointed
02865                 to by pButton), and displays it in the browser window.
02866 
02867 ********************************************************************************************/
02868 
02869 BOOL FlashExportDC::WriteGetURL ( FlashButtonRecord *pButton )
02870 {
02871     // Initialise local variables.
02872     FilePos StartPos    = 0;                    // The start of the string record.
02873     FilePos EndPos      = 0;                    // The end of the string record.
02874     WORD    URLLength   = 0;                    // The length of the stored strings.
02875     TCHAR   *pURL       = pButton->GetURL ();   // Get the URL to go to.
02876     TCHAR   *pFrame     = pButton->GetFrame (); // Get the frame to open the URL in.
02877 
02878     // Step 2:  Record as a get URL action.
02879     WriteByte ( FLASH_GET_URL );                // Is a get URL record.
02880 
02881     // Step 3:  Set up the size field.
02882     WriteWord ( 0 );                            // Place-holder value.
02883     StartPos = ExportFile->tell();              // Get the start position of the file.
02884 
02885     // Step 4:  Record the strings to the file.
02886 
02887     // Write ( ( BYTE* ) pURL, strlen ( pURL ) );   // Write a string of the URL.
02888     TCHAR * pC=pURL;
02889     while (*pC)
02890     {
02891         WriteByte(*(pC++)); // 1:1 TCHAR to CHAR conversion
02892     }
02893     WriteByte ( 0 );                            // Terminate the string.
02894     // Write ( ( BYTE* ) pFrame, strlen ( pFrame ) );   // Write the frame to insert the URL into.
02895     pC=pFrame;
02896     while (*pC)
02897     {
02898         WriteByte(*(pC++)); // 1:1 TCHAR to CHAR conversion
02899     }
02900 
02901     // Step 5:  Fill in the record length.
02902     EndPos = ExportFile->tell ();               // Get the file position.
02903     ExportFile->seekIn ( ( StartPos - 2 ) );    // Go back to the start of the record.
02904     URLLength = ( WORD ) ( EndPos - StartPos ); // Calculate the size of the record...
02905     WriteWord ( URLLength );                    // ... and write it in.
02906     ExportFile->seekIn ( EndPos );              // Run to the end of the file.
02907 
02908     return TRUE;
02909 }
02910 
02911 /********************************************************************************************
02912 
02913 >   BOOL FlashExportDC::ProcessSprite ( FlashSprite *pSprite,
02914                                         FlashButtonRecord *pButton )
02915 
02916     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02917     Created:    18/1/00
02918     Inputs:     pSprite - A record of the sprite to be rendered.
02919                 pButton - A pointer to the head of the button record list.
02920     Returns:    TRUE if success.
02921     Purpose:    Parses through the list of sprites, and replaces any records containing a
02922                 single shape with a direct reference to the shape in the relevant button
02923                 record. If the sprite record contains multiple shapes, then it is written
02924                 out to disk directly.
02925 
02926 ********************************************************************************************/
02927 
02928 BOOL FlashExportDC::ProcessSprite ( FlashSprite *pSprite,
02929                                     FlashButtonRecord *pButton )
02930 {
02931     // Step 1:  Declare local variables.
02932     INT32                   Count           = 0;
02933     FlashPlaceObject    *pFirstPlace    = pSprite->GetPlace ();
02934     FlashPlaceObject    *pPlace         = pFirstPlace;
02935 
02936     // Step 2:  Return FALSE if no button records have been passed in. This stops the
02937     //          processing, and thus catches any errors.
02938     if ( pButton == NULL )
02939         return FALSE;
02940 
02941     // Step 2:  Loop through the list, and count the number of FlashPlaceObject records
02942     //          within the sprite record.
02943     while ( pPlace != NULL )
02944     {
02945         Count ++;
02946         pPlace = pPlace->GetNext ();
02947     }
02948 
02949     // Step 3a: If there is only one object within the sprite, spool through the button list,
02950     //          and replace all references to sprites with those to objects.
02951     if ( Count == 1 )
02952     {
02953         WORD        SpriteID    = pSprite->GetID ();
02954         WORD        ShapeID     = pFirstPlace->GetRawID ();
02955         FlashType   Type        = pFirstPlace->GetType ();
02956         DocCoord    Position    = pFirstPlace->GetPosition ();
02957         BOOL        DoTransform = pFirstPlace->GetDoTransform ();
02958 
02959         // Spool through the list of buttons, and match the sprite against all states.
02960         while ( pButton != NULL )
02961         {
02962             // Check the hit state, and replace if necessary.
02963             if ( pButton->GetHitType () == FLASH_SPRITE )
02964             {
02965                 WORD ID = pButton->GetRawHitID ();
02966 
02967                 if ( ID == SpriteID )
02968                 {
02969                     // Change the state's contents.
02970                     pButton->SetHitID ( ShapeID, Type );
02971                     pButton->SetHitPosition ( Position, DoTransform );
02972                 }
02973                 else if ( ID > SpriteID )
02974                 {
02975                     // Reduce the ID value for future sprites, so that there are no gaps in
02976                     // the ID numbers.
02977                     pButton->SetHitID ( ID - 1, FLASH_SPRITE );
02978                 }
02979             }
02980 
02981             // Check the down state, and replace if necessary.
02982             if ( pButton->GetDownType () == FLASH_SPRITE )
02983             {
02984                 WORD ID = pButton->GetRawDownID ();
02985 
02986                 if ( ID == SpriteID )
02987                 {
02988                     // Change the state's contents.
02989                     pButton->SetDownID ( ShapeID, Type );
02990                     pButton->SetDownPosition ( Position, DoTransform );
02991                 }
02992                 else if ( ID > SpriteID )
02993                 {
02994                     // Reduce the ID value for future sprites, so that there are no gaps in
02995                     // the ID numbers.
02996                     pButton->SetDownID ( ID - 1, FLASH_SPRITE );
02997                 }
02998             }
02999 
03000             // Check the over state, and replace if necessary.
03001             if ( pButton->GetOverType () == FLASH_SPRITE )
03002             {
03003                 WORD ID = pButton->GetRawOverID ();
03004 
03005                 if ( ID == SpriteID )
03006                 {
03007                     // Change the state's contents.
03008                     pButton->SetOverID ( ShapeID, Type );
03009                     pButton->SetOverPosition ( Position, DoTransform );
03010                 }
03011                 else if ( ID > SpriteID )
03012                 {
03013                     // Reduce the ID value for successive sprites, so that there are no gaps
03014                     // in the ID numbers.
03015                     pButton->SetOverID ( ID - 1, FLASH_SPRITE );
03016                 }
03017             }
03018 
03019             // Check the up state, and replace if necessary.
03020             if ( pButton->GetUpType () == FLASH_SPRITE )
03021             {
03022                 WORD ID = pButton->GetRawUpID ();
03023 
03024                 if ( ID == SpriteID )
03025                 {
03026                     // Change the state's contents.
03027                     pButton->SetUpID ( ShapeID, Type );
03028                     pButton->SetUpPosition ( Position, DoTransform );
03029                 }
03030                 else if ( ID > SpriteID )
03031                 {
03032                     // Reduce the ID value for future sprites, so that there are no gaps in
03033                     // the ID numbers.
03034                     pButton->SetUpID ( ID - 1, FLASH_SPRITE );
03035                 }
03036             }
03037 
03038             // Move onto the next button record.
03039             pButton = pButton->GetNext ();
03040         }
03041 
03042         // Decrease the sprite count to indicate that an element has been removed.
03043         FlashPlaceObject::DecSpriteCount ();
03044 
03045         // And parse through the sprite list from this point onwards, decreasing the ID
03046         // numbers of successive sprites.
03047         while ( pSprite = pSprite->GetNext (), pSprite != NULL )
03048         {
03049             pSprite->SetID ( pSprite->GetID () - 1 );
03050         }
03051     }
03052 
03053     // Step 3b: Otherwise export the sprite using the WriteSprite method.
03054     else
03055     {
03056         WriteSprite ( pSprite );
03057     }
03058 
03059     return TRUE;
03060 }
03061 
03062 /********************************************************************************************
03063 
03064 >   BOOL FlashExportDC::WriteSprite ( FlashSprite *pSprite )
03065 
03066     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
03067     Created:    22/12/99
03068     Inputs:     pSprite - A record of the sprite to be rendered.
03069     Returns:    TRUE if success.
03070     Purpose:    Writes out a sprite record to the file, which allows several shapes to be
03071                 combined into a single button.
03072 
03073 ********************************************************************************************/
03074 
03075 BOOL FlashExportDC::WriteSprite ( FlashSprite *pSprite )
03076 {
03077     // Step 1:  Define local variables.
03078     WORD                ID          = FLASH_FIRST_ID + FlashPlaceObject::GetBitmapCount () +
03079                                       FlashPlaceObject::GetFontCount () +
03080                                       FlashPlaceObject::GetTextCount () +
03081                                       FlashPlaceObject::GetShapeCount () +
03082                                       pSprite->GetID ();
03083     FilePos             StartPos    = 0;
03084     FlashPlaceObject    *pPlace     = pSprite->GetPlace ();
03085     WORD                Depth       = FLASH_FIRST_ID;
03086 
03087     // Step 2:  Write out the sprite header.
03088     StartPos = WriteHeader ( FLASH_SPRITE_TAG,  // The header record itself.
03089                              FLASH_MAX_SHORT,
03090                              ID );
03091     WriteWord ( 1 );                            // Frame count for sprite movie.
03092 
03093     // Step 3:  Write out the place object records.
03094     while ( pPlace != NULL )
03095     {
03096         WritePlaceObject ( pPlace, Depth );
03097         pPlace = pPlace->GetNext ();
03098         Depth ++;
03099     }
03100 
03101     // Step 4:  Remember to show the frame!
03102     WriteHeader ( FLASH_SHOW_FRAME_TAG, 0 );
03103 
03104     // Step 5:  Write out the end of record data.
03105     WriteHeader ( FLASH_END_FILE_TAG, 0 );
03106 
03107     WriteTagSize ( StartPos );
03108 
03109     return TRUE;
03110 }

Generated on Sat Nov 10 03:47:06 2007 for Camelot by  doxygen 1.4.4