00001 // $Id: giffiltr.cpp 1461 2006-07-18 09:50:40Z luke $ 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 00099 // A GIF import/export filter 00100 00101 00102 #include "camtypes.h" 00103 #include "giffiltr.h" 00104 //#include "andy.h" 00105 //#include "oilfltrs.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00106 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00107 //#include "dibutil.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00108 #include "grndbmp.h" 00109 #include "nodebmp.h" 00110 #include "bmpfiltr.h" 00111 #include "progress.h" 00112 #include "oilbitmap.h" // Windows specific bitmap information 00113 //#include "docview.h" // DocView - in camtypes.h [AUTOMATICALLY REMOVED] 00114 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00115 00116 //#include "richard2.h" // resource strings _R(IDS_GIFFILTR_FAILED_MASK) 00117 //#include "accures.h" // Accusoft filter ids and messages 00118 //#include "bmpres.h" // general bitmap filter based resources (_R(IDE_TIGIFFILTER_MASKFAILED)/MASK) 00119 //#include "will3.h" // for _R(IDS_GENOPTPALMSGID) 00120 00121 #include "maskfilt.h" // MaskedFilter class 00122 #include "bmpsdlg.h" 00123 #include "frameops.h" // GIFAnimationExportParam 00124 //#include "spread.h" // Pasteboard rect - in camtypes.h [AUTOMATICALLY REMOVED] 00125 #include "bmapprev.h" // tab preview dialog 00126 #include "palman.h" // MakePaletteBrowserCompatible 00127 #include "sprdmsg.h" // SpreadMsg::ANIMATIONPROPERTIESCHANGED 00128 #include "impexpop.h" 00129 00130 #include "exphint.h" 00131 00132 #include "camdoc.h" 00133 #include "menuops.h" 00134 00135 //#include "outptdib.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00136 //#include "cxfrec.h" // for CXaraFileRecord - in camtypes.h [AUTOMATICALLY REMOVED] 00137 00138 #include "mrhbits.h" // For CBMPBits::RenderSelectionToBMP 00139 #include "selall.h" // For OPTOKEN_EDITSELECTALL 00140 #include "bmpprefs.h" 00141 //#include "animparams.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00142 #include "tmplmngr.h" 00143 00144 DECLARE_SOURCE("$Revision: 1461 $"); 00145 00146 CC_IMPLEMENT_DYNAMIC(TI_GIFFilter, MaskedFilter) 00147 CC_IMPLEMENT_MEMDUMP(GIFImportOptions, BitmapImportOptions) 00148 CC_IMPLEMENT_DYNCREATE(GIFExportOptions, MaskedFilterExportOptions) 00149 00150 CC_IMPLEMENT_DYNCREATE(AnimatedGIFImage, ListItem) 00151 00152 #define new CAM_DEBUG_NEW 00153 00154 static UINT32 g_DefaultGIFType = 0; 00155 00156 OutputGIF TI_GIFFilter::DestGIF; 00157 FilterType TI_GIFFilter::s_FilterType = GIF; // Type of filter in use (TI_GIF .. TI_GIF_TRANSINTER) 00158 00159 CENTISECONDS GIFExportOptions::g_AnimationDelay = 10; // Delay in CentiSeconds 00160 GIFDisposalMethod GIFExportOptions::g_AnimationRestoreType = GDM_LEAVE; // How to restore after each frame 00161 UINT32 GIFExportOptions::g_AnimationLoopCount = 1; // Number of loops 00162 KernelBitmap** GIFExportOptions::m_pBitmapList = NULL; 00163 UINT32 GIFExportOptions::m_ListSize = 0; 00164 00165 /******************************************************************************************** 00166 00167 > static BOOL GIFExportOptions::Declare() 00168 00169 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> (from Peter) 00170 Created: 29/10/96 00171 Returns: TRUE if successfully declared preferences 00172 FALSE otherwise 00173 Purpose: To declare preferences associated with these export options 00174 00175 ********************************************************************************************/ 00176 BOOL GIFExportOptions::Declare() 00177 { 00178 if (Camelot.DeclareSection(_T("Filters"), 10)) 00179 { 00180 Camelot.DeclarePref( NULL, _T("ExportGIFtype"), &g_DefaultGIFType, 0, 3 ); 00181 Camelot.DeclarePref( NULL, _T("AnimationDelay"), &g_AnimationDelay, 0, 65535 ); 00182 Camelot.DeclarePref( NULL, _T("AnimationRestoreType"), (INT32*)&g_AnimationRestoreType, 0, 3 ); 00183 Camelot.DeclarePref( NULL, _T("AnimationLoopCount"), &g_AnimationLoopCount, 0, 65535 ); 00184 } 00185 00186 // All ok 00187 return TRUE; 00188 } 00189 00190 00191 00192 /******************************************************************************************** 00193 > GIFExportOptions::GIFExportOptions() 00194 00195 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 00196 Created: 29/10/96 00197 Purpose: Default constructor for a GIFExportOptions object to provide GIF export 00198 options 00199 ********************************************************************************************/ 00200 00201 GIFExportOptions::GIFExportOptions() : 00202 DelayIndex(0), 00203 RestoreIndex(0), 00204 m_GlobalPalette(TRUE), 00205 m_LeftOffset(0), 00206 m_TopOffset(0), 00207 m_AnimDelay(g_AnimationDelay), 00208 m_AnimDispose((GIFDisposalMethod) g_AnimationRestoreType), 00209 m_AnimLoop(g_AnimationLoopCount), 00210 m_AnimSize(0, 0), 00211 DelayValueIsDefault(FALSE) 00212 { 00213 g_AnimationLoopCount = 1; 00214 } 00215 00216 00217 00218 /******************************************************************************************** 00219 > GIFExportOptions::GIFExportOptions(const FilterType FilterID, const StringBase* pFilterName) 00220 00221 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 00222 Created: 29/10/96 00223 Purpose: Constructor for a GIFExportOptions object to provide GIF export 00224 options 00225 ********************************************************************************************/ 00226 00227 GIFExportOptions::GIFExportOptions(const FilterType FilterID, const StringBase* pFilterName) 00228 : MaskedFilterExportOptions(_R(IDD_EXPORTBMPOPTS), FilterID, pFilterName), 00229 DelayIndex(0), 00230 RestoreIndex(0), 00231 m_GlobalPalette(TRUE), 00232 m_LeftOffset(0), 00233 m_TopOffset(0), 00234 m_AnimDelay(g_AnimationDelay), 00235 m_AnimDispose((GIFDisposalMethod) g_AnimationRestoreType), 00236 m_AnimLoop(g_AnimationLoopCount), 00237 m_AnimSize(0, 0), 00238 DelayValueIsDefault(FALSE) 00239 { 00240 g_AnimationLoopCount = 1; 00241 } 00242 00243 00244 00245 /******************************************************************************************** 00246 00247 > virtual BOOL GIFExportOptions::CopyFrom(BitmapExportOptions *pSource) 00248 00249 Author: Stefan_Stoykov (Xara Group Ltd) <camelotdev@xara.com> 00250 Created: 19/05/97 00251 Inputs: pSource - the other BitmapExportOptions object to copy the data from 00252 Purpose: Sets the contents of this object from the passed object 00253 See Also: BitmapExportOptions::MakeCopy() 00254 00255 ********************************************************************************************/ 00256 BOOL GIFExportOptions::CopyFrom(BitmapExportOptions *pSource) 00257 { 00258 // copy the base class first 00259 if (!MaskedFilterExportOptions::CopyFrom(pSource)) 00260 return FALSE; 00261 00262 // must be the same class, otherwise the base class function above returns FALSE 00263 GIFExportOptions *pOther = (GIFExportOptions *)pSource; 00264 00265 m_AnimDelay = pOther->m_AnimDelay; 00266 m_AnimDispose = pOther->m_AnimDispose; 00267 m_AnimLoop = pOther->m_AnimLoop; 00268 DelayValueIsDefault = pOther->DelayValueIsDefault; 00269 DelayIndex = pOther->DelayIndex; 00270 RestoreIndex = pOther->RestoreIndex; 00271 m_GlobalPalette = pOther->m_GlobalPalette; 00272 m_LeftOffset = pOther->m_LeftOffset; 00273 m_TopOffset = pOther->m_TopOffset; 00274 m_AnimSize = pOther->m_AnimSize; 00275 00276 return TRUE; 00277 }; 00278 00279 00280 BOOL GIFExportOptions::FileTypeChangeCopyFrom(BitmapExportOptions *pOther) 00281 { 00282 if( !MaskedFilterExportOptions::FileTypeChangeCopyFrom(pOther) ) 00283 return FALSE; 00284 00285 // Since we are not copying from another GIFOptions-based object, then the variables 00286 // in this object must be assigned some default values. 00287 m_AnimDelay = g_AnimationDelay; 00288 m_AnimDispose = (GIFDisposalMethod)g_AnimationRestoreType; 00289 m_AnimLoop = g_AnimationLoopCount; 00290 00291 g_AnimationLoopCount = 1; 00292 DelayValueIsDefault = FALSE; 00293 DelayIndex = 0; 00294 RestoreIndex = 0; 00295 00296 m_GlobalPalette = TRUE; 00297 m_LeftOffset = 0; 00298 m_TopOffset = 0; 00299 00300 // Graeme (14-9-00) - Limit the colour depth to be no more than 8bpp. Otherwise we get 00301 // problems with changing file types in the export dialogue. 00302 if ( GetDepth () > 8 ) 00303 { 00304 SetDepth ( 8 ); 00305 } 00306 00307 return TRUE; 00308 } 00309 00310 00311 /******************************************************************************************** 00312 00313 > virtual BOOL GIFExportOptions::Equal(BitmapExportOptions *pSource) 00314 00315 Author: Stefan_Stoykov (Xara Group Ltd) <camelotdev@xara.com> 00316 Created: 19/05/97 00317 Inputs: pSource - the other BitmapExportOptions object to copy the data from 00318 Purpose: Compares the contents of this and pOther objects 00319 Returns: TRUE, if objects are equal, FALSE otherwise 00320 See Also: BitmapExportOptions::MakeCopy() 00321 00322 ********************************************************************************************/ 00323 /* 00324 BOOL GIFExportOptions::Equal(BitmapExportOptions *pSource) 00325 { 00326 BOOL ok = TRUE; 00327 00328 // compare the base classes first 00329 ok = MaskedFilterExportOptions::Equal(pSource); 00330 00331 // must be the same class, otherwise the base class function above returns FALSE 00332 GIFExportOptions *pOther = (GIFExportOptions *)pSource; 00333 00334 if (ok) ok = (m_AnimDelay == pOther->m_AnimDelay); 00335 if (ok) ok = (m_AnimDispose == pOther->m_AnimDispose); 00336 if (ok) ok = (m_AnimLoop== pOther->m_AnimLoop); 00337 if (ok) ok = (g_AnimationLoopCount == pOther->g_AnimationLoopCount); 00338 if (ok) ok = (DelayValueIsDefault == pOther->DelayValueIsDefault); 00339 if (ok) ok = (DelayIndex== pOther->DelayIndex); 00340 if (ok) ok = (RestoreIndex == pOther->RestoreIndex); 00341 return ok; 00342 }; 00343 */ 00344 00345 /******************************************************************************************** 00346 00347 > virtual BOOL GIFExportOptions::RetrieveDefaults() 00348 00349 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 00350 Created: 29/10/96 00351 Purpose: See BitmapExportOptions for interface details 00352 Notes: Gets GIF specific preferences 00353 00354 ********************************************************************************************/ 00355 BOOL GIFExportOptions::RetrieveDefaults() 00356 { 00357 if (!MaskedFilterExportOptions::RetrieveDefaults()) 00358 { 00359 return FALSE; 00360 } 00361 00362 ERROR2IF(g_AnimationRestoreType != GDM_NONE && g_AnimationRestoreType != GDM_LEAVE && 00363 g_AnimationRestoreType != GDM_BACKTOBACK && g_AnimationRestoreType != GDM_PREVIOUS, 00364 FALSE, "Invalid g_AnimationRestoreType"); 00365 00366 // Ensure that the depth is no more than 8 bits. 00367 if ( GetDepth () > 8 ) 00368 { 00369 this->SetDepth ( 8 ); 00370 } 00371 00372 m_AnimDelay = g_AnimationDelay; 00373 m_AnimDispose = g_AnimationRestoreType; 00374 m_AnimLoop = g_AnimationLoopCount; 00375 00376 // SetMakeTransparent((g_DefaultGIFType >> 1) & 1); 00377 SetMakeInterlaced(g_DefaultGIFType & 1); 00378 00379 return TRUE; 00380 } 00381 00382 00383 /******************************************************************************************** 00384 00385 > virtual BOOL GIFExportOptions::SetAsDefaults() const 00386 00387 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 00388 Created: 29/10/96 00389 Purpose: Provides additional implementation to set GIF specific info as defaults 00390 See Also: BitmapExportOptions::SetAsDefaults() 00391 00392 ********************************************************************************************/ 00393 BOOL GIFExportOptions::SetAsDefaults() const 00394 { 00395 if (!MaskedFilterExportOptions::SetAsDefaults()) 00396 { 00397 return FALSE; 00398 } 00399 00400 g_AnimationDelay = m_AnimDelay; 00401 00402 g_AnimationRestoreType = m_AnimDispose; 00403 g_AnimationLoopCount = m_AnimLoop; 00404 00405 g_DefaultGIFType = WantTransparent() ? 2 : 0; 00406 g_DefaultGIFType |= WantInterlaced() ? 1 : 0; 00407 00408 return TRUE; 00409 } 00410 00411 00412 00413 /******************************************************************************************** 00414 > virtual BOOL GIFExportOptions::Write(CXaraFileRecord* pRec) 00415 00416 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00417 Created: 21/2/00 00418 Inputs: pRec --- record to write 00419 Returns: TRUE if successful. 00420 Purpose: Writes this object to the given record. 00421 SeeAlso: GIFExportOptions::Read 00422 ********************************************************************************************/ 00423 00424 BOOL GIFExportOptions::Write(CXaraFileRecord* pRec) 00425 { 00426 return MaskedFilterExportOptions::Write(pRec) && 00427 pRec->WriteUINT32(DelayIndex) && 00428 pRec->WriteUINT32(RestoreIndex) && 00429 pRec->WriteBYTE((BYTE) !!m_GlobalPalette) && 00430 pRec->WriteUINT32(m_LeftOffset) && 00431 pRec->WriteUINT32(m_TopOffset) && 00432 pRec->WriteUINT32((UINT32) m_AnimDelay) && 00433 pRec->WriteINT16((INT16) m_AnimDispose) && 00434 pRec->WriteUINT32(m_AnimLoop) && 00435 pRec->WriteCoord((const DocCoord&) m_AnimSize) && 00436 pRec->WriteBYTE((BYTE) !!DelayValueIsDefault); 00437 } 00438 00439 00440 00441 /******************************************************************************************** 00442 > virtual BOOL GIFExportOptions::Read(CXaraFileRecord* pRec) 00443 00444 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00445 Created: 21/2/00 00446 Inputs: pRec --- record to read 00447 Returns: TRUE if successful. 00448 Purpose: Reads this object from the given record. 00449 SeeAlso: GIFExportOptions::Write 00450 ********************************************************************************************/ 00451 00452 BOOL GIFExportOptions::Read(CXaraFileRecord* pRec) 00453 { 00454 m_GlobalPalette = DelayValueIsDefault = FALSE; 00455 return MaskedFilterExportOptions::Read(pRec) && 00456 pRec->ReadUINT32((UINT32*) &DelayIndex) && 00457 pRec->ReadUINT32((UINT32*) &RestoreIndex) && 00458 pRec->ReadBYTE((BYTE*) &m_GlobalPalette) && 00459 pRec->ReadUINT32((UINT32*) &m_LeftOffset) && 00460 pRec->ReadUINT32((UINT32*) &m_TopOffset) && 00461 pRec->ReadUINT32((UINT32*) &m_AnimDelay) && 00462 pRec->ReadINT16((INT16*) &m_AnimDispose) && 00463 pRec->ReadUINT32((UINT32*) &m_AnimLoop) && 00464 pRec->ReadCoord((DocCoord*) &m_AnimSize) && 00465 pRec->ReadBYTE((BYTE*) &DelayValueIsDefault); 00466 } 00467 00468 00469 00470 /******************************************************************************************** 00471 00472 > CENTISECONDS GIFExportOptions::GetAnimationDelay() const 00473 00474 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 00475 Created: 29/10/96 00476 Returns: The delay desired for animated GIFs 00477 Purpose: Support function to obtain export options 00478 00479 ********************************************************************************************/ 00480 CENTISECONDS GIFExportOptions::GetAnimationDelay() 00481 { 00482 // return m_AnimDelay; 00483 UINT32 Delay = m_pBitmapList[DelayIndex]->GetDelay(); 00484 DelayIndex++; 00485 return Delay; 00486 } 00487 00488 00489 /******************************************************************************************** 00490 00491 > BOOL GIFExportOptions::SetAnimationDelay(CENTISECONDS Delay) 00492 00493 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 00494 Created: 29/10/96 00495 Inputs: Delay : The desired delay to be set in the animated GIF 00496 Returns: TRUE if set successfully 00497 FALSE otherwise 00498 Purpose: Support function to set up information for the ensuing export 00499 See Also: GetAnimationDelay() 00500 00501 ********************************************************************************************/ 00502 BOOL GIFExportOptions::SetAnimationDelay(CENTISECONDS Delay) 00503 { 00504 m_AnimDelay = Delay; 00505 return TRUE; 00506 } 00507 00508 00509 /******************************************************************************************** 00510 00511 > GIFDisposalMethod GIFExportOptions::GetAnimationRestore() const 00512 00513 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 00514 Created: 29/10/96 00515 Returns: The disposal method to be used in animated GIFs 00516 Purpose: Support function to obtain export options 00517 00518 ********************************************************************************************/ 00519 GIFDisposalMethod GIFExportOptions::GetAnimationRestore() 00520 { 00521 // return m_AnimDispose; 00522 GIFDisposalMethod Restore = m_pBitmapList[RestoreIndex]->GetActualBitmap()->GetAnimationRestoreType(); 00523 RestoreIndex++; 00524 return Restore; 00525 } 00526 00527 00528 /******************************************************************************************** 00529 00530 > BOOL GIFExportOptions::SetAnimationRestore(const GIFDisposalMethod& DisposalMethod) 00531 00532 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 00533 Created: 29/10/96 00534 Inputs: DisposalMethod : The desired DisposalMethod to be set in the animated GIF 00535 Returns: TRUE if set successfully 00536 FALSE otherwise 00537 Purpose: Support function to set up information for the ensuing export 00538 See Also: GetAnimationRestore(), enum GIFDisposalMethod 00539 00540 ********************************************************************************************/ 00541 BOOL GIFExportOptions::SetAnimationRestore(const GIFDisposalMethod& DisposalMethod) 00542 { 00543 m_AnimDispose = DisposalMethod; 00544 return TRUE; 00545 } 00546 00547 00548 /******************************************************************************************** 00549 00550 > UINT32 GIFExportOptions::GetAnimationLoopCount() const 00551 00552 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 00553 Created: 29/10/96 00554 Returns: How loopy our animated GIF will be 00555 Purpose: Support function to obtain export options 00556 See Also: SetAnimationLoopCount() 00557 00558 ********************************************************************************************/ 00559 UINT32 GIFExportOptions::GetAnimationLoopCount() const 00560 { 00561 return m_AnimLoop; 00562 } 00563 00564 00565 /******************************************************************************************** 00566 00567 > BOOL GIFExportOptions::SetAnimationLoopCount(UINT32 LoopCount) 00568 00569 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 00570 Created: 29/10/96 00571 Inputs: LoopCount : For Animated GIFs: 0 = Repeat forever, 1 = One shot animation. 00572 n = Plays animation n times. 00573 Returns: TRUE if set successfully 00574 FALSE otherwise 00575 Purpose: Support function to set up information for the ensuing export 00576 See Also: GetAnimationLoopCount() 00577 00578 ********************************************************************************************/ 00579 BOOL GIFExportOptions::SetAnimationLoopCount(UINT32 LoopCount, BOOL Value) 00580 { 00581 if(Value) 00582 { 00583 m_AnimLoop = ZERO; 00584 return TRUE; 00585 } 00586 else 00587 { 00588 m_AnimLoop = LoopCount; 00589 return TRUE; 00590 } 00591 } 00592 00593 00594 00595 00596 00597 /******************************************************************************************** 00598 00599 Preference: ExportGIFtype 00600 Section: Filters 00601 Range: 0 to 3 00602 Purpose: Allows a default GIF type to be remembered for the next export GIF 00603 operation. 00604 SeeAlso: - 00605 00606 ********************************************************************************************/ 00607 00608 00609 /******************************************************************************************** 00610 00611 > TI_GIFFilter::TI_GIFFilter() 00612 00613 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00614 Created: 24/4/95 00615 Purpose: Constructor for an TI_GIFFilter object. The object should be initialised 00616 before use. 00617 SeeAlso: TI_GIFFilter::Init 00618 00619 ********************************************************************************************/ 00620 00621 TI_GIFFilter::TI_GIFFilter() : MaskedFilter() 00622 { 00623 ImportMsgID = _R(IDN_IMPORTMSG_GIF); 00624 Flags.CanImport = TRUE; 00625 #ifndef STANDALONE 00626 Flags.CanExport = TRUE; 00627 Flags.CanExportMultipleImages = TRUE; 00628 #else 00629 Flags.CanExport = FALSE; 00630 Flags.CanExportMultipleImages = FALSE; 00631 #endif 00632 FilterID = FILTERID_TI_GIF; 00633 00634 ExportMsgID = _R(IDN_EXPORTMSG_GIF); // "Preparing GIF file..." 00635 00636 ExportingMsgID = _R(IDN_EXPORTINGMSG_GIF); // "Exporting GIF file..." 00637 00638 // Special Mask prepartion stage ID 00639 Export2ndStageMsgID = _R(IDN_MASKINGMSG_GIF); // "Preparing mask for GIF file..." 00640 00641 ExportRegion = NULL; 00642 00643 // Initalise flags 00644 m_DoingAnimation = FALSE; 00645 m_AnimationFrame = 0; 00646 m_LeftOffset = 0; 00647 m_TopOffset = 0; 00648 00649 m_PreviousMethod = GDM_BACKTOBACK; 00650 } 00651 00652 /******************************************************************************************** 00653 00654 > BOOL TI_GIFFilter::Init() 00655 00656 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00657 Created: 24/4/95 00658 Returns: TRUE if the filter was initialised ok, FALSE otherwise. 00659 Purpose: Initialise an TI_GIFFilter object. 00660 Errors: Will fail if not enough memory to initialise. 00661 SeeAlso: EPSStack 00662 00663 ********************************************************************************************/ 00664 00665 BOOL TI_GIFFilter::Init() 00666 { 00667 // Get the OILFilter object 00668 pOILFilter = new GIFOILFilter(this); 00669 if (pOILFilter==NULL) 00670 return FALSE; 00671 00672 // Load the description strings 00673 FilterName.Load(_R(IDN_FILTERNAME_GIF)); 00674 FilterInfo.Load(_R(IDN_GIF_FILTERINFO)); 00675 00676 if (!GIFExportOptions::Declare()) 00677 { 00678 return FALSE; 00679 } 00680 00681 // All ok 00682 return TRUE; 00683 } 00684 00685 00686 /******************************************************************************************** 00687 00688 > virtual BitmapImportOptions* TI_GIFFilter::CreateImportOptions() const 00689 00690 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 00691 Created: 29/10/96 00692 Purpose: Overrides base class to provide GIF specific options 00693 00694 ********************************************************************************************/ 00695 BitmapImportOptions* TI_GIFFilter::CreateImportOptions() const 00696 { 00697 GIFImportOptions* pOptions = new GIFImportOptions; 00698 return (BitmapImportOptions*)pOptions; 00699 } 00700 00701 00702 00703 /******************************************************************************************** 00704 00705 > virtual BOOL TI_GIFFilter::BOOL ReadFromFile(OILBitmap* pOilBitmap, 00706 BaseCamelotFilter* pFilter, 00707 CCLexFile* pFile, BOOL IsCompressed); 00708 00709 00710 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00711 Created: 20/6/96 00712 Inputs: pOilBitmap pointer to the oil bitmap data to be filled in 00713 pFilter - the BaseCamelotFilter which provides functions like progress update 00714 (not used at the moment 20/01/97) 00715 pFile - the CCFile class to use to read the data from 00716 IsCompressed - Flag to say the bitmap is compressed or not. 00717 Outputs: Will have filled in BMInfo pointer to the bitmap header to fill in 00718 BMBytes pointer to the bitmap data to fill in 00719 Purpose: Actually does the process of reading a bitmap from a file. 00720 Inherited classes override this to read in different file formats. 00721 It is used by the web/native filters to pull out a bitmap definition from 00722 inside a bitmap definition record. 00723 It is also used for extracting previews. 00724 IsCompressed is only used for BMP/BMPZIP type bitmaps at present. 00725 Assumes: 00726 pFile has already been opened up for reading 00727 pFilter has been set up for reading the data e.g. progress bar 00728 Returns: TRUE if worked, FALSE if failed. 00729 00730 ********************************************************************************************/ 00731 00732 BOOL TI_GIFFilter::ReadFromFile( OILBitmap* pOilBitmap, BaseCamelotFilter* pFilter, 00733 CCLexFile* pFile, BOOL IsCompressed) 00734 { 00735 ERROR2IF(pOilBitmap == NULL,FALSE,"TI_GIFFilter::ReadFromFile null OilBitmap pointer"); 00736 // no pFilter means we don't get a progress WEBSTER-Martin-20/01/97 00737 // as we are calling this from BaseFileDialog::GetPreviewBitmapFromFile we don't have 00738 // a BaseCamelotFilter. However GIFUtil::ReadImage expects a 100% progress bar. 00739 // ERROR2IF(pFilter == NULL,FALSE,"TI_GIFFilter::ReadFromFile null pFilter pointer"); 00740 ERROR2IF(pFile == NULL,FALSE,"TI_GIFFilter::ReadFromFile null pFile pointer"); 00741 00742 if (!pFilter) 00743 BeginSlowJob(-1); // GIFUtil::ReadImage expects a progress bar. 00744 00745 // Try to import bitmap as usual binary BMP file. 00746 CWxBitmap* pWBitmap = (CWxBitmap*) pOilBitmap; 00747 00748 LPBITMAPINFO *pInfo = &(pWBitmap->BMInfo); 00749 LPBYTE *pBytes = &(pWBitmap->BMBytes); 00750 00751 // Set a default transparent colour 00752 INT32 TransColour = -1; 00753 SetTransColour(TransColour); 00754 00755 // Blank the offsets just in case 00756 m_LeftOffset = 0; 00757 m_TopOffset = 0; 00758 00759 // Read from file, no header and using pFilter for progress bar updates 00760 // 20/01/97 In fact pFilter is not used so NULL ptr ok 00761 if (!GIFUtil::ReadFromFile(pFile, pInfo, pBytes, &TransColour, NULL, pFilter)) 00762 { 00763 if (!pFilter) 00764 EndSlowJob(); 00765 return FALSE; 00766 } 00767 00768 SetTransColour(TransColour); 00769 UINT32 Bpp = pWBitmap->GetBPP(); 00770 if (TransColour != -1 && Bpp <= 8) 00771 pOilBitmap->SetTransparencyIndex(TransColour); 00772 00773 SetLastBitmap(); // can only import one bitmap at the moment 00774 00775 if (!pFilter) 00776 EndSlowJob(); 00777 00778 // Everything went ok and we imported the bitmap ok 00779 return TRUE; 00780 } 00781 00782 /******************************************************************************************** 00783 00784 > BOOL TI_GIFFilter::ReadFromFile(OILBitmap* pOilBitmap) 00785 00786 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00787 Created: 18/8/95 00788 Inputs: pOilBitmap pointer to the oil bitmap data to be filled in 00789 Outputs: Will have filled in BMInfo pointer to the bitmap header to fill in 00790 BMBytes pointer to the bitmap data to fill in 00791 Purpose: Actually does the process of reading a bitmap from a file. 00792 Inherited classes override this to read in different file formats. 00793 00794 Returns: TRUE if worked, FALSE if failed. 00795 00796 ********************************************************************************************/ 00797 00798 BOOL TI_GIFFilter::ReadFromFile(OILBitmap* pOilBitmap) 00799 { 00800 ERROR2IF(pOilBitmap == NULL,FALSE,"TI_GIFFilter::ReadFromFile null OilBitmap pointer"); 00801 00802 // Try to import the bitmap as a GIF file. 00803 00804 CCLexFile* pImportFile = GetImportFile(); 00805 ERROR2IF(pImportFile==NULL,FALSE,"TI_GIFFilter::ReadFromFile - No import file"); 00806 00807 UINT32 ImportMsgId = GetImportMsgID(); 00808 String_64 ProgressString(ImportMsgId); 00809 ProgressString = GetImportProgressString(pImportFile, ImportMsgId); 00810 00811 // Set a default transparent colour 00812 INT32 TransColour = -1; 00813 SetTransColour(TransColour); 00814 INT32 nBitmapToRead = GetBitmapNumber(); 00815 00816 CWxBitmap* pWBitmap = (CWxBitmap*)pOilBitmap; 00817 00818 LPBITMAPINFO *pInfo = &(pWBitmap->BMInfo); 00819 LPBYTE *pBytes = &(pWBitmap->BMBytes); 00820 // Receives the Bitmap delay/Restore value from the Import. 00821 UINT32 Delay=0; 00822 GIFDisposalMethod Restore = GDM_LEAVE; 00823 00824 // Blank the offsets just in case 00825 m_LeftOffset = 0; 00826 m_TopOffset = 0; 00827 00828 // The GIF filter liked it very much and so use it, showing progress bar 00829 if (GIFUtil::ReadFromFile(pImportFile, pInfo, pBytes, &TransColour,nBitmapToRead, &ProgressString, NULL, 00830 &Delay, &Restore, &m_LeftOffset, &m_TopOffset)) 00831 { 00832 // Set the Delay\Restore value of the OILBitmap. 00833 pOilBitmap->SetBitmapAnimDelay(Delay); 00834 pOilBitmap->SetAnimationRestoreType(Restore); 00835 00836 // Set the offset positions 00837 pOilBitmap->SetLeftOffset(m_LeftOffset); 00838 pOilBitmap->SetTopOffset(m_TopOffset); 00839 00840 // Pass on the transparent colour that we found in the loading process 00841 // -1 if none found. 00842 SetTransColour(TransColour); 00843 pOilBitmap->SetTransparencyIndex(TransColour); 00844 if (nBitmapToRead == -1) 00845 SetLastBitmap(); 00846 else 00847 SetBitmapNumber(nBitmapToRead); 00848 return TRUE; 00849 } 00850 00851 return FALSE; 00852 } 00853 00854 /******************************************************************************************** 00855 00856 > BOOL TI_GIFFilter::GetDragAndDropTranslation(ImportPosition *pPos, DocRect BoundsRect, 00857 Coord* Offset) 00858 00859 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> based on Tim function 00860 Created: 15/5/97 00861 Inputs: pSpread - the spread to check against. 00862 BoundsRect - the bounding rectangle to check (in spread coordinates). 00863 Outputs: Offset - 00864 Returns: TRUE if the bounding rectangle is smaller than the spread => Offset now 00865 contains the translation necessary to position the objects correctly. 00866 FALSE if bounding rectangle is bigger than the spread, or pPos was NULL. 00867 In either case, a FALSE return results in Offset containing (0,0). 00868 Purpose: Given an drag'n'drop point (in pPos), calculate the translation necessary 00869 to position the imported objects at this position on the spread. It ensures 00870 that bounding rectangles smaller than the spread are wholly contained within 00871 the spread. i.e. if you drag a file right to the edge of a spread, the 00872 translation will move it closer to the centre of the spread so that it is 00873 wholly contained within the spread. 00874 00875 Used by the import filters for drag'n'drop to ensure that after the 00876 imported objects are translated to the drop point, they are all still 00877 on the spread. 00878 SeeAlso: Filter::DoImport 00879 00880 ********************************************************************************************/ 00881 00882 BOOL TI_GIFFilter::GetDragAndDropTranslation(ImportPosition *pPos, DocRect BoundsRect, 00883 Coord* Offset) 00884 { 00885 // First check to se if we actually have a drag and drop point. 00886 if (pPos == NULL || pPos->pSpread == NULL) 00887 { 00888 // No - set offset to 0 and return FALSE to indicate we can't cope with this. 00889 Offset->x = 0; 00890 Offset->y = 0; 00891 return FALSE; 00892 } 00893 00894 // Get the spread's bounding rectangle and convert it to spread coords. 00895 DocRect SpreadRect = pPos->pSpread->GetPasteboardRect(); 00896 pPos->pSpread->DocCoordToSpreadCoord(&SpreadRect); 00897 00898 // Now check that the bounding rectangle is small enough to fit on the spread... 00899 if ((BoundsRect.Width() > SpreadRect.Width()) || 00900 (BoundsRect.Height() > SpreadRect.Height())) 00901 { 00902 // No - set offset to 0 and return FALSE to indicate we can't cope with this. 00903 Offset->x = 0; 00904 Offset->y = 0; 00905 return FALSE; 00906 } 00907 00908 // Bounding box should be centred on drop point 00909 // This is the default way of doing it. We actually want the bounding box of the animation 00910 // centered on the drop point with the inidividual frames positioned inside this. 00911 // The x and y offsets are handled latter so we must just position the rectangle to the left 00912 // of the main animations' bounding box 00913 UINT32 GIFWidth = GIFUtil::GetGlobalWidth(); 00914 UINT32 GIFHeight = GIFUtil::GetGlobalHeight(); 00915 if (GIFWidth > 0 && GIFHeight > 0) 00916 { 00917 // GIFs have no concept of DPI so assume 96 00918 const double dpi = 96.0; 00919 const INT32 PixelSize = (INT32) ((72000.0 / dpi) + 0.5); // Size of output pixel in millipoints 00920 00921 // We have been told how many pixels the animation is in size so we should just 00922 // multiply by 72000 millipoints per inch and then divide by the pixels per inch or dpi. 00923 MILLIPOINT AnimationWidth = (INT32) (((GIFWidth * 72000.0) / dpi) + 0.5); 00924 MILLIPOINT AnimationHeight = (INT32) (((GIFHeight * 72000.0) / dpi) + 0.5); 00925 // Add these offsets onto the one that is passed in 00926 DocCoord Centre; 00927 Centre.x = (AnimationWidth) / 2; 00928 Centre.y = (AnimationHeight) / 2; 00929 00930 // If the height or width is an odd number then we may be positioning on half pixel 00931 // boundaries. So snap to the nearest whole pixel boundary. 00932 Centre.x -= Centre.x % PixelSize; 00933 Centre.y -= Centre.y % PixelSize; 00934 00935 Offset->x = -Centre.x; 00936 Offset->y = -Centre.y; 00937 00938 // The bitmaps will now be so that their bottom left hand corner is at the corner 00939 // of the animation. So we need to move it up so that its top left hand corner is 00940 // at the top left of the animation. 00941 Offset->y += AnimationHeight - (BoundsRect.hi.y - BoundsRect.lo.y); 00942 } 00943 else 00944 { 00945 // No - set offset to 0 and return FALSE to indicate we can't cope with this. 00946 Offset->x = 0; 00947 Offset->y = 0; 00948 } 00949 00950 // Transform the bounding rect to see if it's off the spread. 00951 BoundsRect.Translate(Offset->x, Offset->y); 00952 00953 // If it's off the spread - limit it to the edge of the spread: 00954 00955 // (a) Horizontal adjustment 00956 if (BoundsRect.lo.x < SpreadRect.lo.x) 00957 Offset->x += (SpreadRect.lo.x - BoundsRect.lo.x); 00958 else if (BoundsRect.hi.x > SpreadRect.hi.x) 00959 Offset->x -= (BoundsRect.hi.x - SpreadRect.hi.x); 00960 00961 // (b) Vertical adjustment 00962 if (BoundsRect.lo.y < SpreadRect.lo.y) 00963 Offset->y += (SpreadRect.lo.y - BoundsRect.lo.y); 00964 else if (BoundsRect.hi.y > SpreadRect.hi.y) 00965 Offset->y -= (BoundsRect.hi.y - SpreadRect.hi.y); 00966 00967 // Whatever happened, we can fit it on the spread. 00968 return TRUE; 00969 } 00970 00971 /******************************************************************************************** 00972 00973 > virtual BOOL TI_GIFFilter::SetFlagsFromBitmap(Layer * pLayer, KernelBitmap * pBitmap, 00974 UINT32 nBitmapToRead) 00975 00976 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00977 Created: 20/5/97 00978 Inputs: pLayer the layer that the bitmap is being put on 00979 pBitmap the bitmap being placed on the layer 00980 nBitmapToRead the number of the bitmap in the sequence 00981 Returns: TRUE if was ok, FALSE otherwise. 00982 Purpose: When loading in multiple bitmaps and placing them on new layers, we should 00983 give the filter an opportunity to set the layer flags from the bitmap. In the 00984 case of a GIF filter this would allow it to set the solid and overlay flags. 00985 00986 ********************************************************************************************/ 00987 00988 BOOL TI_GIFFilter::SetFlagsFromBitmap(Layer * pLayer, KernelBitmap * pBitmap, 00989 UINT32 nBitmapToRead) 00990 { 00991 if (pBitmap && pLayer) 00992 { 00993 // transfer the disposal method from the bitmap to the layer 00994 GIFDisposalMethod method = pBitmap->GetAnimationRestoreType(); 00995 // First frame is always restore background 00996 if (nBitmapToRead == 1) 00997 m_PreviousMethod = GDM_BACKTOBACK; 00998 00999 // REM use the previous frame's restore method, not this one! 01000 switch (m_PreviousMethod) 01001 { 01002 case GDM_NONE: 01003 case GDM_LEAVE: 01004 // Always set frame overlay 01005 pLayer->SetOverlay(TRUE); 01006 // As we are setting overlay, solid is not required 01007 pLayer->SetSolid(FALSE); 01008 // This seems to work but may need some extra clauses.... 01009 //if (nBitmapToRead == 1) 01010 // pLayer->SetSolid(TRUE); 01011 //else 01012 // pLayer->SetSolid(FALSE); 01013 break; 01014 case GDM_PREVIOUS: 01015 case GDM_BACKTOBACK: 01016 // Always set frame overlay false and solid false 01017 pLayer->SetOverlay(FALSE); 01018 pLayer->SetSolid(FALSE); 01019 break; 01020 } 01021 01022 // Note the new restore method for the next frame 01023 m_PreviousMethod = method; 01024 01025 // transfer the delay from the bitmap to the layer 01026 UINT32 delay = pBitmap->GetDelay(); 01027 pLayer->SetFrameDelay(delay); 01028 } 01029 01030 return TRUE; 01031 } 01032 01033 /******************************************************************************************** 01034 01035 > BOOL TI_GIFFilter::AddOffsetFromBitmap(DocCoord * pOffset) 01036 01037 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01038 Created: 15/5/97 01039 Inputs: pOffset the present offset in the bitmap 01040 Returns: TRUE if was ok, FALSE otherwise. 01041 Purpose: When loading in a bitmap, the bitmap definition may conatin an offset. We need 01042 to add this to the offset that we are given so that the bitmap is loaded at 01043 the correct position. 01044 This uses the class variables that were set up during the GIF loading process 01045 to add the offset onto the import position. 01046 01047 ********************************************************************************************/ 01048 01049 BOOL TI_GIFFilter::AddOffsetFromBitmap(DocCoord * pOffset) 01050 { 01051 if (pOffset && m_LeftOffset >= 0 && m_TopOffset >= 0) 01052 { 01053 // GIFs have no concept of DPI so assume 96 01054 const UINT32 dpi = 96; 01055 // We have been told how many pixels to offset by so we should just 01056 // multiply by 72000 millipoints per inch and then divide by the pixels per inch or dpi. 01057 MILLIPOINT ExtraOffsetX = (m_LeftOffset * 72000) / dpi; 01058 MILLIPOINT ExtraOffsetY = (m_TopOffset * 72000) / dpi; 01059 // Add these offsets onto the one that is passed in 01060 pOffset->x += ExtraOffsetX; 01061 // Remember, we have been told the offset from the top, so we need to move downwards 01062 pOffset->y -= ExtraOffsetY; 01063 } 01064 01065 return TRUE; 01066 } 01067 01068 /******************************************************************************************** 01069 01070 > virtual BOOL TI_GIFFilter::SetAnimationPropertiesFromLoaded(Spread * pSpread) 01071 01072 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01073 Created: 8/7/97 01074 Inputs: pSpread the spread that the bitmaps have been put on 01075 Returns: TRUE if was ok, FALSE otherwise. 01076 Purpose: When loading in multiple bitmaps and placing them on new layers, we should 01077 give the filter an opportunity after all the bitmaps have been loaded, to go 01078 and look at the bitmaps and set the animation properties accordingly. 01079 In the case of a GIF filter this would allow it to set the dithering to none 01080 and the palette to something closer to what has been loaded. 01081 Assumes that each bitmap has been added to a separate layer and that the 01082 referenced bitmap in the layer is set to this loaded bitmap. 01083 01084 ********************************************************************************************/ 01085 01086 BOOL TI_GIFFilter::SetAnimationPropertiesFromLoaded(Spread * pSpread) 01087 { 01088 ERROR2IF(pSpread == NULL,FALSE,"SetAnimationPropertiesFromLoaded pSpread = NULL"); 01089 01090 // Find out about the palettes that the bitmaps have 01091 BOOL SamePalettes = FALSE; 01092 BOOL OurBrowserPalette = FALSE; 01093 BOOL AllHaveBitmaps = FALSE; 01094 BOOL AllWithinCount = FALSE; 01095 UINT32 PaletteEntries = 0; 01096 CheckSingleBitmapsOnSpread(pSpread, &SamePalettes, &OurBrowserPalette, &AllHaveBitmaps, 01097 &AllWithinCount, &PaletteEntries); 01098 01099 // Grab the present animation properties from the spread 01100 AnimPropertiesParam *pProperties = &pSpread->GetSpreadAnimPropertiesParam(); 01101 if (pProperties != NULL) 01102 { 01103 // Make any changes that we require 01104 pProperties->SetDither(XARADITHER_NONE); 01105 01106 if (SamePalettes && OurBrowserPalette) 01107 { 01108 // Set ourselves a global browser palette 01109 pProperties->SetPaletteCols(PALCOL_BROWSER); 01110 pProperties->SetPalette(PAL_GLOBAL); 01111 } 01112 else if (SamePalettes) 01113 { 01114 // Set ourselves a global optimised palette 01115 pProperties->SetPaletteCols(PALCOL_OPTIMIZED); 01116 pProperties->SetPalette(PAL_GLOBAL); 01117 if (PaletteEntries > 0) 01118 pProperties->SetNumColsInPalette(PaletteEntries); 01119 } 01120 else 01121 { 01122 // Set ourselves a local optimised palette 01123 pProperties->SetPaletteCols(PALCOL_OPTIMIZED); 01124 pProperties->SetPalette(PAL_LOCAL); 01125 // Ensure that the optimised palette contains 01126 if (PaletteEntries > 0) 01127 pProperties->SetNumColsInPalette(PaletteEntries); 01128 } 01129 01130 // Put back the new animation properties 01131 pSpread->SetSpreadAnimPropertiesParam(*pProperties); 01132 01133 // Tell anybody that is interested about the changes 01134 BROADCAST_TO_ALL(SpreadMsg(pSpread, SpreadMsg::ANIMATIONPROPERTIESCHANGED)); 01135 } 01136 01137 return TRUE; 01138 } 01139 01140 /******************************************************************************************** 01141 01142 > virtual void TI_GIFFilter::CleanUpAfterExport() 01143 01144 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01145 Created: 25/9/95 01146 Purpose: Cleans up the memory allocated at the end of Exporting or when exporting has 01147 been aborted for some reason. Does its cleaning up and then calls the 01148 baseclass version to do its stuff, - used 01149 when the import process ends, either normally or abnormally. Override if 01150 extra things are required. 01151 SeeAlso: BaseBitmapFilter::PrepareToExport(); BaseBitmapFilter::CleanUpAfterExport(); 01152 Scope: Protected 01153 01154 ********************************************************************************************/ 01155 01156 void TI_GIFFilter::CleanUpAfterExport() 01157 { 01158 // Called right at the end of th