OpGrabFrame Class Reference

Performs an operation to grab the selected frame layer and preview it. More...

#include <frameops.h>

Inheritance diagram for OpGrabFrame:

Operation MessageHandler ListItem CCObject SimpleCCObject OpGrabAllFrames OpSaveAnimatedGIF OpBrowserPreview List of all members.

Public Member Functions

 OpGrabFrame ()
 Constructor.
 ~OpGrabFrame ()
 Destructor.
virtual void Do (OpDescriptor *pOpDesc)
 Tries to grab the selected animation frame (i.e. layer).
virtual void DoWithParam (OpDescriptor *pOpDesc, OpParam *Param)
 Regenerate the bitmap associated with the active frame layer.

Static Public Member Functions

static BOOL Init ()
 OpGrabFrame initialiser method.
static void DeInit ()
 De-Initialises OpGrabFrame.
static OpState GetState (String_256 *, OpDescriptor *)
 For finding the OpGrabFrame's state.

Protected Member Functions

virtual BOOL StartGrab ()
 Tries to set up useful items prior to doing the grab.
virtual KernelBitmapGrabFrame ()
 Tries to grab the currently selected frame/layer into a bitmap.
virtual KernelBitmapGrabTheFrame ()
 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.
virtual BOOL EndGrab ()
 Tries to clean up after doing the grab.
virtual BOOL GetFileNameFromUser ()
 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.
virtual BOOL PreviewAnimation ()
 Tries to preview the frames that have been grabbed. Uses the stored animation details in m_ExportParams.
virtual BOOL SaveOrShowTheAnimation (PreviewDialog *pPreviewDialog, BitmapExportParam *pExportParam)
 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 SetFullBitmapList (BOOL SetFlagState=FALSE)
BOOL SetSingleBitmapInList ()
BOOL SetBitmapToListTail ()
BOOL CheckIfSingleBitmap (Layer *pLayer, KernelBitmap **ppBitmap)
 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. 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. 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. 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.
BOOL CheckAllForSingleBitmaps (Spread *pSpread, GrabFrameFilter *pBitmapFilter)
 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.
virtual BitmapPreviewDataGetBitmapPreviewData ()
virtual BOOL RememberTheSelection ()
 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!
virtual BOOL PutBackTheSelection ()
 Tries to put back the remembered selection state at the start of the operation.

Protected Attributes

SelectionStatem_pSelState
GIFAnimationExportParam m_ExportParams
GrabFrameFilterm_pBitmapFilter
Documentm_pDocument
Spreadm_pSpread
Layerm_pLayer
DocViewm_pView
LPLOGPALETTE m_pBrowserPalette

Static Protected Attributes

static BitmapPreviewDatam_pBitmapData = NULL

Private Member Functions

 CC_DECLARE_DYNCREATE (OpGrabFrame)

Detailed Description

Performs an operation to grab the selected frame layer and preview it.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
22/4/97
See also:
-

Definition at line 535 of file frameops.h.


Constructor & Destructor Documentation

OpGrabFrame::OpGrabFrame  ) 
 

Constructor.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/4/97

Definition at line 1841 of file frameops.cpp.

01842 {
01843     m_pDocument     = NULL;
01844     m_pSpread       = NULL;
01845     m_pLayer        = NULL;
01846     m_pView         = NULL;
01847 
01848     m_pBitmapFilter = NULL;
01849     m_pSelState     = NULL;
01850 
01851     //m_pBitmapData = NULL;
01852 
01853     m_pBrowserPalette   = NULL;
01854 }

OpGrabFrame::~OpGrabFrame  ) 
 

Destructor.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/4/97

Definition at line 1866 of file frameops.cpp.

01867 {
01868     if (m_pBitmapFilter != NULL)
01869     {
01870         delete m_pBitmapFilter;
01871         m_pBitmapFilter = NULL;
01872     }
01873 
01874     if (m_pSelState != NULL)
01875     {
01876         delete m_pSelState;
01877         m_pSelState = NULL;
01878     }
01879 
01880     /* if (m_pBitmapData != NULL)
01881     {
01882         delete m_pBitmapData;
01883         m_pBitmapData = NULL;
01884     } */
01885 
01886     if (m_pBrowserPalette != NULL)
01887     {
01888         CCFree(m_pBrowserPalette);
01889         m_pBrowserPalette = NULL;
01890     }
01891 }


Member Function Documentation

OpGrabFrame::CC_DECLARE_DYNCREATE OpGrabFrame   )  [private]
 

BOOL OpGrabFrame::CheckAllForSingleBitmaps Spread pSpread,
GrabFrameFilter pBitmapFilter
[protected]
 

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.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
9/7/97
Parameters:
pLayer - the layer we need to check [INPUTS] pBitmapFilter - a grab frame filter we can use
Returns:
True if worked correctly, False otherwise.

Definition at line 2851 of file frameops.cpp.

