swfrndr.cpp

Go to the documentation of this file.
00001 // $Id: swfrndr.cpp 1611 2006-07-30 11:22:17Z alex $
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 "camtypes.h"
00099 #include "vectrndr.h"
00100 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00101 #include "nodetext.h"
00102 #include "nodetxtl.h"
00103 //#include "ccmaths.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00104 //#include "pathshap.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00105 #include "webaddr.h"
00106 #include "webattr.h"
00107 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 #include "swfrndr.h"
00109 #include "swfexpdc.h"
00110 #include "slicehelper.h"    // For FindNextOfClass. ()
00111 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 //#include "range.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "rendsel.h"
00114 #include "gclips.h"
00115 
00116 // Needed to get stroking working.
00117 #include "brshattr.h"
00118 #include "strkattr.h"
00119 #include "ppstroke.h"
00120 #include "brshbeca.h"
00121 #include "nodebev.h"
00122 
00123 // needed for oversized object warning message (in ExportAll)
00124 //#include "filtrres.h"
00125 
00126 CC_IMPLEMENT_DYNAMIC( FlashRenderRegion, VectorFileRenderRegion )
00127 
00128 #define new CAM_DEBUG_NEW
00129 
00130 /********************************************************************************************
00131 
00132 >   FlashRenderRegion::FlashRenderRegion ( void )
00133 
00134     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00135     Created:    24/8/99
00136     Purpose:    Constructor for the FlashRenderRegion class.
00137     SeeAlso:    FlashFilter::Init
00138 
00139 ********************************************************************************************/
00140 
00141 // Use the default RenderRegion behaviour for now.
00142 FlashRenderRegion::FlashRenderRegion ( void ) :
00143 VectorFileRenderRegion ()
00144 {
00145     // Ensure that member variable pointers are set to NULL.
00146     InitPointers ();
00147 }
00148 
00149 /********************************************************************************************
00150 
00151 >   FlashRenderRegion::FlashRenderRegion ( DocRect ClipRect,
00152                                            Matrix ConvertMatrix,
00153                                            FIXED16 ViewScale )
00154 
00155     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00156     Created:    24/8/99
00157     Purpose:    Constructor for the FlashRenderRegion class.
00158     SeeAlso:    FlashFilter::Init
00159 
00160 ********************************************************************************************/
00161 
00162 FlashRenderRegion::FlashRenderRegion ( DocRect ClipRect,
00163                                        Matrix ConvertMatrix,
00164                                        FIXED16 ViewScale ) :
00165 VectorFileRenderRegion ( ClipRect, ConvertMatrix, ViewScale )
00166 {
00167     // Ensure that member variable pointers are set to NULL.
00168     InitPointers ();
00169 }
00170 
00171 /********************************************************************************************
00172 
00173 >   FlashRenderRegion::~FlashRenderRegion ( void )
00174 
00175     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00176     Created:    24/8/99
00177     Purpose:    Destructor for the FlashRenderRegion class.
00178     SeeAlso:    -
00179 
00180 ********************************************************************************************/
00181 
00182 FlashRenderRegion::~FlashRenderRegion ( void )
00183 {
00184     // Insert clean up code here!
00185     if(mpFont)
00186     {
00187         delete mpFont;
00188         mpFont = NULL;
00189     }
00190 
00191     InitPointers ();
00192 }
00193 
00194 /********************************************************************************************
00195 
00196 >   void FlashRenderRegion::DrawPathToOutputDevice ( Path *PathToRender,
00197                                                      PathShape shapePath = PATHSHAPE_PATH )
00198 
00199     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00200     Created:    7/9/99
00201     Purpose:    Outputs a path to the device context.
00202     Returns:    Void
00203     SeeAlso:    RenderRegion::InitDevice
00204 
00205 ********************************************************************************************/
00206 
00207 void FlashRenderRegion::DrawPathToOutputDevice ( Path *PathToRender,
00208                                                  PathShape shapePath )
00209 {
00210     // Step 1:  Define, and set up all the local variables.
00211     FlashButtonRecord       *pButton        = NULL;
00212     DocRect                 Bounds;
00213     DocCoord                LowCorner;
00214     WebAddressAttribute     *pWebAddress    = ( WebAddressAttribute * ) GetCurrentAttribute
00215                                               ( ATTR_WEBADDRESS );
00216 
00217     // Step 2:  Initialise the path, and use the clipping routines to re-order the path to
00218     //          wind in the correct manner for the Flash editing tools to understand. Though
00219     //          the player operates with an even-odd winding rule, the editing tools don't,
00220     //          so this operations is necessary.
00221 
00222     // We only clip if the path is closed, otherwise rendering artefacts occur.
00223     if ( PathToRender->IsClosed () )
00224     {
00225         // Declare a path for storing the clipped path in.
00226         Path ClippedPath;
00227 
00228         // Initialise the path before using it.
00229         ClippedPath.Initialise ( PathToRender->GetNumCoords () );
00230 
00231         // Set up the path to point in the right direction using ClipPathToPath.
00232         ClippedPath.ClipPathToPath ( *PathToRender, &ClippedPath, 3, 20 );
00233 
00234         // Store the path.
00235         ProcessPath ( &ClippedPath );
00236     }
00237 
00238     else
00239     {
00240         // Store the path.
00241         ProcessPath ( PathToRender );
00242     }
00243 
00244     // Step 3:  If the shape has a web address, create a FlashButtonRecord, and add the
00245     //          shape's ID number to this instead. Because exporting button states can
00246     //          alter the list of FlashPlaceObjects, it is necessary to create any buttons
00247     //          here.
00248     pButton = ProcessURL ( pWebAddress );
00249 
00250     // Step 4:  Add a FlashPlaceObject record.
00251 
00252     // Set up the position for the place object record...
00253     Bounds = mpShapeTail->GetBoundingBox ();
00254     LowCorner.x = Bounds.lo.x;
00255     LowCorner.y = Bounds.hi.y;
00256 
00257     // ... and create it.
00258     PlaceObject ( FlashPlaceObject::GetShapeCount (), FLASH_SHAPE, &LowCorner, TRUE );
00259 
00260     // Step 5:  Export any button states that have been created.
00261     ExportButtonState ( pButton );
00262 }
00263 
00264 /********************************************************************************************
00265 
00266 >   BOOL FlashRenderRegion::ProcessPath ( Path *pPath )
00267 
00268     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00269     Created:    2/11/00
00270     Input:      pPath   - A pointer to the path to be stored.
00271     Returns:    TRUE if success.
00272     Purpose:    Writes all the path attributes to a Flash shape record object, in preparation
00273                 for storing it in the file.
00274     SeeAlso:    FlashRenderRegion::DrawPathToOutputDevice
00275 
00276 ********************************************************************************************/
00277 
00278 BOOL FlashRenderRegion::ProcessPath ( Path *pPath )
00279 {
00280     // Step 1:  Define, and set up all the local variables.
00281     LineWidthAttribute      *pLineWidth     = NULL;
00282     FillGeometryAttribute   *pFill          = NULL;
00283     StrokeTranspAttribute   *pStrokeTransp  = NULL;
00284     StrokeColourAttribute   *pStrokeColour  = NULL;
00285     TranspFillAttribute     *pTransp        = NULL;
00286     DocColour               *pColour        = NULL;
00287 //  FlashExportDC           *FlashDC        = ( FlashExportDC * ) CCDC::ConvertFromNativeDC(RenderDC);
00288 
00289     // Step 2:  If this is the first path to be processed, mpShape will be NULL. Therefore
00290     //          create a new element. Otherwise add one to the end of the existing list.
00291     if ( mpShape == NULL )
00292     {
00293         // Create the head of the list.
00294         mpShape = new FlashShapeRecord;
00295         ASSERT ( mpShape != NULL );
00296         mpShapeTail = mpShape;
00297     }
00298     else
00299     {
00300         // Add an item onto the tail of the list.
00301         mpShapeLast = mpShapeTail;
00302         mpShapeTail = mpShapeTail->AddNext ();
00303         ERROR2IF ( mpShapeTail == NULL, FALSE, "Unable to create path record." );
00304     }
00305 
00306     // Step 3:  Populate the shape record with the relevant values from the path.
00307     mpShapeTail->SetBoundingBox ( pPath->GetBoundingRect () );
00308     mpShapeTail->SetPath ( pPath->GetCoordArray (), pPath->GetVerbArray(),
00309                            pPath->GetNumCoords () );
00310 
00311     // Tell Camelot to split all curves before rendering. This makes the resulting
00312     // image closer to the original Camelot drawing.
00313     mpShapeTail->SetIsCircular ( TRUE );
00314 
00315     // Step 4:  Get line width and colour.
00316 
00317     // Extract the line width.
00318     pLineWidth = (LineWidthAttribute *) GetCurrentAttribute ( ATTR_LINEWIDTH );
00319 
00320     // Get the stroke colour attribute...
00321     pStrokeColour = (StrokeColourAttribute *) GetCurrentAttribute ( ATTR_STROKECOLOUR );
00322     pColour = pStrokeColour->GetStartColour ();
00323 
00324     // Get the stroke transparency attribute...
00325     pStrokeTransp = (StrokeTranspAttribute *) GetCurrentAttribute ( ATTR_STROKETRANSP );
00326 
00327     // Now set the colour. If the line is transparent, or we are ignoring stroking
00328     // information, then export a zero width, transparent line.
00329     if ( pColour->IsTransparent () || mSupressLines )
00330     {
00331         UINT32 Transp = 255;
00332 
00333         // If the stroke is transparent, don't set any colours!
00334         mpShapeTail->SetLineColour ( pStrokeColour->GetStartColour(),
00335                                      &Transp );
00336 
00337         mpShapeTail->SetLineWidth ( 0 );
00338     }
00339     else
00340     {
00341         // Otherwise treat as a normal stroke.
00342         mpShapeTail->SetLineColour ( pStrokeColour->GetStartColour(),
00343                                      pStrokeTransp->GetStartTransp () );
00344 
00345         mpShapeTail->SetLineWidth ( pLineWidth->LineWidth );
00346     }
00347 
00348     // Step 5:  Set the fill attributes.
00349 
00350     // Are we exporting a stroke path?
00351     if ( mExportStroke )
00352     {
00353         // The fill is to be a flat fill, based on the stroke colour.
00354         ProcessFlatTransp ( *( pStrokeTransp->GetStartTransp () ) );
00355         ProcessFlatFill ( pStrokeColour->GetStartColour () );
00356     }
00357 
00358     // If the line is closed, set the fill.
00359     else if ( pPath->IsFilled )
00360     {
00361         // Set the fill to the current fill attribute.
00362         pFill   = ( FillGeometryAttribute * ) GetCurrentAttribute ( ATTR_FILLGEOMETRY );
00363         pTransp = ( TranspFillAttribute* ) GetCurrentAttribute ( ATTR_TRANSPFILLGEOMETRY );
00364 
00365         // Currently the transparency attribute is processed before the fill attribute, since
00366         // this appears to give better results than fill then transparency. Since I'm trying
00367         // to avoid adding any UI to the Flash filter, I've hardcoded this order in. However,
00368         // in a previous version, I had a ProcessFill () function which performed a switch,
00369         // which would have enabled the user to choose their preferences were a UI to be
00370         // implemented. This function can be found in a previous check in to Sourcesafe, and
00371         // the file details are:
00372         //
00373         // File:    swfrndr.cpp     swfrndr.h
00374         // User:    Graeme          Graeme
00375         // Date:    22/12/99        22/12/99
00376         // Version: 27              18
00377         ProcessTransparency ( pTransp, pFill );         // First process the transparency.
00378         ProcessColour ( pFill );                        // Then the colour.
00379     }
00380     
00381     // Otherwise it's an unfilled path.
00382     else
00383     {
00384         mpShapeTail->SetFill ( FLASH_NO_FILL );
00385     }
00386 
00387     // Step 6:  Set the shape's ID value.
00388     mpShapeTail->SetShapeID ( FlashPlaceObject::GetShapeCount () );
00389 
00390     // It worked!
00391     return TRUE;
00392 }
00393 
00394 /********************************************************************************************
00395 
00396 >   BOOL FlashRenderRegion::ExportCharacter ( TextChar *pTheLetter )
00397 
00398     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00399     Created:    13/10/99
00400     Input:      TheLetter - A Unicode character, which is to be stored
00401     Returns:    TRUE if success.
00402     Purpose:    Adds the character into the two lists that maintain the strings to be
00403                 exported to a Flash file.
00404     SeeAlso:    -
00405 
00406 ********************************************************************************************/
00407 
00408 BOOL FlashRenderRegion::ExportCharacter ( TextChar *pTheLetter )
00409 {
00410     // Assume pointers (member variables) to:
00411     // - mpFont:    A list of font styles being used by the program.
00412     // - mpText:    A list of the text strings being used.
00413     // - mpPlace:   A list of the place object tags.
00414 
00415     // Define local variables.
00416     TextLine                *pTextLine  = pTheLetter->FindParentLine ();
00417     Node                    *pTextStory = pTextLine->FindParent ();
00418     Node                    *pNode      = pTextStory->FindFirstChild ();
00419     FlashFontRecord         *pFont      = NULL;
00420     DWORD                   FlashFontID = 0;
00421     INT32                       CharCode    = 0;
00422     FillGeometryAttribute   *pFill      = static_cast <FillGeometryAttribute*>
00423                                           ( GetCurrentAttribute ( ATTR_FILLGEOMETRY ) );
00424     TranspFillAttribute     *pTransp    = static_cast <TranspFillAttribute*>
00425                                          ( GetCurrentAttribute ( ATTR_TRANSPFILLGEOMETRY ) );
00426     StrokeColourAttribute   *pStroke    = static_cast <StrokeColourAttribute*>
00427                                           ( GetCurrentAttribute ( ATTR_STROKECOLOUR ) );
00428 
00429     // If the text has a gradient or bitmap fill, or any transparency other than flat,
00430     // export it as a path.
00431     if ( !pFill->IsAFlatFill () ||
00432          !pTransp->IsAFlatFill () ||
00433          !pStroke->GetStartColour ()->IsTransparent () )
00434     {
00435         // The fill is too complex to be exported as a straight Flash text character, so
00436         // export it as a path.
00437         return FALSE;
00438     }
00439 
00440     // Cycle through the list of children for the text node. If a NodePath is found, then
00441     // return FALSE. This will cause the letter to be exported as a shape rather than a
00442     // character, and so keep the alignment correct. This is here to export text on a curve,
00443     // which would otherwise not be correctly rendered.
00444     while ( pNode != NULL )
00445     {
00446         if ( pNode->IsNodePath () || pNode->IsARegularShape () )
00447         {
00448             // The text story contains a path, therefore it has to be exported as a set
00449             // of curves.
00450             return FALSE;
00451         }
00452         else
00453         {
00454             // Find the next node.
00455             pNode = pNode->FindNextNonHidden ();
00456         }
00457     }
00458 
00459     // Grab a pointer to the previous VTN in the TextStory. This is used for determining
00460     // whether or not to create a new FlashTextRecord for the successive characters.
00461     VisibleTextNode *pLastVTN   = pTheLetter->FindPrevVTNInLine ();
00462 
00463     // Get the character to be exported from the TextChar record.
00464     WCHAR Glyph = pTheLetter->GetUnicodeValue ();
00465 
00466     // VisibleTextNodes are either renderable characters, carets, or end of line nodes.
00467     // I'm not interested in carets, so I'll skip these.
00468     if ( ( pLastVTN != NULL ) && ( pLastVTN->IsACaret () ) )
00469     {
00470         pLastVTN = pLastVTN->FindPrevVTNInLine ();
00471     }
00472 
00473     // Step 1:  Get the details of the font.
00474 
00475     // First the font's handle.
00476     WORD FontName = ( ( TxtFontTypefaceAttribute* ) GetCurrentAttribute
00477                         ( ATTR_TXTFONTTYPEFACE ) )->HTypeface ;
00478 
00479     // Secondly, whether or not it's bold.
00480     BOOL IsBold = ( ( TxtBoldAttribute* ) GetCurrentAttribute
00481                     ( ATTR_TXTBOLD ) )->BoldOn;
00482 
00483     // Thirdly, whether or not it's italic.
00484     BOOL IsItalic = ( ( TxtItalicAttribute* ) GetCurrentAttribute
00485                       ( ATTR_TXTITALIC ) )->ItalicOn;
00486 
00487     // And finally, it's offset and relative size values.
00488 //  TxtScriptAttribute *pScript = ( TxtScriptAttribute* ) GetCurrentAttribute  ( ATTR_TXTSCRIPT );
00489 
00490 
00491     // Flash doesn't seem to support fonts with obscure aspect ratios, so maybe set
00492     // that into the text matrix, along with rotates.
00493 
00494     // Step 2:  Determine whether a new FlashTextRecord is needed. A new one is
00495     //          required if either there isn't an existing FlashTextRecord to add the
00496     //          characters to, or there's been a new line. Since the first character
00497     //          to be stored will, by definition, be at the start of a new line, and
00498     //          hence this is the only check that I need to make.
00499     if ( pLastVTN == NULL )
00500     {
00501         // Step 2a: Create the new FlashTextRecord to contain the string. If none
00502         //          exist at present, create it at mpText. Otherwise use add element.
00503         CreateTextRecord ( pTheLetter );
00504     }
00505 
00506     // Step 2b: For each font, cycle through the list mpFontStyles, and
00507     //          compare existing resources with the current font style. If a pre
00508     //          -existing style matches, reuse this one, otherwise create a new
00509     //          record.
00510     pFont = mpFont;
00511 
00512     // Spool through the list.
00513     while ( pFont != NULL )
00514     {
00515         // Compare font names and styles.
00516         if ( ( pFont->GetTypeface () == FontName ) &&
00517              ( pFont->GetIsBold () == IsBold ) &&
00518              ( pFont->GetIsItalic () == IsItalic ) )
00519         {
00520             // Break out of the while loop.
00521             break;
00522         }
00523         else
00524         {
00525             pFont = pFont->GetNext ();      // Move on to the next item in the list.
00526             FlashFontID ++;                 // Increment ID number.
00527         }
00528     }
00529 
00530     // If pFont is NULL, no matching font styles have been stored, so create a
00531     // new record.
00532     if ( pFont == NULL )
00533     {
00534         // If there are no existing font records, create one.
00535         if ( mpFont == NULL )
00536         {
00537             mpFont = new FlashFontRecord;
00538             ASSERT ( mpFont != NULL );
00539             pFont = mpFontTail = mpFont;
00540         }
00541         else
00542         {
00543             mpFontTail = mpFontTail->AddElement ();
00544             ASSERT ( mpFontTail != NULL );
00545             pFont = mpFontTail;
00546         }
00547 
00548         // Record the necessary font metrics. There's no need to store FlashFontID
00549         // since that is implicit in the order of the elements in the list. (i.e.
00550         // the first item is #0, and the second is #1, etc.)
00551         pFont->SetTypeface ( FontName );
00552         pFont->SetIsBold ( IsBold );
00553         pFont->SetIsItalic ( IsItalic );
00554 
00555         // Set the ID number for the font.
00556         pFont->SetFontID ( FlashPlaceObject::GetFontCount () );
00557         FlashPlaceObject::IncFontCount ();
00558     }
00559 
00560     // And add the path.
00561     if ( pFont->AddGlyph ( Glyph, CharCode ) )
00562     {
00563         Matrix FontMatrix;
00564 
00565         TxtFontSizeAttribute FlashFontSize ( FLASH_FONT_SIZE );
00566         TxtFontSizeAttribute *pLastSize = ( TxtFontSizeAttribute* ) GetCurrentAttribute
00567                                           ( ATTR_TXTFONTSIZE );
00568 
00569         TxtAspectRatioAttribute FlashAspect ( 1 );
00570         TxtAspectRatioAttribute *pLastAspect = ( TxtAspectRatioAttribute* )
00571                                                GetCurrentAttribute ( ATTR_TXTASPECTRATIO );
00572 
00573         // Set the font size and aspect to the correct values to render the path.
00574         SetTxtFontSize ( &FlashFontSize, FALSE );
00575         SetTxtAspectRatio ( &FlashAspect, FALSE );
00576 
00577         // Add it to the record.
00578         pFont->AddPath ( CreateCharPath ( Glyph, &FontMatrix ), CharCode );
00579 
00580         // Restore the current render region settings.
00581         RestoreTxtFontSize ( pLastSize, FALSE );
00582         RestoreTxtAspectRatio ( pLastAspect, FALSE );
00583     }
00584 
00585     // Step 3:  Add the character to the end of the string, and the font style to the list
00586     //          of characters used in that particular font.
00587     INT32 Index = mpTextTail->AddChar ( pTheLetter, CharCode );
00588 
00589     // Fill in the font's characteristics:
00590     
00591     // Font size.
00592 //  INT32       Offset  = ( pScript->Offset ).GetRawLong ();
00593 //  INT32       Ratio   = ( pScript->Size ).GetRawLong ();
00594 
00595     MILLIPOINT  Size    = ( ( TxtFontSizeAttribute* ) GetCurrentAttribute
00596                           ( ATTR_TXTFONTSIZE ) )->FontSize;
00597 
00598     // Set the font size.
00599     mpTextTail->SetSize ( Size, Index );
00600 
00601     // And the ascent.
00602     mpTextTail->SetAscent ( pTheLetter->GetFontAscent () );
00603 
00604     // Calculate the baseline of the font.
00605 //  double      dDiv    = ( double ) Ratio * ( double ) FLASH_FIXED_ONE;
00606 //  double      dBase   = ( double ) ( Size - pTheLetter->GetFontDescent () ) / dDiv;
00607 
00608     // And the offset.
00609 //  double      dOffset = Size * ( ( double ) Offset / ( double ) FLASH_FIXED_ONE );
00610 
00611     // Use these to calculate the y offset value for the text.
00612 //  double      dYOff   = dBase - dOffset - ( double ) pTheLetter->GetBaseLineShift ();
00613 
00614     // mpTextTail->SetBaseline ( ( INT32 ) dYOff, Index );
00615     mpTextTail->SetOffset ( 0 , Index );
00616 
00617     // Font colour.
00618     mpTextTail->SetColour ( pFill->GetStartColour (),
00619                             pTransp->GetStartTransp (),
00620                             Index );
00621 
00622     // Typeface. Note: I'm using the FlashFontID numbers because these map the font
00623     // definitions (within the Flash file) onto the file's text definitions.
00624     mpTextTail->SetStyle ( ( WORD ) FlashFontID, Index );
00625 
00626     // Step 4:  Return TRUE. This allows me to use the standard error checking macros, which
00627     //          will return FALSE if they hit a problem.
00628 
00629     return TRUE;
00630 }
00631 
00632 /********************************************************************************************
00633 
00634 >   BOOL FlashRenderRegion::ExportBevel ( NodeBevel *pBevel )
00635 
00636     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00637     Created:    14/12/99
00638     Input:      pBevel - A pointer to a NodeBevel object.
00639     Returns:    TRUE if success.
00640     Purpose:    Creates a shape record for the bevel's path, and a bitmap fill to do the
00641                 bevel. It can currently only accurately reproduce bevels with flat fills,
00642                 since Flash's support of transparent bitmaps is broken at the moment.
00643     SeeAlso:    -
00644 
00645 ********************************************************************************************/
00646 
00647 BOOL FlashRenderRegion::ExportBevel ( NodeBevel *pBevel )
00648 {
00649     // Set up the range control flags.
00650     RangeControl            ControlFlags    ( TRUE, TRUE );
00651     Range                   ToRender        ( pBevel, pBevel, ControlFlags );
00652     OILBitmap               *pBitmap        = NULL;
00653     KernelBitmap            *pKernBitmap    = NULL;
00654     Path                    *pSourcePath    = &( pBevel->InkPath );
00655     Path                    BevelPath;
00656 
00657     // Create and render the bitmap.
00658     pKernBitmap = pBevel->CreateBitmapCopy(-1.0,FALSE);
00659     pBitmap = pKernBitmap->ActualBitmap;
00660 
00661     // Initialise the path, and copy the data into it.
00662     BevelPath.Initialise ( pSourcePath->GetNumCoords () );
00663 
00664     if ( BevelPath.CopyPathDataFrom ( &( pBevel->InkPath ) ) == FALSE )
00665     {
00666         TRACEUSER( "Graeme", _T("Error, and exiting ExportBevel!\n") );
00667         return FALSE;
00668     }
00669 
00670     DrawPathToOutputDevice ( &BevelPath, PATHSHAPE_CIRCLE );
00671 
00672     // Ensure that we're not writing to a NULL pointer.
00673     if ( mpShapeTail != NULL )
00674     {
00675         // Variables for calculating the transparency.
00676         UINT32  Alpha       = 0;
00677         UINT32  Colours     = mpShapeTail->GetNumberColours ();
00678 
00679         // Sum all the alpha values for the path. I'm assuming that the bevel's
00680         // transparency has already been noted.
00681         for ( UINT32 i = 0; i < Colours; i++ )
00682         {
00683             Alpha += mpShapeTail->GetColour ( i ).Alpha;
00684         }
00685 
00686         // Get the average colour for the bevel.
00687         Alpha /= Colours;
00688 
00689         // There are probably more elegant ways of doing this, but they would involve me
00690         // rewriting a lot of code for one special case. Instead, I'm going to overwrite
00691         // the existing fill colour with the bitmap.
00692         WORD    BitmapID    = GetBitmapID ( pBitmap, NULL, NULL, 255 );
00693         DocRect Bounds      = pBevel->GetBoundingRect ();
00694 
00695         // Remove the boundary lines from the bevel paths.
00696         mpShapeTail->RemoveLines ();
00697 
00698         // Some tweaks to the object inside the bevel.
00699         if ( mpShapeLast != NULL )
00700         {
00701             mpShapeLast->RemoveLines ();
00702         }
00703 
00704         // Record the details of the fill.
00705         mpShapeTail->SetStartPoint  ( Bounds.lo );
00706         mpShapeTail->SetEndPoint    ( DocCoord ( Bounds.hi.x, Bounds.lo.y ) );
00707         mpShapeTail->SetEndPoint2   ( DocCoord ( Bounds.lo.x, Bounds.hi.y ) );
00708         mpShapeTail->SetFill        ( FLASH_CLIPPED_BITMAP );
00709 
00710         // Record the size and ID number of the bitmap used.
00711         mpShapeTail->SetBitmapID    ( BitmapID );
00712         mpShapeTail->SetBitmapWidth ( pBitmap->GetWidth () );
00713         mpShapeTail->SetBitmapHeight ( pBitmap->GetHeight () );
00714     }
00715 
00716     // Clean up the bitmap created.
00717     if(pKernBitmap)
00718     {
00719         pKernBitmap->DestroyGreyscaleVersion();
00720         delete pKernBitmap;
00721     }
00722 
00723     return TRUE;
00724 }
00725 
00726 /********************************************************************************************
00727 
00728 >   BOOL FlashRenderRegion::ExportBevelBegin ( NodeBevelBegin *pBevel )
00729 
00730     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00731     Created:    14/12/99
00732     Input:      pBevel - A pointer to a NodeBevelBegin object.
00733     Returns:    TRUE if success.
00734     Purpose:    Stub function to prevent NodeBevelBegin from rendering.
00735     SeeAlso:    -
00736 
00737 ********************************************************************************************/
00738 
00739 BOOL FlashRenderRegion::ExportBevelBegin ( NodeBevelBegin *pBevel )
00740 {
00741     return TRUE;
00742 }
00743 
00744 /********************************************************************************************
00745 
00746 >   BOOL FlashRenderRegion::ExportShadow ( Path *pShadowPath,
00747                                            OILBitmap *pBitmap,
00748                                            UINT32 Darkness )
00749 
00750     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00751     Created:    19/1/00
00752     Input:      pShadowPath - The path used by the shadow object.
00753                 pBitmap - The bitmap containing the shadow's shape.
00754                 pShadowColour - The colour of the shadow.
00755     Returns:    TRUE if success.
00756     Purpose:    Creates a shape record for a shadow, and stores it inside the Flash file.
00757     SeeAlso:    -
00758 
00759 ********************************************************************************************/
00760 
00761 BOOL FlashRenderRegion::ExportShadow ( Path *pShadowPath,
00762                                        OILBitmap *pBitmap,
00763                                        UINT32 Darkness )
00764 {
00765     // Step 1:  Set up the local variables.
00766     DocColour       ShadColour  = *( ( ( FillGeometryAttribute* ) GetCurrentAttribute
00767                                  ( ATTR_FILLGEOMETRY ) )->GetStartColour () );
00768     DocRect         PathBounds  = pShadowPath->GetBoundingRect ();
00769     DocCoord        EndPoint1   ( PathBounds.hi.x, PathBounds.lo.y );
00770     DocCoord        EndPoint2   ( PathBounds.lo.x, PathBounds.hi.y );
00771     WORD            BitmapID    = FlashPlaceObject::GetBitmapCount ();
00772     FlashExportDC   *pFlashDC   = static_cast <FlashExportDC*> ( CCDC::ConvertFromNativeDC(GetRenderDC()) );
00773 
00774     TRACEUSER( "Graeme", _T("Entering ExportShadow!\n") );
00775 
00776     // Step 2:  Export the path.
00777     DrawPathToOutputDevice ( pShadowPath );
00778 
00779     // Step 3:  Create the bitmap record.
00780 
00781     // Shadow bitmaps are temporary, and so I don't need to store it in a bitmap record,
00782     // since these exist to allow for the re-use of existing bitmaps.
00783 /*
00784     // Create a bitmap record, and add it to the tail of the bitmap list.
00785     if ( mpBitmap == NULL )
00786     {
00787         mpBitmap = new FlashBitmapRecord;
00788         ASSERT ( mpBitmap != NULL );
00789         mpBitmapTail = mpBitmap;
00790     }
00791     else
00792     {
00793         mpBitmapTail = mpBitmapTail->AddElement ();
00794         ASSERT ( mpBitmapTail != NULL );
00795     }
00796 
00797     // Set a pointer to the bitmap within the bitmap record. This prevents confusion with
00798     // exporting other bitmaps.
00799     mpBitmapTail->SetBitmap ( pBitmap );
00800 */
00801     // Step 4:  Export the shadow bitmap.
00802     pFlashDC->WriteShadowBitmap ( pBitmap, BitmapID, ShadColour, Darkness );
00803 
00804     // Step 5:  Replace the fill value for mpShapeTail with a bitmap reference.
00805     mpShapeTail->RemoveLines ();                            // Remove lines around shadow.
00806     mpShapeTail->SetFill ( FLASH_CLIPPED_BITMAP );          // Bitmap style.
00807     mpShapeTail->SetBitmapID ( BitmapID );                  // ID value.
00808     mpShapeTail->SetBitmapWidth ( pBitmap->GetWidth () );   // Width of bitmap.
00809     mpShapeTail->SetBitmapHeight ( pBitmap->GetHeight () ); // Height of bitmap.
00810     mpShapeTail->SetStartPoint ( PathBounds.lo );           // Startpoint of fill.
00811     mpShapeTail->SetEndPoint ( EndPoint1 );                 // Endpoint of fill.
00812     mpShapeTail->SetEndPoint2 ( EndPoint2 );                // Endpoint of fill.
00813 
00814     TRACEUSER( "Graeme", _T("Exiting ExportShadow!\n") );
00815 
00816     // Step 6:  Tidy up, and return TRUE.
00817     FlashPlaceObject::IncBitmapCount ();
00818 
00819     return TRUE;
00820 }
00821 
00822 /********************************************************************************************
00823 
00824 >   BOOL FlashRenderRegion::ExportRenderableNode ( NodeRenderableInk *pInk )
00825 
00826     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00827     Created:    9/11/00
00828     Input:      pInk    - The ink node to be exported.
00829     Returns:    TRUE    - The node contained a stroke, and was exported by this method.
00830                 FALSE   - Export using the default export code.
00831     Purpose:    Renders a stroked path to the file.
00832     SeeAlso:    -
00833 
00834 ********************************************************************************************/
00835 
00836 BOOL FlashRenderRegion::ExportRenderableNode ( NodeRenderableInk *pInk )
00837 {
00838     // Graeme (10/11/00) - I don't think that this is a particularly nice way to export a
00839     // stroked path to a Flash file. The EPS render region will export strokes automatically,
00840     // without any of this messing around, and as a result I suspect that the Flash render
00841     // region hasn't been properly initialised.
00842     //
00843     // There is, however, an advantage to doing it this way: By calling RetroSmoothMe on the
00844     // path, the overall file size required to store a given path is halved, which for is a
00845     // big advantage for the Flash file format, in which the file size is crucial.
00846 
00847     // Pointer to the stroke type attribute.
00848     AttrStrokeType  *pStroke    = NULL;
00849 /*
00850     NodeAttribute   *pAttr      = NULL;
00851     AttrBrushType   *pBrush     = NULL;
00852 
00853     // Find out if we have an applied brush node.
00854     pInk->FindAppliedAttribute ( CC_RUNTIME_CLASS ( AttrBrushType ), &pAttr );
00855 
00856     // Cast it into a brush type attribute to avoid multiple casts in the following code.
00857     pBrush = static_cast <AttrBrushType*> ( pAttr );
00858 
00859     if ( pBrush != NULL &&
00860          pBrush->GetBrushHandle () != BrushHandle_NoBrush )
00861     {
00862         SimpleBecomeA BecomeA ( BECOMEA_PASSBACK, CC_RUNTIME_CLASS ( NodePath ), NULL );
00863 
00864         if ( pBrush->DoBecomeA ( &BecomeA, pInk ) )
00865         {
00866             NodePath *pNodePath = BecomeA.GetNodePath ();
00867 
00868             if ( pNodePath != NULL )
00869             {
00870                 // Supress rendering the stroke around the shape.
00871                 mSupressLines = TRUE;
00872 
00873                 DrawPathToOutputDevice ( &( pNodePath->InkPath ) );
00874 
00875                 // Supress rendering the stroke around the shape.
00876                 mSupressLines = FALSE;
00877 
00878                 return TRUE;
00879             }
00880         }
00881     }
00882 */
00883     // Find out whether this node has an applied stroke attribute.
00884     pInk->FindAppliedAttribute ( CC_RUNTIME_CLASS ( AttrStrokeType ),
00885                                  reinterpret_cast <NodeAttribute**> ( &pStroke ) );
00886 
00887     if ( pStroke != NULL && pStroke->HasPathProcessor () )
00888     {
00889         // Use a SimpleBecomeA to get the path from the parent object
00890         SimpleBecomeA BecomeA ( BECOMEA_PASSBACK, CC_RUNTIME_CLASS ( NodePath ), NULL );
00891         
00892         if ( pInk->DoBecomeA ( &BecomeA ) )
00893         {
00894             NodePath *pNodePath = BecomeA.GetNodePath ();
00895 
00896             if ( pNodePath )
00897             {
00898                 NodePath *pStrokePath = pStroke->GetPathProcessor ()->GetProcessedPath
00899                                                         ( &( pNodePath->InkPath ), pInk );
00900 
00901                 // If the path was successfully created, export it.
00902                 if ( pStrokePath != NULL )
00903                 {
00904                     // Smooth the path first, to reduce the file size.
00905                     pStrokePath->RetroSmoothMe ( 15.0 );
00906 
00907                     // Supress rendering the stroke around the shape.
00908                     mSupressLines = TRUE;
00909 
00910                     // Only render the ink path if it is itself closed.
00911                     if ( pNodePath->InkPath.IsClosed () )
00912                     {
00913                         // Render the node to the file.
00914                         DrawPathToOutputDevice ( &( pNodePath->InkPath ) );
00915                     }
00916 
00917                     // Inform the render region to use the line colour as the fill colour.
00918                     mExportStroke = TRUE;
00919 
00920                     // Export the path directly. This avoids calling the path processors
00921                     // that can mess up the line.
00922                     DrawPathToOutputDevice ( &( pStrokePath->InkPath ) );
00923 
00924                     // We are no longer exporting the stroke path, so reset the control flag.
00925                     mExportStroke = FALSE;
00926 
00927                     // Restore stroke rendering.
00928                     mSupressLines = FALSE;
00929 
00930                     // Tell the program not to export the node using the default code.
00931                     return TRUE;
00932                 }
00933             }
00934         }
00935     }
00936 
00937     // The path wasn't rendered using the custom stroking code, so tell Camelot to use the
00938     // default path rendering code.
00939     return FALSE;
00940 }
00941 
00942 /********************************************************************************************
00943 
00944 >   BOOL FlashRenderRegion::ExportAll ( void )
00945 
00946     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
00947     Created:    20/10/99
00948     Input:      -
00949     Returns:    TRUE if success.
00950     Purpose:    Most of the functions within the FlashRenderRegion class are used to create
00951                 and populate a series of linked lists which contain a processed version of
00952                 the Camelot tree. This function passes all of these lists to the Render DC,
00953                 so that they can be outputted to a file, and then cleans up the objects to
00954                 prevent any memory leaks.
00955     SeeAlso:    -
00956 
00957 ********************************************************************************************/
00958 
00959 BOOL FlashRenderRegion::ExportAll ( void )
00960 {
00961     // These functions all depend on the objects used by the linked list having the pointer
00962     // to the next instance being initialised to NULL when they are created. If this isn't
00963     // done, this function will throw an error, since the code will attempt to access
00964     // uncreated objects.
00965     
00966     // (ChrisG 18/1/01) Added an error box to warn if a shape is detected that's too big to 
00967     //  render properly when imported into Flash/Internet Browsers, etc...
00968     BOOL invalidSizeFound = FALSE;
00969 
00970     // Step 1:  Get a device context to the Flash file.
00971     FlashExportDC *pFlashDC = ( FlashExportDC * ) CCDC::ConvertFromNativeDC(RenderRegion::GetRenderDC());
00972 
00973     TRACEUSER( "Graeme", _T("Entering ExportAll!\n") );
00974     FlashBitmapRecord *pLastBitmap = NULL;
00975 
00976     // Step 2:  Delete the bitmap records.
00977     while ( mpBitmap != NULL )
00978     {
00979         // The bitmap records have already been exported, so just delete the list.
00980         pLastBitmap = mpBitmap;
00981         mpBitmap = mpBitmap->GetNext();
00982 
00983         // (ChrisG 4/1/01) - These two calls have been removed, as they cause access violations
00984         //  with temporary bitmaps (e.g. in blends), as the bitmaps have already been deleted.
00985 //      pLastBitmap->GetBitmap()->DestroyContonePalette();
00986 //      pLastBitmap->GetBitmap()->DestroyGreyscaleVersion();
00987         delete pLastBitmap;
00988     }
00989 
00990     FlashFontRecord *pLastFont = NULL;
00991 
00992     // Step 3:  Export and delete the font records.
00993     while ( mpFont != NULL )
00994     {
00995         pLastFont = mpFont;
00996 
00997         // Write out the font definitions to the file.
00998         pFlashDC->WriteDefineFont ( mpFont );
00999 
01000         mpFont = mpFont->GetNext ();
01001         delete pLastFont;
01002     }
01003 
01004     FlashTextRecord *pLastText = NULL;
01005 
01006     // Step 4:  Export and delete the text string records.
01007     while ( mpText != NULL )
01008     {
01009         pLastText = mpText;
01010 
01011         // Write out the text strings to the file.
01012         pFlashDC->WriteText ( mpText );
01013 
01014         mpText = mpText->GetNext ();
01015         delete pLastText;
01016     }
01017 
01018     // Step 5:  Export and delete the shape records.
01019     while ( mpShape != NULL )
01020     {
01021         FlashShapeRecord *pLastShape = mpShape;
01022 
01023         // Write out the shapes.
01024         pFlashDC->WritePath ( mpShape );
01025 
01026         // (ChrisG 18/1/01) Check to see whether the shape's size is valid
01027         if (pLastShape->WasInvalidSizeFound () == TRUE)
01028         {
01029             invalidSizeFound = TRUE;
01030         }
01031 
01032         mpShape = mpShape->GetNext ();
01033         delete pLastShape;
01034     }
01035 
01036     // Step 6:  Export and delete the sprite records.
01037     while ( mpSprite != NULL )
01038     {
01039         FlashSprite *pLastSprite = mpSprite;
01040 
01041         // Write out the sprites.
01042         pFlashDC->ProcessSprite ( mpSprite, mpButton );
01043 
01044         mpSprite = mpSprite->GetNext ();
01045         delete pLastSprite;
01046     }
01047 
01048     // Step 7:  Export and delete the button records.
01049     while ( mpButton != NULL )
01050     {
01051         FlashButtonRecord *pLastButton = mpButton;
01052 
01053         // Write out the buttons.
01054         pFlashDC->WriteURLScript ( mpButton );
01055 
01056         mpButton = mpButton->GetNext ();
01057         delete pLastButton;
01058     }
01059 
01060     // Step 8:  Export and delete the place object classes.
01061     while ( mpPlace != NULL )
01062     {
01063         FlashPlaceObject *pLastPlace = mpPlace;
01064 
01065         // Write out the place object tags.
01066         pFlashDC->WritePlaceObject ( mpPlace );
01067 
01068         mpPlace = mpPlace->GetNext ();
01069         delete pLastPlace;
01070     }
01071 
01072     // Step 9:  Reset all pointer values.
01073     InitPointers ();
01074 
01075     // Warn of any invalid shapes that were detected.
01076     if (invalidSizeFound == TRUE)
01077     {
01078         // Display error message.
01079         String_256 WarnMsg;
01080 
01081         WarnMsg.MakeMsg(_R(IDT_FLASH_INVALID_SIZE_WARNING));
01082         Error::SetError(0, WarnMsg, 0);
01083     }
01084 
01085     return TRUE;
01086 }
01087 
01088 /********************************************************************************************
01089 
01090 >   void FlashRenderRegion::SetButtonName ( TCHAR *pButtonName )
01091 
01092     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01093     Created:    18/1/00
01094     Input:      pButtonName - A pointer to a sting containing this button's name.
01095     Returns:    -
01096     Purpose:    Sets the name of the current button being exported. If the object being
01097                 exported doesn't have this attribute, the string is cleared to prevent
01098                 problems with old button names persisting.
01099     SeeAlso:    FlashRenderRegion::SetLayerState ()
01100 
01101 ********************************************************************************************/
01102 
01103 void FlashRenderRegion::SetButtonName ( TCHAR *pButtonName )
01104 {
01105     if ( pButtonName != NULL )
01106         mButtonName = pButtonName;
01107     else
01108         mButtonName.Empty ();
01109 }
01110 
01111 /********************************************************************************************
01112 
01113 >   void FlashRenderRegion::SetLayerState ( LayerState State )
01114 
01115     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01116     Created:    18/1/00
01117     Input:      State - The button state of the current layer being exported.
01118     Returns:    -
01119     Purpose:    Sets the value to mButtonState to be State. This is used to determine which
01120                 of the roll-over states of a button and which object should be used.
01121     SeeAlso:    FlashRenderRegion::SetButtonName ()
01122 
01123 ********************************************************************************************/
01124 
01125 void FlashRenderRegion::SetLayerState ( LayerState State )
01126 {
01127     mButtonState = State;
01128 }
01129 
01130 /********************************************************************************************
01131 
01132 >   void FlashRenderRegion::InitPointers ( void )
01133 
01134     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01135     Created:    21/10/99
01136     Purpose:    Initialises all pointer values to NULL
01137     SeeAlso:    -
01138 
01139 ********************************************************************************************/
01140 
01141 void FlashRenderRegion::InitPointers ( void )
01142 {
01143     // Set all the member pointers to be NULL to avoid problems later.
01144     mpBitmap        = NULL;
01145     mpBitmapTail    = NULL;
01146     mpFont          = NULL;
01147     mpFontTail      = NULL;
01148     mpText          = NULL;
01149     mpTextTail      = NULL;
01150     mpShape         = NULL;
01151     mpShapeTail     = NULL;
01152     mpShapeLast     = NULL;
01153     mpButton        = NULL;
01154     mpButtonTail    = NULL;
01155     mpSprite        = NULL;
01156     mpSpriteTail    = NULL;
01157     mpPlace         = NULL;
01158     mpPlaceTail     = NULL;
01159 
01160     // Other global variables that need resetting, but aren't pointers.
01161     mButtonState    = NO_BUTTON;
01162     mButtonName.Empty ();
01163     mSupressLines   = FALSE;
01164     mExportStroke   = FALSE;
01165 
01166 }
01167 
01168 /********************************************************************************************
01169 
01170 >   BOOL FlashRenderRegion::CreateTextRecord ( TextChar *pTheLetter )
01171 
01172     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01173     Created:    26/11/99
01174     Purpose:    Creates a new FlashTextRecord, which is used to store a text character.
01175     Returns:    TRUE if success.
01176     SeeAlso:    FlashRenderRegion::ExportCharacter ()
01177 
01178 ********************************************************************************************/
01179 
01180 BOOL FlashRenderRegion::CreateTextRecord ( TextChar *pTheLetter )
01181 {
01182     // Define local variables.
01183     TextLine                *pTextLine      = pTheLetter->FindParentLine ();
01184     DocRect                 Bounds          = pTextLine->GetBoundingRect ();
01185     WORD                    ID              = FlashPlaceObject::GetTextCount ();
01186     FlashType               ToRender        = FLASH_TEXT;
01187     WebAddressAttribute     *pWebAddress    = ( WebAddressAttribute * ) GetCurrentAttribute
01188                                               ( ATTR_WEBADDRESS );
01189     FlashButtonRecord       *pButton        = NULL;
01190     Matrix                  TextMatrix;
01191     FIXED16                 MatrixValues [4];
01192     INT32                   Translate [2];
01193     DocCoord                LowCorner;
01194 
01195     // If no text records, create one.
01196     if ( mpText == NULL )
01197     {
01198         mpText = new FlashTextRecord;
01199         ASSERT ( mpText != NULL );
01200         mpTextTail = mpText;
01201     }
01202     else
01203     {
01204         // mpTextTail points at the tail of the list.
01205         mpTextTail = mpTextTail->AddElement ();
01206         ASSERT ( mpTextTail != NULL );
01207     }
01208 
01209     // Set ID.
01210     mpTextTail->SetTextID ( FlashPlaceObject::GetTextCount () );
01211 
01212     // Set aspect ratio.
01213     mpTextTail->SetAspect ( ( ( TxtAspectRatioAttribute* ) GetCurrentAttribute
01214                             ( ATTR_TXTASPECTRATIO ) )->AspectRatio );
01215 
01216     // Set the bounding box.
01217     mpTextTail->SetBounds ( Bounds );
01218 
01219     // Get the text story matrix...
01220     pTheLetter->GetStoryAndCharMatrix ( &TextMatrix );
01221     TextMatrix.GetComponents ( MatrixValues, Translate );
01222 
01223     // ... and store it.
01224     mpTextTail->SetScaleX ( MatrixValues [0].GetRawLong () );
01225     mpTextTail->SetScaleY ( MatrixValues [3].GetRawLong () );
01226     mpTextTail->SetSkewX  ( MatrixValues [1].GetRawLong () );
01227     mpTextTail->SetSkewY  ( MatrixValues [2].GetRawLong () );
01228 
01229     // Record the text's web address.
01230     pButton = ProcessURL ( pWebAddress );
01231 
01232     // Add a PlaceObject record.
01233     LowCorner.x = Translate [0];                    // Calculate the x position.
01234     LowCorner.y = Translate [1];                    // And also the y position.
01235 
01236     PlaceObject ( ID, ToRender, &LowCorner, TRUE ); // Then create the FlashPlaceObject.
01237 
01238     // Export any button states that might have been created.
01239     ExportButtonState ( pButton );
01240 
01241     return TRUE;
01242 }
01243 
01244 /********************************************************************************************
01245 
01246 >   BOOL FlashRenderRegion::ProcessTransparency ( TranspFillAttribute *pTransp,
01247                                                   FillGeometryAttribute *pFill )
01248 
01249     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01250     Created:    7/12/99
01251     Purpose:    Processes the TranspFillAttribute of a shape, and fills in the correct
01252                 fill attributes into the FlashShapeRecord referenced by mpShapeTail.
01253     Returns:    TRUE if success.
01254     SeeAlso:    FlashRenderRegion::ProcessColour ()
01255 
01256 ********************************************************************************************/
01257 
01258 BOOL FlashRenderRegion::ProcessTransparency ( TranspFillAttribute *pTransp,
01259                                               FillGeometryAttribute *pFill )
01260 {
01261     // Step 1:  Extract values from the FillGeometryAttribute.
01262     DocCoord    *StartPoint     = pTransp->GetStartPoint ();
01263     DocCoord    *EndPoint1      = pTransp->GetEndPoint ();
01264     DocCoord    *EndPoint2      = pTransp->GetEndPoint2 ();
01265 
01266     UINT32      *StartTransp    = pTransp->GetStartTransp ();
01267     UINT32      *EndTransp1     = pTransp->GetEndTransp ();
01268     UINT32      *EndTransp2     = pTransp->GetEndTransp2 ();
01269     UINT32      *EndTransp3     = pTransp->GetEndTransp3 ();
01270 
01271     BYTE        CurrentFill     = mpShapeTail->GetFill ();
01272 
01273     // Step 2:  Determine what kind of fill is being used, and take appropriate action.
01274 
01275     // Step 2a: Bitmap transparencies have priority, so do them whenever they're encountered.
01276     //          Bitmap transparencies are currently disabled.
01277     if ( ( pTransp->IsABitmapFill () || pTransp->IsAFractalFill () ) &&
01278          CurrentFill == FLASH_FLAT_FILL )
01279     {
01280         // Versions of the Flash player prior to Flash 5 have had trouble rendering
01281         // transparent bitmaps. This appears to have been fixed in the new version, and as a
01282         // consequence, I've re-enabled bitmap transparencies.
01283         ProcessBitmapTransp ( pTransp, pFill );
01284     }
01285 
01286     // Step 2b: If the current transparency is approximated by a linear fill, and the current
01287     //          fill is a flat fill, process as a linear fill.
01288     else if ( ( pTransp->IsALinearFill () || pTransp->IsAConicalFill () ) &&
01289          CurrentFill == FLASH_FLAT_FILL )
01290     {
01291         ProcessGradientTransp ( StartTransp, NULL, EndTransp1, StartPoint, EndPoint1, NULL,
01292                                 FLASH_LINEAR_FILL );
01293     }
01294 
01295     // Step 2c: If it's a radial or diamond fill, output as a radial fill.
01296     else if ( ( pTransp->IsARadialFill () || pTransp->IsASquareFill () ) &&
01297                 CurrentFill == FLASH_FLAT_FILL )
01298     {
01299         ProcessGradientTransp ( StartTransp, NULL, EndTransp1, StartPoint, EndPoint1,
01300                                 EndPoint2, FLASH_RADIAL_FILL );
01301     }
01302 
01303     // Step 2d: If it's a four transparency fill, treat as a Linear fill. This comes before
01304     //          the three colour version because the IsAThreeColFill method returns TRUE for
01305     //          four colour fills.
01306     else if ( pTransp->IsAFourColFill ()  && CurrentFill == FLASH_FLAT_FILL )
01307     {
01308         DocCoord    NewEndPoint     ( *EndPoint1 + ( *EndPoint2 - *StartPoint ) );
01309         UINT32      MidTransp       = ( *EndTransp1 + *EndTransp2 ) / 2;
01310 
01311         ProcessGradientTransp ( StartTransp, &MidTransp, EndTransp3, StartPoint,
01312                                 &NewEndPoint, NULL, FLASH_LINEAR_FILL );
01313     }
01314 
01315     // Step 2e: If it's a three transparency fill, convert it into a linear fill, and process
01316     //          it that way.
01317     else if ( pTransp->IsAThreeColFill () && CurrentFill == FLASH_FLAT_FILL )
01318     {
01319         DocCoord    NewEndPoint     ( *EndPoint1 + ( *EndPoint2 - *StartPoint ) );
01320         UINT32      NewEndTransp    = ( *EndTransp1 + *EndTransp2 ) / 2;
01321 
01322         ProcessGradientTransp ( StartTransp, NULL, &NewEndTransp, StartPoint, &NewEndPoint,
01323                                 NULL, FLASH_LINEAR_FILL );
01324     }
01325 
01326     // Step 2f: Default - process as a flat fill.
01327     else
01328     {
01329         // Get the average transparency for the whole fill.
01330         UINT32      Transparency    = BlendTransparencies ( StartTransp, EndTransp1,
01331                                                             EndTransp2, EndTransp3 );
01332         // Process as a flat fill.
01333         ProcessFlatTransp ( Transparency );
01334     }
01335 
01336     return TRUE;
01337 }
01338 
01339 /********************************************************************************************
01340 
01341 >   BOOL FlashRenderRegion::ProcessColour ( FillGeometryAttribute *pFill )
01342 
01343     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01344     Created:    7/12/99
01345     Purpose:    Processes the FillGeometryAttribute of a shape, and fills in the correct
01346                 fill attributes into the FlashShapeRecord referenced by mpShapeTail.
01347     Returns:    TRUE if success.
01348     SeeAlso:    FlashRenderRegion::ProcessTransparency ()
01349 
01350 ********************************************************************************************/
01351  
01352 BOOL FlashRenderRegion::ProcessColour ( FillGeometryAttribute *pFill )
01353 {
01354     // Step 1:  Extract values from the FillGeometryAttribute.
01355     DocCoord    *StartPoint     = pFill->GetStartPoint ();
01356     DocCoord    *EndPoint1      = pFill->GetEndPoint ();
01357     DocCoord    *EndPoint2      = pFill->GetEndPoint2 ();
01358 
01359     DocColour   *StartColour    = pFill->GetStartColour ();
01360     DocColour   *EndColour1     = pFill->GetEndColour ();
01361     DocColour   *EndColour2     = pFill->GetEndColour2 ();
01362     DocColour   *EndColour3     = pFill->GetEndColour3 ();
01363 
01364     ColourRamp  *pRamp          = pFill->GetColourRamp ();
01365     BYTE        CurrentFill     = mpShapeTail->GetFill ();
01366 
01367     // Step 1a: If the start colour hasn't been set, return TRUE, and stop processing
01368     //          the fill.
01369     if ( StartColour == NULL && !pFill->IsABitmapFill () )
01370         return TRUE;
01371 
01372     // Step 2:  Determine what kind of fill is being used, and take appropriate action.
01373 
01374     // Step 2a: Bitmap fills have priority, so do them whenever they're encountered.
01375     if ( ( pFill->IsABitmapFill () ||
01376            pFill->IsAFractalFill () ||
01377            pFill->IsANoiseFill () ) &&
01378          ( CurrentFill != FLASH_CLIPPED_BITMAP ||
01379            CurrentFill != FLASH_TILED_BITMAP ) )
01380     {
01381         // Process as a bitmap fill.
01382         ProcessBitmapFill ( pFill );
01383     }
01384 
01385     // Step 2b: If the current fill type is approximated by a linear fill, and the current
01386     //          fill is a flat fill, process as a linear fill.
01387     else if ( ( pFill->IsALinearFill () || pFill->IsAConicalFill () )
01388               && CurrentFill == FLASH_FLAT_FILL )
01389     {
01390         ProcessGradientFill ( StartColour, NULL, EndColour1, pRamp, StartPoint, EndPoint1,
01391                               NULL, FLASH_LINEAR_FILL );
01392     }
01393 
01394     // Step 2c: If it's a radial or diamond fill, output as a radial fill.
01395     else if ( ( pFill->IsARadialFill () || pFill->IsASquareFill () ) &&
01396                 CurrentFill == FLASH_FLAT_FILL )
01397     {
01398         ProcessGradientFill ( StartColour, NULL, EndColour1, pRamp, StartPoint, EndPoint1,
01399                               EndPoint2, FLASH_RADIAL_FILL );
01400     }
01401 
01402     // Step 2d: If it's a four colour fill, treat as a Linear fill.
01403     else if ( pFill->IsAFourColFill ()  && CurrentFill == FLASH_FLAT_FILL )
01404     {
01405         DocCoord    NewEndPoint     ( *EndPoint1 + ( *EndPoint2 - *StartPoint ) );
01406         DocColour   MidColour;
01407 
01408         // Create a colour for the midpoint of the fill.
01409         MidColour.Mix ( EndColour1, EndColour2, 0.5f, NULL, FALSE, NULL );
01410 
01411         ProcessGradientFill ( StartColour, &MidColour, EndColour3, NULL, StartPoint,
01412                               &NewEndPoint, NULL, FLASH_LINEAR_FILL );
01413     }
01414 
01415     // Step 2e: If it's a three colour fill, convert it into a linear fill, and process
01416     //          it that way.
01417     else if ( pFill->IsAThreeColFill () && CurrentFill == FLASH_FLAT_FILL )
01418     {
01419         DocCoord    NewEndPoint     ( *EndPoint1 + ( *EndPoint2 - *StartPoint ) );
01420         DocColour   NewEndColour;
01421 
01422         // Mix the colours to create a new end colour.
01423         NewEndColour.Mix ( EndColour1, EndColour2, 0.5f, NULL, FALSE, NULL );
01424 
01425         ProcessGradientFill ( StartColour, NULL, &NewEndColour, NULL, StartPoint,
01426                               &NewEndPoint, NULL, FLASH_LINEAR_FILL );
01427     }
01428 
01429     // Step 2f: Default - process as a flat colour fill.
01430     else
01431     {
01432         // If no fill colour has been set, or the shape is declared transparent, store as
01433         // an unfilled shape.
01434         if ( StartColour != NULL && StartColour->IsTransparent () )
01435         {
01436             mpShapeTail->SetFill ( FLASH_NO_FILL );
01437         }
01438 
01439         // Otherwise treat as a flat fill.
01440         else
01441         {
01442             // Get the blend of all colours.
01443             DocColour   Colour  = BlendColours ( StartColour, EndColour1, EndColour2,
01444                                                  EndColour3, pRamp );
01445 
01446             // Process as a flat fill.
01447             ProcessFlatFill ( &Colour );
01448         }
01449     }
01450 
01451     return TRUE;
01452 }
01453 
01454 /********************************************************************************************
01455 
01456 >   BOOL FlashRenderRegion::ProcessFlatFill ( DocColour *pColour )
01457 
01458     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01459     Created:    6/12/99
01460     Purpose:    Processes a flat fill, and writes the correct values to the file record.
01461     Returns:    TRUE if success.
01462     SeeAlso:    -
01463 
01464 ********************************************************************************************/
01465 
01466 BOOL FlashRenderRegion::ProcessFlatFill ( DocColour *pColour )
01467 {
01468     UINT32 NumberColours = mpShapeTail->GetNumberColours ();
01469 
01470     // If no colours have been set, increment NumberColours so that a single value can be
01471     // set.
01472     if ( NumberColours == 0 )
01473     {
01474         NumberColours = 1;
01475     }
01476 
01477     // Parse through the list of fill colours, and set all fill colours to be pStartColour.
01478     for ( BYTE i = 0; i < NumberColours; i++ )
01479     {
01480         mpShapeTail->SetColour ( pColour, 255 - ( mpShapeTail->GetColour ( i ).Alpha ),
01481                                  mpShapeTail->GetRatio ( i ), i );
01482     }
01483 
01484     return TRUE;
01485 }
01486 
01487 /********************************************************************************************
01488 
01489 >   BOOL FlashRenderRegion::ProcessGradientFill ( DocColour *pStartColour,
01490                                                   DocColour *pMidColour,
01491                                                   DocColour *pEndColour,
01492                                                   ColourRamp *pRamp,
01493                                                   DocCoord *pStartPoint,
01494                                                   DocCoord *pEndPoint,
01495                                                   DocCoord *pEndPoint2,
01496                                                   BYTE FillType )
01497 
01498     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01499     Created:    6/12/99
01500     Purpose:    Processes a gradient fill, and writes the correct values to the file record.
01501     Returns:    TRUE if success.
01502     SeeAlso:    FlashRenderRegion::DrawPathToOutputDevice ()
01503 
01504 ********************************************************************************************/
01505 
01506 BOOL FlashRenderRegion::ProcessGradientFill ( DocColour *pStartColour,
01507                                               DocColour *pMidColour,
01508                                               DocColour *pEndColour,
01509                                               ColourRamp *pRamp,
01510                                               DocCoord *pStartPoint,
01511                                               DocCoord *pEndPoint,
01512                                               DocCoord *pEndPoint2,
01513                                               BYTE FillType )
01514 {
01515     // Step 1:  Set up the local variables.
01516     BYTE Alpha = 255 - ( mpShapeTail->GetColour ( 0 ).Alpha );
01517     BYTE Index = 0;
01518 
01519     // Step 2:  Set the start and end points, and the fill type.
01520     mpShapeTail->SetStartPoint ( *pStartPoint );
01521     mpShapeTail->SetEndPoint ( *pEndPoint );
01522 
01523     // Only set EndPoint2 if a NULL pointer hasn't been passed in.
01524     if ( pEndPoint2 != NULL )
01525     {
01526         mpShapeTail->SetEndPoint2 ( *pEndPoint2 );
01527     }
01528 
01529     // Set the fill type.
01530     mpShapeTail->SetFill ( FillType );
01531 
01532     // Step 3:  Set the fill colours.
01533 
01534     // Set the start colour for the fill.
01535     mpShapeTail->SetColour ( pStartColour, Alpha, 0, Index ++ );
01536 
01537     // If a middle colour has been set, write that in.
01538     if ( pMidColour != NULL )
01539     {
01540         mpShapeTail->SetColour ( pMidColour, Alpha, 128, Index ++ );
01541     }
01542 
01543     // Otherwise process the colour ramp.
01544     if ( pRamp != NULL )
01545     {
01546         ColRampItem *pColour = pRamp->GetFirstCol ();
01547 
01548         // Write in the ramp's colour values.
01549         while ( ( pColour != NULL ) && ( Index < 7 ) )
01550         {
01551             // Get the position of the colour in the fill.
01552             BYTE        Ratio   = ( BYTE ) ( 255.0f * pColour->GetPosition () );
01553             DocColour   Colour  = pColour->GetColour ();
01554 
01555             // Set the colour.
01556             mpShapeTail->SetColour ( &Colour, Alpha, Ratio, Index ++ );
01557 
01558             // Increment the pointer onto the next item.
01559             pColour = pRamp->GetNextCol ( pColour );
01560         }
01561     }
01562 
01563     // Write in the last colour.
01564     mpShapeTail->SetColour ( pEndColour, Alpha, 255, Index );
01565 
01566     return TRUE;
01567 }
01568 
01569 /********************************************************************************************
01570 
01571 >   BOOL FlashRenderRegion::ProcessBitmapFill ( FillGeometryAttribute *pFill )
01572 
01573     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01574     Created:    1/12/99
01575     Purpose:    Processes a bitmap fill, and writes the correct values to the file record.
01576     Returns:    TRUE if success.
01577     SeeAlso:    FlashRenderRegion::DrawPathToOutputDevice ()
01578 
01579 ********************************************************************************************/
01580 
01581 BOOL FlashRenderRegion::ProcessBitmapFill ( FillGeometryAttribute *pFill )
01582 {
01583     BitmapFillAttribute*    pBMFill         = ( BitmapFillAttribute * ) pFill;
01584     OILBitmap               *pBMP           = ( pBMFill->GetBitmap () )->GetActualBitmap ();
01585     DocColour               *pStartColour   = pBMFill->GetStartColour ();
01586     DocColour               *pEndColour     = pBMFill->GetEndColour ();
01587     WORD                    BitmapID        = 0;
01588     UINT32                  Alpha           = 0;
01589     UINT32                  Colours         = mpShapeTail->GetNumberColours ();
01590 
01591     // Sum all the alpha values for the bitmap.
01592     for ( UINT32 i = 0; i < Colours; i++ )
01593     {
01594         Alpha += mpShapeTail->GetColour ( i ).Alpha;
01595     }
01596 
01597     // And divide by the number of colour entries to get an average. Note: This will
01598     // under-represent a four colour transparency, since the second and third colours
01599     // will already have been averaged out.
01600     Alpha /= Colours;
01601 
01602     // Write the bitmap out to the file.
01603     BitmapID = GetBitmapID ( pBMP, pStartColour, pEndColour, Alpha );
01604 
01605     // Record the details of the fill.
01606     RecordBitmapFill ( pBMFill, BitmapID );
01607 
01608     return TRUE;
01609 }
01610 
01611 /********************************************************************************************
01612 
01613 >   BOOL FlashRenderRegion::RecordBitmapFill ( BitmapFillAttribute *pFill,
01614                                                WORD BitmapID )
01615 
01616     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01617     Created:    16/12/99
01618     Purpose:    Records the details of a bitmap fill into a shape record, so that it can
01619                 be stored within a Flash file.
01620     Returns:    TRUE if success.
01621     SeeAlso:    FlashExportDC::ProcessBitmapFill ()
01622 
01623 ********************************************************************************************/
01624 
01625 BOOL FlashRenderRegion::RecordBitmapFill ( BitmapFillAttribute *pFill,
01626                                            WORD BitmapID )
01627 {
01628     OILBitmap               *pBitmap    = ( pFill->GetBitmap () )->GetActualBitmap ();
01629     FillMappingAttribute    *pFillMap   = ( FillMappingAttribute* ) GetCurrentAttribute
01630                                             ( ATTR_FILLMAPPING );
01631 
01632     // Record the fill type, and the start and end points of the fill.
01633     mpShapeTail->SetStartPoint  ( *( pFill->GetStartPoint () ) );
01634     mpShapeTail->SetEndPoint    ( *( pFill->GetEndPoint () ) );
01635     mpShapeTail->SetEndPoint2   ( *( pFill->GetEndPoint2 () ) );
01636 
01637     // Determine whether or not it's a clipped bitmap.
01638     if ( ( pFillMap != NULL ) && ( pFillMap->Repeat == RT_Simple ) )
01639     {
01640         // Single bitmap clipped to the shape.
01641         mpShapeTail->SetFill ( FLASH_CLIPPED_BITMAP );
01642     }
01643     else
01644     {
01645         // Repeating bitmap fill.
01646         mpShapeTail->SetFill ( FLASH_TILED_BITMAP );
01647     }
01648 
01649     // Record the size and ID number of the bitmap used.
01650     mpShapeTail->SetBitmapID ( BitmapID );
01651     mpShapeTail->SetBitmapWidth ( pBitmap->GetWidth () );
01652     mpShapeTail->SetBitmapHeight ( pBitmap->GetHeight () );
01653 
01654     return TRUE;
01655 }
01656 
01657 /********************************************************************************************
01658 
01659 >   WORD FlashRenderRegion::GetBitmapID ( OILBitmap *pBitmap,
01660                                           DocColour *pStartColour,
01661                                           DocColour *pEndColour,
01662                                           UINT32        Transparency )
01663 
01664     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01665     Created:    16/12/99
01666     Purpose:    Spools through the list of bitmaps, and returns the appropriate bitmap
01667                 reference. Note: Bevel bitmaps are treated as being contoned, though the
01668                 process by which their palette is generated is slightly different.
01669 
01670                 The title  of this function is slightly misleading because it actually
01671                 exports the bitmap, rather than just IDing it.
01672     Returns:    TRUE if success.
01673     SeeAlso:    FlashExportDC::ProcessBitmapFill ()
01674 
01675 ********************************************************************************************/
01676 
01677 WORD FlashRenderRegion::GetBitmapID ( OILBitmap *pBitmap,
01678                                       DocColour *pStartColour,
01679                                       DocColour *pEndColour,
01680                                       UINT32        Transparency )
01681 {
01682     BOOL                IsContone   = ( pStartColour != NULL && pEndColour != NULL );
01683     WORD                BitmapID    = FlashPlaceObject::GetBitmapCount ();
01684     FlashExportDC       *pFlashDC   = ( FlashExportDC * ) CCDC::ConvertFromNativeDC(RenderDC);
01685     FlashBitmapRecord   *pRecord    = mpBitmap;
01686 
01687     // If the bitmap has been contoned, but the underlying bitmap is a 32 bit image,
01688     // build an 8 bit greyscale bitmap.
01689     if ( ( IsContone  ) && ( pBitmap->GetBPP () > 8 ) )
01690     {
01691         // Convert the bitmap into a greyscale image.
01692         OILBitmap *pGreyscaleBitmap = pBitmap->GetGreyscaleVersion ();
01693 
01694         if ( pGreyscaleBitmap != NULL )
01695             pBitmap = pGreyscaleBitmap;
01696     }
01697 
01698     // Spool through the list of bitmaps, and compare with existing records. If there's
01699     // a match, return the bitmap's ID number, otherwise create a new record.
01700     while ( pRecord != NULL )
01701     {
01702         if ( ( pBitmap == pRecord->GetBitmap () ) &&
01703              ( Transparency == pRecord->GetTransparency () ) &&
01704              ( IsContone == pRecord->GetIsContone () ) )
01705         {
01706             // If the bitmap is contoned, and the colours don't match.
01707             if ( IsContone &&
01708                  ( ( *pStartColour != pRecord->GetContoneStart () ) ||
01709                  ( *pEndColour != pRecord->GetContoneEnd () ) ) )
01710             {
01711                 // Continue.
01712                 pRecord = pRecord->GetNext ();
01713             }
01714             else
01715             {
01716                 BitmapID = pRecord->GetBitmapID ();
01717                 break;
01718             }
01719         }
01720         else
01721         {
01722             // Continue.
01723             pRecord = pRecord->GetNext ();
01724         }
01725     }
01726 
01727     // No matching record was found, so create a new one.
01728     if ( pRecord == NULL )
01729     {
01730         // Create a bitmap record, and add it to the tail of the bitmap list.
01731         if ( mpBitmap == NULL )
01732         {
01733             mpBitmap = new FlashBitmapRecord;
01734             ASSERT ( mpBitmap != NULL );
01735             mpBitmapTail = mpBitmap;
01736         }
01737         else
01738         {
01739             mpBitmapTail = mpBitmapTail->AddElement ();
01740             ASSERT ( mpBitmapTail != NULL );
01741         }
01742         
01743         mpBitmapTail->SetBitmap ( pBitmap );
01744         mpBitmapTail->SetBitmapID ( BitmapID );
01745         mpBitmapTail->SetIsContone ( IsContone );
01746 
01747         // Set data for contone bitmaps.
01748         if ( IsContone )
01749         {
01750             // Create a contone bitmap palette.
01751             pBitmap->BuildContonePalette ( *( pStartColour ), *( pEndColour ), GetFillEffect (),
01752                                            RenderView );
01753 
01754             // Record the colours in the bitmap record, so multiple versions aren't
01755             // created.
01756             mpBitmapTail->SetContoneColours ( *pStartColour, *pEndColour );
01757         }
01758 
01759         // Write the bitmap out at once.
01760         pFlashDC->WritePNG ( pBitmap, BitmapID, Transparency, IsContone );
01761 
01762         FlashPlaceObject::IncBitmapCount ();
01763 
01764         pBitmap->DestroyContonePalette();
01765     }
01766 
01767     return BitmapID;
01768 }
01769 
01770 /********************************************************************************************
01771 
01772 >   BOOL FlashRenderRegion::ProcessFlatTransp ( UINT32 Transparency )
01773 
01774     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01775     Created:    7/12/99
01776     Purpose:    Processes a flat transparency, and writes the correct values to the file
01777                 record.
01778     Returns:    TRUE if success.
01779     SeeAlso:    FlashRenderRegion::ProcessTransp ()
01780 
01781 ********************************************************************************************/
01782 
01783 BOOL FlashRenderRegion::ProcessFlatTransp ( UINT32 Transparency )
01784 {
01785     UINT32 NumberColours = mpShapeTail->GetNumberColours ();
01786 
01787     // If no colours have been set, increment NumberColours so that a single value can be
01788     // set.
01789     if ( NumberColours == 0 )
01790     {
01791         NumberColours = 1;
01792     }
01793 
01794     // Parse through the list of fill colours, and set all alpha values to be Transparency.
01795     for ( BYTE i = 0; i < NumberColours; i++ )
01796     {
01797         FlashColour CurrentCol  = mpShapeTail->GetColour ( i );
01798         DocColour   NewColour   ( CurrentCol.Red, CurrentCol.Green, CurrentCol.Blue );
01799 
01800         mpShapeTail->SetColour ( &NewColour, Transparency, mpShapeTail->GetRatio ( i ), i );
01801     }
01802 
01803     return TRUE;
01804 }
01805 
01806 /********************************************************************************************
01807 
01808 >   BOOL FlashRenderRegion::ProcessGradientTransp ( UINT32 *pStartTransparency,
01809                                                     UINT32 *pMidTransparency,
01810                                                     UINT32 *pEndTransparency,
01811                                                     DocCoord *pStartPoint,
01812                                                     DocCoord *pEndPoint,
01813                                                     DocCoord *pEndPoint2,
01814                                                     BYTE FillType )
01815 
01816     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01817     Created:    7/12/99
01818     Purpose:    Processes a gradient transparency, and writes the correct values to the file
01819                 record.
01820     Returns:    TRUE if success.
01821     SeeAlso:    FlashRenderRegion::ProcessTransparency ()
01822 
01823 ********************************************************************************************/
01824 
01825 BOOL FlashRenderRegion::ProcessGradientTransp ( UINT32 *pStartTransparency,
01826                                                 UINT32 *pMidTransparency,
01827                                                 UINT32 *pEndTransparency,
01828                                                 DocCoord *pStartPoint,
01829                                                 DocCoord *pEndPoint,
01830                                                 DocCoord *pEndPoint2,
01831                                                 BYTE FillType )
01832 {
01833     // Step 1:  Set up the local variables.
01834     FlashColour CurrentCol  = mpShapeTail->GetColour ( 0 );
01835     DocColour   NewColour   ( CurrentCol.Red, CurrentCol.Green, CurrentCol.Blue );
01836     BYTE        Index       = 0;
01837 
01838     // Step 2:  Set the start and end points, and the fill type.
01839     mpShapeTail->SetStartPoint ( *pStartPoint );
01840     mpShapeTail->SetEndPoint ( *pEndPoint );
01841 
01842     // Only set EndPoint2 if a NULL pointer hasn't been passed in.
01843     if ( pEndPoint2 != NULL )
01844     {
01845         mpShapeTail->SetEndPoint2 ( *pEndPoint2 );
01846     }
01847 
01848     // Set the fill type.
01849     mpShapeTail->SetFill ( FillType );
01850 
01851     // Step 3:  Set the fill colours.
01852 
01853     // Set the start colour for the fill.
01854     mpShapeTail->SetColour ( &NewColour, *pStartTransparency, 0, Index ++ );
01855 
01856     // If a middle colour has been set, write that in.
01857     if ( pMidTransparency != NULL )
01858     {
01859         mpShapeTail->SetColour ( &NewColour, *pMidTransparency, 128, Index ++ );
01860     }
01861 
01862     // Write in the last colour.
01863     mpShapeTail->SetColour ( &NewColour, *pEndTransparency, 255, Index );
01864 
01865     return TRUE;
01866 }
01867 
01868 /********************************************************************************************
01869 
01870 >   BOOL FlashRenderRegion::ProcessBitmapTransp ( TranspFillAttribute *pTransparency,
01871                                                   FillGeometryAttribute *pFill )
01872 
01873     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01874     Created:    3/12/99
01875     Returns:    TRUE if success.
01876     Purpose:    Processes a bitmap fill, and writes the correct values to the file record.
01877                 There were problems with Flash 4 to do with rendering transparent bitmaps,
01878                 and so this was removed. Flash 5 seems to have cured them, and so this
01879                 function has ben re-instated.
01880     SeeAlso:    FlashRenderRegion::ProcessFill ()
01881 
01882 ********************************************************************************************/
01883 
01884 BOOL FlashRenderRegion::ProcessBitmapTransp ( TranspFillAttribute *pTransparency,
01885                                               FillGeometryAttribute *pFill )
01886 {
01887     BitmapFillAttribute *pBMFill        = ( BitmapFillAttribute * ) pTransparency;
01888     WORD                BitmapID        = FlashPlaceObject::GetBitmapCount ();
01889     OILBitmap           *pBitmap        = ( pBMFill->GetBitmap () )->GetActualBitmap ();
01890     DocColour           *pStartColour   = pFill->GetStartColour ();
01891     FlashExportDC       *pFlashDC       = ( FlashExportDC * ) CCDC::ConvertFromNativeDC(RenderDC);
01892 //  BOOL                IsContone       = TRUE;
01893 //  FlashBitmapRecord   *pRecord        = mpBitmap;
01894 
01895     // If we've got a bitmap fill applied too, we want to export that. So just set the
01896     // object up with a flat fill.
01897     if ( pFill->IsABitmapFill () ||
01898          pFill->IsAFractalFill () ||
01899          pFill->IsANoiseFill () )
01900     {
01901         // Calculate the average transparency across the bitmap. In this case, the end
01902         // transparency is 255 (i.e. clear), so add 255 to the value before dividing it.
01903         UINT32 Transparency = ( *( pTransparency->GetStartTransp () + 255 ) ) / 2;
01904 
01905         // Process it as a flat fill instead.
01906         return ProcessFlatTransp ( Transparency );
01907     }
01908 
01909     if ( pBitmap->GetBPP () > 8 )
01910     {
01911         // Convert the bitmap into a greyscale image.
01912         OILBitmap *pGreyscaleBitmap = pBitmap->GetGreyscaleVersion ();
01913 
01914         if ( pGreyscaleBitmap != NULL )
01915             pBitmap = pGreyscaleBitmap;
01916     }
01917 
01918     // Record the fill type, and the start and end points of the fill.
01919     mpShapeTail->SetStartPoint  ( *( pTransparency->GetStartPoint () ) );
01920     mpShapeTail->SetEndPoint    ( *( pTransparency->GetEndPoint () ) );
01921     mpShapeTail->SetEndPoint2   ( *( pTransparency->GetEndPoint2 () ) );
01922 
01923     // Store repeating bitmaps as the appropriate flavour.
01924     if ( pTransparency->GetTesselation () == RT_Repeating ||
01925          pTransparency->GetTesselation () == RT_RepeatInverted )
01926     {
01927         // Repeating bitmap fill.
01928         mpShapeTail->SetFill ( FLASH_TILED_BITMAP );
01929     }
01930     else
01931     {
01932         // Single bitmap clipped to the shape.
01933         mpShapeTail->SetFill ( FLASH_CLIPPED_BITMAP );
01934     }
01935 
01936     // Every transparency will have its own record, unlike normal bitmaps.
01937     FlashPlaceObject::IncBitmapCount ();
01938 
01939     mpShapeTail->SetBitmapID ( BitmapID );
01940     mpShapeTail->SetBitmapWidth ( pBitmap->GetWidth () );
01941     mpShapeTail->SetBitmapHeight ( pBitmap->GetHeight () );
01942 
01943     // Write the bitmap out at once.
01944     pFlashDC->WriteTransparentBitmap ( pBitmap, BitmapID, *pStartColour );
01945 
01946     return TRUE;
01947 }
01948 
01949 /********************************************************************************************
01950 
01951 >   UINT32 FlashRenderRegion::BlendTransparencies ( UINT32 *pStart,
01952                                                   UINT32 *pEnd1,
01953                                                   UINT32 *pEnd2,
01954                                                   UINT32 *pEnd3 )
01955 
01956     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
01957     Created:    7/12/99
01958     Purpose:    Calculates the average value for the transparency of a shape.
01959     Returns:    The average value of pStart, pEnd1, pEnd2, and pEnd3.
01960     SeeAlso:    FlashRenderRegion::ProcessTransparency ()
01961 
01962 ********************************************************************************************/
01963 
01964 UINT32 FlashRenderRegion::BlendTransparencies ( UINT32 *pStart,
01965                                               UINT32 *pEnd1,
01966                                               UINT32 *pEnd2,
01967                                               UINT32 *pEnd3 )
01968 {
01969     // Declare and initialise the local variables.
01970     UINT32 Result   = *pStart;
01971     UINT32 Count    = 1;
01972 
01973     // I've nested the following if statements for efficiency, since (e.g.) if pEnd1 is
01974     // NULL, pEnd2 and pEnd3 will also be NULL.
01975     if ( pEnd1 != NULL )
01976     {
01977         Result += *pEnd1;
01978         Count ++;
01979 
01980         // Call the second if, for pEnd2.
01981         if ( pEnd2 != NULL )
01982         {
01983             Result += *pEnd2;
01984             Count ++;
01985 
01986             // And finally for pEnd3.
01987             if ( pEnd3 != NULL )
01988             {
01989                 Result += *pEnd3;
01990                 Count ++;
01991             }
01992         }
01993     }
01994 
01995     // Divide Result by Count to get the average transparency.
01996     Result /= Count;
01997 
01998     return Result;
01999 }
02000 
02001 /********************************************************************************************
02002 
02003 >   DocColour FlashRenderRegion::BlendColours ( DocColour *pStart,
02004                                                 DocColour *pEnd1,
02005                                                 DocColour *pEnd2,
02006                                                 DocColour *pEnd3,
02007                                                 ColourRamp *pRamp )
02008 
02009     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02010     Created:    7/12/99
02011     Purpose:    Calculates the average value for the fill colour of a shape, along with the
02012                 contents of any colour ramp.
02013     Returns:    The average value of pStart, pEnd1, pEnd2, and pEnd3.
02014     SeeAlso:    FlashRenderRegion::ProcessTransparency ()
02015 
02016 ********************************************************************************************/
02017 
02018 DocColour FlashRenderRegion::BlendColours ( DocColour *pStart,
02019                                             DocColour *pEnd1,
02020                                             DocColour *pEnd2,
02021                                             DocColour *pEnd3,
02022                                             ColourRamp *pRamp )
02023 {
02024     // Declare and initialise the local variables.
02025     DocColour   Result;
02026     INT32       TotalRed    = 0;
02027     INT32       TotalGreen  = 0;
02028     INT32       TotalBlue   = 0;
02029     INT32       Count       = 1;
02030     INT32       Red, Green, Blue;
02031 
02032     // Extract the colours from the DocColour.
02033     if ( pStart != NULL )
02034     {
02035         pStart->GetRGBValue ( &TotalRed, &TotalGreen, &TotalBlue );
02036     }
02037 
02038     // I've nested the following if statements for efficiency, since (e.g.) if pEnd1 is
02039     // NULL, pEnd2 and pEnd3 will also be NULL.
02040     if ( pEnd1 != NULL )
02041     {
02042         // Extract the colours from the DocColour.
02043         pEnd1->GetRGBValue ( &Red, &Green, &Blue );
02044 
02045         TotalRed    += Red;
02046         TotalGreen  += Green;
02047         TotalBlue   += Blue;
02048         Count ++;
02049 
02050         // Call the second if, for pEnd2.
02051         if ( pEnd2 != NULL )
02052         {
02053             // Extract the colours from the DocColour.
02054             pEnd2->GetRGBValue ( &Red, &Green, &Blue );
02055 
02056             TotalRed    += Red;
02057             TotalGreen  += Green;
02058             TotalBlue   += Blue;
02059             Count ++;
02060 
02061             // And finally for pEnd3.
02062             if ( pEnd3 != NULL )
02063             {
02064                 // Extract the colours from the DocColour.
02065                 pEnd3->GetRGBValue ( &Red, &Green, &Blue );
02066 
02067                 TotalRed    += Red;
02068                 TotalGreen  += Green;
02069                 TotalBlue   += Blue;
02070                 Count ++;
02071             }
02072         }
02073     }
02074 
02075     // Process the colour ramp.
02076     if ( pRamp != NULL )
02077     {
02078         ColRampItem *pColour = pRamp->GetFirstCol ();
02079 
02080         // Write in the ramp's colour values.
02081         while ( pColour != NULL )
02082         {
02083             // Get the position of the colour in the fill.
02084             DocColour   RampColour  = pColour->GetColour ();
02085 
02086             // Extract the colour.
02087             RampColour.GetRGBValue ( &Red, &Green, &Blue );
02088 
02089             TotalRed    += Red;
02090             TotalGreen  += Green;
02091             TotalBlue   += Blue;
02092             Count ++;
02093 
02094             // Increment the pointer onto the next item.
02095             pColour = pRamp->GetNextCol ( pColour );
02096         }
02097     }
02098 
02099     // Divide the Total* values by Count to get the average colour.
02100     TotalRed    /= Count;
02101     TotalGreen  /= Count;
02102     TotalBlue   /= Count;
02103 
02104     Result.SetRGBValue ( TotalRed, TotalGreen, TotalBlue );
02105 
02106     return Result;
02107 }
02108 
02109 /********************************************************************************************
02110 
02111 >   FlashButtonRecord* FlashRenderRegion::ProcessURL ( WebAddressAttribute *pWebAddress )
02112 
02113     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02114     Created:    9/12/99
02115     Purpose:    Processes a WebAddressAttribute, and stores the details in a
02116                 FlashButtonRecord for processing in the Export DC.
02117     Returns:    A pointer to the button record used.
02118     SeeAlso:    FlashExportDC::WriteURLScript
02119 
02120 ********************************************************************************************/
02121 
02122 FlashButtonRecord* FlashRenderRegion::ProcessURL ( WebAddressAttribute *pWebAddress )
02123 {
02124     FlashButtonRecord   *pButton    = NULL;
02125 
02126     // Ensure that a valid web address has been set.
02127     if ( ( pWebAddress ) != NULL && ( pWebAddress->HasURL () ) )
02128     {
02129         WebAddress  URL = pWebAddress->m_url;
02130         
02131         // Get a pointer to an existing matching button, otherwise create a new one.
02132         pButton = MatchButton ();
02133 
02134         // Create the button record.
02135         pButton->SetURL ( URL.GetWebAddress () );       // Target URL.
02136         pButton->SetFrame ( pWebAddress->m_pcFrame );   // Window to open it in.
02137     }
02138 
02139     return pButton;
02140 }
02141 
02142 /********************************************************************************************
02143 
02144 >   BOOL FlashRenderRegion::ExportButtonState ( FlashButtonRecord *pButton )
02145 
02146     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02147     Created:    14/1/00
02148     Purpose:    This method is part of the button rollover support that is being added to
02149                 the Flash export filter. Due to the way that the render region has been
02150                 implemented, and the fact that I've been asked to do this after writing
02151                 virtually all of the filter code, it's algorithm is a little strange.
02152                 
02153                 The Flash filter works by creating a series of linked lists containing a
02154                 record of the objects to be exported during the pass through the rendering
02155                 tree, which is a necessary first step to record reuseable resources such as
02156                 bitmap images, and font definitions. This method is unique in that it goes
02157                 back to previously created nodes and changes them by removing PlaceObject
02158                 tags from this list.
02159 
02160                 A more efficient way to do this would have been to pick up on whether a node
02161                 was a part of a button before exporting. However, this would require
02162                 rewriting a lot of code, and would probably end up being much more complex,
02163                 so I'm willing to tolerate some eccentricity.
02164     Returns:    TRUE if success, FALSE if an error is encountered.
02165     SeeAlso:    -
02166 
02167 ********************************************************************************************/
02168 
02169 BOOL FlashRenderRegion::ExportButtonState ( FlashButtonRecord *pButton )
02170 {
02171     // Define local variables.
02172     FlashPlaceObject    *pLast      = mpPlaceTail;
02173     FlashSprite         *pSprite    = NULL;
02174 
02175     // If the function has been passed a NULL pointer, check whether a button name has been
02176     // set. If not, return from this function.
02177     if ( pButton == NULL )
02178     {
02179         // If a name has been set, then this shape is part of a button array, so go and
02180         // process it.
02181         if ( ( mButtonState == NO_BUTTON ) &&
02182              ( mButtonName.IsEmpty () ) )
02183         {
02184             return FALSE;
02185         }
02186     }
02187 
02188     // Remove the object from the tail of the list. Rewind the PlaceObject tail pointer.
02189     mpPlaceTail = mpPlaceTail->GetLast ();
02190 
02191     // Catch NULL pointers to avoid access violations.
02192     if ( mpPlaceTail != NULL )
02193     {
02194         mpPlaceTail->SetNext ( NULL );
02195     }
02196     else
02197     {
02198         mpPlace = NULL;
02199     }
02200 
02201     // If no button exists at this point, get a match.
02202     pButton = MatchButton ();
02203 
02204     // Get the sprite record ID from the list.
02205     pSprite = MatchSprite ( pButton );
02206 
02207     // Re-attatch the place object record to the sprite record.
02208     pSprite->SetTail ( pLast );
02209 
02210     return TRUE;
02211 }
02212 
02213 /********************************************************************************************
02214 
02215 >   FlashButtonRecord* FlashRenderRegion::MatchButton ( void )
02216 
02217     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02218     Created:    14/1/00
02219     Returns:    A pointer to the button record that has the same name string as the one
02220                 passed into this function.
02221     Purpose:    Spools through the list of button records (pointed to by mpButton), and
02222                 attempts to match the sprite with the input parameters. If no match is
02223                 made, a new button record is created, and populated with the correct values.
02224     SeeAlso:    FlashFilter::ExportButtonState, FlashFilter::MatchSprite
02225 
02226 ********************************************************************************************/
02227 
02228 FlashButtonRecord* FlashRenderRegion::MatchButton ( void )
02229 {
02230     FlashButtonRecord *pButton = mpButton;
02231 
02232     // Loop through the list until a match is made.
02233     while ( pButton != NULL && !pButton->IsAMatch ( ( TCHAR* ) mButtonName ) )
02234     {
02235         pButton = pButton->GetNext ();
02236     }
02237 
02238     // Check to see whether there has been a match made. If not, create a new record.
02239     if ( pButton == NULL )
02240     {
02241         WORD ID = FlashPlaceObject::GetButtonCount ();
02242 
02243         // Create a new button record, and make sure that one exists first!
02244         if ( mpButton == NULL )
02245         {
02246             pButton = mpButtonTail = mpButton = new FlashButtonRecord;
02247         }
02248         else
02249         {
02250             pButton = mpButtonTail = mpButtonTail->AddElement ();
02251         }
02252 
02253         // Set the name to act as an ID value.
02254         mpButtonTail->SetName ( ( TCHAR* ) mButtonName );
02255 
02256         // Create a new FlashPlaceObject.
02257         PlaceObject ( ID, FLASH_BUTTON );
02258 
02259         // Set the ID for the button object.
02260         mpButtonTail->SetButtonID ( ID );
02261     }
02262 
02263     return pButton;
02264 }
02265 
02266 /********************************************************************************************
02267 
02268 >   FlashSprite* FlashRenderRegion::MatchSprite ( FlashButtonRecord *pButton )
02269 
02270     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02271     Created:    14/1/99
02272     Returns:    A pointer to the sprite record that has the same name and LayerState to the
02273                 values passed in.
02274     Purpose:    Spools through the list of sprite records (pointed to by mpSprite), and
02275                 attempts to match the sprite with the input parameters. If no match is made,
02276                 a new sprite record is created, and populated with the correct name and
02277                 LayerState.
02278     SeeAlso:    FlashFilter::ExportButtonState, FlashFilter::MatchButton
02279 
02280 ********************************************************************************************/
02281 
02282 FlashSprite* FlashRenderRegion::MatchSprite ( FlashButtonRecord *pButton )
02283 {
02284     FlashSprite *pSprite    = mpSprite;
02285 
02286     // Loop through the list of sprites until a match is made, or the end of the list is
02287     // reached.
02288     while ( pSprite != NULL && !pSprite->IsAMatch ( ( TCHAR* ) mButtonName, mButtonState ) )
02289     {
02290         pSprite = pSprite->GetNext ();
02291     }
02292 
02293     // Check to see whether there has been a match made. If not, create a new record,
02294     // and insert it into the button record at the appropriate point.
02295     if ( pSprite == NULL )
02296     {
02297         WORD ID = FlashPlaceObject::GetSpriteCount ();
02298 
02299         // Check to see whether or not a record has been created, and if not, create one.
02300         if ( mpSpriteTail != NULL )
02301         {
02302             pSprite = mpSpriteTail = mpSpriteTail->AddNext ();
02303         }
02304         else
02305         {
02306             pSprite = mpSpriteTail = mpSprite = new FlashSprite;
02307             ASSERT ( mpSprite != NULL );
02308         }
02309 
02310         mpSpriteTail->SetID ( ID );                 // Set the sprite's ID value.
02311         mpSpriteTail->SetName ( mButtonName );      // Set the name to act as an ID value.
02312         mpSpriteTail->SetLayer ( mButtonState );    // Set the layer value as another ID.
02313 
02314         // Determine which layer we're dealing with here, and attach it to the appropriate
02315         // button state.
02316         switch ( mButtonState )
02317         {
02318         case CLICKED:
02319             pButton->SetDownID ( ID, FLASH_SPRITE );
02320             break;
02321 
02322         case MOUSE:
02323             pButton->SetOverID ( ID, FLASH_SPRITE );
02324             break;
02325 
02326         case SELECTED:
02327             pButton->SetHitID ( ID, FLASH_SPRITE );
02328             break;
02329 
02330         default:    // i.e. DEFAULT or NO_BUTTON.
02331             pButton->SetUpID ( ID, FLASH_SPRITE );
02332             break;
02333         }
02334 
02335         FlashPlaceObject::IncSpriteCount ();    // Increment the sprite count.
02336     }
02337 
02338     return pSprite;
02339 }
02340 
02341 /********************************************************************************************
02342 
02343 >   BOOL FlashRenderRegion::PlaceObject ( WORD ID,
02344                                           FlashType ToRender,
02345                                           DocCoord *pPosition = NULL,
02346                                           BOOL DoTransform = FALSE )
02347 
02348     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02349     Created:    18/1/00
02350     Returns:    TRUE if success.
02351     Purpose:    Creates a FlashPlaceObject record for the object with the corresponding ID.
02352     SeeAlso:    -
02353 
02354 ********************************************************************************************/
02355 
02356 BOOL FlashRenderRegion::PlaceObject ( WORD ID,
02357                                       FlashType ToRender,
02358                                       DocCoord *pPosition,
02359                                       BOOL DoTransform )
02360 {
02361     // If no records exist, create the head of the list.
02362     if ( mpPlace == NULL )
02363     {
02364         mpPlace = new FlashPlaceObject;
02365         ASSERT ( mpPlace != NULL );
02366         mpPlaceTail = mpPlace;
02367     }
02368 
02369     // Otherwise add an element onto the tail of the list.
02370     else
02371     {
02372         mpPlaceTail = mpPlaceTail->AddNext ();
02373         ASSERT ( mpPlaceTail != NULL );
02374     }
02375 
02376     mpPlaceTail->SetID ( ID );
02377     mpPlaceTail->SetType ( ToRender );
02378 
02379     // Don't reset the position if a NULL DocCoord pointer has been passed in.
02380     if ( pPosition != NULL )
02381     {
02382         mpPlaceTail->SetPosition ( *pPosition );
02383         mpPlaceTail->SetDoTransform ( DoTransform );
02384     }
02385 
02386     // Remember to increment the counter for the appropriate shape type.
02387     switch ( ToRender )
02388     {
02389     case FLASH_TEXT:
02390         FlashPlaceObject::IncTextCount ();
02391         break;
02392 
02393     case FLASH_SHAPE:
02394         FlashPlaceObject::IncShapeCount ();
02395         break;
02396 
02397     case FLASH_SPRITE:
02398         FlashPlaceObject::IncSpriteCount ();
02399         break;
02400 
02401     case FLASH_BUTTON:
02402         FlashPlaceObject::IncButtonCount ();
02403         break;
02404     }
02405 
02406     return TRUE;
02407 }

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