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