02852 {
02853     ERROR2IF(pSpread == NULL, FALSE,"CheckIfSingleBitmap bad Spread pointer");
02854     ERROR2IF(pBitmapFilter == NULL, FALSE,"CheckIfSingleBitmap bad GrabFrameFilter pointer");
02855 
02856     // So we can do the optimised palette case, we must go though all the
02857     // layers/frames and see if there is a single bitmap present. We don't worry
02858     // about the palette on this first pass. We just set up the referenced bitmap
02859     // to be the single bitmap if it passes all the tests.
02860     KernelBitmap *  pBitmap = NULL;
02861     BOOL Found              = FALSE;
02862     BOOL SolidSet           = FALSE;
02863     BOOL OverlaySet         = FALSE;
02864     BOOL OverlayedBitmapSet = FALSE;
02865     Layer* pCurrentLayer    = pSpread->FindFirstFrameLayer();
02866     Layer* pNextLayer       = NULL;
02867     Layer* pPrevFrameLayer  = NULL;
02868     while (pCurrentLayer != NULL)
02869     {
02870         // Move to the next bitmap in the animation
02871         pNextLayer = pCurrentLayer->FindNextFrameLayer();
02872 
02873         // This is just as a double check
02874         if (pCurrentLayer->IsPseudoFrame())
02875         {
02876             Found = CheckIfSingleBitmap(pCurrentLayer, &pBitmap);
02877             // If the solid flag is set on anything but the last layer then note this
02878             // as dangerous
02879             if (pCurrentLayer->IsSolid() && pNextLayer != NULL)
02880                 SolidSet = TRUE;
02881             if (pCurrentLayer->IsOverlay())
02882             {
02883                 // If overlay is set then we can allow it if the previous bitmap has a restore
02884                 // type of overlay as this may be an animation that we have saved out
02885                 // and then loaded in. If a diff has happened then overlay will be set.
02886                 // We can only ever allow this if the layers consist of all bitmaps as
02887                 // otherwise the layer may be overlaying a vector layer and hence be wrong.
02888                 KernelBitmap * pPrevBitmap = NULL;
02889                 if (pPrevFrameLayer)
02890                     pPrevBitmap = pPrevFrameLayer->GetReferencedBitmap();
02891                 // Check that we have a single reuseable bitmap on this layer plus one of the previous
02892                 if (pPrevBitmap != NULL && pBitmap != NULL)
02893                 {
02894                     GIFDisposalMethod restore = pPrevBitmap->GetAnimationRestoreType();
02895                     // Do we include GDM_NONE? Not for now.
02896                     if (restore != GDM_LEAVE)
02897                     {
02898                         // We cannot use the bitmap so set the reference to NULL
02899                         pCurrentLayer->SetReferencedBitmap(NULL);
02900                         OverlaySet = TRUE;
02901                     }
02902                     else
02903                         OverlayedBitmapSet = TRUE;
02904                 }
02905                 else if (pPrevFrameLayer != NULL)
02906                 {
02907                     // If overlay set on the first frame then ignore
02908                     // We cannot use the bitmap so set the reference to NULL
02909                     pCurrentLayer->SetReferencedBitmap(NULL);
02910                     OverlaySet = TRUE;
02911                 }
02912             }
02913         }
02914 
02915         // Move to the next bitmap in the animation
02916         pPrevFrameLayer = pCurrentLayer;
02917         pCurrentLayer = pNextLayer;
02918     }
02919 
02920     // Find out about the palettes that the bitmaps have
02921     // Our filter has a useful function for this
02922     UINT32 ReqNumberOfColours   = m_ExportParams.GetNumColsInPalette();
02923     BOOL SamePalettes       = FALSE;
02924     BOOL OurBrowserPalette  = FALSE;
02925     BOOL AllHaveBitmaps     = FALSE;
02926     BOOL AllWithinCount     = FALSE; 
02927     UINT32 NumberOfColours  = ReqNumberOfColours;
02928     pBitmapFilter->CheckSingleBitmapsOnSpread(pSpread, &SamePalettes, &OurBrowserPalette, &AllHaveBitmaps,
02929                                               &AllWithinCount, &NumberOfColours);
02930 
02931     PALETTE_COLOURS Palette = m_ExportParams.GetPaletteCols();
02932     WEB_PALETTE WebPalette  = m_ExportParams.GetPalette();
02933     
02934     BOOL OptionsOk = FALSE;
02935     // If OverlaySet is true then we have found an overlay situation which we cannot cope with and
02936     // so will have set the referenced bitmap to null.
02937     if (OverlaySet && AllHaveBitmaps)
02938         AllHaveBitmaps = FALSE;
02939 
02940     // If solid is set on any of the frames then it is too dangerous to reuse any single bitmaps
02941     // We can only allow overlay, if all layers are single bitmaps and the bitmap concerned is
02942     // of type GDM_LEAVE. Otherwise, it is too dangerous.
02943     BOOL BitmapOverlayOk = TRUE;
02944     if (OverlayedBitmapSet && !AllHaveBitmaps)
02945         BitmapOverlayOk = FALSE;
02946 
02947     if (!SolidSet && BitmapOverlayOk)
02948     {
02949         // Check from the most fussy option to the least fussy option
02950         if (Palette == PALCOL_BROWSER && WebPalette == PAL_GLOBAL && OurBrowserPalette)
02951         {
02952             OptionsOk = TRUE;
02953             //TRACEUSER( "Neville", _T("Global browser, palettes ok\n"));
02954         }
02955         else if (Palette == PALCOL_OPTIMIZED && WebPalette == PAL_GLOBAL && SamePalettes && AllHaveBitmaps &&
02956                  NumberOfColours <= ReqNumberOfColours)
02957         {
02958             OptionsOk = TRUE;
02959             //TRACEUSER( "Neville", _T("Global opt, palettes ok\n"));
02960             // Force the global optimised palette to be null for now
02961             pBitmapFilter->SetGlobalOptimisedPalette(NULL);
02962         }
02963         else if (Palette == PALCOL_OPTIMIZED && WebPalette == PAL_LOCAL && AllWithinCount)
02964         {
02965             // Saving local palette so any palette ok but must be within the count
02966             OptionsOk = TRUE;
02967             //TRACEUSER( "Neville", _T("Local Opt, palettes ok\n"));
02968         }
02969     }
02970     
02971     // Now we need to go through the layers again and ratify our check
02972     pCurrentLayer = pSpread->FindFirstFrameLayer();
02973     pBitmap = NULL; 
02974     while (pCurrentLayer != NULL)
02975     {
02976         // This is just as a double check
02977         if (pCurrentLayer->IsPseudoFrame())
02978         {
02979             pBitmap = pCurrentLayer->GetReferencedBitmap();
02980             if (OptionsOk && pBitmap)
02981             {
02982                 // We can use the bitmap instead of generating one
02983                 // So make sure that the generated bitmap is clean out
02984                 pCurrentLayer->SetGeneratedBitmap(NULL);
02985                 // And ensure that the bitmap has the layer's delay
02986                 pBitmap->SetDelay(pCurrentLayer->GetFrameDelay());
02987 
02988                 // If we are in 
02989                 if (Palette == PALCOL_OPTIMIZED && WebPalette == PAL_GLOBAL)
02990                 {
02991                     // If we haven't set up the global optimised palette then do so now
02992                     // Pull it from the first bitmap that we find
02993                     LPLOGPALETTE pOptPal = pBitmapFilter->GetGlobalOptimisedPalette();
02994                     if (pOptPal == NULL)
02995                     {
02996                         pOptPal = DIBUtil::CopyBitmapPaletteIntoLogPalette(pBitmap);
02997                         // Something went a bit wrong
02998                         if (pOptPal == NULL)
02999                             return FALSE;
03000                         pBitmapFilter->SetGlobalOptimisedPalette(pOptPal);
03001                     }
03002                 }
03003             }
03004             else
03005             {
03006                 // We cannot use the bitmap so set the reference to NULL
03007                 pCurrentLayer->SetReferencedBitmap(NULL);
03008             }
03009         }
03010 
03011         // Move to the next bitmap in the animation
03012         pCurrentLayer = pCurrentLayer->FindNextFrameLayer();
03013     }
03014 
03015     return TRUE;
03016 }

