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 }