frameops.cpp

Go to the documentation of this file.
00001 // $Id: frameops.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 // The Frame Operations source file
00100 
00101 /*
00102 */
00103 
00104 #include "camtypes.h"
00105 #include "frameops.h"
00106 
00107 //#include "prevwres.h"     // _R(IDS_DISPLAY_FRAME_GALLERY) _R(IDD_ANIMATIONBAR) ...
00108 #include "sgframe.h"        // FrameSGallery
00109 //#include "spread.h"           // Spread - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "simon.h"            // _R(IDS_NO_DOC)
00111 //#include "app.h"          // GetApplication() - in camtypes.h [AUTOMATICALLY REMOVED]
00112 //#include "fixmem.h"           // CCMalloc - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "prevwdlg.h"       // OPTOKEN_PREVIEWDIALOG
00114 #include "grndbmp.h"        // GRenderBitmap
00115 #include "filedlgs.h"       // ExportFileDialog
00116 //#include "tim.h"          // _R(IDT_CANT_FIND_FILTER)
00117 //#include "oilfltrs.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00118 //#include "nev.h"          // _R(IDN_USER_CANCELLED)
00119 #include "layermsg.h"       // layer messages REDRAW_LAYER
00120 
00121 //#include "accures.h"      // _R(IDN_FILTEREXT_GIF)
00122 
00123 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00124 
00125 #include "nodebmp.h"        // NodeBitmap
00126 #include "insertnd.h"       // InsertionNode
00127 #include "aprps.h"
00128 
00129 // browser preview
00130 #include "fileutil.h"       // FileUtil::GetTemporaryPathName()
00131 #include "cbmpdata.h"       // CBitmapData
00132 
00133 #include "palman.h"         // MakePaletteBrowserCompatible
00134 
00135 //#include "xshelpid.h" //For the help ID
00136 
00137 #include "gpalopt.h" // for the palette optimiser
00138 #include "mrhbits.h"
00139 #include "page.h"
00140 //#include "quality.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00141 
00142 DECLARE_SOURCE("$Revision: 1282 $");
00143 
00144 CC_IMPLEMENT_DYNCREATE(OpSelectStartFrame,  OpLayerGalChange);
00145 CC_IMPLEMENT_DYNCREATE(OpSelectEndFrame,    OpLayerGalChange);
00146 CC_IMPLEMENT_DYNCREATE(OpSelectPrevFrame,   OpLayerGalChange);
00147 CC_IMPLEMENT_DYNCREATE(OpSelectNextFrame,   OpLayerGalChange);
00148 CC_IMPLEMENT_DYNCREATE(OpCreateNewFrame,    OpLayerGalChange);
00149 CC_IMPLEMENT_DYNCREATE(OpCopyFrame,         OpLayerGalChange);
00150 CC_IMPLEMENT_DYNCREATE(OpDeleteFrame,       OpLayerGalChange);
00151 
00152 CC_IMPLEMENT_DYNCREATE(OpFrameProperties, Operation);
00153 CC_IMPLEMENT_DYNCREATE(OpAnimationProperties, Operation);
00154 
00155 
00156 PORTNOTE("other", "Removed GrabFrameFilter, OpGrabFrame, OpGrabAllFrames")
00157 #ifndef EXCLUDE_FROM_XARALX
00158 CC_IMPLEMENT_DYNAMIC(GIFAnimationExportParam,   BitmapExportParam);
00159 CC_IMPLEMENT_DYNCREATE(OpGrabFrame, Operation);
00160 CC_IMPLEMENT_DYNCREATE(OpGrabAllFrames, OpGrabFrame);
00161 CC_IMPLEMENT_DYNAMIC(GrabFrameFilter, MakeBitmapFilter);
00162 CC_IMPLEMENT_DYNCREATE(OpSaveAnimatedGIF, OpGrabAllFrames);
00163 CC_IMPLEMENT_DYNCREATE(OpBrowserPreview, OpSaveAnimatedGIF);
00164 
00165 BOOL OpGrabAllFrames::ms_ForceRefreshOfAllFrames = FALSE;
00166 #endif
00167 
00168 // This will get Camelot to display the filename and linenumber of any memory allocations
00169 // that are not released at program exit
00170 // This line mustn't go before any CC_IMPLEMENT_... macros
00171 #define new CAM_DEBUG_NEW
00172 
00173 
00174 //------------------------------------------------------------------------------------------
00175 // Methods for the OpSelectStartFrame
00176 //------------------------------------------------------------------------------------------
00177 
00178 /********************************************************************************************
00179 
00180 >   OpState OpSelectStartFrame::GetState(String_256*, OpDescriptor*)
00181 
00182     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00183     Created:    21/4/97
00184     Inputs:     Name of the OpDescriptor being queried
00185     Outputs:    The string to show to the user
00186     Returns:    The state of the OpSelectStartFrame operation
00187     Purpose:    For finding the OpSelectStartFrame's state. 
00188     Errors:     -
00189     SeeAlso:    -
00190 
00191 ********************************************************************************************/
00192 
00193 OpState OpSelectStartFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc)
00194 {
00195     OpState OpSt;  
00196 
00197     // Is there a selected spread?
00198     Spread * pSpread = Document::GetSelectedSpread();
00199     if (pSpread)
00200     {
00201         // yes, so check if there is an active layer
00202         Layer * pLayer = pSpread->FindActiveLayer();
00203         Layer * pPrevLayer = pLayer->FindPrevLayer();
00204         // The previous layer should really be a frame layer but we cannot guarantee that but
00205         // it mustn't be a guide, a page background or a background layer.
00206         while ( pPrevLayer && !pPrevLayer->IsPseudoFrame())
00207         {
00208             pPrevLayer = pPrevLayer->FindPrevLayer();
00209         }
00210 
00211         if (pLayer && pPrevLayer)
00212         {
00213             // Yes, so we are allowed to move to the next one
00214             OpSt.Greyed = FALSE;
00215         }
00216         else
00217         {
00218             // No, so we are greyed
00219             OpSt.Greyed = TRUE;
00220         }
00221     }
00222     else
00223     {
00224         // No selected spread, so we are greyed
00225         OpSt.Greyed = TRUE;
00226     }
00227 
00228     return OpSt;   
00229 }
00230 
00231 /********************************************************************************************
00232 
00233 >   void OpSelectStartFrame::Do(OpDescriptor * pOpDesc)
00234 
00235     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00236     Created:    21/4/97
00237     Inputs:     OpDescriptor (unused)
00238     Outputs:    -
00239     Returns:    -
00240     Purpose:    Tries to select the bottom most animation frame (i.e. layer).
00241     Errors:     -
00242     SeeAlso:    -
00243 
00244 ********************************************************************************************/
00245 
00246 void OpSelectStartFrame::Do( OpDescriptor * pOpDesc )
00247 {
00248     // Just find the background layer and then ask our baseclass to delete it for us
00249     // Is there a selected spread?
00250     Spread * pSpread = Document::GetSelectedSpread();
00251     if (pSpread)
00252     {
00253 PORTNOTE("other", "Disabled FrameSGallery")
00254 #ifndef EXCLUDE_FROM_XARALX
00255         // Check that all visible layers are actually frame layers
00256         FrameSGallery::EnsureFrameLayerIntegrity(pSpread);
00257 #endif
00258         // yes, so find the first layer and try to move to it
00259         Layer * pLayer = pSpread->FindFirstFrameLayer();
00260         if (pLayer)
00261         {
00262             OpLayerGalParam Param(FRAME_SELECT, pSpread);
00263             Param.pLayer = pLayer;
00264             DoWithParam(pOpDesc, (OpParam*)&Param);
00265         }
00266     }
00267 
00268     // End the operation, but we are calling DoWithParam() which we will assume does it for us.
00269     //End();
00270 
00271     return;
00272 }
00273 
00274 /********************************************************************************************
00275 // End of OpSelectStartFrame
00276 ********************************************************************************************/
00277 
00278 //------------------------------------------------------------------------------------------
00279 // Methods for the OpSelectEndFrame
00280 //------------------------------------------------------------------------------------------
00281 
00282 /********************************************************************************************
00283 
00284 >   OpState OpSelectEndFrame::GetState(String_256*, OpDescriptor*)
00285 
00286     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00287     Created:    22/4/97
00288     Inputs:     Name of the OpDescriptor being queried
00289     Outputs:    The string to show to the user
00290     Returns:    The state of the OpSelectEndFrame operation
00291     Purpose:    For finding the OpSelectEndFrame's state. 
00292     Errors:     -
00293     SeeAlso:    -
00294 
00295 ********************************************************************************************/
00296 
00297 OpState OpSelectEndFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc)
00298 {
00299     OpState OpSt;  
00300 
00301     // Is there a selected spread?
00302     Spread * pSpread = Document::GetSelectedSpread();
00303     if (pSpread)
00304     {
00305         // yes, so check if there is an active layer
00306         Layer * pLayer = pSpread->FindActiveLayer();
00307         // If there is an active layer and one following then we are not greyed
00308         Layer * pNextLayer = pLayer->FindNextLayer();
00309         // The next layer should really be a frame layer but we cannot guarantee that but
00310         // it mustn't be a guide, a page background or a background layer.
00311         while ( pNextLayer && !pNextLayer->IsPseudoFrame())
00312         {
00313             pNextLayer = pNextLayer->FindNextLayer();
00314         }
00315 
00316         if (pLayer && pNextLayer)
00317         {
00318             // Yes, so we are allowed to move to the previous one
00319             OpSt.Greyed = FALSE;
00320         }
00321         else
00322         {
00323             // No, so we are greyed
00324             OpSt.Greyed = TRUE;
00325         }
00326     }
00327     else
00328     {
00329         // No selected spread, so we are greyed
00330         OpSt.Greyed = TRUE;
00331     }
00332 
00333     return OpSt;   
00334 }
00335 
00336 /********************************************************************************************
00337 
00338 >   void OpSelectEndFrame::Do(OpDescriptor * pOpDesc)
00339 
00340     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00341     Created:    22/4/97
00342     Inputs:     OpDescriptor (unused)
00343     Outputs:    -
00344     Returns:    -
00345     Purpose:    Tries to select the bottom most animation frame (i.e. layer).
00346     Errors:     -
00347     SeeAlso:    -
00348 
00349 ********************************************************************************************/
00350 
00351 void OpSelectEndFrame::Do( OpDescriptor * pOpDesc )
00352 {
00353     // Just find the background layer and then ask our baseclass to delete it for us
00354     // Is there a selected spread?
00355     Spread * pSpread = Document::GetSelectedSpread();
00356     if (pSpread)
00357     {
00358 PORTNOTE("other", "Disabled FrameSGallery")
00359 #ifndef EXCLUDE_FROM_XARALX
00360         // Check that all visible layers are actually frame layers
00361         FrameSGallery::EnsureFrameLayerIntegrity(pSpread);
00362 #endif
00363         // yes, so find the last layer and try to move to it
00364         Layer * pLayer = pSpread->FindLastFrameLayer();
00365         if (pLayer)
00366         {
00367             OpLayerGalParam Param(FRAME_SELECT, pSpread);
00368             Param.pLayer = pLayer;
00369             DoWithParam(pOpDesc, (OpParam*)&Param);
00370         }
00371     }
00372 
00373     // End the operation, but we are calling DoWithParam() which we will assume does it for us.
00374     //End();
00375 
00376     return;
00377 }
00378 
00379 /********************************************************************************************
00380 // End of OpSelectEndFrame
00381 ********************************************************************************************/
00382 
00383 //------------------------------------------------------------------------------------------
00384 // Methods for the OpSelectPrevFrame
00385 //------------------------------------------------------------------------------------------
00386 
00387 /********************************************************************************************
00388 
00389 >   OpState OpSelectPrevFrame::GetState(String_256*, OpDescriptor*)
00390 
00391     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00392     Created:    22/4/97
00393     Inputs:     Name of the OpDescriptor being queried
00394     Outputs:    The string to show to the user
00395     Returns:    The state of the OpSelectPrevFrame operation
00396     Purpose:    For finding the OpSelectPrevFrame's state. 
00397     Errors:     -
00398     SeeAlso:    -
00399 
00400 ********************************************************************************************/
00401 
00402 OpState OpSelectPrevFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc)
00403 {
00404     //The frame movement controls on the GIF animation bar now work on frames only.
00405     OpState OpSt;  
00406 
00407 #ifdef WEBSTER
00408 
00409     // Is there a selected spread?
00410     Spread * pSpread = Document::GetSelectedSpread();
00411     if (pSpread)
00412     {
00413         // yes, so check if there is an active layer
00414         Layer * pLayer = pSpread->FindActiveLayer();
00415         // If there is an active layer and one preceeding then we are not greyed
00416         Layer * pPrevLayer = pLayer->FindPrevLayer();
00417         // The previous layer should really be a frame layer but we cannot guarantee that but
00418         // it mustn't be a guide, a page background or a background layer.
00419         while ( pPrevLayer && !pPrevLayer->IsPseudoFrame())
00420         {
00421             pPrevLayer = pPrevLayer->FindPrevLayer();
00422         }
00423      
00424         if (pLayer && pPrevLayer)
00425         {
00426             // Yes, so we are allowed to move to the previous one
00427             OpSt.Greyed = FALSE;
00428         }
00429         else
00430         {
00431             // No, so we are greyed
00432             OpSt.Greyed = TRUE;
00433         }
00434     }
00435     else
00436     {
00437         // No selected spread, so we are greyed
00438         OpSt.Greyed = TRUE;
00439     }
00440 
00441 #else
00442     // Are we in frame mode.
00443     BOOL FrameMode = IsFrameMode();
00444 
00445     if(FrameMode)
00446     {
00447         // Is there a selected spread?
00448         Spread * pSpread = Document::GetSelectedSpread();
00449         if (pSpread)
00450         {
00451             // yes, so check if there is an active layer
00452             Layer * pLayer = pSpread->FindActiveLayer();
00453             // If there is an active layer and one preceeding then we are not greyed
00454             Layer * pPrevLayer = pLayer->FindPrevLayer();
00455             // The previous layer should really be a frame layer but we cannot guarantee that but
00456             // it mustn't be a guide, a page background or a background layer.
00457             while ( pPrevLayer && !pPrevLayer->IsPseudoFrame())
00458             {
00459                 pPrevLayer = pPrevLayer->FindPrevLayer();
00460             }
00461 
00462             if (pLayer && pPrevLayer)
00463             {
00464                 // Yes, so we are allowed to move to the previous one
00465                 OpSt.Greyed = FALSE;
00466             }
00467             else
00468             {
00469                 // No, so we are greyed
00470                 OpSt.Greyed = TRUE;
00471             }
00472         }
00473         else
00474         {
00475             // No selected spread, so we are greyed
00476             OpSt.Greyed = TRUE;
00477         }
00478     }
00479     else
00480     {
00481         // The document is layer based, so we are greyed.
00482         OpSt.Greyed = TRUE;
00483     }
00484 #endif
00485 
00486     return OpSt;   
00487 }
00488 
00489 /********************************************************************************************
00490 
00491 >   void OpSelectPrevFrame::Do(OpDescriptor * pOpDesc)
00492 
00493     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00494     Created:    22/4/97
00495     Inputs:     OpDescriptor (unused)
00496     Outputs:    -
00497     Returns:    -
00498     Purpose:    Tries to select the previous animation frame (i.e. layer).
00499     Errors:     -
00500     SeeAlso:    -
00501 
00502 ********************************************************************************************/
00503 
00504 void OpSelectPrevFrame::Do( OpDescriptor * pOpDesc )
00505 {
00506     // Just find the background layer and then ask our baseclass to delete it for us
00507     // Is there a selected spread?
00508     Spread * pSpread = Document::GetSelectedSpread();
00509     if (pSpread)
00510     {
00511 PORTNOTE("other", "Disabled FrameSGallery")
00512 #ifndef EXCLUDE_FROM_XARALX
00513         // Check that all visible layers are actually frame layers
00514         FrameSGallery::EnsureFrameLayerIntegrity(pSpread);
00515 #endif
00516         // yes, so find the last layer and try to move to it
00517         Layer * pLayer = pSpread->FindActiveLayer();
00518         Layer * pPrevLayer = NULL;
00519         if (pLayer)
00520             pPrevLayer = pLayer->FindPrevFrameLayer();
00521         if (pPrevLayer)
00522         {
00523             OpLayerGalParam Param(FRAME_SELECT, pSpread);
00524             Param.pLayer = pPrevLayer;
00525             DoWithParam(pOpDesc, (OpParam*)&Param);
00526         }
00527     }
00528 
00529     // End the operation, but we are calling DoWithParam() which we will assume does it for us.
00530     //End();
00531 
00532     return;
00533 }
00534 
00535 /********************************************************************************************
00536 // End of OpSelectPrevFrame
00537 ********************************************************************************************/
00538 
00539 //------------------------------------------------------------------------------------------
00540 // Methods for the OpSelectNextFrame
00541 //------------------------------------------------------------------------------------------
00542 
00543 /********************************************************************************************
00544 
00545 >   OpState OpSelectNextFrame::GetState(String_256*, OpDescriptor*)
00546 
00547     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00548     Created:    22/4/97
00549     Inputs:     Name of the OpDescriptor being queried
00550     Outputs:    The string to show to the user
00551     Returns:    The state of the OpSelectNextFrame operation
00552     Purpose:    For finding the OpSelectNextFrame's state. 
00553     Errors:     -
00554     SeeAlso:    -
00555 
00556 ********************************************************************************************/
00557 
00558 OpState OpSelectNextFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc)
00559 {
00560     //The frame movement controls on the GIF animation bar now work on frames only.
00561 
00562     OpState OpSt;  
00563 
00564 #ifdef WEBSTER
00565 
00566     // Is there a selected spread?
00567     Spread * pSpread = Document::GetSelectedSpread();
00568     if (pSpread)
00569     {
00570         // yes, so check if there is an active layer
00571         Layer * pLayer = pSpread->FindActiveLayer();
00572         // If there is an active layer and one following then we are not greyed
00573         Layer * pNextLayer = pLayer->FindNextLayer();
00574         // The next layer should really be a frame layer but we cannot guarantee that but
00575         // it mustn't be a guide, a page background or a background layer.
00576         while ( pNextLayer && !pNextLayer->IsPseudoFrame())
00577         {
00578             pNextLayer = pNextLayer->FindNextLayer();
00579         }
00580      
00581         if (pLayer && pNextLayer)
00582         {
00583             // Yes, so we are allowed to move to the previous one
00584             OpSt.Greyed = FALSE;
00585         }
00586         else
00587         {
00588             // No, so we are greyed
00589             OpSt.Greyed = TRUE;
00590         }
00591     }
00592     else
00593     {
00594         // No selected spread, so we are greyed
00595         OpSt.Greyed = TRUE;
00596     }
00597 
00598 #else
00599     // Are we in frame mode.
00600     BOOL FrameMode = IsFrameMode();
00601 
00602     if(FrameMode)
00603     {
00604         // Is there a selected spread?
00605         Spread * pSpread = Document::GetSelectedSpread();
00606         if (pSpread)
00607         {
00608             // yes, so check if there is an active layer
00609             Layer * pLayer = pSpread->FindActiveLayer();
00610             // If there is an active layer and one following then we are not greyed
00611             Layer * pNextLayer = pLayer->FindNextLayer();
00612             // The next layer should really be a frame layer but we cannot guarantee that but
00613             // it mustn't be a guide, a page background or a background layer.
00614             while ( pNextLayer && !pNextLayer->IsPseudoFrame())
00615             {
00616                 pNextLayer = pNextLayer->FindNextLayer();
00617             }
00618 
00619             if (pLayer && pNextLayer)
00620             {
00621                 // Yes, so we are allowed to move to the previous one
00622                 OpSt.Greyed = FALSE;
00623             }
00624             else
00625             {
00626                 // No, so we are greyed
00627                 OpSt.Greyed = TRUE;
00628             }
00629         }
00630         else
00631         {
00632             // No selected spread, so we are greyed
00633             OpSt.Greyed = TRUE;
00634         }
00635     }
00636     else
00637     {
00638             // The document is layer based, so we are greyed.
00639             OpSt.Greyed = TRUE;
00640     }
00641 #endif
00642 
00643     return OpSt;   
00644 }
00645 
00646 /********************************************************************************************
00647 
00648 >   void OpSelectNextFrame::Do(OpDescriptor * pOpDesc)
00649 
00650     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00651     Created:    22/4/97
00652     Inputs:     OpDescriptor (unused)
00653     Outputs:    -
00654     Returns:    -
00655     Purpose:    Tries to select the next animation frame (i.e. layer).
00656     Errors:     -
00657     SeeAlso:    -
00658 
00659 ********************************************************************************************/
00660 
00661 void OpSelectNextFrame::Do( OpDescriptor * pOpDesc )
00662 {
00663     // Just find the background layer and then ask our baseclass to delete it for us
00664     // Is there a selected spread?
00665     Spread * pSpread = Document::GetSelectedSpread();
00666     if (pSpread)
00667     {
00668 PORTNOTE("other", "Disabled BrowserPreviewOptions")
00669 #ifndef EXCLUDE_FROM_XARALX
00670         // Check that all visible layers are actually frame layers
00671         FrameSGallery::EnsureFrameLayerIntegrity(pSpread);
00672 #endif
00673         // yes, so find the next layer and try to move to it
00674         Layer * pLayer = pSpread->FindActiveLayer();
00675         Layer * pNextLayer = NULL;
00676         if (pLayer)
00677             pNextLayer = pLayer->FindNextFrameLayer();
00678         if (pNextLayer)
00679         {
00680             OpLayerGalParam Param(FRAME_SELECT, pSpread);
00681             Param.pLayer = pNextLayer;
00682             DoWithParam(pOpDesc, (OpParam*)&Param);
00683         }
00684     }
00685 
00686     // End the operation, but we are calling DoWithParam() which we will assume does it for us.
00687     //End();
00688 
00689     return;
00690 }
00691 
00692 /********************************************************************************************
00693 // End of OpSelectNextFrame
00694 ********************************************************************************************/
00695 
00696 //------------------------------------------------------------------------------------------
00697 // Methods for the OpCreateNewFrame
00698 //------------------------------------------------------------------------------------------
00699 
00700 /********************************************************************************************
00701 
00702 >   OpState OpCreateNewFrame::GetState(String_256*, OpDescriptor*)
00703 
00704     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00705     Created:    22/4/97
00706     Inputs:     Name of the OpDescriptor being queried
00707     Outputs:    The string to show to the user
00708     Returns:    The state of the OpCreateNewFrame operation
00709     Purpose:    For finding the OpCreateNewFrame's state. 
00710     Errors:     -
00711     SeeAlso:    -
00712 
00713 ********************************************************************************************/
00714 
00715 OpState OpCreateNewFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc)
00716 {
00717     //The frame movement controls on the GIF animation bar now work on frames only.
00718     OpState OpSt;  
00719 
00720 #ifdef WEBSTER
00721     // Is there a selected spread?
00722     Spread * pSpread = Document::GetSelectedSpread();
00723     if (pSpread)
00724     {
00725         // Yes, so we are allowed to move to the previous one
00726         OpSt.Greyed = FALSE;
00727     }
00728     else
00729     {
00730         // No selected spread, so we are greyed
00731         OpSt.Greyed = TRUE;
00732     }
00733 #else
00734     // Are we in frame mode.
00735     BOOL FrameMode = IsFrameMode();
00736 
00737     if(FrameMode)
00738     {
00739         // Is there a selected spread?
00740         Spread * pSpread = Document::GetSelectedSpread();
00741         if (pSpread)
00742         {
00743             // Yes, so we are allowed to move to the previous one
00744             OpSt.Greyed = FALSE;
00745         }
00746         else
00747         {
00748             // No selected spread, so we are greyed
00749             OpSt.Greyed = TRUE;
00750         }
00751     }
00752     else
00753     {
00754         // The document is layer based, so we are greyed.
00755         OpSt.Greyed = TRUE;
00756     }
00757 #endif
00758 
00759     return OpSt;   
00760 }
00761 
00762 /********************************************************************************************
00763 
00764 >   void OpCreateNewFrame::Do(OpDescriptor * pOpDesc)
00765 
00766     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00767     Created:    22/4/97
00768     Inputs:     OpDescriptor (unused)
00769     Outputs:    -
00770     Returns:    -
00771     Purpose:    Tries to create a new animation frame (i.e. layer).
00772     Errors:     -
00773     SeeAlso:    -
00774 
00775 ********************************************************************************************/
00776 
00777 void OpCreateNewFrame::Do( OpDescriptor * pOpDesc )
00778 {
00779 PORTNOTE("other", "Disabled BrowserPreviewOptions")
00780 #ifndef EXCLUDE_FROM_XARALX
00781     // Just find the background layer and then ask our baseclass to delete it for us
00782     // Is there a selected spread?
00783     Spread * pSpread = Document::GetSelectedSpread();
00784     if (pSpread)
00785     {
00786         // Check that all visible layers are actually frame layers
00787         FrameSGallery::EnsureFrameLayerIntegrity(pSpread);
00788         // Use the spread as the context node
00789         OpLayerGalParam Param(FRAME_NEW, pSpread);
00790         Param.pLayer        = NULL;
00791         Param.pContextNode  = pSpread;
00792         Param.AttDir        = LASTCHILD;
00793         // Set up the name that is going to be applied to the frame
00794         String_256 NewName = FrameSGallery::CreateUniqueLayerID(pSpread);
00795         //String_256 NewName(_R(IDS_DEFAULTFRAMENAME));
00796         Param.Status.StringLayerID = NewName;
00797         DoWithParam(pOpDesc, (OpParam*)&Param);
00798     }
00799 
00800     // End the operation, but we are calling DoWithParam() which we will assume does it for us.
00801     //End();
00802 #endif
00803 
00804     return;
00805 }
00806 
00807 /********************************************************************************************
00808 // End of OpCreateNewFrame
00809 ********************************************************************************************/
00810 
00811 //------------------------------------------------------------------------------------------
00812 // Methods for the OpCopyFrame
00813 //------------------------------------------------------------------------------------------
00814 
00815 /********************************************************************************************
00816 
00817 >   OpState OpCopyFrame::GetState(String_256*, OpDescriptor*)
00818 
00819     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00820     Created:    22/4/97
00821     Inputs:     Name of the OpDescriptor being queried
00822     Outputs:    The string to show to the user
00823     Returns:    The state of the OpCopyFrame operation
00824     Purpose:    For finding the OpCopyFrame's state. 
00825     Errors:     -
00826     SeeAlso:    -
00827 
00828 ********************************************************************************************/
00829 
00830 OpState OpCopyFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc)
00831 {
00832     //The frame movement controls on the GIF animation bar now work on frames only.
00833     OpState OpSt;  
00834 
00835 #ifdef WEBSTER
00836     // Is there a selected spread?
00837     Spread * pSpread = Document::GetSelectedSpread();
00838     if (pSpread)
00839     {
00840         // yes, so check if there is an active layer
00841         Layer * pLayer = pSpread->FindActiveLayer();
00842         // If there is an active layer then we are not greyed
00843         if (pLayer)
00844         {
00845             OpSt.Greyed = FALSE;
00846         }
00847         else
00848         {
00849             // No, so we are greyed
00850             OpSt.Greyed = TRUE;
00851         }
00852     }
00853     else
00854     {
00855         // No selected spread, so we are greyed
00856         OpSt.Greyed = TRUE;
00857     }
00858 #else
00859     // Are we in frame mode.
00860     BOOL FrameMode = IsFrameMode();
00861 
00862     if(FrameMode)
00863     {
00864         // Is there a selected spread?
00865         Spread * pSpread = Document::GetSelectedSpread();
00866         if (pSpread)
00867         {
00868             // yes, so check if there is an active layer
00869             Layer * pLayer = pSpread->FindActiveLayer();
00870             // If there is an active layer then we are not greyed
00871             if (pLayer)
00872             {
00873                 OpSt.Greyed = FALSE;
00874             }
00875             else
00876             {
00877                 // No, so we are greyed
00878                 OpSt.Greyed = TRUE;
00879             }
00880         }
00881         else
00882         {
00883             // No selected spread, so we are greyed
00884             OpSt.Greyed = TRUE;
00885         }
00886     }
00887     else
00888     {
00889         // The document is layer based, so we are greyed.
00890         OpSt.Greyed = TRUE;
00891     }
00892 #endif
00893 
00894     return OpSt;   
00895 }
00896 
00897 /********************************************************************************************
00898 
00899 >   void OpCopyFrame::Do(OpDescriptor * pOpDesc)
00900 
00901     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00902     Created:    22/4/97
00903     Inputs:     OpDescriptor (unused)
00904     Outputs:    -
00905     Returns:    -
00906     Purpose:    Tries to create a new frame by copying the present one.
00907     Errors:     -
00908     SeeAlso:    -
00909 
00910 ********************************************************************************************/
00911 
00912 void OpCopyFrame::Do( OpDescriptor * pOpDesc )
00913 {
00914 PORTNOTE("other", "Disabled FrameSGallery")
00915 #ifndef EXCLUDE_FROM_XARALX
00916     // Just find the background layer and then ask our baseclass to delete it for us
00917     // Is there a selected spread?
00918     Spread * pSpread = Document::GetSelectedSpread();
00919     if (pSpread)
00920     {
00921         // Check that all visible layers are actually frame layers
00922         FrameSGallery::EnsureFrameLayerIntegrity(pSpread);
00923 
00924         // yes, so check that there is a presently active layer and try to copy it
00925         // Use the spread as the context node
00926         Layer * pLayer = pSpread->FindActiveLayer();
00927         if (pLayer)
00928         {
00929             OpLayerGalParam Param(FRAME_COPY, pSpread);
00930             Param.pLayer = pLayer;
00931             Param.pContextNode  = pSpread;
00932             Param.AttDir        = LASTCHILD;
00933             // Set up the name that is going to be applied to the frame
00934             String_256 NewName = FrameSGallery::CreateUniqueLayerID(pSpread);
00935             //String_256 NewName(_R(IDS_DEFAULTFRAMENAME));
00936             Param.Status.StringLayerID = NewName;
00937             DoWithParam(pOpDesc, (OpParam*)&Param);
00938         }
00939     }
00940 
00941     // End the operation, but we are calling DoWithParam() which we will assume does it for us.
00942     //End();
00943 #endif
00944     return;
00945 }
00946 
00947 /********************************************************************************************
00948 // End of OpCopyFrame
00949 ********************************************************************************************/
00950 
00951 //------------------------------------------------------------------------------------------
00952 // Methods for the OpDeleteFrame
00953 //------------------------------------------------------------------------------------------
00954 
00955 /********************************************************************************************
00956 
00957 >   OpState OpDeleteFrame::GetState(String_256*, OpDescriptor*)
00958 
00959     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00960     Created:    23/4/97
00961     Inputs:     Name of the OpDescriptor being queried
00962     Outputs:    The string to show to the user
00963     Returns:    The state of the OpDeleteFrame operation
00964     Purpose:    For finding the OpDeleteFrame's state. 
00965     Errors:     -
00966     SeeAlso:    -
00967 
00968 ********************************************************************************************/
00969 
00970 OpState OpDeleteFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc)
00971 {
00972     //The frame movement controls on the GIF animation bar now work on frames only.
00973     OpState OpSt;  
00974 
00975 #ifdef WEBSTER
00976     // Is there a selected spread?
00977     Spread * pSpread = Document::GetSelectedSpread();
00978     if (pSpread)
00979     {
00980         // yes, so check if there is an active layer
00981         Layer * pLayer = pSpread->FindActiveLayer();
00982 
00983         // Get ptr's to the next and previous frame layers.
00984         Layer* pNextLayer = pLayer->FindNextFrameLayer();
00985         Layer* pPrevLayer = pLayer->FindPrevFrameLayer();
00986 
00987         // If there is an active layer and a previous/next layer then we are not greyed.
00988         if ( pLayer && (pPrevLayer || pNextLayer) )
00989         {
00990             OpSt.Greyed = FALSE;
00991         }
00992         else
00993         {
00994             // No, so we are greyed
00995             OpSt.Greyed = TRUE;
00996         }
00997     }
00998     else
00999     {
01000         // No selected spread, so we are greyed
01001         OpSt.Greyed = TRUE;
01002     }
01003 #else
01004     // Are we in frame mode.
01005     BOOL FrameMode = IsFrameMode();
01006 
01007     if(FrameMode)
01008     {
01009         // Is there a selected spread?
01010         Spread * pSpread = Document::GetSelectedSpread();
01011         if (pSpread)
01012         {
01013             // yes, so check if there is an active layer
01014             Layer * pLayer = pSpread->FindActiveLayer();
01015 
01016             // Get ptr's to the next and previous frame layers.
01017             Layer* pNextLayer = pLayer->FindNextFrameLayer();
01018             Layer* pPrevLayer = pLayer->FindPrevFrameLayer();
01019 
01020             // If there is an active layer and a previous/next layer then we are not greyed.
01021             if (pLayer && (pPrevLayer || pNextLayer) )
01022             {
01023                 OpSt.Greyed = FALSE;
01024             }
01025             else
01026             {
01027                 // No, so we are greyed
01028                 OpSt.Greyed = TRUE;
01029             }
01030         }
01031         else
01032         {
01033             // No selected spread, so we are greyed
01034             OpSt.Greyed = TRUE;
01035         }
01036     }
01037     else
01038     {
01039         // We are in layer mode, so we are greyed.
01040         OpSt.Greyed = TRUE;
01041     }
01042 #endif
01043 
01044     return OpSt;   
01045 }
01046 
01047 /********************************************************************************************
01048 
01049 >   void OpDeleteFrame::Do(OpDescriptor * pOpDesc)
01050 
01051     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01052     Created:    23/4/97
01053     Inputs:     OpDescriptor (unused)
01054     Outputs:    -
01055     Returns:    -
01056     Purpose:    Tries to create a new frame by copying the present one.
01057     Errors:     -
01058     SeeAlso:    -
01059 
01060 ********************************************************************************************/
01061 
01062 void OpDeleteFrame::Do( OpDescriptor * pOpDesc )
01063 {
01064     // Just find the background layer and then ask our baseclass to delete it for us
01065     // Is there a selected spread?
01066     Spread * pSpread = Document::GetSelectedSpread();
01067     if (pSpread)
01068     {
01069 PORTNOTE("other", "Disabled FrameSGallery")
01070 #ifndef EXCLUDE_FROM_XARALX
01071         // Check that all visible layers are actually frame layers
01072         FrameSGallery::EnsureFrameLayerIntegrity(pSpread);
01073 #endif
01074         // yes, so check that there is a presently active layer and try to delete it
01075         Layer * pLayer = pSpread->FindActiveLayer();
01076         if (pLayer)
01077         {
01078             OpLayerGalParam Param(FRAME_DELETE, pSpread);
01079             Param.pLayer = pLayer;
01080             DoWithParam(pOpDesc, (OpParam*)&Param);
01081         }
01082     }
01083 
01084     // End the operation, but we are calling DoWithParam() which we will assume does it for us.
01085     //End();
01086 
01087     return;
01088 }
01089 
01090 /********************************************************************************************
01091 // End of OpDeleteFrame
01092 ********************************************************************************************/
01093 
01094 //------------------------------------------------------------------------------------------
01095 // Methods for the OpFrameProperties
01096 //------------------------------------------------------------------------------------------
01097 
01098 /********************************************************************************************
01099 
01100 >   OpState OpFrameProperties::GetState(String_256*, OpDescriptor*)
01101 
01102     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01103     Created:    29/4/97
01104     Inputs:     Name of the OpDescriptor being queried
01105     Outputs:    The string to show to the user
01106     Returns:    The state of the OpFrameProperties operation
01107     Purpose:    For finding the OpFrameProperties's state. 
01108     Errors:     -
01109     SeeAlso:    -
01110 
01111 ********************************************************************************************/
01112 
01113 OpState OpFrameProperties::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc)
01114 {
01115     //The frame movement controls on the GIF animation bar now work on frames only.
01116     OpState OpSt;  
01117 
01118 #ifdef WEBSTER
01119     // Is there a selected spread?
01120     Spread * pSpread = Document::GetSelectedSpread();
01121     if (pSpread)
01122     {
01123         // yes, so check if there is an active layer
01124         Layer * pLayer = pSpread->FindActiveLayer();
01125         // If there is an active layer and one following then we are not greyed
01126         if (pLayer)
01127         {
01128             // Yes, so we are allowed to move to the previous one
01129             OpSt.Greyed = FALSE;
01130         }
01131         else
01132         {
01133             // No, so we are greyed
01134             OpSt.Greyed = TRUE;
01135         }
01136     }
01137     else
01138     {
01139         // No selected spread, so we are greyed
01140         OpSt.Greyed = TRUE;
01141     }
01142 #else
01143     
01144     BOOL FrameMode = FALSE; // Flag to determine the document mode.
01145 
01146     // Is there a selected spread?
01147     Spread* pSpread = Document::GetSelectedSpread();
01148 
01149     // Ensure a valid spread ptr.
01150     if(pSpread)
01151     {
01152         // Are there any frame layers?
01153         Layer* pFrameLayer = pSpread->FindFirstFrameLayer();    
01154 
01155         //If a frame layer exists, then this is an animation doc.
01156         if (pFrameLayer)
01157             FrameMode = TRUE;
01158     }
01159     
01160     if(FrameMode)
01161     {
01162         if (pSpread)
01163         {
01164             // yes, so check if there is an active layer
01165             Layer * pLayer = pSpread->FindActiveLayer();
01166             // If there is an active layer and one following then we are not greyed
01167             if (pLayer)
01168                 // Yes, so we are allowed to move to the previous one
01169                 OpSt.Greyed = FALSE;
01170             else
01171                 // No, so we are greyed
01172                 OpSt.Greyed = TRUE;
01173         }
01174         else
01175             // No selected spread, so we are greyed
01176             OpSt.Greyed = TRUE;
01177     }
01178     else
01179     {
01180         // The document is layer based, so we are greyed.
01181         OpSt.Greyed = TRUE;
01182     }
01183 #endif
01184     
01185     return OpSt;   
01186 }
01187 
01188 /********************************************************************************************
01189 
01190 >   void OpFrameProperties::Do(OpDescriptor * pOpDesc)
01191 
01192     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01193     Created:    29/4/97
01194     Inputs:     OpDescriptor (unused)
01195     Outputs:    -
01196     Returns:    -
01197     Purpose:    Tries to set some new animation properties.
01198     Errors:     -
01199     SeeAlso:    -
01200 
01201 ********************************************************************************************/
01202 
01203 void OpFrameProperties::Do( OpDescriptor * pOpDesc )
01204 {
01205     // Just find the background layer and then ask our baseclass to delete it for us
01206     // Is there a selected spread?
01207     Spread * pSpread = Document::GetSelectedSpread();
01208     if (pSpread)
01209     {
01210 PORTNOTE("other", "Disabled FrameSGallery")
01211 #ifndef EXCLUDE_FROM_XARALX
01212         // Check that all visible layers are actually frame layers
01213         FrameSGallery::EnsureFrameLayerIntegrity(pSpread);
01214 #endif
01215         OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_GIFANIMPROPERTYTABS);
01216 
01217         if (pOpDesc != NULL)
01218         {
01219             // Select the "Frame properties tab".
01220             GIFAnimationPropertyTabsDlg::SetPageToOpen(GIFAnimationPropertyTabs::FramePropertiesTabNumber);
01221 
01222             String_256 Str;
01223             OpState State = pOpDesc->GetOpsState(&Str);
01224             if (!State.Greyed)
01225                 pOpDesc->Invoke();
01226             else
01227             {
01228                 GIFAnimationPropertyTabs * pTabHandler = GIFAnimationPropertyTabsDlg::GetGIFAnimationPropertiesTabs();
01229                 if (pTabHandler)
01230                 {
01231                     DialogTabOp* pDlg =  pTabHandler->GetTabbedDlg();
01232                     if (pDlg != NULL)
01233                         pDlg->Open();
01234                 }
01235             }
01236         }
01237     }
01238 
01239     // End the operation
01240     End();
01241 
01242     return;
01243 }
01244 
01245 /********************************************************************************************
01246 // End of OpFrameProperties
01247 ********************************************************************************************/
01248 
01249 //------------------------------------------------------------------------------------------
01250 // Methods for the OpAnimationProperties
01251 //------------------------------------------------------------------------------------------
01252 
01253 /********************************************************************************************
01254 
01255 >   OpState OpAnimationProperties::GetState(String_256*, OpDescriptor*)
01256 
01257     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01258     Created:    29/4/97
01259     Inputs:     Name of the OpDescriptor being queried
01260     Outputs:    The string to show to the user
01261     Returns:    The state of the OpAnimationProperties operation
01262     Purpose:    For finding the OpAnimationProperties's state. 
01263     Errors:     -
01264     SeeAlso:    -
01265 
01266 ********************************************************************************************/
01267 
01268 OpState OpAnimationProperties::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc)
01269 {
01270     //The frame movement controls on the GIF animation bar now work on frames only.
01271     OpState OpSt;  
01272 
01273 #ifdef WBSTER
01274         // Is there a selected spread?
01275     Spread * pSpread = Document::GetSelectedSpread();
01276     if (pSpread)
01277     {
01278         // yes, so check if there is an active layer
01279         Layer * pLayer = pSpread->FindActiveLayer();
01280         // If there is an active layer and one following then we are not greyed
01281         if (pLayer)
01282         {
01283             // Yes, so we are allowed to move to the previous one
01284             OpSt.Greyed = FALSE;
01285         }
01286         else
01287         {
01288             // No, so we are greyed
01289             OpSt.Greyed = TRUE;
01290         }
01291     }
01292     else
01293     {
01294         // No selected spread, so we are greyed
01295         OpSt.Greyed = TRUE;
01296     }   
01297 #else
01298     
01299     BOOL FrameMode = FALSE;     // Flag to determine the document mode.
01300 
01301     // Is there a selected spread?
01302     Spread * pSpread = Document::GetSelectedSpread();
01303 
01304     // Ensure a valid spread ptr.
01305     if(pSpread)
01306     {
01307         // Are there any frame layers?
01308         Layer* pFrameLayer = pSpread->FindFirstFrameLayer();    
01309 
01310         //If a frame layer exists, then this is an animation doc.
01311         if (pFrameLayer)
01312             FrameMode = TRUE;
01313     }
01314     
01315     if(FrameMode)
01316     {
01317         if (pSpread)
01318         {
01319             // yes, so check if there is an active layer
01320             Layer * pLayer = pSpread->FindActiveLayer();
01321 
01322             // If there is an active layer and one following, then we are not greyed.
01323             if (pLayer)
01324             {
01325                 // Yes, so we are allowed to move to the previous one
01326                 OpSt.Greyed = FALSE;
01327             }
01328             else
01329             {
01330                 // No, so we are greyed
01331                 OpSt.Greyed = TRUE;
01332             }
01333         }
01334         else
01335         {
01336             // No selected spread, so we are greyed
01337             OpSt.Greyed = TRUE;
01338         }   
01339     }
01340     else
01341     {
01342         // The document is layer based, so we are greyed.
01343         OpSt.Greyed = TRUE;
01344         *pUIDescription = String_256 (_R(IDS_NO_FRAMES));
01345     }
01346 #endif
01347 
01348     return OpSt;   
01349 }
01350 
01351 /********************************************************************************************
01352 
01353 >   void OpAnimationProperties::Do(OpDescriptor * pOpDesc)
01354 
01355     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01356     Created:    29/4/97
01357     Inputs:     OpDescriptor (unused)
01358     Outputs:    -
01359     Returns:    -
01360     Purpose:    Tries to set some new animation properties.
01361     Errors:     -
01362     SeeAlso:    -
01363 
01364 ********************************************************************************************/
01365 
01366 void OpAnimationProperties::Do( OpDescriptor * pOpDesc )
01367 {
01368     // Just find the background layer and then ask our baseclass to delete it for us
01369     // Is there a selected spread?
01370     Spread * pSpread = Document::GetSelectedSpread();
01371     if (pSpread)
01372     {
01373 PORTNOTE("other", "Disabled FrameSGallery")
01374 #ifndef EXCLUDE_FROM_XARALX
01375         // Check that all visible layers are actually frame layers.
01376         FrameSGallery::EnsureFrameLayerIntegrity(pSpread);
01377 #endif
01378         OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_GIFANIMPROPERTYTABS);
01379 
01380         if (pOpDesc != NULL)
01381         {
01382             // Select the "Animation properties tab" on start up.
01383             GIFAnimationPropertyTabsDlg::SetPageToOpen(GIFAnimationPropertyTabs::AnimationColoursTabNumber);
01384 
01385             String_256 Str;
01386             OpState State = pOpDesc->GetOpsState(&Str);
01387             if (!State.Greyed)
01388                 pOpDesc->Invoke();
01389             else
01390             {
01391                 GIFAnimationPropertyTabs * pTabHandler = GIFAnimationPropertyTabsDlg::GetGIFAnimationPropertiesTabs();
01392                 if (pTabHandler)
01393                 {
01394                     DialogTabOp* pDlg =  pTabHandler->GetTabbedDlg();
01395                     if (pDlg != NULL)
01396                         pDlg->Open();
01397                 }
01398             }
01399         }
01400     }
01401     
01402     // End the operation
01403     End();
01404 
01405     return;
01406 }
01407 
01408 /********************************************************************************************
01409 // End of OpAnimationProperties
01410 ********************************************************************************************/
01411 
01412 PORTNOTE("other", "Removed GrabFrameFilter, OpGrabFrame, OpGrabAllFrames")
01413 #ifndef EXCLUDE_FROM_XARALX
01414 
01415 //------------------------------------------------------------------------------------------
01416 // Methods for the OpGrabFrame
01417 //------------------------------------------------------------------------------------------
01418 
01419 BitmapPreviewData * OpGrabFrame::m_pBitmapData = NULL;
01420 
01421 /********************************************************************************************
01422 
01423 >   BOOL OpGrabFrame::Init()
01424 
01425     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01426     Created:    19/6/97
01427     Returns:    TRUE if the operation could be successfully initialised 
01428                 FALSE if no more memory could be allocated 
01429     Purpose:    OpGrabFrame initialiser method
01430     Errors:     ERROR will be called if there was insufficient memory to allocate the 
01431                 operation.
01432 
01433 ********************************************************************************************/
01434 
01435 BOOL OpGrabFrame::Init()
01436 {
01437     BOOL ok = FALSE;
01438      
01439     // start of non-undoable operations
01440     ok = RegisterOpDescriptor(
01441                                 0,                              // Tool ID 
01442                                 _R(IDS_FRAMEPROPERTIES),            // String resource ID
01443                                 CC_RUNTIME_CLASS(OpFrameProperties),    // Runtime class
01444                                 OPTOKEN_FRAME_PROPERTIES,       // Token string
01445                                 OpFrameProperties::GetState,            // GetState function
01446                                 0,                              // help ID
01447                                 _R(IDBBL_FRAMEPROPERTIES),          // bubble help
01448                                 _R(IDD_ANIMATIONBAR),               // resource ID
01449                                 _R(IDC_FRAME_FRAMEPROPERTIES),      // control ID
01450                                 SYSTEMBAR_ANIMATION,            // Bar ID
01451                                 TRUE,                           // Recieve system messages
01452                                 FALSE,                          // Smart duplicate operation
01453                                 TRUE,                           // Clean operation
01454                                 NULL,                           // No vertical counterpart
01455                                 0,                              // String for one copy only error
01456                                 (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
01457                                 );
01458     if(ok)
01459         ok = RegisterOpDescriptor(
01460                                 0,                              // Tool ID 
01461                                 _R(IDS_ANIMATIONPROPERTIES),        // String resource ID
01462                                 CC_RUNTIME_CLASS(OpAnimationProperties),    // Runtime class
01463                                 OPTOKEN_FRAME_ANIPROPERTIES,    // Token string
01464                                 OpAnimationProperties::GetState,            // GetState function
01465                                 0,                              // help ID
01466                                 _R(IDBBL_ANIMATIONPROPERTIES),      // bubble help
01467                                 _R(IDD_ANIMATIONBAR),               // resource ID
01468                                 _R(IDC_FRAME_ANIMATIONPROPERTIES),  // control ID
01469                                 SYSTEMBAR_ANIMATION,            // Bar ID
01470                                 TRUE,                           // Recieve system messages
01471                                 FALSE,                          // Smart duplicate operation
01472                                 TRUE,                           // Clean operation
01473                                 NULL,                           // No vertical counterpart
01474                                 0,                              // String for one copy only error
01475                                 (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
01476                                 );
01477      if(ok)
01478         ok = RegisterOpDescriptor(
01479                                 0,                              // Tool ID 
01480                                 _R(IDS_GRABFRAME),                  // String resource ID
01481                                 CC_RUNTIME_CLASS(OpGrabFrame),  // Runtime class
01482                                 OPTOKEN_FRAME_GRABFRAME,        // Token string
01483                                 OpGrabFrame::GetState,          // GetState function
01484                                 _R(IDH_Command_Preview_All_Frames), // help ID
01485                                 _R(IDBBL_GRABFRAME),                // bubble help
01486                                 _R(IDD_ANIMATIONBAR),               // resource ID
01487                                 _R(IDC_FRAME_GRABFRAME),            // control ID
01488                                 SYSTEMBAR_ANIMATION,            // Bar ID
01489                                 TRUE,                           // Recieve system messages
01490                                 FALSE,                          // Smart duplicate operation
01491                                 TRUE,                           // Clean operation
01492                                 NULL,                           // No vertical counterpart
01493                                 0,                              // String for one copy only error
01494                                 (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
01495                                 );
01496      if(ok)
01497         ok = RegisterOpDescriptor(
01498                                 0,                              // Tool ID 
01499                                 _R(IDS_GRABALLFRAMES),          // String resource ID
01500                                 CC_RUNTIME_CLASS(OpGrabAllFrames),  // Runtime class
01501                                 OPTOKEN_FRAME_GRABALLFRAMES,    // Token string
01502                                 OpGrabAllFrames::GetState,  // GetState function
01503                                 _R(IDH_Command_Preview_All_Frames), // help ID
01504                                 _R(IDBBL_GRABALLFRAMES),            // bubble help
01505                                 _R(IDD_ANIMATIONBAR),               // resource ID
01506                                 _R(IDC_FRAME_GRABALLFRAMES),        // control ID
01507                                 SYSTEMBAR_ANIMATION,            // Bar ID
01508                                 TRUE,                           // Recieve system messages
01509                                 FALSE,                          // Smart duplicate operation
01510                                 TRUE,                           // Clean operation
01511                                 NULL,                           // No vertical counterpart
01512                                 0,                              // String for one copy only error
01513                                 (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
01514                                 );
01515     if(ok)
01516         ok = RegisterOpDescriptor(
01517                                 0,                              // Tool ID 
01518                                 _R(IDS_FRAME_SAVEANIMATEDGIF),      // String resource ID
01519                                 CC_RUNTIME_CLASS(OpSaveAnimatedGIF),    // Runtime class
01520                                 OPTOKEN_SAVEANIMATEDGIF,        // Token string
01521                                 OpSaveAnimatedGIF::GetState,            // GetState function
01522                                 0,                              // help ID
01523                                 _R(IDBBL_SAVEANIMATEDGIF),          // bubble help
01524                                 _R(IDD_ANIMATIONBAR),               // resource ID
01525                                 _R(IDC_FRAME_SAVEANIMATEDGIF),      // control ID
01526                                 SYSTEMBAR_ANIMATION,            // Bar ID
01527                                 TRUE,                           // Recieve system messages
01528                                 FALSE,                          // Smart duplicate operation
01529                                 TRUE,                           // Clean operation
01530                                 NULL,                           // No vertical counterpart
01531                                 0,                              // String for one copy only error
01532                                 (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
01533                                 );
01534     if(ok)
01535         ok = RegisterOpDescriptor(
01536                                 0,                              // Tool ID 
01537                                 _R(IDS_BROWSERPREVIEW),             // String resource ID
01538                                 CC_RUNTIME_CLASS(OpBrowserPreview), // Runtime class
01539                                 OPTOKEN_FRAME_BROWSERPREVIEW,   // Token string
01540                                 OpBrowserPreview::GetState,         // GetState function
01541                                 _R(IDH_Command_Preview_Animation_in_Browser), // help ID
01542                                 _R(IDBBL_BROWSERPREVIEW),           // bubble help
01543                                 _R(IDD_ANIMATIONBAR),               // resource ID
01544                                 _R(IDC_FRAME_GOTOBROWSER),          // control ID
01545                                 SYSTEMBAR_ANIMATION,            // Bar ID
01546                                 TRUE,                           // Recieve system messages
01547                                 FALSE,                          // Smart duplicate operation
01548                                 TRUE,                           // Clean operation
01549                                 NULL,                           // No vertical counterpart
01550                                 0,                              // String for one copy only error
01551                                 (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags
01552                                 );
01553             // end of non-undoable operations
01554 
01555             if(ok)
01556                 ok = PreviewInBrowserTab::Declare();
01557             
01558             return ok;
01559 }               
01560 
01561 /********************************************************************************************
01562 
01563 >   static void OpGrabFrame::DeInit(void)
01564 
01565     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01566     Created:    3/7/97
01567     Purpose:    De-Initialises OpGrabFrame
01568 
01569 ********************************************************************************************/
01570 
01571 void OpGrabFrame::DeInit(void)
01572 {
01573     // Deinit our static preview bitmap data pointer if allocated
01574     // This should clean up any temp files that we have used
01575     if (m_pBitmapData != NULL)
01576     {
01577         delete m_pBitmapData;
01578         m_pBitmapData = NULL;
01579     }
01580 
01581     // Give the browser preview chance to clean up its temp file useage
01582     OpBrowserPreview::RemoveTempFile();
01583 }
01584 
01585 /********************************************************************************************
01586 
01587 >   OpState OpGrabFrame::GetState(String_256*, OpDescriptor*)
01588 
01589     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01590     Created:    23/4/97
01591     Inputs:     Name of the OpDescriptor being queried
01592     Outputs:    The string to show to the user
01593     Returns:    The state of the OpGrabFrame operation
01594     Purpose:    For finding the OpGrabFrame's state. 
01595     Errors:     -
01596     SeeAlso:    -
01597 
01598 ********************************************************************************************/
01599 
01600 OpState OpGrabFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc)
01601 {
01602 
01603     //The frame movement controls on the GIF animation bar now work on frames only.
01604     OpState OpSt;
01605 
01606 #ifdef WEBSTER
01607     String_256 DisableReason;
01608 
01609     // Is there a selected spread?
01610     Spread * pSpread = Document::GetSelectedSpread();
01611     if (pSpread)
01612     {
01613         // yes, so check if there is an active layer
01614         Layer * pLayer = pSpread->FindActiveLayer();
01615         if (pLayer)
01616         {
01617             // Ensure that we have some visible objects on the specified layer to render
01618             // Could use a range but easier just to check if there are visible objects on the page
01619             DocRect VisibleRect = pSpread->GetPageVisibleBounds();
01620             BOOL Empty = VisibleRect.IsEmpty();
01621             // If this frame has nothing visible on it then check if there are renderable objects
01622             // on any other frames in the animation.
01623             if (Empty)
01624             {
01625                 // Cannot assume that all the frame layers are actually frame layers so
01626                 // go through all those that might be frame layers.
01627                 Layer * pFrame = pSpread->FindFirstLayer();
01628                 while (pFrame && Empty)
01629                 {
01630                     if (pFrame->IsPseudoFrame() && pFrame->HasLayerGotRenderableChildren())
01631                         Empty = FALSE;
01632                         pFrame = pFrame->FindNextLayer();
01633                 }
01634             }
01635             if (pOpDesc && pOpDesc->Token != String(OPTOKEN_FRAME_GRABFRAME) && !Empty)
01636             {
01637                 // Cannot assume that all the frame layers are actually frame layers so
01638                 // go through all those that might be frame layers.
01639                 Layer * pFrame = pSpread->FindFirstLayer();
01640                 BOOL AllHidden = TRUE;
01641                 while (pFrame && AllHidden)
01642                 {
01643                     if (pFrame->IsPseudoFrame() && !pFrame->IsHiddenFrame())
01644                         AllHidden = FALSE;
01645                         pFrame = pFrame->FindNextLayer();
01646                 }
01647                 if (AllHidden)
01648                 {
01649                     OpSt.Greyed = TRUE; 
01650                     // Load reason why operation is disabled
01651                     DisableReason = String_256(_R(IDS_ALLFRAMESAREHIDDEN));
01652                     if (pUIDescription)
01653                         *pUIDescription = DisableReason;
01654                 }
01655                 else
01656                 {
01657                     // Yes, so we are allowed to grab the frame or all the frames
01658                     OpSt.Greyed = FALSE;
01659                 }
01660             }
01661             else if (pOpDesc && pOpDesc->Token == String(OPTOKEN_FRAME_GRABFRAME) && pLayer->IsHiddenFrame())
01662             {
01663                 // If we are the grab frame op then check that the current layer is not
01664                 // hidden. If so then disallow
01665                 OpSt.Greyed = TRUE; 
01666                 // Load reason why operation is disabled
01667                 DisableReason = String_256(_R(IDS_FRAMEISHIDDEN));
01668                 if (pUIDescription)
01669                     *pUIDescription = DisableReason;    
01670             }
01671             else if (!Empty)
01672             {
01673                 // Yes, so we are allowed to grab the frame or all the frames
01674                 OpSt.Greyed = FALSE;
01675             }
01676             else
01677             {
01678                 OpSt.Greyed = TRUE; 
01679                 // Load reason why operation is disabled
01680                 DisableReason = String_256(_R(IDS_NO_VISIBLE_OBJECTS));
01681                 if (pUIDescription)
01682                     *pUIDescription = DisableReason;            
01683             }           
01684         }
01685         else
01686         { 
01687             // No, so we are greyed
01688             OpSt.Greyed = TRUE;
01689         }
01690     }
01691     else 
01692     {
01693         // No selected spread, so we are greyed
01694         OpSt.Greyed = TRUE;
01695 
01696         // Load reason why operation is disabled
01697         DisableReason = String_256(_R(IDS_NO_DOC));
01698         if (pUIDescription)
01699             *pUIDescription = DisableReason;         
01700     }
01701 
01702 #else
01703     // Flag to determine the document mode.
01704     BOOL FrameMode = FALSE;
01705 
01706     // Get a ptr to the selected spread
01707     Spread* pSpread = Document::GetSelectedSpread();
01708 
01709     // Ensure a valid spread ptr.
01710     if(pSpread)
01711     {
01712         // Are there any frame layers?
01713         Layer* pFrameLayer = pSpread->FindFirstFrameLayer();    
01714 
01715         //If a frame layer exists, then this is an animation doc.
01716         if (pFrameLayer)
01717             FrameMode = TRUE;
01718     }
01719 
01720     if(FrameMode)
01721     {
01722         String_256 DisableReason;
01723 
01724         if (pSpread)
01725         {
01726             // yes, so check if there is an active layer
01727             Layer * pLayer = pSpread->FindActiveLayer();
01728 
01729             if (pLayer)
01730             {
01731                 // Ensure that we have some visible objects on the specified layer to render
01732                 // Could use a range but easier just to check if there are visible objects on the page
01733                 DocRect VisibleRect = pSpread->GetPageVisibleBounds();
01734                 BOOL Empty = VisibleRect.IsEmpty();
01735                 // If this frame has nothing visible on it then check if there are renderable objects
01736                 // on any other frames in the animation.
01737                 if (Empty)
01738                 {
01739                     // Cannot assume that all the frame layers are actually frame layers so
01740                     // go through all those that might be frame layers.
01741                     Layer * pFrame = pSpread->FindFirstLayer();
01742                     while (pFrame && Empty)
01743                     {
01744                         if (pFrame->IsPseudoFrame() && pFrame->HasLayerGotRenderableChildren())
01745                             Empty = FALSE;
01746                         
01747                         pFrame = pFrame->FindNextLayer();
01748                     }
01749                 }
01750 
01751                 if (pOpDesc && pOpDesc->Token != String(OPTOKEN_FRAME_GRABFRAME) && !Empty)
01752                 {
01753                     // Cannot assume that all the frame layers are actually frame layers so
01754                     // go through all those that might be frame layers.
01755                     Layer * pFrame = pSpread->FindFirstLayer();
01756                     BOOL AllHidden = TRUE;
01757                     while (pFrame && AllHidden)
01758                     {
01759                         if (pFrame->IsPseudoFrame() && !pFrame->IsHiddenFrame())
01760                             AllHidden = FALSE;
01761                         
01762                         pFrame = pFrame->FindNextLayer();
01763                     }
01764                     
01765                     if (AllHidden)
01766                     {
01767                         OpSt.Greyed = TRUE; 
01768                         // Load reason why operation is disabled
01769                         DisableReason = String_256(_R(IDS_ALLFRAMESAREHIDDEN));
01770                         if (pUIDescription)
01771                             *pUIDescription = DisableReason;
01772                     }
01773                     else
01774                     {
01775                         // Yes, so we are allowed to grab the frame or all the frames
01776                         OpSt.Greyed = FALSE;
01777                     }
01778                 }
01779                 else if (pOpDesc && pOpDesc->Token == String(OPTOKEN_FRAME_GRABFRAME) && pLayer->IsHiddenFrame())
01780                 {
01781                     // If we are the grab frame op then check that the current layer is not
01782                     // hidden. If so then disallow
01783                     OpSt.Greyed = TRUE; 
01784                     // Load reason why operation is disabled
01785                     DisableReason = String_256(_R(IDS_FRAMEISHIDDEN));
01786                     if (pUIDescription)
01787                         *pUIDescription = DisableReason;    
01788                 }
01789                 else if (!Empty)
01790                 {
01791                     // Yes, so we are allowed to grab the frame or all the frames
01792                     OpSt.Greyed = FALSE;
01793                 }
01794                 else
01795                 {
01796                     OpSt.Greyed = TRUE; 
01797                     // Load reason why operation is disabled
01798                     DisableReason = String_256(_R(IDS_NO_VISIBLE_OBJECTS));
01799                     if (pUIDescription)
01800                         *pUIDescription = DisableReason;            
01801                 }           
01802             }
01803             else
01804             { 
01805                 // No, so we are greyed
01806                 OpSt.Greyed = TRUE;
01807             }
01808         }
01809         else 
01810         {
01811             // No selected spread, so we are greyed
01812             OpSt.Greyed = TRUE;
01813 
01814             // Load reason why operation is disabled
01815             DisableReason = String_256(_R(IDS_NO_DOC));
01816             if (pUIDescription)
01817                 *pUIDescription = DisableReason;         
01818         }
01819     }
01820     else
01821     {
01822         // The document is layer based, so we are greyed.
01823         OpSt.Greyed = TRUE;
01824         *pUIDescription = String_256 (_R(IDS_NO_FRAMES));
01825     }
01826 #endif
01827 
01828     return OpSt;   
01829 }
01830 
01831 /********************************************************************************************
01832 
01833 >   OpGrabFrame::OpGrabFrame()
01834 
01835     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01836     Created:    29/4/97
01837     Purpose:    Constructor
01838 
01839 ********************************************************************************************/
01840 
01841 OpGrabFrame::OpGrabFrame()
01842 {
01843     m_pDocument     = NULL;
01844     m_pSpread       = NULL;
01845     m_pLayer        = NULL;
01846     m_pView         = NULL;
01847 
01848     m_pBitmapFilter = NULL;
01849     m_pSelState     = NULL;
01850 
01851     //m_pBitmapData = NULL;
01852 
01853     m_pBrowserPalette   = NULL;
01854 }
01855 
01856 /********************************************************************************************
01857 
01858 >   OpGrabFrame::~OpGrabFrame()
01859 
01860     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01861     Created:    29/4/97
01862     Purpose:    Destructor
01863 
01864 ********************************************************************************************/
01865 
01866 OpGrabFrame::~OpGrabFrame()
01867 {
01868     if (m_pBitmapFilter != NULL)
01869     {
01870         delete m_pBitmapFilter;
01871         m_pBitmapFilter = NULL;
01872     }
01873 
01874     if (m_pSelState != NULL)
01875     {
01876         delete m_pSelState;
01877         m_pSelState = NULL;
01878     }
01879 
01880     /* if (m_pBitmapData != NULL)
01881     {
01882         delete m_pBitmapData;
01883         m_pBitmapData = NULL;
01884     } */
01885 
01886     if (m_pBrowserPalette != NULL)
01887     {
01888         CCFree(m_pBrowserPalette);
01889         m_pBrowserPalette = NULL;
01890     }
01891 }
01892 
01893 /************************************************************************************************************
01894 
01895 >   void OpGrabFrame::Do(OpDescriptor * pOpDesc)
01896 
01897     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01898     Created:    23/4/97
01899     Inputs:     OpDescriptor (unused)
01900     Outputs:    -
01901     Returns:    -
01902     Purpose:    Tries to grab the selected animation frame (i.e. layer).
01903 
01904     This Op can be invoked under a number of circumstances:-
01905      1. When the preview dialog is open. 
01906           Dissplay the bitmap corresponding to the selected frame layer.
01907           If the selected frame layer is not in the Preview list (i.e has not been generated)   
01908           then generate the bitmap and add it to the list of bitmaps which be will included in the Preview.
01909      2. When the preview dialog is closed.
01910           In this case we need to generate the bitmap corresponding to the selected Frame layer.
01911     
01912 ****************************************************************************************************************/
01913 
01914 void OpGrabFrame::Do( OpDescriptor * pOpDesc )
01915 {
01916     DoWithParam(pOpDesc, NULL);
01917     return;
01918 }
01919 
01920 /********************************************************************************************
01921 
01922 >   void OpGrabFrame::DoWithParam(OpDescriptor * pOpDesc, Param* pParam)
01923 
01924     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com> (From Neville code.)
01925     Created:    21/05/97
01926     Inputs:     OpDescriptor (unused)
01927                 pParam  - NULL      - means grab the active frame
01928                         - Param1 = pLayer   - means grab the specified layer
01929     Outputs:    -
01930     Returns:    -
01931     Purpose:    Regenerate the bitmap associated with the active frame layer.
01932     Errors:     -
01933     SeeAlso:    -
01934 
01935 ********************************************************************************************/
01936 void OpGrabFrame::DoWithParam(OpDescriptor * pOpDesc, OpParam* pParam)
01937 {
01938 //  ERROR3IF(pParam == NULL, "OpGrabFrame::DoWithParam - NULL Param passed in");
01939     
01940     // Get useful data and set up items before starting the grab process
01941     if (!StartGrab())
01942     {
01943         // We failed to grab the frame
01944         FailAndExecute();
01945         End();
01946         return; 
01947     } 
01948 
01949     // If a parameter has been supplied then this should be a layer pointer, which we
01950     // should then use to grab the frame
01951     // Otherwise, we assume we must grab the active frame (StartGrab sets m_pLayer to the active layer)
01952     if (pParam != NULL)
01953     {
01954         // recover the layer pointer that has been specified
01955         Layer* pLayer = (Layer *) (void *) pParam->Param1;
01956         if (pLayer)
01957         {
01958             ERROR3IF(!pLayer->IS_KIND_OF(Layer), "OpParam passed is not a Layer");
01959             
01960             // Note the layer we are expected to grab in our class variable
01961             m_pLayer = pLayer;
01962 
01963             // Set up the visibility of the other layers using this layer
01964             // as the new temporary and acting active layer
01965             FrameSGallery::FixOtherLayersFromActive(m_pLayer);
01966         }
01967     }
01968 
01969     // Are we trying to grab a hidden frame?
01970     if (m_pLayer->IsHiddenFrame())
01971     {
01972         // yes, tell the user
01973         InformError(_R(IDS_FRAMEISHIDDEN));
01974         //ERROR3IF(m_pLayer->IsHiddenFrame(),"OpGrabFrame::DoWithParam Frame is hidden");
01975         // and then fail
01976         FailAndExecute();
01977         End();
01978         return; 
01979     }
01980 
01981     // If required, allow the op to get a filename from the user.
01982     // This also allows them access to the options via the button on the save dialog box.
01983     // This is why we must do this first rather than after we have generated the frames.
01984     if (!GetFileNameFromUser())
01985     {
01986         // We failed to grab the frame
01987         FailAndExecute();
01988         End();
01989         return; 
01990     } 
01991 
01992     // Get our static pointer to the Preview Dialog.
01993     PreviewDialog* pPreviewDlg = PreviewDialog::GetPreviewDialog();
01994     // If the preview dialog is already open, find the selected frame layer.
01995     if (pPreviewDlg)
01996         pPreviewDlg->StopPreviewing();
01997     
01998     // Go and do the work to grab the frame
01999     KernelBitmap* pBitmap = GrabFrame();
02000     if (pBitmap == NULL)
02001     {
02002         // We failed to grab the frame.
02003         // Try and put back the selection that we recorded at the start
02004         PutBackTheSelection();
02005         FailAndExecute();
02006         End();
02007         return; 
02008     } 
02009 
02010     // If we have grabbed the non-active layer then make sure the active layer
02011     // is set up as current
02012     Layer *pActiveLayer = m_pSpread->FindActiveLayer();
02013     if (pActiveLayer && m_pLayer != pActiveLayer)
02014         FrameSGallery::FixOtherLayersFromActive(pActiveLayer);
02015 
02016     // Clean up after the grabbing process.
02017     if (!EndGrab())
02018     {
02019         // We failed to clean up after grabbing the frame.
02020         FailAndExecute();
02021         End();
02022         return; 
02023     } 
02024 
02025     // Add this bitmap and layer pairing to our export list
02026     if (!m_ExportParams.AddLayerAndBitmap(m_pLayer, pBitmap))
02027     {
02028         FailAndExecute();
02029         End();
02030         return; 
02031     }
02032 
02033     // Open the preview dialog, and display the selected frame.
02034     if(!PreviewAnimation())
02035     {
02036         // We failed to preview the bitmap
02037         FailAndExecute();
02038         End();
02039         return; 
02040     }
02041 
02042     // Finish the operation
02043     End(); 
02044 
02045     return;
02046 }
02047 
02048 /********************************************************************************************
02049 
02050 >   BOOL OpGrabFrame::StartGrab()
02051 
02052     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02053     Created:    29/4/97
02054     Inputs:     
02055     Returns:    True if worked ok, False otherwise
02056     Purpose:    Tries to set up useful items prior to doing the grab.
02057 
02058 ********************************************************************************************/
02059 
02060 BOOL OpGrabFrame::StartGrab()
02061 {
02062     // Is there a selected Document?
02063     m_pDocument = Document::GetSelected();
02064     if (m_pDocument == NULL)
02065     {
02066         ERROR3("Called OpGrabFrame with no selected document!");
02067         return FALSE; 
02068     }
02069 
02070     // Is there a selected spread?
02071     m_pSpread = Document::GetSelectedSpread();
02072     if (m_pSpread == NULL)
02073     {
02074         ERROR3("Called OpGrabFrame with no selected spread!");
02075         return FALSE; 
02076     }
02077 
02078     // Is there a selected view?
02079     m_pView = DocView::GetSelected();
02080     if (m_pView == NULL)
02081     {
02082         ERROR3("Called OpGrabFrame with no selected view!");
02083         return FALSE; 
02084     }
02085 
02086     // Check that all visible layers are actually frame layers
02087     FrameSGallery::EnsureFrameLayerIntegrity(m_pSpread);
02088 
02089     // yes, so check if there is an active layer and try to grab it
02090     m_pLayer = m_pSpread->FindActiveLayer();
02091     if (m_pLayer == NULL)
02092     {
02093         ERROR3("Called OpGrabFrame with no active layer!");
02094         return FALSE; 
02095     }
02096 
02097     // Find all objects on this spread from the specified layer,
02098     // selected or unselected, and get the bounding them.
02099     // Range Control parameters are:-
02100     // Include selected nodes - we want TRUE.
02101     // Include Unselected nodes - we want TRUE.
02102     // Cross layers - we want TRUE
02103     // Ignore locked layers - we want FALSE so that we include locked layers.
02104     // IsRenderable if set then calls NeedsToRender - we want TRUE
02105     // Ignore invisible layers - we want FALSE so that we don't include invisible layers.
02106     //Range SearchRange(m_pLayer, NULL, RangeControl(TRUE, TRUE, TRUE, FALSE, TRUE, FALSE)); 
02107 
02108     // We need to invalidate the region
02109     /* if (!DoInvalidateNodesRegions(SearchRange, TRUE))
02110     {
02111         return FALSE; 
02112     } */
02113 
02114     /* if (!DoStartSelOp(FALSE,FALSE))  // Try to record the selection state , don't render the blobs though 
02115     {
02116         return FALSE; 
02117     }*/
02118 
02119     // Remember the selection so that we can put it back at the end of the operation
02120     RememberTheSelection();
02121 
02122     // Copy all the current animation parameters from the spread into our export
02123     // params.
02124     m_ExportParams.SetSpreadAnimPropertiesParam(m_pSpread->GetSpreadAnimPropertiesParam());
02125 
02126     return TRUE;
02127 }
02128 
02129 /********************************************************************************************
02130 
02131 >   virtual BOOL OpGrabFrame::RememberTheSelection()
02132 
02133     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02134     Created:    19/6/97
02135     Returns:    True if worked ok, False otherwise
02136     Purpose:    Tries to remember the current selection state so that we can put it back
02137                 at the end of the operation.
02138                 Don't error if it fails as the loss of the selection is no great hardship
02139                 when memory is tight!
02140 
02141 ********************************************************************************************/
02142 
02143 BOOL OpGrabFrame::RememberTheSelection()
02144 {
02145     // Create a SelectionState object
02146     m_pSelState = new SelectionState(); 
02147     if (m_pSelState == NULL)
02148     {
02149         return FALSE; // Failure 
02150     }
02151 
02152     // We have managed to create a SelectionState instance, now lets try and 
02153     // record the current selections 
02154     if (!m_pSelState->Record())  // We failed to allocate enough memory to store the selection state
02155     {
02156         // There was insufficient memory to record the selections 
02157         delete m_pSelState;     // Delete the selection state 
02158         m_pSelState = NULL; 
02159         return FALSE; 
02160     }
02161 
02162     return TRUE;
02163 }
02164 
02165 /********************************************************************************************
02166 
02167 >   virtual BOOL OpGrabFrame::PutBackTheSelection()
02168 
02169     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02170     Created:    19/6/97
02171     Returns:    True if worked ok, False otherwise
02172     Purpose:    Tries to put back the remembered selection state at the start of the operation.
02173 
02174 ********************************************************************************************/
02175 
02176 BOOL OpGrabFrame::PutBackTheSelection()
02177 {
02178     if (m_pSelState == NULL)
02179         return FALSE;
02180     
02181     BOOL RestoreSelBlobs = TRUE; //FALSE;
02182     BOOL RemoveBlobs = FALSE; //TRUE;
02183     // Restores the recorded selected state   
02184     m_pSelState->Restore(RestoreSelBlobs, RemoveBlobs);
02185 
02186     delete m_pSelState;
02187     m_pSelState = NULL;
02188 
02189     return TRUE;
02190 }
02191 
02192 /********************************************************************************************
02193 
02194 >   KernelBitmap* OpGrabFrame::GrabFrame()
02195 
02196     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02197     Created:    29/4/97
02198     Inputs:     
02199     Returns:    KernelBitmap if worked ok, NULL otherwise
02200     Purpose:    Tries to grab the currently selected frame/layer into a bitmap.
02201 
02202 ********************************************************************************************/
02203 
02204 KernelBitmap* OpGrabFrame::GrabFrame()
02205 {
02206     ERROR2IF(m_pDocument == NULL,FALSE,"GrabFrame bad document pointer");
02207     ERROR2IF(m_pSpread == NULL,FALSE,"GrabFrame bad spread pointer");
02208     ERROR2IF(m_pLayer == NULL,FALSE,"GrabFrame bad layer pointer");
02209     ERROR2IF(m_pView == NULL,FALSE,"GrabFrame bad view pointer");
02210 
02211     // Create a special Bitmap filter, that creates a bitmap
02212     // and puts it in the tree   
02213     ERROR3IF(m_pBitmapFilter != NULL,"Already have a pBitmapFilter!");
02214     m_pBitmapFilter = new GrabFrameFilter();
02215     if (m_pBitmapFilter == NULL)
02216     {
02217         return NULL; 
02218     }
02219 
02220     // Get the filter to work out the new rectangle 
02221     m_pBitmapFilter->SetUpClippingRectangleForExport(m_pSpread, DRAWING);
02222     DocRect NewBoundingRect = m_pBitmapFilter->GetClipRect();
02223     // Save away the new bounding rectangle
02224     m_pSpread->SetAnimationBoundingRect(NewBoundingRect);
02225     m_ExportParams.SetAnimationBoundingRect(NewBoundingRect);
02226 
02227     // Save away the quality that this was grabbed at
02228     Quality NewQuality = m_pView->RenderQuality;
02229     m_pSpread->SetAnimationQuality(NewQuality);
02230 
02231     // Check all the layers to see if they contain a single bitmap which we can use
02232     // instead of generating one.
02233     // This will mark all valid single bitmaps using the reference in the layer
02234     if (!CheckAllForSingleBitmaps(m_pSpread, m_pBitmapFilter))
02235     {
02236         delete m_pBitmapFilter;
02237         m_pBitmapFilter = NULL;
02238         return NULL; 
02239     } 
02240 
02241     // Check if we are grabbing a changed background layer frame, if it is then
02242     // we will then clear the edited bit on this. Once this happens then if the
02243     // user grabs all frames then the dependent frames wont be updated.
02244     if (m_pLayer->IsEdited() && m_pLayer->IsSolid())
02245     {
02246         // Mark all frames above this as edited until we reach the last frame
02247         // OR we hit a solid/background layer.
02248         Layer * pFrame = m_pLayer->FindNextFrameLayer();
02249         while (pFrame != NULL && !pFrame->IsSolid())
02250         {
02251             // Mark that frame as edited
02252             pFrame->SetEdited(TRUE);
02253             pFrame = pFrame->FindNextFrameLayer();
02254         }
02255     }
02256 
02257     // Check to see if we have a single bitmap on the layer which is stored
02258     // in a NodeBitmap at a 1:1 scale and is 8bpp or less and the palette matches
02259     // the present options.
02260     // If it passes all these tests, then set pBitmapToCreate to be that bitmap.
02261     // Otherwise, we will need to go and convert the current frame into a bitmap
02262     KernelBitmap* pBitmapToCreate = NULL;
02263     //if (!CheckIfSingleBitmap(m_pLayer, &pBitmapToCreate))
02264     // If there is a referenced bitmap then we can use this instead of generating one
02265     pBitmapToCreate = m_pLayer->GetReferencedBitmap();
02266     if (pBitmapToCreate == NULL)
02267     {
02268         // Grab the frame
02269 
02270 
02271         // As this will affect us during grabbing, we should force it into the known
02272         // non-interferring state
02273         BOOL CurrentVisEdState = Layer::ActiveLayerVisibleAndEditable;
02274         Layer::ActiveLayerVisibleAndEditable = FALSE;
02275         // The all visible flag will also do this for us. 
02276         Document* pDoc = m_pSpread->FindParentDocument();
02277         BOOL CurrentAllVisibleState = FALSE;
02278         if (pDoc != NULL)
02279         {
02280             CurrentAllVisibleState = pDoc->IsAllVisible();
02281             pDoc->SetAllVisible(FALSE);
02282         }
02283         
02284         // Go and convert the frame into its bitmap form
02285         pBitmapToCreate = GrabTheFrame();
02286 
02287         // Put back the active layer's visibilty and selection
02288         Layer::ActiveLayerVisibleAndEditable = CurrentVisEdState;
02289         // Put back the all visible state
02290         if (pDoc != NULL)
02291             pDoc->SetAllVisible(CurrentAllVisibleState);
02292     }
02293 
02294     // Note the capture quality that the frame was captured at but only if we worked correctly
02295     if (pBitmapToCreate)
02296         m_pLayer->SetCaptureQuality(NewQuality);
02297 
02298     // remove the filter as we have no more use for it
02299     delete m_pBitmapFilter;
02300     m_pBitmapFilter = NULL;
02301 
02302     // Clear the edited flag on the layer
02303     m_pLayer->SetEdited(FALSE);
02304 #ifdef _DEBUG
02305     // Tell the frame gallery to update its display of the frame
02306     BROADCAST_TO_ALL(LayerMsg(m_pLayer, LayerMsg::REDRAW_LAYER));
02307 #endif
02308 
02309     // return the bitmap to the caller
02310     return pBitmapToCreate;
02311 }
02312 
02313 /********************************************************************************************
02314 
02315 >   KernelBitmap* OpGrabFrame::GrabTheFrame()
02316 
02317     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02318     Created:    11/6/97
02319     Inputs:     
02320     Returns:    KernelBitmap if worked ok, NULL otherwise
02321     Purpose:    Tries to grab the currently selected frame/layer into a bitmap.
02322                 Same as GrabFrame but assumes that the filter to do the grab, m_pBitmapFilter,
02323                 is already present.
02324 
02325 ********************************************************************************************/
02326 
02327 KernelBitmap* OpGrabFrame::GrabTheFrame()
02328 {
02329     ERROR2IF(m_pDocument == NULL,FALSE,"GrabFrame bad document pointer");
02330     ERROR2IF(m_pLayer == NULL,FALSE,"GrabFrame bad layer pointer");
02331     ERROR2IF(m_pBitmapFilter == NULL,FALSE,"GrabFrame m_pBitmapFilter pointer");
02332     
02333     // Tell it about the layer that is being captured
02334     // This supplies the name of the bitmap and the export parameters
02335     m_pBitmapFilter->SetLayerBeingCaptured(m_pLayer);
02336 
02337     KernelBitmap* pBitmapToCreate = NULL;
02338     if (!m_pBitmapFilter->DoCreateBitmap(this, m_pDocument, &pBitmapToCreate) || pBitmapToCreate == NULL)
02339     {
02340         return NULL; 
02341     }
02342 
02343     // Copy across the delay from the layer (Andy 5/1/01)
02344     DWORD delay = m_pLayer->GetFrameDelay();
02345     pBitmapToCreate->SetDelay(delay);
02346 
02347     // Make the layer remember this bitmap as the one that was generated
02348     if (!m_pLayer->SetGeneratedBitmap(pBitmapToCreate))
02349     {
02350         ERROR3("Couldn't add bitmap to layer!");
02351         if (pBitmapToCreate)
02352             delete pBitmapToCreate;
02353         return NULL; 
02354     }
02355 
02356     // DO NOT unset the edited flag. This version is used in GrabAllFrames and we need the
02357     // edited flags present until we have finished grabbing so that we can work out dependent
02358     // layers.
02359 
02360     // return the bitmap to the caller
02361     return pBitmapToCreate;
02362 }
02363 
02364 /********************************************************************************************
02365 
02366 >   BOOL OpGrabFrame::EndGrab()
02367 
02368     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02369     Created:    29/4/97
02370     Inputs:     
02371     Returns:    True if worked ok, False otherwise
02372     Purpose:    Tries to clean up after doing the grab.
02373 
02374 ********************************************************************************************/
02375 
02376 BOOL OpGrabFrame::EndGrab()
02377 {
02378     // Try and put back the selection that we recorded at the start
02379     PutBackTheSelection();
02380 
02381     // Make sure that the new selection is up to date
02382     //Range * pSelRange = GetApplication()->FindSelection();
02383 /*  if (pSelRange == NULL || !DoInvalidateNodesRegions(*pSelRange, TRUE))
02384     {
02385         // We failed to invalidate the region
02386         return FALSE; 
02387     } */
02388 
02389 /*  // Recover the active layer again and make sure that it is being shown correctly.
02390     ERROR2IF(m_pSpread == NULL,FALSE,"bad spread in EndGrab()");
02391     Layer *pLayer = m_pSpread->FindActiveLayer();
02392     ERROR2IF(pLayer == NULL,"No active layer in EndGrab()")
02393     if (pLayer)
02394     {
02395         FrameSGallery::FixOtherLayersFromActive(pLayer);
02396     } */
02397 
02398     return TRUE;
02399 }
02400 
02401 /********************************************************************************************
02402 
02403 >   BOOL OpGrabFrame::GetFileNameFromUser()
02404 
02405     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02406     Created:    7/7/97
02407     Returns:    True if worked ok, False otherwise
02408     Purpose:    Gives the operation chance to get the filename from the user.
02409                 In this baseclass version we do nothing as we preview a single frame and
02410                 so have no need of a filename.
02411 
02412 ********************************************************************************************/
02413 
02414 BOOL OpGrabFrame::GetFileNameFromUser()
02415 {
02416     // Baseclass version, do nothing
02417     return TRUE;
02418 }
02419 
02420 /********************************************************************************************
02421 
02422 >   BOOL OpGrabFrame::PreviewAnimation()
02423 
02424     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02425     Created:    29/4/97
02426     Returns:    True if worked ok, False otherwise
02427     Purpose:    Tries to preview the frames that have been grabbed.
02428                 Uses the stored animation details in m_ExportParams
02429 
02430 ********************************************************************************************/
02431 
02432 BOOL OpGrabFrame::PreviewAnimation()
02433 {
02434     // Copy all the current animation parameters from the spread into our export
02435     // params.
02436     m_ExportParams.SetSpreadAnimPropertiesParam(m_pSpread->GetSpreadAnimPropertiesParam());
02437 
02438     // See if there is a currently open preview dialog box
02439     PreviewDialog * pPreviewDialog = PreviewDialog::GetPreviewDialog();
02440 
02441     // Check that we have a list of bitmaps to preview. If not then complain bitterly.
02442     // Hidden frames allow us to get this far.
02443     if (m_ExportParams.GetBitmapCount() == 0)
02444     {
02445         // If the preview dialog is open then force it into an idle state
02446         if (pPreviewDialog != NULL)
02447             pPreviewDialog->SetDialogToIdleState();
02448         
02449         // tell the user about the problems
02450         InformError(_R(IDS_NOFRAMESTOPREVIEW));
02451         return FALSE;
02452     }
02453 
02454     // If the preview dialog is currently open, pass it the list of bitmaps.
02455     // We must do this on all types of preview e.g. save, as we will have stopped
02456     // the animation before previewing and so we need to ensure that the preview
02457     // dialog box is restored to a known state.
02458     if (pPreviewDialog != NULL)
02459     {
02460         // Pass the preview dialog box the new list of bitmaps
02461         pPreviewDialog->SetBitmapList(&m_ExportParams);
02462 
02463         PreviewDialog::ToggleViaBitmapGallery (FALSE);
02464         //pPreviewDialog->ToggleViaBitmapGallery (FALSE);
02465         pPreviewDialog->SetPlayAnimation(TRUE);
02466 
02467         // Call the dialog box so that it sets up the necessary states
02468         pPreviewDialog->ReInitDialog();
02469     }
02470 
02471     // This does the actually job in hand, e.g. preview, save, preview in browser
02472     BOOL ok = SaveOrShowTheAnimation(pPreviewDialog, &m_ExportParams);
02473 
02474     return ok;
02475 }
02476 
02477 /********************************************************************************************
02478 
02479 >   BOOL OpGrabFrame::SaveOrShowTheAnimation(PreviewDialog * pPreviewDialog, BitmapExportParam* pExportParam)
02480 
02481     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02482     Created:    4/8/97
02483     Inputs:     pPreviewDialog  the preview dialog box, if open
02484                 pExportParam    the export param which we will use
02485     Returns:    True if worked ok, False otherwise
02486     Purpose:    Tries to actually do the preview operation required.
02487                 In this case we just start up the preview dialog box, if not already open,
02488                 to show the frames that have been grabbed.
02489                 Uses the stored animation details in m_ExportParams
02490 
02491 ********************************************************************************************/
02492 
02493 BOOL OpGrabFrame::SaveOrShowTheAnimation(PreviewDialog * pPreviewDialog, BitmapExportParam* pExportParam)
02494 {
02495     // Only boot up the preview dialog box if it is not already on display
02496     // If it is already on display then we will have already dealt with it
02497     if (pPreviewDialog == NULL)
02498     {
02499         // Invoke the preview operation
02500         OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_PREVIEWDIALOG);
02501         if (pOpDesc)
02502         {
02503             PreviewDialog::ToggleViaBitmapGallery (FALSE);
02504             pOpDesc->Invoke(&m_ExportParams);
02505             pPreviewDialog = PreviewDialog::GetPreviewDialog();
02506             //pPreviewDialog->ToggleViaBitmapGallery (FALSE);
02507         }
02508     }
02509 
02510     return TRUE;
02511 }
02512 
02513 /****************************************************************************************************
02514 
02515 >   BOOL OpGrabFrame::SetSingleBitmapInList()
02516 
02517     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
02518     Created:    14/05/97
02519     Inputs:     -
02520     Returns:    True if worked ok, False otherwise.
02521     Purpose:    If the Preview Dialog is open and we regenerate a single frame,
02522                 this function allows us to update our Bitmap list in the Preview Dialog. 
02523 
02524 ******************************************************************************************************/
02525 
02526 /* BOOL OpGrabFrame::SetSingleBitmapInList()
02527 {
02528     // Copy all the current animation parameters from the spread into our export params.
02529     m_ExportParams.SetSpreadAnimPropertiesParam(m_pSpread->GetSpreadAnimPropertiesParam());
02530 
02531     // Get our static pointer to the Preview Dialog.
02532     PreviewDialog* pPreviewDialog = PreviewDialog::GetPreviewDialog();
02533 
02534     if (!pPreviewDialog)
02535         return FALSE;
02536 
02537     pPreviewDialog->SetRegeneratedBitmapInList(&m_ExportParams);
02538 
02539     return TRUE;
02540 } */
02541 
02542 /******************************************************************************************************
02543 
02544 >   BOOL OpGrabFrame::SetBitmapToListTail()
02545 
02546     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
02547     Created:    14/05/97
02548     Inputs:     -
02549     Returns:    True if worked ok, False otherwise.
02550     Purpose:    If the Preview Dialog is open and we regenerate a single frame, this function
02551                 allows us to add that Bitmap to the head of the preview dialog bitmap list. 
02552 
02553 ********************************************************************************************************/
02554 
02555 /* BOOL OpGrabFrame::SetBitmapToListTail()
02556 {
02557     // Copy all the current animation parameters from the spread into our export params.
02558     m_ExportParams.SetSpreadAnimPropertiesParam(m_pSpread->GetSpreadAnimPropertiesParam());
02559 
02560     // Get our static pointer to the Preview Dialog.
02561     PreviewDialog* pPreviewDialog = PreviewDialog::GetPreviewDialog();
02562 
02563     if (!pPreviewDialog)
02564         return FALSE;
02565 
02566     // Add this bitmap to the list tail.
02567     pPreviewDialog->SetBitmapToListTail(&m_ExportParams);
02568 
02569     return TRUE;
02570 } */
02571 
02572 /****************************************************************************************************
02573 
02574 >   BOOL OpGrabFrame::SetFullBitmapList()
02575 
02576     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
02577     Created:    14/05/97
02578     Inputs:     SetFlagState: If this is specified, it allows us to set the state of certain flags 
02579                 in the Preview dialog.
02580     Returns:    True if worked ok, False otherwise.
02581     Purpose:    If the Preview Dialog is open and we regenerate the frames in the animation,
02582                 this function allows us to update our Bitmap list in the Preview Dialog. 
02583 
02584 ******************************************************************************************************/
02585 
02586 /* BOOL OpGrabFrame::SetFullBitmapList(BOOL SetFlagState)
02587 {
02588     // Copy all the current animation parameters from the spread into our export params.
02589     m_ExportParams.SetSpreadAnimPropertiesParam(m_pSpread->GetSpreadAnimPropertiesParam());
02590 
02591     // Get our static pointer to the Preview Dialog.
02592     PreviewDialog* pPreviewDialog = PreviewDialog::GetPreviewDialog();
02593 
02594     if (!pPreviewDialog)
02595         return FALSE;
02596 
02597     // If the animation is playing, stop the animation before we pass it our new list of bitmaps.
02598     if(pPreviewDialog->GetPlayAnimation())
02599         pPreviewDialog->SetPlayAnimation(FALSE);
02600 
02601     pPreviewDialog->SetBitmapList(&m_ExportParams);
02602 
02603     // Set the state of the preview dlg flags.
02604     if(SetFlagState)
02605     {
02606         // Call the dialog box so that it sets up the necessary states
02607         pPreviewDialog->ReInitDialog();
02608     }
02609 
02610     // Play the animation.
02611     pPreviewDialog->SetPlayAnimation(TRUE);
02612 
02613     return TRUE;
02614 } */
02615 
02616 
02617 /********************************************************************************************
02618 
02619 >   BOOL OpGrabFrame::CheckIfSingleBitmap(Layer * pLayer, KernelBitmap ** ppBitmap)
02620 
02621     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02622     Created:    16/6/97
02623     Inputs:     pLayer  - the layer we need to check
02624     Outputs:    The bitmap to use for this frame
02625     Returns:    True if found a single bitmap on the frame/layer. False otherwise.
02626     Purpose:    For finding out if there is a single bitmap on the layer which is stored
02627                 in a NodeBitmap at a 1:1 scale and is 8bpp or less and the palette matches
02628                 the present options. This palette testing is now done after this
02629                 If it passes all these tests, then set pBitmap to be that bitmap and return
02630                 True. Also note in the layer that this bitmap can possibly be used to specify
02631                 this layer. We can only say for sure when we have checked that its palette
02632                 matches the current animation options.
02633     SeeAlso:    CheckAllForSingleBitmaps;
02634 
02635 ********************************************************************************************/
02636 
02637 BOOL OpGrabFrame::CheckIfSingleBitmap(Layer * pLayer, KernelBitmap ** ppBitmap)
02638 {
02639     ERROR2IF(pLayer == NULL, FALSE,"CheckIfSingleBitmap bad layer pointer");
02640     ERROR2IF(ppBitmap == NULL, FALSE,"CheckIfSingleBitmap bad bitmap pointer");
02641 
02642     // Get some of the current export options
02643     DocRect BoundingRect    = m_ExportParams.GetAnimationBoundingRect();
02644     ERROR3IF(BoundingRect.IsEmpty(),"Bounding rect not set up");
02645 //  PALETTE_COLOURS Palette = m_ExportParams.GetPaletteCols();
02646 //  WEB_PALETTE WebPalette  = m_ExportParams.GetPalette();
02647 
02648     KernelBitmap * pBitmap  = NULL;
02649     BOOL Scaled1to1         = FALSE;
02650     BOOL PaletteOk          = FALSE;
02651     BOOL InsideBoundingRect = TRUE;
02652     BOOL FullFirstFrame     = TRUE;
02653     UINT32 Bpp              = 0;
02654     INT32 NodeCount         = 0;
02655     NodeBitmap *pNodeBmp    = NULL;
02656 
02657     // check if we are the first animation frame, if so then we the bitmap must be the same
02658     // size as the animation bounding rect. Otherwise, the first frame will not be the size
02659     // of the animation which highlights a bug in MS IE 3.0
02660     Layer * pPreviousFrame = pLayer->FindPrevFrameLayer();
02661 
02662     Node * pNode = pLayer->FindFirstChild();
02663     while (pNode != NULL)
02664     {
02665         // If the node renders something on the screen then we count it as this will mean that
02666         // the single bitmap does not fully define the layer.
02667         // It ignores attributes, hidden nodes, etc - nodes that don't render anything themselves.
02668         if (pNode->IsBounded())
02669             NodeCount++;
02670 
02671         // We need to note any NodeBitmap nodes 
02672         if (pNode->IS_KIND_OF(NodeBitmap) && NodeCount == 1)
02673         {
02674             // Convert the node to a nodebitmap so we can get at the useful NodeBitmap
02675             // related data
02676             pNodeBmp = (NodeBitmap *)pNode;
02677             
02678             // Get the size and position of the node bitmap
02679             DocRect rect = pNodeBmp->GetBoundingRect(TRUE, FALSE);
02680 
02681             // If we have no previous frame then check that the first frame is the
02682             // size of the animation
02683             if (pPreviousFrame == NULL)
02684             {
02685                 DocRect AniBoundingRect = m_ExportParams.GetAnimationBoundingRect();
02686                 ERROR3IF(AniBoundingRect.IsEmpty(),"CheckIfSingleBitmap Animation bounding rect not set up!");
02687 
02688                 // REMEMBER account for rounding errors
02689                 const INT32 delta = 50;
02690                 if (
02691                     (AniBoundingRect.lo.x >= (rect.lo.x - delta)) && (AniBoundingRect.lo.x <= (rect.lo.x + delta)) &&
02692                     (AniBoundingRect.hi.x >= (rect.hi.x - delta)) && (AniBoundingRect.hi.x <= (rect.hi.x + delta)) &&
02693                     (AniBoundingRect.lo.y >= (rect.lo.y - delta)) && (AniBoundingRect.lo.y <= (rect.lo.y + delta)) &&
02694                     (AniBoundingRect.hi.y >= (rect.hi.y - delta)) && (AniBoundingRect.hi.y <= (rect.hi.y + delta))
02695                     )
02696                 {
02697                     FullFirstFrame = TRUE;
02698                 }
02699                 else
02700                 {
02701                     FullFirstFrame = FALSE;
02702                 }
02703             }
02704             
02705             // Get the bitmap stored inside the node, if any
02706             pBitmap = pNodeBmp->GetBitmap();
02707             if (pBitmap)
02708             {
02709                 // Get the width/height of the bitmap in millipoints
02710                 INT32 BmpWidth = pBitmap->GetRecommendedWidth();
02711                 INT32 BmpHeight = pBitmap->GetRecommendedHeight();
02712 
02713                 // Get the Width of the Bitmap in Millipoints
02714                 INT32 Width  = INT32(pNodeBmp->Parallel[0].Distance(pNodeBmp->Parallel[1]));
02715                 INT32 Height = INT32(pNodeBmp->Parallel[1].Distance(pNodeBmp->Parallel[2]));
02716 
02717                 // REMEMBER account for rounding errors and the orientation being the other
02718                 // way round
02719                 const INT32 delta = 2;
02720                 if ((Width >= BmpWidth - delta && Width <= BmpWidth + delta &&
02721                      Height >= BmpHeight - delta && Height <= BmpHeight + delta) ||
02722                     (Height >= BmpWidth - delta && Height <= BmpWidth + delta &&
02723                      Width >= BmpHeight - delta && Width <= BmpHeight + delta) )
02724                     Scaled1to1 = TRUE;
02725                 
02726                 Bpp = pBitmap->GetBPP();
02727 
02728                 // If the bitmap is 8bpp of less then assume this is ok for now
02729                 // We will check the palette in a second pass
02730                 if (Bpp <= 8)
02731                 {
02732                     PaletteOk = TRUE;
02733                 }
02734 
02735                 /*  // We cannot cope with GLOBAL OPTIMISED palettes at present as we
02736                     // would need to wait until the palette was generated before we could
02737                     // check.
02738                     if (Palette == PALCOL_OPTIMIZED && WebPalette == PAL_LOCAL)
02739                     {
02740                         // Saving local palette so any palette ok
02741                         PaletteOk = TRUE;
02742                     }
02743                     else if (Palette == PALCOL_BROWSER && WebPalette == PAL_GLOBAL)
02744                     {
02745                         // Check if we have a browser palette on this bitmap
02746                         //PaletteOk = pBitmap->IsBrowserPalette();
02747                         // Old way of testing. Too lenient as all it does it check that the palette
02748                         // has the correct colours in it, not that the palette will be the same one
02749                         // that we are going to output as the browser palette
02750                         
02751                         // Obviously, browser palettes can only happen on 8bpp bitmaps
02752                         if (Bpp == 8)
02753                         {
02754                             // First of all, if we haven't already got our palette that we check against
02755                             // then construct it.
02756                             if (m_pBrowserPalette == NULL)
02757                             {
02758                                 UINT32 PaletteSize = UINT32(pow(2,Bpp));
02759                                 m_pBrowserPalette = DIBUtil::AllocateLogPalette(PaletteSize);
02760                                 if (m_pBrowserPalette != NULL)
02761                                 {
02762                                     // Now force it into a browser compatible state
02763                                     BOOL AvoidSystemColours = TRUE;
02764                                     PaletteManager::MakePaletteBrowserCompatible(m_pBrowserPalette, AvoidSystemColours);
02765                                 }
02766                             }
02767                             
02768                             INT32 TransColour = -1;
02769                             pBitmap->GetTransparencyIndex(&TransColour);
02770 
02771                             if (m_pBrowserPalette != NULL)
02772                             {
02773                                 PaletteOk = pBitmap->ArePalettesTheSame(m_pBrowserPalette, TransColour);
02774                             }
02775                             else
02776                             {
02777                                 ERROR3("Couldn't allocate browser palette");
02778                                 PaletteOk = FALSE;
02779                             }
02780                         }
02781                         else
02782                             PaletteOk = FALSE;
02783                     }
02784                 } */
02785 
02786                 if (Scaled1to1 && PaletteOk && !rect.IsEmpty() && !BoundingRect.IsEmpty())
02787                 {
02788                     // Work out the position of the bitmap relative to the top left hand
02789                     // corner of the bounding rectangle in terms of pixels and put this
02790                     // in the bitmap 
02791                     MILLIPOINT LeftOffsetMP = rect.lo.x - BoundingRect.lo.x;
02792                     MILLIPOINT TopOffsetMP = BoundingRect.hi.y - rect.hi.y;
02793                     if (LeftOffsetMP >= 0 && TopOffsetMP >= 0)
02794                     {
02795                         const UINT32 dpi = 96;
02796                         UINT32 LeftOffset = LeftOffsetMP * dpi/72000;
02797                         UINT32 TopOffset = TopOffsetMP * dpi/72000;
02798 
02799                         pBitmap->SetLeftOffset(LeftOffset);
02800                         pBitmap->SetTopOffset(TopOffset);
02801                         InsideBoundingRect = TRUE;
02802                     }
02803                 }
02804             }
02805         }
02806 
02807         pNode = pNode->FindNext();
02808     }
02809 
02810     // If all these checks are TRUE then return the bitmap as the source of the frame
02811     if (pBitmap != NULL && Scaled1to1 && Bpp <= 8 && NodeCount == 1 &&
02812         PaletteOk && InsideBoundingRect && FullFirstFrame)
02813     {
02814         if (ppBitmap)
02815             *ppBitmap = pBitmap;
02816 
02817         // Make the layer remember this bitmap
02818         // Remember this bitmap as the reference one
02819         pLayer->SetReferencedBitmap(pBitmap);
02820 
02821         //TRACEUSER( "Neville", _T("Using single bitmap\n"));
02822 
02823         return TRUE;
02824     }
02825 
02826     // Ensure that we have no reference saved
02827     pLayer->SetReferencedBitmap(NULL);
02828             
02829     return FALSE;
02830 }
02831 
02832 
02833 /********************************************************************************************
02834 
02835 >   BOOL OpGrabFrame::CheckAllForSingleBitmaps(Spread * pSpread)
02836 
02837     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02838     Created:    9/7/97
02839     Inputs:     pLayer          - the layer we need to check
02840                 pBitmapFilter   - a grab frame filter we can use 
02841     Returns:    True if worked correctly, False otherwise.
02842     Purpose:    For going through all the frames and seeing if there is a single bitmap
02843                 on the frame/layer which is stored in a NodeBitmap at a 1:1 scale and is 8bpp
02844                 or less and the palette matches the present options.
02845                 We use the grab frame filter as this is derived off GIF filter and this must
02846                 already cope with this when loading animations so that it can set the animation
02847                 options accordingly.
02848 
02849 ********************************************************************************************/
02850 
02851 BOOL OpGrabFrame::CheckAllForSingleBitmaps(Spread * pSpread, GrabFrameFilter * pBitmapFilter)
02852 {
02853     ERROR2IF(pSpread == NULL, FALSE,"CheckIfSingleBitmap bad Spread pointer");
02854     ERROR2IF(pBitmapFilter == NULL, FALSE,"CheckIfSingleBitmap bad GrabFrameFilter pointer");
02855 
02856     // So we can do the optimised palette case, we must go though all the
02857     // layers/frames and see if there is a single bitmap present. We don't worry
02858     // about the palette on this first pass. We just set up the referenced bitmap
02859     // to be the single bitmap if it passes all the tests.
02860     KernelBitmap *  pBitmap = NULL;
02861     BOOL Found              = FALSE;
02862     BOOL SolidSet           = FALSE;
02863     BOOL OverlaySet         = FALSE;
02864     BOOL OverlayedBitmapSet = FALSE;
02865     Layer* pCurrentLayer    = pSpread->FindFirstFrameLayer();
02866     Layer* pNextLayer       = NULL;
02867     Layer* pPrevFrameLayer  = NULL;
02868     while (pCurrentLayer != NULL)
02869     {
02870         // Move to the next bitmap in the animation
02871         pNextLayer = pCurrentLayer->FindNextFrameLayer();
02872 
02873         // This is just as a double check
02874         if (pCurrentLayer->IsPseudoFrame())
02875         {
02876             Found = CheckIfSingleBitmap(pCurrentLayer, &pBitmap);
02877             // If the solid flag is set on anything but the last layer then note this
02878             // as dangerous
02879             if (pCurrentLayer->IsSolid() && pNextLayer != NULL)
02880                 SolidSet = TRUE;
02881             if (pCurrentLayer->IsOverlay())
02882             {
02883                 // If overlay is set then we can allow it if the previous bitmap has a restore
02884                 // type of overlay as this may be an animation that we have saved out
02885                 // and then loaded in. If a diff has happened then overlay will be set.
02886                 // We can only ever allow this if the layers consist of all bitmaps as
02887                 // otherwise the layer may be overlaying a vector layer and hence be wrong.
02888                 KernelBitmap * pPrevBitmap = NULL;
02889                 if (pPrevFrameLayer)
02890                     pPrevBitmap = pPrevFrameLayer->GetReferencedBitmap();
02891                 // Check that we have a single reuseable bitmap on this layer plus one of the previous
02892                 if (pPrevBitmap != NULL && pBitmap != NULL)
02893                 {
02894                     GIFDisposalMethod restore = pPrevBitmap->GetAnimationRestoreType();
02895                     // Do we include GDM_NONE? Not for now.
02896                     if (restore != GDM_LEAVE)
02897                     {
02898                         // We cannot use the bitmap so set the reference to NULL
02899                         pCurrentLayer->SetReferencedBitmap(NULL);
02900                         OverlaySet = TRUE;
02901                     }
02902                     else
02903                         OverlayedBitmapSet = TRUE;
02904                 }
02905                 else if (pPrevFrameLayer != NULL)
02906                 {
02907                     // If overlay set on the first frame then ignore
02908                     // We cannot use the bitmap so set the reference to NULL
02909                     pCurrentLayer->SetReferencedBitmap(NULL);
02910                     OverlaySet = TRUE;
02911                 }
02912             }
02913         }
02914 
02915         // Move to the next bitmap in the animation
02916         pPrevFrameLayer = pCurrentLayer;
02917         pCurrentLayer = pNextLayer;
02918     }
02919 
02920     // Find out about the palettes that the bitmaps have
02921     // Our filter has a useful function for this
02922     UINT32 ReqNumberOfColours   = m_ExportParams.GetNumColsInPalette();
02923     BOOL SamePalettes       = FALSE;
02924     BOOL OurBrowserPalette  = FALSE;
02925     BOOL AllHaveBitmaps     = FALSE;
02926     BOOL AllWithinCount     = FALSE; 
02927     UINT32 NumberOfColours  = ReqNumberOfColours;
02928     pBitmapFilter->CheckSingleBitmapsOnSpread(pSpread, &SamePalettes, &OurBrowserPalette, &AllHaveBitmaps,
02929                                               &AllWithinCount, &NumberOfColours);
02930 
02931     PALETTE_COLOURS Palette = m_ExportParams.GetPaletteCols();
02932     WEB_PALETTE WebPalette  = m_ExportParams.GetPalette();
02933     
02934     BOOL OptionsOk = FALSE;
02935     // If OverlaySet is true then we have found an overlay situation which we cannot cope with and
02936     // so will have set the referenced bitmap to null.
02937     if (OverlaySet && AllHaveBitmaps)
02938         AllHaveBitmaps = FALSE;
02939 
02940     // If solid is set on any of the frames then it is too dangerous to reuse any single bitmaps
02941     // We can only allow overlay, if all layers are single bitmaps and the bitmap concerned is
02942     // of type GDM_LEAVE. Otherwise, it is too dangerous.
02943     BOOL BitmapOverlayOk = TRUE;
02944     if (OverlayedBitmapSet && !AllHaveBitmaps)
02945         BitmapOverlayOk = FALSE;
02946 
02947     if (!SolidSet && BitmapOverlayOk)
02948     {
02949         // Check from the most fussy option to the least fussy option
02950         if (Palette == PALCOL_BROWSER && WebPalette == PAL_GLOBAL && OurBrowserPalette)
02951         {
02952             OptionsOk = TRUE;
02953             //TRACEUSER( "Neville", _T("Global browser, palettes ok\n"));
02954         }
02955         else if (Palette == PALCOL_OPTIMIZED && WebPalette == PAL_GLOBAL && SamePalettes && AllHaveBitmaps &&
02956                  NumberOfColours <= ReqNumberOfColours)
02957         {
02958             OptionsOk = TRUE;
02959             //TRACEUSER( "Neville", _T("Global opt, palettes ok\n"));
02960             // Force the global optimised palette to be null for now
02961             pBitmapFilter->SetGlobalOptimisedPalette(NULL);
02962         }
02963         else if (Palette == PALCOL_OPTIMIZED && WebPalette == PAL_LOCAL && AllWithinCount)
02964         {
02965             // Saving local palette so any palette ok but must be within the count
02966             OptionsOk = TRUE;
02967             //TRACEUSER( "Neville", _T("Local Opt, palettes ok\n"));
02968         }
02969     }
02970     
02971     // Now we need to go through the layers again and ratify our check
02972     pCurrentLayer = pSpread->FindFirstFrameLayer();
02973     pBitmap = NULL; 
02974     while (pCurrentLayer != NULL)
02975     {
02976         // This is just as a double check
02977         if (pCurrentLayer->IsPseudoFrame())
02978         {
02979             pBitmap = pCurrentLayer->GetReferencedBitmap();
02980             if (OptionsOk && pBitmap)
02981             {
02982                 // We can use the bitmap instead of generating one
02983                 // So make sure that the generated bitmap is clean out
02984                 pCurrentLayer->SetGeneratedBitmap(NULL);
02985                 // And ensure that the bitmap has the layer's delay
02986                 pBitmap->SetDelay(pCurrentLayer->GetFrameDelay());
02987 
02988                 // If we are in 
02989                 if (Palette == PALCOL_OPTIMIZED && WebPalette == PAL_GLOBAL)
02990                 {
02991                     // If we haven't set up the global optimised palette then do so now
02992                     // Pull it from the first bitmap that we find
02993                     LPLOGPALETTE pOptPal = pBitmapFilter->GetGlobalOptimisedPalette();
02994                     if (pOptPal == NULL)
02995                     {
02996                         pOptPal = DIBUtil::CopyBitmapPaletteIntoLogPalette(pBitmap);
02997                         // Something went a bit wrong
02998                         if (pOptPal == NULL)
02999                             return FALSE;
03000                         pBitmapFilter->SetGlobalOptimisedPalette(pOptPal);
03001                     }
03002                 }
03003             }
03004             else
03005             {
03006                 // We cannot use the bitmap so set the reference to NULL
03007                 pCurrentLayer->SetReferencedBitmap(NULL);
03008             }
03009         }
03010 
03011         // Move to the next bitmap in the animation
03012         pCurrentLayer = pCurrentLayer->FindNextFrameLayer();
03013     }
03014 
03015     return TRUE;
03016 }
03017 
03018 /********************************************************************************************
03019 // End of OpGrabFrame
03020 ********************************************************************************************/
03021 
03022 //------------------------------------------------------------------------------------------
03023 // Methods for the OpGrabAllFrames
03024 //------------------------------------------------------------------------------------------
03025 
03026 // Macro to determine the bytes in a DWORD aligned DIB scanline
03027 #define BYTESPERLINE(Width, BPP) ((WORD)((((DWORD)(Width) * (DWORD)(BPP) + 31) >> 5)) << 2)
03028 
03029 void OpGrabAllFrames::CreateGlobalPalette(DWORD NumColsInPalette, BOOL RegenerateAllFrames)
03030 {
03031     ERROR3IF(!m_pBitmapFilter, "No bitmap filter to use when generating global palette");
03032     if (!m_pBitmapFilter)
03033         return;
03034 
03035     PaletteOptimiser* pPalOpt = new PaletteOptimiser();
03036     if (!pPalOpt)
03037         return;
03038     pPalOpt->Initialise();
03039 
03040     // Go through all the frame layers in the spread and export them
03041     KernelBitmap * pBitmap = NULL;
03042     Layer* pCurrentLayer = NULL;
03043 
03044     // Set the filter to generate preview bitmaps
03045     m_pBitmapFilter->SetGrabMode(GrabFrameFilter::GRABMODE_PREVIEW);
03046 
03047     pBitmap = NULL;
03048     pCurrentLayer = m_pSpread->FindFirstFrameLayer();
03049 
03050     while (pCurrentLayer != NULL)
03051     {
03052         // see if the user has hidden the frame
03053         if (!pCurrentLayer->IsPseudoFrame() || pCurrentLayer->IsHiddenFrame())
03054         {
03055             // It is either an invalid frame or it is hidden. In both cases but especially
03056             // the second we should ensure that if there is a generated bitmap then we
03057             // vape it as it is now out of date.
03058             pCurrentLayer->SetGeneratedBitmap(NULL);
03059 
03060             // Move to the next bitmap in the animation
03061             pCurrentLayer = pCurrentLayer->FindNextFrameLayer();
03062 
03063             // Go to the next frame
03064             continue;
03065         }
03066 
03067         // Set up the visibility of the other layers using this layer
03068         // as the new temporary and acting active layer
03069         FrameSGallery::FixOtherLayersFromActive(pCurrentLayer);
03070         // This is the layer that we are adding to the global palette
03071         m_pLayer = pCurrentLayer;
03072 
03073         // Render a bitmap of the entire image being exported
03074         KernelBitmap* pTestBitmap=NULL;
03075         m_pBitmapFilter->DoCreateBitmap(this, m_pDocument, &pTestBitmap);
03076 
03077         // not enough memory? or no content worth talking about then give up!
03078         if (!pTestBitmap || !pTestBitmap->GetActualBitmap())
03079         {
03080             FailAndExecute();
03081             End();
03082             return;
03083         }
03084 
03085         // We need to pass Gavin a 32bbp bitmap with an empty channel (rather than an
03086         // alpha channel).  Lets quickly create one (I am sure this is not the best way
03087         // of doing this but it will do for now).
03088         UINT32 nPixels = pTestBitmap->GetActualBitmap()->GetBitmapSize() / 3;
03089         RGBQUAD* pNewBitmap = new RGBQUAD[nPixels];
03090         UINT32 width    = pTestBitmap->GetActualBitmap()->GetBitmapInfoHeader()->biWidth;
03091         UINT32 height   = pTestBitmap->GetActualBitmap()->GetBitmapInfoHeader()->biHeight;
03092         BYTE* pOldBitmapBytes = (BYTE*)pTestBitmap->GetActualBitmap()->GetBitmapBits();
03093         UINT32 bytesPerLine = BYTESPERLINE(width, 24);
03094         for (UINT32 y = 0; y < height; ++y)
03095             for (UINT32 x = 0; x < width; x++)
03096             {
03097                 pNewBitmap[y * width + x].rgbBlue       = pOldBitmapBytes[bytesPerLine * y + x * 3 + 0];
03098                 pNewBitmap[y * width + x].rgbGreen      = pOldBitmapBytes[bytesPerLine * y + x * 3 + 1];
03099                 pNewBitmap[y * width + x].rgbRed        = pOldBitmapBytes[bytesPerLine * y + x * 3 + 2];
03100                 pNewBitmap[y * width + x].rgbReserved   = 0;
03101             }
03102 
03103         // add the stats to the palette optimiser
03104         pPalOpt->AddStats(pNewBitmap, nPixels);
03105 
03106         delete pNewBitmap;
03107         delete pTestBitmap;
03108 
03109         // Move to the next bitmap in the animation
03110         pCurrentLayer = pCurrentLayer->FindNextFrameLayer();
03111     }
03112 
03113     // set the global palette
03114     pPalOpt->SnapToBrowserPalette(0);
03115     pPalOpt->SnapToPrimaries(1);
03116     pPalOpt->AddSystemColours((m_pSpread->GetSpreadAnimPropertiesParam().GetUseSystemCols() == TRUE));
03117     pPalOpt->UseBrowserPalette(0);
03118     pPalOpt->SetFast(TRUE);
03119 
03120     INT32 ColoursToOptimise = camMax(2, NumColsInPalette-1);
03121 
03122     // tell the optimiser that we have finished gathering the stats
03123     pPalOpt->GenPalette(ColoursToOptimise);
03124 
03125     LOGPALETTE * pGlobalPal = DIBUtil::AllocateLogPalette(ColoursToOptimise + 1);
03126 
03127     pGlobalPal->palNumEntries = ColoursToOptimise;
03128 
03129     // get the optimised palette from the optimser
03130     pPalOpt->GetPalette( pGlobalPal, ColoursToOptimise);
03131 
03132      // we want to add a transparent colour to this palette
03133     pGlobalPal->palNumEntries = camMin(255,pGlobalPal->palNumEntries+1);
03134 
03135     // the first entry in the palette is special it should be the background colour as it will
03136     // be what is visible if the background is not transparent so swap the first entry into
03137     // the last and set the last
03138     pGlobalPal->palPalEntry[ pGlobalPal->palNumEntries-1 ].peRed    = pGlobalPal->palPalEntry[ 0 ].peRed;
03139     pGlobalPal->palPalEntry[ pGlobalPal->palNumEntries-1 ].peGreen  = pGlobalPal->palPalEntry[ 0 ].peGreen;
03140     pGlobalPal->palPalEntry[ pGlobalPal->palNumEntries-1 ].peBlue   = pGlobalPal->palPalEntry[ 0 ].peBlue;
03141     pGlobalPal->palPalEntry[ pGlobalPal->palNumEntries-1 ].peFlags  = 0;
03142 
03143     DocColour dcol = Page::GetPageColour();
03144     INT32 r = 255, g = 255, b = 255;
03145     dcol.GetRGBValue(&r,&g,&b);
03146 
03147     pGlobalPal->palPalEntry[ 0 ].peRed      = (BYTE)r;
03148     pGlobalPal->palPalEntry[ 0 ].peGreen    = (BYTE)g;
03149     pGlobalPal->palPalEntry[ 0 ].peBlue     = (BYTE)b;
03150     pGlobalPal->palPalEntry[ 0 ].peFlags    = 255; // the transp entry - not renderable
03151 
03152     // remove the optimiser
03153     delete pPalOpt;
03154 
03155     // save this global palette for later
03156     m_pBitmapFilter->SetGlobalOptimisedPalette(pGlobalPal);
03157     m_pBitmapFilter->AlterPaletteContents(pGlobalPal);
03158 
03159     // Undo our change to the filter
03160     m_pBitmapFilter->SetGrabMode(GrabFrameFilter::GRABMODE_FOROUTPUT);
03161 }
03162 
03163 /********************************************************************************************
03164 
03165 >   void OpGrabAllFrames::Do(OpDescriptor * pOpDesc)
03166 
03167     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03168     Created:    22/4/97
03169     Inputs:     OpDescriptor (unused)
03170     Outputs:    -
03171     Returns:    -
03172     Purpose:    Tries to grab the selected animation frame (i.e. layer).
03173     Errors:     -
03174     SeeAlso:    -
03175 
03176 ********************************************************************************************/
03177 
03178 void OpGrabAllFrames::Do( OpDescriptor * pOpDesc )
03179 {
03180     // Get useful data and set up items before starting the grab process
03181     if (!StartGrab())
03182     {
03183         // We failed to grab the frame
03184         FailAndExecute();
03185         End();
03186         return; 
03187     } 
03188 
03189     // If required, allow the op to get a filename from the user.
03190     // This also allows them access to the options via the button on the save dialog box.
03191     // This is why we must do this first rather than after we have generated the frames.
03192     if (!GetFileNameFromUser())
03193     {
03194         // We failed to grab the frame
03195         FailAndExecute();
03196         End();
03197         return; 
03198     } 
03199 
03200     // Get our static pointer to the Preview Dialog.
03201     PreviewDialog* pPreviewDlg = PreviewDialog::GetPreviewDialog();
03202     // If the preview dialog is already open, find the selected frame layer.
03203     BOOL PlayAnimation = TRUE;
03204     if (pPreviewDlg)
03205     {
03206         // Note the current state of the playing
03207         PlayAnimation = pPreviewDlg->GetPlayAnimation();
03208         // Force the dialog into stop mode
03209         pPreviewDlg->StopPreviewing();
03210     }
03211 
03212     // Create a special Bitmap filter, that creates a bitmap
03213     // and puts it in the tree   
03214     ERROR3IF(m_pBitmapFilter != NULL,"Already have a pBitmapFilter!");
03215     m_pBitmapFilter = new GrabFrameFilter();
03216     if (m_pBitmapFilter == NULL)
03217     {
03218         // We failed to grab the frame
03219         // Try and put back the selection that we recorded at the start
03220         PutBackTheSelection();
03221         FailAndExecute();
03222         End();
03223         return; 
03224     }
03225 
03226     // Get the stored cliprect from the spread.
03227     // This may be blank if the frames have not been generated before.
03228     DocRect OldBoundingRect = m_pSpread->GetAnimationBoundingRect();
03229     // Get the filter to work out the new rectangle 
03230     m_pBitmapFilter->SetUpClippingRectangleForExport(m_pSpread, DRAWING);
03231     DocRect NewBoundingRect = m_pBitmapFilter->GetClipRect();
03232     // Save away the new bounding rectangle
03233     m_pSpread->SetAnimationBoundingRect(NewBoundingRect);
03234     m_ExportParams.SetAnimationBoundingRect(NewBoundingRect);
03235     // If they are different then we must regenerate all frames
03236     BOOL RegenerateAllFrames = ms_ForceRefreshOfAllFrames; // used to be = FALSE (sjk)
03237     ms_ForceRefreshOfAllFrames = FALSE; // have used the force refresh
03238 
03239     if (NewBoundingRect != OldBoundingRect)
03240         RegenerateAllFrames = TRUE;
03241 
03242     Quality OldQuality = m_pSpread->GetAnimationQuality();
03243 
03244     // AMB doesn't understand what the following lines were meant to do. Quality
03245     // is a linear scale. And in any case this doesn't compile (unsurprisingly)
03246     // Quality NewQuality = m_pView->RenderQuality;
03247     // NewQuality.Antialias = Quality::FullAntialias;
03248     // NewQuality.Transparency = Quality::FullTransparency;
03249     Quality NewQuality(Quality::QualityMax);
03250 
03251     // Save away the new quality
03252     m_pSpread->SetAnimationQuality(NewQuality);
03253     if (NewQuality != OldQuality)
03254         RegenerateAllFrames = TRUE;
03255 
03256     // Check if somebody has edited the page background layer. If they have then
03257     // regenerate all frames
03258     Layer * pPageBackground = m_pSpread->FindFirstPageBackgroundLayer();
03259     if (pPageBackground)
03260     {
03261         if (pPageBackground->IsEdited())
03262             RegenerateAllFrames = TRUE;
03263     }
03264 
03265     // If the user has a global optimised palette and they have edited one layer
03266     // then we have really no choice but to always regenerate all frames
03267     // as the user may have changed something that will affect the colours in the palette.
03268     //DITHER            Dither;
03269     WEB_PALETTE     WebPalette          = PAL_GLOBAL;
03270     PALETTE_COLOURS ColoursPalette      = PALCOL_BROWSER;
03271     DWORD           NumColsInPalette;
03272     m_pSpread->GetAnimationColours(NULL, &WebPalette, &ColoursPalette, &NumColsInPalette, NULL);
03273     if (WebPalette == PAL_GLOBAL && ColoursPalette == PALCOL_OPTIMIZED)
03274     {
03275         // check to see if one of the frame layers has been edited
03276         Layer * pTestLayer = m_pSpread->FindFirstFrameLayer();
03277         while (pTestLayer)
03278         {
03279             if (pTestLayer->IsEdited() && pTestLayer->IsPseudoFrame())
03280             {
03281                 // Somebody has edited one of the frames so we must regenerate all
03282                 RegenerateAllFrames = TRUE;
03283                 break;
03284             }
03285             pTestLayer = pTestLayer->FindNextFrameLayer();
03286         }
03287     }
03288 
03289     // Check all the layers to see if they contain a single bitmap which we can use
03290     // instead of generating one.
03291     // This will mark all valid single bitmaps using the reference in the layer
03292     if (!CheckAllForSingleBitmaps(m_pSpread, m_pBitmapFilter))
03293     {
03294         // Try and put back the selection that we recorded at the start
03295         PutBackTheSelection();
03296         delete m_pBitmapFilter;
03297         m_pBitmapFilter = NULL;
03298         // We failed to clean up after grabbing the frame
03299         FailAndExecute();
03300         End();
03301         return; 
03302     } 
03303     
03304     // As this will affect us during grabbing, we should force it into the known
03305     // non-interferring state
03306     BOOL CurrentVisEdState = Layer::ActiveLayerVisibleAndEditable;
03307     Layer::ActiveLayerVisibleAndEditable = FALSE;
03308     // The all visible flag will also do this for us. 
03309     Document* pDoc = m_pSpread->FindParentDocument();
03310     BOOL CurrentAllVisibleState = FALSE;
03311     if (pDoc != NULL)
03312     {
03313         CurrentAllVisibleState = pDoc->IsAllVisible();
03314         pDoc->SetAllVisible(FALSE);
03315     }
03316 
03317     // SMFIX Do we need a global palette for all the frames?
03318     BOOL CreatingGlobalPalette = (WebPalette == PAL_GLOBAL && ColoursPalette == PALCOL_OPTIMIZED);
03319 
03320 
03321     // if we are having a global palette then get an optimiser to create one from the bitmaps
03322     if (CreatingGlobalPalette)
03323         CreateGlobalPalette(NumColsInPalette, RegenerateAllFrames);
03324 
03325     // Go through all the frame layers in the spread and export them
03326     KernelBitmap * pBitmap = NULL;
03327     Layer* pCurrentLayer = NULL;
03328 
03329     // Set the filter to generate output bitmaps
03330     m_pBitmapFilter->SetGrabMode(GrabFrameFilter::GRABMODE_FOROUTPUT);
03331 
03332     // go round once unless we are creating a global palette then go round twice
03333     pBitmap = NULL;
03334     pCurrentLayer = m_pSpread->FindFirstFrameLayer();
03335 
03336     while (pCurrentLayer != NULL)
03337     {
03338         // see if the user has hidden the frame
03339         if (!pCurrentLayer->IsPseudoFrame() || pCurrentLayer->IsHiddenFrame())
03340         {
03341             // It is either an invalid frame or it is hidden. In both cases but especially
03342             // the second we should ensure that if there is a generated bitmap then we
03343             // vape it as it is now out of date.
03344             pCurrentLayer->SetGeneratedBitmap(NULL);
03345 
03346             // Move to the next bitmap in the animation
03347             pCurrentLayer = pCurrentLayer->FindNextFrameLayer();
03348 
03349             // Go to the next frame
03350             continue;
03351         }
03352 
03353         // Set up the visibility of the other layers using this layer
03354         // as the new temporary and acting active layer
03355         FrameSGallery::FixOtherLayersFromActive(pCurrentLayer);
03356             
03357         // This is where the real work starts!  
03358         // This is the layer that we want grabbing
03359         m_pLayer = pCurrentLayer;
03360 
03361         // Check to see if we have a single bitmap on the layer which is stored
03362         // in a NodeBitmap at a 1:1 scale and is 8bpp or less and the palette matches
03363         // the present options.
03364         // If it passes all these tests, then set pBitmap to be that bitmap.
03365         //if (!CheckIfSingleBitmap(pCurrentLayer, &pBitmap))
03366         // If there is a referenced bitmap then we can use this instead of generating one
03367         pBitmap = m_pLayer->GetReferencedBitmap();
03368         if (pBitmap == NULL)
03369         {
03370             // Look to see if we have a bitmap for this layer
03371             KernelBitmap * pOldBitmap = pCurrentLayer->GetGeneratedBitmap(); 
03372             
03373             // Look to see if any visible foreground layers below this one have
03374             // been edited
03375             BOOL LayersBelowEdited = FALSE;
03376             // Only check if we are not already forced to regnerate all frames
03377             if (!RegenerateAllFrames)
03378             {
03379                 Layer * pTestLayer = pCurrentLayer;
03380                 pTestLayer = pTestLayer->FindPrevFrameLayer();
03381                 while (pTestLayer)
03382                 {
03383                     // Dont disclude hidden frames as they can affect the make up of the current frame
03384                     if (pTestLayer->IsEdited() && pTestLayer->IsPseudoFrame() &&
03385                         pTestLayer->IsVisible())
03386                     {
03387                         LayersBelowEdited = TRUE;
03388                         break;
03389                     }
03390                     pTestLayer = pTestLayer->FindPrevFrameLayer();
03391                 }
03392             }
03393 
03394             // we are getting the bitmaps themselves
03395             // check that the quality it was last captured at was the same as the current quality
03396             Quality CurrentFrameQuality = pCurrentLayer->GetCaptureQuality();
03397 
03398             // For a number of reasons we may need to regenerate the bitmap for this frame
03399             // If nay are true then regenerate, otherwise reuse the old one
03400             if (pOldBitmap == NULL || LayersBelowEdited || RegenerateAllFrames ||
03401                 pCurrentLayer->IsEdited() || CurrentFrameQuality != NewQuality)
03402             {
03403                 // Turn this frame into a bitmap
03404                 pBitmap = GrabTheFrame();
03405             }
03406             else
03407             {
03408                 // Reuse the old bitmap that was generated
03409                 pBitmap = pOldBitmap;
03410 
03411                 // test to see that this bitmap uses the correct palette if required
03412                 // otherwise we will have to grab it anyway
03413                 if (CreatingGlobalPalette)
03414                 {
03415                     // compare palettes
03416                     LOGPALETTE * pGlobalPalette = m_pBitmapFilter->GetGlobalOptimisedPalette();
03417                     if (!pBitmap->GetActualBitmap()->ArePalettesTheSame(pGlobalPalette, 0))
03418                     {
03419                         // NOTE:  This happens when the preview window has just gone and generated a bitmap
03420                         // using a locally optimal palette rather than our globally optimal palette and in
03421                         // the process it has replaced our cache version with its dodgy bitmap.
03422                         TRACEALL( _T("Bum bitmap passed to us with wrong palette, grab a fresh one"));
03423                         pBitmap = GrabTheFrame();
03424                     }
03425                 }
03426             }
03427         }
03428 
03429         BOOL bAddLayer = pBitmap != 0;
03430         if (bAddLayer)
03431         {
03432             // We have a bitmap so add this layer pairing to our export list
03433             bAddLayer = m_ExportParams.AddLayerAndBitmap(pCurrentLayer, pBitmap);
03434         }
03435 
03436         if (!bAddLayer)
03437         {
03438             // We failed to grab the frame or failed to add it to our export list
03439 
03440             // Put back the active layer's visibilty and selection
03441             Layer::ActiveLayerVisibleAndEditable = CurrentVisEdState;
03442             FrameSGallery::FixOtherLayersFromActive(m_pLayer);
03443             // Try and put back the selection that we recorded at the start
03444             PutBackTheSelection();
03445             FailAndExecute();
03446             End();
03447             return; 
03448         } 
03449 
03450         //TRACEUSER( "SimonK", _T("colours in frame %d\n"), pBitmap->GetNumPaletteEntries());
03451 
03452         // Note the capture quality that the frame was captured at but only if we worked correctly
03453         pCurrentLayer->SetCaptureQuality(NewQuality);
03454 
03455         // Move to the next bitmap in the animation
03456         pCurrentLayer = pCurrentLayer->FindNextFrameLayer();
03457     }
03458 
03459     // Put back the active layer's visibilty and selection
03460     Layer::ActiveLayerVisibleAndEditable = CurrentVisEdState;
03461 
03462     // Put back the all visible state
03463     if (pDoc != NULL)
03464         pDoc->SetAllVisible(CurrentAllVisibleState);
03465 
03466     Layer *pActiveLayer = m_pSpread->FindActiveLayer();
03467     if (pActiveLayer)
03468         FrameSGallery::FixOtherLayersFromActive(pActiveLayer);
03469 
03470     // Go and mark all layers as not edited now that we have finished the grabbing
03471     // process
03472     Layer* pLayer = m_pSpread->FindFirstFrameLayer();
03473     while (pLayer != NULL)
03474     {
03475         // This is just as a double check
03476         if (pLayer->IsPseudoFrame())
03477         {
03478             // Clear the edited flag on the layer
03479             pLayer->SetEdited(FALSE);
03480 #ifdef _DEBUG
03481             // Tell the frame gallery to update its display of the frame
03482             BROADCAST_TO_ALL(LayerMsg(pLayer, LayerMsg::REDRAW_LAYER));
03483 #endif
03484         }
03485 
03486         // Move to the next frame layer in the animation
03487         pLayer = pLayer->FindNextFrameLayer();
03488     }
03489 
03490     // If we found a page background layer above, now mark it as not edited
03491     if (pPageBackground)
03492         pPageBackground->SetEdited(FALSE);
03493 
03494     // Clean up after the grabbing process
03495     if (!EndGrab())
03496     {
03497         // We failed to clean up after grabbing the frame
03498         delete m_pBitmapFilter;
03499         m_pBitmapFilter = NULL;
03500         FailAndExecute();
03501         End();
03502         return; 
03503     } 
03504 
03505 
03506     // Grab all frames should usually play the animation.
03507     // If the preview dialog is open and in stop mode then it should continue in stop mode.
03508     // In this case we should have noted this before calling stop at the start of this function
03509     // So up the play state we noted earlier before we preview
03510     PreviewDialog * pPreviewDialog = PreviewDialog::GetPreviewDialog();
03511     INT32 CurrentFrame = 0;
03512     if (pPreviewDialog != NULL)
03513     {
03514         pPreviewDialog->SetPlayAnimation(PlayAnimation);
03515         CurrentFrame = pPreviewDialog->GetCurrentItem();
03516     }
03517 
03518     // Fire up the preview dialog box with the bitmaps in our list
03519     if (!PreviewAnimation())
03520     {
03521         // We failed to preview the bitmap
03522         delete m_pBitmapFilter;
03523         m_pBitmapFilter = NULL;
03524         FailAndExecute();
03525         End();
03526         return; 
03527     } 
03528 
03529     // If the dialog is still there then select the new frame to be displayed
03530     // Default is frame 0 so only do it if the requested item is different to this
03531     pPreviewDialog = PreviewDialog::GetPreviewDialog();
03532     if (pPreviewDialog && CurrentFrame != 0)
03533         pPreviewDialog->SelectCurrentFrame(CurrentFrame);
03534 
03535     // remove the filter as we have no more use for it
03536     delete m_pBitmapFilter;
03537     m_pBitmapFilter = NULL;
03538     
03539     End(); 
03540     return;
03541 }
03542 
03543 /********************************************************************************************
03544 // End of OpGrabAllFrames
03545 ********************************************************************************************/
03546 
03547 //-----------------------------------------------------------------------------------------------
03548 // GrabFrameFilter - Dummy filter, used to render the selection into a bitmap
03549 //-----------------------------------------------------------------------------------------------
03550 
03551 /********************************************************************************************
03552 
03553 >   GrabFrameFilter::GrabFrameFilter()
03554 
03555     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03556     Created:    24/4/97
03557     Purpose:    Constructor for an GrabFrameFilter object.  The object should be initialised
03558                 before use.
03559 
03560 ********************************************************************************************/
03561 
03562 GrabFrameFilter::GrabFrameFilter()
03563 {
03564     pTheBitmap          = NULL;
03565     m_pLayer            = NULL;
03566     m_pOptimisedPalette = NULL;
03567     m_pMkBmpOptions     = NULL;
03568     m_pCopyMkBmpOptions = NULL;
03569     m_GrabMode          = GRABMODE_FOROUTPUT;
03570 
03571     // Override this to say something more useful
03572     ExportingMsgID = _R(IDS_EXPORTINGANIMATEDGIF);  //  "Exporting animated GIF file..."
03573 }
03574 
03575 /********************************************************************************************
03576 
03577 >   GrabFrameFilter::GrabFrameFilter()
03578 
03579     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03580     Created:    9/6/97
03581     Purpose:    Destructor for an GrabFrameFilter object.
03582 ********************************************************************************************/
03583 
03584 GrabFrameFilter::~GrabFrameFilter()
03585 {
03586     if (m_pOptimisedPalette != NULL)
03587     {
03588         CCFree(m_pOptimisedPalette);
03589         m_pOptimisedPalette = NULL;
03590     }
03591     if (m_pCopyMkBmpOptions != NULL)
03592     {
03593         delete m_pCopyMkBmpOptions;
03594         m_pCopyMkBmpOptions = NULL;
03595     }
03596 }
03597 
03598 /********************************************************************************************
03599 
03600 >   virtual BOOL GrabFrameFilter::GenerateOptimisedPalette(Spread *pSpread, UINT32 Depth, double DPI,
03601                                                            BOOL SnapToBrowserPalette, UINT32 NumColsInPalette,
03602                                                            BOOL UsePrimaryCols)
03603 
03604     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> based on Will code
03605     Created:    9/6/97
03606     Inputs:     pSpread             = ptr to spread
03607                 Depth               = The BPP of the bitmap
03608                 DPI                 = the dpi of the bitmap
03609                 NumColsInPalette    = prefered number of cols in palette (0 = select maximum allowed)
03610                                       (only applies when Depth == 8)
03611                 UsePrimaryCols      = Put primary colours in palette
03612                                       (only applies when Depth == 8)
03613                 SnapToBrowserPalette= TRUE if the palette should be snapped to the browser palette after generation
03614 
03615     Returns:    TRUE if Palette generated ok
03616     Purpose:    Generates an optimised palette to use during export
03617                 We override the baseclass form so that we generate one optimised palette for
03618                 all frames if we are in global optimised mode.
03619                 Otherwise, we can just call the base class version.
03620     SeeAlso:    -
03621 
03622 ********************************************************************************************/
03623 
03624 BOOL GrabFrameFilter::GenerateOptimisedPalette(Spread *pSpread, UINT32 Depth, double DPI,
03625                                                BOOL SnapToBrowserPalette, UINT32 NumColsInPalette, BOOL UsePrimaryCols)
03626 
03627 {
03628 
03629     // SMFIX it will pick a valid palette as it goes along
03630     // optimal palettes are no longer created in this manner
03631     // sjk
03632 
03633     return TRUE;
03634 }
03635 
03636 /********************************************************************************************
03637 
03638 >   BOOL GrabFrameFilter::SetLayerBeingCaptured(Layer * pNewLayer)
03639 
03640     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03641     Created:    7/5/97
03642     Inputs:     pNewLayer the layer which is being captured.
03643     Purpose:    This remembers the layer that is being captured. It sets the member variable
03644                 up to the specified layer. 
03645 
03646 ********************************************************************************************/
03647 
03648 BOOL GrabFrameFilter::SetLayerBeingCaptured(Layer * pNewLayer)
03649 {
03650     m_pLayer = pNewLayer;
03651     return TRUE;
03652 }
03653 
03654 /********************************************************************************************
03655 
03656  >  virtual BOOL GrabFrameFilter::SetUpClippingRectangleForExport(Spread *pSpread, SelectionType Selection)
03657 
03658     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03659     Created:    29/4/97
03660     Inputs:     pSpread     the spread to export
03661                 Selection   the selection type to use during export
03662     Returns:    TRUE if the operation was successful
03663                 FALSE otherwise
03664     Purpose:    Sets up the class variable ClipRect to be the clipping rectangle to be used
03665                 during export.
03666     See Also:   PrepareToExport()
03667 
03668 ********************************************************************************************/
03669 
03670 BOOL GrabFrameFilter::SetUpClippingRectangleForExport(Spread *pSpread, SelectionType Selection)
03671 {
03672     ERROR2IF(pSpread == NULL,FALSE,"SetUpClippingRectangleForExport Bad spread");
03673     
03674     // Make an empty rect to start with in the class variable
03675     ClipRect.MakeEmpty();
03676     
03677     // Walk through all the frame layers and work out the bounding boxes of each
03678     Layer* pCurrentLayer = pSpread->FindFirstFrameLayer();
03679     Layer* pNextLayer = NULL;
03680     while (pCurrentLayer != NULL)
03681     {
03682         pNextLayer = pCurrentLayer->FindNextFrameLayer();
03683         // Double check that it is a suitable frame layer and check it is not hidden
03684         if (pCurrentLayer->IsPseudoFrame())
03685         {
03686             // Cannot include a simple hidden check as the purpose of hidden frames is to
03687             // act as backgrounds for the animation. Could check for hidden and solid but
03688             // would also need to check for an overlay onto the hidden frame
03689             if (
03690                 (!pCurrentLayer->IsHiddenFrame()) ||
03691                 (pCurrentLayer->IsHiddenFrame() && pCurrentLayer->IsSolid()) ||
03692                 (pCurrentLayer->IsHiddenFrame() && pNextLayer && pNextLayer->IsOverlay())
03693                 )
03694             {
03695                 // Get the bounding rect for this layer
03696                 DocRect LayerRect = pCurrentLayer->GetBoundingRect();
03697                 // Add this to our clipping rectangle
03698                 ClipRect = ClipRect.Union(LayerRect);
03699             }
03700         }
03701         
03702         // Move to the next bitmap in the animation
03703         pCurrentLayer = pNextLayer;
03704     }
03705 
03706     return TRUE;
03707 }
03708 
03709 /********************************************************************************************
03710 
03711 >   virtual BOOL GrabFrameFilter::GetExportOptions(BitmapExportOptions* pOptions)
03712 
03713     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03714     Created:    24/4/97
03715     Purpose:    See BaseBitmapFilter for interface details
03716 
03717 ********************************************************************************************/
03718 
03719 BOOL GrabFrameFilter::GetExportOptions(BitmapExportOptions* pOptions)
03720 {
03721     ERROR2IF(pOptions == NULL, FALSE, "pOptions NULL");
03722     ERROR3IF(!pOptions->IS_KIND_OF(MakeBitmapExportOptions), "pOptions isn't of type MakeBitmapExportOptions");
03723 
03724     m_pMkBmpOptions = (MakeBitmapExportOptions*) pOptions;
03725 
03726     // Determine the filter type currently in use in Accusoft format
03727     s_FilterType = MAKE_BITMAP_FILTER;
03728 
03729     // Force the selection type to be DRAWING as this should render all visible objects
03730     m_pMkBmpOptions->SetSelectionType(DRAWING);
03731 
03732     m_pMkBmpOptions->SetDPI(96.0);
03733 
03734     if (m_GrabMode == GRABMODE_PREVIEW)
03735     {
03736         // We want a 24bbp bitmap to pass to Gavin's code but using 32bbp to
03737         // store each pixel (ie the 4 channel of each pixel is waste).  This
03738         // should do the trick.
03739         m_pMkBmpOptions->SetDepth(24);
03740     }
03741     else
03742     {
03743         // Force the depth to be 8bpp
03744         m_pMkBmpOptions->SetDepth(8);
03745     }
03746 
03747     // Force the interlacing off
03748     m_pMkBmpOptions->SetMakeInterlaced(FALSE);
03749 
03750     // Force the transparency to on.
03751     //m_pMkBmpOptions->SetMakeTransparent(TRUE);
03752 
03753     // recover the relevant animation options from the spread
03754     if (pSpread)
03755     {
03756         DWORD           Loop                = 0;
03757         DWORD           GlobalDelay         = 10;
03758         DITHER          Dither              = XARADITHER_ORDERED_GREY;
03759         WEB_PALETTE     WebPalette          = PAL_GLOBAL;
03760         PALETTE_COLOURS ColoursPalette      = PALCOL_BROWSER;
03761         DWORD           NumColsInPalette    = 255;
03762         BOOL            UseSystemColours    = FALSE;
03763         // Ask the spread for its version of these values
03764         pSpread->GetSpreadAnimPropertiesParam(&Loop, &GlobalDelay, &Dither, &WebPalette,
03765                                               &ColoursPalette, &NumColsInPalette, &UseSystemColours, NULL); 
03766 
03767         // set to use background transp if it is set in the animation properties dlg
03768         m_pMkBmpOptions->SetBackgroundTransparency(pSpread->GetSpreadAnimPropertiesParam().GetIsBackGroundTransp());
03769 
03770         // Ensure the dependent options are set correctly
03771         // There are 20 colours in the system palette
03772         switch (ColoursPalette)
03773         {
03774             case PALCOL_STANDARD:
03775             case PALCOL_BROWSER:
03776                 // Fixed browser palette
03777                 // SMFIX we want a browser palette
03778                 m_pMkBmpOptions->SetToUseBrowserPalette(TRUE);
03779                 m_pMkBmpOptions->CreateValidBrowserPalette(TRUE);
03780                 // set this as the palette being used in output dib
03781                 AlterPaletteContents(m_pMkBmpOptions->GetLogicalPalette());
03782                 break;
03783 
03784             case PALCOL_OPTIMIZED:
03785                 // Optimised, so take the user's chosen number of required colours
03786                 // Check if local or globally optimised
03787 /*              if (WebPalette == PAL_GLOBAL)
03788                     TRACEUSER( "SimonK", _T("PAL_GLOBALOPTIMISED\n"));
03789                 else
03790                     TRACEUSER( "SimonK", _T("PAL_OPTIMISED\n"));
03791 */              //m_pMkBmpOptions->SetNumColsInPalette(NumColsInPalette);
03792                 // store the number of user defined colours in the options
03793                 m_pMkBmpOptions->SetNumberOfUserRequestedColours(NumColsInPalette);
03794                 // In optimised mode we cannot have ordered dithering as it
03795                 // must have a known palette. So switch the dithering to error
03796                 // diffusion.
03797                 if (Dither == XARADITHER_ORDERED_GREY)
03798                     Dither = XARADITHER_ERROR_DIFFUSION;
03799 
03800                 // Set up whether we save system colours or not
03801                 //m_pMkBmpOptions->SetUseSystemColours(UseSystemColours);
03802                 //m_pMkBmpOptions->SetToUseSystemPalette(UseSystemColours);
03803                 break;
03804             default:
03805                 ERROR3("Bad ColoursPalette option");
03806                 break;
03807         }
03808 
03809         switch (WebPalette)
03810         {
03811             case PAL_GLOBAL:
03812                 // If global set then must be browser palette selected
03813                 //TRACEUSER( "SimonK", _T("PAL_GLOBAL\n"));
03814 //              ColoursPalette = PALCOL_BROWSER;
03815                 // use the global palette here
03816                 if (GetGlobalOptimisedPalette())
03817                 {
03818                     m_pMkBmpOptions->CreateValidPalette(GetGlobalOptimisedPalette(),
03819                         m_pMkBmpOptions->IsBackgroundTransparent() ? 0 : -1);
03820                     // set this as the palette being used in output dib
03821                     AlterPaletteContents(m_pMkBmpOptions->GetLogicalPalette());
03822                 }
03823                 break;
03824             case PAL_LOCAL:
03825                 // If local palette selected then must be optimised as
03826                 // no point saving out a global palette
03827                 //TRACEUSER( "SimonK", _T("PAL_LOCAL\n"));
03828 //              ColoursPalette = PALCOL_OPTIMIZED;
03829                 // SMFIX
03830                 // if we are the first frame generate a new valid palette
03831                 // we could use that as a first guess at a global palette
03832                 // but we do know that if we do not have a global palette we
03833                 // should be getting a different palette for each frame
03834                 m_pMkBmpOptions->InvalidatePalette();
03835                 break;
03836             default:
03837                 ERROR3("Bad WebPalette option");
03838                 break;
03839         }
03840 
03841         // Set up the dithering that we are going to use
03842         m_pMkBmpOptions->SetDither(Dither);
03843     }
03844 
03845 
03846     // We have all the options that we require so don't ask the user for anything
03847 
03848     // Take a copy of these options for latter use (Browser Preview)
03849     if (m_pCopyMkBmpOptions == NULL)
03850     {
03851         m_pCopyMkBmpOptions = (MakeBitmapExportOptions *)m_pMkBmpOptions->MakeCopy();
03852         // don't complain about null as only required by browser preview at present
03853     }
03854 
03855     // All ok
03856     return TRUE;
03857 }
03858 
03859 /********************************************************************************************
03860 
03861 >   virtual BOOL GrabFrameFilter::SetupExportOptions(BitmapExportOptions* pOptions, Spread * pCurrentSpread)
03862 
03863     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03864     Created:    4/8/97
03865     Inputs:     pCurrentSpread  The spread we are currently working with
03866     Purpose:    This is just a public interface on the normal filter's GetExportOptions which is protected.
03867                 It also ensures that the pSpread is set up.
03868 
03869 ********************************************************************************************/
03870 
03871 BOOL GrabFrameFilter::SetupExportOptions(BitmapExportOptions* pOptions, Spread * pCurrentSpread)
03872 {
03873     // Ensure that the spread pointer is set up
03874     // If we haven't actually grabbed any frames then it will be NULL
03875     pSpread = pCurrentSpread;
03876     // Set up those export options
03877     return GetExportOptions(pOptions);
03878 }
03879 
03880 
03881 /********************************************************************************************
03882 
03883 >   virtual KernelBitmap* GrabFrameFilter::GetTheBitmap()
03884 
03885     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03886     Created:    24/4/97
03887     Purpose:    Creates a kernel bitmap from the Export RenderRegion
03888                 Overrides the baseclass version as that uses MakeKernelBitmap which does
03889                 check to see if the OIL bitmap pointers are the same but does not check that
03890                 the contents are the same. This means we end up with duplicated versions.
03891                 This is bad. We use TryAndUseExistingBitmap which does this extra check.
03892                 This is ok in the Creat bitmap copy case as this is the only way to generate
03893                 duplicate frames.
03894     Returns:    Ptr to the bitmap, or NULL if error
03895 
03896 Note:
03897 We cannot even do it this way as
03898 a)  the code which checks for duplicates in the global bitmap list complains as the bitmap
03899     is already attached to the list
03900 b)  even after this, using the TryAndUseExistingBitmap does not reuse the existing bitmap
03901 So try plan c. Add the extra code to ExtractBitmapCopy so when it tries to attach the oilbitmap
03902 it sees if it is reusing an existing bitmap. If so then it will just return the existing bitmap
03903 rather than adding a new duplicate to the system.
03904 ********************************************************************************************/
03905 
03906 KernelBitmap* GrabFrameFilter::GetTheBitmap()
03907 {
03908     // Extract a copy of the bitmap from the RenderRegion
03909     // We need to generate new bitmaps as we delete them and also name them ourselves.
03910     BOOL LookForDuplicates = FALSE;
03911     OILBitmap* pOilBitmap = ExportRegion->ExtractBitmapCopy(pOptimisedPalette, pDestBMInfo, pDestBMBytes,
03912                                                             TransColour, LookForDuplicates);
03913 
03914     if (pOilBitmap == NULL)
03915     {
03916         CleanUpAfterExport();
03917         return NULL;
03918     }
03919 
03920     if (m_pLayer)
03921     {
03922         // Make the bitmap name the layer name
03923         String_256 Name = m_pLayer->GetLayerID();
03924         pOilBitmap->SetName(Name);
03925 
03926         // Copy across the delay from the layer
03927         DWORD delay = m_pLayer->GetFrameDelay();
03928         pOilBitmap->SetBitmapAnimDelay(delay);
03929 
03930         // As all these frames are complete, we output them using
03931         // a replace background restore type.
03932         // It is only later that we may do some trickery on them so that
03933         // we can overlay them.
03934         pOilBitmap->SetAnimationRestoreType(GDM_BACKTOBACK);
03935 
03936         // The exception is if the frame is solid in which case we invariably
03937         // want that one to overlay
03938         //if (m_pLayer->IsSolid())
03939         //  pOilBitmap->SetAnimationRestoreType(GDM_LEAVE);
03940         //else
03941     }
03942         
03943     // Make a kernel bitmap from the oily one
03944     // The class variable pDocument should be holding the document required
03945     // Must check it as TryAndUseExistingBitmap does not!
03946 //  ERROR2IF(TheDocument == NULL,NULL,"GrabFrameFilter::GetTheBitmap null document")
03947 //  BOOL IsNew = TRUE;
03948 //  return KernelBitmap::TryAndUseExistingBitmap(pOilBitmap, TheDocument, &IsNew);
03949     return KernelBitmap::MakeKernelBitmap(pOilBitmap, TheDocument);
03950 }
03951 
03952 /********************************************************************************************
03953 
03954 >   virtual BOOL GrabFrameFilter::ExportVisibleLayersOnly()
03955 
03956     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03957     Created:    29/04/97
03958     Inputs:     -
03959     Outputs:    -
03960     Returns:    True if this filter wants to exclude invisible layers and so export only
03961                 visible items Or False if want to export everything.
03962     Purpose:    Determines if the filter wants to export only visible layers.
03963                 In the base bitmap filters class version the default action will be to
03964                 export only those layers which are visible.
03965     SeeAlso:    Filter::ExportRender;
03966 
03967 ********************************************************************************************/
03968 
03969 BOOL GrabFrameFilter::ExportVisibleLayersOnly()
03970 {
03971 #ifdef DO_EXPORT
03972     MaskedFilterExportOptions* pMaskedOptions = (MaskedFilterExportOptions*)GetBitmapExportOptions();
03973     ERROR2IF(pMaskedOptions == NULL, FALSE, "NULL Args");
03974     ERROR3IF(!pMaskedOptions->IS_KIND_OF(MaskedFilterExportOptions), "pMaskedOptions isn't");
03975 
03976     ERROR2IF(pSpread == NULL, FALSE,"GrabFrameFilter::VisibleLayersOnly no spread to export");
03977 
03978     // We always want to export oONLY the visible layers.
03979     // When we are exporting in transparent mode and making up the mask, we must go and set the
03980     // page background layer to be invisible
03981     // We are just taking the oppurtunity that this call gives us to fix up the page background
03982     // layer to be invisible
03983     if (pMaskedOptions->WantTransparent() && !SecondPass && !GeneratingOptimisedPalette())
03984     {
03985         // Masking operation
03986         // If we find a page background layer then make sure it is invisible
03987         Layer * pLayer = pSpread->FindFirstPageBackgroundLayer();
03988         if (pLayer)
03989             pLayer->SetVisible(FALSE);
03990     }
03991     else
03992     {
03993         // Normal export operation
03994         // If we find a page background layer then make sure it is visible
03995         Layer * pLayer = pSpread->FindFirstPageBackgroundLayer();
03996         if (pLayer)
03997             pLayer->SetVisible(TRUE);
03998     }
03999 
04000     // only include all layer that are visible in this bitmap export
04001     return TRUE;
04002 #else
04003     // only include all layer that are visible in this bitmap export
04004     return TRUE;
04005 #endif
04006 }   
04007 
04008 
04009 /********************************************************************************************
04010 
04011 >   virtual BOOL GrabFrameFilter::ExportSelectionOnly()
04012 
04013     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04014     Created:    29/04/97
04015     Returns:    True if this filter wants check if an object is selected or not and so export
04016                 only the selected items Or False if want to export everything.
04017     Purpose:    Determines if the filter wants to export only selected items.
04018                 In the base bitmap filters class version the default action will be to
04019                 export all objects by default
04020     SeeAlso:    Filter::ExportRender;
04021 
04022 ********************************************************************************************/
04023 
04024 BOOL GrabFrameFilter::ExportSelectionOnly(BOOL MaskedRender)
04025 {
04026     // We always export all the objects
04027     return FALSE;
04028 }
04029 
04030 /********************************************************************************************
04031 
04032 >   BOOL GrabFrameFilter::IsSecondPassRequired()
04033 
04034     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04035     Created:    29/04/97
04036     Returns:    True if this filter wants a second export rendering pass and so have a chance
04037                 to setup semething like a mask.
04038     Purpose:    Determines if the a second rendering pass is required or not.
04039 
04040 ********************************************************************************************/
04041 
04042 BOOL GrabFrameFilter::IsSecondPassRequired()
04043 {
04044 #ifdef DO_EXPORT
04045     MaskedFilterExportOptions* pMaskedOptions = (MaskedFilterExportOptions*)GetBitmapExportOptions();
04046     ERROR2IF(pMaskedOptions == NULL, FALSE, "NULL Args");
04047     ERROR3IF(!pMaskedOptions->IS_KIND_OF(MaskedFilterExportOptions), "pMaskedOptions isn't");
04048 
04049     // Only require a second pass if wanting transparency
04050     if (pMaskedOptions->WantTransparent())
04051         return TRUE;
04052     else
04053         return FALSE;   
04054 #else
04055     return FALSE;
04056 #endif
04057 }
04058 
04059 
04060 /********************************************************************************************
04061 
04062 >   virtual BOOL GrabFrameFilter::DoExportBitmaps(Operation* pOp, CCLexFile* pFile, PathName* pPath,
04063                                                   BitmapExportParam* pParam, BOOL DontShowFileName = FALSE)
04064 
04065     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04066     Created:    30/04/97
04067     Inputs:     pOp - the operation that started the export off
04068                 pDiskFile - the file to put the exported data into
04069                 pPath - the pathname of the file to be exported to
04070                 pParam - the data to use when exporting the bitmaps
04071     Returns:    TRUE if worked, FALSE if failed.
04072     Purpose:    Exports the bitmaps specified by the BitmapExportParam object to a multi-
04073                 image capable filter.
04074 
04075 ********************************************************************************************/
04076 
04077 BOOL GrabFrameFilter::DoExportBitmaps(Operation *pOp, CCLexFile* pFile, PathName* pPath,
04078                                       BitmapExportParam* pParam, BOOL DontShowFileName)
04079 {
04080 #ifdef DO_EXPORT
04081     ERROR2IF(pOp == NULL || pFile == NULL || pPath == NULL, FALSE,"NULL Parameters");
04082     ERROR2IF(pParam == NULL,FALSE,"GrabFrameFilter::DoExportBitmaps null BitmapExportParam specified");
04083 
04084     // We could just call the function direct but this may give us some more functionality
04085     // in the long term
04086     return SaveExportBitmapsToFile(pFile, pPath, pParam, DontShowFileName);
04087 #endif
04088     return FALSE;
04089 }
04090 
04091 
04092 /********************************************************************************************
04093 
04094 >   void GrabFrameFilter::SetGlobalOptimisedPalette(LPLOGPALETTE pOptimisedPalette)
04095 
04096     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04097     Created:    09/07/97
04098     Inputs:     pOptimisedPalette - the new global optimised palette
04099     Returns:    TRUE if worked, FALSE if failed.
04100     Purpose:    Sets up a new optimised palette ready to be applied to all frames in the
04101                 animation. Should be used with care.
04102                 At present, only used if we discover that all frames contain compatible
04103                 bitmaps that have the same palette on them.
04104 
04105 ********************************************************************************************/
04106 
04107 void GrabFrameFilter::SetGlobalOptimisedPalette(LPLOGPALETTE pOptimisedPalette)
04108 {
04109     if (m_pOptimisedPalette != NULL)
04110     {
04111         CCFree(m_pOptimisedPalette);
04112         m_pOptimisedPalette = NULL;
04113     }
04114 
04115     m_pOptimisedPalette = pOptimisedPalette;
04116 }
04117 
04118 /********************************************************************************************
04119 
04120 >   virtual UINT32 GrabFrameFilter::GetExportMsgID()
04121 
04122     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04123     Created:    28/07/97
04124     Returns:    The id of the message to put on the progress display whilst exporting.
04125     Purpose:    Used to get the message id to be used during export.
04126                 Virtual, so that two stage exporters can change the message.
04127     SeeAlso:    DoExport;
04128 
04129 ********************************************************************************************/
04130 
04131 UINT32 GrabFrameFilter::GetExportMsgID()
04132 {
04133     // Always return this message regardless of the stage that we are on
04134     return _R(IDS_GENERATINGFRAMES);        // "Generating animation frames..."
04135 }
04136 
04137 /********************************************************************************************
04138 // End of GrabFrameFilter
04139 ********************************************************************************************/
04140 
04141 //------------------------------------------------------------------------------------------
04142 // GIFAnimationExportParam
04143 //------------------------------------------------------------------------------------------
04144 
04145 /********************************************************************************************
04146 
04147 >   GIFAnimationExportParam::GIFAnimationExportParam()
04148 
04149     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04150     Created:    13/05/97
04151     Purpose:    Default constructor
04152 
04153 ********************************************************************************************/
04154 
04155 GIFAnimationExportParam::GIFAnimationExportParam()
04156 {
04157     m_BitmapCount = 0;
04158     m_pBitmaps = NULL;
04159 
04160     m_LayerCount = 0;
04161     m_pLayers = NULL;
04162 
04163     m_RegeneratedBitmapPosition = 0;
04164 }
04165 
04166 /********************************************************************************************
04167 
04168 >   GIFAnimationExportParam::~GIFAnimationExportParam()
04169 
04170     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04171     Created:    13/05/97
04172     Purpose:    Default destructor
04173 
04174 ********************************************************************************************/
04175 
04176 GIFAnimationExportParam::~GIFAnimationExportParam()
04177 {
04178     // free up the arrays that we grabbed
04179     if (m_pBitmaps != NULL)
04180     {
04181         CCFree(m_pBitmaps);
04182         m_pBitmaps = NULL;
04183         m_BitmapCount = 0;
04184     }
04185     if (m_pLayers != NULL)
04186     {
04187         CCFree(m_pLayers);
04188         m_pLayers = NULL;
04189         m_LayerCount = 0;
04190     }
04191 }
04192 
04193 /********************************************************************************************
04194 
04195 >   GIFAnimationExportParam::GIFAnimationExportParam(UINT32 Count, KernelBitmap** pBitmap)
04196 
04197     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04198     Created:    13/05/97
04199     Inputs:     Count - The number of indexes in the array
04200                 pBitmap - pointer to an array of pointers to kernel bitmaps
04201     Outputs:    -
04202     Returns:    -
04203     Purpose:    Used to pass around lists of bitmaps.  Note that deleting the bitmap array
04204                 is the responsibility of the caller.
04205 ********************************************************************************************/
04206 
04207 GIFAnimationExportParam::GIFAnimationExportParam(UINT32 Count, KernelBitmap** pBitmap)
04208 {
04209     ERROR3IF(Count == 0, "Zero bitmap count, that's not right");
04210     ERROR3IF(pBitmap == NULL, "NULL bitmap array");
04211     ERROR3IF(!(*pBitmap)->IS_KIND_OF(KernelBitmap), "This dosen't seem to be an array of kernel bitmaps");
04212 
04213     m_BitmapCount = Count;
04214     m_pBitmaps = pBitmap;
04215 
04216     // set up everything else to defaults
04217     m_RegeneratedBitmapPosition = 0;
04218     m_LayerCount = 0;
04219     m_pLayers = NULL;
04220 }
04221 
04222 /********************************************************************************************
04223 
04224 >   virtual UINT32 GIFAnimationExportParam::GetBitmapCount()
04225 
04226     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04227     Created:    13/05/97
04228     Returns:    The number of bitmaps in the bitmap array.  (The array runs 0..Count-1)
04229     Purpose:    For getting the number of bitmaps in the array!
04230 
04231 ********************************************************************************************/
04232 
04233 UINT32 GIFAnimationExportParam::GetBitmapCount()
04234 {
04235     return m_BitmapCount;
04236 }
04237 
04238 /********************************************************************************************
04239 
04240 >   virtual KernelBitmap* GIFAnimationExportParam::GetBitmap(UINT32 Index)
04241 
04242     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04243     Created:    13/05/97
04244     Inputs:     Index - the index of the required bitmap
04245     Outputs:    -
04246     Returns:    Pointer to the nth bitmap, NULL if error
04247     Purpose:    For safely getting a pointer to a bitmap in the bitmap array
04248 
04249 ********************************************************************************************/
04250 
04251 KernelBitmap* GIFAnimationExportParam::GetBitmap(UINT32 Index)
04252 {
04253     ERROR2IF(Index >= m_BitmapCount, NULL, "Index out of bounds");
04254     ERROR2IF(m_pBitmaps == NULL, NULL, "NULL array");
04255 
04256     ERROR3IF(!(m_pBitmaps[Index])->IS_KIND_OF(KernelBitmap), "This dosen't seem to be a pointer to a kernel bitmap");
04257     return m_pBitmaps[Index];
04258 }
04259 
04260 
04261 /********************************************************************************************
04262 
04263 >   virtual UINT32 GIFAnimationExportParam::GetLayerCount()
04264 
04265     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04266     Created:    13/05/97
04267     Returns:    The number of bitmaps/layers in the layers/bitmap array.  (The array runs 0..Count-1)
04268     Purpose:    For getting the number of layers/bitmaps in the array!
04269 
04270 ********************************************************************************************/
04271 
04272 UINT32 GIFAnimationExportParam::GetLayerCount()
04273 {
04274     return m_LayerCount;
04275 }
04276 
04277 /********************************************************************************************
04278 
04279 >   virtual Layer * GIFAnimationExportParam::GetLayer(UINT32 Index)
04280 
04281     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04282     Created:    13/05/97
04283     Inputs:     Index - the index of the required bitmap
04284     Outputs:    -
04285     Returns:    Pointer to the nth bitmap, NULL if error
04286     Purpose:    For safely getting a pointer to a bitmap in the bitmap array
04287 
04288 ********************************************************************************************/
04289 
04290 Layer* GIFAnimationExportParam::GetLayer(UINT32 Index)
04291 {
04292     ERROR2IF(Index >= m_LayerCount, NULL, "Index out of bounds");
04293     ERROR2IF(m_pLayers == NULL, NULL, "NULL array");
04294 
04295     ERROR3IF(!(m_pLayers[Index])->IS_KIND_OF(Layer), "This dosen't seem to be a pointer to a layer");
04296     return m_pLayers[Index];
04297 }
04298 
04299 /********************************************************************************************
04300 
04301 >   virtual BOOL GIFAnimationExportParam::AddLayerAndBitmap(Layer * pLayer, KernelBitmap * pBitmap)
04302 
04303     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04304     Created:    13/05/97
04305     Inputs:     pLayer  the layer to be added to the list/array
04306                 pBitmap the bitmap associated with this layer to be added to the list/array
04307     Returns:    True if worked ok, False otherwise.
04308     Purpose:    For adding a layer to list ready for exporting the GIF animation.
04309                 Uses the class variables m_pLayers and m_LayerCount.
04310 
04311 ********************************************************************************************/
04312 
04313 BOOL GIFAnimationExportParam::AddLayerAndBitmap(Layer * pLayer, KernelBitmap * pBitmap)
04314 {
04315     // Let the called functions do the parameter checking!
04316     return AddLayer(pLayer) && AddBitmap(pBitmap);
04317 }
04318 
04319 /********************************************************************************************
04320 
04321 >   virtual BOOL GIFAnimationExportParam::AddLayer(Layer * pLayer)
04322 
04323     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04324     Created:    13/05/97
04325     Inputs:     pLayer  the layer to be added to the list/array
04326     Outputs:    -
04327     Returns:    True if worked ok, False otherwise.
04328     Purpose:    For adding a layer to list ready for exporting the GIF animation.
04329                 Uses the class variables m_pLayers and m_LayerCount.
04330 
04331 ********************************************************************************************/
04332 
04333 BOOL GIFAnimationExportParam::AddLayer(Layer * pLayer)
04334 {
04335     ERROR2IF(pLayer == NULL,FALSE,"AddLayer given null layer");
04336     BOOL ok = TRUE;
04337 
04338     // If we have a null list then just allocate the first item
04339     if (m_pLayers == NULL)
04340     {
04341         // Claim selected space
04342         m_pLayers = (Layer**) CCMalloc(sizeof(Layer*));
04343         if (m_pLayers == NULL)
04344             ok = FALSE;
04345         else
04346             m_pLayers[0] = pLayer;
04347         m_LayerCount = 1;
04348     }
04349     else
04350     {
04351         // Add to end of selection
04352         Layer** pTemp = (Layer**) CCRealloc(m_pLayers, (m_LayerCount + 1) * sizeof(Layer*));
04353         if (pTemp == NULL)
04354             ok = FALSE;
04355         else
04356         {
04357             m_pLayers = pTemp;
04358             m_pLayers[m_LayerCount] = pLayer;
04359         }
04360         m_LayerCount++;
04361     }
04362 
04363     return ok;
04364 }
04365 
04366 /********************************************************************************************
04367 
04368 >   BOOL GIFAnimationExportParam::AddBitmap(KernelBitmap * pBitmap)
04369 
04370     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04371     Created:    13/05/97
04372     Inputs:     pBitmap the bitmap to add to our list in the animation
04373     Returns:    True if worked ok, False otherwise
04374     Purpose:    Tries to add the bitmap to the list.
04375                 Uses the class variables m_pBitmaps and m_BitmapCount.
04376                 Copied from BitmapSGallery and BitmapExportParam way of doing things so that
04377                 we are compatible. Not the best way of doing it!
04378     SeeAlso:    BitmapSGallery::GetSelectedBitmaps
04379 
04380 ********************************************************************************************/
04381 
04382 BOOL GIFAnimationExportParam::AddBitmap(KernelBitmap * pBitmap)
04383 {
04384     ERROR2IF(pBitmap == NULL,FALSE,"Addbitmap given null bitmap");
04385     BOOL ok = TRUE;
04386 
04387     // If we have a null list then just allocate the first item
04388     if (m_pBitmaps == NULL)
04389     {
04390         // Claim selected space
04391         m_pBitmaps = (KernelBitmap**) CCMalloc(sizeof(KernelBitmap*));
04392         if (m_pBitmaps == NULL)
04393             ok = FALSE;
04394         else
04395             m_pBitmaps[0] = pBitmap;
04396         m_BitmapCount = 1;
04397     }
04398     else
04399     {
04400         // Add to end of selection
04401         KernelBitmap** pTemp = (KernelBitmap**) CCRealloc(m_pBitmaps, (m_BitmapCount + 1) * sizeof(KernelBitmap*));
04402         if (pTemp == NULL)
04403             ok = FALSE;
04404         else
04405         {
04406             m_pBitmaps = pTemp;
04407             m_pBitmaps[m_BitmapCount] = pBitmap;
04408         }
04409         m_BitmapCount++;
04410     }
04411 
04412     return ok;
04413 }
04414 
04415 /********************************************************************************************
04416 
04417 >   BOOL GIFAnimationExportParam::SetAnimPropertiesParam(AnimPropertiesParam* pParam)
04418 
04419     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04420     Created:    13/05/97
04421     Inputs:     pParam - Sets the Animation Properties details for this GIFAnimationExportParam.
04422     Returns:    TRUE if ok, FALSE otherwise.
04423     
04424 ********************************************************************************************/
04425 
04426 void GIFAnimationExportParam::SetSpreadAnimPropertiesParam(const AnimPropertiesParam& Param)
04427 {
04428     m_AnimPropertiesParam = Param;
04429 }
04430 
04431 /********************************************************************************************
04432 
04433 >   void GIFAnimationExportParam::GetAnimPropertiesParam()
04434 
04435     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04436     Created:    13/05/97
04437     Purpose:    Returns the Animation Properties details for this GIFAnimationExportParam.
04438         
04439 ********************************************************************************************/
04440 
04441 AnimPropertiesParam& GIFAnimationExportParam::GetSpreadAnimPropertiesParam()
04442 {
04443     return m_AnimPropertiesParam;
04444 }
04445 
04446 /********************************************************************************************
04447 
04448 >   DocRect GIFAnimationExportParam::GetBoundingRect() const
04449 
04450     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04451     Created:    11/06/97
04452     Purpose:    Returns the bounding rectangle of the animation.
04453         
04454 ********************************************************************************************/
04455 
04456 DocRect GIFAnimationExportParam::GetBoundingRect() const
04457 {
04458     // Recover the bounding rect of the animation from our copy of the spread's
04459     // animation properties.
04460     DocRect BoundingRect = m_AnimPropertiesParam.GetBoundingRect();
04461     // We are only interested in the size and so translate it to zero
04462     BoundingRect.Translate(-BoundingRect.lo.x, -BoundingRect.lo.y);
04463     // return it to the caller
04464     return BoundingRect;
04465 }
04466 
04467 
04468 //------------------------------------------------------------------------------------------
04469 // end of GIFAnimationExportParam
04470 //------------------------------------------------------------------------------------------
04471 
04472 /********************************************************************************************
04473 // OpSaveAnimatedGIF
04474 ********************************************************************************************/
04475 
04476 /********************************************************************************************
04477 
04478 >   OpState OpSaveAnimatedGIF::GetState(String_256*, OpDescriptor*)
04479 
04480     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04481     Created:    9/9/97
04482     Inputs:     Name of the OpDescriptor being queried
04483     Outputs:    The string to show to the user
04484     Returns:    The state of the OpSaveAnimatedGIF operation
04485     Purpose:    For finding the OpSaveAnimatedGIF's state. 
04486 
04487 ********************************************************************************************/
04488 
04489 OpState OpSaveAnimatedGIF::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc)
04490 {
04491     // else just use the base class version
04492     return OpGrabAllFrames::GetState(pUIDescription, pOpDesc);
04493 }
04494 
04495 /********************************************************************************************
04496 
04497 >   BOOL OpSaveAnimatedGIF::GetFileNameFromUser()
04498 
04499     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04500     Created:    7/7/97
04501     Returns:    True if worked ok, False otherwise
04502     Purpose:    Gives the operation chance to get the filename from the user.
04503                 In this version we need to do this before grabbing the frames so that the
04504                 user is given the oppurtunity to change the options using the button on the
04505                 file save dialog box.
04506 
04507 ********************************************************************************************/
04508 
04509 BOOL OpSaveAnimatedGIF::GetFileNameFromUser()
04510 {
04511     // This is used to export an animated GIF. So we need only show the normal
04512     // GIF filter. This is despite the fact that this is not going to be the filter
04513     // that we use for the job.
04514     
04515     // We are just going to show the animated GIF filter and all files
04516     String_256 FilterString(_R(IDS_SAVEGIFANIFILTERS));
04517 
04518     // Ensure that all the filters have a -1 in their position string so any matching
04519     // of selected filter will fail. Make only the GIF filter have 1 in there.
04520     Filter* pFilter = Filter::GetFirst();
04521     while (pFilter != NULL)
04522     {
04523         if (IS_A(pFilter, TI_GIFFilter))
04524         {
04525             // Its the GIF filter we want, mark it as the first position
04526             pFilter->pOILFilter->Position = 1;
04527         }
04528         else
04529         {
04530             // Make sure we don't try this one later
04531             pFilter->pOILFilter->Position = -1;
04532         }
04533 
04534         // Try the next filter
04535         pFilter = Filter::GetNext(pFilter);
04536     }
04537 
04538     // Create the dialog box
04539     GIFExportFileDialog FDialog(FilterString);
04540     
04541     FDialog.SetTitle(_R(IDS_SAVEGIFANI_TITLE));
04542 
04543     // Use the document name as the default name of animation
04544     String_256 DefaultName(_R(IDS_BUTTBAR_ANIMATION));  // GIF Animation
04545     if (m_pDocument)
04546         DefaultName = m_pDocument->GetDocName(FALSE);
04547     // This is the pathname that we are going to save to
04548     m_SavePath = DefaultName;
04549     // Ensure that we have the correct extension on the filename we have allocated
04550     EnsureFileType(&m_SavePath);
04551 
04552     // Pass this name onto the dialog box
04553     DefaultName = m_SavePath.GetFileName();
04554     FDialog.SetDefaultFileName(DefaultName);
04555     
04556     //FDialog.SetSelectedFilterIndex(1);
04557 
04558     // Select the desired path
04559     String_256 ExportFilterPath = OpMenuExport::DefaultExportFilterPath;
04560     //Camelot.GetPrefDirect("Filters", "DefaultExportFilterPath",&ExportFilterPath);
04561     if (ExportFilterPath.Length() > 0)
04562         FDialog.SetInitialDirectory(ExportFilterPath);
04563 
04564     // 'Do' the dialog and get that filename that we require
04565     BOOL DlgResult = FDialog.OpenAndGetFileName();
04566     if (!DlgResult)
04567     {
04568         return FALSE;
04569     }
04570 
04571     // Get the filename.
04572     FDialog.GetChosenFileName(&m_SavePath);
04573 
04574     // This is now taken care of in FileDlgs.cpp on the ok as it then checks if the file
04575     // exists or not. If we do it here then this does not happen.
04576     // Unfortunately, changes made to the string in the dialog do not filter through
04577     // and so we ust fix it up here as well.
04578     // Always make sure that the filter's default extension is on if the user has not
04579     // specified an extension.
04580     EnsureFileType(&m_SavePath);
04581 
04582     // Ensure that the path is valid
04583     if (!m_SavePath.IsValid())
04584     {
04585         InformError();
04586         //delete m_pBitmapFilter;
04587         //m_pBitmapFilter = NULL;
04588         return FALSE;
04589     }
04590 
04591     // Extract directory name (minus terminating backslash) and remember for next time.
04592     ExportFilterPath = m_SavePath.GetLocation(FALSE);
04593     if (ExportFilterPath.Length() > 0)
04594         OpMenuExport::DefaultExportFilterPath = ExportFilterPath;
04595         //Camelot.SetPrefDirect("Filters", "DefaultExportFilterPath",DefaultExportFilterPath, TRUE);
04596             
04597     //UINT32 TheSelectedFilterID = m_pBitmapFilter->FilterID;
04598 
04599     // Everything got so return to the grabbing process
04600     return TRUE;
04601 }
04602 
04603 /********************************************************************************************
04604 
04605 >   virtual BOOL OpSaveAnimatedGIF::SaveOrShowTheAnimation(PreviewDialog * pPreviewDialog, BitmapExportParam* pExportParam)
04606 
04607     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04608     Created:    4/8/97
04609     Inputs:     pPreviewDialog  the preview dialog box, if open
04610                 pExportParam    the export param which we will use
04611     Returns:    True if worked ok, False otherwise
04612     Purpose:    Tries to actually do the preview operation required.
04613                 In this case we just save the animation out to the file that the user specified.
04614 
04615 ********************************************************************************************/
04616 
04617 BOOL OpSaveAnimatedGIF::SaveOrShowTheAnimation(PreviewDialog * pPreviewDialog, BitmapExportParam* pExportParam)
04618 {
04619     // A bit of checking on parameters
04620     if (pExportParam != NULL)
04621     {
04622         ERROR3IF(!pExportParam->IS_KIND_OF(BitmapExportParam), "OpParam passed is not a BitmapExportParam");
04623 
04624         if (pExportParam->GetBitmapCount() == 0)
04625         {
04626             ERROR2RAW("OpSaveAnimatedGIF::DoWithParam no bitmaps to export");
04627             return FALSE;
04628         }               
04629     }
04630     else
04631     {
04632         ERROR2RAW("OpSaveAnimatedGIF::DoWithParam bad params!");
04633         return FALSE;
04634     }
04635 
04636     // Recover the bitmap pointer from the parameter passed in
04637     // This is to ensure that we have at least one bitmap to save
04638     KernelBitmap* pTheBitmap = pExportParam->GetBitmap(0);
04639     if (pTheBitmap == NULL)
04640     {
04641         ERROR2RAW("OpSaveAnimatedGIF::DoWithParam bitmap pointer is null");
04642         return FALSE;
04643     }
04644 
04645     // Ensure that we have a special grab frame filter available
04646     if (m_pBitmapFilter == NULL)
04647         m_pBitmapFilter = new GrabFrameFilter();
04648     if (m_pBitmapFilter == NULL)
04649     {
04650         InformError(_R(IDT_CANT_FIND_FILTER));
04651         return FALSE;
04652     }
04653 
04654     // Should really check that the pathname is not null
04655     String_256 Filename;
04656     Filename = m_SavePath.GetPath();
04657     ERROR2IF(Filename.IsEmpty(),FALSE,"OpSaveAnimatedGIF::SaveAnimation Save path not set up!");
04658 
04659     // First off, we have to try and open the file
04660     CCDiskFile DiskFile(1024, FALSE, TRUE);
04661 
04662     BOOL ExportedOk = TRUE;
04663     try
04664     {
04665         // Export bitmaps
04666         ExportedOk = m_pBitmapFilter->DoExportBitmaps(this, &DiskFile, &m_SavePath, pExportParam);
04667 
04668         if (!ExportedOk)
04669         {
04670             // Something went a bit wrong - tell the user what it was.
04671             // Supress the error if it was the 'user has cancelled one'
04672             if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED))
04673             {
04674                 InformError();
04675                 m_pBitmapFilter->DeleteExportFile(&DiskFile);
04676             }
04677             else
04678             {
04679                 // otherwise remove the error so it won't get reported
04680                 Error::ClearError();
04681             }
04682         }
04683 
04684         // close the file
04685         if (DiskFile.isOpen())
04686             DiskFile.close();
04687     }
04688 
04689     // See if there was a file io error
04690     catch(CFileException)
04691     {
04692         // Report the error if no one else did
04693         if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED))
04694         {
04695             InformError();
04696         }
04697         else
04698             Error::ClearError();    // otherwise remove the error so it won't get reported
04699 
04700         // Make sure that the file is closed and deleted
04701         try
04702         {
04703             // First try and delete it (tries to close it first)
04704             if (m_pBitmapFilter)
04705                 m_pBitmapFilter->DeleteExportFile(&DiskFile);
04706 
04707             // Double check to make sure it is closed.
04708             if (DiskFile.isOpen())
04709                 DiskFile.close();
04710         }
04711         catch(CFileException)
04712         {
04713             // Failed to close the file - not much we can do about it really
04714         }
04715 
04716         // Fail
04717         ExportedOk = FALSE;
04718     }
04719     
04720     // Clean out the filter we created
04721     delete m_pBitmapFilter;
04722     m_pBitmapFilter = NULL;
04723 
04724     // Blank the path
04725     //m_SavePath.SetPathName(TEXT(""));
04726     // This will give us a nice pathname is invalid error! Don't you just love the pathname class!
04727 
04728     return ExportedOk;
04729 }
04730 
04731 /********************************************************************************************
04732 
04733 >   BOOL OpSaveAnimatedGIF::EnsureFileType(PathName * pPath)
04734 
04735     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04736     Created:    1/5/97
04737     Inputs:     pPath   the pathname in use
04738     Purpose:    Ensures that the pathname has the file extension/type that we require.
04739 
04740 ********************************************************************************************/
04741 
04742 BOOL OpSaveAnimatedGIF::EnsureFileType(PathName * pPath)
04743 {
04744     ERROR2IF(pPath == NULL,FALSE,"EnsureFileExtension bad path specified");
04745 
04746     // we are essentially a GIF filter so we need that extension
04747     String_32 ExtStr(_R(IDN_FILTEREXT_GIF));
04748     ExtStr.toLower();
04749     String_256 Extension = pPath->GetType();
04750     Extension.toLower();
04751     if (Extension.IsEmpty() || Extension != ExtStr)
04752     {
04753         // There is no extension set for this file, so give it one
04754         pPath->SetType(ExtStr);
04755     }
04756 
04757     return TRUE;
04758 } 
04759 
04760 /********************************************************************************************
04761 // end of OpSaveAnimatedGIF
04762 ********************************************************************************************/
04763 
04764 
04765 //------------------------------------------------------------------------------------------
04766 // Methods for the OpBrowserPreview
04767 //------------------------------------------------------------------------------------------
04768 
04769 // Init the static that we have
04770 PathName    OpBrowserPreview::m_TempPath;
04771 
04772 /********************************************************************************************
04773 
04774 >   BOOL OpBrowserPreview::GetFileNameFromUser()
04775 
04776     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04777     Created:    7/7/97
04778     Returns:    True if worked ok, False otherwise
04779     Purpose:    Gives the operation chance to get the filename from the user.
04780                 In this version we need to override the OpSaveAnimation's version so that
04781                 we do nothing.
04782 
04783 ********************************************************************************************/
04784 
04785 BOOL OpBrowserPreview::GetFileNameFromUser()
04786 {
04787     // This version, do nothing
04788     return TRUE;
04789 }
04790 
04791 /********************************************************************************************
04792 
04793 >   virtual BOOL OpBrowserPreview::SaveOrShowTheAnimation(PreviewDialog * pPreviewDialog, BitmapExportParam* pExportParam)
04794 
04795     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04796     Created:    4/8/97
04797     Inputs:     pPreviewDialog  the preview dialog box, if open
04798                 pExportParam    the export param which we will use
04799     Returns:    True if worked ok, False otherwise
04800     Purpose:    Tries to actually do the preview operation required.
04801                 In this case we just save the animation out to a temporary file and then fire
04802                 up the browser with an html wrapper which references that file.
04803 
04804 ********************************************************************************************/
04805 
04806 BOOL OpBrowserPreview::SaveOrShowTheAnimation(PreviewDialog * pPreviewDialog, BitmapExportParam* pExportParam)
04807 {
04808     // A bit of checking on parameters
04809     if (pExportParam != NULL)
04810     {
04811         ERROR3IF(!pExportParam->IS_KIND_OF(BitmapExportParam), "OpParam passed is not a BitmapExportParam");
04812 
04813         if (pExportParam->GetBitmapCount() == 0)
04814         {
04815             ERROR2RAW("OpSaveAnimatedGIF::DoWithParam no bitmaps to export");
04816             return FALSE;
04817         }               
04818     }
04819     else
04820     {
04821         ERROR2RAW("OpSaveAnimatedGIF::DoWithParam bad params!");
04822         return FALSE;
04823     }
04824 
04825     // Go and preview it in a browser.
04826     // Get our saving filter
04827     if (m_pBitmapFilter == NULL)
04828         m_pBitmapFilter = new GrabFrameFilter();
04829     if (m_pBitmapFilter == NULL)
04830     {
04831         InformError(_R(IDT_CANT_FIND_FILTER));
04832         return FALSE;
04833     }
04834     
04835     // create a disk file
04836     CCDiskFile TempDiskFile(1024, FALSE, TRUE);
04837 
04838     // Ensure that if we have been using a previous temp file then
04839     // it is cleaned up
04840     RemoveTempFile();
04841 
04842     // Create the required unique temporary of the correct filetype
04843     String_32 ExtStr(_R(IDN_FILTEREXT_GIF));
04844     ExtStr.toLower();
04845     if (!FileUtil::GetTemporaryPathName(ExtStr, &m_TempPath))
04846         return FALSE;
04847 
04848     // Ensure that we have the correct extension on the filename we have allocated
04849     EnsureFileType(&m_TempPath);
04850 
04851     // First off, we have to try and open the file
04852     CCDiskFile DiskFile(1024, FALSE, TRUE);
04853 
04854     BOOL ExportedOk = TRUE;
04855 
04856     try
04857     {
04858         // Export bitmaps supressing the filename so that the user does not see the temp filename
04859         ExportedOk = m_pBitmapFilter->DoExportBitmaps(this, &TempDiskFile, &m_TempPath, &m_ExportParams, TRUE);
04860 
04861         if (!ExportedOk)
04862         {
04863             // Something went a bit wrong - tell the user what it was.
04864             // Supress the error if it was the 'user has cancelled one'
04865             if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED))
04866             {
04867                 InformError();
04868                 m_pBitmapFilter->DeleteExportFile(&DiskFile);
04869             }
04870             else
04871             {
04872                 // otherwise remove the error so it won't get reported
04873                 Error::ClearError();
04874             }
04875         }
04876 
04877         // close the file
04878         if (DiskFile.isOpen())
04879             DiskFile.close();
04880     }
04881 
04882     // See if there was a file io error
04883     catch(CFileException)
04884     {
04885         // Report the error if no one else did
04886         if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED))
04887         {
04888             InformError();
04889         }
04890         else
04891             Error::ClearError();    // otherwise remove the error so it won't get reported
04892 
04893         // Make sure that the file is closed and deleted
04894         try
04895         {
04896             // First try and delete it (tries to close it first)
04897             if (m_pBitmapFilter)
04898                 m_pBitmapFilter->DeleteExportFile(&DiskFile);
04899 
04900             // Double check to make sure it is closed.
04901             if (DiskFile.isOpen())
04902                 DiskFile.close();
04903         }
04904         catch(CFileException)
04905         {
04906             // Failed to close the file - not much we can do about it really
04907         }
04908 
04909         // Fail
04910         ExportedOk = FALSE;
04911     }
04912 
04914     // Now we have the file, we can go and preview it in the browser
04915     
04916     // Allocate our preview class, must keep it around as destruction causes
04917     // it to clean up the temp files, which is bad if this is before it has
04918     // had a chance to fire up the browser!
04919     if (m_pBitmapData == NULL)
04920     {
04921         m_pBitmapData = new BitmapPreviewData;
04922         if (m_pBitmapData == NULL)
04923             return FALSE;
04924     } 
04925     // Now a static pointer as otherwise the temp file is deleted too quickly
04926     
04927     MakeBitmapExportOptions * pBmpOptions = NULL;
04928     // Recover the options from the filter that it saved during the preparation of the bitmaps
04929     // They are helpfully vaped by now! So, we took a copy during GetExportOptions
04930     // But if all the frame are already captured then we will not have any options
04931     pBmpOptions = m_pBitmapFilter->GetCurrentExportOptionsCopy();
04932     BOOL MadeBitmapOptions = FALSE;
04933     if (pBmpOptions == NULL)
04934     {
04935         // Get the filter to set up the bitmap options for us (Use out public version of CreateExportOptions)
04936         pBmpOptions = m_pBitmapFilter->MakeExportOptions();
04937         // Use our public interface onto the GetExportOptions protected function
04938         if (pBmpOptions != NULL)
04939         {
04940             MadeBitmapOptions = TRUE;
04941             m_pBitmapFilter->SetupExportOptions(pBmpOptions, m_pSpread);
04942         }
04943     }
04944     ERROR2IF(pBmpOptions == NULL,FALSE,"OpBrowserPreview::PreviewAnimation No current bitmap options");
04945 
04946     // Get the first bitmap in the list, this will give us the size of the animation
04947     KernelBitmap* pTheBitmap = pExportParam->GetBitmap(0);
04948     // Get the filesize that we have exported
04949     UINT32 FileSize = TempDiskFile.Size();
04950 
04951     // tell the options about the temp file that we are using
04952     pBmpOptions->SetPathName(&m_TempPath);
04953 
04954     // This is our copy of the BitmapExportParam
04955     m_pBitmapData->SetNewBitmap(pTheBitmap, FileSize, pBmpOptions);
04956 
04957     // Set up the options that we require
04958 /*  BrowserBackground Bgr   = BROWSER_BGR_DOC; //BROWSER_BGR_CHECKER;
04959     BOOL ShowInfo           = TRUE;
04960     BOOL GenerateImagemap   = FALSE;
04961 */
04962     // Get the values from our global variables.
04963     BrowserBackground Bgr   = PreviewInBrowserTab::g_Background;
04964     BOOL ShowInfo           = PreviewInBrowserTab::g_InfoInHtmlStub;
04965     BOOL GenerateImagemap   = FALSE;    
04966 
04967     BrowserPreviewOptions PreviewOptions(Bgr, ShowInfo, GenerateImagemap);
04968 
04969     //BrowserPreviewOptions PreviewOptions(PreviewInBrowserTab::GetBrowserOptions());
04970 
04971     // tell it what spread to use when getting the document background
04972     PreviewOptions.SetSpread(m_pSpread);
04973     
04974     // This should actually preview it in the browser
04975     m_pBitmapData->GenerateHTMLStub(PreviewOptions);
04976     
04977 
04978     // Clean out the filter we created
04979     delete m_pBitmapFilter;
04980     m_pBitmapFilter = NULL;
04981     
04982     if (MadeBitmapOptions && pBmpOptions != NULL)
04983         delete pBmpOptions;
04984 
04985     return ExportedOk;
04986 }
04987 
04988 /********************************************************************************************
04989 
04990 >   OpState OpBrowserPreview::GetState(String_256*, OpDescriptor*)
04991 
04992     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04993     Created:    20/6/97
04994     Inputs:     Name of the OpDescriptor being queried
04995     Outputs:    The string to show to the user
04996     Returns:    The state of the OpBrowserPreview operation
04997     Purpose:    For finding the OpBrowserPreview's state. 
04998 
04999 ********************************************************************************************/
05000 
05001 /* OpState  OpBrowserPreview::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc)
05002 {
05003     // This is always unavailable for the present moment
05004     OpState OpSt;
05005     OpSt.Greyed = TRUE; 
05006     return OpSt;   
05007 } */
05008 
05009 /********************************************************************************************
05010 
05011 >   static BOOL OpBrowserPreview::RemoveTempFile()
05012 
05013     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
05014     Created:    7/7/97
05015     Returns:    True if worked correctly, False otherwise.
05016     Purpose:    For cleaning up any temp file useage that we may have made.
05017                 This should be called in the DeInit during program shut down.
05018 
05019 ********************************************************************************************/
05020 
05021 BOOL OpBrowserPreview::RemoveTempFile()
05022 {
05023     // If we have used the m_TempPath during this session then ensure that we have cleaned up
05024     // any temp files
05025     String_256 Filename;
05026     Filename = m_TempPath.GetPath();
05027     if (!Filename.IsEmpty() && m_TempPath.IsValid())
05028     {   
05029         FileUtil::DeleteFile(&m_TempPath);
05030     }
05031 
05032     return TRUE;
05033 }
05034 
05035 /********************************************************************************************
05036 // End of OpBrowserPreview
05037 ********************************************************************************************/
05038 
05039 #endif // EXCLUDE_FROM_XARALX
05040 
05041 

Generated on Sat Nov 10 03:45:23 2007 for Camelot by  doxygen 1.4.4