BOOL OpGrabFrame::CheckIfSingleBitmap Layer pLayer,
KernelBitmap **  ppBitmap
[protected]
 

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. 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. 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. 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.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/6/97
Parameters:
pLayer - the layer we need to check [INPUTS]
The bitmap to use for this frame [OUTPUTS]
Returns:
True if found a single bitmap on the frame/layer. False otherwise.
See also:
CheckAllForSingleBitmaps;

Definition at line 2637 of file frameops.cpp.

02638 {
02639     ERROR2IF(pLayer == NULL, FALSE,"CheckIfSingleBitmap bad layer pointer");
02640     ERROR2IF(ppBitmap == NULL, FALSE,"CheckIfSingleBitmap bad bitmap pointer");
02641 
02642     // Get some of the current export options
02643     DocRect BoundingRect    = m_ExportParams.GetAnimationBoundingRect();
02644     ERROR3IF(BoundingRect.IsEmpty(),"Bounding rect not set up");
02645 //  PALETTE_COLOURS Palette = m_ExportParams.GetPaletteCols();
02646 //  WEB_PALETTE WebPalette  = m_ExportParams.GetPalette();
02647 
02648     KernelBitmap * pBitmap  = NULL;
02649     BOOL Scaled1to1         = FALSE;
02650     BOOL PaletteOk          = FALSE;
02651     BOOL InsideBoundingRect = TRUE;
02652     BOOL FullFirstFrame     = TRUE;
02653     UINT32 Bpp              = 0;
02654     INT32 NodeCount         = 0;
02655     NodeBitmap *pNodeBmp    = NULL;
02656 
02657     // check if we are the first animation frame, if so then we the bitmap must be the same
02658     // size as the animation bounding rect. Otherwise, the first frame will not be the size
02659     // of the animation which highlights a bug in MS IE 3.0
02660     Layer * pPreviousFrame = pLayer->FindPrevFrameLayer();
02661 
02662     Node * pNode = pLayer->FindFirstChild();
02663     while (pNode != NULL)
02664     {
02665         // If the node renders something on the screen then we count it as this will mean that
02666         // the single bitmap does not fully define the layer.
02667         // It ignores attributes, hidden nodes, etc - nodes that don't render anything themselves.
02668         if (pNode->IsBounded())
02669             NodeCount++;
02670 
02671         // We need to note any NodeBitmap nodes 
02672         if (pNode->IS_KIND_OF(NodeBitmap) && NodeCount == 1)
02673         {
02674             // Convert the node to a nodebitmap so we can get at the useful NodeBitmap
02675             // related data
02676             pNodeBmp = (NodeBitmap *)pNode;
02677             
02678             // Get the size and position of the node bitmap
02679             DocRect rect = pNodeBmp->GetBoundingRect(TRUE, FALSE);
02680 
02681             // If we have no previous frame then check that the first frame is the
02682             // size of the animation
02683             if (pPreviousFrame == NULL)
02684             {
02685                 DocRect AniBoundingRect = m_ExportParams.GetAnimationBoundingRect();
02686                 ERROR3IF(AniBoundingRect.IsEmpty(),"CheckIfSingleBitmap Animation bounding rect not set up!");
02687 
02688                 // REMEMBER account for rounding errors
02689                 const INT32 delta = 50;
02690                 if (
02691                     (AniBoundingRect.lo.x >= (rect.lo.x - delta)) && (AniBoundingRect.lo.x <= (rect.lo.x + delta)) &&
02692                     (AniBoundingRect.hi.x >= (rect.hi.x - delta)) && (AniBoundingRect.hi.x <= (rect.hi.x + delta)) &&
02693                     (AniBoundingRect.lo.y >= (rect.lo.y - delta)) && (AniBoundingRect.lo.y <= (rect.lo.y + delta)) &&
02694                     (AniBoundingRect.hi.y >= (rect.hi.y - delta)) && (AniBoundingRect.hi.y <= (rect.hi.y + delta))
02695                     )
02696                 {
02697                     FullFirstFrame = TRUE;
02698                 }
02699                 else
02700                 {
02701                     FullFirstFrame = FALSE;
02702                 }
02703             }
02704             
02705             // Get the bitmap stored inside the node, if any
02706             pBitmap = pNodeBmp->GetBitmap();
02707             if (pBitmap)
02708             {
02709                 // Get the width/height of the bitmap in millipoints
02710                 INT32 BmpWidth = pBitmap->GetRecommendedWidth();
02711                 INT32 BmpHeight = pBitmap->GetRecommendedHeight();
02712 
02713                 // Get the Width of the Bitmap in Millipoints
02714                 INT32 Width  = INT32(pNodeBmp->Parallel[0].Distance(pNodeBmp->Parallel[1]));
02715                 INT32 Height = INT32(pNodeBmp->Parallel[1].Distance(pNodeBmp->Parallel[2]));
02716 
02717                 // REMEMBER account for rounding errors and the orientation being the other
02718                 // way round
02719                 const INT32 delta = 2;
02720                 if ((Width >= BmpWidth - delta && Width <= BmpWidth + delta &&
02721                      Height >= BmpHeight - delta && Height <= BmpHeight + delta) ||
02722                     (Height >= BmpWidth - delta && Height <= BmpWidth + delta &&
02723                      Width >= BmpHeight - delta && Width <= BmpHeight + delta) )
02724                     Scaled1to1 = TRUE;
02725                 
02726                 Bpp = pBitmap->GetBPP();
02727 
02728                 // If the bitmap is 8bpp of less then assume this is ok for now
02729                 // We will check the palette in a second pass
02730                 if (Bpp <= 8)
02731                 {
02732                     PaletteOk = TRUE;
02733                 }
02734 
02735                 /*  // We cannot cope with GLOBAL OPTIMISED palettes at present as we
02736                     // would need to wait until the palette was generated before we could
02737                     // check.
02738                     if (Palette == PALCOL_OPTIMIZED && WebPalette == PAL_LOCAL)
02739                     {
02740                         // Saving local palette so any palette ok
02741                         PaletteOk = TRUE;
02742                     }
02743                     else if (Palette == PALCOL_BROWSER && WebPalette == PAL_GLOBAL)
02744                     {
02745                         // Check if we have a browser palette on this bitmap
02746                         //PaletteOk = pBitmap->IsBrowserPalette();
02747                         // Old way of testing. Too lenient as all it does it check that the palette
02748                         // has the correct colours in it, not that the palette will be the same one
02749                         // that we are going to output as the browser palette
02750                         
02751                         // Obviously, browser palettes can only happen on 8bpp bitmaps
02752                         if (Bpp == 8)
02753                         {
02754                             // First of all, if we haven't already got our palette that we check against
02755                             // then construct it.
02756                             if (m_pBrowserPalette == NULL)
02757                             {
02758                                 UINT32 PaletteSize = UINT32(pow(2,Bpp));
02759                                 m_pBrowserPalette = DIBUtil::AllocateLogPalette(PaletteSize);
02760                                 if (m_pBrowserPalette != NULL)
02761                                 {
02762                                     // Now force it into a browser compatible state
02763                                     BOOL AvoidSystemColours = TRUE;
02764                                     PaletteManager::MakePaletteBrowserCompatible(m_pBrowserPalette, AvoidSystemColours);
02765                                 }
02766                             }
02767                             
02768                             INT32 TransColour = -1;
02769                             pBitmap->GetTransparencyIndex(&TransColour);
02770 
02771                             if (m_pBrowserPalette != NULL)
02772                             {
02773                                 PaletteOk = pBitmap->ArePalettesTheSame(m_pBrowserPalette, TransColour);
02774                             }
02775                             else
02776                             {
02777                                 ERROR3("Couldn't allocate browser palette");
02778                                 PaletteOk = FALSE;
02779                             }
02780                         }
02781                         else
02782                             PaletteOk = FALSE;
02783                     }
02784                 } */
02785 
02786                 if (Scaled1to1 && PaletteOk && !rect.IsEmpty() && !BoundingRect.IsEmpty())
02787                 {
02788                     // Work out the position of the bitmap relative to the top left hand
02789                     // corner of the bounding rectangle in terms of pixels and put this
02790                     // in the bitmap 
02791                     MILLIPOINT LeftOffsetMP = rect.lo.x - BoundingRect.lo.x;
02792                     MILLIPOINT TopOffsetMP = BoundingRect.hi.y - rect.hi.y;
02793                     if (LeftOffsetMP >= 0 && TopOffsetMP >= 0)
02794                     {
02795                         const UINT32 dpi = 96;
02796                         UINT32 LeftOffset = LeftOffsetMP * dpi/72000;
02797                         UINT32 TopOffset = TopOffsetMP * dpi/72000;
02798 
02799                         pBitmap->SetLeftOffset(LeftOffset);
02800                         pBitmap->SetTopOffset(TopOffset);
02801                         InsideBoundingRect = TRUE;
02802                     }
02803                 }
02804             }
02805         }
02806 
02807         pNode = pNode->FindNext();
02808     }
02809 
02810     // If all these checks are TRUE then return the bitmap as the source of the frame
02811     if (pBitmap != NULL && Scaled1to1 && Bpp <= 8 && NodeCount == 1 &&
02812         PaletteOk && InsideBoundingRect && FullFirstFrame)
02813     {
02814         if (ppBitmap)
02815             *ppBitmap = pBitmap;
02816 
02817         // Make the layer remember this bitmap
02818         // Remember this bitmap as the reference one
02819         pLayer->SetReferencedBitmap(pBitmap);
02820 
02821         //TRACEUSER( "Neville", _T("Using single bitmap\n"));
02822 
02823         return TRUE;
02824     }
02825 
02826     // Ensure that we have no reference saved
02827     pLayer->SetReferencedBitmap(NULL);
02828             
02829     return FALSE;
02830 }

