bitfilt.cpp

Go to the documentation of this file.
00001 // $Id: bitfilt.cpp 1762 2006-09-27 09:39:14Z luke $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 // Base class for bitmap filters (currently meaningful for export only)
00100 
00101 
00102 #include "camtypes.h"
00103 #include "bitfilt.h"
00104 
00105 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "resource.h" // _R(IDS_OUT_OF_MEMORY)
00107 //#include "camvw.h"                                // sadly
00108 #include "layer.h"
00109 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 #include "page.h"
00111 //#include "tim.h"
00112 #include "grndbmp.h"
00113 #include "osrndrgn.h"
00114 #include "nodebmp.h"
00115 #include "bitmpinf.h"
00116 #include "progress.h"
00117 //#include "nev.h"      // _R(IDN_USER_CANCELLED)
00118 //#include "bmpres.h"       // general bitmap filter based resources
00119 #include "prvwflt.h"
00120 #ifndef WEBSTER
00121 //#include "extfilts.h" // Accusoft filters
00122 #endif //WEBSTER
00123 //#include "selop.h"
00124 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00125 #include "bmpexdoc.h"
00126 #include "impexpop.h"
00127 #include "zoomops.h"
00128 //#include "will3.h"        // for _R(IDS_GENOPTPALMSGID)
00129 #include "nodetxtl.h"
00130 #include "qualattr.h"
00131 #include "ccbuffil.h"
00132 //#include "palman.h"
00133 #include "bmpprefs.h"
00134 #include "exjpeg.h"
00135 //#include "giffiltr.h"
00136 #include "grndbmp.h"
00137 
00138 #include "bmapprev.h"
00139 
00140 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00141 
00142 #include "filtimag.h"   //The imagemap filter class
00143 #include "filtrmgr.h"   //The Filter Manager - used to find the imagemap filter
00144 //#include "resimmap.h" //Imagemap resources
00145 //#include "clipint.h"  //To put text on the clipboard
00146 
00147 #include "htmlfltr.h"   //For HTMLFilter::ImportingHTML
00148 
00149 #include "sprdmsg.h"    // SpreadMsg
00150 #include "layermsg.h"   // UPDATE_ACTIVE_LAYER
00151 
00152 #include "fileutil.h"
00153 //#include "prevwres.h" // _R(IDS_DEFAULTFRAMENAME)
00154 //#include "will2.h"        // _R(IDS_K_EPSFILTER_IMPORTED)
00155 //#include "phil.h"
00156 //#include "simon.h"
00157 
00158 //#include "opbevel.h"  // for bevel tools
00159 //#include "registry.h"
00160 //#include "sliceres.h"
00161 
00162 #include "gpalopt.h"
00163 #include "colplate.h"
00164 #include "fillattr2.h"
00165 #include "nodetext.h"
00166 
00167 CC_IMPLEMENT_MEMDUMP(BitmapImportOptions, CC_CLASS_MEMDUMP)
00168 CC_IMPLEMENT_DYNAMIC(BaseBitmapFilter, BitmapFilter)
00169 
00170 // Declare smart memory handling in Debug builds
00171 #define new CAM_DEBUG_NEW
00172 
00173 GRenderBitmap*  BaseBitmapFilter::ExportRegion  = NULL; // The region used for export
00174 CCLexFile*      BaseBitmapFilter::OutputFile        = NULL; // The file used for output
00175 BOOL            BaseBitmapFilter::WrittenHeader     = FALSE;// Have we done the first strip yet
00176     
00177 UINT32          BaseBitmapFilter::SizeOfExport      = 100;  // defined progress bar size.
00178 UINT32          BaseBitmapFilter::OurNumNodes       = 0;    // our copy of the number of nodes being exported
00179 
00180 LPLOGPALETTE    BaseBitmapFilter::pOptimisedPalette         = NULL;
00181 
00182 BOOL            BaseBitmapFilter::WeAreGeneratingOptPalette = FALSE;
00183 
00184 const INT32     BaseBitmapFilter::MinPelsPerMeter   = 1000;     // Minimum Pels per meter allowed
00185 
00186 const INT32     BaseBitmapFilter::MinExportSize = 10;           // Minimum selection width/height allowed
00187 
00188 KernelBitmap*   BaseBitmapFilter::pExportBitmap = NULL;         // Store for the bitmap pointr in DoExportBitmap
00189 
00190 DPI             BaseBitmapFilter::m_DefaultExportDPI = 96.0;    // Used as the default DPI when exporting
00191 
00192 LPLOGPALETTE    BaseBitmapFilter::m_pBrowserPalette         = NULL;
00193 
00194 BOOL            BaseBitmapFilter::s_fZoomOnImport       = 9999;
00195 BOOL            BaseBitmapFilter::s_fWarnedZoomOnImport = 9999;
00196 
00197 //  This constant gives you the ( square of the ) maximum distance that a colour has to be from a browser colour
00198 //  to be snapped to that colour.
00199 const INT32 WEB_SNAP_OPTIMISED_DISTANCE_SQUARED = 25;
00200 
00201 void PixelAlignedFiddle(DocRect*);
00202 
00203 // Added by Craig Hamilton 29/8/00.
00204 INT32 BaseBitmapFilter::m_NumberOfPaletteEntries = 0;
00205 // End added.
00206 
00207 /********************************************************************************************
00208 
00209 >   BaseBitmapFilter::BaseBitmapFilter()
00210 
00211     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00212     Created:    28/6/94
00213     Purpose:    Constructor for an BaseBitmapFilter object.  The object should be initialised
00214                 before use. Base class version
00215     SeeAlso:    BaseBitmapFilter::Init
00216 
00217 ********************************************************************************************/
00218 
00219 BaseBitmapFilter::BaseBitmapFilter()
00220 {
00221     OutputFile = NULL;
00222     ExportRegion = NULL;
00223     pNewBitmap = NULL;
00224     InputFile = NULL;
00225     BackgroundRedrawState = FALSE;
00226     BackgroundRedrawStateSet = FALSE;
00227     ViewQualitySet = FALSE;
00228     IsPreviewBitmap = FALSE;
00229     pExportBitmap = NULL;
00230     pSpread = NULL;
00231     m_pImportOptions    = NULL;
00232     m_pExportOptions    = NULL;
00233     pOptimisedPalette = NULL;
00234 
00235     WrittenHeader       = FALSE;// Have we done the first strip yet
00236     RenderInStrips  = TRUE; // Should we render in strips or not
00237     RenderBottomToTop = TRUE;   // control over which way we render
00238     BadExportRender = FALSE;// whether the export rendering has gone ok or not
00239     
00240     SizeOfExport        = 100;  // defined progress bar size.
00241     OurNumNodes     = 0;    // our copy of the number of nodes being exported
00242 
00243     PaletteType     = PAL_OPTIMISED;
00244 
00245     //Should these lines be in or out - Martin 14/04/97
00246     PreviewDither   = XARADITHER_ERROR_DIFFUSION;
00247     PreviewPalette  = PAL_OPTIMISED;
00248                
00249     WeAreGeneratingOptPalette = FALSE;
00250     ClipRect.MakeEmpty();
00251 
00252     m_pOptimisedPalette2 = NULL;
00253     m_pExportOptions = NULL;
00254 }
00255 
00256 
00257 
00258 /********************************************************************************************
00259 
00260 >   BaseBitmapFilter::~BaseBitmapFilter()
00261 
00262     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00263     Created:    28/6/94
00264     Purpose:    Destructor for an BaseBitmapFilter object.
00265 
00266 ********************************************************************************************/
00267 
00268 BaseBitmapFilter::~BaseBitmapFilter()
00269 {
00270     //  Clear up some dynamically allocated memory
00271     if (m_pOptimisedPalette2)
00272     {
00273         CCFree(m_pOptimisedPalette2);
00274         m_pOptimisedPalette2 = 0;
00275     }
00276 
00277     if (m_pBrowserPalette)
00278     {
00279         CCFree(m_pBrowserPalette);
00280         m_pBrowserPalette = 0;
00281     }
00282 
00283     delete m_pImportOptions;
00284     m_pImportOptions = 0;
00285 
00286 //  delete m_pExportOptions;
00287     m_pExportOptions = 0;
00288 }
00289 
00290 
00291 
00292 /********************************************************************************************
00293 
00294 >   BOOL BaseBitmapFilter::InitBaseClass()
00295 
00296     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
00297     Created:    23/5/97
00298     Returns:    TRUE if the filter was initialized ok
00299                 FALSE otherwise
00300     Purpose:    Initialises any static member variables for the base bitmap filter
00301                 class
00302 
00303 ********************************************************************************************/
00304 BOOL BaseBitmapFilter::InitBaseClass()
00305 {
00306     if( 9999 == s_fZoomOnImport &&
00307         Camelot.DeclareSection( _T("Filters"), 10 ) )
00308     {
00309         s_fZoomOnImport = TRUE;
00310         s_fWarnedZoomOnImport = FALSE;
00311 
00312         Camelot.DeclarePref( NULL, _T("ZoomToFitOnImport"), &s_fZoomOnImport, FALSE, TRUE );
00313         Camelot.DeclarePref( NULL, _T("WarnedZoomToFitOnImport"), &s_fWarnedZoomOnImport, FALSE, TRUE );
00314     }
00315     
00316     return BitmapExportOptions::Declare();
00317 }
00318 
00319 
00320 /********************************************************************************************
00321 
00322 >   void BaseBitmapFilter::SetPreviewBitmap(BOOL IsPreviewBmp)
00323 
00324     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00325     Created:    2/2/95
00326     Inputs:     isPreviewBmp - TRUE if this bitmap we are saving is actually a Preview bitmap
00327                 FALSE if not.
00328     Purpose:    Allows you to set the state of this flag. Always set it back to FALSE after
00329                 the export as the filter hangs around, ready for the next export.
00330 
00331 ********************************************************************************************/
00332 
00333 void BaseBitmapFilter::SetPreviewBitmap(BOOL IsPreviewBmp)
00334 {
00335     IsPreviewBitmap = IsPreviewBmp;
00336 }
00337 
00338 
00339 /********************************************************************************************
00340 
00341 >   virtual BOOL BaseBitmapFilter::ExportVisibleLayersOnly()
00342 
00343     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00344     Created:    14/02/95
00345     Inputs:     -
00346     Outputs:    -
00347     Returns:    True if this filter wants to exclude invisible layers and so export only
00348                 visible items Or False if want to export everything.
00349     Purpose:    Determines if the filter wants to export only visible layers.
00350                 In the base bitmap filters class version the default action will be to
00351                 export only those layers which are visible.
00352     SeeAlso:    Filter::ExportRender;
00353 
00354 ********************************************************************************************/
00355 
00356 BOOL BaseBitmapFilter::ExportVisibleLayersOnly()
00357 {
00358     // only include all layer that are visible in this bitmap export
00359     return TRUE;
00360 }   
00361 
00362 
00363 /********************************************************************************************
00364 
00365 >   BOOL BaseBitmapFilter::IsSecondPassRequired()
00366 
00367     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00368     Created:    18/09/95
00369     Returns:    True if this filter wants a second export rendering pass and so have a chance
00370                 to setup semething like a mask. False if no second pass required.
00371     Purpose:    Determines if the a second rendering pass is required or not.
00372     SeeAlso:    DoExport;
00373 
00374 ********************************************************************************************/
00375 
00376 BOOL BaseBitmapFilter::IsSecondPassRequired()
00377 {
00378     return FALSE;
00379 }
00380 
00381 /********************************************************************************************
00382 
00383 >   virtual BOOL BaseBitmapFilter::IsDefaultDocRequired(const TCHAR* pcszPathName)
00384 
00385     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00386     Created:    9/10/95
00387     Inputs:     pcszPathName    pointer to the pathname to check
00388     Returns:    TRUE if the filter requires a default document, FALSE if not.
00389     Purpose:    Works out if opening a file of this type requires a default document to be
00390                 loaded. If the file format supplies the document then return FALSE otherwise
00391                 return TRUE. An example would be opening a bitmap file. This has no document
00392                 defined in the file format and so we need to laod the default document before
00393                 importing the bitmap into this file.
00394                 In this baseclass version return FALSE and hence assume that the filters that
00395                 need to will override this function to return TRUE.
00396     SeeAlso:    Filter; Filter::IsDefaultDocRequired; CCamDoc::OnOpenDocument;
00397     SeeAlso:    FilterFamily::DoImport; Filter::DoImport;
00398 
00399 ********************************************************************************************/
00400 
00401 BOOL BaseBitmapFilter::IsDefaultDocRequired(const TCHAR* pcszPathName)
00402 {
00403     // No need to check the pathname, just return TRUE as all currently known bitmap filters
00404     // will require the default document.
00405     return TRUE;
00406 }
00407 
00408 
00409 /********************************************************************************************
00410 
00411 >   virtual void BaseCamelotFilter::IncProgressBarCount(UINT32 n)
00412 
00413     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> (Markn)
00414     Created:    5/6/96
00415     Inputs:     n = amount to inc the progress bar count by
00416     Returns:    -
00417     Purpose:    Func to incrementing the progress bar count.
00418                 If there is a progress bar available, it is updated by this call.
00419     Scope:      Protected.
00420 
00421 ********************************************************************************************/
00422 BOOL BaseBitmapFilter::IncProgressBarCount(UINT32 n)
00423 {
00424     return TRUE;
00425 }
00426 
00427 
00428 /********************************************************************************************
00429 
00430 >   virtual void BaseBitmapFilter::SetTotalProgressBarCount(UINT32 n)
00431 
00432     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> (Markn)
00433     Created:    5/6/96
00434     Inputs:     n = amount to set the total progress bar count to
00435     Purpose:    Func to set total the progress bar count.
00436                 If there is a progress bar available, it is updated by this call.
00437     Scope:      Protected.
00438 
00439 ********************************************************************************************/
00440 void BaseBitmapFilter::SetTotalProgressBarCount(UINT32 n)
00441 {
00442     ERROR3IF(n == 0,"Should only be set to a value greater that 0");
00443 
00444     m_TotalProgressBarCount = n;
00445 }
00446 
00447 /********************************************************************************************
00448 
00449 >   virtual BitmapSource* BaseBitmapFilter::CreateBitmapSource(FilePos Size) const
00450 
00451     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00452     Created:    21/08/96
00453     Inputs:     Size: The required size of the BitmapSource
00454     Returns:    A pointer to a new BitmapSource
00455     Purpose:    The PrepareToImport() function calls this member to create a BitmapSource
00456                 for lossy file formats.
00457                 The BaseBitmapFilter implementation returns NULL.
00458                 Derived classes with lossy formats should override this function to provide
00459                 a subclassed BitmapSource.
00460     SeeAlso:    IsFormatLossy()
00461     Scope:      protected
00462 
00463 ********************************************************************************************/
00464 BitmapSource* BaseBitmapFilter::CreateBitmapSource(OFFSET Size) const
00465 {
00466     return NULL;
00467 }
00468 
00469 
00470 /********************************************************************************************
00471 
00472 >   BOOL BaseBitmapFilter::PrepareBitmapSource()
00473 
00474     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00475     Created:    21/08/96
00476     Returns:    TRUE if successful
00477                 FALSE otherwise
00478     Purpose:    The PrepareToImport() function calls this member to create a BitmapSource
00479                 for lossy file formats, and a CCLexFile to work with it.
00480     SeeAlso:    IsFormatLossy()
00481     Scope:      protected
00482 
00483 ********************************************************************************************/
00484 BOOL BaseBitmapFilter::PrepareBitmapSource()
00485 {
00486 #ifdef DO_EXPORT
00487     OFFSET offset = GetDataStartOffset();
00488     OFFSET size = InputFile->Size() - offset;
00489 
00490     // Create the actual BitmapSource object
00491     m_pBitmapSource = CreateBitmapSource(size);
00492     if (m_pBitmapSource == NULL || !m_pBitmapSource->IsOK())
00493     {
00494         Error::SetError(_R(IDS_OUT_OF_MEMORY));
00495         return FALSE;
00496     }
00497 
00498     // Check for errors but let CCFile report them
00499     InputFile->SetThrowExceptions(FALSE);
00500     InputFile->SetReportErrors(TRUE);
00501 
00502     // Ignore those superfluous bits at the start of the file
00503     InputFile->seekIn(offset);
00504     if (!InputFile->good())
00505     {
00506         return FALSE;
00507     }
00508 
00509     // Now create a file to fill our BitmapSource & provide the filter with something
00510     // to work with
00511     CCBufferFile* pBufferFile = new CCBufferFile(InputFile);
00512     if (pBufferFile == NULL || !pBufferFile->IsInited())
00513     {
00514         Error::SetError(_R(IDS_OUT_OF_MEMORY));
00515         return FALSE;
00516     }
00517 
00518     // We have a file, so attach out BitmapSource to it
00519     m_pBitmapSource->AttachToBufferFile(pBufferFile);
00520 
00521     // Now ditch our current InputFile in favour of the BitmapSource's one
00522     // We don't need InputFile again
00523     InputFile = (CCLexFile*)pBufferFile;
00524 #endif
00525 
00526     return TRUE;
00527 }
00528 
00529 
00530 /********************************************************************************************
00531 
00532 >   virtual BOOL BaseBitmapFilter::PrepareToImport()
00533 
00534     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00535     Created:    28/6/94
00536     Returns:    TRUE if succeeded, FALSE if not.
00537     Purpose:    Prepare to import bitmap data using this filter.  This sets up the filter
00538                 to a sensible state for reading.
00539     Errors:     Out of memory.
00540     SeeAlso:    BaseBitmapFilter::DoImport; BaseBitmapFilter::CleanUpAfterImport
00541     Scope:      Private
00542 
00543 ********************************************************************************************/
00544 
00545 BOOL BaseBitmapFilter::PrepareToImport()
00546 {
00547     ERROR2IF(InputFile == NULL, FALSE, "InputFile is NULL");
00548 
00549     // Assume we won't want a BitmapSource
00550     m_pBitmapSource = NULL;
00551 
00552 #ifdef DO_EXPORT
00553     // Do we need to keep the data to prevent it from deteriorating?
00554     if (IsFormatLossy())
00555     {
00556         // SetTotalProgressBarCount(InputFile->Size()); ...one day
00557         if (!PrepareBitmapSource())
00558         {
00559             return FALSE;
00560         }
00561     }
00562 #endif
00563     return TRUE;
00564 }
00565 
00566 /********************************************************************************************
00567 
00568 >   void BaseBitmapFilter::CleanUpAfterImport()
00569 
00570     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00571     Created:    28/6/94
00572     Purpose:    Cleans up the memory allocated by BaseBitmapFilter::PrepareToImport() - used
00573                 when the import process ends, either normally or abnormally.
00574     SeeAlso:    BaseBitmapFilter::PrepareToImport; BaseBitmapFilter::DoImport
00575     Scope:      Private
00576 
00577 ********************************************************************************************/
00578 
00579 void BaseBitmapFilter::CleanUpAfterImport()
00580 {
00581     TheDocument = NULL;
00582     
00583     //WEBSTER-Martin-02/01/97
00584 #ifndef WEBSTER
00585 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
00586     // Reset the filter type used by the Accusoft filters so that it can cache the
00587     // filter type correctly and so only call the Accusoft DLL on the first filter
00588     // rather than on all filters. 
00589 
00590     AccusoftFilters::ResetFilterType();
00591 
00592 #endif
00593 #endif //WEBSTER
00594 }
00595 
00596 /********************************************************************************************
00597 
00598 >   BitmapImportOptions* BaseBitmapFilter::GetImportOptions()
00599 
00600     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00601     Created:    22/11/94
00602     Inputs:     None
00603     Outputs:    None
00604     Returns:    A pointer to BitmapImportOptions with the options in it set.
00605                 NULL if an error occured.
00606     Purpose:    To allow a filter to offer the user a choice over what gets imported.
00607                 Derived BaseBitmapFilter classes should also derive a new BitmapImportOptions
00608                 class and return a new copy on the heap with the user options in it.
00609                 BaseBitmapFilter will delete the BitmapImportOptions class when no longer needed.
00610                 At present used by PhotoCD filter to get image to import.
00611     SeeAlso:    BaseBitmapFilter::PrepareToImport; BaseBitmapFilter::DoImport
00612     Scope:      Protected
00613 
00614 ********************************************************************************************/
00615 
00616 BitmapImportOptions* BaseBitmapFilter::GetImportOptions()
00617 {
00618     BitmapImportOptions* pOptions = new BitmapImportOptions;
00619     return pOptions;
00620 }
00621 
00622 
00623 /********************************************************************************************
00624 
00625  >  virtual BOOL BaseBitmapFilter::IsFormatLossy() const
00626 
00627     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00628     Created:    20/08/96
00629 
00630     Returns:    TRUE if the file format for the derived filter is lossy
00631             FALSE otherwise
00632 
00633     Purpose:    Provides information to the BaseBitmapFilter so that it knows whether
00634                 or not to provide a BitmapSource to prevent progressive degradation of
00635                 the bitmap when exported via the new file format.
00636     Notes:      Derived classes should override this function for their particular
00637                 implementation.
00638 
00639 ********************************************************************************************/
00640 BOOL BaseBitmapFilter::IsFormatLossy() const
00641 {
00642     return FALSE;
00643 }
00644 
00645 
00646 /********************************************************************************************
00647 
00648  >  virtual OFFSET BaseBitmapFilter::GetDataStartOffset() const
00649 
00650     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
00651     Created:    20/08/96
00652 
00653     Returns:    The offset from the HeaderStart parameter given in HowCompatible(), 
00654                 from which data essential to the correct functionality of this filter 
00655                 starts.
00656 
00657     Purpose:    Provides information to the BaseBitmapFilter, so that it knows where
00658                 to start any required BitmapSource. It will only be useful to derived 
00659                 classes that deal with a lossy file format.
00660     Notes:      The default implementation returns zero, assuming there is no useless 
00661                 garbage before any actual header. Derived classes should override this
00662                 for any special case.
00663 
00664     See Also:   IsFormatLossy()
00665 
00666 ********************************************************************************************/
00667 OFFSET BaseBitmapFilter::GetDataStartOffset() const
00668 {
00669     return 0;
00670 }
00671 
00672 
00673 /********************************************************************************************
00674 
00675 >   BOOL BaseBitmapFilter::DoImport(SelOperation *Op, CCLexFile* pFile, 
00676                                     Document *DestDoc, BOOL AutoChosen, ImportPosition *Pos,
00677                                     KernelBitmap** ppImportedBitmap,
00678                                     DocCoord* pPosTranslate, String_256* URL)
00679 
00680     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00681     Created:    28/6/94
00682     Inputs:     Op - pointer to the operation that this input process is associated with.
00683                 pFile - The file that we should load the bitmap from
00684                 DestDoc - The Document object which should hold the data read in from
00685                           the bitmap.
00686                 ImportPosition -
00687                 ppImportedBitmap - Used to set the bitmap background
00688                 pPosTranslate - specify the position of the bitmap on the screen
00689     Returns:    TRUE if the input operation worked ok, FALSE if not.
00690     Purpose:    Read bitmap data from a file. This is the same for all bitmap filters; 
00691                 the ImportBitmap() function should be over-ridden for actual bitmap
00692                 import filters.
00693     Errors:     Fails (returns FALSE) if the document structure is incorrect, or if there
00694                 is a problem with the bitmap.
00695 
00696 ********************************************************************************************/
00697 
00698 BOOL BaseBitmapFilter::DoImport(SelOperation *Op, CCLexFile* pFile, 
00699                                 Document *DestDoc, BOOL AutoChosen, ImportPosition *Pos,
00700                                 KernelBitmap** ppImportedBitmap,
00701                                 DocCoord* pPosTranslate, String_256* URL)
00702 {
00703     ERROR2IF(Op == NULL, FALSE,         "BaseBitmapFilter::DoImport NULL operation supplied");
00704     ERROR2IF(pFile == NULL, FALSE,  "BaseBitmapFilter::DoImport NULL diskfile supplied");
00705     ERROR2IF(DestDoc == NULL, FALSE,    "BaseBitmapFilter::DoImport NULL doc supplied");
00706 
00707     // Make a note of the disk file we are given
00708     InputFile = pFile;
00709 
00710     // Set up the class variable which is used by the bitmap system to determine which document
00711     // to load the bitmap into. Added 24/9/96 as opening a PhotoCD causes the selection to change!
00712     // Removing the photocd import dialog box causes the selection to be put into an existing doc
00713     // rather than a new one.
00714     TheDocument = DestDoc;
00715 
00716     if (ProcessImportOptions() == FALSE)
00717         return FALSE;
00718 
00719     Spread *pSpread = NULL;
00720     DocCoord Origin;
00721 
00722     //So first find the current view
00723     DocView* pDocView=DocView::GetCurrent();
00724         
00725     if (Pos == NULL)
00726     {
00727         // For now, position Draw objects on 1st page of spread 1
00728 
00729         //Graham 30/6/97: We now position imported bitmaps in the top left of the view
00730 
00731         ERROR2IF(pDocView==NULL, FALSE, "BaseBitmapFilter::DoImport - no current view");
00732 
00733         //And get the centre coordinate
00734         Origin=pDocView->GetTopLeftCoord();
00735 
00736         // Find the first spread in that document.
00737         pSpread = TheDocument->FindFirstSpread ();
00738     }
00739     else
00740     {
00741         pSpread = Pos->pSpread;
00742         Origin = Pos->Position;
00743     }
00744 
00745     // If we use the PhotoCD import then current/selected doc/spread MAY be wrong. So force it again.
00746     // Must ensure the selected spread is in the destination document as otherwise we will insert the
00747     // object AFTER the insertion node and hence in an illegal position. 
00748     Document::SetSelectedViewAndSpread(DestDoc, DocView::GetCurrent(), pSpread);
00749 
00750     // Let's get ready
00751     if (!PrepareToImport())
00752         return FALSE;
00753     
00754     UINT32 nBitmapToRead = 0;
00755     Layer* pNewLayer = NULL;
00756     Layer* pNewActiveLayer = NULL;
00757     do  // for every bitmap in the file
00758     {
00759         KernelBitmap* pKernelBmp = NULL;
00760         ++nBitmapToRead;
00761 
00762         // Import that bitmap, if first bitmap then nBitmapToRead will be set to 1
00763         BOOL Success = ImportBitmap(pFile, &pKernelBmp, nBitmapToRead);
00764         if (!Success)
00765         {
00766             if (m_pImportOptions != NULL)
00767             {
00768                 delete m_pImportOptions;
00769                 m_pImportOptions = NULL;
00770             }
00771 
00772             // Did not work - report this to the caller.
00773             return FALSE;
00774         }
00775 
00776         // If the caller wants to handle the imported bitmap, then set the return pointer up,
00777         // otherwise, we handle the bitmap by inserting a NodeBitmap into the document
00778         if (ppImportedBitmap != NULL && pPosTranslate == NULL)
00779             *ppImportedBitmap = pKernelBmp;
00780         else
00781         {
00782             // Get a new NodeBitmap object to import into.
00783             NodeBitmap *pNodeBitmap = new NodeBitmap;
00784             if ((pNodeBitmap == NULL) || (!pNodeBitmap->SetUpPath(12,12)))
00785             {
00786                 if (m_pImportOptions != NULL)
00787                 {
00788                     delete m_pImportOptions;
00789                     m_pImportOptions = NULL;
00790                 }
00791                 if (pNodeBitmap != NULL)
00792                     delete pNodeBitmap;
00793 
00794                 return FALSE;
00795             }
00796 
00797             pNodeBitmap->GetBitmapRef()->Attach(pKernelBmp, DestDoc); //GetDocument());
00798 
00799             if (pNodeBitmap->GetBitmap() != pKernelBmp)
00800             {
00801                 // It didn't use the bitmap we gave it, so we can delete it
00802                 delete pKernelBmp;
00803             }
00804 
00805             //And if the caller wants a pointer to the kernel bitmap, give them one...
00806             if (ppImportedBitmap)
00807             {
00808                 *ppImportedBitmap=pNodeBitmap->GetBitmap();
00809             }
00810 
00811             // Import worked - try to add the bitmap object into the tree.
00812             // First, set the rectangle to the right size for the bitmap...
00813             BitmapInfo Info;
00814             pNodeBitmap->GetBitmap()->ActualBitmap->GetInfo(&Info);
00815 
00816             const INT32 HPixelSize = ( pDocView->GetPixelWidth() + 0.5 ).MakeLong();    // Size of output pixel in millipoints
00817             const INT32 VPixelSize = ( pDocView->GetPixelHeight() + 0.5 ).MakeLong();// Size of output pixel in millipoints
00818 
00819             DocRect BoundsRect;
00820             BoundsRect.lo = Origin;
00821             // Make sure that this is snapped to a pixel grid
00822             BoundsRect.lo.x = GridLock(BoundsRect.lo.x, HPixelSize);
00823             BoundsRect.lo.y = GridLock(BoundsRect.lo.y, VPixelSize);
00824             // And now add in the rest of the bounds
00825             BoundsRect.hi.x = BoundsRect.lo.x + Info.RecommendedWidth;
00826             BoundsRect.hi.y = BoundsRect.lo.y + Info.RecommendedHeight;
00827             BoundsRect.hi.x = GridLock(BoundsRect.hi.x, HPixelSize);
00828             BoundsRect.hi.y = GridLock(BoundsRect.hi.y, VPixelSize);
00829 
00830             // And set this in our bitmap node
00831             pNodeBitmap->CreateShape(BoundsRect);
00832             
00833             // Make sure that there is a layer to put the bitmap onto
00834             if (!MakeSureLayerExists(DestDoc))
00835             {
00836                 // There is no layer and one could not be made, so we will have to fail
00837                 delete pNodeBitmap;
00838                 if (m_pImportOptions != NULL)
00839                 {
00840                     delete m_pImportOptions;
00841                     m_pImportOptions = NULL;
00842                 }
00843                 return FALSE;
00844             }
00845 
00846             // Set the default attrs
00847             // This MUST be done before the NodeBitmap is Inserted into the tree
00848             if (!pNodeBitmap->ApplyDefaultBitmapAttrs(Op))
00849             {
00850                 if (m_pImportOptions != NULL)
00851                 {
00852                     delete m_pImportOptions;
00853                     m_pImportOptions = NULL;
00854                 }
00855                 return FALSE;
00856             }
00857 
00858             // Insert the node, but don't invalidate its region
00859             // If we are the only bitmap then just add it as the first child of the active layer
00860             // Could use Filter::ImportWithLayers to determine if we use layers or not
00861             BOOL Fail = FALSE;
00862             BOOL SingleBitmap = !AreBitmapsToRead() && nBitmapToRead <= 1;
00863 
00864             //Graham 30/5/97
00865             //If we're importing an animated bitmap as part of an 
00866             //HTML document
00867 PORTNOTE("filters","Removed HTMLFilter usage")
00868             if( !SingleBitmap
00869 #ifndef EXCLUDE_FROM_XARALX
00870                 && HTMLFilter::ImportingHTML
00871 #endif
00872                 )
00873             {
00874                 //Then turn the "all layers visible" flag on in the document
00875                 DestDoc->SetMultilayer(TRUE);
00876                 DestDoc->SetAllVisible(TRUE);
00877             }
00878 
00879             if (SingleBitmap || !Filter::ImportBitmapsOntoLayers)
00880             {
00881                 // This inserts the node as the last child of the active layer
00882                 if (!Op->DoInsertNewNode(pNodeBitmap, pSpread, FALSE))
00883                 {
00884                     Fail = TRUE;
00885                     // It didn't work - delete the sub-tree we just created, and report error.
00886                     pNodeBitmap->CascadeDelete();
00887                     // Of course, Cascade delete does not actually delete the node itself, so now do that
00888                     delete pNodeBitmap;
00889                     pNodeBitmap = NULL;
00890                 }
00891             }
00892             else
00893             {
00894                 // We are not the only bitmap in the loading process so for each bitmap try and create
00895                 // a new layer and put the new bitmap there.
00896                 // The first layer should be added after the active layer.
00897                 // We could do this but this means that when multiple animations are being loaded you
00898                 // end up with the first frames close together rather than the two animations being
00899                 // separate.
00900                 if (!InsertBitmapOnNewLayer(Op, pSpread, pNodeBitmap, &pNewLayer))
00901                 {
00902                     Fail = TRUE;
00903                     // It didn't work - delete the sub-tree we just created, and report error.
00904                     pNodeBitmap->CascadeDelete();
00905                     // Of course, Cascade delete does not actually delete the node itself, so now do that
00906                     delete pNodeBitmap;
00907                     pNodeBitmap = NULL;
00908                 }
00909                 // Remember the layer we used for the first bitmap so that we can make it active
00910                 if (nBitmapToRead == 1)
00911                     pNewActiveLayer = pNewLayer;
00912 
00913                 // Let the filter set things up from the bitmap on the layer
00914                 // GIF filter can use disposal method to set overlay and solid flags
00915                 KernelBitmap * pBitmap = pNodeBitmap->GetBitmap();
00916                 SetFlagsFromBitmap(pNewLayer, pBitmap, nBitmapToRead);
00917             }
00918             // If we noted a failure then handle it now
00919             if (Fail)
00920             {
00921                 if (m_pImportOptions != NULL)
00922                 {
00923                     delete m_pImportOptions;
00924                     m_pImportOptions = NULL;
00925                 }
00926                 return FALSE;
00927             }
00928 
00929             // and move it to the correct location if we need to...
00930             DocCoord Offset(0,0);
00931             if (GetDragAndDropTranslation(Pos, BoundsRect, &Offset))
00932             {
00933                 // See if the bitmap contained an offset and if it did add it in
00934                 // Baseclass defaults to 0,0 offset
00935                 AddOffsetFromBitmap(&Offset);
00936                 
00937                 Offset.x = GridLock(Offset.x, HPixelSize);
00938                 Offset.y = GridLock(Offset.y, VPixelSize);
00939 
00940                 // Build the matrix and transform the bitmap to the correct place
00941                 Trans2DMatrix Xlate(Offset.x, Offset.y);
00942                 pNodeBitmap->Transform(Xlate);
00943             }
00944             else
00945             {
00946                 // No drag and drop - bitmap is currently positioned so its bottom left hand
00947                 // corner is at the top left of the page - translate it down by its height so
00948                 // that the top left corner of the bitmap is aligned to the top left corner
00949                 // of the page.
00950 
00951                 // Do we have an additional translation to apply?
00952                 if (pPosTranslate != NULL)
00953                 {
00954                     Offset.x = pPosTranslate->x;
00955                     Offset.y = pPosTranslate->y;
00956                 }
00957 
00958                 // See if the bitmap contained an offset as well and if it did add it in
00959                 // Baseclass defaults to 0,0 offset
00960                 AddOffsetFromBitmap(&Offset);
00961 
00962                 Offset.x = GridLock(Offset.x, HPixelSize);
00963                 Offset.y = GridLock(Offset.y, VPixelSize);
00964 
00965                 Trans2DMatrix Xlate(Offset.x, -(Info.RecommendedHeight) + Offset.y);
00966                 pNodeBitmap->Transform(Xlate);
00967             }
00968 
00969             // Invalidate the region
00970             Success = Op->DoInvalidateNodeRegion(pNodeBitmap, TRUE, FALSE);
00971             if (!Success)
00972             {
00973                 if (m_pImportOptions != NULL)
00974                 {
00975                     delete m_pImportOptions;
00976                     m_pImportOptions = NULL;
00977                 }
00978                 return FALSE;   // hmmm....
00979             }
00980     
00981             DocRect     docrectBounds = pNodeBitmap->GetBoundingRect();
00982             DocRect     docrectView = pDocView->GetDocViewRect( pSpread );
00983             pSpread->DocCoordToSpreadCoord( &docrectView );
00984             if( ( docrectBounds.lo.x < docrectView.lo.x ||
00985                   docrectBounds.lo.y < docrectView.lo.y ||
00986                   docrectBounds.hi.x > docrectView.hi.x ||
00987                   docrectBounds.hi.y > docrectView.hi.y ) &&
00988                 s_fZoomOnImport )
00989             {
00990                 // Calculate bounding rect of view plus new photo and then make sure that edges in
00991                 // in both axes grow by same amount. We make use of the fact that zoom code only allows
00992                 // zooming in both axes by the same amount, so we don't need to make sure that growth in
00993                 // both axes is by the same percentage.
00994                 docrectBounds = docrectBounds.Union( docrectView );
00995                 if( docrectView.lo.x - docrectBounds.lo.x > docrectBounds.hi.x - docrectView.hi.x )
00996                     docrectBounds.hi.x = docrectView.hi.x + docrectView.lo.x - docrectBounds.lo.x;
00997                 else
00998                     docrectBounds.lo.x = docrectView.lo.x - docrectBounds.hi.x + docrectView.hi.x;
00999                 if( docrectView.lo.y - docrectBounds.lo.y > docrectBounds.hi.y - docrectView.hi.y )
01000                     docrectBounds.hi.y = docrectView.hi.y + docrectView.lo.y - docrectBounds.lo.y;
01001                 else
01002                     docrectBounds.lo.y = docrectView.lo.y - docrectBounds.hi.y + docrectView.hi.y;
01003                 
01004                 OpZoomFitRectDescriptor* pOpDesc = (OpZoomFitRectDescriptor*)OpDescriptor::FindOpDescriptor( OPTOKEN_ZOOMRECT );
01005                 if( NULL != pOpDesc )
01006                 {
01007                     pOpDesc->SetZoomRect( docrectBounds );
01008                     pOpDesc->Invoke();
01009                 }
01010 
01011                 if( !s_fWarnedZoomOnImport )
01012                 {
01013                     ErrorInfo   Info;
01014                     memset( &Info, 0, sizeof(Info) );
01015                     Info.ErrorMsg   = _R(IDS_ZOOM_ON_IMAGE_IMPORT);
01016                     Info.Button[0]  = _R(IDS_OK);
01017                     Info.Button[1]  = _R(IDS_DONT_SHOW_AGAIN);
01018                     Info.OK         = 1;
01019                     if( _R(IDS_DONT_SHOW_AGAIN) == UINT32(InformMessage( &Info )) )
01020                         s_fWarnedZoomOnImport = TRUE;
01021                 }
01022             }
01023         }
01024     }
01025     while (AreBitmapsToRead());
01026 
01027     // If we have loaded bitmaps onto layers and hence requested a new active layer then set
01028     // it now.
01029     // Graham 1/8/97: If we are importing an animated GIF as part of an HTML page, we don't
01030     // change the active layer, because this may result in subsequent bitmaps in the HTML
01031     // page being imported on the wrong layer.
01032 PORTNOTE("filters","Removed HTMLFilter usage")
01033     if( pNewActiveLayer
01034 #ifndef EXCLUDE_FROM_XARALX
01035         && !HTMLFilter::ImportingHTML
01036 #endif
01037          )
01038     {
01039         // If the old active layer is blank and has nothing on it, then delete it
01040         Layer * pActiveLayer = pSpread->FindActiveLayer();
01041         if (pActiveLayer)
01042         { 
01043             // Scans the layer for children that render something on the screen.
01044             // It ignores attributes, hidden nodes, etc - nodes that don't render anything themselves.
01045             Node* pNode = pActiveLayer->FindFirstChild();
01046             BOOL ChildFound = FALSE;
01047             while (pNode != NULL && !ChildFound)
01048             {
01049                 ChildFound = pNode->IsBounded();
01050                 pNode = pNode->FindNext();
01051             }
01052             // Hide the old active layer
01053             if (!ChildFound)
01054                 Op->DoHideNode(pActiveLayer, TRUE);
01055         }
01056 
01057         // Check that all visible layers are actually frame layers as we have
01058         // created some new frame layers for each of the bitmaps.       
01059 PORTNOTE("dialog","Removed FrameSGallery usage")
01060 #ifndef EXCLUDE_FROM_XARALX
01061         FrameSGallery::MakeActiveLayer(pNewActiveLayer);
01062 #endif
01063         BROADCAST_TO_ALL( LayerMsg( pNewActiveLayer, LayerMsg::UPDATE_ACTIVE_LAYER ) );
01064 
01065         // Try and fix up the animation properties according to the bitmaps that have been loaded in
01066         SetAnimationPropertiesFromLoaded(pSpread);
01067     }
01068     
01069     // Ensure Sel Bounds are correct after translation
01070     GetApplication()->UpdateSelection();
01071 
01072     if (m_pImportOptions != NULL)
01073     {
01074         delete m_pImportOptions;
01075         m_pImportOptions = NULL;
01076     }
01077     // All ok
01078 
01079     return TRUE;
01080 }
01081 
01082 /********************************************************************************************
01083 
01084 >   BOOL BaseBitmapFilter::InsertBitmapOnNewLayer(SelOperation *pOp, Spread * pSpread, NodeBitmap *pNodeBitmap,
01085                                                   Layer ** ppNewLayer)
01086 
01087     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01088     Created:    6/5/97
01089     Inputs:     pOp             the operation to use to insert new items
01090                 pSpread         the spread we are using
01091                 pNodeBitmap     the new node bitmap which is to be inserted
01092     Outputs:    ppNewlayer      the new layer that was inserted (ready to be used next time around)
01093     Returns:    TRUE if everything was insert ok, FALSE otherwise.
01094     Purpose:    When loading in multiple bitmaps then each bitmap should be inserted onto
01095                 a new layer. The first bitmap is inserted as the last child on the active
01096                 layer. Each subsequent bitmap is loaded onto a new layer after this.
01097                 The routine returns the new layer so that this can be used next time as the
01098                 insertion point.
01099     SeeAlso:    BaseBitmapFilter::DoImport
01100 
01101 ********************************************************************************************/
01102 
01103 BOOL BaseBitmapFilter::InsertBitmapOnNewLayer(SelOperation *pOp, Spread * pSpread, NodeBitmap *pNodeBitmap,
01104                                               Layer ** ppNewLayer)
01105 {
01106     ERROR2IF(pOp == NULL || pSpread == NULL || pNodeBitmap == NULL || ppNewLayer == NULL,FALSE,"InsertBitmapOnNewLayer bad parameters!");
01107     
01108     Layer * pCurrentLayer = NULL;
01109     if (*ppNewLayer)
01110     {
01111         // We have been supplied with the last inserted new layer so use this.
01112         pCurrentLayer = *ppNewLayer;
01113     }
01114     else
01115     {
01116         // We are the first time through and so try and create
01117         // a layer after the active layer and put the bitmap there.
01118         // We could do this but we get problems when loading multiple animations. So 
01119         // do what we do elsewhere and load after the last layer.
01120         Layer * pInsertionLayer = pSpread->FindLastLayer();
01121 
01122         // No Active layer so get out now!
01123         if (pInsertionLayer == NULL)
01124             return FALSE;
01125 
01126         // Use the active layer as the insertion point
01127         pCurrentLayer = pInsertionLayer;
01128     }
01129 
01130     // Create the new layer
01131     Layer* pNewLayer = new Layer;
01132     if (pNewLayer == NULL)
01133         return FALSE;
01134 
01135     // Ensure that the layer name has a frame flavour about it
01136     // We also need to add an imported at the start so that if the original Frame 1
01137     // layer is deleted as it has nothing on it, then the layer is not called Frame 2
01138     // but Imported Frame 1
01139     String_256 LayerName(_R(IDS_K_EPSFILTER_IMPORTED));
01140     String_256 Suffix(_R(IDS_DEFAULTFRAMENAME));    // Frame
01141     LayerName += Suffix;
01142 PORTNOTE("dialog","Removed FrameSGallery usage")
01143 #ifndef EXCLUDE_FROM_XARALX
01144     String_256 NewLayerName = FrameSGallery::CreateUniqueLayerID(pSpread, &LayerName);
01145 #else
01146     String_256 NewLayerName = ""; 
01147 #endif
01148     pNewLayer->SetLayerID(NewLayerName);
01149 
01150     pNewLayer->SetVisible(TRUE);            // Ensure visible
01151     pNewLayer->SetLocked(FALSE);            // Ensure unlocked so insertion works
01152     pNewLayer->SetPrintable(FALSE); 
01153     pNewLayer->SetBackground(FALSE);        // Ensure it is foreground 
01154     pNewLayer->SetOutline(FALSE);
01155     pNewLayer->SetGuide(FALSE);
01156     pNewLayer->SetPageBackground(FALSE);
01157 #ifdef WEBSTER
01158     // In Webster mode, always make the new layer a frame layer
01159     pNewLayer->SetFrame(TRUE);              // Mark it as a frame layer
01160 #else
01161     // In Camelot mode, only make the new layer a frame layer if there are
01162     // already frame layers in the document
01163     Layer * pFrame = pSpread->FindFirstFrameLayer();
01164     if (pFrame != NULL)
01165         pNewLayer->SetFrame(TRUE);          // Mark it as a frame layer
01166     else
01167         pNewLayer->SetFrame(FALSE);         // Mark it as a layer
01168 #endif
01169     // Insert the new layer as the next node after the last page.
01170     if (!pOp->DoInsertNewNode(pNewLayer, pCurrentLayer, NEXT, FALSE,FALSE,FALSE,FALSE))
01171     {
01172         delete pNewLayer;
01173         pNewLayer = NULL;
01174         // Return the new layer to the caller
01175         *ppNewLayer = pNewLayer;
01176         return FALSE;
01177     }
01178 
01179     // And now insert the bitmap node into the new layer
01180     if (!pOp->DoInsertNewNode(pNodeBitmap, pNewLayer, FIRSTCHILD,FALSE,FALSE,FALSE,FALSE))
01181     {
01182         // It didn't work - hide the layer sub-tree we just created
01183         pOp->DoHideNode(pNewLayer, TRUE);
01184         // Return the new layer to the caller as null
01185         *ppNewLayer = NULL;
01186         // Assume the caller deletes the node bitmap
01187         return FALSE;
01188     }
01189 
01190     pNewLayer->SetVisible(FALSE);       // Ensure it is invisible
01191     pNewLayer->SetLocked(TRUE);         // Ensure locked 
01192 
01193     // Set the fact that this layer is presently fully defined by this bitmap
01194     KernelBitmap * pBitmap = pNodeBitmap->GetBitmap();
01195     pNewLayer->SetReferencedBitmap(pBitmap);
01196 
01197     pNewLayer->EnsureUniqueLayerID();
01198     BROADCAST_TO_ALL( SpreadMsg( pSpread, SpreadMsg::LAYERCHANGES ) );
01199 
01200     // Return the new layer to the caller
01201     *ppNewLayer = pNewLayer;
01202 
01203     return TRUE;
01204 }
01205 
01206 /********************************************************************************************
01207 
01208 >   virtual BOOL BaseBitmapFilter::SetFlagsFromBitmap(Layer * pLayer, KernelBitmap * pBitmap,
01209                                                       UINT32 nBitmapToRead)
01210 
01211     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01212     Created:    20/5/97
01213     Inputs:     pLayer          the layer that the bitmap is being put on
01214                 pBitmap         the bitmap being placed on the layer
01215                 nBitmapToRead   the number of the bitmap in the sequence
01216     Returns:    TRUE if was ok, FALSE otherwise.
01217     Purpose:    When loading in multiple bitmaps and placing them on new layers, we should
01218                 give the filter an opportunity to set the layer flags from the bitmap. In the
01219                 case of a GIF filter this would allow it to set the solid and overlay flags.
01220                 This baseclass version does nothing.
01221 
01222 ********************************************************************************************/
01223 
01224 BOOL BaseBitmapFilter::SetFlagsFromBitmap(Layer * pLayer, KernelBitmap * pBitmap,
01225                                           UINT32 nBitmapToRead)
01226 {
01227     // Do nothing
01228     return TRUE;
01229 }
01230 
01231 /********************************************************************************************
01232 
01233 >   BOOL BaseBitmapFilter::AddOffsetFromBitmap(DocCoord * pOffset)
01234 
01235     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01236     Created:    15/5/97
01237     Inputs:     pOffset         the present offset in the bitmap
01238     Returns:    TRUE if was ok, FALSE otherwise.
01239     Purpose:    When loading in a bitmap, the bitmap definition may contain an offset. We need
01240                 to add this to the offset that we are given so that the bitmap is loaded at
01241                 the correct position.
01242                 This baseclass version does nothing.
01243 
01244 ********************************************************************************************/
01245 
01246 BOOL BaseBitmapFilter::AddOffsetFromBitmap(DocCoord * pOffset)
01247 {
01248     // Do nothing
01249     return TRUE;
01250 }
01251 
01252 /********************************************************************************************
01253 
01254 >   virtual BOOL BaseBitmapFilter::SetAnimationPropertiesFromLoaded(Spread * pSpread)
01255 
01256     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01257     Created:    8/7/97
01258     Inputs:     pSpread     the spread that the bitmaps have been put on
01259     Returns:    TRUE if was ok, FALSE otherwise.
01260     Purpose:    When loading in multiple bitmaps and placing them on new layers, we should
01261                 give the filter an opportunity after all the bitmaps have been loaded, to go
01262                 and look at the bitmaps and set the animation properties accordingly.
01263                 In the case of a GIF filter this would allow it to set the dithering to none
01264                 and the palette to something closer to what has been loaded.
01265                 This baseclass version does nothing.
01266 
01267 ********************************************************************************************/
01268 
01269 BOOL BaseBitmapFilter::SetAnimationPropertiesFromLoaded(Spread * pSpread)
01270 {
01271     // Do nothing
01272     return TRUE;
01273 }
01274 
01275 /********************************************************************************************
01276 
01277 >   BOOL BaseBitmapFilter::ImportBitmap(CCLexFile* pDiskFile, KernelBitmap** ppBitmap)
01278 
01279     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01280     Created:    8/4/94
01281     Inputs:     -
01282     Returns:    TRUE if the bitmap was imported ok (or if it wasn't imported because the
01283                      file format does not support it;
01284                 FALSE if an error occured.
01285     Purpose:    -
01286     Errors:     Usual disk/file errors.
01287     SeeAlso:    CamelotEPSFilter::ExportBitmap
01288 
01289 ********************************************************************************************/
01290 
01291 BOOL BaseBitmapFilter::ImportBitmap(CCLexFile* pDiskFile, KernelBitmap** ppBitmap)
01292 {
01293     // Make a note of the disk file we are given
01294     InputFile = pDiskFile;
01295 
01296     if (ProcessImportOptions() == FALSE)
01297         return FALSE;
01298 
01299     // Let's get ready
01300     if (!PrepareToImport())
01301         return FALSE;
01302 
01303     if (!ImportBitmap(pDiskFile, ppBitmap, 1))
01304     {
01305         if (m_pImportOptions != NULL)
01306         {
01307             delete m_pImportOptions;
01308             m_pImportOptions = NULL;
01309         }
01310         return FALSE;
01311     }
01312     if (m_pImportOptions != NULL)
01313     {
01314         delete m_pImportOptions;
01315         m_pImportOptions = NULL;
01316     }
01317     return TRUE;
01318 }
01319 
01320 
01321 /********************************************************************************************
01322 
01323 >   BOOL BaseBitmapFilter::ImportBitmap(CCLexFile* pDiskFile, KernelBitmap** ppBitmap, const UINT32 nBitmapToRead)
01324 
01325     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01326     Created:    12/06/96
01327     Inputs:     pDiskFile - the CCLexFile from which the bitmap should be imported
01328                 nBitmapToRead - the position of the bitmap in the CCLexFile
01329     Outputs:    ppBitmap - a pointer to the KernelBitmap into which the bitmap will be
01330                 imported
01331     Returns:    TRUE if the bitmap was imported ok (or if it wasn't imported because the
01332                      file format does not support it;
01333                 FALSE if an error occured.
01334     Purpose:    Imports the nBitmapToRead'th bitmap from the given file.
01335                 This may be used to import a file either via the menu or from the EPS filters.
01336     Errors:     
01337     SeeAlso:    CamelotEPSFilter::ExportBitmap, DoImport(), SGLibOil::
01338 
01339 ********************************************************************************************/
01340 
01341 BOOL BaseBitmapFilter::ImportBitmap(CCLexFile* pDiskFile, KernelBitmap** ppBitmap, const UINT32 nBitmapToRead)
01342 {
01343     ERROR2IF(pDiskFile == NULL, FALSE, "pDiskFile - invalid");
01344     ERROR2IF(ppBitmap == NULL, FALSE, "ppBitmap is NULL");
01345     ERROR2IF(nBitmapToRead < 1, FALSE, "nBitmapToRead < 1");
01346 
01347     *ppBitmap = NULL;
01348     SetBitmapNumber(nBitmapToRead);
01349 
01350     KernelBitmap* KernelBmp;
01351     BOOL IsNew = TRUE;
01352 
01353     BOOL ReuseExisting = ShouldReuseExistingBitmaps();
01354     
01355     if (IsPreviewBitmap)    //for preview bitmaps always false
01356         ReuseExisting = FALSE;
01357 
01358     BOOL Success = KernelBitmap::ImportBitmap(this, NULL, 0, &KernelBmp, ReuseExisting ? &IsNew : NULL);
01359 
01360     if (Success && IsNew)
01361     {
01362         // Give the bitmap a name from the file path
01363         CreateBitmapName(pDiskFile, KernelBmp, nBitmapToRead);
01364 
01365         // If we have a BitmapSource then use it
01366         if (m_pBitmapSource != NULL)
01367         {
01368             KernelBmp->SetOriginalSource(m_pBitmapSource, this);
01369             delete InputFile;
01370             InputFile = NULL;
01371         }
01372     }
01373     else
01374     {
01375         // Throw away the source as we already have it or don't need it
01376         if (m_pBitmapSource != NULL)
01377         {
01378             delete m_pBitmapSource;
01379             delete InputFile;
01380             InputFile = NULL;
01381         }
01382     }           
01383 
01384     // Free up dynamic objects used for import and close the file
01385     CleanUpAfterImport();
01386 
01387     if (!Success)
01388     {
01389         // Did not work - report this to the caller.
01390         return FALSE;
01391     }
01392 
01393     *ppBitmap = KernelBmp;
01394 
01395     return TRUE;
01396 }
01397 
01398 
01399 /********************************************************************************************
01400 
01401 >   BOOL BaseBitmapFilter::ProcessImportOptions()
01402 
01403     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01404     Created:    12/06/96
01405     Inputs:     -
01406     Outputs:    -
01407     Returns:    TRUE if it is OK to continue processing
01408                 FALSE if an error occured or the user cancelled the import, in which case
01409                 Error::SetError is called signalling the fact.
01410     Purpose:    Validates the options returned by GetImportOptions
01411                 Sets m_pImportOptions if OK
01412                 Shouldn't really be overridden
01413     SeeAlso:    BaseBitmapFilter::DoImport()
01414 
01415 ********************************************************************************************/
01416 BOOL BaseBitmapFilter::ProcessImportOptions()
01417 {
01418     // Get any user options, if required
01419     ERROR3IF(m_pImportOptions != NULL, "m_pImportOptions not deleted");
01420     BitmapImportOptions* options = GetImportOptions();
01421     if (options == NULL)
01422     {
01423         ERROR3("options is NULL");
01424         return FALSE;
01425     }
01426     ERROR3IF(!options->IS_KIND_OF(BitmapImportOptions), "options is not");
01427     if (!options->m_bValid)
01428     {
01429         delete options;
01430         m_pImportOptions = NULL;
01431         return TRUE;
01432     }
01433     if (options->m_bCancelled)
01434     {
01435         delete options;
01436         m_pImportOptions = NULL;
01437         Error::SetError(_R(IDN_USER_CANCELLED),0);          // Expects error set on cancel
01438         return FALSE;                                   // if cancelled
01439     }
01440     m_pImportOptions = options;
01441     return TRUE;
01442 }
01443 
01444 
01445 /********************************************************************************************
01446 
01447 >   BOOL BaseBitmapFilter::CreateBitmapName(const CCLexFile* pDiskFile, const KernelBitmap* pBitmap,
01448                                          const UINT32 nBitmapNumber)
01449 
01450     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01451     Created:    18/06/96
01452     Inputs:     pDiskFile : file from which the bitmap was extracted
01453                 pBitmap : the bitmap itself
01454                 nBitmapNumber : the number of the bitmap in the file
01455     Outputs:    -
01456     Returns:    TRUE if name set OK, FALSE if failed.
01457     Purpose:    Sets the name of the given bitmap to that of the form "filename - number.ext"
01458                 or "filename.ext" depending on whether we have assumed there to be more than
01459                 one image in the imported file.
01460                 Used by ImportBitmap to supply this name and avoid bizarre file names when
01461                 re-exporting.
01462     Errors:     ERROR2 for invalid arguments
01463                 ERROR3 if pDiskFile is not a kind of CCDiskFile
01464     Notes:      Suppose we should really set the names after when we know that there actually 
01465                 are multiple bitmaps
01466 
01467 ********************************************************************************************/
01468 
01469 BOOL BaseBitmapFilter::CreateBitmapName(const CCLexFile* pDiskFile, const KernelBitmap* pBitmap,
01470                                          const UINT32 nBitmapNumber)
01471 {
01472     ERROR2IF(pDiskFile == NULL, FALSE, "pDiskFile - invalid");
01473     ERROR2IF(pBitmap == NULL, FALSE, "pBitmap - invalid");
01474 
01475     PathName Path = pDiskFile->GetPathName();
01476     if (!Path.IsValid())
01477     {
01478         TRACE( _T("Invalid file path in BaseBitmapFilter::CreateBitmapName\n") );
01479         return FALSE;
01480     }
01481 
01482     String_256 Str;
01483     if ((nBitmapNumber > 1) || AreBitmapsToRead())
01484     {
01485         // give it a number ?
01486         String_256 shortName = Path.GetFileName(FALSE); // without extension
01487         String_16 index;
01488         Convert::LongToString(INT32(nBitmapNumber), &index);
01489         Str.MakeMsg(_R(IDS_BITMAP_NAME), (TCHAR*)shortName, (TCHAR*)index);
01490         Path.SetFileName(Str);
01491     }
01492     Str = Path.GetFileName(TRUE);   // with extension
01493     pBitmap->ActualBitmap->SetName(Str);
01494     return TRUE;
01495 }
01496 
01497 
01498 /********************************************************************************************
01499 
01500 >   BOOL BaseBitmapFilter::ReadFromFile( OILBitmap* pOilBitmap )
01501 
01502     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01503     Created:    18/8/95
01504     Inputs:     pOilBitmap  pointer to the oil bitmap data to be filled in
01505     Outputs:    Will have filled in BMInfo  pointer to the bitmap header to fill in
01506                                     BMBytes pointer to the bitmap data to fill in
01507     Purpose:    Actually does the process of reading a bitmap from a file.
01508                 Inherited classes override this to read in different file formats.
01509                 
01510     Returns:    TRUE if worked, FALSE if failed.
01511 
01512 ********************************************************************************************/
01513 
01514 BOOL BaseBitmapFilter::ReadFromFile( OILBitmap* pOilBitmap )
01515 {
01516     ERROR3("Base class bitmap filter ReadFromFile called");
01517     return FALSE;
01518 }
01519 
01520 /********************************************************************************************
01521 
01522 >   virtual BOOL BaseBitmapFilter::ReadFromFile( OILBitmap* pOilBitmap,
01523                                                  BaseCamelotFilter *pFilter,
01524                                                  CCLexFile* pFile, BOOL IsCompressed)
01525 
01526     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01527     Created:    20/6/96
01528     Inputs:     pOilBitmap  pointer to the oil bitmap data to be filled in
01529                 pFilter         - the BaseCamelotFilter which provides functions like progress update
01530                 pFile           - the CCFile class to use to read the data from
01531                 IsCompressed    - Flag to say the bitmap is compressed or not.  
01532     Outputs:    Will have filled in BMInfo  pointer to the bitmap header to fill in
01533                                     BMBytes pointer to the bitmap data to fill in
01534     Purpose:    Actually does the process of reading a bitmap from a file.
01535                 Inherited classes override this to read in different file formats.
01536                 It is used by the web/native filters to pull out a bitmap definition from
01537                 inside a bitmap definition record.
01538                 IsCompressed is only used for BMP/BMPZIP type bitmaps at present.
01539                 Assumes:
01540                     pFile has already been opened up for reading
01541                     pFilter has been set up for reading the data e.g. progress bar 
01542     Returns:    TRUE if worked, FALSE if failed.
01543 
01544 ********************************************************************************************/
01545 
01546 BOOL BaseBitmapFilter::ReadFromFile(OILBitmap* pOilBitmap, BaseCamelotFilter* pFilter,
01547                                     CCLexFile* pFile, BOOL IsCompressed)
01548 {
01549     ERROR3("Base class bitmap filter ReadFromFile called");
01550     return FALSE;
01551 }
01552 
01553 /********************************************************************************************
01554 >   UINT32 BaseBitmapFilter::GetBitmapNumber() const
01555 
01556     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01557     Created:    11/06/96
01558     Inputs:     -
01559     Returns:    The next bitmap to read
01560                 0 if the bitmap number is invalid
01561     Purpose:    On entry to the filter this member function returns the number of the desired
01562                 bitmap in the file. Once the import is complete, either SetBitmapNumber is
01563                 called with an argument of the next bitmap that can be read or SetLastBitmap
01564                 is called indicating there are no more to read.
01565     Scope:      protected
01566     SeeAlso:    SetBitmapNumber(), SetLastBitmap(), ...ReadFromFile()
01567 
01568 ********************************************************************************************/
01569 UINT32 BaseBitmapFilter::GetBitmapNumber() const
01570 {
01571     return m_nBitmapToRead < 1 ? 0 : (UINT32) m_nBitmapToRead;
01572 }
01573 
01574 
01575 
01576 /********************************************************************************************
01577 >   BOOL BaseBitmapFilter::SetBitmapNumber(UINT32 nBitmapToRead)
01578 
01579     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01580     Created:    11/06/96
01581     Inputs:     -
01582     Returns:    TRUE if set OK
01583                 FALSE otherwise
01584     Purpose:    Once a filter has read a bitmap it should call this member function with
01585                 the number of the next bitmap that can be read. If there are none, 
01586                 SetLastBitmap() should be called instead.
01587     Scope:      protected
01588     SeeAlso:    SetLastBitmap(), GetBitmapNumber()
01589 
01590 ********************************************************************************************/
01591 BOOL BaseBitmapFilter::SetBitmapNumber(const UINT32 nBitmapToRead)
01592 {
01593     ERROR2IF(nBitmapToRead < 1, FALSE, "nBitmapToRead invalid");
01594     m_nBitmapToRead = nBitmapToRead;
01595     return TRUE;
01596 }
01597 
01598 
01599 /********************************************************************************************
01600 >   BOOL BaseBitmapFilter::SetLastBitmap()
01601 
01602     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01603     Created:    11/06/96
01604     Inputs:     -
01605     Returns:    TRUE if set OK
01606                 FALSE otherwise
01607     Purpose:    When the bitmap filter has no more bitmaps to read from its file it should
01608                 call this member function.
01609     Scope:      protected
01610     SeeAlso:    SetBitmapNumber(), GetBitmapNumber()
01611 
01612 ********************************************************************************************/
01613 BOOL BaseBitmapFilter::SetLastBitmap()
01614 {
01615     m_nBitmapToRead = -1;
01616     return TRUE;
01617 }
01618 
01619 
01620 /********************************************************************************************
01621 >   BOOL BaseBitmapFilter::AreBitmapsToRead() const
01622 
01623     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01624     Created:    11/06/96
01625     Inputs:     -
01626     Returns:    TRUE if there are bitmaps in the set OK
01627                 FALSE otherwise
01628     Purpose:    The BaseBitmapFilter uses this to determine whether or not it should try
01629                 to read another bitmap from the file.
01630     Scope:      protected
01631     SeeAlso:    GetBitmapNumber(), SetBitmapNumber(), SetLastBitmap()
01632 
01633 ********************************************************************************************/
01634 BOOL BaseBitmapFilter::AreBitmapsToRead() const
01635 {
01636     return (m_nBitmapToRead != -1);
01637 }
01638 
01639 
01640 /********************************************************************************************
01641 
01642 >   BOOL BaseBitmapFilter::SetPixelWidth(const BMP_SIZE& Width)
01643 
01644     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01645     Created:    29/10/96
01646     Inputs:     Width : The width of the bitmap to be exported in pixels
01647     Returns:    TRUE if the operation was successful
01648                 FALSE otherwise
01649     Purpose:    Support function to obtain bitmap info
01650     See Also:   GetExportHeight()
01651 
01652 ********************************************************************************************/
01653 BOOL BaseBitmapFilter::SetPixelWidth(const BMP_SIZE& Width)
01654 {
01655     m_PixelWidth = Width;
01656     return TRUE;
01657 }
01658 
01659 
01660 /********************************************************************************************
01661 
01662 >   BMP_SIZE BaseBitmapFilter::GetPixelWidth() const
01663 
01664     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01665     Created:    29/10/96
01666     Returns:    The width of the bitmap to export in pixels
01667     Purpose:    Support function to obtain bitmap info
01668 
01669 ********************************************************************************************/
01670 BMP_SIZE BaseBitmapFilter::GetPixelWidth() const
01671 {
01672     return m_PixelWidth;
01673 }
01674 
01675 
01676 /********************************************************************************************
01677 
01678 >   BMP_SIZE BaseBitmapFilter::GetPixelHeight() const
01679 
01680     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01681     Created:    29/10/96
01682     Returns:    The height of the bitmap to export in pixels
01683     Purpose:    Support function to obtain bitmap info
01684 
01685 ********************************************************************************************/
01686 BMP_SIZE BaseBitmapFilter::GetPixelHeight() const
01687 {
01688     return m_PixelHeight;
01689 }
01690 
01691 
01692 /********************************************************************************************
01693 
01694 >   virtual BOOL BaseBitmapFilter::SetPixelHeight(const BMP_SIZE& Height)
01695 
01696     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01697     Created:    29/10/96
01698     Inputs:     Height : The pixel height of the bitmap to be exported
01699     Returns:    TRUE if the operation was successful
01700                 FALSE otherwise
01701     Purpose:    Support function to obtain bitmap info
01702     See Also:   GetExportHeight()
01703 
01704 ********************************************************************************************/
01705 BOOL BaseBitmapFilter::SetPixelHeight(const BMP_SIZE& Height)
01706 {
01707     m_PixelHeight = Height;
01708     return TRUE;
01709 }
01710 
01711 
01712 /********************************************************************************************
01713 
01714 >   BOOL BaseBitmapFilter::GetExportOptions(* pOptions)
01715 
01716     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
01717     Created:    12/11/96
01718     Inputs:     pOptions : A pointer to some BitmapExportOptions
01719     Outputs:    pOptions : the same with some extra information in it
01720     Returns:    TRUE if OK
01721                 FALSE if user pressed Cancel.
01722 
01723     Purpose:    Allows the user to be prompted to get export information which should be set
01724                 in the given BitmapExportOptions.
01725 
01726     Notes:      Due to the existence of three public entry points into bitmap filters, 
01727                 two of which are virtual, the BaseBitmapFilter::WriteBitmapToFile may not 
01728                 be called and so may not create a BitmapExportOptions object, which would 
01729                 not be disasterous in itself, unless a derived class calls BaseBitmapFilter 
01730                 functions which use BitmapExportOptions. It is therefore at the filter 
01731                 author's discretion whether or not to create one of these objects.
01732 
01733     Scope:      protected
01734 
01735 ********************************************************************************************/
01736 BOOL BaseBitmapFilter::GetExportOptions(BitmapExportOptions* pOptions)
01737 {
01738 #if !defined(EXCLUDE_FROM_RALPH)
01739     ERROR2IF(pOptions == NULL, FALSE, "NULL Args");
01740 
01741     WrittenHeader = FALSE;
01742 
01743     // When saving a bitmap directly then only use the dialog box for certain filter types
01744     // as it will be just requesting compression type and hence otherwise it is superfluous.
01745     // Otherwise, always use it.
01746     BOOL Ok = TRUE;
01747     if (pOptions->GetSelectionType() != ABITMAP)
01748     {
01749         // This is ok as we are using a modal dialog box
01750 PORTNOTE("export", "Remove BmpPrefsDlg usage")
01751 #if !defined(EXCLUDE_FROM_XARALX)
01752         Ok = BmpPrefsDlg::InvokeDialog(pOptions);
01753 #endif
01754     }
01755 
01756     if (Ok)
01757     {
01758         // Only save the depth as the default if not saving a bitmap itself
01759         // from say the bitmap gallery. (keep this rubbish for now...)
01760         if (pOptions->GetSelectionType() != ABITMAP && pOptions->GetSelectionType() != SOMEBITMAPS)
01761         {
01762             pOptions->SetAsDefaults();
01763         }
01764         PaletteType     = PAL_OPTIMISED;
01765     }
01766 
01767     // Return with the ok/cancel state used on the dialog box
01768     return Ok;
01769 #else
01770     return FALSE;
01771 #endif
01772 }
01773 
01774 
01775 // SMFIX sjk 5/12/00 there used to be some junk in the call to GetExportOptions that assumed the
01776 // filter type being used which could be changed by the GetExportOptions call itself
01777 // therefore all this sort of stuff should be called on the correct known filter using this
01778 // call afterwards
01779 void BaseBitmapFilter::PostGetExportOptions(BitmapExportOptions* pOptions)
01780 {
01781     pOptions->SetAsDefaults();
01782 }
01783 
01784 
01785 
01786 
01787 /********************************************************************************************
01788 
01789  >  virtual BOOL BaseBitmapFilter::SetUpClippingRectangleForExport(Spread *pSpread, SelectionType Selection)
01790 
01791     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01792     Created:    29/4/97
01793     Inputs:     pSpread     the spread to export
01794                 Selection   the selection type to use during export
01795     Returns:    TRUE if the operation was successful
01796                 FALSE otherwise
01797     Purpose:    Sets up the class variable ClipRect to be the clipping rectangle to be used
01798                 during export.
01799     See Also:   PrepareToExport()
01800 
01801 ********************************************************************************************/
01802 
01803 BOOL BaseBitmapFilter::SetUpClippingRectangleForExport(Spread *pSpread, SelectionType Selection)
01804 {
01805     ERROR2IF(pSpread == NULL,FALSE,"SetUpClippingRectangleForExport Bad spread");
01806 
01807     // We need to decide what clipping rectangle to set up which we will then render the
01808     // bitmap through. The choice might be to export:-
01809     // - the selection bounds (if there is a selection),
01810     // - or the current spread
01811     // - or the current drawing
01812     // First, check if there is a selection present. ClipRect should be empty if not.
01813 
01814     // Karim 17/07/2000
01815     // We need to take controller nodes into account when we're finding this bbox,
01816     // which means temporarily setting PromoteToParent on the selection.
01817     SelRange* pSel = GetApplication()->FindSelection();
01818     if (pSel != NULL)
01819     {
01820         ClipRect = pSel->GetBoundingRect(TRUE);
01821     }
01822 
01823     // However, if this is a Preview Bitmap then use the spreads bounds as the clip rect
01824     // This should in fact be the bounding rectangle of all visible layers in the current
01825     // drawing.
01826     if (IsPreviewBitmap || (Selection==DRAWING))
01827     {
01828         // Work out the size of the rectangle encompassing the drawing (visible layers only)
01829         ClipRect = GetSizeOfDrawing(pSpread);
01830     }
01831 
01832     if (!IsPreviewBitmap && (Selection==SELECTION))
01833     {
01834         // Quick check to make sure the selection is something sensible ...
01835         SelRange* pSel = GetApplication()->FindSelection();
01836         if (pSel && 
01837             pSel->Count()==1)
01838         {
01839             // Only one thing selected ... Is it the Text Caret per chance ?
01840             Node* pSelNode = pSel->FindFirst();
01841             if (pSelNode && pSelNode->IsAVisibleTextNode())
01842             {
01843                 VisibleTextNode* pTextNode = (VisibleTextNode*)pSelNode;
01844                 if (pTextNode->IsACaret())
01845                 {
01846                     // Aha! It's the Caret that's selected.
01847 
01848                     // We'll use the bounds of the parent text line instead then ...
01849                     Node* pTextLine = pTextNode->FindParent();
01850                     ERROR3IF(!IS_A(pTextLine, TextLine), "Caret doesn't have a parent text line in DoCreateBitmap");
01851                 
01852                     // Get the bounds of the text line
01853                     ClipRect = ((TextLine*)pTextLine)->GetBoundingRect();               
01854                     Selection = DRAWING;
01855                 }               
01856             }
01857         }
01858     }
01859 
01860     // If this is the Preview bitmap, then we have to check for too big and too small cases
01861     if (IsPreviewBitmap)
01862     {
01863         // Find out how big the preview is at the moment
01864         MILLIPOINT Width = ClipRect.Width();
01865         MILLIPOINT Height = ClipRect.Height();
01866 
01867         // Note from Martin: This is probably a bodge connected with the scaling bodge which
01868         // has been corrected below, but I'm leaving this one in cos it leaves a nice 1 pixel
01869         // boarder round the thumbnail.
01870         // Inflate the rect a little as we can get odd clipping effects at the edges otherwise
01871         ClipRect.Inflate(Width/128, Height/128);
01872         
01873         // Define what too big and too small are
01874         // bigger the 2 feet or smaller than 1/2 inch
01875         MILLIPOINT MaxWidth = 72000 * 12 * 2;
01876         MILLIPOINT MinWidth = 72000 / 2;
01877 
01878         // See if the rectangle is too big or too small and fix it if it is
01879         MILLIPOINT WidthChange = 0;
01880         MILLIPOINT HeightChange = 0;
01881         // too big?
01882         WidthChange = Width>MaxWidth ? (MaxWidth - Width)/2 : 0;    // a -ve number
01883         HeightChange = Height>MaxWidth ? (MaxWidth - Height)/2 : 0; // a -ve number
01884         // too little?
01885         WidthChange = Width<MinWidth ? (MinWidth - Width)/2 : 0;    // a +ve number
01886         HeightChange = Height<MinWidth ? (MinWidth - Height)/2 : 0; // a +ve number
01887         // Shrink or expand the clip rect
01888         if ( WidthChange || HeightChange )
01889             ClipRect.Inflate( WidthChange, HeightChange );
01890     }
01891 
01892     return TRUE;
01893 }
01894 
01895 
01896 /********************************************************************************************
01897 
01898 >   BOOL BaseBitmapFilter::PrepareToExport(Spread *pSpread, UINT32 Depth, double DPI,
01899                                             SelectionType Selection,
01900                                             UINT32 Dither = XARADITHER_ORDERED_GREY)
01901 
01902     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01903     Created:    28/6/94
01904     Inputs:     Pointer to the spread, colour depth in bpp, resolution in dpi and a selection
01905                 flag which indicates whether there is a selection present (=1), no selection
01906                 (=0) and if there is a selection whether we want to export the spread instead
01907                 (=2).
01908     Returns:    TRUE if succeeded, FALSE if not (e.g. no memory)
01909     Purpose:    Prepare to export bitmap data using this filter.  This sets up the filter
01910                 to a sensible state for reading. Assumes file is opened by caller. This
01911                 should NOT be overridden by inherited classes.
01912     Errors:     Out of memory.
01913     SeeAlso:    BaseBitmapFilter::DoImport; BaseBitmapFilter::CleanUpAfterImport
01914     Scope:      Private
01915 
01916 ********************************************************************************************/
01917 
01918 #define PIXELWIDTH 750      // @ 96DPI @ 100%
01919 #define PIXELHEIGHT 750     // @ 96DPI @ 100%
01920 
01921 BOOL BaseBitmapFilter::PrepareToExport(Spread *pSpread, UINT32 Depth, double DPI,
01922                                        SelectionType Selection, UINT32 Dither)
01923 {
01924 #ifdef DO_EXPORT
01925     ERROR2IF(pSpread==NULL,FALSE,"BaseBitmapFilter::PrepareToExport null spread pointer");
01926 
01927     // Check whether the selection contains objects that can't be represented
01928     // in a bitmap
01929     if (WarnIfIncompatible()==FALSE)
01930     {
01931         ERRORIF(TRUE, _R(IDN_USER_CANCELLED), FALSE);
01932     }
01933 
01934     // We need to decide what clipping rectangle to set up which we will then render the
01935     // bitmap through. The choice might be to export:-
01936     // - the selection bounds (if there is a selection),
01937     // - or the current spread
01938     // - or the current drawing
01939     // Ask the virtual function to set it up for us
01940 
01941     if (ClipRect.IsEmpty())
01942         SetUpClippingRectangleForExport(pSpread, Selection);
01943 
01944     // We can either have no selection present whereby the user may have chosen to export
01945     // the spread or the drawing OR we have a selection present whereby the user may have
01946     // chosen to export the spread or drawing instead. In the later case we must output the
01947     // spread instead of the selection but double check there is a selection. 
01948     if (ClipRect.IsEmpty() || ClipRect.Width() < MinExportSize || ClipRect.Height() < MinExportSize ||
01949         ((Selection==SPREAD) && (!IsPreviewBitmap)))
01950     {
01951         // Use our function to work out the size of the spread
01952         ClipRect = GetSizeOfSpread(pSpread);
01953         
01954         if (ClipRect.IsEmpty())
01955         {
01956             ENSURE(FALSE, "Current spread has no pages");
01957             ERRORIF(TRUE, _R(IDT_DOC_BADSTRUCTURE), FALSE);
01958         }
01959     }
01960 
01961     // Don't use rendering matrix when exporting BMPs as it uses coordinates as is
01962     Matrix Identity;
01963 
01964     // Don't use view scale; set to 1
01965     FIXED16 Scale(1);
01966 
01967     // If this is the Preview bitmap, the scale may need changin
01968     if (IsPreviewBitmap)
01969     {
01970         // Find out the maximum dimension of the clip rect
01971         MILLIPOINT Width = ClipRect.Width();
01972         MILLIPOINT Height = ClipRect.Height();
01973         MILLIPOINT MaxSize = (Width>Height) ? Width : Height;
01974 
01975         // this can't happen considering the code above - but you never know.
01976         ERROR3IF( MaxSize==0, "BaseBitmapFilter::PrepareToExport both dimensions of preview are zero");
01977         // stop div zeros. We set it quite high here otherwise we get huge values in the DPI field
01978         if (MaxSize==0)
01979             MaxSize = 1000;
01980 
01981         // Set the scale factor to get this down into the required size
01982         //WEBSTER-Martin-02/01/97
01983         MILLIPOINT WantSize = PreviewFilter::PreviewBitmapSize;
01984 
01985         // Removed changes to 'Scale' variable so the scale factor is
01986         // now always 1.  Jonathan Payne, 8/9/2000.
01987 
01988         // The Scale Factor is not actually used, so we have to change the size of things
01989         // by effecting the DPI. Scale the DPI, but make sure it does not get too small.
01990         DPI = ((double)WantSize) / ((double)MaxSize) * DPI;
01991         if (DPI < 4.0)
01992             DPI = 4.0;
01993 
01994         //WEBSTER-Martin-30/01/97
01995         // It doesn't matter what rounding we do here, but there is a problem because the bitmap
01996         // is not exactly the same size as the cliprect need something like ??? Any region outside
01997         // the cliprect is rendered as black hence the black lines that appear at the top and bottom
01998         // of some previews. It is especially noticable when the original is smaller than the preview.
01999         // Here we are using the dpi to do some scaling we're not really concerned with the exact value
02000         INT32 b_dpi = (INT32) DPI;
02001         DPI = (double)b_dpi;    //round down
02002     }
02003     else
02004     {
02005         // Ensure Bitmap is at least 1 pixel square!
02006         if (ClipRect.Width()<PIXELWIDTH)    ClipRect.hi.x = ClipRect.lo.x + PIXELWIDTH;
02007         if (ClipRect.Height()<PIXELHEIGHT)  ClipRect.hi.y = ClipRect.lo.y + PIXELHEIGHT;
02008     }
02009 
02010     // Remember the size of the bitmap
02011     WinRect Rect = OSRenderRegion::BitmapDocRectToWin( Identity, ClipRect, DPI );
02012     SetPixelWidth(Rect.GetWidth());
02013     SetPixelHeight(Rect.GetHeight());
02014 
02015     // Create the region
02016 //  TRACEUSER( "Gerry", _T("PrepareToExport creating GRenderBitmap %d bpp   (cmyk = %d)\n"), Depth, GetBitmapExportOptions()->IsCMYK());
02017     ExportRegion = new GRenderBitmap(ClipRect, Identity, Scale, Depth, DPI, FALSE, Dither, NULL, TRUE);
02018     if (ExportRegion == NULL)
02019         // Error already set by new, so just return
02020         return FALSE;
02021 
02022     ExportRegion->SetFilter(this);
02023 
02024     // exporting a bitmap, so we will want any bitmaps used in there to be of the best quality - sjk
02025     ExportRegion->SetUsingSmoothedBitmaps(TRUE);
02026 
02027     // MarkH 23/7/99 - New Flag to say that we require to render using the biCompression Field
02028     if(GetBitmapExportOptions()->GetDepth() == 32)
02029     {
02030         ExportRegion->m_DoCompression = TRUE;
02031     }
02032 
02033     // we need a View to Attach to, so that:
02034     //      default Quality setting
02035     //      CalcPixelWidth etc get called
02036 
02037     DocView *View = DocView::GetCurrent();
02038     if (View)
02039     {
02040         // Must force background rendering off as otherwise we might get a partly
02041         // rendered drawing or object if it is complex.
02042         ForceBackgroundRedrawOff(View);
02043 
02044         if (GetBitmapExportOptions()->GetDepth() == 1)
02045         {
02046             // If we are outputting at 1bpp, then we'll force antialiasing off,
02047             // so that Gavin's palette optimisation can detect objects which 
02048             // are 'one solid colour'
02049             ForceAntialiasingOff(View);
02050         }
02051 
02052         // If we are in preview bitmap mode then force anti-aliasing to be full
02053         // rather than the default setting for the view
02054         if (IsPreviewBitmap)
02055         {
02056             ForceAntialiasingFull(View);
02057         }
02058 
02059         // Attach to the right device. (note no DC)
02060         ExportRegion->AttachDevice(View, NULL, pSpread);
02061     }
02062     else
02063     {
02064         ERROR2(FALSE,"BaseBitmapFilter::WriteToFile no current view");
02065     }
02066 #endif
02067     // All ok
02068     return TRUE;
02069 }
02070 
02071 /********************************************************************************************
02072 
02073 >   BOOL BaseBitmapFilter::WarnIfIncompatible()
02074 
02075     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
02076     Created:    14/05/2004
02077     Inputs:     -
02078     Returns:    TRUE is can continue
02079                 FALSE if export should be aborted
02080     Purpose:    Checks for things that can't be represented using the current options
02081                 E.g. non-mix transparencies in Alpha channel bitmap
02082     Errors:     -
02083     Scope:      Protected
02084 
02085 ********************************************************************************************/
02086 
02087 BOOL BaseBitmapFilter::WarnIfIncompatible()
02088 {
02089     // Check whether the user has asked us to be silent about this
02090     if (bDontWarnBitmapNonMixTransp)
02091         return TRUE;
02092 
02093     // Check whether the export options will make transparencies difficult
02094     // Is export type 32BPP including alpha?
02095     // If not everything's OK
02096     if (m_pExportOptions->GetDepth()!=32)
02097     {
02098         return TRUE;
02099     }
02100 
02101     // Check whether the export selection contains non-mix transparency
02102     BOOL bFound = FALSE;
02103     Node* pNode = NULL;
02104     switch (m_pExportOptions->GetSelectionType())
02105     {
02106     case SELECTION:
02107         {
02108             Range* pscanrange;
02109             pscanrange = Camelot.FindSelection();
02110             pNode = pscanrange->FindFirst(TRUE);
02111             while (pNode!=NULL && !bFound)
02112             {
02113                 if (pNode->IsAnAttribute())
02114                 {
02115                     if (((NodeAttribute*)pNode)->IsATranspFill())
02116                     {
02117                         UINT32 transptype = ((AttrFillGeometry*)pNode)->GetTranspType();
02118                         if (transptype!=TT_Mix && transptype!=TT_NoTranspType)
02119                             bFound = TRUE;
02120                     }
02121                 }
02122                 pNode = pscanrange->FindNext(pNode, TRUE);
02123             }
02124         }
02125         break;
02126     case DRAWING:
02127     case PAGE:
02128     case SPREAD:
02129         {
02130             Node* pRootNode = pSpread;
02131             pNode = pRootNode->FindFirstDepthFirst();
02132             while (pNode!=NULL && !bFound)
02133             {
02134                 if (pNode->IsAnAttribute())
02135                 {
02136                     if (((NodeAttribute*)pNode)->IsATranspFill())
02137                     {
02138                         UINT32 transptype = ((AttrFillGeometry*)pNode)->GetTranspType();
02139                         if (transptype!=TT_Mix && transptype!=TT_NoTranspType)
02140                             bFound = TRUE;
02141                     }
02142                 }
02143 
02144                 pNode = pNode->FindNextDepthFirst(pRootNode);
02145             }
02146         }
02147         break;
02148     default:
02149         ERROR2RAW("Unknown selection type in WarnIfIncompatible");
02150         return FALSE;
02151     }
02152 
02153     if (!bFound)
02154         return TRUE;
02155 
02156     // We need to show the warning dialog...
02157     INT32 ret = InformWarning(_R(IDS_WARN_INCOMPATIBLETRANSPARENCY), _R(IDS_CONTINUE), _R(IDS_ALWAYSCONTINUE), _R(IDS_CANCEL));
02158     if (ret==3)
02159         return FALSE;
02160 
02161     if (ret==2)
02162         bDontWarnBitmapNonMixTransp = TRUE;
02163 
02164     return TRUE;
02165 }
02166 
02167 
02168 
02169 
02170 /********************************************************************************************
02171 
02172 >   void BaseBitmapFilter::ForceBackgroundRedrawOff(DocView* pView)
02173 
02174     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02175     Created:    1/7/96
02176     Inputs:     pView, pointer to the View to change
02177     Returns:    -
02178     Purpose:    Forces background redraw off in the specified view, so we render all the
02179                 objects in one pass.
02180                 Use RestoreBackgroundRedrawState to restore the state.
02181     Errors:     -
02182     SeeAlso:    BaseBitmapFilter::RestoreBackgroundRedrawState
02183     Scope:      Protected
02184 
02185 ********************************************************************************************/
02186 
02187 void BaseBitmapFilter::ForceBackgroundRedrawOff(DocView* pView)
02188 {
02189     ERROR3IF(pView == NULL, "NULL pointer passed into BaseBitmapFilter::ForceBackgroundRedrawOff");
02190     if (pView == NULL)
02191         return;
02192 
02193     // We wan't to make sure we only remember the old state once ...
02194     if (!BackgroundRedrawStateSet)
02195     {
02196         BackgroundRedrawState = pView->GetForeBackMode();
02197         BackgroundRedrawStateSet = TRUE;    // So we don't do this more than once
02198     }
02199 
02200     pView->SetForeBackMode(FALSE);
02201 }
02202 
02203 /********************************************************************************************
02204 
02205 >   void BaseBitmapFilter::RestoreBackgroundRedrawState(DocView* pView)
02206 
02207     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02208     Created:    1/7/96
02209     Inputs:     pView, pointer to the View to change
02210     Returns:    -
02211     Purpose:    Restores the background redraw state in the specified view, to the state
02212                 before we called BaseBitmapFilter::ForceBackgroundRedrawOff.
02213     Errors:     -
02214     SeeAlso:    BaseBitmapFilter::ForceBackgroundRedrawOff
02215     Scope:      Protected
02216 
02217 ********************************************************************************************/
02218 
02219 void BaseBitmapFilter::RestoreBackgroundRedrawState(DocView* pView)
02220 {
02221     ERROR3IF(pView == NULL, "NULL pointer passed into BaseBitmapFilter::RestoreBackgroundRedrawState");
02222     if (pView == NULL)
02223         return;
02224 
02225     // Only restore if we saved the state earlier ...
02226     if (BackgroundRedrawStateSet)
02227     {
02228         pView->SetForeBackMode(BackgroundRedrawState);
02229         BackgroundRedrawStateSet = FALSE;
02230     }
02231 }
02232 
02233 /********************************************************************************************
02234 
02235 >   void BaseBitmapFilter::ForceAntialiasingOff(DocView* pView)
02236 
02237     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02238     Created:    1/7/96
02239     Inputs:     pView, pointer to the View to change
02240     Returns:    -
02241     Purpose:    Forces Antialiasing off in the specified view.
02242                 Use RestoreViewQuality to restore the quality.
02243     Errors:     -
02244     SeeAlso:    BaseBitmapFilter::RestoreViewQuality
02245     Scope:      Protected
02246 
02247 ********************************************************************************************/
02248 
02249 void BaseBitmapFilter::ForceAntialiasingOff(DocView* pView)
02250 {
02251     ERROR3IF(pView == NULL, "NULL pointer passed into BaseBitmapFilter::ForceAntialiasingOff");
02252     if (pView == NULL)
02253         return;
02254 
02255     // We don't need to do anything if the view quality is already not Antialiased
02256     if (!ViewQualitySet && pView->RenderQuality.GetAntialiasQuality() >= Quality::FullAntialias)
02257     {
02258         ViewQuality = pView->RenderQuality;
02259         ViewQualitySet = TRUE;              // So we don't do this more than once
02260 
02261         pView->RenderQuality.SetQuality(QUALITY_DEFAULT);
02262     }
02263 }
02264 
02265 /********************************************************************************************
02266 
02267 >   void BaseBitmapFilter::ForceAntialiasingFull(DocView* pView)
02268 
02269     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02270     Created:    11/9/96
02271     Inputs:     pView, pointer to the View to change
02272     Returns:    -
02273     Purpose:    Forces Antialiasing to be full in the specified view.
02274                 Use RestoreViewQuality to restore the quality.
02275                 Used when generating preview bitmaps, which should always be in full anti-
02276                 aliasing mode.
02277     Errors:     -
02278     SeeAlso:    BaseBitmapFilter::RestoreViewQuality
02279     Scope:      Protected
02280 
02281 ********************************************************************************************/
02282 
02283 void BaseBitmapFilter::ForceAntialiasingFull(DocView* pView)
02284 {
02285     ERROR3IF(pView == NULL, "NULL pointer passed into BaseBitmapFilter::ForceAntialiasingFull");
02286     if (pView == NULL)
02287         return;
02288 
02289     // We don't need to do anything if the view quality is already not Antialiased
02290     if (!ViewQualitySet && pView->RenderQuality.GetAntialiasQuality() < Quality::FullAntialias)
02291     {
02292         ViewQuality = pView->RenderQuality;
02293         ViewQualitySet = TRUE;              // So we don't do this more than once
02294 
02295         pView->RenderQuality.SetQuality(QUALITY_MAX);
02296     }
02297 }
02298 
02299 /********************************************************************************************
02300 
02301 >   void BaseBitmapFilter::RestoreViewQuality(DocView* pView)
02302 
02303     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02304     Created:    1/7/96
02305     Inputs:     pView, pointer to the View to change
02306     Returns:    -
02307     Purpose:    Restores the view quality to the state before we called ForceAntialiasingOff
02308     Errors:     -
02309     SeeAlso:    BaseBitmapFilter::ForceAntialiasingOff
02310     Scope:      Protected
02311 
02312 ********************************************************************************************/
02313 
02314 void BaseBitmapFilter::RestoreViewQuality(DocView* pView)
02315 {
02316     ERROR3IF(pView == NULL, "NULL pointer passed into BaseBitmapFilter::RestoreViewQuality");
02317     if (pView == NULL)
02318         return;
02319 
02320     if (ViewQualitySet)
02321     {
02322         // Restore the previous view quality
02323         pView->RenderQuality = ViewQuality;
02324         ViewQualitySet = FALSE;
02325     }
02326 }
02327 
02328 /********************************************************************************************
02329 
02330 >   void BaseBitmapFilter::CleanUpAfterExport()
02331 
02332     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
02333     Created:    28/6/94
02334     Purpose:    Cleans up the memory allocated by BaseBitmapFilter::PrepareToImport() - used
02335                 when the import process ends, either normally or abnormally. Override if
02336                 extra things are required.
02337     SeeAlso:    BaseBitmapFilter::PrepareToImport; BaseBitmapFilter::DoImport
02338     Scope:      Private
02339 
02340 ********************************************************************************************/
02341 
02342 void BaseBitmapFilter::CleanUpAfterExport()
02343 {
02344 #ifdef DO_EXPORT
02345     // Get rid of our dynamic objects
02346     if (OutputFile)
02347     {
02348         OutputFile = NULL;
02349     }
02350 
02351     DocView *View = DocView::GetCurrent();
02352     if (View)
02353     {
02354         if( ViewQualitySet )
02355         {
02356             //  Only need to do this if the view quality has been set but not restored.
02357             RestoreViewQuality(View);
02358         }
02359     }
02360 
02361     if (ExportRegion)
02362     {
02363         // If we have create the export region then delete it
02364         delete ExportRegion;
02365         ExportRegion = NULL;
02366 
02367         // Must try and set our background rendering state back to the default 
02368         DocView *View = DocView::GetCurrent();
02369         if (View)
02370         {
02371             // Force background back to its entry state
02372             RestoreBackgroundRedrawState(View);
02373         }
02374     }
02375 
02376     if (pOptimisedPalette)
02377     {
02378         CCFree( pOptimisedPalette );
02379         pOptimisedPalette = NULL;
02380     }
02381 
02382 #endif
02383 }
02384 
02385 /********************************************************************************************
02386 
02387 >   virtual BOOL BaseBitmapFilter::GetRenderBottomToTop()
02388 
02389     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02390     Created:    17/5/95
02391     Inputs:     -
02392     Outputs:    -
02393     Returns:    TRUE if going to use the default of rendering bottom to top, FALSE otherwise
02394     Purpose:    Find out which way we need to render
02395 
02396 ********************************************************************************************/
02397 
02398 BOOL BaseBitmapFilter::GetRenderBottomToTop()
02399 {
02400     return TRUE;
02401 }
02402     
02403 
02404 /********************************************************************************************
02405 
02406 >   virtual BOOL BaseBitmapFilter::DoExport(Operation* pOp, CCLexFile* pFile, PathName* pPath,
02407                                             Document* pDoc)
02408 
02409     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
02410     Created:    22/8/94
02411     Inputs:     pOp - the operation that started the export off
02412                 pDiskFile - the file to put the exported data into
02413                 pPath - the pathname of the file to be exported to
02414                 pDoc - the document to export
02415     Returns:    TRUE if worked, FALSE if failed.
02416     Purpose:    Exports the current selection as a bitmap, via the virtual fns of the
02417                 inherited class. Do not override unless really necessary.
02418     SeeAlso:    GetExportOptions; PrepareToExport; ExportRenderNodes; CleanUpAfterExport;
02419 
02420 ********************************************************************************************/
02421 
02422 BOOL BaseBitmapFilter::DoExport(Operation *pOp, CCLexFile* pFile,
02423                                 PathName* pPath, Document* pDoc,
02424                                 BOOL ShowOptions)
02425 {
02426     // The success / failure flag.
02427     BOOL ok = TRUE;
02428 
02429     // smfix put back more or less this should be only used by the preview filters
02430 
02431 #ifdef DO_EXPORT
02432 
02433     // Dreamweaver integration.
02434 //  BOOL bDesignNotesSelectedValue = FALSE;
02435 
02436     ERROR2IF(pOp == NULL, FALSE,"BaseBitmapFilter::DoExport no export operation");
02437     ERROR2IF(pFile == NULL, FALSE,"BaseBitmapFilter::DoExport no file to export to");
02438     ERROR2IF(pPath == NULL, FALSE,"BaseBitmapFilter::DoExport no export pathname");
02439     ERROR2IF(pDoc == NULL, FALSE,"BaseBitmapFilter::DoExport no document to export");
02440 
02441     // Set the bitmap pointer to null just in case, usually only used by DoExportBitmap
02442     pExportBitmap = NULL;
02443 
02444     // Get pointer to the spread to export.
02445 PORTNOTE("spread", "Multi-spread warning!")
02446     pSpread = GetFirstSpread(pDoc);
02447     ERROR2IF(pSpread == NULL, FALSE,"BaseCamelotFilter::DoExport no spread to export");
02448 
02449     // We must now check if there is a selection present so that we can set up whether the
02450     // user gets the choice of exporting the selection, drawing or spread if there is a 
02451     // selection present OR just a choice between the spread or drawing if no selection is
02452     // present.
02453     // If have a caret selected in a text story then the selection will be almost zero so
02454     // trap this case as well. 
02455     ClipRect = GetApplication ()->FindSelection ()->GetBoundingRect(TRUE);
02456     SelectionType Selection = DRAWING;
02457 
02458     // Determine the selection type.
02459     if ( !IsPreviewBitmap && !ClipRect.IsEmpty() && ClipRect.Width() >= MinExportSize && ClipRect.Height() >= MinExportSize )
02460     {
02461         Selection = SELECTION; // Something is selected, so use this.
02462     }
02463     else // The selection is either too small to export, or the clipping rectangle is empty.
02464     {
02465         // Work out the size of the rectangle encompassing the drawing (visible layers only).
02466         ClipRect = GetSizeOfDrawing(pSpread);
02467 
02468         // Check that that cliprect is ok, if not then set the spread as the export type.
02469         if ( ClipRect.IsEmpty() || ClipRect.Width() < MinExportSize || ClipRect.Height() < MinExportSize )
02470             Selection = SPREAD;
02471     }
02472 
02473     // If there is no selection then warn the user that exporting the current spread may
02474     // take a lot of disc space, but only if this is not a Preview Bitmap.
02475     if ((!IsPreviewBitmap) && (Selection == SPREAD))
02476     {
02477         // Warn the user that there is no selection = large export
02478         ErrorInfo Info;
02479         Info.ErrorMsg = _R(IDT_BMPEXP_NOSELECTION);
02480         Info.Button[0] = _R(IDB_EXPQUERY_EXPORT);
02481         Info.Button[1] = _R(IDB_EXPQUERY_DONTEXPORT);
02482         if ((ResourceID)(AskQuestion(&Info)) == _R(IDB_EXPQUERY_DONTEXPORT))
02483         {
02484             Error::SetError(_R(IDN_USER_CANCELLED),0);      // Expects error set on cancel
02485             ok = FALSE;
02486         }
02487     }
02488 
02489     // Mark H 18/12/00
02490     // From here on, I`ve tidied up the code so that this function is responsible for it`s
02491     // own Bitmap Export Options pointer and not reliant on the member variable. This fixes
02492     //a 1.5MB!!! memory leak on exiting of the program!
02493 
02494     // Create a new Bitmap Export Options pointer for the current filter
02495     BitmapExportOptions* pExportOptions = CreateExportOptions();
02496 
02497     // Try to create the export options.
02498     if (ok && pExportOptions)
02499     {
02500         pExportOptions->RetrieveDefaults();
02501         pExportOptions->SetSelectionType(Selection);
02502         pExportOptions->SetBackgroundTransparency(FALSE);
02503     }
02504     else
02505         ok = FALSE;
02506 
02507     //Graham W 3/7/97: Tell the preview dialog what the path to save out to is
02508     BmapPrevDlg::m_pthExport=*pPath;
02509 
02510     if(ok)
02511         ok = GetExportOptions(pExportOptions);
02512 
02513     // This pointer is used to call the ExportBitmap function. If the filetype has changed,
02514     // then it will be set-up to be invoked from the new type.
02515     BaseBitmapFilter *pFilter = this;
02516 
02517     // Write out the bitmap.
02518     if (ok)
02519     {
02520         if (!pFilter->DoExportWithOptions(pOp, pFile, pPath, pDoc, pExportOptions))
02521         {
02522             // Export failed, therefore no valid export options.
02523             Error::SetError(_R(IDN_USER_CANCELLED),0);
02524         }
02525     }
02526 
02527     // Clear up the existing bitmap options.
02528     if(pExportOptions)
02529     {
02530         delete pExportOptions;
02531         pExportOptions = NULL;
02532     }
02533 
02534 #endif
02535 
02536     return ok;
02537 }
02538 
02539 
02540 /********************************************************************************************
02541 
02542 >   virtual BOOL BaseBitmapFilter::DoExportDoc(Operation* pOp, CCLexFile* pFile, PathName* pPath,
02543                                                Document* pDoc,  UINT32 Depth, double DPI,
02544                                                const SelectionType& Selection , BOOL UseExistingPalette)
02545     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
02546     Created:    12/6/96
02547     Purpose:    Actually does the work of DoExport() above
02548                 Code split out for use by DoExportBitmaps() function
02549                 This DOES NOT call CleanUpAfterExport() if it fails
02550                 If the call returns FALSE then the caller must call CleanUpAfterExport()
02551     Returns:    TRUE if worked, FALSE if failed.
02552     Scope:      protected
02553     SeeAlso:    GetExportOptions; PrepareToExport; ExportRenderNodes; CleanUpAfterExport;
02554     Additional information( ap ) - Added 'UseExistingPalette'. If this is TRUE, then the 
02555     existing palette in BmapPrevDlg is used instead of a newly generated one. This variable 
02556     is given the default value of FALSE.
02557 
02558 ********************************************************************************************/
02559 
02560 BOOL BaseBitmapFilter::DoExportDoc(Operation* pOp, CCLexFile* pFile, PathName* pPath,
02561                                    Document* pDoc, UINT32 RenderDepth, double DPI,
02562                                    const SelectionType& Selection , BOOL UseExistingPalette)
02563 {
02564 #ifdef DO_EXPORT
02565     if (!WritePreFrame()) return(FALSE);
02566 
02567     /*
02568     //  Only try to do the exact palette if we are using an 8 bit optimised palette
02569     if( ( PaletteType == 1 ) && ( GetBitmapExportOptions()->GetDepth() == 8 ) )
02570         GRenderOptPalette::UseOldPalette = FALSE;
02571     else
02572         GRenderOptPalette::UseOldPalette = TRUE;
02573     */
02574 
02575     // Set up device context and render region for this export.
02576     // This will show a progress hourglass for the objects being rendered
02577     // This will now also write the data out to file via our ExportRenderNodes function
02578     if (!PrepareToExport(pSpread, RenderDepth, DPI, Selection))
02579     {
02580         return FALSE;
02581     }
02582 
02583     // SMFIX
02584     // this is where we will build up the palette from the export options IF the one
02585     // that is already in the export options is NOT valid
02586     // the fn bellow export render needs the palette to be valid
02587 //  m_pExportOptions->CreateValidPalette();
02588 
02589     // this call sets this palette in the lower reaches of the code from the palette held in the export options
02590 //  AlterPaletteContents(m_pExportOptions->GetLogicalPalette());
02591 
02592     // Export the data to the file ensuring we render in strips, if required.
02593     RenderInStrips = TRUE;
02594     if (!ExportRender(ExportRegion))
02595     {
02596         // SMFIX - Make sure we reset the StripStart as it could stuff up further operations.
02597         m__StripStart = 0;
02598         return FALSE;
02599     }
02600 
02601     
02602     //SMFIX was calling AlterPaletteContents( lpPalette ); on a palette that it built here
02603 
02604 
02605 
02606     // Ask the filter if it requires a second pass export render. This might be used for
02607     // say preparing a mask for transparency or something. Used by the GIF filter for this
02608     // purpose.
02609     /*
02610     if (IsSecondPassRequired())
02611     {
02612         WritePreSecondPass();
02613 
02614         // Set up device context and render region for this export.
02615         // This will show a progress hourglass for the objects being rendered
02616         // This will now also write the data out to file via our ExportRenderNodes function
02617         if (!PrepareToExport(pSpread, RenderDepth, DPI, Selection))
02618         {
02619             return FALSE;
02620         }
02621 
02622         // Export the data to the file esnuring we render in strips, if required.
02623         RenderInStrips = TRUE;
02624         if (!ExportRender(ExportRegion))
02625         {
02626             return FALSE;
02627         }
02628     }
02629     */
02630     
02631     if (!WritePostFrame())
02632     {
02633         // SMFIX - Make sure we reset the StripStart as it could stuff up further operations.
02634         m__StripStart = 0;
02635         return FALSE;
02636     }
02637 
02638     // SMFIX - Make sure we reset the StripStart as it could stuff up further operations.
02639     m__StripStart = 0;
02640 #endif
02641     return TRUE;
02642 }
02643 
02644 
02645 
02646 
02647 /********************************************************************************************
02648 
02649 >   BOOL BaseBitmapFilter::DoExportBitmap(Operation* pOp, CCLexFile* pFile, PathName* pPath,
02650                                           KernelBitmap* pBitmap)
02651 
02652     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02653     Created:    25/4/95
02654     Inputs:         
02655     Purpose:    Exports the specified bitmap straight out to file with none of the rendering
02656                 that DoExport does. Uses the virtual fns of the inherited class.
02657                 Do not override unless really necessary.
02658     Returns:    TRUE if worked, FALSE if failed.
02659 
02660 ********************************************************************************************/
02661 
02662 BOOL BaseBitmapFilter::DoExportBitmap(Operation* pOp, CCLexFile* pFile, PathName* pPath,
02663                                       KernelBitmap* pBitmap)
02664 {
02665 #ifdef DO_EXPORT
02666     ERROR2IF(pBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmap null bitmap pointer specified");
02667 
02668     // Note this pointer for later use
02669     pExportBitmap = pBitmap;
02670 
02671     // Note this ptr for use in JPEG export.
02672     JPEGExportOptions::SetKernelBitmap(pBitmap);
02673     
02674     // Get a pointer to the actual bitmap so that we can get some details from it.
02675     OILBitmap *pOilBitmap = pBitmap->ActualBitmap;
02676     ERROR2IF(pOilBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmap null oil bitmap pointer");
02677 
02678     // Create a record of information about the export
02679     m_pExportOptions = CreateExportOptions();
02680 
02681     if (m_pExportOptions == NULL)
02682     {
02683         return FALSE;
02684     }
02685 
02686     // Get the default settings
02687     GetBitmapExportOptions()->RetrieveDefaults();
02688 
02689     // Specify to the user what the export options for depth etc are going to be
02690     GetBitmapExportOptions()->SetSelectionType(ABITMAP);
02691 
02692     // Get the details from the specified bitmap
02693     BitmapInfo BmInfo;
02694     pOilBitmap->GetInfo(&BmInfo);
02695     GetBitmapExportOptions()->SetDepth(BmInfo.PixelDepth);  // get the bitmaps bpp
02696     
02697     // Should really save the dpi when we load the file itself rather than doing
02698     // all this conversion with possible rounding errors.
02699     // Use the original size that has been calculated in the info header
02700     UINT32 PixWidth  = BmInfo.PixelWidth;
02701 //  UINT32 PixHeight = BmInfo.PixelHeight;
02702     MILLIPOINT  RecWidth = BmInfo.RecommendedWidth;
02703 //  MILLIPOINT  RecHeight = BmInfo.RecommendedHeight;
02704 
02705     if (PixWidth > 0)
02706     {
02707         GetBitmapExportOptions()->SetDPI((PixWidth * 72000.0)/(double)RecWidth);
02708     }
02709 
02710     // WEBSTER - markn 5/2/97
02711     // If the bitmap has a transparent colour index, store it in the options object
02712     // -1 means no transparent colour
02713     INT32 TransIndex = -1;
02714     if (!pBitmap->GetTransparencyIndex(&TransIndex)) TransIndex = -1;
02715     GetBitmapExportOptions()->SetTransparencyIndex(TransIndex);
02716 
02717     BOOL ok = TRUE;
02718 
02719 /* It used to call the export options dlg here - but why bother just export as is
02720     BOOL ok = GetExportOptions(GetBitmapExportOptions());
02721     if (!ok)
02722     {
02723         delete m_pExportOptions;
02724         m_pExportOptions = 0;
02725 
02726         Error::SetError(_R(IDN_USER_CANCELLED),0);          // Expects error set on cancel
02727         return FALSE;                                   // if cancelled
02728     }
02729 
02730     if (GetBitmapExportOptions()->HasTempFile())
02731     {
02732         // the export options preview dialog has produced a temp file, so just rename that
02733 
02734         // get the temp file name
02735         PathName TempPath = GetBitmapExportOptions()->GetPathName();
02736 
02737         String_256 FinalName = pPath->GetPath();
02738         String_256 TempName = TempPath.GetPath();
02739 
02740         if (pFile->isOpen())
02741             pFile->close();
02742 
02743         // delete the empty file, if one was created
02744         FileUtil::DeleteFile(pPath);
02745                      
02746         // try to rename the file
02747         if (_trename(TempName, FinalName) != 0)
02748             ok = FALSE;
02749         else
02750             ok = TRUE;
02751     }
02752     else */
02753     {
02754         // Used to open the file up before starting DoExport. But this meant a cancel on the export
02755         // options dialog had filled the file, if it was already present. So now up up here if
02756         // not open already. In the PreviewBitmap case the file will already be open.
02757         if (!pFile->isOpen())
02758         {
02759             if (pFile->IsKindOf(CC_RUNTIME_CLASS(CCDiskFile)))
02760             {
02761                 ok = OpenExportFile((CCDiskFile*) pFile, pPath);
02762                 if (!ok) return FALSE;
02763             }
02764             else
02765             {
02766                 TRACEUSER( "JustinF", _T("Tried to open non-CCDiskFile in BaseBitmapFilter::DoExportBitmap\n") );
02767                 return FALSE;
02768             }
02769         }
02770 
02771         // Make a note of the Disk file we are to use
02772         OutputFile = pFile;
02773 
02774         // We do not use an export region so specify null.
02775         ExportRegion = NULL;
02776         
02777         // Actually write to the file, showing progress hourglass as we go
02778         ok = WriteBitmapToFile(pBitmap, GetBitmapExportOptions()->GetDPI());
02779 
02780         if (ok)
02781             WriteFileEnd();
02782     }
02783 
02784     // All done - deallocate dynamic objects, stop the progress display/hourglass
02785     // and return success. (Also closes file).
02786     CleanUpAfterExport();
02787 
02788     // we created these here so we should delete them
02789     delete m_pExportOptions;
02790     m_pExportOptions = NULL;
02791 
02792     return ok;
02793 #else
02794     return FALSE;
02795 #endif
02796 }
02797 
02798 
02799 
02800 /********************************************************************************************
02801 
02802 >   virtual BOOL BaseBitmapFilter::DoExportBitmaps(Operation* pOp, CCLexFile* pFile,
02803                                                    PathName* pPath, BitmapExportParam* pParam)
02804 
02805     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
02806     Created:    11/6/96
02807     Inputs:         
02808     Purpose:    Exports the bitmaps specified by the BitmapExportParam object to a multi-
02809                 image capable filter.
02810                 It works creating a special document containing a single NodeBitmap
02811                 It then sets this document to use each bitmap in turn and calls DoExport
02812                 to actually export it.
02813     Returns:    TRUE if worked, FALSE if failed.
02814 
02815 ********************************************************************************************/
02816 
02817 BOOL BaseBitmapFilter::DoExportBitmaps(Operation *pOp, CCLexFile* pFile, PathName* pPath,
02818                                         BitmapExportParam* pParam)
02819 {
02820 #ifdef DO_EXPORT
02821     ERROR2IF(pOp == NULL || pFile == NULL || pPath == NULL, FALSE,"NULL Parameters");
02822     ERROR2IF(pParam == NULL,FALSE,"BaseBitmapFilter::DoExportBitmaps null BitmapExportParam specified");
02823 
02824     // Create an object so we can ask the user for some options
02825     if (m_pExportOptions)
02826         delete m_pExportOptions;
02827 
02828     m_pExportOptions = CreateExportOptions();
02829 
02830     if (m_pExportOptions == NULL)
02831         return FALSE;
02832 
02833     // Get the first bitmap pointer
02834     KernelBitmap* pBitmap = pParam->GetBitmap(0);
02835     ERROR2IF(pBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmaps has no bitmaps to export");
02836 
02837     pExportBitmap = pBitmap;
02838 
02839     // Get a pointer to the actual bitmap so that we can get some details from it.
02840     OILBitmap *pOilBitmap = pBitmap->ActualBitmap;
02841     ERROR2IF(pOilBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmaps null oil bitmap pointer");
02842 
02843     // Specify to the user what the export options for depth etc are going to be
02844     GetBitmapExportOptions()->SetSelectionType(SOMEBITMAPS);
02845 
02846     GetBitmapExportOptions()->SetBitmapExportParam(pParam); 
02847 
02848     // Get the defaults from the first bitmap
02849     BitmapInfo BmInfo;
02850     pOilBitmap->GetInfo(&BmInfo);
02851     GetBitmapExportOptions()->SetDepth(BmInfo.PixelDepth);  // get the bitmaps bpp
02852 
02853     // Calculate the millipoint size from the pixel size assuming 96 dpi
02854     double DPI = 96.0;
02855     MILLIPOINT RecWidth = (MILLIPOINT) ((((double)BmInfo.PixelWidth * 72000.0) / DPI) + 0.5);
02856     MILLIPOINT RecHeight = (MILLIPOINT) ((((double)BmInfo.PixelHeight * 72000.0) / DPI) + 0.5);
02857     // Create a Coord for GetExportOptions
02858     GetBitmapExportOptions()->SetOutputSize(RecWidth, RecHeight);
02859 
02860     BOOL ok = GetExportOptions(GetBitmapExportOptions());
02861     if (!ok)
02862     {
02863         delete m_pExportOptions;
02864         m_pExportOptions = NULL;
02865 
02866         Error::SetError(_R(IDN_USER_CANCELLED),0);          // Expects error set on cancel
02867         return FALSE;                                   // if cancelled
02868     }
02869 
02870     // Used to open the file up before starting DoExport. But this meant a cancel on the export
02871     // options dialog had filled the file, if it was already present. So now up up here if
02872     // not open already. In the PreviewBitmap case the file will already be open.
02873     if (!pFile->isOpen())
02874     {
02875         if (pFile->IsKindOf(CC_RUNTIME_CLASS(CCDiskFile)))
02876         {
02877             ok = OpenExportFile((CCDiskFile*) pFile, pPath);
02878             if (!ok) return FALSE;
02879         }
02880         else
02881         {
02882             TRACEUSER( "JustinF", _T("Tried to open non-CCDiskFile in BaseBitmapFilter::DoExportBitmaps\n") );
02883             return FALSE;
02884         }
02885     }
02886 
02887     // Make a note of the Disk file we are to use
02888     OutputFile = pFile;
02889 
02890     // Make sure the Region pointer is NULL for the time being
02891     ExportRegion = NULL;
02892 
02893     // TODO: Rampant change to Selection
02894     GetBitmapExportOptions()->SetSelectionType(DRAWING);
02895 
02896     // Output the file header
02897     if (!WriteFileHeader())
02898     {
02899         CleanUpAfterExport();
02900         return(FALSE);
02901     }
02902 
02903     // Remember the current document as we are just about to use a new document and
02904     // then delete it. Of course, systems like the bitmap system may just decide to
02905     // change current document just to screw things up. Put back before the end as the
02906     // EndOp will broadcast a message causing controls to update which require current
02907     // document to get the units list correctly.
02908     Document *pOldCurrent = Document::GetCurrent();
02909 
02910     // Create a document for the export
02911     BitmapExportDocument* pDoc = new BitmapExportDocument;
02912 
02913     if (pDoc != NULL)
02914     {
02915         if (!pDoc->Init(pBitmap, DocRect(0, 0, GetBitmapExportOptions()->GetOutputSize().x, GetBitmapExportOptions()->GetOutputSize().y)))
02916         {
02917             TRACEUSER( "Gerry", _T("BitmapExportDocument::Init() failed\n") );
02918             delete pDoc;
02919             pDoc = NULL;
02920             CleanUpAfterExport();
02921             if (pOldCurrent != NULL)
02922                 pOldCurrent->SetCurrent();
02923             return(FALSE);
02924         }
02925 
02926         // Get pointer to the spread to export.
02927 PORTNOTE("spread", "Multi-spread warning!")
02928         pSpread = GetFirstSpread(pDoc);
02929 
02930         UINT32 BitmapCount = pParam->GetBitmapCount();
02931 
02932         for (UINT32 Index = 0; ok && (Index < BitmapCount); Index++)
02933         {
02934             // Get the bitmap pointer
02935             pBitmap = pParam->GetBitmap(Index);
02936 
02937             // We have to render the bitmap so...
02938             // Update the BitmapExportDocument
02939             pDoc->SetBitmap(pBitmap);
02940 
02941             // Export the document
02942             // If it fails then break out of the image loop
02943             ok = DoExportDoc(   pOp, pFile, pPath, pDoc, GetRenderDepth(), 
02944                                 GetBitmapExportOptions()->GetDPI(), 
02945                                 GetBitmapExportOptions()->GetSelectionType());
02946 
02947             if (ExportRegion != NULL)
02948             {
02949                 delete ExportRegion;
02950                 ExportRegion = NULL;
02951             }
02952             if (pOptimisedPalette != NULL)
02953             {
02954                 CCFree( pOptimisedPalette );
02955                 pOptimisedPalette = NULL;
02956             }
02957 
02958         }
02959 
02960         delete pDoc;
02961         pDoc = NULL;
02962     }
02963 
02964     // Write any end of file stuff
02965     if (ok)
02966         ok = WriteFileEnd();
02967 
02968     // All done - deallocate dynamic objects, stop the progress display/hourglass
02969     // and return success. (Also closes file).
02970     CleanUpAfterExport();
02971 
02972     // Ensure that we return CurrentDoc to its original value
02973     // Leave QuickShape tool with item selected before exporting animated gif from bitmap
02974     // gallery. Convert/Unit system blows up as using current doc!
02975     if (pOldCurrent != NULL)
02976         pOldCurrent->SetCurrent();
02977 
02978     return ok;
02979 #endif
02980     return FALSE;
02981 }
02982 
02983 
02984 
02985 
02986 /********************************************************************************************
02987 
02988 >   BOOL BaseBitmapFilter::SetUpExportOptions(BitmapExportOptions **ppExportOptions, 
02989                                                 BOOL OnlyDefaults = FALSE)
02990 
02991     Author:     Stefan_Stoykov (Xara Group Ltd) <camelotdev@xara.com>
02992     Created:    12/5/97
02993     Inputs:     
02994     Outputs:    ppExportOptions - pointer, where a pointer to the export options object 
02995                 will be returned
02996     Purpose:    Displays the export options dialog for this bitmap filter. This allows export
02997                 options to be obtained by somebody else then the filter
02998     Returns:    TRUE if worked, FALSE if failed.
02999 
03000   NB. SMFIX sjk this function will if you pass it a NULL ptr new the correct options for the filter for
03001     the calling function. This is great. However in this case the caller function has responsibility
03002     to delete this export object when they are finished with it. They receive the export object through
03003     the static member variable BmapPrevDlg::m_pExportOptions which is a ptr to the base class BitmapExportOptions,
03004     rather than just filling in the users structure, since if the graphic type has changed the users class will have
03005     been deleted and the export object could be a different class derived from BitmapExportOptions.
03006 
03007 ********************************************************************************************/
03008 
03009 BOOL BaseBitmapFilter::SetUpExportOptions(BitmapExportOptions **ppExportOptions, BOOL OnlyDefaults)
03010 {
03011     ERROR2IF(ppExportOptions == NULL, FALSE,"BaseBitmapFilter::Can't Set up export options");
03012 
03013     Document *pDoc = Document::GetCurrent();
03014 
03015     // Get pointer to the spread to export.
03016 PORTNOTE("spread", "Multi-spread warning!")
03017     pSpread = GetFirstSpread(pDoc);
03018     ERROR2IF(pSpread == NULL, FALSE,"BaseCamelotFilter::DoExport no spread to export");
03019 
03020     // We must now check if there is a selection present so that we can set up whether the
03021     // user gets the choice of exporting the selection, drawing or spread if there is a 
03022     // selection present OR just a choice between the spread or drawing if no selection is
03023     // present.
03024     // If have a caret selected in a text story then the selection will be almost zero so trap
03025     // this case as well. 
03026     DocRect ClipRect = GetApplication()->FindSelection()->GetBoundingRect(TRUE);
03027     SelectionType Selection = DRAWING;
03028     if (
03029         ClipRect.IsEmpty() ||
03030         ClipRect.Width() < MinExportSize || ClipRect.Height() < MinExportSize
03031        )
03032         Selection = DRAWING;        // no selection present, so choose drawing by default
03033     else
03034         Selection = SELECTION;      // selection present, so choose this by default
03035 
03036     if (Selection == DRAWING)
03037     {
03038         // Work out the size of the rectangle encompassing the drawing (visible layers only)
03039         ClipRect = GetSizeOfDrawing(pSpread);
03040 
03041         // Check that that cliprect is ok, if not then set the spread as the export type
03042         if (
03043             ClipRect.IsEmpty() ||
03044             ClipRect.Width() < MinExportSize || ClipRect.Height() < MinExportSize
03045            )
03046             Selection = SPREAD;
03047     }
03048     
03049 
03050     // If there is no selection then warn the user that exporting the current spread may
03051     // take a lot of disc space, but only if this is not a Preview Bitmap.
03052     if ((!IsPreviewBitmap) && (Selection == SPREAD))
03053     {
03054         // Warn the user that there is no selection = large export
03055         ErrorInfo Info;
03056         Info.ErrorMsg = _R(IDT_BMPEXP_NOSELECTION);
03057         Info.Button[0] = _R(IDB_EXPQUERY_EXPORT);
03058         Info.Button[1] = _R(IDB_EXPQUERY_DONTEXPORT);
03059         if ((ResourceID)AskQuestion(&Info) == _R(IDB_EXPQUERY_DONTEXPORT))
03060         {
03061             Error::SetError(_R(IDN_USER_CANCELLED),0);      // Expects error set on cancel
03062             return FALSE;                               // if cancelled
03063         }
03064     }
03065 
03066     // Create a record of information about the export
03067     *ppExportOptions = CreateExportOptions();
03068     if (*ppExportOptions == NULL)
03069     {
03070         return FALSE;
03071     }
03072 
03073     (*ppExportOptions)->RetrieveDefaults();
03074 
03075     (*ppExportOptions)->SetSelectionType(Selection);
03076 
03077     // check whether only the defaults are needed
03078     if (OnlyDefaults)
03079         return TRUE;
03080 
03081     // get the user options for depth etc here
03082     BOOL ok = GetExportOptions( *ppExportOptions );
03083 
03084     // remember this ptr and make it externally available
03085     // dont do this any more the above call brings up the export dlg and sets the BmapPrevDlg::m_pExportOptions
03086     // even when the user has messed around with them
03087     //BmapPrevDlg::m_pExportOptions = *ppExportOptions;
03088     // so rather the *ppExportOptions should reflect the state that the dlg left them in
03089     if (BmapPrevDlg::m_pExportOptions)
03090         *ppExportOptions = BmapPrevDlg::m_pExportOptions;
03091 
03092     if (!ok)
03093     {
03094         if (*ppExportOptions != NULL)
03095         {
03096             delete *ppExportOptions;
03097             *ppExportOptions = NULL;
03098         }
03099         Error::SetError(_R(IDN_USER_CANCELLED),0);          // Expects error set on cancel
03100         BmapPrevDlg::m_pExportOptions = NULL;   // we have no export options
03101 
03102         return FALSE;                                   // if cancelled
03103     }
03104 
03105     return TRUE;
03106 }
03107 
03108 
03109 
03110 
03111 /********************************************************************************************
03112 
03113 >   virtual BOOL BaseBitmapFilter::DoExportWithOptions(Operation* pOp, CCLexFile* pFile, 
03114                             PathName* pPath, Document* pDoc, BitmapExportOptions *pOptions)
03115 
03116     Author:     Stefan_Stoykov (Xara Group Ltd) <camelotdev@xara.com>
03117     Created:    12/5/97
03118     Inputs:     pOp - the operation that started the export off
03119                 pFile - the file to put the exported data into
03120                 pPath - the pathname of the file to be exported to
03121                 pDoc - the document to export
03122                 pOptions - the bitmap export options to use when exporting. The options are 
03123                 deleted after the export, so if you want to keep them make a copy first.
03124     Purpose:    Exports the document by using the export options passed as parameter, rather 
03125                 then invoking an options dialog box to obtain them.
03126     Returns:    TRUE if worked, FALSE if failed.
03127 
03128 ********************************************************************************************/
03129 
03130 BOOL BaseBitmapFilter::DoExportWithOptions(Operation* pOp, CCLexFile* pFile, PathName* pPath,
03131                                    Document* pDoc, BitmapExportOptions *pOptions, DocRect *pRect)
03132 {
03133     ERROR2IF(pOp == NULL, FALSE,"BaseBitmapFilter::DoExport no export operation");
03134     ERROR2IF(pFile == NULL, FALSE,"BaseBitmapFilter::DoExport no file to export to");
03135     ERROR2IF(pPath == NULL, FALSE,"BaseBitmapFilter::DoExport no export pathname");
03136     ERROR2IF(pDoc == NULL, FALSE,"BaseBitmapFilter::DoExport no document to export");
03137 
03138     // Have any valid export options been passed in?
03139     if (pOptions == NULL)
03140     {
03141         // Create a record of information about the export.
03142         SetUpExportOptions(&m_pExportOptions, TRUE);
03143         if (m_pExportOptions == NULL)
03144             return FALSE;
03145     }
03146     else
03147     {
03148         // Copy the existing export options.
03149         //m_pExportOptions = pOptions->MakeCopy ();
03150         m_pExportOptions = pOptions; // rather point at the options passed in
03151     }
03152 
03153     // set up the pSpread
03154 PORTNOTE("spread", "Multi-spread warning!")
03155     pSpread = GetFirstSpread(pDoc);
03156 
03157     // deal with no selection
03158     SelRange* pSelection = GetApplication()->FindSelection();
03159     // deal with exporting no selection as the drawing
03160     if (pRect == NULL && pSelection->Count() == 0 && (m_pExportOptions->GetSelectionType() == SELECTION))
03161         m_pExportOptions->SetSelectionType(DRAWING);
03162 
03163     if (pRect != NULL)  // Force the cliping rect for the image to be the one passed in
03164                         // and not just defined by the selection! sjk
03165     {
03166         ClipRect = *pRect;
03167     }
03168     else
03169     {
03170         // reassign the clipping rectangle to the selection's bounding rect
03171         SetUpClippingRectangleForExport(pSpread, m_pExportOptions->GetSelectionType());
03172 
03173         // Set the page limits to drawing if thats whats requested
03174         if (pSpread && m_pExportOptions->IsClipToPage() )
03175         {
03176             Page *pPage = pSpread->FindFirstPageInSpread(); 
03177             if (pPage)
03178                 ClipRect = pPage->GetPageRect();
03179         }   
03180 
03181         // to use SJK's new fiddle the rect to maintain the antialiasing
03182         // as seen on screen call the function bellow
03183         // If you want it to work like it did in CX2 comment the line out
03184         if( m_pExportOptions->GetAntiAliasing() == MAINTAIN_SCREEN_AA )
03185             PixelAlignedFiddle(&ClipRect);
03186     }
03187 
03188     BOOL ok = TRUE;
03189 
03190     // Always export the whole thing into one composite file
03191     ok = DoExportHelper(pOp, pFile, pPath, pDoc);
03192 
03193     if (!IsPreviewBitmap && m_pExportOptions->CanExportSeparateLayers())
03194     {
03195         // We need to export each layer as a separate file
03196         Layer* pLayer = pSpread->FindFirstLayer();
03197         while (ok && pLayer!=NULL)
03198         {
03199             if (pLayer->IsVisible()
03200                 && !pLayer->IsGuide()
03201                 && pLayer->HasLayerGotRenderableChildren()
03202                 )
03203             {
03204                 SetSoleLayer(pLayer);
03205 
03206                 PathName pathLayer = pLayer->MakeExportLayerName(*pPath);
03207                 CCLexFile* pLayerFile = new CCDiskFile(pathLayer, ios::in | ios::out | ios::binary | ios::trunc);
03208 
03209                 if (ok) ok = DoExportHelper(pOp, pLayerFile, &pathLayer, pDoc);
03210 
03211                 delete pLayerFile;
03212 
03213                 SetSoleLayer(NULL);
03214             }
03215 
03216             pLayer = pLayer->FindNextLayer();
03217         }
03218     }
03219 
03220     // Delete the newly created export options ONLY if we did create them
03221     if (pOptions == NULL)
03222     {
03223         delete m_pExportOptions;
03224         m_pExportOptions = NULL;
03225     }
03226 
03227     // Restore the file.
03228     OutputFile = pFile;
03229 
03230     return ok;
03231 }
03232 
03233 
03234 
03235 /********************************************************************************************
03236 
03237 >   virtual BOOL BaseBitmapFilter::DoExportWithOptions(Operation* pOp,
03238                                                        CCLexFile* pFile,
03239                                                        PathName* pPath,
03240                                                        Document* pDoc)
03241 
03242     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> (from Stefan)
03243     Created:    24/03/2004
03244     Inputs:     pOp - the operation that started the export off
03245                 pFile - the file to put the exported data into
03246                 pPath - the pathname of the file to be exported to
03247                 pDoc - the document to export
03248     Purpose:    Exports the document by using the export options passed as parameter, rather 
03249                 then invoking an options dialog box to obtain them.
03250     Returns:    TRUE if worked, FALSE if failed.
03251 
03252 ********************************************************************************************/
03253 
03254 BOOL BaseBitmapFilter::DoExportHelper(Operation* pOp,
03255                                       CCLexFile* pFile,
03256                                       PathName* pPath,
03257                                       Document* pDoc)
03258 {
03259     // Used to open the file up before starting DoExport. But this meant a cancel on the export
03260     // options dialog had filled the file, if it was already present. So now up up here if
03261     // not open already. In the PreviewBitmap case the file will already be open.
03262     if ( !pFile->isOpen() && 
03263          pFile->IsKindOf ( CC_RUNTIME_CLASS ( CCDiskFile ) ) &&
03264          !OpenExportFile ( static_cast<CCDiskFile*> ( pFile ), pPath) )
03265     {
03266          return FALSE;
03267     }
03268     
03269     WrittenHeader = 0;
03270     SetDepthToRender(32);
03271     
03272     // set the palette type which might get changed during the preview
03273     if (m_pExportOptions->IS_KIND_OF(BMPExportOptions))
03274     {
03275         PaletteType = ((BMPExportOptions *)m_pExportOptions)->GetPalette() ? 1 : 0; // 1 for an optimised palette
03276         BMPFilter::SetDefaultExportDPI(m_pExportOptions->GetDPI());
03277         BMPFilter::SetDefaultExportDepth(m_pExportOptions->GetDepth());
03278 PORTNOTE("filter", "Removed use fo GIFFilter")
03279 #ifndef EXCLUDE_FROM_XARALX
03280         // Need to set the dither for the accusoft filter here, otherwise the dither
03281         // changes by the user will not have any effect
03282         AccusoftFilters::SetDitherToUse(m_pExportOptions->GetDither());
03283 #endif
03284     }
03285     else if (m_pExportOptions->IS_KIND_OF(MaskedFilterExportOptions))
03286     {
03287         PaletteType = ((MaskedFilterExportOptions *)m_pExportOptions)->GetPalette() ? 1 : 0;// 1 for an optimised palette
03288     }
03289 
03290     // set the render depth, which might change during the preview
03291     switch (m_pExportOptions->GetFilterType())
03292     {
03293 PORTNOTE("filter", "Removed use fo GIFFilter")
03294 #ifndef EXCLUDE_FROM_XARALX
03295         case TI_GIF:
03296             if (m_pExportOptions->GetDepth() > 8)
03297                 m_pExportOptions->SetDepth(8);
03298             SetDepthToRender(m_pExportOptions->GetDepth());
03299             break;
03300 #endif
03301 
03302         case JPEG:
03303             SetDepthToRender(24);
03304             break;
03305 
03306         default:
03307             SetDepthToRender(m_pExportOptions->GetDepth());
03308             break;
03309     }
03310 
03311 //Mark Howitt, 24/10/97. Reset the FilterType variable as Importing uses this for something else!
03312 PORTNOTE("filter", "Removed use of AccusoftFilters")
03313 #if !defined(EXCLUDE_FROM_XARALX) && !defined(WEBSTER)
03314     // Andy Hills, 21-12-00
03315     // Warning: bodge alert!
03316     // At this stage, AccusoftFilters::FilterType may contain a useful value.
03317     // E.g. 9 for TIFF_LZW. This means that AccusoftFilters can make a special
03318     // case for exporting TIFFs, and export using CTIFFWriter instead of
03319     // calling Snowbound.
03320     // For whatever reason, the following line of code replaced this value with
03321     // m_pExportOptions->m_FilterID, which since the rewrite of the export dlg
03322     // contains the value 0.
03323     // This bodge ensures that we don't overwrite AccusoftFilters::FilterType
03324     // with 0.
03325     if (m_pExportOptions->GetFilterType() != 0)
03326         AccusoftFilters::SetFilterType(m_pExportOptions->GetFilterType());
03327 #endif
03328 
03329     // Make a note of the Disk file we are to use
03330     OutputFile = pFile;
03331 
03332     // Actually export the document
03333     BOOL ok = WriteFileHeader();
03334         
03335     // Do we want to use the existing palette, or generate a new one? The
03336     // value of BmapPrevDlg::m_bUseExistingPalette determines whether or
03337     // not one is needed to be generated, so no need to use any switch
03338     // logic.
03339     if ( ok )
03340     {
03341         ok = DoExportDoc( pOp, pFile, pPath, pDoc, GetRenderDepth (), 
03342                            m_pExportOptions->GetDPI (), 
03343                            m_pExportOptions->GetSelectionType (),
03344                            BmapPrevDlg::m_bUseExistingPalette );
03345     }
03346 
03347     ok &= WriteFileEnd();
03348 
03349     // pOptimised memory freed here.
03350     CleanUpAfterExport();
03351 
03352     return ok;
03353 }
03354 
03355 
03356 
03357 
03358 /********************************************************************************************
03359 
03360 >   BOOL BaseBitmapFilter::SetUpExportBitmapOptions(BitmapExportOptions **ppExportOptions, 
03361                                             KernelBitmap *pBitmap, BOOL OnlyDefaults = FALSE)
03362 
03363     Author:     Stefan_Stoykov (Xara Group Ltd) <camelotdev@xara.com>
03364     Created:    12/5/97
03365     Inputs:     
03366     Outputs:    ppExportOptions - pointer, where a pointer to the export options object 
03367                 will be returned
03368     Purpose:    Displays the export options dialog for this bitmap filter. This allows export
03369                 options to be obtained by somebody else then the filter
03370     Returns:    TRUE if worked, FALSE if failed.
03371 
03372 ********************************************************************************************/
03373 
03374 BOOL BaseBitmapFilter::SetUpExportBitmapOptions(BitmapExportOptions **ppExportOptions, 
03375                                                 KernelBitmap *pBitmap, BOOL OnlyDefaults)
03376 {
03377 #ifdef DO_EXPORT
03378     ERROR2IF(pBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmap null bitmap pointer specified");
03379 
03380     // Note this pointer for later use
03381     pExportBitmap = pBitmap;
03382 
03383     // Note this ptr for use in JPEG export.
03384     JPEGExportOptions::SetKernelBitmap(pBitmap);
03385     
03386     // Get a pointer to the actual bitmap so that we can get some details from it.
03387     OILBitmap *pOilBitmap = pBitmap->ActualBitmap;
03388     ERROR2IF(pOilBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmap null oil bitmap pointer");
03389 
03390     // Create a record of information about the export
03391     *ppExportOptions = CreateExportOptions();
03392     if (*ppExportOptions == NULL)
03393     {
03394         return FALSE;
03395     }
03396 
03397     // Get the default settings
03398     (*ppExportOptions)->RetrieveDefaults();
03399 
03400     // Specify to the user what the export options for depth etc are going to be
03401     (*ppExportOptions)->SetSelectionType(ABITMAP);
03402 
03403     // Get the details from the specified bitmap
03404     BitmapInfo BmInfo;
03405     pOilBitmap->GetInfo(&BmInfo);
03406     (*ppExportOptions)->SetDepth(BmInfo.PixelDepth);    // get the bitmaps bpp
03407     
03408     // Should really save the dpi when we load the file itself rather than doing
03409     // all this conversion with possible rounding errors.
03410     // Use the original size that has been calculated in the info header
03411     UINT32 PixWidth  = BmInfo.PixelWidth;
03412 //  UINT32 PixHeight = BmInfo.PixelHeight;
03413     MILLIPOINT  RecWidth = BmInfo.RecommendedWidth;
03414 //  MILLIPOINT  RecHeight = BmInfo.RecommendedHeight;
03415 
03416     if (PixWidth > 0)
03417     {
03418         (*ppExportOptions)->SetDPI((PixWidth * 72000.0)/(double)RecWidth);
03419     }
03420 
03421     // WEBSTER - markn 5/2/97
03422     // If the bitmap has a transparent colour index, store it in the options object
03423     // -1 means no transparent colour
03424     INT32 TransIndex = -1;
03425     if (!pBitmap->GetTransparencyIndex(&TransIndex))
03426         TransIndex = -1;
03427     (*ppExportOptions)->SetTransparencyIndex(TransIndex);
03428 
03429     // check whether only the defaults are needed
03430     if (OnlyDefaults)
03431         return TRUE;
03432 
03433     BOOL ok = GetExportOptions(*ppExportOptions);
03434     if (!ok)
03435     {
03436         if (*ppExportOptions != NULL)
03437         {
03438             delete *ppExportOptions;
03439             *ppExportOptions = NULL;
03440         }
03441         Error::SetError(_R(IDN_USER_CANCELLED),0);          // Expects error set on cancel
03442         return FALSE;                                   // if cancelled
03443     }
03444 
03445     return ok;
03446 #else
03447     return FALSE;
03448 #endif
03449 }
03450 
03451 /********************************************************************************************
03452 
03453 >   BOOL BaseBitmapFilter::DoExportBitmapWithOptions(Operation* pOp, CCLexFile* pFile, PathName* pPath,
03454                                                 KernelBitmap* pBitmap, BitmapExportOptions *pOptions)
03455 
03456     Author:     Stefan_Stoykov (Xara Group Ltd) <camelotdev@xara.com>
03457     Created:    25/7/97
03458     Inputs:         
03459     Purpose:    Exports the specified bitmap straight out to file with none of the rendering
03460                 that DoExport does. Uses the virtual fns of the inherited class.
03461                 Do not override unless really necessary. Similar to DoExportBitmap in the base
03462                 class, but uses the passed options, rather then invoking a dialog to get ones.
03463     Returns:    TRUE if worked, FALSE if failed.
03464 
03465 ********************************************************************************************/
03466 
03467 BOOL BaseBitmapFilter::DoExportBitmapWithOptions(Operation* pOp, CCLexFile* pFile, PathName* pPath,
03468                                                 KernelBitmap* pBitmap, BitmapExportOptions *pOptions)
03469 {
03470 #ifdef DO_EXPORT
03471     ERROR2IF(pBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmap null bitmap pointer specified");
03472 
03473     if (pOptions == NULL)
03474     {
03475         // Create a record of information about the export
03476         SetUpExportBitmapOptions(&pOptions, pBitmap, TRUE);
03477         if (pOptions == NULL)
03478             return FALSE;
03479     }
03480 
03481     // remember the old export options
03482     BitmapExportOptions *pOldOptions = GetBitmapExportOptions();
03483     if (pOldOptions != NULL)
03484         pOldOptions->RetrieveDefaults();
03485     
03486     // set the new ones
03487     SetExportOptions(pOptions);
03488     pOptions->SetAsDefaults();
03489 
03490     // Make a note of the Disk file we are to use
03491     OutputFile = pFile;
03492 
03493     // Note this pointer for later use
03494     pExportBitmap = pBitmap;
03495 
03496     // Note this ptr for use in JPEG export.
03497     JPEGExportOptions::SetKernelBitmap(pBitmap);
03498     
03499     // Get a pointer to the actual bitmap so that we can get some details from it.
03500     OILBitmap *pOilBitmap = pBitmap->ActualBitmap;
03501     ERROR2IF(pOilBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmap null oil bitmap pointer");
03502 
03503     // Get the details from the specified bitmap
03504     BitmapInfo BmInfo;
03505     pOilBitmap->GetInfo(&BmInfo);
03506     GetBitmapExportOptions()->SetDepth(BmInfo.PixelDepth);  // get the bitmaps bpp
03507     
03508     // Should really save the dpi when we load the file itself rather than doing
03509     // all this conversion with possible rounding errors.
03510     // Use the original size that has been calculated in the info header
03511     UINT32 PixWidth  = BmInfo.PixelWidth;
03512 //  UINT32 PixHeight = BmInfo.PixelHeight;
03513     MILLIPOINT  RecWidth = BmInfo.RecommendedWidth;
03514 //  MILLIPOINT  RecHeight = BmInfo.RecommendedHeight;
03515 
03516     if (PixWidth > 0)
03517     {
03518         //DPI = Mul32Div32( PixWidth,  72000, RecWidth );
03519         GetBitmapExportOptions()->SetDPI((PixWidth * 72000.0)/(double)RecWidth);
03520     }
03521 
03522     BOOL ok = TRUE;
03523 
03524     // Used to open the file up before starting DoExport. But this meant a cancel on the export
03525     // options dialog had filled the file, if it was already present. So now up up here if
03526     // not open already. In the PreviewBitmap case the file will already be open.
03527     if (!pFile->isOpen())
03528     {
03529         if (pFile->IsKindOf(CC_RUNTIME_CLASS(CCDiskFile)))
03530         {
03531             ok = OpenExportFile((CCDiskFile*) pFile, pPath);
03532             if (!ok) return FALSE;
03533         }
03534         else
03535         {
03536             TRACEUSER( "JustinF", _T("Tried to open non-CCDiskFile in BaseBitmapFilter::DoExportBitmap\n") );
03537             return FALSE;
03538         }
03539     }
03540 
03541     // Make a note of the Disk file we are to use
03542     OutputFile = pFile;
03543 
03544     // We do not use an export region so specify null.
03545     ExportRegion = NULL;
03546     
03547     // Actually write to the file, showing progress hourglass as we go
03548     ok = WriteBitmapToFile(pBitmap, GetBitmapExportOptions()->GetDPI());
03549 
03550     if (ok)
03551         WriteFileEnd();
03552 
03553     // All done - deallocate dynamic objects, stop the progress display/hourglass
03554     // and return success. (Also closes file).
03555     CleanUpAfterExport();
03556 
03557     // restore the old export options
03558     if (pOldOptions != NULL)
03559     {
03560         SetExportOptions(pOldOptions);
03561         pOldOptions->SetAsDefaults();
03562     }
03563 
03564     // restore the file
03565     OutputFile = pFile;
03566 
03567     return ok;
03568 #else
03569     return FALSE;
03570 #endif
03571 }
03572 
03573 
03574 
03575 /********************************************************************************************
03576 
03577 >   virtual BOOL BaseBitmapFilter::SaveExportBitmapsToFile(CCLexFile* pFile, PathName* pPath, BitmapExportParam* pParam,
03578                                                            BOOL DontShowFileName = FALSE)
03579 
03580     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03581     Created:    1/5/97
03582     Inputs:     pDiskFile - the file to put the exported data into
03583                 pPath - the pathname of the file to be exported to
03584                 pParam - the data to use when exporting the bitmaps
03585                 DontShowFileName - if set to true then don't show the filename in the progress string
03586     Purpose:    Exports the bitmaps specified by the BitmapExportParam object to a multi-
03587                 image capable filter. Each of the bitmaps will be saved to file using the
03588                 settings specified.
03589                 This is the baseclass version and so is usually overriden
03590     Returns:    TRUE if worked, FALSE if failed.
03591 
03592 ********************************************************************************************/
03593 
03594 BOOL BaseBitmapFilter::SaveExportBitmapsToFile(CCLexFile* pFile, PathName* pPath, BitmapExportParam* pParam,
03595                                                BOOL DontShowFileName)
03596 {
03597 #ifdef DO_EXPORT
03598     ERROR2IF(pFile == NULL || pPath == NULL, FALSE,"NULL Parameters");
03599     ERROR2IF(pParam == NULL,FALSE,"TI_GIFFilter::DoExportBitmaps null BitmapExportParam specified");
03600 
03601     ERROR3("BaseBitmapFilter::SaveExportBitmapsToFile calling baseclass version!");
03602     
03603     return TRUE;
03604 #endif
03605     return FALSE;
03606 }
03607 
03608 
03609 /********************************************************************************************
03610 
03611 >   virtual BOOL BaseBitmapFilter::ExportRenderNodes(RenderRegion *pRegion, ExportDC *pDC,
03612                                                      BOOL VisibleLayersOnly = FALSE,
03613                                                      BOOL CheckSelected = FALSE,
03614                                                      BOOL ShowProgress = TRUE)
03615 
03616     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03617     Created:    12/5/95
03618     Inputs:     pRegion         - the render region to export to.
03619                 pDc             - device context to use
03620                 VisibleLayersOnly - use visible layers or not
03621                 ShowProgress    - TRUE then start up a progress bar or FALSE assume the caller
03622                                   has done it.
03623     Returns:    TRUE if the export process completed successfully, FALSE if an error occured.
03624     Purpose:    Actually export the nodes to the given render region showing a progress bar
03625                 as we go. Assumes everything has been set up by ExportRender.
03626                 Overrides the baseclass version so that we can render in strips.
03627                 Ignores the setting of ShowProgress as we must be in charge of the progress
03628                 bar in this version. 
03629     SeeAlso:    ExportRender
03630 
03631 ********************************************************************************************/
03632 
03633 BOOL BaseBitmapFilter::ExportRenderNodes(RenderRegion *pRegion, ExportDC *pDC,
03634                                          BOOL VisibleLayersOnly, BOOL CheckSelected,
03635                                          BOOL ShowProgress)
03636 {
03637 #ifdef DO_EXPORT
03638     ERROR2IF(pRegion==NULL,FALSE,"BaseBitmapFilter::ExportRender null render region supplied");
03639 
03640     // Set up the Accusoft variables used for its redenring loop and call back form of the
03641     // do next strip. This is just in case we are going to change from using the Bitmap
03642     // filter to using the Accusoft filters as we are saving in a format which the Bitmap
03643     // filters do not understand. 
03644     //WEBSTER-Martin-03/01/97
03645 PORTNOTE("ExportAccusoft", "Removed use fo Accusoft filters")
03646 #ifndef EXCLUDE_FROM_XARALX
03647     AccusoftFilters::SetRenderVariables(this, pRegion, pDC, VisibleLayersOnly, CheckSelected);
03648 #endif
03649 
03650     // Set the bad rendering flag to its default value
03651     BadExportRender = FALSE;
03652 
03653     BOOL ok = TRUE;
03654     DocRect rClipRect = pRegion->GetRegionRect();
03655     
03656     BitmapExportOptions * pExportOptions = GetBitmapExportOptions();
03657     BOOL DidASwap = FALSE;
03658         
03659     // Check our class variable to see if we should render in strips or not
03660     // We do this so that things like the GIF filters 1bpp masked rendering can turn the
03661     // rendering in strips off. Should be on by default.
03662     if (RenderInStrips)
03663     {
03664         OurNumNodes = GetNumNodes();
03665         //UINT32 OurUpdateEvery = UpdateEvery;
03666         
03667         // We have a useful function in the GRenderBitmap class which tells us the number
03668         // of strips we are going to render with.
03669         GRenderBitmap *pGRenderBitmap = (GRenderBitmap*)pRegion;
03670         INT32 NumberOfStrips = pGRenderBitmap->GetNumBands();
03671         if (NumberOfStrips <= 0)
03672             NumberOfStrips = 1;
03673 TRACEUSER( "Gerry", _T("Number of bands is %d\n"), NumberOfStrips);
03674 TRACEUSER( "Gerry", _T("Number of nodes is %d\n"), OurNumNodes);
03675 
03676         // We need the progress bar to just move up once rather than for every strip    
03677         // plus include the number of lines in the export bitmap so that we can show
03678         // a progress bar for this part of the export. 
03679         // First, get the size of the bitmap we are going to export
03680         INT32 HeightInPixels = pGRenderBitmap->GetFullRegionHeight();
03681 TRACEUSER( "Gerry", _T("Full region height in pixels is %d\n"), HeightInPixels );
03682         
03683         SizeOfExport = OurNumNodes * NumberOfStrips;
03684         SetNumNodes(SizeOfExport);
03685 
03686         BitmapExportOptions* pOptions = GetBitmapExportOptions();
03687 
03688         // Start a progress update going
03689         // Extend it by the pixel height of the export
03690         String_64 ExportMessage(GetExportMsgID());
03691         ExportMessage = GetExportProgressString(OutputFile, GetExportMsgID());
03692         BeginSlowJob(200, FALSE, &ExportMessage);
03693 TRACEUSER( "Gerry", _T("Size of progress bar = %d\n"), SizeOfExport + HeightInPixels );
03694 
03695         // Reset this back to zero so that when we update the progress bar in WriteToFile
03696         // we can work out the current point reached on the progress bar
03697         SizeOfExport = 0;
03698         ProgressOffset = 0;
03699         m__StripStart = 0;
03700         
03701         // Find out which way we want to render by asking the filters
03702         BOOL BottomToTop = GetRenderBottomToTop();
03703         pGRenderBitmap->SetRenderBottomToTop(BottomToTop);
03704 
03705         // SMFIX this is where we will generate a new optimal palette if we need to
03706         BOOL CreatingPalette = !pExportOptions->IsPaletteValid() && pExportOptions->GetDepth() <= 8;
03707         if (CreatingPalette)
03708         {
03709             if (!pExportOptions->CreatePaletteOptimiser())
03710             {
03711                 // we didn't create an optimiser as we already have a good one
03712                 // use it to create the palette NOW! without the stats gathering part as are stats are still valid
03713                 pExportOptions->CreateValidPalette();
03714                 // let the optimiser fill in the palette in the export options
03715                 AlterPaletteContents(pExportOptions->GetLogicalPalette());
03716                 CreatingPalette = FALSE;
03717             }
03718         }
03719         else if(pExportOptions->GetDepth() <= 8)
03720         {
03721         // this call sets this palette in the lower reaches of the code from the palette held in the export options
03722             AlterPaletteContents(pExportOptions->GetLogicalPalette());
03723         }
03724 
03725         if (pExportOptions->IsCMYK())
03726         {
03727             // If we are doing a CMYK export then we need to do a really cunning 4-pass render
03728 
03729             TRACEUSER( "Gerry", _T("BaseBitmapFilter::ExportRenderNodes starting CMYK export\n") );
03730 
03731             // We need to save away the current ColourPlate and restore it afterwards
03732             // This may be problematic as the render region has already been created at this point
03733             // and also, the view will redraw when the ColourPlate is changed
03734             
03735             View* pView = pRegion->GetRenderView();
03736             ColourPlate* pCurPlate = pView->GetColourPlate();
03737             if (pCurPlate)
03738             {
03739                 pCurPlate = new ColourPlate(*pCurPlate);    // Make a copy of it
03740             }
03741             else
03742             {
03743                 pCurPlate = new ColourPlate;                // Make a default
03744                 pCurPlate->SetMonochrome(NULL, FALSE);      // Set to non-mono
03745             }
03746 
03747             // Get the first strip ready for action
03748             ok = pRegion->SetFirstBand();
03749             if (!ok)
03750             {
03751                 BadExportRender = TRUE;     // flag that something has gone wrong
03752                 EndWriteToFile();
03753                 EndSlowJob();
03754                 return FALSE;       
03755             }
03756 
03757             UINT32 nBandsCompleted = 0;
03758 
03759             // Now render all the other strips, if there are any, until we have completed
03760             // the entire region.
03761             do
03762             {
03763                 // Make sure this gets set back to the correct value before doing any rendering
03764                 pGRenderBitmap->SetDoBitmapConversion(TRUE);
03765                 
03766                 // Set up a destination bitmap of the strip size at 32 bpp
03767                 // We must somehow get the size of the bitmap here before
03768                 // it has actually been allocated in StartRender
03769                 WinRect BitmapRect = ((GRenderRegion*)pGRenderBitmap)->CalculateWinRect(pGRenderBitmap->GetClipRect());
03770 
03771                 TRACEUSER( "Gerry", _T("CMYK bitmap is (%d, %d)\n"), BitmapRect.GetWidth(), BitmapRect.GetHeight() );
03772                 LPBYTE pCMYKBits = NULL;
03773                 LPBITMAPINFO pCMYKInfo = AllocDIB(BitmapRect.GetWidth(), BitmapRect.GetHeight(), 32, &pCMYKBits);
03774                 memset(pCMYKBits, 0, BitmapRect.GetWidth() * BitmapRect.GetHeight() * sizeof(DWORD));
03775 
03776                 // Loop around the four plates
03777                 for (UINT32 PlateType = COLOURPLATE_CYAN; PlateType <= COLOURPLATE_KEY; PlateType += 1)
03778                 {
03779                     // Set the relevant ColourPlate on the View
03780                     ColourPlate* pPlate = new ColourPlate((ColourPlateType)PlateType, TRUE, FALSE);
03781                     pView->SetColourPlate(pPlate, FALSE);
03782                     delete pPlate;
03783 
03784                     // This will cause a new ColourContext to be got from the view
03785                     pRegion->ResetColourContext();
03786 
03787                     // Call the base class version to do the actual node exporting
03788                     // We have started the progress bar so tell it not to
03789                     ok = Filter::ExportRenderNodes(pRegion, pDC, VisibleLayersOnly, CheckSelected, FALSE);
03790                     // If a problem happened then get out quick.
03791                     // Assume function has stopped the rendering.
03792                     if (!ok)
03793                     {
03794                         if (pView)
03795                         {
03796                             pView->SetColourPlate(pCurPlate);
03797                             delete pCurPlate;
03798                         }
03799                         BadExportRender = TRUE;     // flag that something has gone wrong
03800                         EndWriteToFile();
03801                         EndSlowJob();
03802                         return FALSE;       
03803                     }
03804 
03805                     LPBITMAPINFO pRenderInfo = NULL;
03806                     LPBYTE pRenderData = NULL;
03807                     pGRenderBitmap->GetBitmapData(&pRenderInfo, &pRenderData, FALSE);
03808                     TRACEUSER( "Gerry", _T("Strip bitmap for plate %d is (%d, %d)\n"), PlateType, pRenderInfo->bmiHeader.biWidth, pRenderInfo->bmiHeader.biHeight);
03809                     BYTE* pSrcBits = pRenderData;
03810                     UINT32 NumPixels = pRenderInfo->bmiHeader.biWidth * pRenderInfo->bmiHeader.biHeight;
03811                     BYTE* pDestBits = ((BYTE*)pCMYKBits) + PlateType - COLOURPLATE_CYAN;    // Pointer arithmetic
03812                     for (UINT32 Pixel = 0; Pixel < NumPixels; Pixel++)
03813                     {
03814                         *pDestBits = (255 - pSrcBits[0]) * (255 - pSrcBits[3]) / 255;
03815                         pDestBits += 4;
03816                         pSrcBits += 4;
03817                     }
03818                 }
03819 
03820                 // Update our size of export variable
03821                 SizeOfExport += OurNumNodes;
03822                 // Update the filters stored progress offset value
03823                 ProgressOffset += OurNumNodes;
03824                 TRACEUSER( "Gerry", _T("BaseBitmapFilter::RenderNextStrip ProgressOffset = %d\n"), ProgressOffset);
03825                             
03826                 // Now we need to get WriteFrame to output the composited bitmap
03827                 // The easiest way to do this will be to replace the bitmap in the render region
03828                 // with the composited one and just call WriteFrame as normal
03829                 DWORD* pSrcBits = (DWORD*)pGRenderBitmap->Get32BitRGBQuadData();
03830                 UINT32 NumPixels = pGRenderBitmap->GetSizeOfRGBQuadData();
03831                 memcpy(pSrcBits, pCMYKBits, NumPixels * sizeof(DWORD));
03832 
03833                 // We need to stop GetBitmapData from doing another conversion when reading the CMYK data
03834                 pGRenderBitmap->SetDoBitmapConversion(FALSE);
03835 
03836                 // Free the temp bitmap
03837                 FreeDIB(pCMYKInfo, pCMYKBits);
03838 
03839                 // Save that data out to file, this should update SizeOfExport with the
03840                 // current strip size
03841                 // Note: it will also render all the remaining strips
03842                 ok = WriteFrame();
03843                 // If a problem happened then get out quick.
03844                 if (!ok)
03845                 {
03846                     if (pView)
03847                     {
03848                         pView->SetColourPlate(pCurPlate);
03849                         delete pCurPlate;
03850                     }
03851                     BadExportRender = TRUE;     // flag that something has gone wrong
03852                     EndWriteToFile();
03853                     EndSlowJob();
03854                     return FALSE;       
03855                 }
03856 
03857                 // Advance the progress bar
03858                 UINT32 nProgress = UINT32((double(nBandsCompleted) / double(NumberOfStrips)) * 200.0);
03859                 TRACEUSER( "Gerry", _T("nProgress = %d\n"), nProgress);
03860 
03861                 if ( !ContinueSlowJob (nProgress) )
03862                 {
03863                     // Error; close down and exit nicely.
03864                     // Must set an error otherwise we will get the dreaded reporting error
03865                     // when none set message.
03866                     // If no error message ID set in this filter then use default
03867 
03868                     // Andy, 13-12-00
03869                     // N.B. At the moment, things go pear-shaped if we press ESC during export.
03870                     // e.g. subsequent presses of 'preview' do not generate a preview.
03871                     // However it wasn't exactly well behaved before, e.g. sometimes gave
03872                     // internal error 'Failed to create an intermediate bitmap pointer!', or
03873                     // access violated if the user clicked 'background transparency' after a
03874                     // cancelled export.
03875                     if (pView)
03876                     {
03877                         pView->SetColourPlate(pCurPlate);
03878                         delete pCurPlate;
03879                     }
03880                     if ( StopExportMsgID == 0 )
03881                         Error::SetError ( _R(IDW_CANCELEXPORT) );
03882                     else
03883                         Error::SetError ( StopExportMsgID );
03884                     pRegion->StopRender ();
03885                     if ( ShowProgress )
03886                         EndSlowJob ();
03887                     return FALSE;
03888                 }
03889 
03890                 nBandsCompleted ++;
03891 
03892                 // Check if there are any more bands
03893             } while (pRegion->GetNextBand());
03894 
03895             if (pView)
03896             {
03897                 pView->SetColourPlate(pCurPlate);
03898                 delete pCurPlate;
03899             }
03900         }
03901         else
03902         {
03903             for (INT32 loop = 0; loop < 2; loop++) // never do this more than twice once for the palette and once to write it out to file
03904             {
03905                 TRACEUSER( "Gerry", _T("BaseBitmapFilter::ExportRenderNodes loop = %d\n"), loop);
03906 
03907                 if (!CreatingPalette && pExportOptions->GetDepth() <= 8)
03908                 {
03909                     DidASwap = pExportOptions->SwapEditedColoursInLogicalPalette();
03910                     AlterPaletteContents(pExportOptions->GetLogicalPalette());
03911                 }
03912 
03913                 // Get the first strip ready for action
03914                 ok = pRegion->SetFirstBand();
03915                 if (!ok)
03916                 {
03917                     BadExportRender = TRUE;     // flag that something has gone wrong
03918                     EndWriteToFile();
03919                     EndSlowJob();
03920                     return FALSE;       
03921                 }
03922 
03923                 UINT32 nBandsCompleted = 0;
03924 
03925                 // Now render all the other strips, if there are any, until we have completed
03926                 // the entire region.
03927                 do
03928                 {
03929                     // Call the base class version to do the actual node exporting
03930                     // We have started the progress bar so tell it not to
03931                     ok = Filter::ExportRenderNodes(pRegion, pDC, VisibleLayersOnly, CheckSelected, FALSE);
03932                     // If a problem happened then get out quick.
03933                     // Assume function has stopped the rendering.
03934                     if (!ok)
03935                     {
03936                         BadExportRender = TRUE;     // flag that something has gone wrong
03937                         EndWriteToFile();
03938                         EndSlowJob();
03939                         return FALSE;       
03940                     }
03941 
03942                     if (!CreatingPalette)
03943                     {
03944                         // Update our size of export variable
03945                         SizeOfExport += OurNumNodes;
03946                         // Update the filters stored progress offset value
03947                         ProgressOffset += OurNumNodes;
03948                         TRACEUSER( "Gerry", _T("BaseBitmapFilter::RenderNextStrip ProgressOffset = %d\n"),ProgressOffset);
03949                     }
03950                                 
03951                     // Save that data out to file, this should update SizeOfExport with the
03952                     // current strip size
03953                     if (CreatingPalette)
03954                     {
03955                         // calc the stats for an optimised palette
03956                         pExportOptions->GatherPaletteStats( ((GRenderRegion * )pRegion)->Get32BitRGBQuadData(),
03957                                             ((GRenderRegion * )pRegion)->GetSizeOfRGBQuadData());
03958                     }
03959                     else
03960                         ok = WriteFrame();
03961                     // If a problem happened then get out quick.
03962                     if (!ok)
03963                     {
03964                         BadExportRender = TRUE;     // flag that something has gone wrong
03965                         EndWriteToFile();
03966                         EndSlowJob();
03967                         return FALSE;       
03968                     }
03969 
03970                     // Advance the progress bar
03971                     UINT32 nProgress;
03972                     // if this image doesn't need a palette, scale the progress value to
03973                     // the full length of the bar
03974                     if (!CreatingPalette && loop==0)
03975                         nProgress = UINT32((double(nBandsCompleted) / double(NumberOfStrips)) * 200.0);
03976                     // otherwise, scale the progress value to half the length of the bar
03977                     // (as this rendering loop will occur twice)
03978                     else
03979                         nProgress = UINT32((double(nBandsCompleted) / double(NumberOfStrips)) * 100.0 + double(loop)*100.0);
03980                     TRACEUSER( "Gerry", _T("nProgress = %d\n"), nProgress);
03981 
03982                     if ( !ContinueSlowJob (nProgress) )
03983                     {
03984                         // Error; close down and exit nicely.
03985                         // Must set an error otherwise we will get the dreaded reporting error
03986                         // when none set message.
03987                         // If no error message ID set in this filter then use default
03988 
03989                         // Andy, 13-12-00
03990                         // N.B. At the moment, things go pear-shaped if we press ESC during export.
03991                         // e.g. subsequent presses of 'preview' do not generate a preview.
03992                         // However it wasn't exactly well behaved before, e.g. sometimes gave
03993                         // internal error 'Failed to create an intermediate bitmap pointer!', or
03994                         // access violated if the user clicked 'background transparency' after a
03995                         // cancelled export.
03996                         if ( StopExportMsgID == 0 )
03997                             Error::SetError ( _R(IDW_CANCELEXPORT) );
03998                         else
03999                             Error::SetError ( StopExportMsgID );
04000                         pRegion->StopRender ();
04001                         if ( ShowProgress )
04002                             EndSlowJob ();
04003                         return FALSE;
04004                     }
04005 
04006                     nBandsCompleted ++;
04007 
04008                     // Check if there are any more bands
04009                 } while (pRegion->GetNextBand());
04010             
04011                 if (CreatingPalette)
04012                 {
04013                     CreatingPalette = FALSE;
04014                     // let the optimiser fill in the palette in the export options
04015                     pExportOptions->CreateValidPalette();
04016                     // set this as the palette being used in output dib
04017                     AlterPaletteContents(pExportOptions->GetLogicalPalette());
04018                     // Reset the clip region to what it was when we started this
04019                     pRegion->SetClipRect(rClipRect);
04020                 }
04021                 else
04022                     break; // leave this for loop now
04023             }
04024         }
04025 
04026         if (DidASwap)
04027         {
04028             pOptions->SwapEditedColoursInLogicalPalette();
04029             AlterPaletteContents(pOptions->GetLogicalPalette());
04030         }
04031         // Close down progress display
04032         // Do it before ending as then the TI GIF filter can show a progress bar on
04033         // its possible masked rendering for transparency and export of the GIF data
04034         // which happens in the EndWriteToFile.
04035         EndSlowJob();
04036     }
04037     else
04038     {
04039         // Call the base class version to do the actual node exporting
04040         // Use the pass in version to say whether we need to start the progress bar or not.
04041         // Assume that we are the GIF filter renderer and so do not try and output the data
04042         // at all. We will ensure as this might be dangerous.
04043 PORTNOTE("filter", "Removed use of GIFFilter")
04044 #ifndef EXCLUDE_FROM_XARALX
04045         ERROR3IF(!(this->IS_KIND_OF(TI_GIFFilter)) && !(this->IS_KIND_OF(PNGFilter)),
04046                  "BaseBitmapFilter::ExportRenderNodes rendering in strips off");
04047 #else
04048         ERROR3IF(!(this->IS_KIND_OF(PNGFilter)),
04049                  "BaseBitmapFilter::ExportRenderNodes rendering in strips off");
04050 #endif
04051 
04052         ok = Filter::ExportRenderNodes(pRegion, pDC, VisibleLayersOnly,
04053                                        CheckSelected, ShowProgress);
04054 
04055         // SMFIX optimise the palette in the no strip based manner
04056         BOOL CreatingPalette = !pExportOptions->IsPaletteValid();
04057         if (CreatingPalette)
04058         {
04059             // create a palette optimiser (or retrieve a valid one)
04060             if (pExportOptions->CreatePaletteOptimiser())
04061             {
04062                 // we need to gather stats as we have made a virgin new optimiser
04063                 pExportOptions->GatherPaletteStats( ((GRenderRegion * )pRegion)->Get32BitRGBQuadData(),
04064                                     ((GRenderRegion * )pRegion)->GetSizeOfRGBQuadData());
04065             }
04066 
04067             // let the optimiser fill in the palette in the export options
04068             pExportOptions->CreateValidPalette();
04069             // let the optimiser fill in the palette in the export options
04070             AlterPaletteContents(pExportOptions->GetLogicalPalette());
04071         }
04072 
04073 /*      // SMFIX
04074         if(pRegion->m_DoCompression)
04075         {
04076             BITMAPINFO* pBMPInfo = NULL;
04077             BYTE* pBMPData = NULL;
04078             ((GRenderBitmap*)pRegion)->GetBitmapData(&pBMPInfo,&pBMPData);
04079             ((GRenderBitmap*)pRegion)->GetDrawContext()->ConvertBitmap(&pBMPInfo->bmiHeader,pBMPData,&pBMPInfo->bmiHeader,pBMPData,0);
04080         }*/
04081     }
04082 
04083     // return outcome to caller
04084     return ok;
04085 #else
04086     return FALSE;
04087 #endif
04088 }
04089 
04090 
04091 /********************************************************************************************
04092 
04093 >   BOOL BaseBitmapFilter::WriteToFile( BOOL AtEnd)
04094 
04095     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
04096     Created:    22/8/94
04097     Inputs:     AtEnd is TRUE if this is the last chunk of the file, FALSE if not.
04098     Purpose:    Writes out the bitmap to a file. Inherited classes override this to write
04099                 in different file formats.
04100                 AtEnd is ignored now and should always be set to TRUE.
04101                 
04102     Returns:    TRUE if worked, FALSE if failed.
04103 
04104 ********************************************************************************************/
04105 
04106 BOOL BaseBitmapFilter::WriteToFile( BOOL AtEnd)
04107 {
04108     ENSURE(FALSE, "Base class bitmap filter WriteToFile called");
04109     return FALSE;
04110 }
04111 
04112 /********************************************************************************************
04113 
04114 >   BOOL BaseBitmapFilter::EndWriteToFile( )
04115 
04116     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04117     Created:    12/5/95
04118     Inputs:     -
04119     Purpose:    Cleans up after writing the bitmap data out to a file. Inherited classes
04120                 override this to write in different file formats.
04121     Returns:    TRUE if worked, FALSE if failed.
04122 
04123 ********************************************************************************************/
04124 
04125 BOOL BaseBitmapFilter::EndWriteToFile( )
04126 {
04127     ENSURE(FALSE, "Base class bitmap filter EndWriteToFile called");
04128     return FALSE;
04129 }
04130 
04131 
04132 /********************************************************************************************
04133 
04134 >   virtual BOOL BaseBitmapFilter::WriteBitmapToFile(KernelBitmap* pKernelBitmap, double Dpi)
04135 
04136     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04137     Created:    25/4/95
04138     Inputs:     Pointer to the bitmap to be exported.
04139     Returns:    TRUE if worked, FALSE if errored.
04140     Purpose:    Physically put the bitmap into the disk.  Inherited classes override this to write
04141                 in different file formats.
04142     SeeAlso:    WriteDataToFile(); AccusoftFilters::WriteToFile; AccusoftFilters::WriteDataToFile;
04143 
04144 ********************************************************************************************/
04145 
04146 BOOL BaseBitmapFilter::WriteBitmapToFile(KernelBitmap* pKernelBitmap, double Dpi)
04147 {
04148     ERROR3("Base class bitmap filter WriteBitmapToFile called");
04149     return FALSE;
04150 }
04151 
04152 /********************************************************************************************
04153 
04154 >   virtual BOOL BaseBitmapFilter::WriteBitmapToFile(KernelBitmap* pKernelBitmap, BaseCamelotFilter *pFilter,
04155                                                      CCLexFile *pFile, INT32 Compression)
04156     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04157     Created:    20/6/96
04158     Inputs:     pKernelBitmap   - Pointer to the bitmap to be exported.
04159                 pFilter         - Pointer to the BaseCamelot filter which provides progress functions
04160                 pFile           - Pointer to the CCFile class to use for export
04161                 Compression     - used to flag how much compression of the data is required.
04162     Returns:    TRUE if worked, FALSE if errored.
04163     Purpose:    Physically put the bitmap into the disk.  Inherited classes override this to write
04164                 in different file formats.
04165                 This is used by the native/web format to output the actual bitmap data content
04166                 of a bitmap definition record. The function can assume that the CCFile is open
04167                 and ready for writing and must use the functions provided by pFilter to update
04168                 the progress system.
04169                 This is the baseclass version and hence needs overiding, hence the error.
04170     SeeAlso:    BitmapListComponent::SaveBitmapDefinition;
04171 
04172 ********************************************************************************************/
04173 
04174 BOOL BaseBitmapFilter::WriteBitmapToFile(KernelBitmap* pKernelBitmap, BaseCamelotFilter *pFilter,
04175                                          CCLexFile *pFile, INT32 Compression)
04176 {
04177     // Create a record of information about the export
04178     m_pExportOptions = CreateExportOptions();
04179     if (GetBitmapExportOptions() == NULL)
04180     {
04181         return FALSE;
04182     }
04183 
04184     OutputFile = pFile;
04185 
04186     return TRUE;
04187 }
04188 
04189 /********************************************************************************************
04190 
04191 >   static  DocRect BaseBitmapFilter::GetSizeOfDrawing(Spread *pSpread=NULL)
04192 
04193     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04194     Created:    18/4/95
04195     Inputs:     pointer to the spread to use
04196     Purpose:    Works out the size of the rectangle encompassing the drawing.
04197                 Code also used to work out the pixel size in the bitmap export options
04198                 dialog box.
04199 
04200                 Added by Graham 11/4/97: If pSpread is NULL, we get the first
04201                 spread of the current document to use
04202 
04203     Returns:    Size of the rectangle encompassing the drawing.
04204     SeeAlso:    BmpPrefsDlg::RecalculateSize; BaseBitmapFilter::DoExport;
04205 
04206 ********************************************************************************************/
04207 
04208 DocRect BaseBitmapFilter::GetSizeOfDrawing(Spread *pSpread)
04209 {
04210     // Start out with an empty clip rect
04211     DocRect SpreadRect;
04212     SpreadRect.MakeEmpty();
04213 
04214     //If we have not been passed a spread...
04215     if (pSpread == NULL)
04216     {
04217         //Then let's get the first spread of the current document
04218         Document* pdocCurrent=Document::GetCurrent();
04219         ERROR2IF(pdocCurrent==NULL, DocRect(0,0,0,0), "BaseBitmapFilter - no current document");
04220 
04221         //And finally the current spread
04222 PORTNOTE("spread", "Multi-spread warning!")
04223         pSpread=GetFirstSpread(pdocCurrent);
04224         ERROR2IF(pSpread==NULL, DocRect(0,0,0,0), "BaseBitmapFilter - no spread");
04225     }
04226 
04227     // We need to take into account the fact that some layers may not be visible
04228     Layer* pLayer = pSpread->FindFirstLayer(); 
04229     while (pLayer != NULL)
04230     {
04231         // We've got a layer so check to see if it is visible
04232         // Added 8/4/97 extra checks to see if we are the special layers
04233         // and so shouldn't be included in the bounding calulations
04234         if (pLayer->IncludeLayerInBoundingCalcs())
04235         {
04236             // This one is visible, so union it in
04237             DocRect LayerRect = pLayer->GetBoundingRect();
04238             SpreadRect = SpreadRect.Union(LayerRect);
04239         }
04240 
04241         // Get the next sibling layer
04242         pLayer = pLayer->FindNextLayer();   
04243     }
04244 
04245     // return the found rectangle to the caller.    
04246     return SpreadRect;
04247 }
04248 
04249 /********************************************************************************************
04250 
04251 >   static  DocRect BaseBitmapFilter::GetSizeOfSpread(Spread *pSpread)
04252 
04253     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04254     Created:    18/4/95
04255     Inputs:     pointer to the spread to use
04256     Purpose:    Works out the size of the rectangle encompassing the spread.
04257                 Code also used to work out the pixel size in the bitmap export options
04258                 dialog box.
04259     Returns:    Size of the rectangle encompassing the spread.
04260     SeeAlso:    BmpPrefsDlg::RecalculateSize; BaseBitmapFilter::PrepareToExport;
04261 
04262 ********************************************************************************************/
04263 
04264 DocRect BaseBitmapFilter::GetSizeOfSpread(Spread *pSpread)
04265 {
04266     // Start out with an empty clip rect
04267     DocRect SpreadRect;
04268     SpreadRect.MakeEmpty();
04269 
04270     if (pSpread == NULL)
04271     {
04272         ERROR3("BaseBitmapFilter::GetSizeOfSpread null spread");
04273         return SpreadRect;
04274     }
04275 
04276     // build a rectangle out of all the pages in the selected spread
04277     Node *pPage = pSpread->FindFirstPageInSpread(); 
04278     ERROR3IF(pPage == NULL, "Spread has no pages");
04279 
04280     while (pPage)
04281     {
04282         if (pPage->GetRuntimeClass() == CC_RUNTIME_CLASS(Page) )
04283             SpreadRect = SpreadRect.Union(( (Page*)pPage)->GetPageRect() );
04284 
04285         pPage = pPage->FindNext();
04286     }
04287 
04288     ERROR3IF(SpreadRect.IsEmpty(),"Current spread has no pages");
04289 
04290     return SpreadRect;
04291 }    
04292 
04293 /********************************************************************************************
04294 
04295 >   static  BOOL    BaseBitmapFilter::GetSizeOfBitmap(INT32 *PixelWidth, INT32 *PixelHeight)
04296 
04297     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04298     Created:    25/4/95
04299     Inputs:     -
04300     Outputs:    PixelWidth  bitmap width in pixels
04301                 PixelHeight bitmap height in pixels
04302     Purpose:    Works out the size of the bitmap in the bitmap export options
04303                 dialog box.
04304     Returns:    True if completed ok.
04305     SeeAlso:    BmpPrefsDlg::RecalculateSize; BaseBitmapFilter::PrepareToExport;
04306 
04307 ********************************************************************************************/
04308 BOOL    BaseBitmapFilter::GetSizeOfBitmap(INT32 *PixelWidth, INT32 *PixelHeight)
04309 {
04310 #ifdef DO_EXPORT
04311     ERROR2IF(pExportBitmap==NULL,FALSE,"BaseBitmapFilter::GetSizeOfBitmap no bitmap");
04312     ERROR2IF(PixelWidth==NULL,FALSE,"BaseBitmapFilter::GetSizeOfBitmap no PixelWidth");
04313     ERROR2IF(PixelHeight==NULL,FALSE,"BaseBitmapFilter::GetSizeOfBitmap no PixelHeight");
04314 
04315     // Set return values in case of early exit
04316     *PixelWidth = 0;
04317     *PixelHeight = 0;
04318 
04319     // Get a pointer to the actual bitmap so that we can get some details from it.
04320     OILBitmap *pOilBitmap = pExportBitmap->ActualBitmap;
04321     ERROR3IF(pOilBitmap == NULL,"BaseBitmapFilter::GetSizeOfBitmap null oil bitmap pointer");
04322     if (pOilBitmap)
04323     {
04324         BitmapInfo BmInfo;
04325         pOilBitmap->GetInfo(&BmInfo);
04326         *PixelWidth  = BmInfo.PixelWidth;
04327         *PixelHeight = BmInfo.PixelHeight;
04328     }
04329 
04330     return TRUE;
04331 #else
04332     return FALSE;
04333 #endif
04334 } 
04335 
04336 /********************************************************************************************
04337 
04338 >   virtual BOOL BaseBitmapFilter::IsThisBppOk(UINT32 Bpp)
04339 
04340     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04341     Created:    27/4/95
04342     Inputs:     Bpp or Colour depth.
04343     Returns:    TRUE if this filter can cope with this colour depth, FALSE otherwise.
04344     Purpose:    Check if this Bitmap filter can cope with saving at this Bpp/Colour depth.
04345     SeeAlso:    OpMenuExport::DoWithParam;
04346 
04347 ********************************************************************************************/
04348 
04349 BOOL BaseBitmapFilter::IsThisBppOk(UINT32 Bpp)
04350 {
04351     // Base class version so always return FALSE.
04352     return FALSE;
04353 }
04354 
04355 /********************************************************************************************
04356 
04357 >   virtual UINT32 BaseBitmapFilter::GetExportMsgID()
04358 
04359     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04360     Created:    18/09/95
04361     Returns:    The id of the message to put on the progress display whilst exporting.
04362     Purpose:    Used to get the message id to be used during export.
04363                 Virtual, so that two stage exporters can change the message.
04364     SeeAlso:    DoExport;
04365 
04366 ********************************************************************************************/
04367 
04368 UINT32 BaseBitmapFilter::GetExportMsgID()
04369 {
04370     if (GeneratingOptimisedPalette())
04371         return _R(IDS_GENOPTPALMSGID);          // "Generating optimised palette..."
04372     else
04373         return Filter::GetExportMsgID();
04374 }
04375 
04376 /********************************************************************************************
04377 
04378 >   virtual BOOL BaseBitmapFilter::GenerateOptimisedPalette(Spread *pSpread, UINT32 Depth, double DPI, BOOL SnapToBrowserPalette, UINT32 NumColsInPalette = 0, BOOL UsePrimaryCols = TRUE)
04379 
04380     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04381     Created:    30/5/96
04382     Inputs:     pSpread             = ptr to spread
04383                 Depth               = The BPP of the bitmap
04384                 DPI                 = the dpi of the bitmap
04385                 NumColsInPalette    = prefered number of cols in palette (0 = select maximum allowed)
04386                                       (only applies when Depth == 8)
04387                 UsePrimaryCols      = Put primary colours in palette
04388                                       (only applies when Depth == 8)
04389                 SnapToBrowserPalette= TRUE if the palette should be snapped to the browser palette after generation
04390 
04391     Returns:    TRUE if Palette generated ok
04392     Purpose:    Generates an optimised palette to use during export
04393     SeeAlso:    -
04394 
04395 ********************************************************************************************/
04396 
04397 BOOL BaseBitmapFilter::GenerateOptimisedPalette(Spread *pSpread, UINT32 Depth, double DPI, BOOL SnapToBrowserPalette, UINT32 NumColsInPalette, BOOL UsePrimaryCols)
04398 {
04399 #ifdef DO_EXPORT
04400     if (Depth > 8)
04401     {
04402         pOptimisedPalette = NULL;
04403         return TRUE;
04404     }
04405 
04406     TRACEUSER( "Neville", _T("Trying to generate an optimised palette ...\n") );
04407 
04408     WeAreGeneratingOptPalette = TRUE;
04409 
04410     // Don't use rendering matrix when exporting BMPs as it uses coordinates as is
04411     Matrix Identity;
04412 
04413     // Don't use view scale; set to 1
04414     FIXED16 Scale(1);
04415 
04416     // Only use special 8bpp palette if the UsePrimaryColours flag is TRUE
04417     BOOL use8bpp = ((Depth == 8) && UsePrimaryCols);
04418     GRenderOptPalette* pPalRegion = new GRenderOptPalette(ClipRect, Identity, Scale, 32, DPI, use8bpp);
04419     if (pPalRegion)
04420     {
04421         // we need a View to Attach to, so that:
04422         //      default Quality setting
04423         //      CalcPixelWidth etc get called
04424 
04425         DocView *View = DocView::GetCurrent();
04426         if (View)
04427         {
04428             // Attach to the right device. (note no DC)
04429             pPalRegion->AttachDevice(View, NULL, pSpread);
04430         }
04431         else
04432             ERROR2(FALSE,"BaseBitmapFilter::GenerateOptimisedPalette no current view");
04433 
04434         RenderInStrips = TRUE;
04435 
04436         // Now do an export render pass, using the Palette Region
04437         if (ExportRender(pPalRegion))
04438         {
04439             UINT32 MaxColours = 1U<<Depth; // let's not use floating point here - UINT32(pow(2,Depth));
04440 
04441             if (NumColsInPalette < 1)
04442                 NumColsInPalette = MaxColours;
04443 
04444             if (use8bpp && NumColsInPalette < 20)
04445                 NumColsInPalette = 20;
04446 
04447             if (NumColsInPalette > MaxColours)
04448                 NumColsInPalette = MaxColours;
04449 
04450             // All went ok, so extract the Optimised palette from the Region
04451             pOptimisedPalette = pPalRegion->GetOptimisedPalette(MaxColours, NumColsInPalette, GetNumReservedColours(), SnapToBrowserPalette);
04452             
04453             if (pOptimisedPalette) TRACEUSER( "Neville", _T("Blimey. We got an optimised palette to use.\n") );
04454         }
04455 
04456         delete pPalRegion;
04457     }
04458 
04459     WeAreGeneratingOptPalette = FALSE;
04460 #endif
04461     return TRUE;
04462 }
04463 
04464 /********************************************************************************************
04465 
04466 >   virtual BOOL BaseBitmapFilter::GenerateOptimisedPalette(Spread *pSpread, BitmapExportOptions *pOptions, BOOL SnapToBrowserPalette)
04467 
04468     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
04469     Created:    16/1/97
04470     Inputs:     pSpread              = ptr to spread
04471                 pOptions             = ptr to bitmap export options
04472                 SnapToBrowserPalette = If TRUE, snap all optimised palette entries to the browser palette
04473 
04474     Returns:    TRUE if Palette generated ok
04475     Purpose:    Generates an optimised palette to use during export
04476 
04477                 This is an alternative interface to GenerateOptimisedPalette(Spread *pSpread, UINT32 Depth, double DPI, UINT32 NumColsInPalette, BOOL UsePrimaryCols);
04478 
04479                 WEBSTER - markn 16/1/97
04480     SeeAlso:    -
04481 
04482 ********************************************************************************************/
04483 
04484 BOOL BaseBitmapFilter::GenerateOptimisedPalette(Spread *pSpread, BitmapExportOptions *pOptions, BOOL SnapToBrowserPalette)
04485 {
04486     if (pSpread != NULL && pOptions != NULL)
04487     {
04488         return GenerateOptimisedPalette(pSpread,
04489                                         pOptions->GetDepth(), 
04490                                         pOptions->GetDPI(),
04491                                         SnapToBrowserPalette,
04492                                         pOptions->GetNumColsInPalette(),
04493                                         pOptions->GetUseSystemColours()
04494                                         );
04495     }
04496 
04497     return FALSE;
04498 }
04499 
04500 void BaseBitmapFilter::AlterPaletteContents( LPLOGPALETTE pPalette )
04501 {
04502     return;
04503 }
04504 
04505 /********************************************************************************************
04506 
04507 >   static BOOL BaseBitmapFilter::GeneratingOptimisedPalette()
04508 
04509     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
04510     Created:    30/5/96
04511     Inputs:     -
04512     Returns:    TRUE if we are in the middle of generating an optimised Palette
04513     Purpose:    Find out if we are currently generating an optimised palette or not
04514     SeeAlso:    -
04515 
04516 ********************************************************************************************/
04517 
04518 BOOL BaseBitmapFilter::GeneratingOptimisedPalette()
04519 {
04520     return WeAreGeneratingOptPalette;
04521 }
04522 
04523 
04524 /********************************************************************************************
04525 
04526 >   virtual BOOL BaseBitmapFilter::WriteFileHeader(void)
04527 
04528     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
04529     Created:    12/6/96
04530     Inputs:     -
04531     Returns:    FALSE if failed else TRUE
04532     Purpose:    To write out the file specific header data
04533     SeeAlso:    -
04534 
04535 ********************************************************************************************/
04536 
04537 BOOL BaseBitmapFilter::WriteFileHeader(void)
04538 {
04539     return(TRUE);
04540 }
04541 
04542 
04543 /********************************************************************************************
04544 
04545 >   virtual BOOL BaseBitmapFilter::WritePreFrame(void)
04546 
04547     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
04548     Created:    12/6/96
04549     Inputs:     -
04550     Returns:    FALSE if failed else TRUE
04551     Purpose:    To write out any frame specific info before the image
04552     SeeAlso:    -
04553 
04554 ********************************************************************************************/
04555 
04556 BOOL BaseBitmapFilter::WritePreFrame(void)
04557 {
04558     return(TRUE);
04559 }
04560 
04561 
04562 /********************************************************************************************
04563 
04564 >   virtual BOOL BaseBitmapFilter::WriteFileHeader(void)
04565 
04566     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
04567     Created:    12/6/96
04568     Inputs:     -
04569     Returns:    FALSE if failed else TRUE
04570     Purpose:    To write out the image itself
04571                 This base class version actually calls the WriteToFile() function so that
04572                 derived classes do not have to implement any of the multi-image stuff
04573     SeeAlso:    -
04574 
04575 ********************************************************************************************/
04576 
04577 BOOL BaseBitmapFilter::WriteFrame(void)
04578 {
04579     return(WriteToFile(TRUE));
04580 }
04581 
04582 
04583 /********************************************************************************************
04584 
04585 >   virtual BOOL BaseBitmapFilter::WritePostFrame(void)
04586 
04587     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
04588     Created:    12/6/96
04589     Inputs:     -
04590     Returns:    FALSE if failed else TRUE
04591     Purpose:    To write out any frame specific info after the image
04592     SeeAlso:    -
04593 
04594 ********************************************************************************************/
04595 
04596 BOOL BaseBitmapFilter::WritePostFrame(void)
04597 {
04598     return(TRUE);
04599 }
04600 
04601 
04602 /********************************************************************************************
04603 
04604 >   virtual BOOL BaseBitmapFilter::WriteFileEnd(void)
04605 
04606     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
04607     Created:    12/6/96
04608     Inputs:     -
04609     Returns:    FALSE if failed else TRUE
04610     Purpose:    To write out the file specific data at the end of the file
04611                 This base class version calls EndWriteToFile() so that derived classes
04612                 do not have to implement the multi-image stuff
04613     SeeAlso:    -
04614 
04615 ********************************************************************************************/
04616 
04617 BOOL BaseBitmapFilter::WriteFileEnd(void)
04618 {
04619     return(EndWriteToFile());
04620 }
04621 
04622 
04623 /********************************************************************************************
04624 
04625 >   virtual BOOL BaseBitmapFilter::WritePreSecondPass(void)
04626 
04627     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
04628     Created:    17/6/96
04629     Inputs:     -
04630     Returns:    FALSE if failed else TRUE
04631     Purpose:    Called before the second pass of a two pass export so the filter can reset
04632                 itself
04633     SeeAlso:    -
04634 
04635 ********************************************************************************************/
04636 
04637 BOOL BaseBitmapFilter::WritePreSecondPass(void)
04638 {
04639     return(TRUE);
04640 }
04641 
04642 
04643 /********************************************************************************************
04644 
04645 >   virtual BOOL BaseBitmapFilter::WritePostOptimisedPalette(void)
04646 
04647     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
04648     Created:    17/6/96
04649     Inputs:     -
04650     Returns:    FALSE if failed else TRUE
04651     Purpose:    Called after the optimised palette has been generated but before the export 
04652                 of the bitmap.
04653     SeeAlso:    -
04654 
04655 ********************************************************************************************/
04656 
04657 BOOL BaseBitmapFilter::WritePostOptimisedPalette(void)
04658 {
04659     return(TRUE);
04660 }
04661 
04662 
04663 /********************************************************************************************
04664 >   UINT32 BaseBitmapFilter::GetNumReservedColours()
04665 
04666     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
04667     Created:    31/5/96
04668     Inputs:     -
04669     Returns:    The numbers of colours the filter would like to reserve.  The base class
04670                 reserves zero colours.
04671     Purpose:    Override this to leave spaces in the palette.  eg the GIF filter reserves an
04672                 index for the transparency mask colour.
04673     SeeAlso:    -
04674 ********************************************************************************************/
04675 UINT32 BaseBitmapFilter::GetNumReservedColours()
04676 {
04677     return 0;
04678 }
04679 
04680 
04681 /********************************************************************************************
04682 
04683 >   CCLexFile*  BaseBitmapFilter::GetExportFile() const
04684 
04685     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
04686     Created:    29/10/96
04687     Returns:    A pointer to the file provided in the filter entry point (DoExport,etc.)
04688     Purpose:    Support function to obtain file to export in WriteBitmapToFile
04689 
04690 ********************************************************************************************/
04691 CCLexFile*  BaseBitmapFilter::GetExportFile() const
04692 {
04693     return OutputFile;
04694 }
04695 
04696 
04697 /********************************************************************************************
04698 
04699 >   BOOL BaseBitmapFilter::GetCurrentStripInfo( ADDR* ppBits, 
04700                                             BMP_SIZE* pWidth, BMP_SIZE* pHeight,
04701                                             BMP_DEPTH* pDepth) const
04702     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
04703     Created:    29/10/96
04704     Outputs:    ppBits : address of ADDR variable to accept pointer to bitmap bits
04705                 pWidth : address of BMP_SIZE variable to accept bitmap width
04706                 pHeight: address of BMP_SIZE variable to accept bitmap height
04707                 pDepth : address of BMP_DEPTH variable to accept bitmap depth
04708     Returns:    TRUE if data is valid
04709                 FALSE otherwise
04710     Purpose:    Support function to obtain information regarding the strip we are currently
04711                 exporting.
04712     Notes:      This information is only valid in the WriteFrame member
04713 
04714 ********************************************************************************************/
04715 BOOL BaseBitmapFilter::GetCurrentStripInfo( ADDR* ppBits, 
04716                                             BMP_SIZE* pWidth, BMP_SIZE* pHeight,
04717                                             BMP_DEPTH* pDepth) const
04718 {
04719     LPBITMAPINFO    pBitmapInfo;
04720     LPBYTE          pBitmapBits;
04721 
04722     ExportRegion->GetBitmapData(&pBitmapInfo, &pBitmapBits);
04723 
04724     if (pBitmapInfo == NULL || pBitmapBits == NULL)
04725     {
04726         ERROR3("pBitmapInfo == NULL || pBitmapBits == NULL");
04727         return FALSE;
04728     }
04729 
04730     *ppBits     = pBitmapBits;
04731     *pWidth     = pBitmapInfo->bmiHeader.biWidth;
04732     *pHeight    = pBitmapInfo->bmiHeader.biHeight;
04733     *pDepth     = pBitmapInfo->bmiHeader.biBitCount;
04734     return TRUE;
04735 }
04736 
04737 
04738 /********************************************************************************************
04739 
04740 >   BitmapExportOptions* BaseBitmapFilter::GetBitmapExportOptions() const
04741 
04742     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
04743     Created:    29/10/96
04744     Returns:    Details of the data to be exported
04745     Purpose:    Support function to obtain BitmapExportOptions
04746 
04747 ********************************************************************************************/
04748 BitmapExportOptions* BaseBitmapFilter::GetBitmapExportOptions() const
04749 {
04750     ERROR3IF(m_pExportOptions != NULL && !m_pExportOptions->IS_KIND_OF(BitmapExportOptions),
04751             "m_pExportOptions isn't");
04752     return m_pExportOptions;
04753 }
04754 
04755 
04756 /********************************************************************************************
04757 
04758 >   BOOL BaseBitmapFilter::SetExportOptions ( BitmapExportOptions*  pOptions )
04759 
04760     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
04761     Created:    29/10/96
04762     Returns:    TRUE if successful
04763                 FALSE otherwise
04764     Purpose:    To allow that f!?@$%g MakeBitmapFilter have its wicked way
04765 
04766 ********************************************************************************************/
04767 
04768 BOOL BaseBitmapFilter::SetExportOptions ( BitmapExportOptions*  pOptions )
04769 {
04770     ERROR3IF ( pOptions != NULL && !pOptions->IS_KIND_OF ( BitmapExportOptions ),
04771                "BitmapExportOptions is wrong kind" );
04772 
04773     // Don't delete the old options unless specifically requested. This is to avoid the nasty
04774     // access violations that might occur otherwise.
04775 
04776     //if (m_pExportOptions && pOptions != m_pExportOptions)
04777     //  delete m_pExportOptions;
04778 
04779     m_pExportOptions = pOptions;
04780 
04781     return TRUE;
04782 }
04783 
04784 
04785 /********************************************************************************************
04786 
04787 >   virtual BitmapExportOptions* BaseBitmapFilter::CreateExportOptions() const
04788 
04789     Author:     Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
04790     Created:    29/10/96
04791     Returns:    A pointer to a new BitmapExportOptions class
04792     Purpose:    Allows derived classes to override this function to provide their own class
04793                 derived from BitmapExportOptions containing filter specific information.
04794     Notes:      This should never be called
04795 
04796 ********************************************************************************************/
04797 BitmapExportOptions* BaseBitmapFilter::CreateExportOptions() const
04798 {
04799     TRACE( _T("BaseBitmapFilter::CreateExportOptions() called\n"));
04800 
04801     BitmapExportOptions* pOptions = new BitmapExportOptions(_R(IDD_EXPORTBMPOPTS), FilterType(FilterID), &FilterName);
04802 
04803     return pOptions;
04804 }
04805 
04806 
04807 /********************************************************************************************
04808 
04809 >   static LPLOGPALETTE BaseBitmapFilter::Create8bppPalette() const
04810 
04811     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
04812     Created:    8/2/97
04813     Returns:    A pointer to a 8bpp palette
04814     Purpose:    Creates an 8bpp palette used when generating an 8bpp bitmap
04815                 Centralises common code previously found in BMP, GIF & PNG filters
04816 
04817                 The palette returned is created using CCMalloc().  The caller should use
04818                 CCFree() to discard the returned palette object when no longer needed.
04819 
04820                 Introduced for WEBSTER - markn 8/2/97.
04821                 Made static so that the Accusoft filter can use it
04822     Notes:      
04823 
04824 ********************************************************************************************/
04825 
04826 LPLOGPALETTE BaseBitmapFilter::Create8bppPalette()
04827 {
04828     /*
04829     LPLOGPALETTE lpPalette = NULL;
04830     GDrawContext *GDC = GRenderRegion::GetDrawContext();
04831     if (GDC != NULL)
04832     {
04833         // This should return a palette plus tell it what dithering we require
04834         // 0 = dither, not 0 for no dithering.
04835         LPLOGPALETTE lpGavPalette = GDC->SelectPalette( 0 );
04836 
04837         if (lpGavPalette != NULL)
04838         {
04839             const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 );
04840             lpPalette = (LPLOGPALETTE)CCMalloc( TotalPal );
04841             if (lpPalette != NULL)
04842             {
04843                 // Take a copy of that palette
04844                 memcpy( lpPalette, lpGavPalette, TotalPal );
04845 
04846                 // Always make 'browser' palette instead of 'standard' palette
04847                 // - Harrison 8/10/97
04848                 PaletteManager::MakePaletteBrowserCompatible(lpPalette,TRUE);
04849             }
04850         }
04851     }
04852 
04853     ERROR3IF(lpPalette == NULL, "Didnt get a palette");
04854 
04855     //  The section of code below is used when the user has deleted 1 or more colours, and then
04856     //  clicked on 'Preview'.
04857     //  Have to change the palette here before it is used to decide which palette colours
04858     //  match each pixel in the image.
04859     if( ( BmapPrevDlg::GetNumberOfDeletedColours() ) && ( BmapPrevDlg::m_bUseExistingPalette ) )
04860     {
04861         BOOL Deleted = FALSE;
04862         INT32 NewIndex = -1;
04863         INT32 Popularity = 0;
04864 
04865         //  Go through the palette in BmapPrevDlg.
04866         for( INT32 PaletteIndex = 0; PaletteIndex < ( lpPalette->palNumEntries ); PaletteIndex++ )
04867         {
04868             //  Has this colour been deleted by the user?
04869             Deleted = BmapPrevDlg::IsThisColourDeleted( PaletteIndex );
04870             if( Deleted )
04871             {
04872                 //  If this colour has been deleted, then we need to get its
04873                 //  original palette order.
04874                 NewIndex = BmapPrevDlg::GetOriginalPaletteOrder( PaletteIndex );
04875                 //  Set flags to 255 to tell the system that this colour is not
04876                 //  to be used in generating the exported image.
04877                 lpPalette->palPalEntry[NewIndex].peFlags = 255;
04878             }
04879             else
04880             {
04881                 //  Not deleted, but is the popularity of this colour = 0?
04882                 Popularity = BmapPrevDlg::GetPopularityValueForColour( PaletteIndex );
04883                 if( Popularity <= 0 )
04884                 {
04885                     NewIndex = BmapPrevDlg::GetOriginalPaletteOrder( PaletteIndex );
04886                     lpPalette->palPalEntry[NewIndex].peFlags = 255;
04887                 }
04888             }
04889         }
04890     }
04891 
04892     ExtendedPalette LockedColoursInformation;
04893     if( BmapPrevDlg::GotLockedColours() && lpPalette)
04894     {
04895         //  Copy all the locked colours information over.
04896         LockedColoursInformation = BmapPrevDlg::m_LockedColoursPalette;
04897         
04898         ExtendedPalette LockedColoursInformation2 = BmapPrevDlg::m_LockedColoursPalette2;
04899 
04900         //  Go through all the locked colours that we have
04901         for( INT32 i = 0; i < LockedColoursInformation.NumberOfColours; i++ )
04902         {
04903             //  Make sure that we are not exceeding the number of colours in the current palette.
04904             if( i >= ( lpPalette->palNumEntries ) )
04905                 continue;
04906 
04907             //  We want to find the nearest colour in the current palette to this locked colour.
04908             double SmallestDistance = 0.0;
04909             BOOL FirstDistanceCalc = TRUE;
04910             INT32 ClosestColourIndex = 0;
04911 
04912             //  Some variables needed below
04913             INT32 Red1, Green1, Blue1;
04914             INT32 Red2, Green2, Blue2;
04915             double RedDistance, GreenDistance, BlueDistance;
04916             double Distance;            
04917 
04918             INT32 LockedIndex = LockedColoursInformation.Data[ i ].ExtraInformation;
04919             Red1    = LockedColoursInformation2.Data[ LockedIndex ].Red;
04920             Green1  = LockedColoursInformation2.Data[ LockedIndex ].Green;
04921             Blue1   = LockedColoursInformation2.Data[ LockedIndex ].Blue;
04922 
04923             //  Go through all the colours in the current palette.
04924             for( INT32 j = 0; j < lpPalette->palNumEntries; j++ )
04925             {
04926                 //  The components of the palette colour we are looking at.
04927                 Red2    = lpPalette->palPalEntry[j].peRed;
04928                 Green2  = lpPalette->palPalEntry[j].peGreen;
04929                 Blue2   = lpPalette->palPalEntry[j].peBlue;
04930 
04931                 //  Calculate the distance between each of the colour components
04932                 //  ( Actually the square of this value - this does not matter since we
04933                 //  are not interested in the absolute values, only relative ones ).
04934                 RedDistance   = pow( double( Red1 - Red2 ), 2 );
04935                 GreenDistance = pow( double( Green1 - Green2 ), 2 );
04936                 BlueDistance  = pow( double( Blue1 - Blue2 ), 2 );
04937 
04938                 //  The overall distance.
04939                 Distance = ( INT32 )( RedDistance + GreenDistance + BlueDistance );
04940 
04941                 if( FirstDistanceCalc )
04942                 {
04943                     // First time around, so 'Distance' must be closest yet
04944                     // However, there may be an occasion where this colour is already being used by one of 
04945                     // the existing locked colours. In this case, we just want to completely ignore this
04946                     // colour, and carry on with the next loop
04947                     BOOL BeingUsed = FALSE;
04948                     for( INT32 Index = 0; Index < i; Index++ )
04949                     {
04950                         if( LockedColoursInformation.Data[ Index ].ExtraInformation == j )
04951                             BeingUsed = TRUE;
04952                     }
04953                     //  If it is being used, don't do anything.
04954                     if( !BeingUsed )
04955                     {
04956                         FirstDistanceCalc   = FALSE;
04957                         SmallestDistance    = Distance;
04958                         ClosestColourIndex  = j;
04959                     }
04960                 }
04961                 else if( Distance <= SmallestDistance )
04962                 {
04963                     //  Smallest distance so far?  if so remember the distance & index
04964                     //  Do this only if this index is not being used by another locked colour
04965                     //  already. To do this, have to look through the currently assigned locked
04966                     //  colour indices. If this index is being used, then just do nothing.
04967                     BOOL BeingUsed = FALSE;
04968                     for( INT32 Index = 0; Index < i; Index++ )
04969                     {
04970                         if( LockedColoursInformation.Data[ Index ].ExtraInformation == j )
04971                             BeingUsed = TRUE;
04972                     }
04973                     if( !BeingUsed )
04974                     {
04975                         SmallestDistance    = Distance;
04976                         ClosestColourIndex  = j;
04977                     }
04978                 }
04979             }
04980 
04981             //  Put the colour index into the locked colour palette
04982             INT32 Information = LockedColoursInformation.Data[ i ].ExtraInformation;
04983 
04984             //  Update the palette which holds the original values of the locked colours.
04985             INT32 r = BmapPrevDlg::m_LockedColoursPalette2.Data[ ClosestColourIndex ].Red;
04986             INT32 g = BmapPrevDlg::m_LockedColoursPalette2.Data[ ClosestColourIndex ].Green;
04987             INT32 b = BmapPrevDlg::m_LockedColoursPalette2.Data[ ClosestColourIndex ].Blue;
04988 
04989             BmapPrevDlg::m_LockedColoursPalette2.Data[ ClosestColourIndex ].Red = 
04990                 BmapPrevDlg::m_LockedColoursPalette2.Data[ Information ].Red;
04991             BmapPrevDlg::m_LockedColoursPalette2.Data[ ClosestColourIndex ].Green = 
04992                 BmapPrevDlg::m_LockedColoursPalette2.Data[ Information ].Green;
04993             BmapPrevDlg::m_LockedColoursPalette2.Data[ ClosestColourIndex ].Blue = 
04994                 BmapPrevDlg::m_LockedColoursPalette2.Data[ Information ].Blue;
04995 
04996             BmapPrevDlg::m_LockedColoursPalette2.Data[ Information ].Red = r;
04997             BmapPrevDlg::m_LockedColoursPalette2.Data[ Information ].Green = g;
04998             BmapPrevDlg::m_LockedColoursPalette2.Data[ Information ].Blue = b;
04999 
05000             BmapPrevDlg::m_LockedColoursPalette.Data[ i ].ExtraInformation = ClosestColourIndex;
05001             LockedColoursInformation = BmapPrevDlg::m_LockedColoursPalette;
05002         }
05003     }
05004 
05005     return lpPalette;
05006     */
05007     return NULL;
05008 }
05009 
05010 /********************************************************************************************
05011 >   BOOL BaseBitmapFilter::ExportImagemap(Operation *pOp, PathName* pPath, Document* pDoc)
05012     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
05013     Created:    9/4/97
05014     Returns:    TRUE if export was successful
05015                 FALSE if there was a problem
05016     Purpose:    Calls on the Imagemap Filter to export an imagemap based on the current
05017                 bitmap. 
05018 ********************************************************************************************/
05019 BOOL BaseBitmapFilter::ExportImagemap(Operation *pOp, PathName* pPath, Document* pDoc)
05020 {
05021     //Check our parameters
05022     ERROR2IF(pOp == NULL, FALSE,"BaseBitmapFilter::ExportImagemap no export operation");
05023     ERROR2IF(pPath == NULL, FALSE,"BaseBitmapFilter::ExportImagemap no export pathname");
05024     ERROR2IF(pDoc == NULL, FALSE,"BaseBitmapFilter::DoExport no document to export");
05025 
05026     //First, let's find the imagemap filter
05027     ImagemapFilter* pImagemapFilter=GetImagemapFilter();
05028 
05029     //And if we haven't found it, throw an error
05030     //Note that it is entirely possible that a future (modular) build might
05031     //not have an Imagemap filter, but for the moment it's worrying
05032     ERROR2IF(pImagemapFilter==NULL, FALSE, "OK. Own up. Who nicked the Imagemap filter?");
05033 
05034     //Create a file to export to
05035     CCDiskFile ImagemapFile(1024, FALSE, TRUE);
05036 
05037     //Now we need to set up some Imagemap Filter Options
05038     //We base these on the last set of ImagemapFilterOptions that the user exported
05039     //with, so get those options from the ImagemapFilter
05040     ImagemapFilterOptions ifoToSet=pImagemapFilter->GetFilterOptions();
05041 
05042     // Check we are exporting an imagemap either to a file or to the clipboard
05043     if (!(ifoToSet.m_fFile || ifoToSet.m_fClipboard))
05044         return TRUE; // Successfully done as requested (not exported an image map)
05045     
05046     if (!GetBitmapExportOptions())
05047         return FALSE; // can't export image map with out export options
05048 
05049     //Set the DPI from our bitmap options
05050     ifoToSet.m_dDPI=GetBitmapExportOptions()->GetDPI(); 
05051 
05052     //And set the selection type
05053     ifoToSet.m_stExportArea=GetBitmapExportOptions()->GetSelectionType();
05054 
05055 
05056     // Use the path set previously in the image map options -- Jonathan 6/12/2000   
05057     //And give the filter a pointer to our export file
05058     ifoToSet.m_pfileFile=&ImagemapFile;
05059 
05060     // tell the filter where the graphic is that it is describing
05061     ifoToSet.m_GraphicPath = *pPath; 
05062 
05063     //Then set our new options back into the imagemap filter
05064     pImagemapFilter->SetFilterOptions(ifoToSet);
05065 
05066     //And tell the filter to export the file
05067     BOOL ok= pImagemapFilter->PrepareAndWriteData(pDoc);
05068 
05069     //Then close the file if it's still open
05070     if (ImagemapFile.isOpen())
05071         ImagemapFile.close();
05072 
05073     //And return
05074     return ok;
05075 }
05076 
05077 /********************************************************************************************
05078 
05079 >   ImagemapFilter* BaseBitmapFilter::GetImagemapFilter()
05080 
05081     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
05082     Created:    10/4/97
05083     Returns:    A pointer to the imagemap filter
05084     Purpose:    Gets a pointer to the imagemap filter
05085 
05086                 This function may return NULL and the calling code should handle this case.
05087 
05088                 This is in case we ever build a version of Camelot without an Imagemap Filter.
05089                 All our code should cope with the Imagemap Filter not being there.
05090 
05091 ********************************************************************************************/
05092 ImagemapFilter* BaseBitmapFilter::GetImagemapFilter()
05093 {
05094     //First get a pointer to the filter manager
05095     FilterManager* pFilterManager=Camelot.GetFilterManager();
05096 
05097     ERROR2IF(pFilterManager==NULL, NULL, "BaseBitmapFilter::GetImagemapFilter - FilterManager does not exist");
05098 
05099     //Then return a pointer to the imagemap filter
05100     return ((ImagemapFilter*) pFilterManager->FindFilterFromID(FILTERID_IMAGEMAP));
05101     
05102 }
05103 
05104 
05105 /********************************************************************************************
05106 >   void BaseBitmapFilter::ExportHTMLTag(PathName* ppthToUse)
05107     Author:     Graham_Walmsley (Xara Group Ltd) <camelotdev@xara.com>
05108     Created:    21/5/97
05109     Purpose:    Exports an HTML tag to the clipboard that can be
05110                 used in a page of HTML to embed the bitmap that is
05111                 being exported.
05112   Technical notes:
05113                 Note that the width and height parameters of the bitmap
05114                 come from the width and height member variables of
05115                 the BitmapExportOptions member variable.
05116 
05117                 *But* Colin's comments say that it's at the filter author's 
05118                 discretion whether to use a BitmapExportOptions object or not.
05119                 So, it seems we shouldn't throw an error if we can't find
05120                 a BitmapExportOptions object.
05121 
05122                 So if we can't find a BFO object, we don't throw an error - 
05123                 we simply don't export.
05124 ********************************************************************************************/
05125 void BaseBitmapFilter::ExportHTMLTag(PathName* ppthToUse)
05126 {
05127     //Check our parameter
05128     if (ppthToUse==NULL)
05129     {
05130         ERROR2RAW("BaseCamelotFilter::ExportHTMLTag - NULL parameter");
05131         return;
05132     }
05133 
05134     //First get the name of the file we are exporting to
05135     String_256 strFileName=ppthToUse->GetFileName(TRUE);
05136 
05137     //Now, do we have sensible bitmap export dimensions?
05138     ERROR3IF(m_PixelWidth<=0 || m_PixelHeight<=0, "Width and Height are both 0 in BaseBitmapFilter::ExportHTMLTag");
05139     
05140     //And if they make sense
05141     if (m_PixelWidth>0 && m_PixelHeight>0)
05142     {
05143         //Then export a tag based on that width and height
05144 
05145         String_256 strTag;
05146         strTag.MakeMsg(_R(IDS_BITMAPFILTER_HTMLTAG), &strFileName, m_PixelWidth, m_PixelHeight);
05147 
05148         //And put that string on the clipboard
05149 PORTNOTE("clipboard","Removed InternalClipboard usage")
05150 #ifndef EXCLUDE_FROM_XARALX
05151         InternalClipboard::CopyText(strTag);
05152 #endif
05153     }
05154 }
05155 
05156 void PixelAlignedFiddle(DocRect* r)
05157 {
05158     INT32 lox, loy, hix, hiy = 0;
05159 
05160 #define INFLATE_ONLY
05161 
05162 #ifdef INFLATE_ONLY
05163     INT32 fiddle = 0; // extends the export clipping box to surround the exported image
05164                      // maintaining the screen antialiasing
05165 #else
05166     INT32 fiddle = 375; // shaves small amounts of aa if we think we dont need it
05167 #endif
05168     
05169     lox = ((r->lo.x + fiddle)/750) * 750;
05170     loy = ((r->lo.y + fiddle)/750) * 750;
05171     hix = ((r->hi.x + 749 - fiddle)/750) * 750;
05172     hiy = ((r->hi.y + 749 - fiddle)/750) * 750;
05173 
05174     DocRect newr(lox, loy, hix, hiy);
05175     *r = newr;
05176 }
05177 
05178 
05179 //  Static function which is used by BmapPrevDlg to call the above function.
05180 void BaseBitmapFilter::CallPixelAlignedFiddle( DocRect * r )
05181 {
05182     PixelAlignedFiddle( r );
05183 }
05184 

Generated on Sat Nov 10 03:44:22 2007 for Camelot by  doxygen 1.4.4