// $Id: frameops.cpp 1282 2006-06-09 09:46:49Z alex $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ // The Frame Operations source file /* */ #include "camtypes.h" #include "frameops.h" //#include "prevwres.h" // _R(IDS_DISPLAY_FRAME_GALLERY) _R(IDD_ANIMATIONBAR) ... #include "sgframe.h" // FrameSGallery //#include "spread.h" // Spread - in camtypes.h [AUTOMATICALLY REMOVED] //#include "simon.h" // _R(IDS_NO_DOC) //#include "app.h" // GetApplication() - in camtypes.h [AUTOMATICALLY REMOVED] //#include "fixmem.h" // CCMalloc - in camtypes.h [AUTOMATICALLY REMOVED] #include "prevwdlg.h" // OPTOKEN_PREVIEWDIALOG #include "grndbmp.h" // GRenderBitmap #include "filedlgs.h" // ExportFileDialog //#include "tim.h" // _R(IDT_CANT_FIND_FILTER) //#include "oilfltrs.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "nev.h" // _R(IDN_USER_CANCELLED) #include "layermsg.h" // layer messages REDRAW_LAYER //#include "accures.h" // _R(IDN_FILTEREXT_GIF) //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "nodebmp.h" // NodeBitmap #include "insertnd.h" // InsertionNode #include "aprps.h" // browser preview #include "fileutil.h" // FileUtil::GetTemporaryPathName() #include "cbmpdata.h" // CBitmapData #include "palman.h" // MakePaletteBrowserCompatible //#include "xshelpid.h" //For the help ID #include "gpalopt.h" // for the palette optimiser #include "mrhbits.h" #include "page.h" //#include "quality.h" - in camtypes.h [AUTOMATICALLY REMOVED] DECLARE_SOURCE("$Revision: 1282 $"); CC_IMPLEMENT_DYNCREATE(OpSelectStartFrame, OpLayerGalChange); CC_IMPLEMENT_DYNCREATE(OpSelectEndFrame, OpLayerGalChange); CC_IMPLEMENT_DYNCREATE(OpSelectPrevFrame, OpLayerGalChange); CC_IMPLEMENT_DYNCREATE(OpSelectNextFrame, OpLayerGalChange); CC_IMPLEMENT_DYNCREATE(OpCreateNewFrame, OpLayerGalChange); CC_IMPLEMENT_DYNCREATE(OpCopyFrame, OpLayerGalChange); CC_IMPLEMENT_DYNCREATE(OpDeleteFrame, OpLayerGalChange); CC_IMPLEMENT_DYNCREATE(OpFrameProperties, Operation); CC_IMPLEMENT_DYNCREATE(OpAnimationProperties, Operation); PORTNOTE("other", "Removed GrabFrameFilter, OpGrabFrame, OpGrabAllFrames") #ifndef EXCLUDE_FROM_XARALX CC_IMPLEMENT_DYNAMIC(GIFAnimationExportParam, BitmapExportParam); CC_IMPLEMENT_DYNCREATE(OpGrabFrame, Operation); CC_IMPLEMENT_DYNCREATE(OpGrabAllFrames, OpGrabFrame); CC_IMPLEMENT_DYNAMIC(GrabFrameFilter, MakeBitmapFilter); CC_IMPLEMENT_DYNCREATE(OpSaveAnimatedGIF, OpGrabAllFrames); CC_IMPLEMENT_DYNCREATE(OpBrowserPreview, OpSaveAnimatedGIF); BOOL OpGrabAllFrames::ms_ForceRefreshOfAllFrames = FALSE; #endif // This will get Camelot to display the filename and linenumber of any memory allocations // that are not released at program exit // This line mustn't go before any CC_IMPLEMENT_... macros #define new CAM_DEBUG_NEW //------------------------------------------------------------------------------------------ // Methods for the OpSelectStartFrame //------------------------------------------------------------------------------------------ /******************************************************************************************** > OpState OpSelectStartFrame::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 21/4/97 Inputs: Name of the OpDescriptor being queried Outputs: The string to show to the user Returns: The state of the OpSelectStartFrame operation Purpose: For finding the OpSelectStartFrame's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpSelectStartFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc) { OpState OpSt; // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); Layer * pPrevLayer = pLayer->FindPrevLayer(); // The previous layer should really be a frame layer but we cannot guarantee that but // it mustn't be a guide, a page background or a background layer. while ( pPrevLayer && !pPrevLayer->IsPseudoFrame()) { pPrevLayer = pPrevLayer->FindPrevLayer(); } if (pLayer && pPrevLayer) { // Yes, so we are allowed to move to the next one OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } return OpSt; } /******************************************************************************************** > void OpSelectStartFrame::Do(OpDescriptor * pOpDesc) Author: Neville_Humphrys (Xara Group Ltd) Created: 21/4/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Tries to select the bottom most animation frame (i.e. layer). Errors: - SeeAlso: - ********************************************************************************************/ void OpSelectStartFrame::Do( OpDescriptor * pOpDesc ) { // Just find the background layer and then ask our baseclass to delete it for us // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { PORTNOTE("other", "Disabled FrameSGallery") #ifndef EXCLUDE_FROM_XARALX // Check that all visible layers are actually frame layers FrameSGallery::EnsureFrameLayerIntegrity(pSpread); #endif // yes, so find the first layer and try to move to it Layer * pLayer = pSpread->FindFirstFrameLayer(); if (pLayer) { OpLayerGalParam Param(FRAME_SELECT, pSpread); Param.pLayer = pLayer; DoWithParam(pOpDesc, (OpParam*)&Param); } } // End the operation, but we are calling DoWithParam() which we will assume does it for us. //End(); return; } /******************************************************************************************** // End of OpSelectStartFrame ********************************************************************************************/ //------------------------------------------------------------------------------------------ // Methods for the OpSelectEndFrame //------------------------------------------------------------------------------------------ /******************************************************************************************** > OpState OpSelectEndFrame::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 22/4/97 Inputs: Name of the OpDescriptor being queried Outputs: The string to show to the user Returns: The state of the OpSelectEndFrame operation Purpose: For finding the OpSelectEndFrame's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpSelectEndFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc) { OpState OpSt; // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // If there is an active layer and one following then we are not greyed Layer * pNextLayer = pLayer->FindNextLayer(); // The next layer should really be a frame layer but we cannot guarantee that but // it mustn't be a guide, a page background or a background layer. while ( pNextLayer && !pNextLayer->IsPseudoFrame()) { pNextLayer = pNextLayer->FindNextLayer(); } if (pLayer && pNextLayer) { // Yes, so we are allowed to move to the previous one OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } return OpSt; } /******************************************************************************************** > void OpSelectEndFrame::Do(OpDescriptor * pOpDesc) Author: Neville_Humphrys (Xara Group Ltd) Created: 22/4/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Tries to select the bottom most animation frame (i.e. layer). Errors: - SeeAlso: - ********************************************************************************************/ void OpSelectEndFrame::Do( OpDescriptor * pOpDesc ) { // Just find the background layer and then ask our baseclass to delete it for us // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { PORTNOTE("other", "Disabled FrameSGallery") #ifndef EXCLUDE_FROM_XARALX // Check that all visible layers are actually frame layers FrameSGallery::EnsureFrameLayerIntegrity(pSpread); #endif // yes, so find the last layer and try to move to it Layer * pLayer = pSpread->FindLastFrameLayer(); if (pLayer) { OpLayerGalParam Param(FRAME_SELECT, pSpread); Param.pLayer = pLayer; DoWithParam(pOpDesc, (OpParam*)&Param); } } // End the operation, but we are calling DoWithParam() which we will assume does it for us. //End(); return; } /******************************************************************************************** // End of OpSelectEndFrame ********************************************************************************************/ //------------------------------------------------------------------------------------------ // Methods for the OpSelectPrevFrame //------------------------------------------------------------------------------------------ /******************************************************************************************** > OpState OpSelectPrevFrame::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 22/4/97 Inputs: Name of the OpDescriptor being queried Outputs: The string to show to the user Returns: The state of the OpSelectPrevFrame operation Purpose: For finding the OpSelectPrevFrame's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpSelectPrevFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc) { //The frame movement controls on the GIF animation bar now work on frames only. OpState OpSt; #ifdef WEBSTER // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // If there is an active layer and one preceeding then we are not greyed Layer * pPrevLayer = pLayer->FindPrevLayer(); // The previous layer should really be a frame layer but we cannot guarantee that but // it mustn't be a guide, a page background or a background layer. while ( pPrevLayer && !pPrevLayer->IsPseudoFrame()) { pPrevLayer = pPrevLayer->FindPrevLayer(); } if (pLayer && pPrevLayer) { // Yes, so we are allowed to move to the previous one OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } #else // Are we in frame mode. BOOL FrameMode = IsFrameMode(); if(FrameMode) { // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // If there is an active layer and one preceeding then we are not greyed Layer * pPrevLayer = pLayer->FindPrevLayer(); // The previous layer should really be a frame layer but we cannot guarantee that but // it mustn't be a guide, a page background or a background layer. while ( pPrevLayer && !pPrevLayer->IsPseudoFrame()) { pPrevLayer = pPrevLayer->FindPrevLayer(); } if (pLayer && pPrevLayer) { // Yes, so we are allowed to move to the previous one OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } } else { // The document is layer based, so we are greyed. OpSt.Greyed = TRUE; } #endif return OpSt; } /******************************************************************************************** > void OpSelectPrevFrame::Do(OpDescriptor * pOpDesc) Author: Neville_Humphrys (Xara Group Ltd) Created: 22/4/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Tries to select the previous animation frame (i.e. layer). Errors: - SeeAlso: - ********************************************************************************************/ void OpSelectPrevFrame::Do( OpDescriptor * pOpDesc ) { // Just find the background layer and then ask our baseclass to delete it for us // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { PORTNOTE("other", "Disabled FrameSGallery") #ifndef EXCLUDE_FROM_XARALX // Check that all visible layers are actually frame layers FrameSGallery::EnsureFrameLayerIntegrity(pSpread); #endif // yes, so find the last layer and try to move to it Layer * pLayer = pSpread->FindActiveLayer(); Layer * pPrevLayer = NULL; if (pLayer) pPrevLayer = pLayer->FindPrevFrameLayer(); if (pPrevLayer) { OpLayerGalParam Param(FRAME_SELECT, pSpread); Param.pLayer = pPrevLayer; DoWithParam(pOpDesc, (OpParam*)&Param); } } // End the operation, but we are calling DoWithParam() which we will assume does it for us. //End(); return; } /******************************************************************************************** // End of OpSelectPrevFrame ********************************************************************************************/ //------------------------------------------------------------------------------------------ // Methods for the OpSelectNextFrame //------------------------------------------------------------------------------------------ /******************************************************************************************** > OpState OpSelectNextFrame::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 22/4/97 Inputs: Name of the OpDescriptor being queried Outputs: The string to show to the user Returns: The state of the OpSelectNextFrame operation Purpose: For finding the OpSelectNextFrame's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpSelectNextFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc) { //The frame movement controls on the GIF animation bar now work on frames only. OpState OpSt; #ifdef WEBSTER // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // If there is an active layer and one following then we are not greyed Layer * pNextLayer = pLayer->FindNextLayer(); // The next layer should really be a frame layer but we cannot guarantee that but // it mustn't be a guide, a page background or a background layer. while ( pNextLayer && !pNextLayer->IsPseudoFrame()) { pNextLayer = pNextLayer->FindNextLayer(); } if (pLayer && pNextLayer) { // Yes, so we are allowed to move to the previous one OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } #else // Are we in frame mode. BOOL FrameMode = IsFrameMode(); if(FrameMode) { // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // If there is an active layer and one following then we are not greyed Layer * pNextLayer = pLayer->FindNextLayer(); // The next layer should really be a frame layer but we cannot guarantee that but // it mustn't be a guide, a page background or a background layer. while ( pNextLayer && !pNextLayer->IsPseudoFrame()) { pNextLayer = pNextLayer->FindNextLayer(); } if (pLayer && pNextLayer) { // Yes, so we are allowed to move to the previous one OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } } else { // The document is layer based, so we are greyed. OpSt.Greyed = TRUE; } #endif return OpSt; } /******************************************************************************************** > void OpSelectNextFrame::Do(OpDescriptor * pOpDesc) Author: Neville_Humphrys (Xara Group Ltd) Created: 22/4/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Tries to select the next animation frame (i.e. layer). Errors: - SeeAlso: - ********************************************************************************************/ void OpSelectNextFrame::Do( OpDescriptor * pOpDesc ) { // Just find the background layer and then ask our baseclass to delete it for us // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { PORTNOTE("other", "Disabled BrowserPreviewOptions") #ifndef EXCLUDE_FROM_XARALX // Check that all visible layers are actually frame layers FrameSGallery::EnsureFrameLayerIntegrity(pSpread); #endif // yes, so find the next layer and try to move to it Layer * pLayer = pSpread->FindActiveLayer(); Layer * pNextLayer = NULL; if (pLayer) pNextLayer = pLayer->FindNextFrameLayer(); if (pNextLayer) { OpLayerGalParam Param(FRAME_SELECT, pSpread); Param.pLayer = pNextLayer; DoWithParam(pOpDesc, (OpParam*)&Param); } } // End the operation, but we are calling DoWithParam() which we will assume does it for us. //End(); return; } /******************************************************************************************** // End of OpSelectNextFrame ********************************************************************************************/ //------------------------------------------------------------------------------------------ // Methods for the OpCreateNewFrame //------------------------------------------------------------------------------------------ /******************************************************************************************** > OpState OpCreateNewFrame::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 22/4/97 Inputs: Name of the OpDescriptor being queried Outputs: The string to show to the user Returns: The state of the OpCreateNewFrame operation Purpose: For finding the OpCreateNewFrame's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpCreateNewFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc) { //The frame movement controls on the GIF animation bar now work on frames only. OpState OpSt; #ifdef WEBSTER // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // Yes, so we are allowed to move to the previous one OpSt.Greyed = FALSE; } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } #else // Are we in frame mode. BOOL FrameMode = IsFrameMode(); if(FrameMode) { // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // Yes, so we are allowed to move to the previous one OpSt.Greyed = FALSE; } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } } else { // The document is layer based, so we are greyed. OpSt.Greyed = TRUE; } #endif return OpSt; } /******************************************************************************************** > void OpCreateNewFrame::Do(OpDescriptor * pOpDesc) Author: Neville_Humphrys (Xara Group Ltd) Created: 22/4/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Tries to create a new animation frame (i.e. layer). Errors: - SeeAlso: - ********************************************************************************************/ void OpCreateNewFrame::Do( OpDescriptor * pOpDesc ) { PORTNOTE("other", "Disabled BrowserPreviewOptions") #ifndef EXCLUDE_FROM_XARALX // Just find the background layer and then ask our baseclass to delete it for us // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // Check that all visible layers are actually frame layers FrameSGallery::EnsureFrameLayerIntegrity(pSpread); // Use the spread as the context node OpLayerGalParam Param(FRAME_NEW, pSpread); Param.pLayer = NULL; Param.pContextNode = pSpread; Param.AttDir = LASTCHILD; // Set up the name that is going to be applied to the frame String_256 NewName = FrameSGallery::CreateUniqueLayerID(pSpread); //String_256 NewName(_R(IDS_DEFAULTFRAMENAME)); Param.Status.StringLayerID = NewName; DoWithParam(pOpDesc, (OpParam*)&Param); } // End the operation, but we are calling DoWithParam() which we will assume does it for us. //End(); #endif return; } /******************************************************************************************** // End of OpCreateNewFrame ********************************************************************************************/ //------------------------------------------------------------------------------------------ // Methods for the OpCopyFrame //------------------------------------------------------------------------------------------ /******************************************************************************************** > OpState OpCopyFrame::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 22/4/97 Inputs: Name of the OpDescriptor being queried Outputs: The string to show to the user Returns: The state of the OpCopyFrame operation Purpose: For finding the OpCopyFrame's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpCopyFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc) { //The frame movement controls on the GIF animation bar now work on frames only. OpState OpSt; #ifdef WEBSTER // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // If there is an active layer then we are not greyed if (pLayer) { OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } #else // Are we in frame mode. BOOL FrameMode = IsFrameMode(); if(FrameMode) { // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // If there is an active layer then we are not greyed if (pLayer) { OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } } else { // The document is layer based, so we are greyed. OpSt.Greyed = TRUE; } #endif return OpSt; } /******************************************************************************************** > void OpCopyFrame::Do(OpDescriptor * pOpDesc) Author: Neville_Humphrys (Xara Group Ltd) Created: 22/4/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Tries to create a new frame by copying the present one. Errors: - SeeAlso: - ********************************************************************************************/ void OpCopyFrame::Do( OpDescriptor * pOpDesc ) { PORTNOTE("other", "Disabled FrameSGallery") #ifndef EXCLUDE_FROM_XARALX // Just find the background layer and then ask our baseclass to delete it for us // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // Check that all visible layers are actually frame layers FrameSGallery::EnsureFrameLayerIntegrity(pSpread); // yes, so check that there is a presently active layer and try to copy it // Use the spread as the context node Layer * pLayer = pSpread->FindActiveLayer(); if (pLayer) { OpLayerGalParam Param(FRAME_COPY, pSpread); Param.pLayer = pLayer; Param.pContextNode = pSpread; Param.AttDir = LASTCHILD; // Set up the name that is going to be applied to the frame String_256 NewName = FrameSGallery::CreateUniqueLayerID(pSpread); //String_256 NewName(_R(IDS_DEFAULTFRAMENAME)); Param.Status.StringLayerID = NewName; DoWithParam(pOpDesc, (OpParam*)&Param); } } // End the operation, but we are calling DoWithParam() which we will assume does it for us. //End(); #endif return; } /******************************************************************************************** // End of OpCopyFrame ********************************************************************************************/ //------------------------------------------------------------------------------------------ // Methods for the OpDeleteFrame //------------------------------------------------------------------------------------------ /******************************************************************************************** > OpState OpDeleteFrame::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 23/4/97 Inputs: Name of the OpDescriptor being queried Outputs: The string to show to the user Returns: The state of the OpDeleteFrame operation Purpose: For finding the OpDeleteFrame's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpDeleteFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc) { //The frame movement controls on the GIF animation bar now work on frames only. OpState OpSt; #ifdef WEBSTER // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // Get ptr's to the next and previous frame layers. Layer* pNextLayer = pLayer->FindNextFrameLayer(); Layer* pPrevLayer = pLayer->FindPrevFrameLayer(); // If there is an active layer and a previous/next layer then we are not greyed. if ( pLayer && (pPrevLayer || pNextLayer) ) { OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } #else // Are we in frame mode. BOOL FrameMode = IsFrameMode(); if(FrameMode) { // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // Get ptr's to the next and previous frame layers. Layer* pNextLayer = pLayer->FindNextFrameLayer(); Layer* pPrevLayer = pLayer->FindPrevFrameLayer(); // If there is an active layer and a previous/next layer then we are not greyed. if (pLayer && (pPrevLayer || pNextLayer) ) { OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } } else { // We are in layer mode, so we are greyed. OpSt.Greyed = TRUE; } #endif return OpSt; } /******************************************************************************************** > void OpDeleteFrame::Do(OpDescriptor * pOpDesc) Author: Neville_Humphrys (Xara Group Ltd) Created: 23/4/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Tries to create a new frame by copying the present one. Errors: - SeeAlso: - ********************************************************************************************/ void OpDeleteFrame::Do( OpDescriptor * pOpDesc ) { // Just find the background layer and then ask our baseclass to delete it for us // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { PORTNOTE("other", "Disabled FrameSGallery") #ifndef EXCLUDE_FROM_XARALX // Check that all visible layers are actually frame layers FrameSGallery::EnsureFrameLayerIntegrity(pSpread); #endif // yes, so check that there is a presently active layer and try to delete it Layer * pLayer = pSpread->FindActiveLayer(); if (pLayer) { OpLayerGalParam Param(FRAME_DELETE, pSpread); Param.pLayer = pLayer; DoWithParam(pOpDesc, (OpParam*)&Param); } } // End the operation, but we are calling DoWithParam() which we will assume does it for us. //End(); return; } /******************************************************************************************** // End of OpDeleteFrame ********************************************************************************************/ //------------------------------------------------------------------------------------------ // Methods for the OpFrameProperties //------------------------------------------------------------------------------------------ /******************************************************************************************** > OpState OpFrameProperties::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 29/4/97 Inputs: Name of the OpDescriptor being queried Outputs: The string to show to the user Returns: The state of the OpFrameProperties operation Purpose: For finding the OpFrameProperties's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpFrameProperties::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc) { //The frame movement controls on the GIF animation bar now work on frames only. OpState OpSt; #ifdef WEBSTER // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // If there is an active layer and one following then we are not greyed if (pLayer) { // Yes, so we are allowed to move to the previous one OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } #else BOOL FrameMode = FALSE; // Flag to determine the document mode. // Is there a selected spread? Spread* pSpread = Document::GetSelectedSpread(); // Ensure a valid spread ptr. if(pSpread) { // Are there any frame layers? Layer* pFrameLayer = pSpread->FindFirstFrameLayer(); //If a frame layer exists, then this is an animation doc. if (pFrameLayer) FrameMode = TRUE; } if(FrameMode) { if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // If there is an active layer and one following then we are not greyed if (pLayer) // Yes, so we are allowed to move to the previous one OpSt.Greyed = FALSE; else // No, so we are greyed OpSt.Greyed = TRUE; } else // No selected spread, so we are greyed OpSt.Greyed = TRUE; } else { // The document is layer based, so we are greyed. OpSt.Greyed = TRUE; } #endif return OpSt; } /******************************************************************************************** > void OpFrameProperties::Do(OpDescriptor * pOpDesc) Author: Neville_Humphrys (Xara Group Ltd) Created: 29/4/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Tries to set some new animation properties. Errors: - SeeAlso: - ********************************************************************************************/ void OpFrameProperties::Do( OpDescriptor * pOpDesc ) { // Just find the background layer and then ask our baseclass to delete it for us // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { PORTNOTE("other", "Disabled FrameSGallery") #ifndef EXCLUDE_FROM_XARALX // Check that all visible layers are actually frame layers FrameSGallery::EnsureFrameLayerIntegrity(pSpread); #endif OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_GIFANIMPROPERTYTABS); if (pOpDesc != NULL) { // Select the "Frame properties tab". GIFAnimationPropertyTabsDlg::SetPageToOpen(GIFAnimationPropertyTabs::FramePropertiesTabNumber); String_256 Str; OpState State = pOpDesc->GetOpsState(&Str); if (!State.Greyed) pOpDesc->Invoke(); else { GIFAnimationPropertyTabs * pTabHandler = GIFAnimationPropertyTabsDlg::GetGIFAnimationPropertiesTabs(); if (pTabHandler) { DialogTabOp* pDlg = pTabHandler->GetTabbedDlg(); if (pDlg != NULL) pDlg->Open(); } } } } // End the operation End(); return; } /******************************************************************************************** // End of OpFrameProperties ********************************************************************************************/ //------------------------------------------------------------------------------------------ // Methods for the OpAnimationProperties //------------------------------------------------------------------------------------------ /******************************************************************************************** > OpState OpAnimationProperties::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 29/4/97 Inputs: Name of the OpDescriptor being queried Outputs: The string to show to the user Returns: The state of the OpAnimationProperties operation Purpose: For finding the OpAnimationProperties's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpAnimationProperties::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc) { //The frame movement controls on the GIF animation bar now work on frames only. OpState OpSt; #ifdef WBSTER // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // If there is an active layer and one following then we are not greyed if (pLayer) { // Yes, so we are allowed to move to the previous one OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } #else BOOL FrameMode = FALSE; // Flag to determine the document mode. // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); // Ensure a valid spread ptr. if(pSpread) { // Are there any frame layers? Layer* pFrameLayer = pSpread->FindFirstFrameLayer(); //If a frame layer exists, then this is an animation doc. if (pFrameLayer) FrameMode = TRUE; } if(FrameMode) { if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); // If there is an active layer and one following, then we are not greyed. if (pLayer) { // Yes, so we are allowed to move to the previous one OpSt.Greyed = FALSE; } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; } } else { // The document is layer based, so we are greyed. OpSt.Greyed = TRUE; *pUIDescription = String_256 (_R(IDS_NO_FRAMES)); } #endif return OpSt; } /******************************************************************************************** > void OpAnimationProperties::Do(OpDescriptor * pOpDesc) Author: Neville_Humphrys (Xara Group Ltd) Created: 29/4/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Tries to set some new animation properties. Errors: - SeeAlso: - ********************************************************************************************/ void OpAnimationProperties::Do( OpDescriptor * pOpDesc ) { // Just find the background layer and then ask our baseclass to delete it for us // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { PORTNOTE("other", "Disabled FrameSGallery") #ifndef EXCLUDE_FROM_XARALX // Check that all visible layers are actually frame layers. FrameSGallery::EnsureFrameLayerIntegrity(pSpread); #endif OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_GIFANIMPROPERTYTABS); if (pOpDesc != NULL) { // Select the "Animation properties tab" on start up. GIFAnimationPropertyTabsDlg::SetPageToOpen(GIFAnimationPropertyTabs::AnimationColoursTabNumber); String_256 Str; OpState State = pOpDesc->GetOpsState(&Str); if (!State.Greyed) pOpDesc->Invoke(); else { GIFAnimationPropertyTabs * pTabHandler = GIFAnimationPropertyTabsDlg::GetGIFAnimationPropertiesTabs(); if (pTabHandler) { DialogTabOp* pDlg = pTabHandler->GetTabbedDlg(); if (pDlg != NULL) pDlg->Open(); } } } } // End the operation End(); return; } /******************************************************************************************** // End of OpAnimationProperties ********************************************************************************************/ PORTNOTE("other", "Removed GrabFrameFilter, OpGrabFrame, OpGrabAllFrames") #ifndef EXCLUDE_FROM_XARALX //------------------------------------------------------------------------------------------ // Methods for the OpGrabFrame //------------------------------------------------------------------------------------------ BitmapPreviewData * OpGrabFrame::m_pBitmapData = NULL; /******************************************************************************************** > BOOL OpGrabFrame::Init() Author: Neville_Humphrys (Xara Group Ltd) Created: 19/6/97 Returns: TRUE if the operation could be successfully initialised FALSE if no more memory could be allocated Purpose: OpGrabFrame initialiser method Errors: ERROR will be called if there was insufficient memory to allocate the operation. ********************************************************************************************/ BOOL OpGrabFrame::Init() { BOOL ok = FALSE; // start of non-undoable operations ok = RegisterOpDescriptor( 0, // Tool ID _R(IDS_FRAMEPROPERTIES), // String resource ID CC_RUNTIME_CLASS(OpFrameProperties), // Runtime class OPTOKEN_FRAME_PROPERTIES, // Token string OpFrameProperties::GetState, // GetState function 0, // help ID _R(IDBBL_FRAMEPROPERTIES), // bubble help _R(IDD_ANIMATIONBAR), // resource ID _R(IDC_FRAME_FRAMEPROPERTIES), // control ID SYSTEMBAR_ANIMATION, // Bar ID TRUE, // Recieve system messages FALSE, // Smart duplicate operation TRUE, // Clean operation NULL, // No vertical counterpart 0, // String for one copy only error (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags ); if(ok) ok = RegisterOpDescriptor( 0, // Tool ID _R(IDS_ANIMATIONPROPERTIES), // String resource ID CC_RUNTIME_CLASS(OpAnimationProperties), // Runtime class OPTOKEN_FRAME_ANIPROPERTIES, // Token string OpAnimationProperties::GetState, // GetState function 0, // help ID _R(IDBBL_ANIMATIONPROPERTIES), // bubble help _R(IDD_ANIMATIONBAR), // resource ID _R(IDC_FRAME_ANIMATIONPROPERTIES), // control ID SYSTEMBAR_ANIMATION, // Bar ID TRUE, // Recieve system messages FALSE, // Smart duplicate operation TRUE, // Clean operation NULL, // No vertical counterpart 0, // String for one copy only error (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags ); if(ok) ok = RegisterOpDescriptor( 0, // Tool ID _R(IDS_GRABFRAME), // String resource ID CC_RUNTIME_CLASS(OpGrabFrame), // Runtime class OPTOKEN_FRAME_GRABFRAME, // Token string OpGrabFrame::GetState, // GetState function _R(IDH_Command_Preview_All_Frames), // help ID _R(IDBBL_GRABFRAME), // bubble help _R(IDD_ANIMATIONBAR), // resource ID _R(IDC_FRAME_GRABFRAME), // control ID SYSTEMBAR_ANIMATION, // Bar ID TRUE, // Recieve system messages FALSE, // Smart duplicate operation TRUE, // Clean operation NULL, // No vertical counterpart 0, // String for one copy only error (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags ); if(ok) ok = RegisterOpDescriptor( 0, // Tool ID _R(IDS_GRABALLFRAMES), // String resource ID CC_RUNTIME_CLASS(OpGrabAllFrames), // Runtime class OPTOKEN_FRAME_GRABALLFRAMES, // Token string OpGrabAllFrames::GetState, // GetState function _R(IDH_Command_Preview_All_Frames), // help ID _R(IDBBL_GRABALLFRAMES), // bubble help _R(IDD_ANIMATIONBAR), // resource ID _R(IDC_FRAME_GRABALLFRAMES), // control ID SYSTEMBAR_ANIMATION, // Bar ID TRUE, // Recieve system messages FALSE, // Smart duplicate operation TRUE, // Clean operation NULL, // No vertical counterpart 0, // String for one copy only error (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags ); if(ok) ok = RegisterOpDescriptor( 0, // Tool ID _R(IDS_FRAME_SAVEANIMATEDGIF), // String resource ID CC_RUNTIME_CLASS(OpSaveAnimatedGIF), // Runtime class OPTOKEN_SAVEANIMATEDGIF, // Token string OpSaveAnimatedGIF::GetState, // GetState function 0, // help ID _R(IDBBL_SAVEANIMATEDGIF), // bubble help _R(IDD_ANIMATIONBAR), // resource ID _R(IDC_FRAME_SAVEANIMATEDGIF), // control ID SYSTEMBAR_ANIMATION, // Bar ID TRUE, // Recieve system messages FALSE, // Smart duplicate operation TRUE, // Clean operation NULL, // No vertical counterpart 0, // String for one copy only error (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags ); if(ok) ok = RegisterOpDescriptor( 0, // Tool ID _R(IDS_BROWSERPREVIEW), // String resource ID CC_RUNTIME_CLASS(OpBrowserPreview), // Runtime class OPTOKEN_FRAME_BROWSERPREVIEW, // Token string OpBrowserPreview::GetState, // GetState function _R(IDH_Command_Preview_Animation_in_Browser), // help ID _R(IDBBL_BROWSERPREVIEW), // bubble help _R(IDD_ANIMATIONBAR), // resource ID _R(IDC_FRAME_GOTOBROWSER), // control ID SYSTEMBAR_ANIMATION, // Bar ID TRUE, // Recieve system messages FALSE, // Smart duplicate operation TRUE, // Clean operation NULL, // No vertical counterpart 0, // String for one copy only error (DONT_GREY_WHEN_SELECT_INSIDE | GREY_WHEN_NO_CURRENT_DOC) // Auto state flags ); // end of non-undoable operations if(ok) ok = PreviewInBrowserTab::Declare(); return ok; } /******************************************************************************************** > static void OpGrabFrame::DeInit(void) Author: Neville_Humphrys (Xara Group Ltd) Created: 3/7/97 Purpose: De-Initialises OpGrabFrame ********************************************************************************************/ void OpGrabFrame::DeInit(void) { // Deinit our static preview bitmap data pointer if allocated // This should clean up any temp files that we have used if (m_pBitmapData != NULL) { delete m_pBitmapData; m_pBitmapData = NULL; } // Give the browser preview chance to clean up its temp file useage OpBrowserPreview::RemoveTempFile(); } /******************************************************************************************** > OpState OpGrabFrame::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 23/4/97 Inputs: Name of the OpDescriptor being queried Outputs: The string to show to the user Returns: The state of the OpGrabFrame operation Purpose: For finding the OpGrabFrame's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpGrabFrame::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc) { //The frame movement controls on the GIF animation bar now work on frames only. OpState OpSt; #ifdef WEBSTER String_256 DisableReason; // Is there a selected spread? Spread * pSpread = Document::GetSelectedSpread(); if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); if (pLayer) { // Ensure that we have some visible objects on the specified layer to render // Could use a range but easier just to check if there are visible objects on the page DocRect VisibleRect = pSpread->GetPageVisibleBounds(); BOOL Empty = VisibleRect.IsEmpty(); // If this frame has nothing visible on it then check if there are renderable objects // on any other frames in the animation. if (Empty) { // Cannot assume that all the frame layers are actually frame layers so // go through all those that might be frame layers. Layer * pFrame = pSpread->FindFirstLayer(); while (pFrame && Empty) { if (pFrame->IsPseudoFrame() && pFrame->HasLayerGotRenderableChildren()) Empty = FALSE; pFrame = pFrame->FindNextLayer(); } } if (pOpDesc && pOpDesc->Token != String(OPTOKEN_FRAME_GRABFRAME) && !Empty) { // Cannot assume that all the frame layers are actually frame layers so // go through all those that might be frame layers. Layer * pFrame = pSpread->FindFirstLayer(); BOOL AllHidden = TRUE; while (pFrame && AllHidden) { if (pFrame->IsPseudoFrame() && !pFrame->IsHiddenFrame()) AllHidden = FALSE; pFrame = pFrame->FindNextLayer(); } if (AllHidden) { OpSt.Greyed = TRUE; // Load reason why operation is disabled DisableReason = String_256(_R(IDS_ALLFRAMESAREHIDDEN)); if (pUIDescription) *pUIDescription = DisableReason; } else { // Yes, so we are allowed to grab the frame or all the frames OpSt.Greyed = FALSE; } } else if (pOpDesc && pOpDesc->Token == String(OPTOKEN_FRAME_GRABFRAME) && pLayer->IsHiddenFrame()) { // If we are the grab frame op then check that the current layer is not // hidden. If so then disallow OpSt.Greyed = TRUE; // Load reason why operation is disabled DisableReason = String_256(_R(IDS_FRAMEISHIDDEN)); if (pUIDescription) *pUIDescription = DisableReason; } else if (!Empty) { // Yes, so we are allowed to grab the frame or all the frames OpSt.Greyed = FALSE; } else { OpSt.Greyed = TRUE; // Load reason why operation is disabled DisableReason = String_256(_R(IDS_NO_VISIBLE_OBJECTS)); if (pUIDescription) *pUIDescription = DisableReason; } } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; // Load reason why operation is disabled DisableReason = String_256(_R(IDS_NO_DOC)); if (pUIDescription) *pUIDescription = DisableReason; } #else // Flag to determine the document mode. BOOL FrameMode = FALSE; // Get a ptr to the selected spread Spread* pSpread = Document::GetSelectedSpread(); // Ensure a valid spread ptr. if(pSpread) { // Are there any frame layers? Layer* pFrameLayer = pSpread->FindFirstFrameLayer(); //If a frame layer exists, then this is an animation doc. if (pFrameLayer) FrameMode = TRUE; } if(FrameMode) { String_256 DisableReason; if (pSpread) { // yes, so check if there is an active layer Layer * pLayer = pSpread->FindActiveLayer(); if (pLayer) { // Ensure that we have some visible objects on the specified layer to render // Could use a range but easier just to check if there are visible objects on the page DocRect VisibleRect = pSpread->GetPageVisibleBounds(); BOOL Empty = VisibleRect.IsEmpty(); // If this frame has nothing visible on it then check if there are renderable objects // on any other frames in the animation. if (Empty) { // Cannot assume that all the frame layers are actually frame layers so // go through all those that might be frame layers. Layer * pFrame = pSpread->FindFirstLayer(); while (pFrame && Empty) { if (pFrame->IsPseudoFrame() && pFrame->HasLayerGotRenderableChildren()) Empty = FALSE; pFrame = pFrame->FindNextLayer(); } } if (pOpDesc && pOpDesc->Token != String(OPTOKEN_FRAME_GRABFRAME) && !Empty) { // Cannot assume that all the frame layers are actually frame layers so // go through all those that might be frame layers. Layer * pFrame = pSpread->FindFirstLayer(); BOOL AllHidden = TRUE; while (pFrame && AllHidden) { if (pFrame->IsPseudoFrame() && !pFrame->IsHiddenFrame()) AllHidden = FALSE; pFrame = pFrame->FindNextLayer(); } if (AllHidden) { OpSt.Greyed = TRUE; // Load reason why operation is disabled DisableReason = String_256(_R(IDS_ALLFRAMESAREHIDDEN)); if (pUIDescription) *pUIDescription = DisableReason; } else { // Yes, so we are allowed to grab the frame or all the frames OpSt.Greyed = FALSE; } } else if (pOpDesc && pOpDesc->Token == String(OPTOKEN_FRAME_GRABFRAME) && pLayer->IsHiddenFrame()) { // If we are the grab frame op then check that the current layer is not // hidden. If so then disallow OpSt.Greyed = TRUE; // Load reason why operation is disabled DisableReason = String_256(_R(IDS_FRAMEISHIDDEN)); if (pUIDescription) *pUIDescription = DisableReason; } else if (!Empty) { // Yes, so we are allowed to grab the frame or all the frames OpSt.Greyed = FALSE; } else { OpSt.Greyed = TRUE; // Load reason why operation is disabled DisableReason = String_256(_R(IDS_NO_VISIBLE_OBJECTS)); if (pUIDescription) *pUIDescription = DisableReason; } } else { // No, so we are greyed OpSt.Greyed = TRUE; } } else { // No selected spread, so we are greyed OpSt.Greyed = TRUE; // Load reason why operation is disabled DisableReason = String_256(_R(IDS_NO_DOC)); if (pUIDescription) *pUIDescription = DisableReason; } } else { // The document is layer based, so we are greyed. OpSt.Greyed = TRUE; *pUIDescription = String_256 (_R(IDS_NO_FRAMES)); } #endif return OpSt; } /******************************************************************************************** > OpGrabFrame::OpGrabFrame() Author: Neville_Humphrys (Xara Group Ltd) Created: 29/4/97 Purpose: Constructor ********************************************************************************************/ OpGrabFrame::OpGrabFrame() { m_pDocument = NULL; m_pSpread = NULL; m_pLayer = NULL; m_pView = NULL; m_pBitmapFilter = NULL; m_pSelState = NULL; //m_pBitmapData = NULL; m_pBrowserPalette = NULL; } /******************************************************************************************** > OpGrabFrame::~OpGrabFrame() Author: Neville_Humphrys (Xara Group Ltd) Created: 29/4/97 Purpose: Destructor ********************************************************************************************/ OpGrabFrame::~OpGrabFrame() { if (m_pBitmapFilter != NULL) { delete m_pBitmapFilter; m_pBitmapFilter = NULL; } if (m_pSelState != NULL) { delete m_pSelState; m_pSelState = NULL; } /* if (m_pBitmapData != NULL) { delete m_pBitmapData; m_pBitmapData = NULL; } */ if (m_pBrowserPalette != NULL) { CCFree(m_pBrowserPalette); m_pBrowserPalette = NULL; } } /************************************************************************************************************ > void OpGrabFrame::Do(OpDescriptor * pOpDesc) Author: Neville_Humphrys (Xara Group Ltd) Created: 23/4/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Tries to grab the selected animation frame (i.e. layer). This Op can be invoked under a number of circumstances:- 1. When the preview dialog is open. Dissplay the bitmap corresponding to the selected frame layer. If the selected frame layer is not in the Preview list (i.e has not been generated) then generate the bitmap and add it to the list of bitmaps which be will included in the Preview. 2. When the preview dialog is closed. In this case we need to generate the bitmap corresponding to the selected Frame layer. ****************************************************************************************************************/ void OpGrabFrame::Do( OpDescriptor * pOpDesc ) { DoWithParam(pOpDesc, NULL); return; } /******************************************************************************************** > void OpGrabFrame::DoWithParam(OpDescriptor * pOpDesc, Param* pParam) Author: Ranbir_Rana (Xara Group Ltd) (From Neville code.) Created: 21/05/97 Inputs: OpDescriptor (unused) pParam - NULL - means grab the active frame - Param1 = pLayer - means grab the specified layer Outputs: - Returns: - Purpose: Regenerate the bitmap associated with the active frame layer. Errors: - SeeAlso: - ********************************************************************************************/ void OpGrabFrame::DoWithParam(OpDescriptor * pOpDesc, OpParam* pParam) { // ERROR3IF(pParam == NULL, "OpGrabFrame::DoWithParam - NULL Param passed in"); // Get useful data and set up items before starting the grab process if (!StartGrab()) { // We failed to grab the frame FailAndExecute(); End(); return; } // If a parameter has been supplied then this should be a layer pointer, which we // should then use to grab the frame // Otherwise, we assume we must grab the active frame (StartGrab sets m_pLayer to the active layer) if (pParam != NULL) { // recover the layer pointer that has been specified Layer* pLayer = (Layer *) (void *) pParam->Param1; if (pLayer) { ERROR3IF(!pLayer->IS_KIND_OF(Layer), "OpParam passed is not a Layer"); // Note the layer we are expected to grab in our class variable m_pLayer = pLayer; // Set up the visibility of the other layers using this layer // as the new temporary and acting active layer FrameSGallery::FixOtherLayersFromActive(m_pLayer); } } // Are we trying to grab a hidden frame? if (m_pLayer->IsHiddenFrame()) { // yes, tell the user InformError(_R(IDS_FRAMEISHIDDEN)); //ERROR3IF(m_pLayer->IsHiddenFrame(),"OpGrabFrame::DoWithParam Frame is hidden"); // and then fail FailAndExecute(); End(); return; } // If required, allow the op to get a filename from the user. // This also allows them access to the options via the button on the save dialog box. // This is why we must do this first rather than after we have generated the frames. if (!GetFileNameFromUser()) { // We failed to grab the frame FailAndExecute(); End(); return; } // Get our static pointer to the Preview Dialog. PreviewDialog* pPreviewDlg = PreviewDialog::GetPreviewDialog(); // If the preview dialog is already open, find the selected frame layer. if (pPreviewDlg) pPreviewDlg->StopPreviewing(); // Go and do the work to grab the frame KernelBitmap* pBitmap = GrabFrame(); if (pBitmap == NULL) { // We failed to grab the frame. // Try and put back the selection that we recorded at the start PutBackTheSelection(); FailAndExecute(); End(); return; } // If we have grabbed the non-active layer then make sure the active layer // is set up as current Layer *pActiveLayer = m_pSpread->FindActiveLayer(); if (pActiveLayer && m_pLayer != pActiveLayer) FrameSGallery::FixOtherLayersFromActive(pActiveLayer); // Clean up after the grabbing process. if (!EndGrab()) { // We failed to clean up after grabbing the frame. FailAndExecute(); End(); return; } // Add this bitmap and layer pairing to our export list if (!m_ExportParams.AddLayerAndBitmap(m_pLayer, pBitmap)) { FailAndExecute(); End(); return; } // Open the preview dialog, and display the selected frame. if(!PreviewAnimation()) { // We failed to preview the bitmap FailAndExecute(); End(); return; } // Finish the operation End(); return; } /******************************************************************************************** > BOOL OpGrabFrame::StartGrab() Author: Neville_Humphrys (Xara Group Ltd) Created: 29/4/97 Inputs: Returns: True if worked ok, False otherwise Purpose: Tries to set up useful items prior to doing the grab. ********************************************************************************************/ BOOL OpGrabFrame::StartGrab() { // Is there a selected Document? m_pDocument = Document::GetSelected(); if (m_pDocument == NULL) { ERROR3("Called OpGrabFrame with no selected document!"); return FALSE; } // Is there a selected spread? m_pSpread = Document::GetSelectedSpread(); if (m_pSpread == NULL) { ERROR3("Called OpGrabFrame with no selected spread!"); return FALSE; } // Is there a selected view? m_pView = DocView::GetSelected(); if (m_pView == NULL) { ERROR3("Called OpGrabFrame with no selected view!"); return FALSE; } // Check that all visible layers are actually frame layers FrameSGallery::EnsureFrameLayerIntegrity(m_pSpread); // yes, so check if there is an active layer and try to grab it m_pLayer = m_pSpread->FindActiveLayer(); if (m_pLayer == NULL) { ERROR3("Called OpGrabFrame with no active layer!"); return FALSE; } // Find all objects on this spread from the specified layer, // selected or unselected, and get the bounding them. // Range Control parameters are:- // Include selected nodes - we want TRUE. // Include Unselected nodes - we want TRUE. // Cross layers - we want TRUE // Ignore locked layers - we want FALSE so that we include locked layers. // IsRenderable if set then calls NeedsToRender - we want TRUE // Ignore invisible layers - we want FALSE so that we don't include invisible layers. //Range SearchRange(m_pLayer, NULL, RangeControl(TRUE, TRUE, TRUE, FALSE, TRUE, FALSE)); // We need to invalidate the region /* if (!DoInvalidateNodesRegions(SearchRange, TRUE)) { return FALSE; } */ /* if (!DoStartSelOp(FALSE,FALSE)) // Try to record the selection state , don't render the blobs though { return FALSE; }*/ // Remember the selection so that we can put it back at the end of the operation RememberTheSelection(); // Copy all the current animation parameters from the spread into our export // params. m_ExportParams.SetSpreadAnimPropertiesParam(m_pSpread->GetSpreadAnimPropertiesParam()); return TRUE; } /******************************************************************************************** > virtual BOOL OpGrabFrame::RememberTheSelection() Author: Neville_Humphrys (Xara Group Ltd) Created: 19/6/97 Returns: True if worked ok, False otherwise Purpose: Tries to remember the current selection state so that we can put it back at the end of the operation. Don't error if it fails as the loss of the selection is no great hardship when memory is tight! ********************************************************************************************/ BOOL OpGrabFrame::RememberTheSelection() { // Create a SelectionState object m_pSelState = new SelectionState(); if (m_pSelState == NULL) { return FALSE; // Failure } // We have managed to create a SelectionState instance, now lets try and // record the current selections if (!m_pSelState->Record()) // We failed to allocate enough memory to store the selection state { // There was insufficient memory to record the selections delete m_pSelState; // Delete the selection state m_pSelState = NULL; return FALSE; } return TRUE; } /******************************************************************************************** > virtual BOOL OpGrabFrame::PutBackTheSelection() Author: Neville_Humphrys (Xara Group Ltd) Created: 19/6/97 Returns: True if worked ok, False otherwise Purpose: Tries to put back the remembered selection state at the start of the operation. ********************************************************************************************/ BOOL OpGrabFrame::PutBackTheSelection() { if (m_pSelState == NULL) return FALSE; BOOL RestoreSelBlobs = TRUE; //FALSE; BOOL RemoveBlobs = FALSE; //TRUE; // Restores the recorded selected state m_pSelState->Restore(RestoreSelBlobs, RemoveBlobs); delete m_pSelState; m_pSelState = NULL; return TRUE; } /******************************************************************************************** > KernelBitmap* OpGrabFrame::GrabFrame() Author: Neville_Humphrys (Xara Group Ltd) Created: 29/4/97 Inputs: Returns: KernelBitmap if worked ok, NULL otherwise Purpose: Tries to grab the currently selected frame/layer into a bitmap. ********************************************************************************************/ KernelBitmap* OpGrabFrame::GrabFrame() { ERROR2IF(m_pDocument == NULL,FALSE,"GrabFrame bad document pointer"); ERROR2IF(m_pSpread == NULL,FALSE,"GrabFrame bad spread pointer"); ERROR2IF(m_pLayer == NULL,FALSE,"GrabFrame bad layer pointer"); ERROR2IF(m_pView == NULL,FALSE,"GrabFrame bad view pointer"); // Create a special Bitmap filter, that creates a bitmap // and puts it in the tree ERROR3IF(m_pBitmapFilter != NULL,"Already have a pBitmapFilter!"); m_pBitmapFilter = new GrabFrameFilter(); if (m_pBitmapFilter == NULL) { return NULL; } // Get the filter to work out the new rectangle m_pBitmapFilter->SetUpClippingRectangleForExport(m_pSpread, DRAWING); DocRect NewBoundingRect = m_pBitmapFilter->GetClipRect(); // Save away the new bounding rectangle m_pSpread->SetAnimationBoundingRect(NewBoundingRect); m_ExportParams.SetAnimationBoundingRect(NewBoundingRect); // Save away the quality that this was grabbed at Quality NewQuality = m_pView->RenderQuality; m_pSpread->SetAnimationQuality(NewQuality); // Check all the layers to see if they contain a single bitmap which we can use // instead of generating one. // This will mark all valid single bitmaps using the reference in the layer if (!CheckAllForSingleBitmaps(m_pSpread, m_pBitmapFilter)) { delete m_pBitmapFilter; m_pBitmapFilter = NULL; return NULL; } // Check if we are grabbing a changed background layer frame, if it is then // we will then clear the edited bit on this. Once this happens then if the // user grabs all frames then the dependent frames wont be updated. if (m_pLayer->IsEdited() && m_pLayer->IsSolid()) { // Mark all frames above this as edited until we reach the last frame // OR we hit a solid/background layer. Layer * pFrame = m_pLayer->FindNextFrameLayer(); while (pFrame != NULL && !pFrame->IsSolid()) { // Mark that frame as edited pFrame->SetEdited(TRUE); pFrame = pFrame->FindNextFrameLayer(); } } // Check to see if we have a single bitmap on the layer which is stored // in a NodeBitmap at a 1:1 scale and is 8bpp or less and the palette matches // the present options. // If it passes all these tests, then set pBitmapToCreate to be that bitmap. // Otherwise, we will need to go and convert the current frame into a bitmap KernelBitmap* pBitmapToCreate = NULL; //if (!CheckIfSingleBitmap(m_pLayer, &pBitmapToCreate)) // If there is a referenced bitmap then we can use this instead of generating one pBitmapToCreate = m_pLayer->GetReferencedBitmap(); if (pBitmapToCreate == NULL) { // Grab the frame // As this will affect us during grabbing, we should force it into the known // non-interferring state BOOL CurrentVisEdState = Layer::ActiveLayerVisibleAndEditable; Layer::ActiveLayerVisibleAndEditable = FALSE; // The all visible flag will also do this for us. Document* pDoc = m_pSpread->FindParentDocument(); BOOL CurrentAllVisibleState = FALSE; if (pDoc != NULL) { CurrentAllVisibleState = pDoc->IsAllVisible(); pDoc->SetAllVisible(FALSE); } // Go and convert the frame into its bitmap form pBitmapToCreate = GrabTheFrame(); // Put back the active layer's visibilty and selection Layer::ActiveLayerVisibleAndEditable = CurrentVisEdState; // Put back the all visible state if (pDoc != NULL) pDoc->SetAllVisible(CurrentAllVisibleState); } // Note the capture quality that the frame was captured at but only if we worked correctly if (pBitmapToCreate) m_pLayer->SetCaptureQuality(NewQuality); // remove the filter as we have no more use for it delete m_pBitmapFilter; m_pBitmapFilter = NULL; // Clear the edited flag on the layer m_pLayer->SetEdited(FALSE); #ifdef _DEBUG // Tell the frame gallery to update its display of the frame BROADCAST_TO_ALL(LayerMsg(m_pLayer, LayerMsg::REDRAW_LAYER)); #endif // return the bitmap to the caller return pBitmapToCreate; } /******************************************************************************************** > KernelBitmap* OpGrabFrame::GrabTheFrame() Author: Neville_Humphrys (Xara Group Ltd) Created: 11/6/97 Inputs: Returns: KernelBitmap if worked ok, NULL otherwise Purpose: Tries to grab the currently selected frame/layer into a bitmap. Same as GrabFrame but assumes that the filter to do the grab, m_pBitmapFilter, is already present. ********************************************************************************************/ KernelBitmap* OpGrabFrame::GrabTheFrame() { ERROR2IF(m_pDocument == NULL,FALSE,"GrabFrame bad document pointer"); ERROR2IF(m_pLayer == NULL,FALSE,"GrabFrame bad layer pointer"); ERROR2IF(m_pBitmapFilter == NULL,FALSE,"GrabFrame m_pBitmapFilter pointer"); // Tell it about the layer that is being captured // This supplies the name of the bitmap and the export parameters m_pBitmapFilter->SetLayerBeingCaptured(m_pLayer); KernelBitmap* pBitmapToCreate = NULL; if (!m_pBitmapFilter->DoCreateBitmap(this, m_pDocument, &pBitmapToCreate) || pBitmapToCreate == NULL) { return NULL; } // Copy across the delay from the layer (Andy 5/1/01) DWORD delay = m_pLayer->GetFrameDelay(); pBitmapToCreate->SetDelay(delay); // Make the layer remember this bitmap as the one that was generated if (!m_pLayer->SetGeneratedBitmap(pBitmapToCreate)) { ERROR3("Couldn't add bitmap to layer!"); if (pBitmapToCreate) delete pBitmapToCreate; return NULL; } // DO NOT unset the edited flag. This version is used in GrabAllFrames and we need the // edited flags present until we have finished grabbing so that we can work out dependent // layers. // return the bitmap to the caller return pBitmapToCreate; } /******************************************************************************************** > BOOL OpGrabFrame::EndGrab() Author: Neville_Humphrys (Xara Group Ltd) Created: 29/4/97 Inputs: Returns: True if worked ok, False otherwise Purpose: Tries to clean up after doing the grab. ********************************************************************************************/ BOOL OpGrabFrame::EndGrab() { // Try and put back the selection that we recorded at the start PutBackTheSelection(); // Make sure that the new selection is up to date //Range * pSelRange = GetApplication()->FindSelection(); /* if (pSelRange == NULL || !DoInvalidateNodesRegions(*pSelRange, TRUE)) { // We failed to invalidate the region return FALSE; } */ /* // Recover the active layer again and make sure that it is being shown correctly. ERROR2IF(m_pSpread == NULL,FALSE,"bad spread in EndGrab()"); Layer *pLayer = m_pSpread->FindActiveLayer(); ERROR2IF(pLayer == NULL,"No active layer in EndGrab()") if (pLayer) { FrameSGallery::FixOtherLayersFromActive(pLayer); } */ return TRUE; } /******************************************************************************************** > BOOL OpGrabFrame::GetFileNameFromUser() Author: Neville_Humphrys (Xara Group Ltd) Created: 7/7/97 Returns: True if worked ok, False otherwise Purpose: Gives the operation chance to get the filename from the user. In this baseclass version we do nothing as we preview a single frame and so have no need of a filename. ********************************************************************************************/ BOOL OpGrabFrame::GetFileNameFromUser() { // Baseclass version, do nothing return TRUE; } /******************************************************************************************** > BOOL OpGrabFrame::PreviewAnimation() Author: Neville_Humphrys (Xara Group Ltd) Created: 29/4/97 Returns: True if worked ok, False otherwise Purpose: Tries to preview the frames that have been grabbed. Uses the stored animation details in m_ExportParams ********************************************************************************************/ BOOL OpGrabFrame::PreviewAnimation() { // Copy all the current animation parameters from the spread into our export // params. m_ExportParams.SetSpreadAnimPropertiesParam(m_pSpread->GetSpreadAnimPropertiesParam()); // See if there is a currently open preview dialog box PreviewDialog * pPreviewDialog = PreviewDialog::GetPreviewDialog(); // Check that we have a list of bitmaps to preview. If not then complain bitterly. // Hidden frames allow us to get this far. if (m_ExportParams.GetBitmapCount() == 0) { // If the preview dialog is open then force it into an idle state if (pPreviewDialog != NULL) pPreviewDialog->SetDialogToIdleState(); // tell the user about the problems InformError(_R(IDS_NOFRAMESTOPREVIEW)); return FALSE; } // If the preview dialog is currently open, pass it the list of bitmaps. // We must do this on all types of preview e.g. save, as we will have stopped // the animation before previewing and so we need to ensure that the preview // dialog box is restored to a known state. if (pPreviewDialog != NULL) { // Pass the preview dialog box the new list of bitmaps pPreviewDialog->SetBitmapList(&m_ExportParams); PreviewDialog::ToggleViaBitmapGallery (FALSE); //pPreviewDialog->ToggleViaBitmapGallery (FALSE); pPreviewDialog->SetPlayAnimation(TRUE); // Call the dialog box so that it sets up the necessary states pPreviewDialog->ReInitDialog(); } // This does the actually job in hand, e.g. preview, save, preview in browser BOOL ok = SaveOrShowTheAnimation(pPreviewDialog, &m_ExportParams); return ok; } /******************************************************************************************** > BOOL OpGrabFrame::SaveOrShowTheAnimation(PreviewDialog * pPreviewDialog, BitmapExportParam* pExportParam) Author: Neville_Humphrys (Xara Group Ltd) Created: 4/8/97 Inputs: pPreviewDialog the preview dialog box, if open pExportParam the export param which we will use Returns: True if worked ok, False otherwise Purpose: Tries to actually do the preview operation required. In this case we just start up the preview dialog box, if not already open, to show the frames that have been grabbed. Uses the stored animation details in m_ExportParams ********************************************************************************************/ BOOL OpGrabFrame::SaveOrShowTheAnimation(PreviewDialog * pPreviewDialog, BitmapExportParam* pExportParam) { // Only boot up the preview dialog box if it is not already on display // If it is already on display then we will have already dealt with it if (pPreviewDialog == NULL) { // Invoke the preview operation OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_PREVIEWDIALOG); if (pOpDesc) { PreviewDialog::ToggleViaBitmapGallery (FALSE); pOpDesc->Invoke(&m_ExportParams); pPreviewDialog = PreviewDialog::GetPreviewDialog(); //pPreviewDialog->ToggleViaBitmapGallery (FALSE); } } return TRUE; } /**************************************************************************************************** > BOOL OpGrabFrame::SetSingleBitmapInList() Author: Ranbir_Rana (Xara Group Ltd) Created: 14/05/97 Inputs: - Returns: True if worked ok, False otherwise. Purpose: If the Preview Dialog is open and we regenerate a single frame, this function allows us to update our Bitmap list in the Preview Dialog. ******************************************************************************************************/ /* BOOL OpGrabFrame::SetSingleBitmapInList() { // Copy all the current animation parameters from the spread into our export params. m_ExportParams.SetSpreadAnimPropertiesParam(m_pSpread->GetSpreadAnimPropertiesParam()); // Get our static pointer to the Preview Dialog. PreviewDialog* pPreviewDialog = PreviewDialog::GetPreviewDialog(); if (!pPreviewDialog) return FALSE; pPreviewDialog->SetRegeneratedBitmapInList(&m_ExportParams); return TRUE; } */ /****************************************************************************************************** > BOOL OpGrabFrame::SetBitmapToListTail() Author: Ranbir_Rana (Xara Group Ltd) Created: 14/05/97 Inputs: - Returns: True if worked ok, False otherwise. Purpose: If the Preview Dialog is open and we regenerate a single frame, this function allows us to add that Bitmap to the head of the preview dialog bitmap list. ********************************************************************************************************/ /* BOOL OpGrabFrame::SetBitmapToListTail() { // Copy all the current animation parameters from the spread into our export params. m_ExportParams.SetSpreadAnimPropertiesParam(m_pSpread->GetSpreadAnimPropertiesParam()); // Get our static pointer to the Preview Dialog. PreviewDialog* pPreviewDialog = PreviewDialog::GetPreviewDialog(); if (!pPreviewDialog) return FALSE; // Add this bitmap to the list tail. pPreviewDialog->SetBitmapToListTail(&m_ExportParams); return TRUE; } */ /**************************************************************************************************** > BOOL OpGrabFrame::SetFullBitmapList() Author: Ranbir_Rana (Xara Group Ltd) Created: 14/05/97 Inputs: SetFlagState: If this is specified, it allows us to set the state of certain flags in the Preview dialog. Returns: True if worked ok, False otherwise. Purpose: If the Preview Dialog is open and we regenerate the frames in the animation, this function allows us to update our Bitmap list in the Preview Dialog. ******************************************************************************************************/ /* BOOL OpGrabFrame::SetFullBitmapList(BOOL SetFlagState) { // Copy all the current animation parameters from the spread into our export params. m_ExportParams.SetSpreadAnimPropertiesParam(m_pSpread->GetSpreadAnimPropertiesParam()); // Get our static pointer to the Preview Dialog. PreviewDialog* pPreviewDialog = PreviewDialog::GetPreviewDialog(); if (!pPreviewDialog) return FALSE; // If the animation is playing, stop the animation before we pass it our new list of bitmaps. if(pPreviewDialog->GetPlayAnimation()) pPreviewDialog->SetPlayAnimation(FALSE); pPreviewDialog->SetBitmapList(&m_ExportParams); // Set the state of the preview dlg flags. if(SetFlagState) { // Call the dialog box so that it sets up the necessary states pPreviewDialog->ReInitDialog(); } // Play the animation. pPreviewDialog->SetPlayAnimation(TRUE); return TRUE; } */ /******************************************************************************************** > BOOL OpGrabFrame::CheckIfSingleBitmap(Layer * pLayer, KernelBitmap ** ppBitmap) Author: Neville_Humphrys (Xara Group Ltd) Created: 16/6/97 Inputs: pLayer - the layer we need to check Outputs: The bitmap to use for this frame Returns: True if found a single bitmap on the frame/layer. False otherwise. Purpose: For finding out if there is a single bitmap on the layer which is stored in a NodeBitmap at a 1:1 scale and is 8bpp or less and the palette matches the present options. This palette testing is now done after this If it passes all these tests, then set pBitmap to be that bitmap and return True. Also note in the layer that this bitmap can possibly be used to specify this layer. We can only say for sure when we have checked that its palette matches the current animation options. SeeAlso: CheckAllForSingleBitmaps; ********************************************************************************************/ BOOL OpGrabFrame::CheckIfSingleBitmap(Layer * pLayer, KernelBitmap ** ppBitmap) { ERROR2IF(pLayer == NULL, FALSE,"CheckIfSingleBitmap bad layer pointer"); ERROR2IF(ppBitmap == NULL, FALSE,"CheckIfSingleBitmap bad bitmap pointer"); // Get some of the current export options DocRect BoundingRect = m_ExportParams.GetAnimationBoundingRect(); ERROR3IF(BoundingRect.IsEmpty(),"Bounding rect not set up"); // PALETTE_COLOURS Palette = m_ExportParams.GetPaletteCols(); // WEB_PALETTE WebPalette = m_ExportParams.GetPalette(); KernelBitmap * pBitmap = NULL; BOOL Scaled1to1 = FALSE; BOOL PaletteOk = FALSE; BOOL InsideBoundingRect = TRUE; BOOL FullFirstFrame = TRUE; UINT32 Bpp = 0; INT32 NodeCount = 0; NodeBitmap *pNodeBmp = NULL; // check if we are the first animation frame, if so then we the bitmap must be the same // size as the animation bounding rect. Otherwise, the first frame will not be the size // of the animation which highlights a bug in MS IE 3.0 Layer * pPreviousFrame = pLayer->FindPrevFrameLayer(); Node * pNode = pLayer->FindFirstChild(); while (pNode != NULL) { // If the node renders something on the screen then we count it as this will mean that // the single bitmap does not fully define the layer. // It ignores attributes, hidden nodes, etc - nodes that don't render anything themselves. if (pNode->IsBounded()) NodeCount++; // We need to note any NodeBitmap nodes if (pNode->IS_KIND_OF(NodeBitmap) && NodeCount == 1) { // Convert the node to a nodebitmap so we can get at the useful NodeBitmap // related data pNodeBmp = (NodeBitmap *)pNode; // Get the size and position of the node bitmap DocRect rect = pNodeBmp->GetBoundingRect(TRUE, FALSE); // If we have no previous frame then check that the first frame is the // size of the animation if (pPreviousFrame == NULL) { DocRect AniBoundingRect = m_ExportParams.GetAnimationBoundingRect(); ERROR3IF(AniBoundingRect.IsEmpty(),"CheckIfSingleBitmap Animation bounding rect not set up!"); // REMEMBER account for rounding errors const INT32 delta = 50; if ( (AniBoundingRect.lo.x >= (rect.lo.x - delta)) && (AniBoundingRect.lo.x <= (rect.lo.x + delta)) && (AniBoundingRect.hi.x >= (rect.hi.x - delta)) && (AniBoundingRect.hi.x <= (rect.hi.x + delta)) && (AniBoundingRect.lo.y >= (rect.lo.y - delta)) && (AniBoundingRect.lo.y <= (rect.lo.y + delta)) && (AniBoundingRect.hi.y >= (rect.hi.y - delta)) && (AniBoundingRect.hi.y <= (rect.hi.y + delta)) ) { FullFirstFrame = TRUE; } else { FullFirstFrame = FALSE; } } // Get the bitmap stored inside the node, if any pBitmap = pNodeBmp->GetBitmap(); if (pBitmap) { // Get the width/height of the bitmap in millipoints INT32 BmpWidth = pBitmap->GetRecommendedWidth(); INT32 BmpHeight = pBitmap->GetRecommendedHeight(); // Get the Width of the Bitmap in Millipoints INT32 Width = INT32(pNodeBmp->Parallel[0].Distance(pNodeBmp->Parallel[1])); INT32 Height = INT32(pNodeBmp->Parallel[1].Distance(pNodeBmp->Parallel[2])); // REMEMBER account for rounding errors and the orientation being the other // way round const INT32 delta = 2; if ((Width >= BmpWidth - delta && Width <= BmpWidth + delta && Height >= BmpHeight - delta && Height <= BmpHeight + delta) || (Height >= BmpWidth - delta && Height <= BmpWidth + delta && Width >= BmpHeight - delta && Width <= BmpHeight + delta) ) Scaled1to1 = TRUE; Bpp = pBitmap->GetBPP(); // If the bitmap is 8bpp of less then assume this is ok for now // We will check the palette in a second pass if (Bpp <= 8) { PaletteOk = TRUE; } /* // We cannot cope with GLOBAL OPTIMISED palettes at present as we // would need to wait until the palette was generated before we could // check. if (Palette == PALCOL_OPTIMIZED && WebPalette == PAL_LOCAL) { // Saving local palette so any palette ok PaletteOk = TRUE; } else if (Palette == PALCOL_BROWSER && WebPalette == PAL_GLOBAL) { // Check if we have a browser palette on this bitmap //PaletteOk = pBitmap->IsBrowserPalette(); // Old way of testing. Too lenient as all it does it check that the palette // has the correct colours in it, not that the palette will be the same one // that we are going to output as the browser palette // Obviously, browser palettes can only happen on 8bpp bitmaps if (Bpp == 8) { // First of all, if we haven't already got our palette that we check against // then construct it. if (m_pBrowserPalette == NULL) { UINT32 PaletteSize = UINT32(pow(2,Bpp)); m_pBrowserPalette = DIBUtil::AllocateLogPalette(PaletteSize); if (m_pBrowserPalette != NULL) { // Now force it into a browser compatible state BOOL AvoidSystemColours = TRUE; PaletteManager::MakePaletteBrowserCompatible(m_pBrowserPalette, AvoidSystemColours); } } INT32 TransColour = -1; pBitmap->GetTransparencyIndex(&TransColour); if (m_pBrowserPalette != NULL) { PaletteOk = pBitmap->ArePalettesTheSame(m_pBrowserPalette, TransColour); } else { ERROR3("Couldn't allocate browser palette"); PaletteOk = FALSE; } } else PaletteOk = FALSE; } } */ if (Scaled1to1 && PaletteOk && !rect.IsEmpty() && !BoundingRect.IsEmpty()) { // Work out the position of the bitmap relative to the top left hand // corner of the bounding rectangle in terms of pixels and put this // in the bitmap MILLIPOINT LeftOffsetMP = rect.lo.x - BoundingRect.lo.x; MILLIPOINT TopOffsetMP = BoundingRect.hi.y - rect.hi.y; if (LeftOffsetMP >= 0 && TopOffsetMP >= 0) { const UINT32 dpi = 96; UINT32 LeftOffset = LeftOffsetMP * dpi/72000; UINT32 TopOffset = TopOffsetMP * dpi/72000; pBitmap->SetLeftOffset(LeftOffset); pBitmap->SetTopOffset(TopOffset); InsideBoundingRect = TRUE; } } } } pNode = pNode->FindNext(); } // If all these checks are TRUE then return the bitmap as the source of the frame if (pBitmap != NULL && Scaled1to1 && Bpp <= 8 && NodeCount == 1 && PaletteOk && InsideBoundingRect && FullFirstFrame) { if (ppBitmap) *ppBitmap = pBitmap; // Make the layer remember this bitmap // Remember this bitmap as the reference one pLayer->SetReferencedBitmap(pBitmap); //TRACEUSER( "Neville", _T("Using single bitmap\n")); return TRUE; } // Ensure that we have no reference saved pLayer->SetReferencedBitmap(NULL); return FALSE; } /******************************************************************************************** > BOOL OpGrabFrame::CheckAllForSingleBitmaps(Spread * pSpread) Author: Neville_Humphrys (Xara Group Ltd) Created: 9/7/97 Inputs: pLayer - the layer we need to check pBitmapFilter - a grab frame filter we can use Returns: True if worked correctly, False otherwise. Purpose: For going through all the frames and seeing if there is a single bitmap on the frame/layer which is stored in a NodeBitmap at a 1:1 scale and is 8bpp or less and the palette matches the present options. We use the grab frame filter as this is derived off GIF filter and this must already cope with this when loading animations so that it can set the animation options accordingly. ********************************************************************************************/ BOOL OpGrabFrame::CheckAllForSingleBitmaps(Spread * pSpread, GrabFrameFilter * pBitmapFilter) { ERROR2IF(pSpread == NULL, FALSE,"CheckIfSingleBitmap bad Spread pointer"); ERROR2IF(pBitmapFilter == NULL, FALSE,"CheckIfSingleBitmap bad GrabFrameFilter pointer"); // So we can do the optimised palette case, we must go though all the // layers/frames and see if there is a single bitmap present. We don't worry // about the palette on this first pass. We just set up the referenced bitmap // to be the single bitmap if it passes all the tests. KernelBitmap * pBitmap = NULL; BOOL Found = FALSE; BOOL SolidSet = FALSE; BOOL OverlaySet = FALSE; BOOL OverlayedBitmapSet = FALSE; Layer* pCurrentLayer = pSpread->FindFirstFrameLayer(); Layer* pNextLayer = NULL; Layer* pPrevFrameLayer = NULL; while (pCurrentLayer != NULL) { // Move to the next bitmap in the animation pNextLayer = pCurrentLayer->FindNextFrameLayer(); // This is just as a double check if (pCurrentLayer->IsPseudoFrame()) { Found = CheckIfSingleBitmap(pCurrentLayer, &pBitmap); // If the solid flag is set on anything but the last layer then note this // as dangerous if (pCurrentLayer->IsSolid() && pNextLayer != NULL) SolidSet = TRUE; if (pCurrentLayer->IsOverlay()) { // If overlay is set then we can allow it if the previous bitmap has a restore // type of overlay as this may be an animation that we have saved out // and then loaded in. If a diff has happened then overlay will be set. // We can only ever allow this if the layers consist of all bitmaps as // otherwise the layer may be overlaying a vector layer and hence be wrong. KernelBitmap * pPrevBitmap = NULL; if (pPrevFrameLayer) pPrevBitmap = pPrevFrameLayer->GetReferencedBitmap(); // Check that we have a single reuseable bitmap on this layer plus one of the previous if (pPrevBitmap != NULL && pBitmap != NULL) { GIFDisposalMethod restore = pPrevBitmap->GetAnimationRestoreType(); // Do we include GDM_NONE? Not for now. if (restore != GDM_LEAVE) { // We cannot use the bitmap so set the reference to NULL pCurrentLayer->SetReferencedBitmap(NULL); OverlaySet = TRUE; } else OverlayedBitmapSet = TRUE; } else if (pPrevFrameLayer != NULL) { // If overlay set on the first frame then ignore // We cannot use the bitmap so set the reference to NULL pCurrentLayer->SetReferencedBitmap(NULL); OverlaySet = TRUE; } } } // Move to the next bitmap in the animation pPrevFrameLayer = pCurrentLayer; pCurrentLayer = pNextLayer; } // Find out about the palettes that the bitmaps have // Our filter has a useful function for this UINT32 ReqNumberOfColours = m_ExportParams.GetNumColsInPalette(); BOOL SamePalettes = FALSE; BOOL OurBrowserPalette = FALSE; BOOL AllHaveBitmaps = FALSE; BOOL AllWithinCount = FALSE; UINT32 NumberOfColours = ReqNumberOfColours; pBitmapFilter->CheckSingleBitmapsOnSpread(pSpread, &SamePalettes, &OurBrowserPalette, &AllHaveBitmaps, &AllWithinCount, &NumberOfColours); PALETTE_COLOURS Palette = m_ExportParams.GetPaletteCols(); WEB_PALETTE WebPalette = m_ExportParams.GetPalette(); BOOL OptionsOk = FALSE; // If OverlaySet is true then we have found an overlay situation which we cannot cope with and // so will have set the referenced bitmap to null. if (OverlaySet && AllHaveBitmaps) AllHaveBitmaps = FALSE; // If solid is set on any of the frames then it is too dangerous to reuse any single bitmaps // We can only allow overlay, if all layers are single bitmaps and the bitmap concerned is // of type GDM_LEAVE. Otherwise, it is too dangerous. BOOL BitmapOverlayOk = TRUE; if (OverlayedBitmapSet && !AllHaveBitmaps) BitmapOverlayOk = FALSE; if (!SolidSet && BitmapOverlayOk) { // Check from the most fussy option to the least fussy option if (Palette == PALCOL_BROWSER && WebPalette == PAL_GLOBAL && OurBrowserPalette) { OptionsOk = TRUE; //TRACEUSER( "Neville", _T("Global browser, palettes ok\n")); } else if (Palette == PALCOL_OPTIMIZED && WebPalette == PAL_GLOBAL && SamePalettes && AllHaveBitmaps && NumberOfColours <= ReqNumberOfColours) { OptionsOk = TRUE; //TRACEUSER( "Neville", _T("Global opt, palettes ok\n")); // Force the global optimised palette to be null for now pBitmapFilter->SetGlobalOptimisedPalette(NULL); } else if (Palette == PALCOL_OPTIMIZED && WebPalette == PAL_LOCAL && AllWithinCount) { // Saving local palette so any palette ok but must be within the count OptionsOk = TRUE; //TRACEUSER( "Neville", _T("Local Opt, palettes ok\n")); } } // Now we need to go through the layers again and ratify our check pCurrentLayer = pSpread->FindFirstFrameLayer(); pBitmap = NULL; while (pCurrentLayer != NULL) { // This is just as a double check if (pCurrentLayer->IsPseudoFrame()) { pBitmap = pCurrentLayer->GetReferencedBitmap(); if (OptionsOk && pBitmap) { // We can use the bitmap instead of generating one // So make sure that the generated bitmap is clean out pCurrentLayer->SetGeneratedBitmap(NULL); // And ensure that the bitmap has the layer's delay pBitmap->SetDelay(pCurrentLayer->GetFrameDelay()); // If we are in if (Palette == PALCOL_OPTIMIZED && WebPalette == PAL_GLOBAL) { // If we haven't set up the global optimised palette then do so now // Pull it from the first bitmap that we find LPLOGPALETTE pOptPal = pBitmapFilter->GetGlobalOptimisedPalette(); if (pOptPal == NULL) { pOptPal = DIBUtil::CopyBitmapPaletteIntoLogPalette(pBitmap); // Something went a bit wrong if (pOptPal == NULL) return FALSE; pBitmapFilter->SetGlobalOptimisedPalette(pOptPal); } } } else { // We cannot use the bitmap so set the reference to NULL pCurrentLayer->SetReferencedBitmap(NULL); } } // Move to the next bitmap in the animation pCurrentLayer = pCurrentLayer->FindNextFrameLayer(); } return TRUE; } /******************************************************************************************** // End of OpGrabFrame ********************************************************************************************/ //------------------------------------------------------------------------------------------ // Methods for the OpGrabAllFrames //------------------------------------------------------------------------------------------ // Macro to determine the bytes in a DWORD aligned DIB scanline #define BYTESPERLINE(Width, BPP) ((WORD)((((DWORD)(Width) * (DWORD)(BPP) + 31) >> 5)) << 2) void OpGrabAllFrames::CreateGlobalPalette(DWORD NumColsInPalette, BOOL RegenerateAllFrames) { ERROR3IF(!m_pBitmapFilter, "No bitmap filter to use when generating global palette"); if (!m_pBitmapFilter) return; PaletteOptimiser* pPalOpt = new PaletteOptimiser(); if (!pPalOpt) return; pPalOpt->Initialise(); // Go through all the frame layers in the spread and export them KernelBitmap * pBitmap = NULL; Layer* pCurrentLayer = NULL; // Set the filter to generate preview bitmaps m_pBitmapFilter->SetGrabMode(GrabFrameFilter::GRABMODE_PREVIEW); pBitmap = NULL; pCurrentLayer = m_pSpread->FindFirstFrameLayer(); while (pCurrentLayer != NULL) { // see if the user has hidden the frame if (!pCurrentLayer->IsPseudoFrame() || pCurrentLayer->IsHiddenFrame()) { // It is either an invalid frame or it is hidden. In both cases but especially // the second we should ensure that if there is a generated bitmap then we // vape it as it is now out of date. pCurrentLayer->SetGeneratedBitmap(NULL); // Move to the next bitmap in the animation pCurrentLayer = pCurrentLayer->FindNextFrameLayer(); // Go to the next frame continue; } // Set up the visibility of the other layers using this layer // as the new temporary and acting active layer FrameSGallery::FixOtherLayersFromActive(pCurrentLayer); // This is the layer that we are adding to the global palette m_pLayer = pCurrentLayer; // Render a bitmap of the entire image being exported KernelBitmap* pTestBitmap=NULL; m_pBitmapFilter->DoCreateBitmap(this, m_pDocument, &pTestBitmap); // not enough memory? or no content worth talking about then give up! if (!pTestBitmap || !pTestBitmap->GetActualBitmap()) { FailAndExecute(); End(); return; } // We need to pass Gavin a 32bbp bitmap with an empty channel (rather than an // alpha channel). Lets quickly create one (I am sure this is not the best way // of doing this but it will do for now). UINT32 nPixels = pTestBitmap->GetActualBitmap()->GetBitmapSize() / 3; RGBQUAD* pNewBitmap = new RGBQUAD[nPixels]; UINT32 width = pTestBitmap->GetActualBitmap()->GetBitmapInfoHeader()->biWidth; UINT32 height = pTestBitmap->GetActualBitmap()->GetBitmapInfoHeader()->biHeight; BYTE* pOldBitmapBytes = (BYTE*)pTestBitmap->GetActualBitmap()->GetBitmapBits(); UINT32 bytesPerLine = BYTESPERLINE(width, 24); for (UINT32 y = 0; y < height; ++y) for (UINT32 x = 0; x < width; x++) { pNewBitmap[y * width + x].rgbBlue = pOldBitmapBytes[bytesPerLine * y + x * 3 + 0]; pNewBitmap[y * width + x].rgbGreen = pOldBitmapBytes[bytesPerLine * y + x * 3 + 1]; pNewBitmap[y * width + x].rgbRed = pOldBitmapBytes[bytesPerLine * y + x * 3 + 2]; pNewBitmap[y * width + x].rgbReserved = 0; } // add the stats to the palette optimiser pPalOpt->AddStats(pNewBitmap, nPixels); delete pNewBitmap; delete pTestBitmap; // Move to the next bitmap in the animation pCurrentLayer = pCurrentLayer->FindNextFrameLayer(); } // set the global palette pPalOpt->SnapToBrowserPalette(0); pPalOpt->SnapToPrimaries(1); pPalOpt->AddSystemColours((m_pSpread->GetSpreadAnimPropertiesParam().GetUseSystemCols() == TRUE)); pPalOpt->UseBrowserPalette(0); pPalOpt->SetFast(TRUE); INT32 ColoursToOptimise = camMax(2, NumColsInPalette-1); // tell the optimiser that we have finished gathering the stats pPalOpt->GenPalette(ColoursToOptimise); LOGPALETTE * pGlobalPal = DIBUtil::AllocateLogPalette(ColoursToOptimise + 1); pGlobalPal->palNumEntries = ColoursToOptimise; // get the optimised palette from the optimser pPalOpt->GetPalette( pGlobalPal, ColoursToOptimise); // we want to add a transparent colour to this palette pGlobalPal->palNumEntries = camMin(255,pGlobalPal->palNumEntries+1); // the first entry in the palette is special it should be the background colour as it will // be what is visible if the background is not transparent so swap the first entry into // the last and set the last pGlobalPal->palPalEntry[ pGlobalPal->palNumEntries-1 ].peRed = pGlobalPal->palPalEntry[ 0 ].peRed; pGlobalPal->palPalEntry[ pGlobalPal->palNumEntries-1 ].peGreen = pGlobalPal->palPalEntry[ 0 ].peGreen; pGlobalPal->palPalEntry[ pGlobalPal->palNumEntries-1 ].peBlue = pGlobalPal->palPalEntry[ 0 ].peBlue; pGlobalPal->palPalEntry[ pGlobalPal->palNumEntries-1 ].peFlags = 0; DocColour dcol = Page::GetPageColour(); INT32 r = 255, g = 255, b = 255; dcol.GetRGBValue(&r,&g,&b); pGlobalPal->palPalEntry[ 0 ].peRed = (BYTE)r; pGlobalPal->palPalEntry[ 0 ].peGreen = (BYTE)g; pGlobalPal->palPalEntry[ 0 ].peBlue = (BYTE)b; pGlobalPal->palPalEntry[ 0 ].peFlags = 255; // the transp entry - not renderable // remove the optimiser delete pPalOpt; // save this global palette for later m_pBitmapFilter->SetGlobalOptimisedPalette(pGlobalPal); m_pBitmapFilter->AlterPaletteContents(pGlobalPal); // Undo our change to the filter m_pBitmapFilter->SetGrabMode(GrabFrameFilter::GRABMODE_FOROUTPUT); } /******************************************************************************************** > void OpGrabAllFrames::Do(OpDescriptor * pOpDesc) Author: Neville_Humphrys (Xara Group Ltd) Created: 22/4/97 Inputs: OpDescriptor (unused) Outputs: - Returns: - Purpose: Tries to grab the selected animation frame (i.e. layer). Errors: - SeeAlso: - ********************************************************************************************/ void OpGrabAllFrames::Do( OpDescriptor * pOpDesc ) { // Get useful data and set up items before starting the grab process if (!StartGrab()) { // We failed to grab the frame FailAndExecute(); End(); return; } // If required, allow the op to get a filename from the user. // This also allows them access to the options via the button on the save dialog box. // This is why we must do this first rather than after we have generated the frames. if (!GetFileNameFromUser()) { // We failed to grab the frame FailAndExecute(); End(); return; } // Get our static pointer to the Preview Dialog. PreviewDialog* pPreviewDlg = PreviewDialog::GetPreviewDialog(); // If the preview dialog is already open, find the selected frame layer. BOOL PlayAnimation = TRUE; if (pPreviewDlg) { // Note the current state of the playing PlayAnimation = pPreviewDlg->GetPlayAnimation(); // Force the dialog into stop mode pPreviewDlg->StopPreviewing(); } // Create a special Bitmap filter, that creates a bitmap // and puts it in the tree ERROR3IF(m_pBitmapFilter != NULL,"Already have a pBitmapFilter!"); m_pBitmapFilter = new GrabFrameFilter(); if (m_pBitmapFilter == NULL) { // We failed to grab the frame // Try and put back the selection that we recorded at the start PutBackTheSelection(); FailAndExecute(); End(); return; } // Get the stored cliprect from the spread. // This may be blank if the frames have not been generated before. DocRect OldBoundingRect = m_pSpread->GetAnimationBoundingRect(); // Get the filter to work out the new rectangle m_pBitmapFilter->SetUpClippingRectangleForExport(m_pSpread, DRAWING); DocRect NewBoundingRect = m_pBitmapFilter->GetClipRect(); // Save away the new bounding rectangle m_pSpread->SetAnimationBoundingRect(NewBoundingRect); m_ExportParams.SetAnimationBoundingRect(NewBoundingRect); // If they are different then we must regenerate all frames BOOL RegenerateAllFrames = ms_ForceRefreshOfAllFrames; // used to be = FALSE (sjk) ms_ForceRefreshOfAllFrames = FALSE; // have used the force refresh if (NewBoundingRect != OldBoundingRect) RegenerateAllFrames = TRUE; Quality OldQuality = m_pSpread->GetAnimationQuality(); // AMB doesn't understand what the following lines were meant to do. Quality // is a linear scale. And in any case this doesn't compile (unsurprisingly) // Quality NewQuality = m_pView->RenderQuality; // NewQuality.Antialias = Quality::FullAntialias; // NewQuality.Transparency = Quality::FullTransparency; Quality NewQuality(Quality::QualityMax); // Save away the new quality m_pSpread->SetAnimationQuality(NewQuality); if (NewQuality != OldQuality) RegenerateAllFrames = TRUE; // Check if somebody has edited the page background layer. If they have then // regenerate all frames Layer * pPageBackground = m_pSpread->FindFirstPageBackgroundLayer(); if (pPageBackground) { if (pPageBackground->IsEdited()) RegenerateAllFrames = TRUE; } // If the user has a global optimised palette and they have edited one layer // then we have really no choice but to always regenerate all frames // as the user may have changed something that will affect the colours in the palette. //DITHER Dither; WEB_PALETTE WebPalette = PAL_GLOBAL; PALETTE_COLOURS ColoursPalette = PALCOL_BROWSER; DWORD NumColsInPalette; m_pSpread->GetAnimationColours(NULL, &WebPalette, &ColoursPalette, &NumColsInPalette, NULL); if (WebPalette == PAL_GLOBAL && ColoursPalette == PALCOL_OPTIMIZED) { // check to see if one of the frame layers has been edited Layer * pTestLayer = m_pSpread->FindFirstFrameLayer(); while (pTestLayer) { if (pTestLayer->IsEdited() && pTestLayer->IsPseudoFrame()) { // Somebody has edited one of the frames so we must regenerate all RegenerateAllFrames = TRUE; break; } pTestLayer = pTestLayer->FindNextFrameLayer(); } } // Check all the layers to see if they contain a single bitmap which we can use // instead of generating one. // This will mark all valid single bitmaps using the reference in the layer if (!CheckAllForSingleBitmaps(m_pSpread, m_pBitmapFilter)) { // Try and put back the selection that we recorded at the start PutBackTheSelection(); delete m_pBitmapFilter; m_pBitmapFilter = NULL; // We failed to clean up after grabbing the frame FailAndExecute(); End(); return; } // As this will affect us during grabbing, we should force it into the known // non-interferring state BOOL CurrentVisEdState = Layer::ActiveLayerVisibleAndEditable; Layer::ActiveLayerVisibleAndEditable = FALSE; // The all visible flag will also do this for us. Document* pDoc = m_pSpread->FindParentDocument(); BOOL CurrentAllVisibleState = FALSE; if (pDoc != NULL) { CurrentAllVisibleState = pDoc->IsAllVisible(); pDoc->SetAllVisible(FALSE); } // SMFIX Do we need a global palette for all the frames? BOOL CreatingGlobalPalette = (WebPalette == PAL_GLOBAL && ColoursPalette == PALCOL_OPTIMIZED); // if we are having a global palette then get an optimiser to create one from the bitmaps if (CreatingGlobalPalette) CreateGlobalPalette(NumColsInPalette, RegenerateAllFrames); // Go through all the frame layers in the spread and export them KernelBitmap * pBitmap = NULL; Layer* pCurrentLayer = NULL; // Set the filter to generate output bitmaps m_pBitmapFilter->SetGrabMode(GrabFrameFilter::GRABMODE_FOROUTPUT); // go round once unless we are creating a global palette then go round twice pBitmap = NULL; pCurrentLayer = m_pSpread->FindFirstFrameLayer(); while (pCurrentLayer != NULL) { // see if the user has hidden the frame if (!pCurrentLayer->IsPseudoFrame() || pCurrentLayer->IsHiddenFrame()) { // It is either an invalid frame or it is hidden. In both cases but especially // the second we should ensure that if there is a generated bitmap then we // vape it as it is now out of date. pCurrentLayer->SetGeneratedBitmap(NULL); // Move to the next bitmap in the animation pCurrentLayer = pCurrentLayer->FindNextFrameLayer(); // Go to the next frame continue; } // Set up the visibility of the other layers using this layer // as the new temporary and acting active layer FrameSGallery::FixOtherLayersFromActive(pCurrentLayer); // This is where the real work starts! // This is the layer that we want grabbing m_pLayer = pCurrentLayer; // Check to see if we have a single bitmap on the layer which is stored // in a NodeBitmap at a 1:1 scale and is 8bpp or less and the palette matches // the present options. // If it passes all these tests, then set pBitmap to be that bitmap. //if (!CheckIfSingleBitmap(pCurrentLayer, &pBitmap)) // If there is a referenced bitmap then we can use this instead of generating one pBitmap = m_pLayer->GetReferencedBitmap(); if (pBitmap == NULL) { // Look to see if we have a bitmap for this layer KernelBitmap * pOldBitmap = pCurrentLayer->GetGeneratedBitmap(); // Look to see if any visible foreground layers below this one have // been edited BOOL LayersBelowEdited = FALSE; // Only check if we are not already forced to regnerate all frames if (!RegenerateAllFrames) { Layer * pTestLayer = pCurrentLayer; pTestLayer = pTestLayer->FindPrevFrameLayer(); while (pTestLayer) { // Dont disclude hidden frames as they can affect the make up of the current frame if (pTestLayer->IsEdited() && pTestLayer->IsPseudoFrame() && pTestLayer->IsVisible()) { LayersBelowEdited = TRUE; break; } pTestLayer = pTestLayer->FindPrevFrameLayer(); } } // we are getting the bitmaps themselves // check that the quality it was last captured at was the same as the current quality Quality CurrentFrameQuality = pCurrentLayer->GetCaptureQuality(); // For a number of reasons we may need to regenerate the bitmap for this frame // If nay are true then regenerate, otherwise reuse the old one if (pOldBitmap == NULL || LayersBelowEdited || RegenerateAllFrames || pCurrentLayer->IsEdited() || CurrentFrameQuality != NewQuality) { // Turn this frame into a bitmap pBitmap = GrabTheFrame(); } else { // Reuse the old bitmap that was generated pBitmap = pOldBitmap; // test to see that this bitmap uses the correct palette if required // otherwise we will have to grab it anyway if (CreatingGlobalPalette) { // compare palettes LOGPALETTE * pGlobalPalette = m_pBitmapFilter->GetGlobalOptimisedPalette(); if (!pBitmap->GetActualBitmap()->ArePalettesTheSame(pGlobalPalette, 0)) { // NOTE: This happens when the preview window has just gone and generated a bitmap // using a locally optimal palette rather than our globally optimal palette and in // the process it has replaced our cache version with its dodgy bitmap. TRACEALL( _T("Bum bitmap passed to us with wrong palette, grab a fresh one")); pBitmap = GrabTheFrame(); } } } } BOOL bAddLayer = pBitmap != 0; if (bAddLayer) { // We have a bitmap so add this layer pairing to our export list bAddLayer = m_ExportParams.AddLayerAndBitmap(pCurrentLayer, pBitmap); } if (!bAddLayer) { // We failed to grab the frame or failed to add it to our export list // Put back the active layer's visibilty and selection Layer::ActiveLayerVisibleAndEditable = CurrentVisEdState; FrameSGallery::FixOtherLayersFromActive(m_pLayer); // Try and put back the selection that we recorded at the start PutBackTheSelection(); FailAndExecute(); End(); return; } //TRACEUSER( "SimonK", _T("colours in frame %d\n"), pBitmap->GetNumPaletteEntries()); // Note the capture quality that the frame was captured at but only if we worked correctly pCurrentLayer->SetCaptureQuality(NewQuality); // Move to the next bitmap in the animation pCurrentLayer = pCurrentLayer->FindNextFrameLayer(); } // Put back the active layer's visibilty and selection Layer::ActiveLayerVisibleAndEditable = CurrentVisEdState; // Put back the all visible state if (pDoc != NULL) pDoc->SetAllVisible(CurrentAllVisibleState); Layer *pActiveLayer = m_pSpread->FindActiveLayer(); if (pActiveLayer) FrameSGallery::FixOtherLayersFromActive(pActiveLayer); // Go and mark all layers as not edited now that we have finished the grabbing // process Layer* pLayer = m_pSpread->FindFirstFrameLayer(); while (pLayer != NULL) { // This is just as a double check if (pLayer->IsPseudoFrame()) { // Clear the edited flag on the layer pLayer->SetEdited(FALSE); #ifdef _DEBUG // Tell the frame gallery to update its display of the frame BROADCAST_TO_ALL(LayerMsg(pLayer, LayerMsg::REDRAW_LAYER)); #endif } // Move to the next frame layer in the animation pLayer = pLayer->FindNextFrameLayer(); } // If we found a page background layer above, now mark it as not edited if (pPageBackground) pPageBackground->SetEdited(FALSE); // Clean up after the grabbing process if (!EndGrab()) { // We failed to clean up after grabbing the frame delete m_pBitmapFilter; m_pBitmapFilter = NULL; FailAndExecute(); End(); return; } // Grab all frames should usually play the animation. // If the preview dialog is open and in stop mode then it should continue in stop mode. // In this case we should have noted this before calling stop at the start of this function // So up the play state we noted earlier before we preview PreviewDialog * pPreviewDialog = PreviewDialog::GetPreviewDialog(); INT32 CurrentFrame = 0; if (pPreviewDialog != NULL) { pPreviewDialog->SetPlayAnimation(PlayAnimation); CurrentFrame = pPreviewDialog->GetCurrentItem(); } // Fire up the preview dialog box with the bitmaps in our list if (!PreviewAnimation()) { // We failed to preview the bitmap delete m_pBitmapFilter; m_pBitmapFilter = NULL; FailAndExecute(); End(); return; } // If the dialog is still there then select the new frame to be displayed // Default is frame 0 so only do it if the requested item is different to this pPreviewDialog = PreviewDialog::GetPreviewDialog(); if (pPreviewDialog && CurrentFrame != 0) pPreviewDialog->SelectCurrentFrame(CurrentFrame); // remove the filter as we have no more use for it delete m_pBitmapFilter; m_pBitmapFilter = NULL; End(); return; } /******************************************************************************************** // End of OpGrabAllFrames ********************************************************************************************/ //----------------------------------------------------------------------------------------------- // GrabFrameFilter - Dummy filter, used to render the selection into a bitmap //----------------------------------------------------------------------------------------------- /******************************************************************************************** > GrabFrameFilter::GrabFrameFilter() Author: Neville_Humphrys (Xara Group Ltd) Created: 24/4/97 Purpose: Constructor for an GrabFrameFilter object. The object should be initialised before use. ********************************************************************************************/ GrabFrameFilter::GrabFrameFilter() { pTheBitmap = NULL; m_pLayer = NULL; m_pOptimisedPalette = NULL; m_pMkBmpOptions = NULL; m_pCopyMkBmpOptions = NULL; m_GrabMode = GRABMODE_FOROUTPUT; // Override this to say something more useful ExportingMsgID = _R(IDS_EXPORTINGANIMATEDGIF); // "Exporting animated GIF file..." } /******************************************************************************************** > GrabFrameFilter::GrabFrameFilter() Author: Neville_Humphrys (Xara Group Ltd) Created: 9/6/97 Purpose: Destructor for an GrabFrameFilter object. ********************************************************************************************/ GrabFrameFilter::~GrabFrameFilter() { if (m_pOptimisedPalette != NULL) { CCFree(m_pOptimisedPalette); m_pOptimisedPalette = NULL; } if (m_pCopyMkBmpOptions != NULL) { delete m_pCopyMkBmpOptions; m_pCopyMkBmpOptions = NULL; } } /******************************************************************************************** > virtual BOOL GrabFrameFilter::GenerateOptimisedPalette(Spread *pSpread, UINT32 Depth, double DPI, BOOL SnapToBrowserPalette, UINT32 NumColsInPalette, BOOL UsePrimaryCols) Author: Neville_Humphrys (Xara Group Ltd) based on Will code Created: 9/6/97 Inputs: pSpread = ptr to spread Depth = The BPP of the bitmap DPI = the dpi of the bitmap NumColsInPalette = prefered number of cols in palette (0 = select maximum allowed) (only applies when Depth == 8) UsePrimaryCols = Put primary colours in palette (only applies when Depth == 8) SnapToBrowserPalette= TRUE if the palette should be snapped to the browser palette after generation Returns: TRUE if Palette generated ok Purpose: Generates an optimised palette to use during export We override the baseclass form so that we generate one optimised palette for all frames if we are in global optimised mode. Otherwise, we can just call the base class version. SeeAlso: - ********************************************************************************************/ BOOL GrabFrameFilter::GenerateOptimisedPalette(Spread *pSpread, UINT32 Depth, double DPI, BOOL SnapToBrowserPalette, UINT32 NumColsInPalette, BOOL UsePrimaryCols) { // SMFIX it will pick a valid palette as it goes along // optimal palettes are no longer created in this manner // sjk return TRUE; } /******************************************************************************************** > BOOL GrabFrameFilter::SetLayerBeingCaptured(Layer * pNewLayer) Author: Neville_Humphrys (Xara Group Ltd) Created: 7/5/97 Inputs: pNewLayer the layer which is being captured. Purpose: This remembers the layer that is being captured. It sets the member variable up to the specified layer. ********************************************************************************************/ BOOL GrabFrameFilter::SetLayerBeingCaptured(Layer * pNewLayer) { m_pLayer = pNewLayer; return TRUE; } /******************************************************************************************** > virtual BOOL GrabFrameFilter::SetUpClippingRectangleForExport(Spread *pSpread, SelectionType Selection) Author: Neville_Humphrys (Xara Group Ltd) Created: 29/4/97 Inputs: pSpread the spread to export Selection the selection type to use during export Returns: TRUE if the operation was successful FALSE otherwise Purpose: Sets up the class variable ClipRect to be the clipping rectangle to be used during export. See Also: PrepareToExport() ********************************************************************************************/ BOOL GrabFrameFilter::SetUpClippingRectangleForExport(Spread *pSpread, SelectionType Selection) { ERROR2IF(pSpread == NULL,FALSE,"SetUpClippingRectangleForExport Bad spread"); // Make an empty rect to start with in the class variable ClipRect.MakeEmpty(); // Walk through all the frame layers and work out the bounding boxes of each Layer* pCurrentLayer = pSpread->FindFirstFrameLayer(); Layer* pNextLayer = NULL; while (pCurrentLayer != NULL) { pNextLayer = pCurrentLayer->FindNextFrameLayer(); // Double check that it is a suitable frame layer and check it is not hidden if (pCurrentLayer->IsPseudoFrame()) { // Cannot include a simple hidden check as the purpose of hidden frames is to // act as backgrounds for the animation. Could check for hidden and solid but // would also need to check for an overlay onto the hidden frame if ( (!pCurrentLayer->IsHiddenFrame()) || (pCurrentLayer->IsHiddenFrame() && pCurrentLayer->IsSolid()) || (pCurrentLayer->IsHiddenFrame() && pNextLayer && pNextLayer->IsOverlay()) ) { // Get the bounding rect for this layer DocRect LayerRect = pCurrentLayer->GetBoundingRect(); // Add this to our clipping rectangle ClipRect = ClipRect.Union(LayerRect); } } // Move to the next bitmap in the animation pCurrentLayer = pNextLayer; } return TRUE; } /******************************************************************************************** > virtual BOOL GrabFrameFilter::GetExportOptions(BitmapExportOptions* pOptions) Author: Neville_Humphrys (Xara Group Ltd) Created: 24/4/97 Purpose: See BaseBitmapFilter for interface details ********************************************************************************************/ BOOL GrabFrameFilter::GetExportOptions(BitmapExportOptions* pOptions) { ERROR2IF(pOptions == NULL, FALSE, "pOptions NULL"); ERROR3IF(!pOptions->IS_KIND_OF(MakeBitmapExportOptions), "pOptions isn't of type MakeBitmapExportOptions"); m_pMkBmpOptions = (MakeBitmapExportOptions*) pOptions; // Determine the filter type currently in use in Accusoft format s_FilterType = MAKE_BITMAP_FILTER; // Force the selection type to be DRAWING as this should render all visible objects m_pMkBmpOptions->SetSelectionType(DRAWING); m_pMkBmpOptions->SetDPI(96.0); if (m_GrabMode == GRABMODE_PREVIEW) { // We want a 24bbp bitmap to pass to Gavin's code but using 32bbp to // store each pixel (ie the 4 channel of each pixel is waste). This // should do the trick. m_pMkBmpOptions->SetDepth(24); } else { // Force the depth to be 8bpp m_pMkBmpOptions->SetDepth(8); } // Force the interlacing off m_pMkBmpOptions->SetMakeInterlaced(FALSE); // Force the transparency to on. //m_pMkBmpOptions->SetMakeTransparent(TRUE); // recover the relevant animation options from the spread if (pSpread) { DWORD Loop = 0; DWORD GlobalDelay = 10; DITHER Dither = XARADITHER_ORDERED_GREY; WEB_PALETTE WebPalette = PAL_GLOBAL; PALETTE_COLOURS ColoursPalette = PALCOL_BROWSER; DWORD NumColsInPalette = 255; BOOL UseSystemColours = FALSE; // Ask the spread for its version of these values pSpread->GetSpreadAnimPropertiesParam(&Loop, &GlobalDelay, &Dither, &WebPalette, &ColoursPalette, &NumColsInPalette, &UseSystemColours, NULL); // set to use background transp if it is set in the animation properties dlg m_pMkBmpOptions->SetBackgroundTransparency(pSpread->GetSpreadAnimPropertiesParam().GetIsBackGroundTransp()); // Ensure the dependent options are set correctly // There are 20 colours in the system palette switch (ColoursPalette) { case PALCOL_STANDARD: case PALCOL_BROWSER: // Fixed browser palette // SMFIX we want a browser palette m_pMkBmpOptions->SetToUseBrowserPalette(TRUE); m_pMkBmpOptions->CreateValidBrowserPalette(TRUE); // set this as the palette being used in output dib AlterPaletteContents(m_pMkBmpOptions->GetLogicalPalette()); break; case PALCOL_OPTIMIZED: // Optimised, so take the user's chosen number of required colours // Check if local or globally optimised /* if (WebPalette == PAL_GLOBAL) TRACEUSER( "SimonK", _T("PAL_GLOBALOPTIMISED\n")); else TRACEUSER( "SimonK", _T("PAL_OPTIMISED\n")); */ //m_pMkBmpOptions->SetNumColsInPalette(NumColsInPalette); // store the number of user defined colours in the options m_pMkBmpOptions->SetNumberOfUserRequestedColours(NumColsInPalette); // In optimised mode we cannot have ordered dithering as it // must have a known palette. So switch the dithering to error // diffusion. if (Dither == XARADITHER_ORDERED_GREY) Dither = XARADITHER_ERROR_DIFFUSION; // Set up whether we save system colours or not //m_pMkBmpOptions->SetUseSystemColours(UseSystemColours); //m_pMkBmpOptions->SetToUseSystemPalette(UseSystemColours); break; default: ERROR3("Bad ColoursPalette option"); break; } switch (WebPalette) { case PAL_GLOBAL: // If global set then must be browser palette selected //TRACEUSER( "SimonK", _T("PAL_GLOBAL\n")); // ColoursPalette = PALCOL_BROWSER; // use the global palette here if (GetGlobalOptimisedPalette()) { m_pMkBmpOptions->CreateValidPalette(GetGlobalOptimisedPalette(), m_pMkBmpOptions->IsBackgroundTransparent() ? 0 : -1); // set this as the palette being used in output dib AlterPaletteContents(m_pMkBmpOptions->GetLogicalPalette()); } break; case PAL_LOCAL: // If local palette selected then must be optimised as // no point saving out a global palette //TRACEUSER( "SimonK", _T("PAL_LOCAL\n")); // ColoursPalette = PALCOL_OPTIMIZED; // SMFIX // if we are the first frame generate a new valid palette // we could use that as a first guess at a global palette // but we do know that if we do not have a global palette we // should be getting a different palette for each frame m_pMkBmpOptions->InvalidatePalette(); break; default: ERROR3("Bad WebPalette option"); break; } // Set up the dithering that we are going to use m_pMkBmpOptions->SetDither(Dither); } // We have all the options that we require so don't ask the user for anything // Take a copy of these options for latter use (Browser Preview) if (m_pCopyMkBmpOptions == NULL) { m_pCopyMkBmpOptions = (MakeBitmapExportOptions *)m_pMkBmpOptions->MakeCopy(); // don't complain about null as only required by browser preview at present } // All ok return TRUE; } /******************************************************************************************** > virtual BOOL GrabFrameFilter::SetupExportOptions(BitmapExportOptions* pOptions, Spread * pCurrentSpread) Author: Neville_Humphrys (Xara Group Ltd) Created: 4/8/97 Inputs: pCurrentSpread The spread we are currently working with Purpose: This is just a public interface on the normal filter's GetExportOptions which is protected. It also ensures that the pSpread is set up. ********************************************************************************************/ BOOL GrabFrameFilter::SetupExportOptions(BitmapExportOptions* pOptions, Spread * pCurrentSpread) { // Ensure that the spread pointer is set up // If we haven't actually grabbed any frames then it will be NULL pSpread = pCurrentSpread; // Set up those export options return GetExportOptions(pOptions); } /******************************************************************************************** > virtual KernelBitmap* GrabFrameFilter::GetTheBitmap() Author: Neville_Humphrys (Xara Group Ltd) Created: 24/4/97 Purpose: Creates a kernel bitmap from the Export RenderRegion Overrides the baseclass version as that uses MakeKernelBitmap which does check to see if the OIL bitmap pointers are the same but does not check that the contents are the same. This means we end up with duplicated versions. This is bad. We use TryAndUseExistingBitmap which does this extra check. This is ok in the Creat bitmap copy case as this is the only way to generate duplicate frames. Returns: Ptr to the bitmap, or NULL if error Note: We cannot even do it this way as a) the code which checks for duplicates in the global bitmap list complains as the bitmap is already attached to the list b) even after this, using the TryAndUseExistingBitmap does not reuse the existing bitmap So try plan c. Add the extra code to ExtractBitmapCopy so when it tries to attach the oilbitmap it sees if it is reusing an existing bitmap. If so then it will just return the existing bitmap rather than adding a new duplicate to the system. ********************************************************************************************/ KernelBitmap* GrabFrameFilter::GetTheBitmap() { // Extract a copy of the bitmap from the RenderRegion // We need to generate new bitmaps as we delete them and also name them ourselves. BOOL LookForDuplicates = FALSE; OILBitmap* pOilBitmap = ExportRegion->ExtractBitmapCopy(pOptimisedPalette, pDestBMInfo, pDestBMBytes, TransColour, LookForDuplicates); if (pOilBitmap == NULL) { CleanUpAfterExport(); return NULL; } if (m_pLayer) { // Make the bitmap name the layer name String_256 Name = m_pLayer->GetLayerID(); pOilBitmap->SetName(Name); // Copy across the delay from the layer DWORD delay = m_pLayer->GetFrameDelay(); pOilBitmap->SetBitmapAnimDelay(delay); // As all these frames are complete, we output them using // a replace background restore type. // It is only later that we may do some trickery on them so that // we can overlay them. pOilBitmap->SetAnimationRestoreType(GDM_BACKTOBACK); // The exception is if the frame is solid in which case we invariably // want that one to overlay //if (m_pLayer->IsSolid()) // pOilBitmap->SetAnimationRestoreType(GDM_LEAVE); //else } // Make a kernel bitmap from the oily one // The class variable pDocument should be holding the document required // Must check it as TryAndUseExistingBitmap does not! // ERROR2IF(TheDocument == NULL,NULL,"GrabFrameFilter::GetTheBitmap null document") // BOOL IsNew = TRUE; // return KernelBitmap::TryAndUseExistingBitmap(pOilBitmap, TheDocument, &IsNew); return KernelBitmap::MakeKernelBitmap(pOilBitmap, TheDocument); } /******************************************************************************************** > virtual BOOL GrabFrameFilter::ExportVisibleLayersOnly() Author: Neville_Humphrys (Xara Group Ltd) Created: 29/04/97 Inputs: - Outputs: - Returns: True if this filter wants to exclude invisible layers and so export only visible items Or False if want to export everything. Purpose: Determines if the filter wants to export only visible layers. In the base bitmap filters class version the default action will be to export only those layers which are visible. SeeAlso: Filter::ExportRender; ********************************************************************************************/ BOOL GrabFrameFilter::ExportVisibleLayersOnly() { #ifdef DO_EXPORT MaskedFilterExportOptions* pMaskedOptions = (MaskedFilterExportOptions*)GetBitmapExportOptions(); ERROR2IF(pMaskedOptions == NULL, FALSE, "NULL Args"); ERROR3IF(!pMaskedOptions->IS_KIND_OF(MaskedFilterExportOptions), "pMaskedOptions isn't"); ERROR2IF(pSpread == NULL, FALSE,"GrabFrameFilter::VisibleLayersOnly no spread to export"); // We always want to export oONLY the visible layers. // When we are exporting in transparent mode and making up the mask, we must go and set the // page background layer to be invisible // We are just taking the oppurtunity that this call gives us to fix up the page background // layer to be invisible if (pMaskedOptions->WantTransparent() && !SecondPass && !GeneratingOptimisedPalette()) { // Masking operation // If we find a page background layer then make sure it is invisible Layer * pLayer = pSpread->FindFirstPageBackgroundLayer(); if (pLayer) pLayer->SetVisible(FALSE); } else { // Normal export operation // If we find a page background layer then make sure it is visible Layer * pLayer = pSpread->FindFirstPageBackgroundLayer(); if (pLayer) pLayer->SetVisible(TRUE); } // only include all layer that are visible in this bitmap export return TRUE; #else // only include all layer that are visible in this bitmap export return TRUE; #endif } /******************************************************************************************** > virtual BOOL GrabFrameFilter::ExportSelectionOnly() Author: Neville_Humphrys (Xara Group Ltd) Created: 29/04/97 Returns: True if this filter wants check if an object is selected or not and so export only the selected items Or False if want to export everything. Purpose: Determines if the filter wants to export only selected items. In the base bitmap filters class version the default action will be to export all objects by default SeeAlso: Filter::ExportRender; ********************************************************************************************/ BOOL GrabFrameFilter::ExportSelectionOnly(BOOL MaskedRender) { // We always export all the objects return FALSE; } /******************************************************************************************** > BOOL GrabFrameFilter::IsSecondPassRequired() Author: Neville_Humphrys (Xara Group Ltd) Created: 29/04/97 Returns: True if this filter wants a second export rendering pass and so have a chance to setup semething like a mask. Purpose: Determines if the a second rendering pass is required or not. ********************************************************************************************/ BOOL GrabFrameFilter::IsSecondPassRequired() { #ifdef DO_EXPORT MaskedFilterExportOptions* pMaskedOptions = (MaskedFilterExportOptions*)GetBitmapExportOptions(); ERROR2IF(pMaskedOptions == NULL, FALSE, "NULL Args"); ERROR3IF(!pMaskedOptions->IS_KIND_OF(MaskedFilterExportOptions), "pMaskedOptions isn't"); // Only require a second pass if wanting transparency if (pMaskedOptions->WantTransparent()) return TRUE; else return FALSE; #else return FALSE; #endif } /******************************************************************************************** > virtual BOOL GrabFrameFilter::DoExportBitmaps(Operation* pOp, CCLexFile* pFile, PathName* pPath, BitmapExportParam* pParam, BOOL DontShowFileName = FALSE) Author: Neville_Humphrys (Xara Group Ltd) Created: 30/04/97 Inputs: pOp - the operation that started the export off pDiskFile - the file to put the exported data into pPath - the pathname of the file to be exported to pParam - the data to use when exporting the bitmaps Returns: TRUE if worked, FALSE if failed. Purpose: Exports the bitmaps specified by the BitmapExportParam object to a multi- image capable filter. ********************************************************************************************/ BOOL GrabFrameFilter::DoExportBitmaps(Operation *pOp, CCLexFile* pFile, PathName* pPath, BitmapExportParam* pParam, BOOL DontShowFileName) { #ifdef DO_EXPORT ERROR2IF(pOp == NULL || pFile == NULL || pPath == NULL, FALSE,"NULL Parameters"); ERROR2IF(pParam == NULL,FALSE,"GrabFrameFilter::DoExportBitmaps null BitmapExportParam specified"); // We could just call the function direct but this may give us some more functionality // in the long term return SaveExportBitmapsToFile(pFile, pPath, pParam, DontShowFileName); #endif return FALSE; } /******************************************************************************************** > void GrabFrameFilter::SetGlobalOptimisedPalette(LPLOGPALETTE pOptimisedPalette) Author: Neville_Humphrys (Xara Group Ltd) Created: 09/07/97 Inputs: pOptimisedPalette - the new global optimised palette Returns: TRUE if worked, FALSE if failed. Purpose: Sets up a new optimised palette ready to be applied to all frames in the animation. Should be used with care. At present, only used if we discover that all frames contain compatible bitmaps that have the same palette on them. ********************************************************************************************/ void GrabFrameFilter::SetGlobalOptimisedPalette(LPLOGPALETTE pOptimisedPalette) { if (m_pOptimisedPalette != NULL) { CCFree(m_pOptimisedPalette); m_pOptimisedPalette = NULL; } m_pOptimisedPalette = pOptimisedPalette; } /******************************************************************************************** > virtual UINT32 GrabFrameFilter::GetExportMsgID() Author: Neville_Humphrys (Xara Group Ltd) Created: 28/07/97 Returns: The id of the message to put on the progress display whilst exporting. Purpose: Used to get the message id to be used during export. Virtual, so that two stage exporters can change the message. SeeAlso: DoExport; ********************************************************************************************/ UINT32 GrabFrameFilter::GetExportMsgID() { // Always return this message regardless of the stage that we are on return _R(IDS_GENERATINGFRAMES); // "Generating animation frames..." } /******************************************************************************************** // End of GrabFrameFilter ********************************************************************************************/ //------------------------------------------------------------------------------------------ // GIFAnimationExportParam //------------------------------------------------------------------------------------------ /******************************************************************************************** > GIFAnimationExportParam::GIFAnimationExportParam() Author: Neville_Humphrys (Xara Group Ltd) Created: 13/05/97 Purpose: Default constructor ********************************************************************************************/ GIFAnimationExportParam::GIFAnimationExportParam() { m_BitmapCount = 0; m_pBitmaps = NULL; m_LayerCount = 0; m_pLayers = NULL; m_RegeneratedBitmapPosition = 0; } /******************************************************************************************** > GIFAnimationExportParam::~GIFAnimationExportParam() Author: Neville_Humphrys (Xara Group Ltd) Created: 13/05/97 Purpose: Default destructor ********************************************************************************************/ GIFAnimationExportParam::~GIFAnimationExportParam() { // free up the arrays that we grabbed if (m_pBitmaps != NULL) { CCFree(m_pBitmaps); m_pBitmaps = NULL; m_BitmapCount = 0; } if (m_pLayers != NULL) { CCFree(m_pLayers); m_pLayers = NULL; m_LayerCount = 0; } } /******************************************************************************************** > GIFAnimationExportParam::GIFAnimationExportParam(UINT32 Count, KernelBitmap** pBitmap) Author: Neville_Humphrys (Xara Group Ltd) Created: 13/05/97 Inputs: Count - The number of indexes in the array pBitmap - pointer to an array of pointers to kernel bitmaps Outputs: - Returns: - Purpose: Used to pass around lists of bitmaps. Note that deleting the bitmap array is the responsibility of the caller. ********************************************************************************************/ GIFAnimationExportParam::GIFAnimationExportParam(UINT32 Count, KernelBitmap** pBitmap) { ERROR3IF(Count == 0, "Zero bitmap count, that's not right"); ERROR3IF(pBitmap == NULL, "NULL bitmap array"); ERROR3IF(!(*pBitmap)->IS_KIND_OF(KernelBitmap), "This dosen't seem to be an array of kernel bitmaps"); m_BitmapCount = Count; m_pBitmaps = pBitmap; // set up everything else to defaults m_RegeneratedBitmapPosition = 0; m_LayerCount = 0; m_pLayers = NULL; } /******************************************************************************************** > virtual UINT32 GIFAnimationExportParam::GetBitmapCount() Author: Neville_Humphrys (Xara Group Ltd) Created: 13/05/97 Returns: The number of bitmaps in the bitmap array. (The array runs 0..Count-1) Purpose: For getting the number of bitmaps in the array! ********************************************************************************************/ UINT32 GIFAnimationExportParam::GetBitmapCount() { return m_BitmapCount; } /******************************************************************************************** > virtual KernelBitmap* GIFAnimationExportParam::GetBitmap(UINT32 Index) Author: Neville_Humphrys (Xara Group Ltd) Created: 13/05/97 Inputs: Index - the index of the required bitmap Outputs: - Returns: Pointer to the nth bitmap, NULL if error Purpose: For safely getting a pointer to a bitmap in the bitmap array ********************************************************************************************/ KernelBitmap* GIFAnimationExportParam::GetBitmap(UINT32 Index) { ERROR2IF(Index >= m_BitmapCount, NULL, "Index out of bounds"); ERROR2IF(m_pBitmaps == NULL, NULL, "NULL array"); ERROR3IF(!(m_pBitmaps[Index])->IS_KIND_OF(KernelBitmap), "This dosen't seem to be a pointer to a kernel bitmap"); return m_pBitmaps[Index]; } /******************************************************************************************** > virtual UINT32 GIFAnimationExportParam::GetLayerCount() Author: Neville_Humphrys (Xara Group Ltd) Created: 13/05/97 Returns: The number of bitmaps/layers in the layers/bitmap array. (The array runs 0..Count-1) Purpose: For getting the number of layers/bitmaps in the array! ********************************************************************************************/ UINT32 GIFAnimationExportParam::GetLayerCount() { return m_LayerCount; } /******************************************************************************************** > virtual Layer * GIFAnimationExportParam::GetLayer(UINT32 Index) Author: Neville_Humphrys (Xara Group Ltd) Created: 13/05/97 Inputs: Index - the index of the required bitmap Outputs: - Returns: Pointer to the nth bitmap, NULL if error Purpose: For safely getting a pointer to a bitmap in the bitmap array ********************************************************************************************/ Layer* GIFAnimationExportParam::GetLayer(UINT32 Index) { ERROR2IF(Index >= m_LayerCount, NULL, "Index out of bounds"); ERROR2IF(m_pLayers == NULL, NULL, "NULL array"); ERROR3IF(!(m_pLayers[Index])->IS_KIND_OF(Layer), "This dosen't seem to be a pointer to a layer"); return m_pLayers[Index]; } /******************************************************************************************** > virtual BOOL GIFAnimationExportParam::AddLayerAndBitmap(Layer * pLayer, KernelBitmap * pBitmap) Author: Neville_Humphrys (Xara Group Ltd) Created: 13/05/97 Inputs: pLayer the layer to be added to the list/array pBitmap the bitmap associated with this layer to be added to the list/array Returns: True if worked ok, False otherwise. Purpose: For adding a layer to list ready for exporting the GIF animation. Uses the class variables m_pLayers and m_LayerCount. ********************************************************************************************/ BOOL GIFAnimationExportParam::AddLayerAndBitmap(Layer * pLayer, KernelBitmap * pBitmap) { // Let the called functions do the parameter checking! return AddLayer(pLayer) && AddBitmap(pBitmap); } /******************************************************************************************** > virtual BOOL GIFAnimationExportParam::AddLayer(Layer * pLayer) Author: Neville_Humphrys (Xara Group Ltd) Created: 13/05/97 Inputs: pLayer the layer to be added to the list/array Outputs: - Returns: True if worked ok, False otherwise. Purpose: For adding a layer to list ready for exporting the GIF animation. Uses the class variables m_pLayers and m_LayerCount. ********************************************************************************************/ BOOL GIFAnimationExportParam::AddLayer(Layer * pLayer) { ERROR2IF(pLayer == NULL,FALSE,"AddLayer given null layer"); BOOL ok = TRUE; // If we have a null list then just allocate the first item if (m_pLayers == NULL) { // Claim selected space m_pLayers = (Layer**) CCMalloc(sizeof(Layer*)); if (m_pLayers == NULL) ok = FALSE; else m_pLayers[0] = pLayer; m_LayerCount = 1; } else { // Add to end of selection Layer** pTemp = (Layer**) CCRealloc(m_pLayers, (m_LayerCount + 1) * sizeof(Layer*)); if (pTemp == NULL) ok = FALSE; else { m_pLayers = pTemp; m_pLayers[m_LayerCount] = pLayer; } m_LayerCount++; } return ok; } /******************************************************************************************** > BOOL GIFAnimationExportParam::AddBitmap(KernelBitmap * pBitmap) Author: Neville_Humphrys (Xara Group Ltd) Created: 13/05/97 Inputs: pBitmap the bitmap to add to our list in the animation Returns: True if worked ok, False otherwise Purpose: Tries to add the bitmap to the list. Uses the class variables m_pBitmaps and m_BitmapCount. Copied from BitmapSGallery and BitmapExportParam way of doing things so that we are compatible. Not the best way of doing it! SeeAlso: BitmapSGallery::GetSelectedBitmaps ********************************************************************************************/ BOOL GIFAnimationExportParam::AddBitmap(KernelBitmap * pBitmap) { ERROR2IF(pBitmap == NULL,FALSE,"Addbitmap given null bitmap"); BOOL ok = TRUE; // If we have a null list then just allocate the first item if (m_pBitmaps == NULL) { // Claim selected space m_pBitmaps = (KernelBitmap**) CCMalloc(sizeof(KernelBitmap*)); if (m_pBitmaps == NULL) ok = FALSE; else m_pBitmaps[0] = pBitmap; m_BitmapCount = 1; } else { // Add to end of selection KernelBitmap** pTemp = (KernelBitmap**) CCRealloc(m_pBitmaps, (m_BitmapCount + 1) * sizeof(KernelBitmap*)); if (pTemp == NULL) ok = FALSE; else { m_pBitmaps = pTemp; m_pBitmaps[m_BitmapCount] = pBitmap; } m_BitmapCount++; } return ok; } /******************************************************************************************** > BOOL GIFAnimationExportParam::SetAnimPropertiesParam(AnimPropertiesParam* pParam) Author: Neville_Humphrys (Xara Group Ltd) Created: 13/05/97 Inputs: pParam - Sets the Animation Properties details for this GIFAnimationExportParam. Returns: TRUE if ok, FALSE otherwise. ********************************************************************************************/ void GIFAnimationExportParam::SetSpreadAnimPropertiesParam(const AnimPropertiesParam& Param) { m_AnimPropertiesParam = Param; } /******************************************************************************************** > void GIFAnimationExportParam::GetAnimPropertiesParam() Author: Neville_Humphrys (Xara Group Ltd) Created: 13/05/97 Purpose: Returns the Animation Properties details for this GIFAnimationExportParam. ********************************************************************************************/ AnimPropertiesParam& GIFAnimationExportParam::GetSpreadAnimPropertiesParam() { return m_AnimPropertiesParam; } /******************************************************************************************** > DocRect GIFAnimationExportParam::GetBoundingRect() const Author: Neville_Humphrys (Xara Group Ltd) Created: 11/06/97 Purpose: Returns the bounding rectangle of the animation. ********************************************************************************************/ DocRect GIFAnimationExportParam::GetBoundingRect() const { // Recover the bounding rect of the animation from our copy of the spread's // animation properties. DocRect BoundingRect = m_AnimPropertiesParam.GetBoundingRect(); // We are only interested in the size and so translate it to zero BoundingRect.Translate(-BoundingRect.lo.x, -BoundingRect.lo.y); // return it to the caller return BoundingRect; } //------------------------------------------------------------------------------------------ // end of GIFAnimationExportParam //------------------------------------------------------------------------------------------ /******************************************************************************************** // OpSaveAnimatedGIF ********************************************************************************************/ /******************************************************************************************** > OpState OpSaveAnimatedGIF::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 9/9/97 Inputs: Name of the OpDescriptor being queried Outputs: The string to show to the user Returns: The state of the OpSaveAnimatedGIF operation Purpose: For finding the OpSaveAnimatedGIF's state. ********************************************************************************************/ OpState OpSaveAnimatedGIF::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc) { // else just use the base class version return OpGrabAllFrames::GetState(pUIDescription, pOpDesc); } /******************************************************************************************** > BOOL OpSaveAnimatedGIF::GetFileNameFromUser() Author: Neville_Humphrys (Xara Group Ltd) Created: 7/7/97 Returns: True if worked ok, False otherwise Purpose: Gives the operation chance to get the filename from the user. In this version we need to do this before grabbing the frames so that the user is given the oppurtunity to change the options using the button on the file save dialog box. ********************************************************************************************/ BOOL OpSaveAnimatedGIF::GetFileNameFromUser() { // This is used to export an animated GIF. So we need only show the normal // GIF filter. This is despite the fact that this is not going to be the filter // that we use for the job. // We are just going to show the animated GIF filter and all files String_256 FilterString(_R(IDS_SAVEGIFANIFILTERS)); // Ensure that all the filters have a -1 in their position string so any matching // of selected filter will fail. Make only the GIF filter have 1 in there. Filter* pFilter = Filter::GetFirst(); while (pFilter != NULL) { if (IS_A(pFilter, TI_GIFFilter)) { // Its the GIF filter we want, mark it as the first position pFilter->pOILFilter->Position = 1; } else { // Make sure we don't try this one later pFilter->pOILFilter->Position = -1; } // Try the next filter pFilter = Filter::GetNext(pFilter); } // Create the dialog box GIFExportFileDialog FDialog(FilterString); FDialog.SetTitle(_R(IDS_SAVEGIFANI_TITLE)); // Use the document name as the default name of animation String_256 DefaultName(_R(IDS_BUTTBAR_ANIMATION)); // GIF Animation if (m_pDocument) DefaultName = m_pDocument->GetDocName(FALSE); // This is the pathname that we are going to save to m_SavePath = DefaultName; // Ensure that we have the correct extension on the filename we have allocated EnsureFileType(&m_SavePath); // Pass this name onto the dialog box DefaultName = m_SavePath.GetFileName(); FDialog.SetDefaultFileName(DefaultName); //FDialog.SetSelectedFilterIndex(1); // Select the desired path String_256 ExportFilterPath = OpMenuExport::DefaultExportFilterPath; //Camelot.GetPrefDirect("Filters", "DefaultExportFilterPath",&ExportFilterPath); if (ExportFilterPath.Length() > 0) FDialog.SetInitialDirectory(ExportFilterPath); // 'Do' the dialog and get that filename that we require BOOL DlgResult = FDialog.OpenAndGetFileName(); if (!DlgResult) { return FALSE; } // Get the filename. FDialog.GetChosenFileName(&m_SavePath); // This is now taken care of in FileDlgs.cpp on the ok as it then checks if the file // exists or not. If we do it here then this does not happen. // Unfortunately, changes made to the string in the dialog do not filter through // and so we ust fix it up here as well. // Always make sure that the filter's default extension is on if the user has not // specified an extension. EnsureFileType(&m_SavePath); // Ensure that the path is valid if (!m_SavePath.IsValid()) { InformError(); //delete m_pBitmapFilter; //m_pBitmapFilter = NULL; return FALSE; } // Extract directory name (minus terminating backslash) and remember for next time. ExportFilterPath = m_SavePath.GetLocation(FALSE); if (ExportFilterPath.Length() > 0) OpMenuExport::DefaultExportFilterPath = ExportFilterPath; //Camelot.SetPrefDirect("Filters", "DefaultExportFilterPath",DefaultExportFilterPath, TRUE); //UINT32 TheSelectedFilterID = m_pBitmapFilter->FilterID; // Everything got so return to the grabbing process return TRUE; } /******************************************************************************************** > virtual BOOL OpSaveAnimatedGIF::SaveOrShowTheAnimation(PreviewDialog * pPreviewDialog, BitmapExportParam* pExportParam) Author: Neville_Humphrys (Xara Group Ltd) Created: 4/8/97 Inputs: pPreviewDialog the preview dialog box, if open pExportParam the export param which we will use Returns: True if worked ok, False otherwise Purpose: Tries to actually do the preview operation required. In this case we just save the animation out to the file that the user specified. ********************************************************************************************/ BOOL OpSaveAnimatedGIF::SaveOrShowTheAnimation(PreviewDialog * pPreviewDialog, BitmapExportParam* pExportParam) { // A bit of checking on parameters if (pExportParam != NULL) { ERROR3IF(!pExportParam->IS_KIND_OF(BitmapExportParam), "OpParam passed is not a BitmapExportParam"); if (pExportParam->GetBitmapCount() == 0) { ERROR2RAW("OpSaveAnimatedGIF::DoWithParam no bitmaps to export"); return FALSE; } } else { ERROR2RAW("OpSaveAnimatedGIF::DoWithParam bad params!"); return FALSE; } // Recover the bitmap pointer from the parameter passed in // This is to ensure that we have at least one bitmap to save KernelBitmap* pTheBitmap = pExportParam->GetBitmap(0); if (pTheBitmap == NULL) { ERROR2RAW("OpSaveAnimatedGIF::DoWithParam bitmap pointer is null"); return FALSE; } // Ensure that we have a special grab frame filter available if (m_pBitmapFilter == NULL) m_pBitmapFilter = new GrabFrameFilter(); if (m_pBitmapFilter == NULL) { InformError(_R(IDT_CANT_FIND_FILTER)); return FALSE; } // Should really check that the pathname is not null String_256 Filename; Filename = m_SavePath.GetPath(); ERROR2IF(Filename.IsEmpty(),FALSE,"OpSaveAnimatedGIF::SaveAnimation Save path not set up!"); // First off, we have to try and open the file CCDiskFile DiskFile(1024, FALSE, TRUE); BOOL ExportedOk = TRUE; try { // Export bitmaps ExportedOk = m_pBitmapFilter->DoExportBitmaps(this, &DiskFile, &m_SavePath, pExportParam); if (!ExportedOk) { // Something went a bit wrong - tell the user what it was. // Supress the error if it was the 'user has cancelled one' if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED)) { InformError(); m_pBitmapFilter->DeleteExportFile(&DiskFile); } else { // otherwise remove the error so it won't get reported Error::ClearError(); } } // close the file if (DiskFile.isOpen()) DiskFile.close(); } // See if there was a file io error catch(CFileException) { // Report the error if no one else did if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED)) { InformError(); } else Error::ClearError(); // otherwise remove the error so it won't get reported // Make sure that the file is closed and deleted try { // First try and delete it (tries to close it first) if (m_pBitmapFilter) m_pBitmapFilter->DeleteExportFile(&DiskFile); // Double check to make sure it is closed. if (DiskFile.isOpen()) DiskFile.close(); } catch(CFileException) { // Failed to close the file - not much we can do about it really } // Fail ExportedOk = FALSE; } // Clean out the filter we created delete m_pBitmapFilter; m_pBitmapFilter = NULL; // Blank the path //m_SavePath.SetPathName(TEXT("")); // This will give us a nice pathname is invalid error! Don't you just love the pathname class! return ExportedOk; } /******************************************************************************************** > BOOL OpSaveAnimatedGIF::EnsureFileType(PathName * pPath) Author: Neville_Humphrys (Xara Group Ltd) Created: 1/5/97 Inputs: pPath the pathname in use Purpose: Ensures that the pathname has the file extension/type that we require. ********************************************************************************************/ BOOL OpSaveAnimatedGIF::EnsureFileType(PathName * pPath) { ERROR2IF(pPath == NULL,FALSE,"EnsureFileExtension bad path specified"); // we are essentially a GIF filter so we need that extension String_32 ExtStr(_R(IDN_FILTEREXT_GIF)); ExtStr.toLower(); String_256 Extension = pPath->GetType(); Extension.toLower(); if (Extension.IsEmpty() || Extension != ExtStr) { // There is no extension set for this file, so give it one pPath->SetType(ExtStr); } return TRUE; } /******************************************************************************************** // end of OpSaveAnimatedGIF ********************************************************************************************/ //------------------------------------------------------------------------------------------ // Methods for the OpBrowserPreview //------------------------------------------------------------------------------------------ // Init the static that we have PathName OpBrowserPreview::m_TempPath; /******************************************************************************************** > BOOL OpBrowserPreview::GetFileNameFromUser() Author: Neville_Humphrys (Xara Group Ltd) Created: 7/7/97 Returns: True if worked ok, False otherwise Purpose: Gives the operation chance to get the filename from the user. In this version we need to override the OpSaveAnimation's version so that we do nothing. ********************************************************************************************/ BOOL OpBrowserPreview::GetFileNameFromUser() { // This version, do nothing return TRUE; } /******************************************************************************************** > virtual BOOL OpBrowserPreview::SaveOrShowTheAnimation(PreviewDialog * pPreviewDialog, BitmapExportParam* pExportParam) Author: Neville_Humphrys (Xara Group Ltd) Created: 4/8/97 Inputs: pPreviewDialog the preview dialog box, if open pExportParam the export param which we will use Returns: True if worked ok, False otherwise Purpose: Tries to actually do the preview operation required. In this case we just save the animation out to a temporary file and then fire up the browser with an html wrapper which references that file. ********************************************************************************************/ BOOL OpBrowserPreview::SaveOrShowTheAnimation(PreviewDialog * pPreviewDialog, BitmapExportParam* pExportParam) { // A bit of checking on parameters if (pExportParam != NULL) { ERROR3IF(!pExportParam->IS_KIND_OF(BitmapExportParam), "OpParam passed is not a BitmapExportParam"); if (pExportParam->GetBitmapCount() == 0) { ERROR2RAW("OpSaveAnimatedGIF::DoWithParam no bitmaps to export"); return FALSE; } } else { ERROR2RAW("OpSaveAnimatedGIF::DoWithParam bad params!"); return FALSE; } // Go and preview it in a browser. // Get our saving filter if (m_pBitmapFilter == NULL) m_pBitmapFilter = new GrabFrameFilter(); if (m_pBitmapFilter == NULL) { InformError(_R(IDT_CANT_FIND_FILTER)); return FALSE; } // create a disk file CCDiskFile TempDiskFile(1024, FALSE, TRUE); // Ensure that if we have been using a previous temp file then // it is cleaned up RemoveTempFile(); // Create the required unique temporary of the correct filetype String_32 ExtStr(_R(IDN_FILTEREXT_GIF)); ExtStr.toLower(); if (!FileUtil::GetTemporaryPathName(ExtStr, &m_TempPath)) return FALSE; // Ensure that we have the correct extension on the filename we have allocated EnsureFileType(&m_TempPath); // First off, we have to try and open the file CCDiskFile DiskFile(1024, FALSE, TRUE); BOOL ExportedOk = TRUE; try { // Export bitmaps supressing the filename so that the user does not see the temp filename ExportedOk = m_pBitmapFilter->DoExportBitmaps(this, &TempDiskFile, &m_TempPath, &m_ExportParams, TRUE); if (!ExportedOk) { // Something went a bit wrong - tell the user what it was. // Supress the error if it was the 'user has cancelled one' if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED)) { InformError(); m_pBitmapFilter->DeleteExportFile(&DiskFile); } else { // otherwise remove the error so it won't get reported Error::ClearError(); } } // close the file if (DiskFile.isOpen()) DiskFile.close(); } // See if there was a file io error catch(CFileException) { // Report the error if no one else did if (Error::GetErrorNumber() != _R(IDN_USER_CANCELLED)) { InformError(); } else Error::ClearError(); // otherwise remove the error so it won't get reported // Make sure that the file is closed and deleted try { // First try and delete it (tries to close it first) if (m_pBitmapFilter) m_pBitmapFilter->DeleteExportFile(&DiskFile); // Double check to make sure it is closed. if (DiskFile.isOpen()) DiskFile.close(); } catch(CFileException) { // Failed to close the file - not much we can do about it really } // Fail ExportedOk = FALSE; } ///------------------------------------ // Now we have the file, we can go and preview it in the browser // Allocate our preview class, must keep it around as destruction causes // it to clean up the temp files, which is bad if this is before it has // had a chance to fire up the browser! if (m_pBitmapData == NULL) { m_pBitmapData = new BitmapPreviewData; if (m_pBitmapData == NULL) return FALSE; } // Now a static pointer as otherwise the temp file is deleted too quickly MakeBitmapExportOptions * pBmpOptions = NULL; // Recover the options from the filter that it saved during the preparation of the bitmaps // They are helpfully vaped by now! So, we took a copy during GetExportOptions // But if all the frame are already captured then we will not have any options pBmpOptions = m_pBitmapFilter->GetCurrentExportOptionsCopy(); BOOL MadeBitmapOptions = FALSE; if (pBmpOptions == NULL) { // Get the filter to set up the bitmap options for us (Use out public version of CreateExportOptions) pBmpOptions = m_pBitmapFilter->MakeExportOptions(); // Use our public interface onto the GetExportOptions protected function if (pBmpOptions != NULL) { MadeBitmapOptions = TRUE; m_pBitmapFilter->SetupExportOptions(pBmpOptions, m_pSpread); } } ERROR2IF(pBmpOptions == NULL,FALSE,"OpBrowserPreview::PreviewAnimation No current bitmap options"); // Get the first bitmap in the list, this will give us the size of the animation KernelBitmap* pTheBitmap = pExportParam->GetBitmap(0); // Get the filesize that we have exported UINT32 FileSize = TempDiskFile.Size(); // tell the options about the temp file that we are using pBmpOptions->SetPathName(&m_TempPath); // This is our copy of the BitmapExportParam m_pBitmapData->SetNewBitmap(pTheBitmap, FileSize, pBmpOptions); // Set up the options that we require /* BrowserBackground Bgr = BROWSER_BGR_DOC; //BROWSER_BGR_CHECKER; BOOL ShowInfo = TRUE; BOOL GenerateImagemap = FALSE; */ // Get the values from our global variables. BrowserBackground Bgr = PreviewInBrowserTab::g_Background; BOOL ShowInfo = PreviewInBrowserTab::g_InfoInHtmlStub; BOOL GenerateImagemap = FALSE; BrowserPreviewOptions PreviewOptions(Bgr, ShowInfo, GenerateImagemap); //BrowserPreviewOptions PreviewOptions(PreviewInBrowserTab::GetBrowserOptions()); // tell it what spread to use when getting the document background PreviewOptions.SetSpread(m_pSpread); // This should actually preview it in the browser m_pBitmapData->GenerateHTMLStub(PreviewOptions); // Clean out the filter we created delete m_pBitmapFilter; m_pBitmapFilter = NULL; if (MadeBitmapOptions && pBmpOptions != NULL) delete pBmpOptions; return ExportedOk; } /******************************************************************************************** > OpState OpBrowserPreview::GetState(String_256*, OpDescriptor*) Author: Neville_Humphrys (Xara Group Ltd) Created: 20/6/97 Inputs: Name of the OpDescriptor being queried Outputs: The string to show to the user Returns: The state of the OpBrowserPreview operation Purpose: For finding the OpBrowserPreview's state. ********************************************************************************************/ /* OpState OpBrowserPreview::GetState(String_256 * pUIDescription, OpDescriptor * pOpDesc) { // This is always unavailable for the present moment OpState OpSt; OpSt.Greyed = TRUE; return OpSt; } */ /******************************************************************************************** > static BOOL OpBrowserPreview::RemoveTempFile() Author: Neville_Humphrys (Xara Group Ltd) Created: 7/7/97 Returns: True if worked correctly, False otherwise. Purpose: For cleaning up any temp file useage that we may have made. This should be called in the DeInit during program shut down. ********************************************************************************************/ BOOL OpBrowserPreview::RemoveTempFile() { // If we have used the m_TempPath during this session then ensure that we have cleaned up // any temp files String_256 Filename; Filename = m_TempPath.GetPath(); if (!Filename.IsEmpty() && m_TempPath.IsValid()) { FileUtil::DeleteFile(&m_TempPath); } return TRUE; } /******************************************************************************************** // End of OpBrowserPreview ********************************************************************************************/ #endif // EXCLUDE_FROM_XARALX