void OpGrabFrame::DeInit void   )  [static]
 

De-Initialises OpGrabFrame.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
3/7/97

Definition at line 1571 of file frameops.cpp.

01572 {
01573     // Deinit our static preview bitmap data pointer if allocated
01574     // This should clean up any temp files that we have used
01575     if (m_pBitmapData != NULL)
01576     {
01577         delete m_pBitmapData;
01578         m_pBitmapData = NULL;
01579     }
01580 
01581     // Give the browser preview chance to clean up its temp file useage
01582     OpBrowserPreview::RemoveTempFile();
01583 }

void OpGrabFrame::Do OpDescriptor pOpDesc  )  [virtual]
 

Tries to grab the selected animation frame (i.e. layer).

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/4/97
Parameters:
OpDescriptor (unused) [INPUTS]
- [OUTPUTS]
Returns:
-
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.

Reimplemented from Operation.

Reimplemented in OpGrabAllFrames.

Definition at line 1914 of file frameops.cpp.

01915 {
01916     DoWithParam(pOpDesc, NULL);
01917     return;
01918 }

void OpGrabFrame::DoWithParam OpDescriptor pOpDesc,
OpParam pParam
[virtual]
 

Regenerate the bitmap associated with the active frame layer.

Author:
Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com> (From Neville code.)
Date:
21/05/97
Parameters:
OpDescriptor (unused) [INPUTS] pParam - NULL - means grab the active frame
  • Param1 = pLayer - means grab the specified layer
- [OUTPUTS]
Returns:
-

Errors: -

See also:
-

Reimplemented from Operation.

Definition at line 1936 of file frameops.cpp.

01937 {
01938 //  ERROR3IF(pParam == NULL, "OpGrabFrame::DoWithParam - NULL Param passed in");
01939     
01940     // Get useful data and set up items before starting the grab process
01941     if (!StartGrab())
01942     {
01943         // We failed to grab the frame
01944         FailAndExecute();
01945         End();
01946         return; 
01947     } 
01948 
01949     // If a parameter has been supplied then this should be a layer pointer, which we
01950     // should then use to grab the frame
01951     // Otherwise, we assume we must grab the active frame (StartGrab sets m_pLayer to the active layer)
01952     if (pParam != NULL)
01953     {
01954         // recover the layer pointer that has been specified
01955         Layer* pLayer = (Layer *) (void *) pParam->Param1;
01956         if (pLayer)
01957         {
01958             ERROR3IF(!pLayer->IS_KIND_OF(Layer), "OpParam passed is not a Layer");
01959             
01960             // Note the layer we are expected to grab in our class variable
01961             m_pLayer = pLayer;
01962 
01963             // Set up the visibility of the other layers using this layer
01964             // as the new temporary and acting active layer
01965             FrameSGallery::FixOtherLayersFromActive(m_pLayer);
01966         }
01967     }
01968 
01969     // Are we trying to grab a hidden frame?
01970     if (m_pLayer->IsHiddenFrame())
01971     {
01972         // yes, tell the user
01973         InformError(_R(IDS_FRAMEISHIDDEN));
01974         //ERROR3IF(m_pLayer->IsHiddenFrame(),"OpGrabFrame::DoWithParam Frame is hidden");
01975         // and then fail
01976         FailAndExecute();
01977         End();
01978         return; 
01979     }
01980 
01981     // If required, allow the op to get a filename from the user.
01982     // This also allows them access to the options via the button on the save dialog box.
01983     // This is why we must do this first rather than after we have generated the frames.
01984     if (!GetFileNameFromUser())
01985     {
01986         // We failed to grab the frame
01987         FailAndExecute();
01988         End();
01989         return; 
01990     } 
01991 
01992     // Get our static pointer to the Preview Dialog.
01993     PreviewDialog* pPreviewDlg = PreviewDialog::GetPreviewDialog();
01994     // If the preview dialog is already open, find the selected frame layer.
01995     if (pPreviewDlg)
01996         pPreviewDlg->StopPreviewing();
01997     
01998     // Go and do the work to grab the frame
01999     KernelBitmap* pBitmap = GrabFrame();
02000     if (pBitmap == NULL)
02001     {
02002         // We failed to grab the frame.
02003         // Try and put back the selection that we recorded at the start
02004         PutBackTheSelection();
02005         FailAndExecute();
02006         End();
02007         return; 
02008     } 
02009 
02010     // If we have grabbed the non-active layer then make sure the active layer
02011     // is set up as current
02012     Layer *pActiveLayer = m_pSpread->FindActiveLayer();
02013     if (pActiveLayer && m_pLayer != pActiveLayer)
02014         FrameSGallery::FixOtherLayersFromActive(pActiveLayer);
02015 
02016     // Clean up after the grabbing process.
02017     if (!EndGrab())
02018     {
02019         // We failed to clean up after grabbing the frame.
02020         FailAndExecute();
02021         End();
02022         return; 
02023     } 
02024 
02025     // Add this bitmap and layer pairing to our export list
02026     if (!m_ExportParams.AddLayerAndBitmap(m_pLayer, pBitmap))
02027     {
02028         FailAndExecute();
02029         End();
02030         return; 
02031     }
02032 
02033     // Open the preview dialog, and display the selected frame.
02034     if(!PreviewAnimation())
02035     {
02036         // We failed to preview the bitmap
02037         FailAndExecute();
02038         End();
02039         return; 
02040     }
02041 
02042     // Finish the operation
02043     End(); 
02044 
02045     return;
02046 }

BOOL OpGrabFrame::EndGrab  )  [protected, virtual]
 

Tries to clean up after doing the grab.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/4/97
Parameters:
[INPUTS] 
Returns:
True if worked ok, False otherwise

Definition at line 2376 of file frameops.cpp.

02377 {
02378     // Try and put back the selection that we recorded at the start
02379     PutBackTheSelection();
02380 
02381     // Make sure that the new selection is up to date
02382     //Range * pSelRange = GetApplication()->FindSelection();
02383 /*  if (pSelRange == NULL || !DoInvalidateNodesRegions(*pSelRange, TRUE))
02384     {
02385         // We failed to invalidate the region
02386         return FALSE; 
02387     } */
02388 
02389 /*  // Recover the active layer again and make sure that it is being shown correctly.
02390     ERROR2IF(m_pSpread == NULL,FALSE,"bad spread in EndGrab()");
02391     Layer *pLayer = m_pSpread->FindActiveLayer();
02392     ERROR2IF(pLayer == NULL,"No active layer in EndGrab()")
02393     if (pLayer)
02394     {
02395         FrameSGallery::FixOtherLayersFromActive(pLayer);
02396     } */
02397 
02398     return TRUE;
02399 }

virtual BitmapPreviewData* OpGrabFrame::GetBitmapPreviewData  )  [inline, protected, virtual]
 

Definition at line 572 of file frameops.h.

00572 { return m_pBitmapData; }

BOOL OpGrabFrame::GetFileNameFromUser  )  [protected, virtual]
 

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.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/7/97
Returns:
True if worked ok, False otherwise

Reimplemented in OpSaveAnimatedGIF, and OpBrowserPreview.

Definition at line 2414 of file frameops.cpp.

02415 {
02416     // Baseclass version, do nothing
02417     return TRUE;
02418 }

OpState OpGrabFrame::GetState String_256 pUIDescription,
OpDescriptor pOpDesc
[static]
 

For finding the OpGrabFrame's state.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/4/97
Parameters:
Name of the OpDescriptor being queried [INPUTS]
The string to show to the user [OUTPUTS]
Returns:
The state of the OpGrabFrame operation

Errors: -

See also:
-

Reimplemented in OpSaveAnimatedGIF.

Definition at line 1600 of file frameops.cpp.

01601 {
01602 
01603     //The frame movement controls on the GIF animation bar now work on frames only.
01604     OpState OpSt;
01605 
01606 #ifdef WEBSTER
01607     String_256 DisableReason;
01608 
01609     // Is there a selected spread?
01610     Spread * pSpread = Document::GetSelectedSpread();
01611     if (pSpread)
01612     {
01613         // yes, so check if there is an active layer
01614         Layer * pLayer = pSpread->FindActiveLayer();
01615         if (pLayer)
01616         {
01617             // Ensure that we have some visible objects on the specified layer to render
01618             // Could use a range but easier just to check if there are visible objects on the page
01619             DocRect VisibleRect = pSpread->GetPageVisibleBounds();
01620             BOOL Empty = VisibleRect.IsEmpty();
01621             // If this frame has nothing visible on it then check if there are renderable objects
01622             // on any other frames in the animation.
01623             if (Empty)
01624             {
01625                 // Cannot assume that all the frame layers are actually frame layers so
01626                 // go through all those that might be frame layers.
01627                 Layer * pFrame = pSpread->FindFirstLayer();
01628                 while (pFrame && Empty)
01629                 {
01630                     if (pFrame->IsPseudoFrame() && pFrame->HasLayerGotRenderableChildren())
01631                         Empty = FALSE;
01632                         pFrame = pFrame->FindNextLayer();
01633                 }
01634             }
01635             if (pOpDesc && pOpDesc->Token != String(OPTOKEN_FRAME_GRABFRAME) && !Empty)
01636             {
01637                 // Cannot assume that all the frame layers are actually frame layers so
01638                 // go through all those that might be frame layers.
01639                 Layer * pFrame = pSpread->FindFirstLayer();
01640                 BOOL AllHidden = TRUE;
01641                 while (pFrame && AllHidden)
01642                 {
01643                     if (pFrame->IsPseudoFrame() && !pFrame->IsHiddenFrame())
01644                         AllHidden = FALSE;
01645                         pFrame = pFrame->FindNextLayer();
01646                 }
01647                 if (AllHidden)
01648                 {
01649                     OpSt.Greyed = TRUE; 
01650                     // Load reason why operation is disabled
01651                     DisableReason = String_256(_R(IDS_ALLFRAMESAREHIDDEN));
01652                     if (pUIDescription)
01653                         *pUIDescription = DisableReason;
01654                 }
01655                 else
01656                 {
01657                     // Yes, so we are allowed to grab the frame or all the frames
01658                     OpSt.Greyed = FALSE;
01659                 }
01660             }
01661             else if (pOpDesc && pOpDesc->Token == String(OPTOKEN_FRAME_GRABFRAME) && pLayer->IsHiddenFrame())
01662             {
01663                 // If we are the grab frame op then check that the current layer is not
01664                 // hidden. If so then disallow
01665                 OpSt.Greyed = TRUE; 
01666                 // Load reason why operation is disabled
01667                 DisableReason = String_256(_R(IDS_FRAMEISHIDDEN));
01668                 if (pUIDescription)
01669                     *pUIDescription = DisableReason;    
01670             }
01671             else if (!Empty)
01672             {
01673                 // Yes, so we are allowed to grab the frame or all the frames
01674                 OpSt.Greyed = FALSE;
01675             }
01676             else
01677             {
01678                 OpSt.Greyed = TRUE; 
01679                 // Load reason why operation is disabled
01680                 DisableReason = String_256(_R(IDS_NO_VISIBLE_OBJECTS));
01681                 if (pUIDescription)
01682                     *pUIDescription = DisableReason;            
01683             }           
01684         }
01685         else
01686         { 
01687             // No, so we are greyed
01688             OpSt.Greyed = TRUE;
01689         }
01690     }
01691     else 
01692     {
01693         // No selected spread, so we are greyed
01694         OpSt.Greyed = TRUE;
01695 
01696         // Load reason why operation is disabled
01697         DisableReason = String_256(_R(IDS_NO_DOC));
01698         if (pUIDescription)
01699             *pUIDescription = DisableReason;         
01700     }
01701 
01702 #else
01703     // Flag to determine the document mode.
01704     BOOL FrameMode = FALSE;
01705 
01706     // Get a ptr to the selected spread
01707     Spread* pSpread = Document::GetSelectedSpread();
01708 
01709     // Ensure a valid spread ptr.
01710     if(pSpread)
01711     {
01712         // Are there any frame layers?
01713         Layer* pFrameLayer = pSpread->FindFirstFrameLayer();    
01714 
01715         //If a frame layer exists, then this is an animation doc.
01716         if (pFrameLayer)
01717             FrameMode = TRUE;
01718     }
01719 
01720     if(FrameMode)
01721     {
01722         String_256 DisableReason;
01723 
01724         if (pSpread)
01725         {
01726             // yes, so check if there is an active layer
01727             Layer * pLayer = pSpread->FindActiveLayer();
01728 
01729             if (pLayer)
01730             {
01731                 // Ensure that we have some visible objects on the specified layer to render
01732                 // Could use a range but easier just to check if there are visible objects on the page
01733                 DocRect VisibleRect = pSpread->GetPageVisibleBounds();
01734                 BOOL Empty = VisibleRect.IsEmpty();
01735                 // If this frame has nothing visible on it then check if there are renderable objects
01736                 // on any other frames in the animation.
01737                 if (Empty)
01738                 {
01739                     // Cannot assume that all the frame layers are actually frame layers so
01740                     // go through all those that might be frame layers.
01741                     Layer * pFrame = pSpread->FindFirstLayer();
01742                     while (pFrame && Empty)
01743                     {
01744                         if (pFrame->IsPseudoFrame() && pFrame->HasLayerGotRenderableChildren())
01745                             Empty = FALSE;
01746                         
01747                         pFrame = pFrame->FindNextLayer();
01748                     }
01749                 }
01750 
01751                 if (pOpDesc && pOpDesc->Token != String(OPTOKEN_FRAME_GRABFRAME) && !Empty)
01752                 {
01753                     // Cannot assume that all the frame layers are actually frame layers so
01754                     // go through all those that might be frame layers.
01755                     Layer * pFrame = pSpread->FindFirstLayer();
01756                     BOOL AllHidden = TRUE;
01757                     while (pFrame && AllHidden)
01758                     {
01759                         if (pFrame->IsPseudoFrame() && !pFrame->IsHiddenFrame())
01760                             AllHidden = FALSE;
01761                         
01762                         pFrame = pFrame->FindNextLayer();
01763                     }
01764                     
01765                     if (AllHidden)
01766                     {
01767                         OpSt.Greyed = TRUE; 
01768                         // Load reason why operation is disabled
01769                         DisableReason = String_256(_R(IDS_ALLFRAMESAREHIDDEN));
01770                         if (pUIDescription)
01771                             *pUIDescription = DisableReason;
01772                     }
01773                     else
01774                     {
01775                         // Yes, so we are allowed to grab the frame or all the frames
01776                         OpSt.Greyed = FALSE;
01777                     }
01778                 }
01779                 else if (pOpDesc && pOpDesc->Token == String(OPTOKEN_FRAME_GRABFRAME) && pLayer->IsHiddenFrame())
01780                 {
01781                     // If we are the grab frame op then check that the current layer is not
01782                     // hidden. If so then disallow
01783                     OpSt.Greyed = TRUE; 
01784                     // Load reason why operation is disabled
01785                     DisableReason = String_256(_R(IDS_FRAMEISHIDDEN));
01786                     if (pUIDescription)
01787                         *pUIDescription = DisableReason;    
01788                 }
01789                 else if (!Empty)
01790                 {
01791                     // Yes, so we are allowed to grab the frame or all the frames
01792                     OpSt.Greyed = FALSE;
01793                 }
01794                 else
01795                 {
01796                     OpSt.Greyed = TRUE; 
01797                     // Load reason why operation is disabled
01798                     DisableReason = String_256(_R(IDS_NO_VISIBLE_OBJECTS));
01799                     if (pUIDescription)
01800                         *pUIDescription = DisableReason;            
01801                 }           
01802             }
01803             else
01804             { 
01805                 // No, so we are greyed
01806                 OpSt.Greyed = TRUE;
01807             }
01808         }
01809         else 
01810         {
01811             // No selected spread, so we are greyed
01812             OpSt.Greyed = TRUE;
01813 
01814             // Load reason why operation is disabled
01815             DisableReason = String_256(_R(IDS_NO_DOC));
01816             if (pUIDescription)
01817                 *pUIDescription = DisableReason;         
01818         }
01819     }
01820     else
01821     {
01822         // The document is layer based, so we are greyed.
01823         OpSt.Greyed = TRUE;
01824         *pUIDescription = String_256 (_R(IDS_NO_FRAMES));
01825     }
01826 #endif
01827 
01828     return OpSt;   
01829 }

KernelBitmap * OpGrabFrame::GrabFrame  )  [protected, virtual]
 

Tries to grab the currently selected frame/layer into a bitmap.

Author:
Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/4/97
Parameters:
[INPUTS] 
Returns:
KernelBitmap if worked ok, NULL otherwise

Definition at line 2204 of file frameops.cpp.

02205 {
02206     ERROR2IF(m_pDocument == NULL,FALSE,"GrabFrame bad document pointer");
02207     ERROR2IF(m_pSpread == NULL,FALSE,"GrabFrame bad spread pointer");
02208     ERROR2IF(m_pLayer == NULL,FALSE,"GrabFrame bad layer pointer");
02209     ERROR2IF(m_pView == NULL,FALSE,"GrabFrame bad view pointer");
02210 
02211     // Create a special Bitmap filter, that creates a bitmap
02212     // and puts it in the tree   
02213     ERROR3IF(m_pBitmapFilter != NULL,"Already have a pBitmapFilter!");
02214     m_pBitmapFilter = new GrabFrameFilter();
02215     if (m_pBitmapFilter == NULL)
02216     {
02217         return NULL; 
02218     }
02219 
02220     // Get the filter to work out the new rectangle 
02221     m_pBitmapFilter->SetUpClippingRectangleForExport(m_pSpread, DRAWING);
02222     DocRect NewBoundingRect = m_pBitmapFilter->GetClipRect();
02223     // Save away the new bounding rectangle
02224     m_pSpread->SetAnimationBoundingRect(NewBoundingRect);
02225     m_ExportParams.SetAnimationBoundingRect(NewBoundingRect);
02226 
02227     // Save away the quality that this was grabbed at
02228     Quality NewQuality = m_pView->RenderQuality;
02229     m_pSpread->SetAnimationQuality(NewQuality);
02230 
02231     // Check all the layers to see if they contain a single bitmap which we can use
02232     // instead of generating one.
02233     // This will mark all valid single bitmaps using the reference in the layer
02234     if (!CheckAllForSingleBitmaps(m_pSpread, m_pBitmapFilter))
02235     {
02236         delete m_pBitmapFilter;
02237         m_pBitmapFilter = NULL;
02238         return NULL; 
02239     } 
02240 
02241     // Check if we are grabbing a changed background layer frame, if it is then
02242     // we will then clear the edited bit on this. Once this happens then if the
02243     // user grabs all frames then the dependent frames wont be updated.
02244     if (m_pLayer->IsEdited() && m_pLayer->IsSolid())
02245     {
02246         // Mark all frames above this as edited until we reach the last frame
02247         // OR we hit a solid/background layer.
02248         Layer * pFrame = m_pLayer->FindNextFrameLayer();
02249         while (pFrame != NULL && !pFrame->IsSolid())
02250         {
02251             // Mark that frame as edited
02252             pFrame->SetEdited(