// $Id: bitfilt.cpp 1515 2006-07-24 20:33:54Z luke $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ // Base class for bitmap filters (currently meaningful for export only) #include "camtypes.h" #include "bitfilt.h" //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "resource.h" // _R(IDS_OUT_OF_MEMORY) //#include "camvw.h" // sadly #include "layer.h" //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "page.h" //#include "tim.h" #include "grndbmp.h" #include "osrndrgn.h" #include "nodebmp.h" #include "bitmpinf.h" #include "progress.h" //#include "nev.h" // _R(IDN_USER_CANCELLED) //#include "bmpres.h" // general bitmap filter based resources #include "prvwflt.h" #ifndef WEBSTER //#include "extfilts.h" // Accusoft filters #endif //WEBSTER //#include "selop.h" //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "bmpexdoc.h" #include "impexpop.h" //#include "will3.h" // for _R(IDS_GENOPTPALMSGID) #include "nodetxtl.h" #include "qualattr.h" #include "ccbuffil.h" //#include "palman.h" #include "bmpprefs.h" #include "exjpeg.h" //#include "giffiltr.h" #include "grndbmp.h" #include "bmapprev.h" //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "filtimag.h" //The imagemap filter class #include "filtrmgr.h" //The Filter Manager - used to find the imagemap filter //#include "resimmap.h" //Imagemap resources //#include "clipint.h" //To put text on the clipboard #include "htmlfltr.h" //For HTMLFilter::ImportingHTML #include "sprdmsg.h" // SpreadMsg #include "layermsg.h" // UPDATE_ACTIVE_LAYER #include "fileutil.h" //#include "prevwres.h" // _R(IDS_DEFAULTFRAMENAME) //#include "will2.h" // _R(IDS_K_EPSFILTER_IMPORTED) //#include "phil.h" //#include "simon.h" //#include "opbevel.h" // for bevel tools //#include "registry.h" //#include "sliceres.h" #include "gpalopt.h" #include "colplate.h" #include "fillattr2.h" #include "nodetext.h" CC_IMPLEMENT_MEMDUMP(BitmapImportOptions, CC_CLASS_MEMDUMP) CC_IMPLEMENT_DYNAMIC(BaseBitmapFilter, BitmapFilter) // Declare smart memory handling in Debug builds #define new CAM_DEBUG_NEW GRenderBitmap* BaseBitmapFilter::ExportRegion = NULL; // The region used for export CCLexFile* BaseBitmapFilter::OutputFile = NULL; // The file used for output BOOL BaseBitmapFilter::WrittenHeader = FALSE;// Have we done the first strip yet UINT32 BaseBitmapFilter::SizeOfExport = 100; // defined progress bar size. UINT32 BaseBitmapFilter::OurNumNodes = 0; // our copy of the number of nodes being exported LPLOGPALETTE BaseBitmapFilter::pOptimisedPalette = NULL; BOOL BaseBitmapFilter::WeAreGeneratingOptPalette = FALSE; const INT32 BaseBitmapFilter::MinPelsPerMeter = 1000; // Minimum Pels per meter allowed const INT32 BaseBitmapFilter::MinExportSize = 10; // Minimum selection width/height allowed KernelBitmap* BaseBitmapFilter::pExportBitmap = NULL; // Store for the bitmap pointr in DoExportBitmap DPI BaseBitmapFilter::m_DefaultExportDPI = 96.0; // Used as the default DPI when exporting LPLOGPALETTE BaseBitmapFilter::m_pBrowserPalette = NULL; // This constant gives you the ( square of the ) maximum distance that a colour has to be from a browser colour // to be snapped to that colour. const INT32 WEB_SNAP_OPTIMISED_DISTANCE_SQUARED = 25; void PixelAlignedFiddle(DocRect*); // Added by Craig Hamilton 29/8/00. INT32 BaseBitmapFilter::m_NumberOfPaletteEntries = 0; // End added. /******************************************************************************************** > BaseBitmapFilter::BaseBitmapFilter() Author: Andy_Pennell (Xara Group Ltd) Created: 28/6/94 Purpose: Constructor for an BaseBitmapFilter object. The object should be initialised before use. Base class version SeeAlso: BaseBitmapFilter::Init ********************************************************************************************/ BaseBitmapFilter::BaseBitmapFilter() { OutputFile = NULL; ExportRegion = NULL; pNewBitmap = NULL; InputFile = NULL; BackgroundRedrawState = FALSE; BackgroundRedrawStateSet = FALSE; ViewQualitySet = FALSE; IsPreviewBitmap = FALSE; pExportBitmap = NULL; pSpread = NULL; m_pImportOptions = NULL; m_pExportOptions = NULL; pOptimisedPalette = NULL; WrittenHeader = FALSE;// Have we done the first strip yet RenderInStrips = TRUE; // Should we render in strips or not RenderBottomToTop = TRUE; // control over which way we render BadExportRender = FALSE;// whether the export rendering has gone ok or not SizeOfExport = 100; // defined progress bar size. OurNumNodes = 0; // our copy of the number of nodes being exported PaletteType = PAL_OPTIMISED; //Should these lines be in or out - Martin 14/04/97 PreviewDither = XARADITHER_ERROR_DIFFUSION; PreviewPalette = PAL_OPTIMISED; WeAreGeneratingOptPalette = FALSE; ClipRect.MakeEmpty(); m_pOptimisedPalette2 = NULL; m_pExportOptions = NULL; } /******************************************************************************************** > BaseBitmapFilter::~BaseBitmapFilter() Author: Andy_Pennell (Xara Group Ltd) Created: 28/6/94 Purpose: Destructor for an BaseBitmapFilter object. ********************************************************************************************/ BaseBitmapFilter::~BaseBitmapFilter() { // Clear up some dynamically allocated memory if (m_pOptimisedPalette2) { CCFree(m_pOptimisedPalette2); m_pOptimisedPalette2 = 0; } if (m_pBrowserPalette) { CCFree(m_pBrowserPalette); m_pBrowserPalette = 0; } delete m_pImportOptions; m_pImportOptions = 0; // delete m_pExportOptions; m_pExportOptions = 0; } /******************************************************************************************** > BOOL BaseBitmapFilter::InitBaseClass() Author: Graham_Walmsley (Xara Group Ltd) Created: 23/5/97 Returns: TRUE if the filter was initialized ok FALSE otherwise Purpose: Initialises any static member variables for the base bitmap filter class ********************************************************************************************/ BOOL BaseBitmapFilter::InitBaseClass() { return BitmapExportOptions::Declare(); } /******************************************************************************************** > void BaseBitmapFilter::SetPreviewBitmap(BOOL IsPreviewBmp) Author: Rik_Heywood (Xara Group Ltd) Created: 2/2/95 Inputs: isPreviewBmp - TRUE if this bitmap we are saving is actually a Preview bitmap FALSE if not. Purpose: Allows you to set the state of this flag. Always set it back to FALSE after the export as the filter hangs around, ready for the next export. ********************************************************************************************/ void BaseBitmapFilter::SetPreviewBitmap(BOOL IsPreviewBmp) { IsPreviewBitmap = IsPreviewBmp; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::ExportVisibleLayersOnly() Author: Neville_Humphrys (Xara Group Ltd) Created: 14/02/95 Inputs: - Outputs: - Returns: True if this filter wants to exclude invisible layers and so export only visible items Or False if want to export everything. Purpose: Determines if the filter wants to export only visible layers. In the base bitmap filters class version the default action will be to export only those layers which are visible. SeeAlso: Filter::ExportRender; ********************************************************************************************/ BOOL BaseBitmapFilter::ExportVisibleLayersOnly() { // only include all layer that are visible in this bitmap export return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::IsSecondPassRequired() Author: Neville_Humphrys (Xara Group Ltd) Created: 18/09/95 Returns: True if this filter wants a second export rendering pass and so have a chance to setup semething like a mask. False if no second pass required. Purpose: Determines if the a second rendering pass is required or not. SeeAlso: DoExport; ********************************************************************************************/ BOOL BaseBitmapFilter::IsSecondPassRequired() { return FALSE; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::IsDefaultDocRequired(const TCHAR* pcszPathName) Author: Neville_Humphrys (Xara Group Ltd) Created: 9/10/95 Inputs: pcszPathName pointer to the pathname to check Returns: TRUE if the filter requires a default document, FALSE if not. Purpose: Works out if opening a file of this type requires a default document to be loaded. If the file format supplies the document then return FALSE otherwise return TRUE. An example would be opening a bitmap file. This has no document defined in the file format and so we need to laod the default document before importing the bitmap into this file. In this baseclass version return FALSE and hence assume that the filters that need to will override this function to return TRUE. SeeAlso: Filter; Filter::IsDefaultDocRequired; CCamDoc::OnOpenDocument; SeeAlso: FilterFamily::DoImport; Filter::DoImport; ********************************************************************************************/ BOOL BaseBitmapFilter::IsDefaultDocRequired(const TCHAR* pcszPathName) { // No need to check the pathname, just return TRUE as all currently known bitmap filters // will require the default document. return TRUE; } /******************************************************************************************** > virtual void BaseCamelotFilter::IncProgressBarCount(UINT32 n) Author: Colin_Barfoot (Xara Group Ltd) (Markn) Created: 5/6/96 Inputs: n = amount to inc the progress bar count by Returns: - Purpose: Func to incrementing the progress bar count. If there is a progress bar available, it is updated by this call. Scope: Protected. ********************************************************************************************/ BOOL BaseBitmapFilter::IncProgressBarCount(UINT32 n) { return TRUE; } /******************************************************************************************** > virtual void BaseBitmapFilter::SetTotalProgressBarCount(UINT32 n) Author: Colin_Barfoot (Xara Group Ltd) (Markn) Created: 5/6/96 Inputs: n = amount to set the total progress bar count to Purpose: Func to set total the progress bar count. If there is a progress bar available, it is updated by this call. Scope: Protected. ********************************************************************************************/ void BaseBitmapFilter::SetTotalProgressBarCount(UINT32 n) { ERROR3IF(n == 0,"Should only be set to a value greater that 0"); m_TotalProgressBarCount = n; } /******************************************************************************************** > virtual BitmapSource* BaseBitmapFilter::CreateBitmapSource(FilePos Size) const Author: Colin_Barfoot (Xara Group Ltd) Created: 21/08/96 Inputs: Size: The required size of the BitmapSource Returns: A pointer to a new BitmapSource Purpose: The PrepareToImport() function calls this member to create a BitmapSource for lossy file formats. The BaseBitmapFilter implementation returns NULL. Derived classes with lossy formats should override this function to provide a subclassed BitmapSource. SeeAlso: IsFormatLossy() Scope: protected ********************************************************************************************/ BitmapSource* BaseBitmapFilter::CreateBitmapSource(OFFSET Size) const { return NULL; } /******************************************************************************************** > BOOL BaseBitmapFilter::PrepareBitmapSource() Author: Colin_Barfoot (Xara Group Ltd) Created: 21/08/96 Returns: TRUE if successful FALSE otherwise Purpose: The PrepareToImport() function calls this member to create a BitmapSource for lossy file formats, and a CCLexFile to work with it. SeeAlso: IsFormatLossy() Scope: protected ********************************************************************************************/ BOOL BaseBitmapFilter::PrepareBitmapSource() { #ifdef DO_EXPORT OFFSET offset = GetDataStartOffset(); OFFSET size = InputFile->Size() - offset; // Create the actual BitmapSource object m_pBitmapSource = CreateBitmapSource(size); if (m_pBitmapSource == NULL || !m_pBitmapSource->IsOK()) { Error::SetError(_R(IDS_OUT_OF_MEMORY)); return FALSE; } // Check for errors but let CCFile report them InputFile->SetThrowExceptions(FALSE); InputFile->SetReportErrors(TRUE); // Ignore those superfluous bits at the start of the file InputFile->seekIn(offset); if (!InputFile->good()) { return FALSE; } // Now create a file to fill our BitmapSource & provide the filter with something // to work with CCBufferFile* pBufferFile = new CCBufferFile(InputFile); if (pBufferFile == NULL || !pBufferFile->IsInited()) { Error::SetError(_R(IDS_OUT_OF_MEMORY)); return FALSE; } // We have a file, so attach out BitmapSource to it m_pBitmapSource->AttachToBufferFile(pBufferFile); // Now ditch our current InputFile in favour of the BitmapSource's one // We don't need InputFile again InputFile = (CCLexFile*)pBufferFile; #endif return TRUE; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::PrepareToImport() Author: Andy_Pennell (Xara Group Ltd) Created: 28/6/94 Returns: TRUE if succeeded, FALSE if not. Purpose: Prepare to import bitmap data using this filter. This sets up the filter to a sensible state for reading. Errors: Out of memory. SeeAlso: BaseBitmapFilter::DoImport; BaseBitmapFilter::CleanUpAfterImport Scope: Private ********************************************************************************************/ BOOL BaseBitmapFilter::PrepareToImport() { ERROR2IF(InputFile == NULL, FALSE, "InputFile is NULL"); // Assume we won't want a BitmapSource m_pBitmapSource = NULL; #ifdef DO_EXPORT // Do we need to keep the data to prevent it from deteriorating? if (IsFormatLossy()) { // SetTotalProgressBarCount(InputFile->Size()); ...one day if (!PrepareBitmapSource()) { return FALSE; } } #endif return TRUE; } /******************************************************************************************** > void BaseBitmapFilter::CleanUpAfterImport() Author: Andy_Pennell (Xara Group Ltd) Created: 28/6/94 Purpose: Cleans up the memory allocated by BaseBitmapFilter::PrepareToImport() - used when the import process ends, either normally or abnormally. SeeAlso: BaseBitmapFilter::PrepareToImport; BaseBitmapFilter::DoImport Scope: Private ********************************************************************************************/ void BaseBitmapFilter::CleanUpAfterImport() { TheDocument = NULL; //WEBSTER-Martin-02/01/97 #ifndef WEBSTER #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX) // Reset the filter type used by the Accusoft filters so that it can cache the // filter type correctly and so only call the Accusoft DLL on the first filter // rather than on all filters. AccusoftFilters::ResetFilterType(); #endif #endif //WEBSTER } /******************************************************************************************** > BitmapImportOptions* BaseBitmapFilter::GetImportOptions() Author: Neville_Humphrys (Xara Group Ltd) Created: 22/11/94 Inputs: None Outputs: None Returns: A pointer to BitmapImportOptions with the options in it set. NULL if an error occured. Purpose: To allow a filter to offer the user a choice over what gets imported. Derived BaseBitmapFilter classes should also derive a new BitmapImportOptions class and return a new copy on the heap with the user options in it. BaseBitmapFilter will delete the BitmapImportOptions class when no longer needed. At present used by PhotoCD filter to get image to import. SeeAlso: BaseBitmapFilter::PrepareToImport; BaseBitmapFilter::DoImport Scope: Protected ********************************************************************************************/ BitmapImportOptions* BaseBitmapFilter::GetImportOptions() { BitmapImportOptions* pOptions = new BitmapImportOptions; return pOptions; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::IsFormatLossy() const Author: Colin_Barfoot (Xara Group Ltd) Created: 20/08/96 Returns: TRUE if the file format for the derived filter is lossy FALSE otherwise Purpose: Provides information to the BaseBitmapFilter so that it knows whether or not to provide a BitmapSource to prevent progressive degradation of the bitmap when exported via the new file format. Notes: Derived classes should override this function for their particular implementation. ********************************************************************************************/ BOOL BaseBitmapFilter::IsFormatLossy() const { return FALSE; } /******************************************************************************************** > virtual OFFSET BaseBitmapFilter::GetDataStartOffset() const Author: Colin_Barfoot (Xara Group Ltd) Created: 20/08/96 Returns: The offset from the HeaderStart parameter given in HowCompatible(), from which data essential to the correct functionality of this filter starts. Purpose: Provides information to the BaseBitmapFilter, so that it knows where to start any required BitmapSource. It will only be useful to derived classes that deal with a lossy file format. Notes: The default implementation returns zero, assuming there is no useless garbage before any actual header. Derived classes should override this for any special case. See Also: IsFormatLossy() ********************************************************************************************/ OFFSET BaseBitmapFilter::GetDataStartOffset() const { return 0; } /******************************************************************************************** > inline INT32 GridLock(INT32 Position, INT32 GridSize) Author: Neville_Humphrys (Xara Group Ltd) from Jason code in coldlog.cpp Created: 22/9/97 Inputs: Position - The X/Y position, in millipoints GridSize - the size of the grid to lock to, in millipoints Returns: Position, locked (by rounding) to a grid of the given size, and offset by half a grid. Purpose: Grid-locks a given plotting position to lie over a grid (usually the output device-pixel grid). The result is shifted by half the grid size to grid-lock to the _center_ of a pixel rather than the edges. Note: stolen from ColourEditDlg/PreviewDialog rendering routines ********************************************************************************************/ inline INT32 GridLock(INT32 Position, INT32 GridSize) { // By truncating down to the nearest grid point, and adding half the grid value, // we achieve rounding to the nearest offset-grid position. // NOTE: // The original algorithm incorrectly rounded negative numbers towards // zero. Negative numbers should be rounded towards negative infinity. // The algorithm has been corrected by always rounding a positive number // and restoring the original sign of the number after rounding. BOOL bNegative = FALSE; // Assume the number is positive if (Position < 0) // If the number if not positive { // note the fact and make positive bNegative = TRUE; Position = -Position; } Position += GridSize / 2; Position -= Position % GridSize; if (bNegative) // If the number was negative Position = -Position; // restore the sign return (Position); } /******************************************************************************************** > BOOL BaseBitmapFilter::DoImport(SelOperation *Op, CCLexFile* pFile, Document *DestDoc, BOOL AutoChosen, ImportPosition *Pos, KernelBitmap** ppImportedBitmap, DocCoord* pPosTranslate, String_256* URL) Author: Andy_Pennell (Xara Group Ltd) Created: 28/6/94 Inputs: Op - pointer to the operation that this input process is associated with. pFile - The file that we should load the bitmap from DestDoc - The Document object which should hold the data read in from the bitmap. ImportPosition - ppImportedBitmap - Used to set the bitmap background pPosTranslate - specify the position of the bitmap on the screen Returns: TRUE if the input operation worked ok, FALSE if not. Purpose: Read bitmap data from a file. This is the same for all bitmap filters; the ImportBitmap() function should be over-ridden for actual bitmap import filters. Errors: Fails (returns FALSE) if the document structure is incorrect, or if there is a problem with the bitmap. ********************************************************************************************/ BOOL BaseBitmapFilter::DoImport(SelOperation *Op, CCLexFile* pFile, Document *DestDoc, BOOL AutoChosen, ImportPosition *Pos, KernelBitmap** ppImportedBitmap, DocCoord* pPosTranslate, String_256* URL) { ERROR2IF(Op == NULL, FALSE, "BaseBitmapFilter::DoImport NULL operation supplied"); ERROR2IF(pFile == NULL, FALSE, "BaseBitmapFilter::DoImport NULL diskfile supplied"); ERROR2IF(DestDoc == NULL, FALSE, "BaseBitmapFilter::DoImport NULL doc supplied"); // Make a note of the disk file we are given InputFile = pFile; // Set up the class variable which is used by the bitmap system to determine which document // to load the bitmap into. Added 24/9/96 as opening a PhotoCD causes the selection to change! // Removing the photocd import dialog box causes the selection to be put into an existing doc // rather than a new one. TheDocument = DestDoc; if (ProcessImportOptions() == FALSE) return FALSE; Spread *pSpread = NULL; DocCoord Origin; if (Pos == NULL) { // For now, position Draw objects on 1st page of spread 1 //Graham 30/6/97: We now position imported bitmaps in the top left of the view //So first find the current view DocView* pDocView=DocView::GetCurrent(); ERROR2IF(pDocView==NULL, FALSE, "BaseBitmapFilter::DoImport - no current view"); //And get the centre coordinate Origin=pDocView->GetTopLeftCoord(); // Find the first spread in that document. pSpread = TheDocument->FindFirstSpread (); } else { pSpread = Pos->pSpread; Origin = Pos->Position; } // If we use the PhotoCD import then current/selected doc/spread MAY be wrong. So force it again. // Must ensure the selected spread is in the destination document as otherwise we will insert the // object AFTER the insertion node and hence in an illegal position. Document::SetSelectedViewAndSpread(DestDoc, DocView::GetCurrent(), pSpread); // Let's get ready if (!PrepareToImport()) return FALSE; UINT32 nBitmapToRead = 0; Layer* pNewLayer = NULL; Layer* pNewActiveLayer = NULL; do // for every bitmap in the file { KernelBitmap* pKernelBmp = NULL; ++nBitmapToRead; // Import that bitmap, if first bitmap then nBitmapToRead will be set to 1 BOOL Success = ImportBitmap(pFile, &pKernelBmp, nBitmapToRead); if (!Success) { if (m_pImportOptions != NULL) { delete m_pImportOptions; m_pImportOptions = NULL; } // Did not work - report this to the caller. return FALSE; } // If the caller wants to handle the imported bitmap, then set the return pointer up, // otherwise, we handle the bitmap by inserting a NodeBitmap into the document if (ppImportedBitmap != NULL && pPosTranslate == NULL) *ppImportedBitmap = pKernelBmp; else { // Get a new NodeBitmap object to import into. NodeBitmap *pNodeBitmap = new NodeBitmap; if ((pNodeBitmap == NULL) || (!pNodeBitmap->SetUpPath(12,12))) { if (m_pImportOptions != NULL) { delete m_pImportOptions; m_pImportOptions = NULL; } if (pNodeBitmap != NULL) delete pNodeBitmap; return FALSE; } pNodeBitmap->GetBitmapRef()->Attach(pKernelBmp, DestDoc); //GetDocument()); if (pNodeBitmap->GetBitmap() != pKernelBmp) { // It didn't use the bitmap we gave it, so we can delete it delete pKernelBmp; } //And if the caller wants a pointer to the kernel bitmap, give them one... if (ppImportedBitmap) { *ppImportedBitmap=pNodeBitmap->GetBitmap(); } // Import worked - try to add the bitmap object into the tree. // First, set the rectangle to the right size for the bitmap... BitmapInfo Info; pNodeBitmap->GetBitmap()->ActualBitmap->GetInfo(&Info); INT32 hdpi = pNodeBitmap->GetBitmap()->GetHorizontalDPI(); if (hdpi == 0) hdpi = 96; INT32 vdpi = pNodeBitmap->GetBitmap()->GetVerticalDPI(); if (vdpi == 0) vdpi = 96; const INT32 HPixelSize = (INT32) ((72000.0 / hdpi) + 0.5); // Size of output pixel in millipoints const INT32 VPixelSize = (INT32) ((72000.0 / vdpi) + 0.5); // Size of output pixel in millipoints DocRect BoundsRect; BoundsRect.lo = Origin; // Make sure that this is snapped to a pixel grid BoundsRect.lo.x = GridLock(BoundsRect.lo.x, HPixelSize); BoundsRect.lo.y = GridLock(BoundsRect.lo.y, VPixelSize); // And now add in the rest of the bounds BoundsRect.hi.x = BoundsRect.lo.x + Info.RecommendedWidth; BoundsRect.hi.y = BoundsRect.lo.y + Info.RecommendedHeight; BoundsRect.hi.x = GridLock(BoundsRect.hi.x, HPixelSize); BoundsRect.hi.y = GridLock(BoundsRect.hi.y, VPixelSize); // And set this in our bitmap node pNodeBitmap->CreateShape(BoundsRect); // Make sure that there is a layer to put the bitmap onto if (!MakeSureLayerExists(DestDoc)) { // There is no layer and one could not be made, so we will have to fail delete pNodeBitmap; if (m_pImportOptions != NULL) { delete m_pImportOptions; m_pImportOptions = NULL; } return FALSE; } // Set the default attrs // This MUST be done before the NodeBitmap is Inserted into the tree if (!pNodeBitmap->ApplyDefaultBitmapAttrs(Op)) { if (m_pImportOptions != NULL) { delete m_pImportOptions; m_pImportOptions = NULL; } return FALSE; } // Insert the node, but don't invalidate its region // If we are the only bitmap then just add it as the first child of the active layer // Could use Filter::ImportWithLayers to determine if we use layers or not BOOL Fail = FALSE; BOOL SingleBitmap = !AreBitmapsToRead() && nBitmapToRead <= 1; //Graham 30/5/97 //If we're importing an animated bitmap as part of an //HTML document PORTNOTE("filters","Removed HTMLFilter usage") if( !SingleBitmap #ifndef EXCLUDE_FROM_XARALX && HTMLFilter::ImportingHTML #endif ) { //Then turn the "all layers visible" flag on in the document DestDoc->SetMultilayer(TRUE); DestDoc->SetAllVisible(TRUE); } if (SingleBitmap || !Filter::ImportBitmapsOntoLayers) { // This inserts the node as the last child of the active layer if (!Op->DoInsertNewNode(pNodeBitmap, pSpread, FALSE)) { Fail = TRUE; // It didn't work - delete the sub-tree we just created, and report error. pNodeBitmap->CascadeDelete(); // Of course, Cascade delete does not actually delete the node itself, so now do that delete pNodeBitmap; pNodeBitmap = NULL; } } else { // We are not the only bitmap in the loading process so for each bitmap try and create // a new layer and put the new bitmap there. // The first layer should be added after the active layer. // We could do this but this means that when multiple animations are being loaded you // end up with the first frames close together rather than the two animations being // separate. if (!InsertBitmapOnNewLayer(Op, pSpread, pNodeBitmap, &pNewLayer)) { Fail = TRUE; // It didn't work - delete the sub-tree we just created, and report error. pNodeBitmap->CascadeDelete(); // Of course, Cascade delete does not actually delete the node itself, so now do that delete pNodeBitmap; pNodeBitmap = NULL; } // Remember the layer we used for the first bitmap so that we can make it active if (nBitmapToRead == 1) pNewActiveLayer = pNewLayer; // Let the filter set things up from the bitmap on the layer // GIF filter can use disposal method to set overlay and solid flags KernelBitmap * pBitmap = pNodeBitmap->GetBitmap(); SetFlagsFromBitmap(pNewLayer, pBitmap, nBitmapToRead); } // If we noted a failure then handle it now if (Fail) { if (m_pImportOptions != NULL) { delete m_pImportOptions; m_pImportOptions = NULL; } return FALSE; } // and move it to the correct location if we need to... DocCoord Offset(0,0); if (GetDragAndDropTranslation(Pos, BoundsRect, &Offset)) { // See if the bitmap contained an offset and if it did add it in // Baseclass defaults to 0,0 offset AddOffsetFromBitmap(&Offset); Offset.x = GridLock(Offset.x, HPixelSize); Offset.y = GridLock(Offset.y, VPixelSize); // Build the matrix and transform the bitmap to the correct place Trans2DMatrix Xlate(Offset.x, Offset.y); pNodeBitmap->Transform(Xlate); } else { // No drag and drop - bitmap is currently positioned so its bottom left hand // corner is at the top left of the page - translate it down by its height so // that the top left corner of the bitmap is aligned to the top left corner // of the page. // Do we have an additional translation to apply? if (pPosTranslate != NULL) { Offset.x = pPosTranslate->x; Offset.y = pPosTranslate->y; } // See if the bitmap contained an offset as well and if it did add it in // Baseclass defaults to 0,0 offset AddOffsetFromBitmap(&Offset); Offset.x = GridLock(Offset.x, HPixelSize); Offset.y = GridLock(Offset.y, VPixelSize); Trans2DMatrix Xlate(Offset.x, -(Info.RecommendedHeight) + Offset.y); pNodeBitmap->Transform(Xlate); } // Invalidate the region Success = Op->DoInvalidateNodeRegion(pNodeBitmap, TRUE, FALSE); if (!Success) { if (m_pImportOptions != NULL) { delete m_pImportOptions; m_pImportOptions = NULL; } return FALSE; // hmmm.... } } } while (AreBitmapsToRead()); // If we have loaded bitmaps onto layers and hence requested a new active layer then set // it now. // Graham 1/8/97: If we are importing an animated GIF as part of an HTML page, we don't // change the active layer, because this may result in subsequent bitmaps in the HTML // page being imported on the wrong layer. PORTNOTE("filters","Removed HTMLFilter usage") if( pNewActiveLayer #ifndef EXCLUDE_FROM_XARALX && !HTMLFilter::ImportingHTML #endif ) { // If the old active layer is blank and has nothing on it, then delete it Layer * pActiveLayer = pSpread->FindActiveLayer(); if (pActiveLayer) { // Scans the layer for children that render something on the screen. // It ignores attributes, hidden nodes, etc - nodes that don't render anything themselves. Node* pNode = pActiveLayer->FindFirstChild(); BOOL ChildFound = FALSE; while (pNode != NULL && !ChildFound) { ChildFound = pNode->IsBounded(); pNode = pNode->FindNext(); } // Hide the old active layer if (!ChildFound) Op->DoHideNode(pActiveLayer, TRUE); } // Check that all visible layers are actually frame layers as we have // created some new frame layers for each of the bitmaps. PORTNOTE("dialog","Removed FrameSGallery usage") #ifndef EXCLUDE_FROM_XARALX FrameSGallery::MakeActiveLayer(pNewActiveLayer); #endif BROADCAST_TO_ALL( LayerMsg( pNewActiveLayer, LayerMsg::UPDATE_ACTIVE_LAYER ) ); // Try and fix up the animation properties according to the bitmaps that have been loaded in SetAnimationPropertiesFromLoaded(pSpread); } // Ensure Sel Bounds are correct after translation GetApplication()->UpdateSelection(); if (m_pImportOptions != NULL) { delete m_pImportOptions; m_pImportOptions = NULL; } // All ok return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::InsertBitmapOnNewLayer(SelOperation *pOp, Spread * pSpread, NodeBitmap *pNodeBitmap, Layer ** ppNewLayer) Author: Neville_Humphrys (Xara Group Ltd) Created: 6/5/97 Inputs: pOp the operation to use to insert new items pSpread the spread we are using pNodeBitmap the new node bitmap which is to be inserted Outputs: ppNewlayer the new layer that was inserted (ready to be used next time around) Returns: TRUE if everything was insert ok, FALSE otherwise. Purpose: When loading in multiple bitmaps then each bitmap should be inserted onto a new layer. The first bitmap is inserted as the last child on the active layer. Each subsequent bitmap is loaded onto a new layer after this. The routine returns the new layer so that this can be used next time as the insertion point. SeeAlso: BaseBitmapFilter::DoImport ********************************************************************************************/ BOOL BaseBitmapFilter::InsertBitmapOnNewLayer(SelOperation *pOp, Spread * pSpread, NodeBitmap *pNodeBitmap, Layer ** ppNewLayer) { ERROR2IF(pOp == NULL || pSpread == NULL || pNodeBitmap == NULL || ppNewLayer == NULL,FALSE,"InsertBitmapOnNewLayer bad parameters!"); Layer * pCurrentLayer = NULL; if (*ppNewLayer) { // We have been supplied with the last inserted new layer so use this. pCurrentLayer = *ppNewLayer; } else { // We are the first time through and so try and create // a layer after the active layer and put the bitmap there. // We could do this but we get problems when loading multiple animations. So // do what we do elsewhere and load after the last layer. Layer * pInsertionLayer = pSpread->FindLastLayer(); // No Active layer so get out now! if (pInsertionLayer == NULL) return FALSE; // Use the active layer as the insertion point pCurrentLayer = pInsertionLayer; } // Create the new layer Layer* pNewLayer = new Layer; if (pNewLayer == NULL) return FALSE; // Ensure that the layer name has a frame flavour about it // We also need to add an imported at the start so that if the original Frame 1 // layer is deleted as it has nothing on it, then the layer is not called Frame 2 // but Imported Frame 1 String_256 LayerName(_R(IDS_K_EPSFILTER_IMPORTED)); String_256 Suffix(_R(IDS_DEFAULTFRAMENAME)); // Frame LayerName += Suffix; PORTNOTE("dialog","Removed FrameSGallery usage") #ifndef EXCLUDE_FROM_XARALX String_256 NewLayerName = FrameSGallery::CreateUniqueLayerID(pSpread, &LayerName); #else String_256 NewLayerName = ""; #endif pNewLayer->SetLayerID(NewLayerName); pNewLayer->SetVisible(TRUE); // Ensure visible pNewLayer->SetLocked(FALSE); // Ensure unlocked so insertion works pNewLayer->SetPrintable(FALSE); pNewLayer->SetBackground(FALSE); // Ensure it is foreground pNewLayer->SetOutline(FALSE); pNewLayer->SetGuide(FALSE); pNewLayer->SetPageBackground(FALSE); #ifdef WEBSTER // In Webster mode, always make the new layer a frame layer pNewLayer->SetFrame(TRUE); // Mark it as a frame layer #else // In Camelot mode, only make the new layer a frame layer if there are // already frame layers in the document Layer * pFrame = pSpread->FindFirstFrameLayer(); if (pFrame != NULL) pNewLayer->SetFrame(TRUE); // Mark it as a frame layer else pNewLayer->SetFrame(FALSE); // Mark it as a layer #endif // Insert the new layer as the next node after the last page. if (!pOp->DoInsertNewNode(pNewLayer, pCurrentLayer, NEXT, FALSE,FALSE,FALSE,FALSE)) { delete pNewLayer; pNewLayer = NULL; // Return the new layer to the caller *ppNewLayer = pNewLayer; return FALSE; } // And now insert the bitmap node into the new layer if (!pOp->DoInsertNewNode(pNodeBitmap, pNewLayer, FIRSTCHILD,FALSE,FALSE,FALSE,FALSE)) { // It didn't work - hide the layer sub-tree we just created pOp->DoHideNode(pNewLayer, TRUE); // Return the new layer to the caller as null *ppNewLayer = NULL; // Assume the caller deletes the node bitmap return FALSE; } pNewLayer->SetVisible(FALSE); // Ensure it is invisible pNewLayer->SetLocked(TRUE); // Ensure locked // Set the fact that this layer is presently fully defined by this bitmap KernelBitmap * pBitmap = pNodeBitmap->GetBitmap(); pNewLayer->SetReferencedBitmap(pBitmap); pNewLayer->EnsureUniqueLayerID(); BROADCAST_TO_ALL( SpreadMsg( pSpread, SpreadMsg::LAYERCHANGES ) ); // Return the new layer to the caller *ppNewLayer = pNewLayer; return TRUE; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::SetFlagsFromBitmap(Layer * pLayer, KernelBitmap * pBitmap, UINT32 nBitmapToRead) Author: Neville_Humphrys (Xara Group Ltd) Created: 20/5/97 Inputs: pLayer the layer that the bitmap is being put on pBitmap the bitmap being placed on the layer nBitmapToRead the number of the bitmap in the sequence Returns: TRUE if was ok, FALSE otherwise. Purpose: When loading in multiple bitmaps and placing them on new layers, we should give the filter an opportunity to set the layer flags from the bitmap. In the case of a GIF filter this would allow it to set the solid and overlay flags. This baseclass version does nothing. ********************************************************************************************/ BOOL BaseBitmapFilter::SetFlagsFromBitmap(Layer * pLayer, KernelBitmap * pBitmap, UINT32 nBitmapToRead) { // Do nothing return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::AddOffsetFromBitmap(DocCoord * pOffset) Author: Neville_Humphrys (Xara Group Ltd) Created: 15/5/97 Inputs: pOffset the present offset in the bitmap Returns: TRUE if was ok, FALSE otherwise. Purpose: When loading in a bitmap, the bitmap definition may contain an offset. We need to add this to the offset that we are given so that the bitmap is loaded at the correct position. This baseclass version does nothing. ********************************************************************************************/ BOOL BaseBitmapFilter::AddOffsetFromBitmap(DocCoord * pOffset) { // Do nothing return TRUE; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::SetAnimationPropertiesFromLoaded(Spread * pSpread) Author: Neville_Humphrys (Xara Group Ltd) Created: 8/7/97 Inputs: pSpread the spread that the bitmaps have been put on Returns: TRUE if was ok, FALSE otherwise. Purpose: When loading in multiple bitmaps and placing them on new layers, we should give the filter an opportunity after all the bitmaps have been loaded, to go and look at the bitmaps and set the animation properties accordingly. In the case of a GIF filter this would allow it to set the dithering to none and the palette to something closer to what has been loaded. This baseclass version does nothing. ********************************************************************************************/ BOOL BaseBitmapFilter::SetAnimationPropertiesFromLoaded(Spread * pSpread) { // Do nothing return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::ImportBitmap(CCLexFile* pDiskFile, KernelBitmap** ppBitmap) Author: Will_Cowling (Xara Group Ltd) Created: 8/4/94 Inputs: - Returns: TRUE if the bitmap was imported ok (or if it wasn't imported because the file format does not support it; FALSE if an error occured. Purpose: - Errors: Usual disk/file errors. SeeAlso: CamelotEPSFilter::ExportBitmap ********************************************************************************************/ BOOL BaseBitmapFilter::ImportBitmap(CCLexFile* pDiskFile, KernelBitmap** ppBitmap) { // Make a note of the disk file we are given InputFile = pDiskFile; if (ProcessImportOptions() == FALSE) return FALSE; // Let's get ready if (!PrepareToImport()) return FALSE; if (!ImportBitmap(pDiskFile, ppBitmap, 1)) { if (m_pImportOptions != NULL) { delete m_pImportOptions; m_pImportOptions = NULL; } return FALSE; } if (m_pImportOptions != NULL) { delete m_pImportOptions; m_pImportOptions = NULL; } return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::ImportBitmap(CCLexFile* pDiskFile, KernelBitmap** ppBitmap, const UINT32 nBitmapToRead) Author: Colin_Barfoot (Xara Group Ltd) Created: 12/06/96 Inputs: pDiskFile - the CCLexFile from which the bitmap should be imported nBitmapToRead - the position of the bitmap in the CCLexFile Outputs: ppBitmap - a pointer to the KernelBitmap into which the bitmap will be imported Returns: TRUE if the bitmap was imported ok (or if it wasn't imported because the file format does not support it; FALSE if an error occured. Purpose: Imports the nBitmapToRead'th bitmap from the given file. This may be used to import a file either via the menu or from the EPS filters. Errors: SeeAlso: CamelotEPSFilter::ExportBitmap, DoImport(), SGLibOil:: ********************************************************************************************/ BOOL BaseBitmapFilter::ImportBitmap(CCLexFile* pDiskFile, KernelBitmap** ppBitmap, const UINT32 nBitmapToRead) { ERROR2IF(pDiskFile == NULL, FALSE, "pDiskFile - invalid"); ERROR2IF(ppBitmap == NULL, FALSE, "ppBitmap is NULL"); ERROR2IF(nBitmapToRead < 1, FALSE, "nBitmapToRead < 1"); *ppBitmap = NULL; SetBitmapNumber(nBitmapToRead); KernelBitmap* KernelBmp; BOOL IsNew = TRUE; BOOL ReuseExisting = ShouldReuseExistingBitmaps(); if (IsPreviewBitmap) //for preview bitmaps always false ReuseExisting = FALSE; BOOL Success = KernelBitmap::ImportBitmap(this, NULL, 0, &KernelBmp, ReuseExisting ? &IsNew : NULL); if (Success && IsNew) { // Give the bitmap a name from the file path CreateBitmapName(pDiskFile, KernelBmp, nBitmapToRead); // If we have a BitmapSource then use it if (m_pBitmapSource != NULL) { KernelBmp->SetOriginalSource(m_pBitmapSource, this); delete InputFile; InputFile = NULL; } } else { // Throw away the source as we already have it or don't need it if (m_pBitmapSource != NULL) { delete m_pBitmapSource; delete InputFile; InputFile = NULL; } } // Free up dynamic objects used for import and close the file CleanUpAfterImport(); if (!Success) { // Did not work - report this to the caller. return FALSE; } *ppBitmap = KernelBmp; return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::ProcessImportOptions() Author: Colin_Barfoot (Xara Group Ltd) Created: 12/06/96 Inputs: - Outputs: - Returns: TRUE if it is OK to continue processing FALSE if an error occured or the user cancelled the import, in which case Error::SetError is called signalling the fact. Purpose: Validates the options returned by GetImportOptions Sets m_pImportOptions if OK Shouldn't really be overridden SeeAlso: BaseBitmapFilter::DoImport() ********************************************************************************************/ BOOL BaseBitmapFilter::ProcessImportOptions() { // Get any user options, if required ERROR3IF(m_pImportOptions != NULL, "m_pImportOptions not deleted"); BitmapImportOptions* options = GetImportOptions(); if (options == NULL) { ERROR3("options is NULL"); return FALSE; } ERROR3IF(!options->IS_KIND_OF(BitmapImportOptions), "options is not"); if (!options->m_bValid) { delete options; m_pImportOptions = NULL; return TRUE; } if (options->m_bCancelled) { delete options; m_pImportOptions = NULL; Error::SetError(_R(IDN_USER_CANCELLED),0); // Expects error set on cancel return FALSE; // if cancelled } m_pImportOptions = options; return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::CreateBitmapName(const CCLexFile* pDiskFile, const KernelBitmap* pBitmap, const UINT32 nBitmapNumber) Author: Colin_Barfoot (Xara Group Ltd) Created: 18/06/96 Inputs: pDiskFile : file from which the bitmap was extracted pBitmap : the bitmap itself nBitmapNumber : the number of the bitmap in the file Outputs: - Returns: TRUE if name set OK, FALSE if failed. Purpose: Sets the name of the given bitmap to that of the form "filename - number.ext" or "filename.ext" depending on whether we have assumed there to be more than one image in the imported file. Used by ImportBitmap to supply this name and avoid bizarre file names when re-exporting. Errors: ERROR2 for invalid arguments ERROR3 if pDiskFile is not a kind of CCDiskFile Notes: Suppose we should really set the names after when we know that there actually are multiple bitmaps ********************************************************************************************/ BOOL BaseBitmapFilter::CreateBitmapName(const CCLexFile* pDiskFile, const KernelBitmap* pBitmap, const UINT32 nBitmapNumber) { ERROR2IF(pDiskFile == NULL, FALSE, "pDiskFile - invalid"); ERROR2IF(pBitmap == NULL, FALSE, "pBitmap - invalid"); PathName Path = pDiskFile->GetPathName(); if (!Path.IsValid()) { TRACE( _T("Invalid file path in BaseBitmapFilter::CreateBitmapName\n") ); return FALSE; } String_256 Str; if ((nBitmapNumber > 1) || AreBitmapsToRead()) { // give it a number ? String_256 shortName = Path.GetFileName(FALSE); // without extension String_16 index; Convert::LongToString(INT32(nBitmapNumber), &index); Str.MakeMsg(_R(IDS_BITMAP_NAME), (TCHAR*)shortName, (TCHAR*)index); Path.SetFileName(Str); } Str = Path.GetFileName(TRUE); // with extension pBitmap->ActualBitmap->SetName(Str); return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::ReadFromFile( OILBitmap* pOilBitmap ) Author: Neville_Humphrys (Xara Group Ltd) Created: 18/8/95 Inputs: pOilBitmap pointer to the oil bitmap data to be filled in Outputs: Will have filled in BMInfo pointer to the bitmap header to fill in BMBytes pointer to the bitmap data to fill in Purpose: Actually does the process of reading a bitmap from a file. Inherited classes override this to read in different file formats. Returns: TRUE if worked, FALSE if failed. ********************************************************************************************/ BOOL BaseBitmapFilter::ReadFromFile( OILBitmap* pOilBitmap ) { ERROR3("Base class bitmap filter ReadFromFile called"); return FALSE; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::ReadFromFile( OILBitmap* pOilBitmap, BaseCamelotFilter *pFilter, CCLexFile* pFile, BOOL IsCompressed) Author: Neville_Humphrys (Xara Group Ltd) Created: 20/6/96 Inputs: pOilBitmap pointer to the oil bitmap data to be filled in pFilter - the BaseCamelotFilter which provides functions like progress update pFile - the CCFile class to use to read the data from IsCompressed - Flag to say the bitmap is compressed or not. Outputs: Will have filled in BMInfo pointer to the bitmap header to fill in BMBytes pointer to the bitmap data to fill in Purpose: Actually does the process of reading a bitmap from a file. Inherited classes override this to read in different file formats. It is used by the web/native filters to pull out a bitmap definition from inside a bitmap definition record. IsCompressed is only used for BMP/BMPZIP type bitmaps at present. Assumes: pFile has already been opened up for reading pFilter has been set up for reading the data e.g. progress bar Returns: TRUE if worked, FALSE if failed. ********************************************************************************************/ BOOL BaseBitmapFilter::ReadFromFile(OILBitmap* pOilBitmap, BaseCamelotFilter* pFilter, CCLexFile* pFile, BOOL IsCompressed) { ERROR3("Base class bitmap filter ReadFromFile called"); return FALSE; } /******************************************************************************************** > UINT32 BaseBitmapFilter::GetBitmapNumber() const Author: Colin_Barfoot (Xara Group Ltd) Created: 11/06/96 Inputs: - Returns: The next bitmap to read 0 if the bitmap number is invalid Purpose: On entry to the filter this member function returns the number of the desired bitmap in the file. Once the import is complete, either SetBitmapNumber is called with an argument of the next bitmap that can be read or SetLastBitmap is called indicating there are no more to read. Scope: protected SeeAlso: SetBitmapNumber(), SetLastBitmap(), ...ReadFromFile() ********************************************************************************************/ UINT32 BaseBitmapFilter::GetBitmapNumber() const { return m_nBitmapToRead < 1 ? 0 : (UINT32) m_nBitmapToRead; } /******************************************************************************************** > BOOL BaseBitmapFilter::SetBitmapNumber(UINT32 nBitmapToRead) Author: Colin_Barfoot (Xara Group Ltd) Created: 11/06/96 Inputs: - Returns: TRUE if set OK FALSE otherwise Purpose: Once a filter has read a bitmap it should call this member function with the number of the next bitmap that can be read. If there are none, SetLastBitmap() should be called instead. Scope: protected SeeAlso: SetLastBitmap(), GetBitmapNumber() ********************************************************************************************/ BOOL BaseBitmapFilter::SetBitmapNumber(const UINT32 nBitmapToRead) { ERROR2IF(nBitmapToRead < 1, FALSE, "nBitmapToRead invalid"); m_nBitmapToRead = nBitmapToRead; return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::SetLastBitmap() Author: Colin_Barfoot (Xara Group Ltd) Created: 11/06/96 Inputs: - Returns: TRUE if set OK FALSE otherwise Purpose: When the bitmap filter has no more bitmaps to read from its file it should call this member function. Scope: protected SeeAlso: SetBitmapNumber(), GetBitmapNumber() ********************************************************************************************/ BOOL BaseBitmapFilter::SetLastBitmap() { m_nBitmapToRead = -1; return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::AreBitmapsToRead() const Author: Colin_Barfoot (Xara Group Ltd) Created: 11/06/96 Inputs: - Returns: TRUE if there are bitmaps in the set OK FALSE otherwise Purpose: The BaseBitmapFilter uses this to determine whether or not it should try to read another bitmap from the file. Scope: protected SeeAlso: GetBitmapNumber(), SetBitmapNumber(), SetLastBitmap() ********************************************************************************************/ BOOL BaseBitmapFilter::AreBitmapsToRead() const { return (m_nBitmapToRead != -1); } /******************************************************************************************** > BOOL BaseBitmapFilter::SetPixelWidth(const BMP_SIZE& Width) Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Inputs: Width : The width of the bitmap to be exported in pixels Returns: TRUE if the operation was successful FALSE otherwise Purpose: Support function to obtain bitmap info See Also: GetExportHeight() ********************************************************************************************/ BOOL BaseBitmapFilter::SetPixelWidth(const BMP_SIZE& Width) { m_PixelWidth = Width; return TRUE; } /******************************************************************************************** > BMP_SIZE BaseBitmapFilter::GetPixelWidth() const Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Returns: The width of the bitmap to export in pixels Purpose: Support function to obtain bitmap info ********************************************************************************************/ BMP_SIZE BaseBitmapFilter::GetPixelWidth() const { return m_PixelWidth; } /******************************************************************************************** > BMP_SIZE BaseBitmapFilter::GetPixelHeight() const Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Returns: The height of the bitmap to export in pixels Purpose: Support function to obtain bitmap info ********************************************************************************************/ BMP_SIZE BaseBitmapFilter::GetPixelHeight() const { return m_PixelHeight; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::SetPixelHeight(const BMP_SIZE& Height) Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Inputs: Height : The pixel height of the bitmap to be exported Returns: TRUE if the operation was successful FALSE otherwise Purpose: Support function to obtain bitmap info See Also: GetExportHeight() ********************************************************************************************/ BOOL BaseBitmapFilter::SetPixelHeight(const BMP_SIZE& Height) { m_PixelHeight = Height; return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::GetExportOptions(* pOptions) Author: Colin_Barfoot (Xara Group Ltd) Created: 12/11/96 Inputs: pOptions : A pointer to some BitmapExportOptions Outputs: pOptions : the same with some extra information in it Returns: TRUE if OK FALSE if user pressed Cancel. Purpose: Allows the user to be prompted to get export information which should be set in the given BitmapExportOptions. Notes: Due to the existence of three public entry points into bitmap filters, two of which are virtual, the BaseBitmapFilter::WriteBitmapToFile may not be called and so may not create a BitmapExportOptions object, which would not be disasterous in itself, unless a derived class calls BaseBitmapFilter functions which use BitmapExportOptions. It is therefore at the filter author's discretion whether or not to create one of these objects. Scope: protected ********************************************************************************************/ BOOL BaseBitmapFilter::GetExportOptions(BitmapExportOptions* pOptions) { #if !defined(EXCLUDE_FROM_RALPH) ERROR2IF(pOptions == NULL, FALSE, "NULL Args"); WrittenHeader = FALSE; // When saving a bitmap directly then only use the dialog box for certain filter types // as it will be just requesting compression type and hence otherwise it is superfluous. // Otherwise, always use it. BOOL Ok = TRUE; if (pOptions->GetSelectionType() != ABITMAP) { // This is ok as we are using a modal dialog box PORTNOTE("export", "Remove BmpPrefsDlg usage") #if !defined(EXCLUDE_FROM_XARALX) Ok = BmpPrefsDlg::InvokeDialog(pOptions); #endif } if (Ok) { // Only save the depth as the default if not saving a bitmap itself // from say the bitmap gallery. (keep this rubbish for now...) if (pOptions->GetSelectionType() != ABITMAP && pOptions->GetSelectionType() != SOMEBITMAPS) { pOptions->SetAsDefaults(); } PaletteType = PAL_OPTIMISED; } // Return with the ok/cancel state used on the dialog box return Ok; #else return FALSE; #endif } // SMFIX sjk 5/12/00 there used to be some junk in the call to GetExportOptions that assumed the // filter type being used which could be changed by the GetExportOptions call itself // therefore all this sort of stuff should be called on the correct known filter using this // call afterwards void BaseBitmapFilter::PostGetExportOptions(BitmapExportOptions* pOptions) { pOptions->SetAsDefaults(); } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::SetUpClippingRectangleForExport(Spread *pSpread, SelectionType Selection) Author: Neville_Humphrys (Xara Group Ltd) Created: 29/4/97 Inputs: pSpread the spread to export Selection the selection type to use during export Returns: TRUE if the operation was successful FALSE otherwise Purpose: Sets up the class variable ClipRect to be the clipping rectangle to be used during export. See Also: PrepareToExport() ********************************************************************************************/ BOOL BaseBitmapFilter::SetUpClippingRectangleForExport(Spread *pSpread, SelectionType Selection) { ERROR2IF(pSpread == NULL,FALSE,"SetUpClippingRectangleForExport Bad spread"); // We need to decide what clipping rectangle to set up which we will then render the // bitmap through. The choice might be to export:- // - the selection bounds (if there is a selection), // - or the current spread // - or the current drawing // First, check if there is a selection present. ClipRect should be empty if not. // Karim 17/07/2000 // We need to take controller nodes into account when we're finding this bbox, // which means temporarily setting PromoteToParent on the selection. SelRange* pSel = GetApplication()->FindSelection(); if (pSel != NULL) { ClipRect = pSel->GetBoundingRect(TRUE); } // However, if this is a Preview Bitmap then use the spreads bounds as the clip rect // This should in fact be the bounding rectangle of all visible layers in the current // drawing. if (IsPreviewBitmap || (Selection==DRAWING)) { // Work out the size of the rectangle encompassing the drawing (visible layers only) ClipRect = GetSizeOfDrawing(pSpread); } if (!IsPreviewBitmap && (Selection==SELECTION)) { // Quick check to make sure the selection is something sensible ... SelRange* pSel = GetApplication()->FindSelection(); if (pSel && pSel->Count()==1) { // Only one thing selected ... Is it the Text Caret per chance ? Node* pSelNode = pSel->FindFirst(); if (pSelNode && pSelNode->IsAVisibleTextNode()) { VisibleTextNode* pTextNode = (VisibleTextNode*)pSelNode; if (pTextNode->IsACaret()) { // Aha! It's the Caret that's selected. // We'll use the bounds of the parent text line instead then ... Node* pTextLine = pTextNode->FindParent(); ERROR3IF(!IS_A(pTextLine, TextLine), "Caret doesn't have a parent text line in DoCreateBitmap"); // Get the bounds of the text line ClipRect = ((TextLine*)pTextLine)->GetBoundingRect(); Selection = DRAWING; } } } } // If this is the Preview bitmap, then we have to check for too big and too small cases if (IsPreviewBitmap) { // Find out how big the preview is at the moment MILLIPOINT Width = ClipRect.Width(); MILLIPOINT Height = ClipRect.Height(); // Note from Martin: This is probably a bodge connected with the scaling bodge which // has been corrected below, but I'm leaving this one in cos it leaves a nice 1 pixel // boarder round the thumbnail. // Inflate the rect a little as we can get odd clipping effects at the edges otherwise ClipRect.Inflate(Width/128, Height/128); // Define what too big and too small are // bigger the 2 feet or smaller than 1/2 inch MILLIPOINT MaxWidth = 72000 * 12 * 2; MILLIPOINT MinWidth = 72000 / 2; // See if the rectangle is too big or too small and fix it if it is MILLIPOINT WidthChange = 0; MILLIPOINT HeightChange = 0; // too big? WidthChange = Width>MaxWidth ? (MaxWidth - Width)/2 : 0; // a -ve number HeightChange = Height>MaxWidth ? (MaxWidth - Height)/2 : 0; // a -ve number // too little? WidthChange = Width BOOL BaseBitmapFilter::PrepareToExport(Spread *pSpread, UINT32 Depth, double DPI, SelectionType Selection, UINT32 Dither = XARADITHER_ORDERED_GREY) Author: Andy_Pennell (Xara Group Ltd) Created: 28/6/94 Inputs: Pointer to the spread, colour depth in bpp, resolution in dpi and a selection flag which indicates whether there is a selection present (=1), no selection (=0) and if there is a selection whether we want to export the spread instead (=2). Returns: TRUE if succeeded, FALSE if not (e.g. no memory) Purpose: Prepare to export bitmap data using this filter. This sets up the filter to a sensible state for reading. Assumes file is opened by caller. This should NOT be overridden by inherited classes. Errors: Out of memory. SeeAlso: BaseBitmapFilter::DoImport; BaseBitmapFilter::CleanUpAfterImport Scope: Private ********************************************************************************************/ #define PIXELWIDTH 750 // @ 96DPI @ 100% #define PIXELHEIGHT 750 // @ 96DPI @ 100% BOOL BaseBitmapFilter::PrepareToExport(Spread *pSpread, UINT32 Depth, double DPI, SelectionType Selection, UINT32 Dither) { #ifdef DO_EXPORT ERROR2IF(pSpread==NULL,FALSE,"BaseBitmapFilter::PrepareToExport null spread pointer"); // Check whether the selection contains objects that can't be represented // in a bitmap if (WarnIfIncompatible()==FALSE) { ERRORIF(TRUE, _R(IDN_USER_CANCELLED), FALSE); } // We need to decide what clipping rectangle to set up which we will then render the // bitmap through. The choice might be to export:- // - the selection bounds (if there is a selection), // - or the current spread // - or the current drawing // Ask the virtual function to set it up for us if (ClipRect.IsEmpty()) SetUpClippingRectangleForExport(pSpread, Selection); // We can either have no selection present whereby the user may have chosen to export // the spread or the drawing OR we have a selection present whereby the user may have // chosen to export the spread or drawing instead. In the later case we must output the // spread instead of the selection but double check there is a selection. if (ClipRect.IsEmpty() || ClipRect.Width() < MinExportSize || ClipRect.Height() < MinExportSize || ((Selection==SPREAD) && (!IsPreviewBitmap))) { // Use our function to work out the size of the spread ClipRect = GetSizeOfSpread(pSpread); if (ClipRect.IsEmpty()) { ENSURE(FALSE, "Current spread has no pages"); ERRORIF(TRUE, _R(IDT_DOC_BADSTRUCTURE), FALSE); } } // Don't use rendering matrix when exporting BMPs as it uses coordinates as is Matrix Identity; // Don't use view scale; set to 1 FIXED16 Scale(1); // If this is the Preview bitmap, the scale may need changin if (IsPreviewBitmap) { // Find out the maximum dimension of the clip rect MILLIPOINT Width = ClipRect.Width(); MILLIPOINT Height = ClipRect.Height(); MILLIPOINT MaxSize = (Width>Height) ? Width : Height; // this can't happen considering the code above - but you never know. ERROR3IF( MaxSize==0, "BaseBitmapFilter::PrepareToExport both dimensions of preview are zero"); // stop div zeros. We set it quite high here otherwise we get huge values in the DPI field if (MaxSize==0) MaxSize = 1000; // Set the scale factor to get this down into the required size //WEBSTER-Martin-02/01/97 MILLIPOINT WantSize = PreviewFilter::PreviewBitmapSize; // Removed changes to 'Scale' variable so the scale factor is // now always 1. Jonathan Payne, 8/9/2000. // The Scale Factor is not actually used, so we have to change the size of things // by effecting the DPI. Scale the DPI, but make sure it does not get too small. DPI = ((double)WantSize) / ((double)MaxSize) * DPI; if (DPI < 4.0) DPI = 4.0; //WEBSTER-Martin-30/01/97 // It doesn't matter what rounding we do here, but there is a problem because the bitmap // is not exactly the same size as the cliprect need something like ??? Any region outside // the cliprect is rendered as black hence the black lines that appear at the top and bottom // of some previews. It is especially noticable when the original is smaller than the preview. // Here we are using the dpi to do some scaling we're not really concerned with the exact value INT32 b_dpi = (INT32) DPI; DPI = (double)b_dpi; //round down } else { // Ensure Bitmap is at least 1 pixel square! if (ClipRect.Width()IsCMYK()); ExportRegion = new GRenderBitmap(ClipRect, Identity, Scale, Depth, DPI, FALSE, Dither, NULL, TRUE); if (ExportRegion == NULL) // Error already set by new, so just return return FALSE; ExportRegion->SetFilter(this); // exporting a bitmap, so we will want any bitmaps used in there to be of the best quality - sjk ExportRegion->SetUsingSmoothedBitmaps(TRUE); // MarkH 23/7/99 - New Flag to say that we require to render using the biCompression Field if(GetBitmapExportOptions()->GetDepth() == 32) { ExportRegion->m_DoCompression = TRUE; } // we need a View to Attach to, so that: // default Quality setting // CalcPixelWidth etc get called DocView *View = DocView::GetCurrent(); if (View) { // Must force background rendering off as otherwise we might get a partly // rendered drawing or object if it is complex. ForceBackgroundRedrawOff(View); if (GetBitmapExportOptions()->GetDepth() == 1) { // If we are outputting at 1bpp, then we'll force antialiasing off, // so that Gavin's palette optimisation can detect objects which // are 'one solid colour' ForceAntialiasingOff(View); } // If we are in preview bitmap mode then force anti-aliasing to be full // rather than the default setting for the view if (IsPreviewBitmap) { ForceAntialiasingFull(View); } // Attach to the right device. (note no DC) ExportRegion->AttachDevice(View, NULL, pSpread); } else { ERROR2(FALSE,"BaseBitmapFilter::WriteToFile no current view"); } #endif // All ok return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::WarnIfIncompatible() Author: Phil_Martin (Xara Group Ltd) Created: 14/05/2004 Inputs: - Returns: TRUE is can continue FALSE if export should be aborted Purpose: Checks for things that can't be represented using the current options E.g. non-mix transparencies in Alpha channel bitmap Errors: - Scope: Protected ********************************************************************************************/ BOOL BaseBitmapFilter::WarnIfIncompatible() { // Check whether the user has asked us to be silent about this if (bDontWarnBitmapNonMixTransp) return TRUE; // Check whether the export options will make transparencies difficult // Is export type 32BPP including alpha? // If not everything's OK if (m_pExportOptions->GetDepth()!=32) { return TRUE; } // Check whether the export selection contains non-mix transparency BOOL bFound = FALSE; Node* pNode = NULL; switch (m_pExportOptions->GetSelectionType()) { case SELECTION: { Range* pscanrange; pscanrange = Camelot.FindSelection(); pNode = pscanrange->FindFirst(TRUE); while (pNode!=NULL && !bFound) { if (pNode->IsAnAttribute()) { if (((NodeAttribute*)pNode)->IsATranspFill()) { UINT32 transptype = ((AttrFillGeometry*)pNode)->GetTranspType(); if (transptype!=TT_Mix && transptype!=TT_NoTranspType) bFound = TRUE; } } pNode = pscanrange->FindNext(pNode, TRUE); } } break; case DRAWING: case PAGE: case SPREAD: { Node* pRootNode = pSpread; pNode = pRootNode->FindFirstDepthFirst(); while (pNode!=NULL && !bFound) { if (pNode->IsAnAttribute()) { if (((NodeAttribute*)pNode)->IsATranspFill()) { UINT32 transptype = ((AttrFillGeometry*)pNode)->GetTranspType(); if (transptype!=TT_Mix && transptype!=TT_NoTranspType) bFound = TRUE; } } pNode = pNode->FindNextDepthFirst(pRootNode); } } break; default: ERROR2RAW("Unknown selection type in WarnIfIncompatible"); return FALSE; } if (!bFound) return TRUE; // We need to show the warning dialog... INT32 ret = InformWarning(_R(IDS_WARN_INCOMPATIBLETRANSPARENCY), _R(IDS_CONTINUE), _R(IDS_ALWAYSCONTINUE), _R(IDS_CANCEL)); if (ret==3) return FALSE; if (ret==2) bDontWarnBitmapNonMixTransp = TRUE; return TRUE; } /******************************************************************************************** > void BaseBitmapFilter::ForceBackgroundRedrawOff(DocView* pView) Author: Will_Cowling (Xara Group Ltd) Created: 1/7/96 Inputs: pView, pointer to the View to change Returns: - Purpose: Forces background redraw off in the specified view, so we render all the objects in one pass. Use RestoreBackgroundRedrawState to restore the state. Errors: - SeeAlso: BaseBitmapFilter::RestoreBackgroundRedrawState Scope: Protected ********************************************************************************************/ void BaseBitmapFilter::ForceBackgroundRedrawOff(DocView* pView) { ERROR3IF(pView == NULL, "NULL pointer passed into BaseBitmapFilter::ForceBackgroundRedrawOff"); if (pView == NULL) return; // We wan't to make sure we only remember the old state once ... if (!BackgroundRedrawStateSet) { BackgroundRedrawState = pView->GetForeBackMode(); BackgroundRedrawStateSet = TRUE; // So we don't do this more than once } pView->SetForeBackMode(FALSE); } /******************************************************************************************** > void BaseBitmapFilter::RestoreBackgroundRedrawState(DocView* pView) Author: Will_Cowling (Xara Group Ltd) Created: 1/7/96 Inputs: pView, pointer to the View to change Returns: - Purpose: Restores the background redraw state in the specified view, to the state before we called BaseBitmapFilter::ForceBackgroundRedrawOff. Errors: - SeeAlso: BaseBitmapFilter::ForceBackgroundRedrawOff Scope: Protected ********************************************************************************************/ void BaseBitmapFilter::RestoreBackgroundRedrawState(DocView* pView) { ERROR3IF(pView == NULL, "NULL pointer passed into BaseBitmapFilter::RestoreBackgroundRedrawState"); if (pView == NULL) return; // Only restore if we saved the state earlier ... if (BackgroundRedrawStateSet) { pView->SetForeBackMode(BackgroundRedrawState); BackgroundRedrawStateSet = FALSE; } } /******************************************************************************************** > void BaseBitmapFilter::ForceAntialiasingOff(DocView* pView) Author: Will_Cowling (Xara Group Ltd) Created: 1/7/96 Inputs: pView, pointer to the View to change Returns: - Purpose: Forces Antialiasing off in the specified view. Use RestoreViewQuality to restore the quality. Errors: - SeeAlso: BaseBitmapFilter::RestoreViewQuality Scope: Protected ********************************************************************************************/ void BaseBitmapFilter::ForceAntialiasingOff(DocView* pView) { ERROR3IF(pView == NULL, "NULL pointer passed into BaseBitmapFilter::ForceAntialiasingOff"); if (pView == NULL) return; // We don't need to do anything if the view quality is already not Antialiased if (!ViewQualitySet && pView->RenderQuality.GetAntialiasQuality() >= Quality::FullAntialias) { ViewQuality = pView->RenderQuality; ViewQualitySet = TRUE; // So we don't do this more than once pView->RenderQuality.SetQuality(QUALITY_DEFAULT); } } /******************************************************************************************** > void BaseBitmapFilter::ForceAntialiasingFull(DocView* pView) Author: Neville_Humphrys (Xara Group Ltd) Created: 11/9/96 Inputs: pView, pointer to the View to change Returns: - Purpose: Forces Antialiasing to be full in the specified view. Use RestoreViewQuality to restore the quality. Used when generating preview bitmaps, which should always be in full anti- aliasing mode. Errors: - SeeAlso: BaseBitmapFilter::RestoreViewQuality Scope: Protected ********************************************************************************************/ void BaseBitmapFilter::ForceAntialiasingFull(DocView* pView) { ERROR3IF(pView == NULL, "NULL pointer passed into BaseBitmapFilter::ForceAntialiasingFull"); if (pView == NULL) return; // We don't need to do anything if the view quality is already not Antialiased if (!ViewQualitySet && pView->RenderQuality.GetAntialiasQuality() < Quality::FullAntialias) { ViewQuality = pView->RenderQuality; ViewQualitySet = TRUE; // So we don't do this more than once pView->RenderQuality.SetQuality(QUALITY_MAX); } } /******************************************************************************************** > void BaseBitmapFilter::RestoreViewQuality(DocView* pView) Author: Will_Cowling (Xara Group Ltd) Created: 1/7/96 Inputs: pView, pointer to the View to change Returns: - Purpose: Restores the view quality to the state before we called ForceAntialiasingOff Errors: - SeeAlso: BaseBitmapFilter::ForceAntialiasingOff Scope: Protected ********************************************************************************************/ void BaseBitmapFilter::RestoreViewQuality(DocView* pView) { ERROR3IF(pView == NULL, "NULL pointer passed into BaseBitmapFilter::RestoreViewQuality"); if (pView == NULL) return; if (ViewQualitySet) { // Restore the previous view quality pView->RenderQuality = ViewQuality; ViewQualitySet = FALSE; } } /******************************************************************************************** > void BaseBitmapFilter::CleanUpAfterExport() Author: Andy_Pennell (Xara Group Ltd) Created: 28/6/94 Purpose: Cleans up the memory allocated by BaseBitmapFilter::PrepareToImport() - used when the import process ends, either normally or abnormally. Override if extra things are required. SeeAlso: BaseBitmapFilter::PrepareToImport; BaseBitmapFilter::DoImport Scope: Private ********************************************************************************************/ void BaseBitmapFilter::CleanUpAfterExport() { #ifdef DO_EXPORT // Get rid of our dynamic objects if (OutputFile) { OutputFile = NULL; } DocView *View = DocView::GetCurrent(); if (View) { if( ViewQualitySet ) { // Only need to do this if the view quality has been set but not restored. RestoreViewQuality(View); } } if (ExportRegion) { // If we have create the export region then delete it delete ExportRegion; ExportRegion = NULL; // Must try and set our background rendering state back to the default DocView *View = DocView::GetCurrent(); if (View) { // Force background back to its entry state RestoreBackgroundRedrawState(View); } } if (pOptimisedPalette) { CCFree( pOptimisedPalette ); pOptimisedPalette = NULL; } #endif } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::GetRenderBottomToTop() Author: Neville_Humphrys (Xara Group Ltd) Created: 17/5/95 Inputs: - Outputs: - Returns: TRUE if going to use the default of rendering bottom to top, FALSE otherwise Purpose: Find out which way we need to render ********************************************************************************************/ BOOL BaseBitmapFilter::GetRenderBottomToTop() { return TRUE; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::DoExport(Operation* pOp, CCLexFile* pFile, PathName* pPath, Document* pDoc) Author: Andy_Pennell (Xara Group Ltd) Created: 22/8/94 Inputs: pOp - the operation that started the export off pDiskFile - the file to put the exported data into pPath - the pathname of the file to be exported to pDoc - the document to export Returns: TRUE if worked, FALSE if failed. Purpose: Exports the current selection as a bitmap, via the virtual fns of the inherited class. Do not override unless really necessary. SeeAlso: GetExportOptions; PrepareToExport; ExportRenderNodes; CleanUpAfterExport; ********************************************************************************************/ BOOL BaseBitmapFilter::DoExport(Operation *pOp, CCLexFile* pFile, PathName* pPath, Document* pDoc, BOOL ShowOptions) { // The success / failure flag. BOOL ok = TRUE; // smfix put back more or less this should be only used by the preview filters #ifdef DO_EXPORT // Dreamweaver integration. // BOOL bDesignNotesSelectedValue = FALSE; ERROR2IF(pOp == NULL, FALSE,"BaseBitmapFilter::DoExport no export operation"); ERROR2IF(pFile == NULL, FALSE,"BaseBitmapFilter::DoExport no file to export to"); ERROR2IF(pPath == NULL, FALSE,"BaseBitmapFilter::DoExport no export pathname"); ERROR2IF(pDoc == NULL, FALSE,"BaseBitmapFilter::DoExport no document to export"); // Set the bitmap pointer to null just in case, usually only used by DoExportBitmap pExportBitmap = NULL; // Get pointer to the spread to export. PORTNOTE("spread", "Multi-spread warning!") pSpread = GetFirstSpread(pDoc); ERROR2IF(pSpread == NULL, FALSE,"BaseCamelotFilter::DoExport no spread to export"); // We must now check if there is a selection present so that we can set up whether the // user gets the choice of exporting the selection, drawing or spread if there is a // selection present OR just a choice between the spread or drawing if no selection is // present. // If have a caret selected in a text story then the selection will be almost zero so // trap this case as well. ClipRect = GetApplication ()->FindSelection ()->GetBoundingRect(TRUE); SelectionType Selection = DRAWING; // Determine the selection type. if ( !IsPreviewBitmap && !ClipRect.IsEmpty() && ClipRect.Width() >= MinExportSize && ClipRect.Height() >= MinExportSize ) { Selection = SELECTION; // Something is selected, so use this. } else // The selection is either too small to export, or the clipping rectangle is empty. { // Work out the size of the rectangle encompassing the drawing (visible layers only). ClipRect = GetSizeOfDrawing(pSpread); // Check that that cliprect is ok, if not then set the spread as the export type. if ( ClipRect.IsEmpty() || ClipRect.Width() < MinExportSize || ClipRect.Height() < MinExportSize ) Selection = SPREAD; } // If there is no selection then warn the user that exporting the current spread may // take a lot of disc space, but only if this is not a Preview Bitmap. if ((!IsPreviewBitmap) && (Selection == SPREAD)) { // Warn the user that there is no selection = large export ErrorInfo Info; Info.ErrorMsg = _R(IDT_BMPEXP_NOSELECTION); Info.Button[0] = _R(IDB_EXPQUERY_EXPORT); Info.Button[1] = _R(IDB_EXPQUERY_DONTEXPORT); if ((ResourceID)(AskQuestion(&Info)) == _R(IDB_EXPQUERY_DONTEXPORT)) { Error::SetError(_R(IDN_USER_CANCELLED),0); // Expects error set on cancel ok = FALSE; } } // Mark H 18/12/00 // From here on, I`ve tidied up the code so that this function is responsible for it`s // own Bitmap Export Options pointer and not reliant on the member variable. This fixes //a 1.5MB!!! memory leak on exiting of the program! // Create a new Bitmap Export Options pointer for the current filter BitmapExportOptions* pExportOptions = CreateExportOptions(); // Try to create the export options. if (ok && pExportOptions) { pExportOptions->RetrieveDefaults(); pExportOptions->SetSelectionType(Selection); pExportOptions->SetBackgroundTransparency(FALSE); } else ok = FALSE; //Graham W 3/7/97: Tell the preview dialog what the path to save out to is BmapPrevDlg::m_pthExport=*pPath; if(ok) ok = GetExportOptions(pExportOptions); // This pointer is used to call the ExportBitmap function. If the filetype has changed, // then it will be set-up to be invoked from the new type. BaseBitmapFilter *pFilter = this; // Write out the bitmap. if (ok) { if (!pFilter->DoExportWithOptions(pOp, pFile, pPath, pDoc, pExportOptions)) { // Export failed, therefore no valid export options. Error::SetError(_R(IDN_USER_CANCELLED),0); } } // Clear up the existing bitmap options. if(pExportOptions) { delete pExportOptions; pExportOptions = NULL; } #endif return ok; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::DoExportDoc(Operation* pOp, CCLexFile* pFile, PathName* pPath, Document* pDoc, UINT32 Depth, double DPI, const SelectionType& Selection , BOOL UseExistingPalette) Author: Gerry_Iles (Xara Group Ltd) Created: 12/6/96 Purpose: Actually does the work of DoExport() above Code split out for use by DoExportBitmaps() function This DOES NOT call CleanUpAfterExport() if it fails If the call returns FALSE then the caller must call CleanUpAfterExport() Returns: TRUE if worked, FALSE if failed. Scope: protected SeeAlso: GetExportOptions; PrepareToExport; ExportRenderNodes; CleanUpAfterExport; Additional information( ap ) - Added 'UseExistingPalette'. If this is TRUE, then the existing palette in BmapPrevDlg is used instead of a newly generated one. This variable is given the default value of FALSE. ********************************************************************************************/ BOOL BaseBitmapFilter::DoExportDoc(Operation* pOp, CCLexFile* pFile, PathName* pPath, Document* pDoc, UINT32 RenderDepth, double DPI, const SelectionType& Selection , BOOL UseExistingPalette) { #ifdef DO_EXPORT if (!WritePreFrame()) return(FALSE); /* // Only try to do the exact palette if we are using an 8 bit optimised palette if( ( PaletteType == 1 ) && ( GetBitmapExportOptions()->GetDepth() == 8 ) ) GRenderOptPalette::UseOldPalette = FALSE; else GRenderOptPalette::UseOldPalette = TRUE; */ // Set up device context and render region for this export. // This will show a progress hourglass for the objects being rendered // This will now also write the data out to file via our ExportRenderNodes function if (!PrepareToExport(pSpread, RenderDepth, DPI, Selection)) { return FALSE; } // SMFIX // this is where we will build up the palette from the export options IF the one // that is already in the export options is NOT valid // the fn bellow export render needs the palette to be valid // m_pExportOptions->CreateValidPalette(); // this call sets this palette in the lower reaches of the code from the palette held in the export options // AlterPaletteContents(m_pExportOptions->GetLogicalPalette()); // Export the data to the file ensuring we render in strips, if required. RenderInStrips = TRUE; if (!ExportRender(ExportRegion)) { // SMFIX - Make sure we reset the StripStart as it could stuff up further operations. m__StripStart = 0; return FALSE; } //SMFIX was calling AlterPaletteContents( lpPalette ); on a palette that it built here // Ask the filter if it requires a second pass export render. This might be used for // say preparing a mask for transparency or something. Used by the GIF filter for this // purpose. /* if (IsSecondPassRequired()) { WritePreSecondPass(); // Set up device context and render region for this export. // This will show a progress hourglass for the objects being rendered // This will now also write the data out to file via our ExportRenderNodes function if (!PrepareToExport(pSpread, RenderDepth, DPI, Selection)) { return FALSE; } // Export the data to the file esnuring we render in strips, if required. RenderInStrips = TRUE; if (!ExportRender(ExportRegion)) { return FALSE; } } */ if (!WritePostFrame()) { // SMFIX - Make sure we reset the StripStart as it could stuff up further operations. m__StripStart = 0; return FALSE; } // SMFIX - Make sure we reset the StripStart as it could stuff up further operations. m__StripStart = 0; #endif return TRUE; } /******************************************************************************************** > BOOL BaseBitmapFilter::DoExportBitmap(Operation* pOp, CCLexFile* pFile, PathName* pPath, KernelBitmap* pBitmap) Author: Neville_Humphrys (Xara Group Ltd) Created: 25/4/95 Inputs: Purpose: Exports the specified bitmap straight out to file with none of the rendering that DoExport does. Uses the virtual fns of the inherited class. Do not override unless really necessary. Returns: TRUE if worked, FALSE if failed. ********************************************************************************************/ BOOL BaseBitmapFilter::DoExportBitmap(Operation* pOp, CCLexFile* pFile, PathName* pPath, KernelBitmap* pBitmap) { #ifdef DO_EXPORT ERROR2IF(pBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmap null bitmap pointer specified"); // Note this pointer for later use pExportBitmap = pBitmap; // Note this ptr for use in JPEG export. JPEGExportOptions::SetKernelBitmap(pBitmap); // Get a pointer to the actual bitmap so that we can get some details from it. OILBitmap *pOilBitmap = pBitmap->ActualBitmap; ERROR2IF(pOilBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmap null oil bitmap pointer"); // Create a record of information about the export m_pExportOptions = CreateExportOptions(); if (m_pExportOptions == NULL) { return FALSE; } // Get the default settings GetBitmapExportOptions()->RetrieveDefaults(); // Specify to the user what the export options for depth etc are going to be GetBitmapExportOptions()->SetSelectionType(ABITMAP); // Get the details from the specified bitmap BitmapInfo BmInfo; pOilBitmap->GetInfo(&BmInfo); GetBitmapExportOptions()->SetDepth(BmInfo.PixelDepth); // get the bitmaps bpp // Should really save the dpi when we load the file itself rather than doing // all this conversion with possible rounding errors. // Use the original size that has been calculated in the info header UINT32 PixWidth = BmInfo.PixelWidth; // UINT32 PixHeight = BmInfo.PixelHeight; MILLIPOINT RecWidth = BmInfo.RecommendedWidth; // MILLIPOINT RecHeight = BmInfo.RecommendedHeight; if (PixWidth > 0) { GetBitmapExportOptions()->SetDPI((PixWidth * 72000.0)/(double)RecWidth); } // WEBSTER - markn 5/2/97 // If the bitmap has a transparent colour index, store it in the options object // -1 means no transparent colour INT32 TransIndex = -1; if (!pBitmap->GetTransparencyIndex(&TransIndex)) TransIndex = -1; GetBitmapExportOptions()->SetTransparencyIndex(TransIndex); BOOL ok = TRUE; /* It used to call the export options dlg here - but why bother just export as is BOOL ok = GetExportOptions(GetBitmapExportOptions()); if (!ok) { delete m_pExportOptions; m_pExportOptions = 0; Error::SetError(_R(IDN_USER_CANCELLED),0); // Expects error set on cancel return FALSE; // if cancelled } if (GetBitmapExportOptions()->HasTempFile()) { // the export options preview dialog has produced a temp file, so just rename that // get the temp file name PathName TempPath = GetBitmapExportOptions()->GetPathName(); String_256 FinalName = pPath->GetPath(); String_256 TempName = TempPath.GetPath(); if (pFile->isOpen()) pFile->close(); // delete the empty file, if one was created FileUtil::DeleteFile(pPath); // try to rename the file if (_trename(TempName, FinalName) != 0) ok = FALSE; else ok = TRUE; } else */ { // Used to open the file up before starting DoExport. But this meant a cancel on the export // options dialog had filled the file, if it was already present. So now up up here if // not open already. In the PreviewBitmap case the file will already be open. if (!pFile->isOpen()) { if (pFile->IsKindOf(CC_RUNTIME_CLASS(CCDiskFile))) { ok = OpenExportFile((CCDiskFile*) pFile, pPath); if (!ok) return FALSE; } else { TRACEUSER( "JustinF", _T("Tried to open non-CCDiskFile in BaseBitmapFilter::DoExportBitmap\n") ); return FALSE; } } // Make a note of the Disk file we are to use OutputFile = pFile; // We do not use an export region so specify null. ExportRegion = NULL; // Actually write to the file, showing progress hourglass as we go ok = WriteBitmapToFile(pBitmap, GetBitmapExportOptions()->GetDPI()); if (ok) WriteFileEnd(); } // All done - deallocate dynamic objects, stop the progress display/hourglass // and return success. (Also closes file). CleanUpAfterExport(); // we created these here so we should delete them delete m_pExportOptions; m_pExportOptions = NULL; return ok; #else return FALSE; #endif } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::DoExportBitmaps(Operation* pOp, CCLexFile* pFile, PathName* pPath, BitmapExportParam* pParam) Author: Gerry_Iles (Xara Group Ltd) Created: 11/6/96 Inputs: Purpose: Exports the bitmaps specified by the BitmapExportParam object to a multi- image capable filter. It works creating a special document containing a single NodeBitmap It then sets this document to use each bitmap in turn and calls DoExport to actually export it. Returns: TRUE if worked, FALSE if failed. ********************************************************************************************/ BOOL BaseBitmapFilter::DoExportBitmaps(Operation *pOp, CCLexFile* pFile, PathName* pPath, BitmapExportParam* pParam) { #ifdef DO_EXPORT ERROR2IF(pOp == NULL || pFile == NULL || pPath == NULL, FALSE,"NULL Parameters"); ERROR2IF(pParam == NULL,FALSE,"BaseBitmapFilter::DoExportBitmaps null BitmapExportParam specified"); // Create an object so we can ask the user for some options if (m_pExportOptions) delete m_pExportOptions; m_pExportOptions = CreateExportOptions(); if (m_pExportOptions == NULL) return FALSE; // Get the first bitmap pointer KernelBitmap* pBitmap = pParam->GetBitmap(0); ERROR2IF(pBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmaps has no bitmaps to export"); pExportBitmap = pBitmap; // Get a pointer to the actual bitmap so that we can get some details from it. OILBitmap *pOilBitmap = pBitmap->ActualBitmap; ERROR2IF(pOilBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmaps null oil bitmap pointer"); // Specify to the user what the export options for depth etc are going to be GetBitmapExportOptions()->SetSelectionType(SOMEBITMAPS); GetBitmapExportOptions()->SetBitmapExportParam(pParam); // Get the defaults from the first bitmap BitmapInfo BmInfo; pOilBitmap->GetInfo(&BmInfo); GetBitmapExportOptions()->SetDepth(BmInfo.PixelDepth); // get the bitmaps bpp // Calculate the millipoint size from the pixel size assuming 96 dpi double DPI = 96.0; MILLIPOINT RecWidth = (MILLIPOINT) ((((double)BmInfo.PixelWidth * 72000.0) / DPI) + 0.5); MILLIPOINT RecHeight = (MILLIPOINT) ((((double)BmInfo.PixelHeight * 72000.0) / DPI) + 0.5); // Create a Coord for GetExportOptions GetBitmapExportOptions()->SetOutputSize(RecWidth, RecHeight); BOOL ok = GetExportOptions(GetBitmapExportOptions()); if (!ok) { delete m_pExportOptions; m_pExportOptions = NULL; Error::SetError(_R(IDN_USER_CANCELLED),0); // Expects error set on cancel return FALSE; // if cancelled } // Used to open the file up before starting DoExport. But this meant a cancel on the export // options dialog had filled the file, if it was already present. So now up up here if // not open already. In the PreviewBitmap case the file will already be open. if (!pFile->isOpen()) { if (pFile->IsKindOf(CC_RUNTIME_CLASS(CCDiskFile))) { ok = OpenExportFile((CCDiskFile*) pFile, pPath); if (!ok) return FALSE; } else { TRACEUSER( "JustinF", _T("Tried to open non-CCDiskFile in BaseBitmapFilter::DoExportBitmaps\n") ); return FALSE; } } // Make a note of the Disk file we are to use OutputFile = pFile; // Make sure the Region pointer is NULL for the time being ExportRegion = NULL; // TODO: Rampant change to Selection GetBitmapExportOptions()->SetSelectionType(DRAWING); // Output the file header if (!WriteFileHeader()) { CleanUpAfterExport(); return(FALSE); } // Remember the current document as we are just about to use a new document and // then delete it. Of course, systems like the bitmap system may just decide to // change current document just to screw things up. Put back before the end as the // EndOp will broadcast a message causing controls to update which require current // document to get the units list correctly. Document *pOldCurrent = Document::GetCurrent(); // Create a document for the export BitmapExportDocument* pDoc = new BitmapExportDocument; if (pDoc != NULL) { if (!pDoc->Init(pBitmap, DocRect(0, 0, GetBitmapExportOptions()->GetOutputSize().x, GetBitmapExportOptions()->GetOutputSize().y))) { TRACEUSER( "Gerry", _T("BitmapExportDocument::Init() failed\n") ); delete pDoc; pDoc = NULL; CleanUpAfterExport(); if (pOldCurrent != NULL) pOldCurrent->SetCurrent(); return(FALSE); } // Get pointer to the spread to export. PORTNOTE("spread", "Multi-spread warning!") pSpread = GetFirstSpread(pDoc); UINT32 BitmapCount = pParam->GetBitmapCount(); for (UINT32 Index = 0; ok && (Index < BitmapCount); Index++) { // Get the bitmap pointer pBitmap = pParam->GetBitmap(Index); // We have to render the bitmap so... // Update the BitmapExportDocument pDoc->SetBitmap(pBitmap); // Export the document // If it fails then break out of the image loop ok = DoExportDoc( pOp, pFile, pPath, pDoc, GetRenderDepth(), GetBitmapExportOptions()->GetDPI(), GetBitmapExportOptions()->GetSelectionType()); if (ExportRegion != NULL) { delete ExportRegion; ExportRegion = NULL; } if (pOptimisedPalette != NULL) { CCFree( pOptimisedPalette ); pOptimisedPalette = NULL; } } delete pDoc; pDoc = NULL; } // Write any end of file stuff if (ok) ok = WriteFileEnd(); // All done - deallocate dynamic objects, stop the progress display/hourglass // and return success. (Also closes file). CleanUpAfterExport(); // Ensure that we return CurrentDoc to its original value // Leave QuickShape tool with item selected before exporting animated gif from bitmap // gallery. Convert/Unit system blows up as using current doc! if (pOldCurrent != NULL) pOldCurrent->SetCurrent(); return ok; #endif return FALSE; } /******************************************************************************************** > BOOL BaseBitmapFilter::SetUpExportOptions(BitmapExportOptions **ppExportOptions, BOOL OnlyDefaults = FALSE) Author: Stefan_Stoykov (Xara Group Ltd) Created: 12/5/97 Inputs: Outputs: ppExportOptions - pointer, where a pointer to the export options object will be returned Purpose: Displays the export options dialog for this bitmap filter. This allows export options to be obtained by somebody else then the filter Returns: TRUE if worked, FALSE if failed. NB. SMFIX sjk this function will if you pass it a NULL ptr new the correct options for the filter for the calling function. This is great. However in this case the caller function has responsibility to delete this export object when they are finished with it. They receive the export object through the static member variable BmapPrevDlg::m_pExportOptions which is a ptr to the base class BitmapExportOptions, rather than just filling in the users structure, since if the graphic type has changed the users class will have been deleted and the export object could be a different class derived from BitmapExportOptions. ********************************************************************************************/ BOOL BaseBitmapFilter::SetUpExportOptions(BitmapExportOptions **ppExportOptions, BOOL OnlyDefaults) { ERROR2IF(ppExportOptions == NULL, FALSE,"BaseBitmapFilter::Can't Set up export options"); Document *pDoc = Document::GetCurrent(); // Get pointer to the spread to export. PORTNOTE("spread", "Multi-spread warning!") pSpread = GetFirstSpread(pDoc); ERROR2IF(pSpread == NULL, FALSE,"BaseCamelotFilter::DoExport no spread to export"); // We must now check if there is a selection present so that we can set up whether the // user gets the choice of exporting the selection, drawing or spread if there is a // selection present OR just a choice between the spread or drawing if no selection is // present. // If have a caret selected in a text story then the selection will be almost zero so trap // this case as well. DocRect ClipRect = GetApplication()->FindSelection()->GetBoundingRect(TRUE); SelectionType Selection = DRAWING; if ( ClipRect.IsEmpty() || ClipRect.Width() < MinExportSize || ClipRect.Height() < MinExportSize ) Selection = DRAWING; // no selection present, so choose drawing by default else Selection = SELECTION; // selection present, so choose this by default if (Selection == DRAWING) { // Work out the size of the rectangle encompassing the drawing (visible layers only) ClipRect = GetSizeOfDrawing(pSpread); // Check that that cliprect is ok, if not then set the spread as the export type if ( ClipRect.IsEmpty() || ClipRect.Width() < MinExportSize || ClipRect.Height() < MinExportSize ) Selection = SPREAD; } // If there is no selection then warn the user that exporting the current spread may // take a lot of disc space, but only if this is not a Preview Bitmap. if ((!IsPreviewBitmap) && (Selection == SPREAD)) { // Warn the user that there is no selection = large export ErrorInfo Info; Info.ErrorMsg = _R(IDT_BMPEXP_NOSELECTION); Info.Button[0] = _R(IDB_EXPQUERY_EXPORT); Info.Button[1] = _R(IDB_EXPQUERY_DONTEXPORT); if ((ResourceID)AskQuestion(&Info) == _R(IDB_EXPQUERY_DONTEXPORT)) { Error::SetError(_R(IDN_USER_CANCELLED),0); // Expects error set on cancel return FALSE; // if cancelled } } // Create a record of information about the export *ppExportOptions = CreateExportOptions(); if (*ppExportOptions == NULL) { return FALSE; } (*ppExportOptions)->RetrieveDefaults(); (*ppExportOptions)->SetSelectionType(Selection); // check whether only the defaults are needed if (OnlyDefaults) return TRUE; // get the user options for depth etc here BOOL ok = GetExportOptions( *ppExportOptions ); // remember this ptr and make it externally available // dont do this any more the above call brings up the export dlg and sets the BmapPrevDlg::m_pExportOptions // even when the user has messed around with them //BmapPrevDlg::m_pExportOptions = *ppExportOptions; // so rather the *ppExportOptions should reflect the state that the dlg left them in if (BmapPrevDlg::m_pExportOptions) *ppExportOptions = BmapPrevDlg::m_pExportOptions; if (!ok) { if (*ppExportOptions != NULL) { delete *ppExportOptions; *ppExportOptions = NULL; } Error::SetError(_R(IDN_USER_CANCELLED),0); // Expects error set on cancel BmapPrevDlg::m_pExportOptions = NULL; // we have no export options return FALSE; // if cancelled } return TRUE; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::DoExportWithOptions(Operation* pOp, CCLexFile* pFile, PathName* pPath, Document* pDoc, BitmapExportOptions *pOptions) Author: Stefan_Stoykov (Xara Group Ltd) Created: 12/5/97 Inputs: pOp - the operation that started the export off pFile - the file to put the exported data into pPath - the pathname of the file to be exported to pDoc - the document to export pOptions - the bitmap export options to use when exporting. The options are deleted after the export, so if you want to keep them make a copy first. Purpose: Exports the document by using the export options passed as parameter, rather then invoking an options dialog box to obtain them. Returns: TRUE if worked, FALSE if failed. ********************************************************************************************/ BOOL BaseBitmapFilter::DoExportWithOptions(Operation* pOp, CCLexFile* pFile, PathName* pPath, Document* pDoc, BitmapExportOptions *pOptions, DocRect *pRect) { ERROR2IF(pOp == NULL, FALSE,"BaseBitmapFilter::DoExport no export operation"); ERROR2IF(pFile == NULL, FALSE,"BaseBitmapFilter::DoExport no file to export to"); ERROR2IF(pPath == NULL, FALSE,"BaseBitmapFilter::DoExport no export pathname"); ERROR2IF(pDoc == NULL, FALSE,"BaseBitmapFilter::DoExport no document to export"); // Have any valid export options been passed in? if (pOptions == NULL) { // Create a record of information about the export. SetUpExportOptions(&m_pExportOptions, TRUE); if (m_pExportOptions == NULL) return FALSE; } else { // Copy the existing export options. //m_pExportOptions = pOptions->MakeCopy (); m_pExportOptions = pOptions; // rather point at the options passed in } // set up the pSpread PORTNOTE("spread", "Multi-spread warning!") pSpread = GetFirstSpread(pDoc); // deal with no selection SelRange* pSelection = GetApplication()->FindSelection(); // deal with exporting no selection as the drawing if (pRect == NULL && pSelection->Count() == 0 && (m_pExportOptions->GetSelectionType() == SELECTION)) m_pExportOptions->SetSelectionType(DRAWING); if (pRect != NULL) // Force the cliping rect for the image to be the one passed in // and not just defined by the selection! sjk { ClipRect = *pRect; } else { // reassign the clipping rectangle to the selection's bounding rect SetUpClippingRectangleForExport(pSpread, m_pExportOptions->GetSelectionType()); // Set the page limits to drawing if thats whats requested if (pSpread && m_pExportOptions->IsClipToPage() ) { Page *pPage = pSpread->FindFirstPageInSpread(); if (pPage) ClipRect = pPage->GetPageRect(); } // to use SJK's new fiddle the rect to maintain the antialiasing // as seen on screen call the function bellow // If you want it to work like it did in CX2 comment the line out if( m_pExportOptions->GetAntiAliasing() == MAINTAIN_SCREEN_AA ) PixelAlignedFiddle(&ClipRect); } BOOL ok = TRUE; // Always export the whole thing into one composite file ok = DoExportHelper(pOp, pFile, pPath, pDoc); if (!IsPreviewBitmap && m_pExportOptions->CanExportSeparateLayers()) { // We need to export each layer as a separate file Layer* pLayer = pSpread->FindFirstLayer(); while (ok && pLayer!=NULL) { if (pLayer->IsVisible() && !pLayer->IsGuide() && pLayer->HasLayerGotRenderableChildren() ) { SetSoleLayer(pLayer); PathName pathLayer = pLayer->MakeExportLayerName(*pPath); CCLexFile* pLayerFile = new CCDiskFile(pathLayer, ios::in | ios::out | ios::binary | ios::trunc); if (ok) ok = DoExportHelper(pOp, pLayerFile, &pathLayer, pDoc); delete pLayerFile; SetSoleLayer(NULL); } pLayer = pLayer->FindNextLayer(); } } // Delete the newly created export options ONLY if we did create them if (pOptions == NULL) { delete m_pExportOptions; m_pExportOptions = NULL; } // Restore the file. OutputFile = pFile; return ok; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::DoExportWithOptions(Operation* pOp, CCLexFile* pFile, PathName* pPath, Document* pDoc) Author: Phil_Martin (Xara Group Ltd) (from Stefan) Created: 24/03/2004 Inputs: pOp - the operation that started the export off pFile - the file to put the exported data into pPath - the pathname of the file to be exported to pDoc - the document to export Purpose: Exports the document by using the export options passed as parameter, rather then invoking an options dialog box to obtain them. Returns: TRUE if worked, FALSE if failed. ********************************************************************************************/ BOOL BaseBitmapFilter::DoExportHelper(Operation* pOp, CCLexFile* pFile, PathName* pPath, Document* pDoc) { // Used to open the file up before starting DoExport. But this meant a cancel on the export // options dialog had filled the file, if it was already present. So now up up here if // not open already. In the PreviewBitmap case the file will already be open. if ( !pFile->isOpen() && pFile->IsKindOf ( CC_RUNTIME_CLASS ( CCDiskFile ) ) && !OpenExportFile ( static_cast ( pFile ), pPath) ) { return FALSE; } WrittenHeader = 0; SetDepthToRender(32); // set the palette type which might get changed during the preview if (m_pExportOptions->IS_KIND_OF(BMPExportOptions)) { PaletteType = ((BMPExportOptions *)m_pExportOptions)->GetPalette() ? 1 : 0; // 1 for an optimised palette BMPFilter::SetDefaultExportDPI(m_pExportOptions->GetDPI()); BMPFilter::SetDefaultExportDepth(m_pExportOptions->GetDepth()); PORTNOTE("filter", "Removed use fo GIFFilter") #ifndef EXCLUDE_FROM_XARALX // Need to set the dither for the accusoft filter here, otherwise the dither // changes by the user will not have any effect AccusoftFilters::SetDitherToUse(m_pExportOptions->GetDither()); #endif } else if (m_pExportOptions->IS_KIND_OF(MaskedFilterExportOptions)) { PaletteType = ((MaskedFilterExportOptions *)m_pExportOptions)->GetPalette() ? 1 : 0;// 1 for an optimised palette } // set the render depth, which might change during the preview switch (m_pExportOptions->GetFilterType()) { PORTNOTE("filter", "Removed use fo GIFFilter") #ifndef EXCLUDE_FROM_XARALX case TI_GIF: if (m_pExportOptions->GetDepth() > 8) m_pExportOptions->SetDepth(8); SetDepthToRender(m_pExportOptions->GetDepth()); break; #endif case JPEG: SetDepthToRender(24); break; default: SetDepthToRender(m_pExportOptions->GetDepth()); break; } //Mark Howitt, 24/10/97. Reset the FilterType variable as Importing uses this for something else! PORTNOTE("filter", "Removed use of AccusoftFilters") #if !defined(EXCLUDE_FROM_XARALX) && !defined(WEBSTER) // Andy Hills, 21-12-00 // Warning: bodge alert! // At this stage, AccusoftFilters::FilterType may contain a useful value. // E.g. 9 for TIFF_LZW. This means that AccusoftFilters can make a special // case for exporting TIFFs, and export using CTIFFWriter instead of // calling Snowbound. // For whatever reason, the following line of code replaced this value with // m_pExportOptions->m_FilterID, which since the rewrite of the export dlg // contains the value 0. // This bodge ensures that we don't overwrite AccusoftFilters::FilterType // with 0. if (m_pExportOptions->GetFilterType() != 0) AccusoftFilters::SetFilterType(m_pExportOptions->GetFilterType()); #endif // Make a note of the Disk file we are to use OutputFile = pFile; // Actually export the document BOOL ok = WriteFileHeader(); // Do we want to use the existing palette, or generate a new one? The // value of BmapPrevDlg::m_bUseExistingPalette determines whether or // not one is needed to be generated, so no need to use any switch // logic. if ( ok ) { ok = DoExportDoc( pOp, pFile, pPath, pDoc, GetRenderDepth (), m_pExportOptions->GetDPI (), m_pExportOptions->GetSelectionType (), BmapPrevDlg::m_bUseExistingPalette ); } ok &= WriteFileEnd(); // pOptimised memory freed here. CleanUpAfterExport(); return ok; } /******************************************************************************************** > BOOL BaseBitmapFilter::SetUpExportBitmapOptions(BitmapExportOptions **ppExportOptions, KernelBitmap *pBitmap, BOOL OnlyDefaults = FALSE) Author: Stefan_Stoykov (Xara Group Ltd) Created: 12/5/97 Inputs: Outputs: ppExportOptions - pointer, where a pointer to the export options object will be returned Purpose: Displays the export options dialog for this bitmap filter. This allows export options to be obtained by somebody else then the filter Returns: TRUE if worked, FALSE if failed. ********************************************************************************************/ BOOL BaseBitmapFilter::SetUpExportBitmapOptions(BitmapExportOptions **ppExportOptions, KernelBitmap *pBitmap, BOOL OnlyDefaults) { #ifdef DO_EXPORT ERROR2IF(pBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmap null bitmap pointer specified"); // Note this pointer for later use pExportBitmap = pBitmap; // Note this ptr for use in JPEG export. JPEGExportOptions::SetKernelBitmap(pBitmap); // Get a pointer to the actual bitmap so that we can get some details from it. OILBitmap *pOilBitmap = pBitmap->ActualBitmap; ERROR2IF(pOilBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmap null oil bitmap pointer"); // Create a record of information about the export *ppExportOptions = CreateExportOptions(); if (*ppExportOptions == NULL) { return FALSE; } // Get the default settings (*ppExportOptions)->RetrieveDefaults(); // Specify to the user what the export options for depth etc are going to be (*ppExportOptions)->SetSelectionType(ABITMAP); // Get the details from the specified bitmap BitmapInfo BmInfo; pOilBitmap->GetInfo(&BmInfo); (*ppExportOptions)->SetDepth(BmInfo.PixelDepth); // get the bitmaps bpp // Should really save the dpi when we load the file itself rather than doing // all this conversion with possible rounding errors. // Use the original size that has been calculated in the info header UINT32 PixWidth = BmInfo.PixelWidth; // UINT32 PixHeight = BmInfo.PixelHeight; MILLIPOINT RecWidth = BmInfo.RecommendedWidth; // MILLIPOINT RecHeight = BmInfo.RecommendedHeight; if (PixWidth > 0) { (*ppExportOptions)->SetDPI((PixWidth * 72000.0)/(double)RecWidth); } // WEBSTER - markn 5/2/97 // If the bitmap has a transparent colour index, store it in the options object // -1 means no transparent colour INT32 TransIndex = -1; if (!pBitmap->GetTransparencyIndex(&TransIndex)) TransIndex = -1; (*ppExportOptions)->SetTransparencyIndex(TransIndex); // check whether only the defaults are needed if (OnlyDefaults) return TRUE; BOOL ok = GetExportOptions(*ppExportOptions); if (!ok) { if (*ppExportOptions != NULL) { delete *ppExportOptions; *ppExportOptions = NULL; } Error::SetError(_R(IDN_USER_CANCELLED),0); // Expects error set on cancel return FALSE; // if cancelled } return ok; #else return FALSE; #endif } /******************************************************************************************** > BOOL BaseBitmapFilter::DoExportBitmapWithOptions(Operation* pOp, CCLexFile* pFile, PathName* pPath, KernelBitmap* pBitmap, BitmapExportOptions *pOptions) Author: Stefan_Stoykov (Xara Group Ltd) Created: 25/7/97 Inputs: Purpose: Exports the specified bitmap straight out to file with none of the rendering that DoExport does. Uses the virtual fns of the inherited class. Do not override unless really necessary. Similar to DoExportBitmap in the base class, but uses the passed options, rather then invoking a dialog to get ones. Returns: TRUE if worked, FALSE if failed. ********************************************************************************************/ BOOL BaseBitmapFilter::DoExportBitmapWithOptions(Operation* pOp, CCLexFile* pFile, PathName* pPath, KernelBitmap* pBitmap, BitmapExportOptions *pOptions) { #ifdef DO_EXPORT ERROR2IF(pBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmap null bitmap pointer specified"); if (pOptions == NULL) { // Create a record of information about the export SetUpExportBitmapOptions(&pOptions, pBitmap, TRUE); if (pOptions == NULL) return FALSE; } // remember the old export options BitmapExportOptions *pOldOptions = GetBitmapExportOptions(); if (pOldOptions != NULL) pOldOptions->RetrieveDefaults(); // set the new ones SetExportOptions(pOptions); pOptions->SetAsDefaults(); // Make a note of the Disk file we are to use OutputFile = pFile; // Note this pointer for later use pExportBitmap = pBitmap; // Note this ptr for use in JPEG export. JPEGExportOptions::SetKernelBitmap(pBitmap); // Get a pointer to the actual bitmap so that we can get some details from it. OILBitmap *pOilBitmap = pBitmap->ActualBitmap; ERROR2IF(pOilBitmap == NULL,FALSE,"BaseBitmapFilter::DoExportBitmap null oil bitmap pointer"); // Get the details from the specified bitmap BitmapInfo BmInfo; pOilBitmap->GetInfo(&BmInfo); GetBitmapExportOptions()->SetDepth(BmInfo.PixelDepth); // get the bitmaps bpp // Should really save the dpi when we load the file itself rather than doing // all this conversion with possible rounding errors. // Use the original size that has been calculated in the info header UINT32 PixWidth = BmInfo.PixelWidth; // UINT32 PixHeight = BmInfo.PixelHeight; MILLIPOINT RecWidth = BmInfo.RecommendedWidth; // MILLIPOINT RecHeight = BmInfo.RecommendedHeight; if (PixWidth > 0) { //DPI = Mul32Div32( PixWidth, 72000, RecWidth ); GetBitmapExportOptions()->SetDPI((PixWidth * 72000.0)/(double)RecWidth); } BOOL ok = TRUE; // Used to open the file up before starting DoExport. But this meant a cancel on the export // options dialog had filled the file, if it was already present. So now up up here if // not open already. In the PreviewBitmap case the file will already be open. if (!pFile->isOpen()) { if (pFile->IsKindOf(CC_RUNTIME_CLASS(CCDiskFile))) { ok = OpenExportFile((CCDiskFile*) pFile, pPath); if (!ok) return FALSE; } else { TRACEUSER( "JustinF", _T("Tried to open non-CCDiskFile in BaseBitmapFilter::DoExportBitmap\n") ); return FALSE; } } // Make a note of the Disk file we are to use OutputFile = pFile; // We do not use an export region so specify null. ExportRegion = NULL; // Actually write to the file, showing progress hourglass as we go ok = WriteBitmapToFile(pBitmap, GetBitmapExportOptions()->GetDPI()); if (ok) WriteFileEnd(); // All done - deallocate dynamic objects, stop the progress display/hourglass // and return success. (Also closes file). CleanUpAfterExport(); // restore the old export options if (pOldOptions != NULL) { SetExportOptions(pOldOptions); pOldOptions->SetAsDefaults(); } // restore the file OutputFile = pFile; return ok; #else return FALSE; #endif } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::SaveExportBitmapsToFile(CCLexFile* pFile, PathName* pPath, BitmapExportParam* pParam, BOOL DontShowFileName = FALSE) Author: Neville_Humphrys (Xara Group Ltd) Created: 1/5/97 Inputs: pDiskFile - the file to put the exported data into pPath - the pathname of the file to be exported to pParam - the data to use when exporting the bitmaps DontShowFileName - if set to true then don't show the filename in the progress string Purpose: Exports the bitmaps specified by the BitmapExportParam object to a multi- image capable filter. Each of the bitmaps will be saved to file using the settings specified. This is the baseclass version and so is usually overriden Returns: TRUE if worked, FALSE if failed. ********************************************************************************************/ BOOL BaseBitmapFilter::SaveExportBitmapsToFile(CCLexFile* pFile, PathName* pPath, BitmapExportParam* pParam, BOOL DontShowFileName) { #ifdef DO_EXPORT ERROR2IF(pFile == NULL || pPath == NULL, FALSE,"NULL Parameters"); ERROR2IF(pParam == NULL,FALSE,"TI_GIFFilter::DoExportBitmaps null BitmapExportParam specified"); ERROR3("BaseBitmapFilter::SaveExportBitmapsToFile calling baseclass version!"); return TRUE; #endif return FALSE; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::ExportRenderNodes(RenderRegion *pRegion, ExportDC *pDC, BOOL VisibleLayersOnly = FALSE, BOOL CheckSelected = FALSE, BOOL ShowProgress = TRUE) Author: Neville_Humphrys (Xara Group Ltd) Created: 12/5/95 Inputs: pRegion - the render region to export to. pDc - device context to use VisibleLayersOnly - use visible layers or not ShowProgress - TRUE then start up a progress bar or FALSE assume the caller has done it. Returns: TRUE if the export process completed successfully, FALSE if an error occured. Purpose: Actually export the nodes to the given render region showing a progress bar as we go. Assumes everything has been set up by ExportRender. Overrides the baseclass version so that we can render in strips. Ignores the setting of ShowProgress as we must be in charge of the progress bar in this version. SeeAlso: ExportRender ********************************************************************************************/ BOOL BaseBitmapFilter::ExportRenderNodes(RenderRegion *pRegion, ExportDC *pDC, BOOL VisibleLayersOnly, BOOL CheckSelected, BOOL ShowProgress) { #ifdef DO_EXPORT ERROR2IF(pRegion==NULL,FALSE,"BaseBitmapFilter::ExportRender null render region supplied"); // Set up the Accusoft variables used for its redenring loop and call back form of the // do next strip. This is just in case we are going to change from using the Bitmap // filter to using the Accusoft filters as we are saving in a format which the Bitmap // filters do not understand. //WEBSTER-Martin-03/01/97 PORTNOTE("ExportAccusoft", "Removed use fo Accusoft filters") #ifndef EXCLUDE_FROM_XARALX AccusoftFilters::SetRenderVariables(this, pRegion, pDC, VisibleLayersOnly, CheckSelected); #endif // Set the bad rendering flag to its default value BadExportRender = FALSE; BOOL ok = TRUE; DocRect rClipRect = pRegion->GetRegionRect(); BitmapExportOptions * pExportOptions = GetBitmapExportOptions(); BOOL DidASwap = FALSE; // Check our class variable to see if we should render in strips or not // We do this so that things like the GIF filters 1bpp masked rendering can turn the // rendering in strips off. Should be on by default. if (RenderInStrips) { OurNumNodes = GetNumNodes(); //UINT32 OurUpdateEvery = UpdateEvery; // We have a useful function in the GRenderBitmap class which tells us the number // of strips we are going to render with. GRenderBitmap *pGRenderBitmap = (GRenderBitmap*)pRegion; INT32 NumberOfStrips = pGRenderBitmap->GetNumBands(); if (NumberOfStrips <= 0) NumberOfStrips = 1; TRACEUSER( "Gerry", _T("Number of bands is %d\n"), NumberOfStrips); TRACEUSER( "Gerry", _T("Number of nodes is %d\n"), OurNumNodes); // We need the progress bar to just move up once rather than for every strip // plus include the number of lines in the export bitmap so that we can show // a progress bar for this part of the export. // First, get the size of the bitmap we are going to export INT32 HeightInPixels = pGRenderBitmap->GetFullRegionHeight(); TRACEUSER( "Gerry", _T("Full region height in pixels is %d\n"), HeightInPixels ); SizeOfExport = OurNumNodes * NumberOfStrips; SetNumNodes(SizeOfExport); BitmapExportOptions* pOptions = GetBitmapExportOptions(); // Start a progress update going // Extend it by the pixel height of the export String_64 ExportMessage(GetExportMsgID()); ExportMessage = GetExportProgressString(OutputFile, GetExportMsgID()); BeginSlowJob(200, FALSE, &ExportMessage); TRACEUSER( "Gerry", _T("Size of progress bar = %d\n"), SizeOfExport + HeightInPixels ); // Reset this back to zero so that when we update the progress bar in WriteToFile // we can work out the current point reached on the progress bar SizeOfExport = 0; ProgressOffset = 0; m__StripStart = 0; // Find out which way we want to render by asking the filters BOOL BottomToTop = GetRenderBottomToTop(); pGRenderBitmap->SetRenderBottomToTop(BottomToTop); // SMFIX this is where we will generate a new optimal palette if we need to BOOL CreatingPalette = !pExportOptions->IsPaletteValid() && pExportOptions->GetDepth() <= 8; if (CreatingPalette) { if (!pExportOptions->CreatePaletteOptimiser()) { // we didn't create an optimiser as we already have a good one // use it to create the palette NOW! without the stats gathering part as are stats are still valid pExportOptions->CreateValidPalette(); // let the optimiser fill in the palette in the export options AlterPaletteContents(pExportOptions->GetLogicalPalette()); CreatingPalette = FALSE; } } else if(pExportOptions->GetDepth() <= 8) { // this call sets this palette in the lower reaches of the code from the palette held in the export options AlterPaletteContents(pExportOptions->GetLogicalPalette()); } if (pExportOptions->IsCMYK()) { // If we are doing a CMYK export then we need to do a really cunning 4-pass render TRACEUSER( "Gerry", _T("BaseBitmapFilter::ExportRenderNodes starting CMYK export\n") ); // We need to save away the current ColourPlate and restore it afterwards // This may be problematic as the render region has already been created at this point // and also, the view will redraw when the ColourPlate is changed View* pView = pRegion->GetRenderView(); ColourPlate* pCurPlate = pView->GetColourPlate(); if (pCurPlate) { pCurPlate = new ColourPlate(*pCurPlate); // Make a copy of it } else { pCurPlate = new ColourPlate; // Make a default pCurPlate->SetMonochrome(NULL, FALSE); // Set to non-mono } // Get the first strip ready for action ok = pRegion->SetFirstBand(); if (!ok) { BadExportRender = TRUE; // flag that something has gone wrong EndWriteToFile(); EndSlowJob(); return FALSE; } UINT32 nBandsCompleted = 0; // Now render all the other strips, if there are any, until we have completed // the entire region. do { // Make sure this gets set back to the correct value before doing any rendering pGRenderBitmap->SetDoBitmapConversion(TRUE); // Set up a destination bitmap of the strip size at 32 bpp // We must somehow get the size of the bitmap here before // it has actually been allocated in StartRender WinRect BitmapRect = ((GRenderRegion*)pGRenderBitmap)->CalculateWinRect(pGRenderBitmap->GetClipRect()); TRACEUSER( "Gerry", _T("CMYK bitmap is (%d, %d)\n"), BitmapRect.GetWidth(), BitmapRect.GetHeight() ); LPBYTE pCMYKBits = NULL; LPBITMAPINFO pCMYKInfo = AllocDIB(BitmapRect.GetWidth(), BitmapRect.GetHeight(), 32, &pCMYKBits); memset(pCMYKBits, 0, BitmapRect.GetWidth() * BitmapRect.GetHeight() * sizeof(DWORD)); // Loop around the four plates for (UINT32 PlateType = COLOURPLATE_CYAN; PlateType <= COLOURPLATE_KEY; PlateType += 1) { // Set the relevant ColourPlate on the View ColourPlate* pPlate = new ColourPlate((ColourPlateType)PlateType, TRUE, FALSE); pView->SetColourPlate(pPlate, FALSE); delete pPlate; // This will cause a new ColourContext to be got from the view pRegion->ResetColourContext(); // Call the base class version to do the actual node exporting // We have started the progress bar so tell it not to ok = Filter::ExportRenderNodes(pRegion, pDC, VisibleLayersOnly, CheckSelected, FALSE); // If a problem happened then get out quick. // Assume function has stopped the rendering. if (!ok) { if (pView) { pView->SetColourPlate(pCurPlate); delete pCurPlate; } BadExportRender = TRUE; // flag that something has gone wrong EndWriteToFile(); EndSlowJob(); return FALSE; } LPBITMAPINFO pRenderInfo = NULL; LPBYTE pRenderData = NULL; pGRenderBitmap->GetBitmapData(&pRenderInfo, &pRenderData, FALSE); TRACEUSER( "Gerry", _T("Strip bitmap for plate %d is (%d, %d)\n"), PlateType, pRenderInfo->bmiHeader.biWidth, pRenderInfo->bmiHeader.biHeight); BYTE* pSrcBits = pRenderData; UINT32 NumPixels = pRenderInfo->bmiHeader.biWidth * pRenderInfo->bmiHeader.biHeight; BYTE* pDestBits = ((BYTE*)pCMYKBits) + PlateType - COLOURPLATE_CYAN; // Pointer arithmetic for (UINT32 Pixel = 0; Pixel < NumPixels; Pixel++) { *pDestBits = (255 - pSrcBits[0]) * (255 - pSrcBits[3]) / 255; pDestBits += 4; pSrcBits += 4; } } // Update our size of export variable SizeOfExport += OurNumNodes; // Update the filters stored progress offset value ProgressOffset += OurNumNodes; TRACEUSER( "Gerry", _T("BaseBitmapFilter::RenderNextStrip ProgressOffset = %d\n"), ProgressOffset); // Now we need to get WriteFrame to output the composited bitmap // The easiest way to do this will be to replace the bitmap in the render region // with the composited one and just call WriteFrame as normal DWORD* pSrcBits = (DWORD*)pGRenderBitmap->Get32BitRGBQuadData(); UINT32 NumPixels = pGRenderBitmap->GetSizeOfRGBQuadData(); memcpy(pSrcBits, pCMYKBits, NumPixels * sizeof(DWORD)); // We need to stop GetBitmapData from doing another conversion when reading the CMYK data pGRenderBitmap->SetDoBitmapConversion(FALSE); // Free the temp bitmap FreeDIB(pCMYKInfo, pCMYKBits); // Save that data out to file, this should update SizeOfExport with the // current strip size // Note: it will also render all the remaining strips ok = WriteFrame(); // If a problem happened then get out quick. if (!ok) { if (pView) { pView->SetColourPlate(pCurPlate); delete pCurPlate; } BadExportRender = TRUE; // flag that something has gone wrong EndWriteToFile(); EndSlowJob(); return FALSE; } // Advance the progress bar UINT32 nProgress = UINT32((double(nBandsCompleted) / double(NumberOfStrips)) * 200.0); TRACEUSER( "Gerry", _T("nProgress = %d\n"), nProgress); if ( !ContinueSlowJob (nProgress) ) { // Error; close down and exit nicely. // Must set an error otherwise we will get the dreaded reporting error // when none set message. // If no error message ID set in this filter then use default // Andy, 13-12-00 // N.B. At the moment, things go pear-shaped if we press ESC during export. // e.g. subsequent presses of 'preview' do not generate a preview. // However it wasn't exactly well behaved before, e.g. sometimes gave // internal error 'Failed to create an intermediate bitmap pointer!', or // access violated if the user clicked 'background transparency' after a // cancelled export. if (pView) { pView->SetColourPlate(pCurPlate); delete pCurPlate; } if ( StopExportMsgID == 0 ) Error::SetError ( _R(IDW_CANCELEXPORT) ); else Error::SetError ( StopExportMsgID ); pRegion->StopRender (); if ( ShowProgress ) EndSlowJob (); return FALSE; } nBandsCompleted ++; // Check if there are any more bands } while (pRegion->GetNextBand()); if (pView) { pView->SetColourPlate(pCurPlate); delete pCurPlate; } } else { 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 { TRACEUSER( "Gerry", _T("BaseBitmapFilter::ExportRenderNodes loop = %d\n"), loop); if (!CreatingPalette && pExportOptions->GetDepth() <= 8) { DidASwap = pExportOptions->SwapEditedColoursInLogicalPalette(); AlterPaletteContents(pExportOptions->GetLogicalPalette()); } // Get the first strip ready for action ok = pRegion->SetFirstBand(); if (!ok) { BadExportRender = TRUE; // flag that something has gone wrong EndWriteToFile(); EndSlowJob(); return FALSE; } UINT32 nBandsCompleted = 0; // Now render all the other strips, if there are any, until we have completed // the entire region. do { // Call the base class version to do the actual node exporting // We have started the progress bar so tell it not to ok = Filter::ExportRenderNodes(pRegion, pDC, VisibleLayersOnly, CheckSelected, FALSE); // If a problem happened then get out quick. // Assume function has stopped the rendering. if (!ok) { BadExportRender = TRUE; // flag that something has gone wrong EndWriteToFile(); EndSlowJob(); return FALSE; } if (!CreatingPalette) { // Update our size of export variable SizeOfExport += OurNumNodes; // Update the filters stored progress offset value ProgressOffset += OurNumNodes; TRACEUSER( "Gerry", _T("BaseBitmapFilter::RenderNextStrip ProgressOffset = %d\n"),ProgressOffset); } // Save that data out to file, this should update SizeOfExport with the // current strip size if (CreatingPalette) { // calc the stats for an optimised palette pExportOptions->GatherPaletteStats( ((GRenderRegion * )pRegion)->Get32BitRGBQuadData(), ((GRenderRegion * )pRegion)->GetSizeOfRGBQuadData()); } else ok = WriteFrame(); // If a problem happened then get out quick. if (!ok) { BadExportRender = TRUE; // flag that something has gone wrong EndWriteToFile(); EndSlowJob(); return FALSE; } // Advance the progress bar UINT32 nProgress; // if this image doesn't need a palette, scale the progress value to // the full length of the bar if (!CreatingPalette && loop==0) nProgress = UINT32((double(nBandsCompleted) / double(NumberOfStrips)) * 200.0); // otherwise, scale the progress value to half the length of the bar // (as this rendering loop will occur twice) else nProgress = UINT32((double(nBandsCompleted) / double(NumberOfStrips)) * 100.0 + double(loop)*100.0); TRACEUSER( "Gerry", _T("nProgress = %d\n"), nProgress); if ( !ContinueSlowJob (nProgress) ) { // Error; close down and exit nicely. // Must set an error otherwise we will get the dreaded reporting error // when none set message. // If no error message ID set in this filter then use default // Andy, 13-12-00 // N.B. At the moment, things go pear-shaped if we press ESC during export. // e.g. subsequent presses of 'preview' do not generate a preview. // However it wasn't exactly well behaved before, e.g. sometimes gave // internal error 'Failed to create an intermediate bitmap pointer!', or // access violated if the user clicked 'background transparency' after a // cancelled export. if ( StopExportMsgID == 0 ) Error::SetError ( _R(IDW_CANCELEXPORT) ); else Error::SetError ( StopExportMsgID ); pRegion->StopRender (); if ( ShowProgress ) EndSlowJob (); return FALSE; } nBandsCompleted ++; // Check if there are any more bands } while (pRegion->GetNextBand()); if (CreatingPalette) { CreatingPalette = FALSE; // let the optimiser fill in the palette in the export options pExportOptions->CreateValidPalette(); // set this as the palette being used in output dib AlterPaletteContents(pExportOptions->GetLogicalPalette()); // Reset the clip region to what it was when we started this pRegion->SetClipRect(rClipRect); } else break; // leave this for loop now } } if (DidASwap) { pOptions->SwapEditedColoursInLogicalPalette(); AlterPaletteContents(pOptions->GetLogicalPalette()); } // Close down progress display // Do it before ending as then the TI GIF filter can show a progress bar on // its possible masked rendering for transparency and export of the GIF data // which happens in the EndWriteToFile. EndSlowJob(); } else { // Call the base class version to do the actual node exporting // Use the pass in version to say whether we need to start the progress bar or not. // Assume that we are the GIF filter renderer and so do not try and output the data // at all. We will ensure as this might be dangerous. PORTNOTE("filter", "Removed use of GIFFilter") #ifndef EXCLUDE_FROM_XARALX ERROR3IF(!(this->IS_KIND_OF(TI_GIFFilter)) && !(this->IS_KIND_OF(PNGFilter)), "BaseBitmapFilter::ExportRenderNodes rendering in strips off"); #else ERROR3IF(!(this->IS_KIND_OF(PNGFilter)), "BaseBitmapFilter::ExportRenderNodes rendering in strips off"); #endif ok = Filter::ExportRenderNodes(pRegion, pDC, VisibleLayersOnly, CheckSelected, ShowProgress); // SMFIX optimise the palette in the no strip based manner BOOL CreatingPalette = !pExportOptions->IsPaletteValid(); if (CreatingPalette) { // create a palette optimiser (or retrieve a valid one) if (pExportOptions->CreatePaletteOptimiser()) { // we need to gather stats as we have made a virgin new optimiser pExportOptions->GatherPaletteStats( ((GRenderRegion * )pRegion)->Get32BitRGBQuadData(), ((GRenderRegion * )pRegion)->GetSizeOfRGBQuadData()); } // let the optimiser fill in the palette in the export options pExportOptions->CreateValidPalette(); // let the optimiser fill in the palette in the export options AlterPaletteContents(pExportOptions->GetLogicalPalette()); } /* // SMFIX if(pRegion->m_DoCompression) { BITMAPINFO* pBMPInfo = NULL; BYTE* pBMPData = NULL; ((GRenderBitmap*)pRegion)->GetBitmapData(&pBMPInfo,&pBMPData); ((GRenderBitmap*)pRegion)->GetDrawContext()->ConvertBitmap(&pBMPInfo->bmiHeader,pBMPData,&pBMPInfo->bmiHeader,pBMPData,0); }*/ } // return outcome to caller return ok; #else return FALSE; #endif } /******************************************************************************************** > BOOL BaseBitmapFilter::WriteToFile( BOOL AtEnd) Author: Andy_Pennell (Xara Group Ltd) Created: 22/8/94 Inputs: AtEnd is TRUE if this is the last chunk of the file, FALSE if not. Purpose: Writes out the bitmap to a file. Inherited classes override this to write in different file formats. AtEnd is ignored now and should always be set to TRUE. Returns: TRUE if worked, FALSE if failed. ********************************************************************************************/ BOOL BaseBitmapFilter::WriteToFile( BOOL AtEnd) { ENSURE(FALSE, "Base class bitmap filter WriteToFile called"); return FALSE; } /******************************************************************************************** > BOOL BaseBitmapFilter::EndWriteToFile( ) Author: Neville_Humphrys (Xara Group Ltd) Created: 12/5/95 Inputs: - Purpose: Cleans up after writing the bitmap data out to a file. Inherited classes override this to write in different file formats. Returns: TRUE if worked, FALSE if failed. ********************************************************************************************/ BOOL BaseBitmapFilter::EndWriteToFile( ) { ENSURE(FALSE, "Base class bitmap filter EndWriteToFile called"); return FALSE; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::WriteBitmapToFile(KernelBitmap* pKernelBitmap, double Dpi) Author: Neville_Humphrys (Xara Group Ltd) Created: 25/4/95 Inputs: Pointer to the bitmap to be exported. Returns: TRUE if worked, FALSE if errored. Purpose: Physically put the bitmap into the disk. Inherited classes override this to write in different file formats. SeeAlso: WriteDataToFile(); AccusoftFilters::WriteToFile; AccusoftFilters::WriteDataToFile; ********************************************************************************************/ BOOL BaseBitmapFilter::WriteBitmapToFile(KernelBitmap* pKernelBitmap, double Dpi) { ERROR3("Base class bitmap filter WriteBitmapToFile called"); return FALSE; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::WriteBitmapToFile(KernelBitmap* pKernelBitmap, BaseCamelotFilter *pFilter, CCLexFile *pFile, INT32 Compression) Author: Neville_Humphrys (Xara Group Ltd) Created: 20/6/96 Inputs: pKernelBitmap - Pointer to the bitmap to be exported. pFilter - Pointer to the BaseCamelot filter which provides progress functions pFile - Pointer to the CCFile class to use for export Compression - used to flag how much compression of the data is required. Returns: TRUE if worked, FALSE if errored. Purpose: Physically put the bitmap into the disk. Inherited classes override this to write in different file formats. This is used by the native/web format to output the actual bitmap data content of a bitmap definition record. The function can assume that the CCFile is open and ready for writing and must use the functions provided by pFilter to update the progress system. This is the baseclass version and hence needs overiding, hence the error. SeeAlso: BitmapListComponent::SaveBitmapDefinition; ********************************************************************************************/ BOOL BaseBitmapFilter::WriteBitmapToFile(KernelBitmap* pKernelBitmap, BaseCamelotFilter *pFilter, CCLexFile *pFile, INT32 Compression) { // Create a record of information about the export m_pExportOptions = CreateExportOptions(); if (GetBitmapExportOptions() == NULL) { return FALSE; } OutputFile = pFile; return TRUE; } /******************************************************************************************** > static DocRect BaseBitmapFilter::GetSizeOfDrawing(Spread *pSpread=NULL) Author: Neville_Humphrys (Xara Group Ltd) Created: 18/4/95 Inputs: pointer to the spread to use Purpose: Works out the size of the rectangle encompassing the drawing. Code also used to work out the pixel size in the bitmap export options dialog box. Added by Graham 11/4/97: If pSpread is NULL, we get the first spread of the current document to use Returns: Size of the rectangle encompassing the drawing. SeeAlso: BmpPrefsDlg::RecalculateSize; BaseBitmapFilter::DoExport; ********************************************************************************************/ DocRect BaseBitmapFilter::GetSizeOfDrawing(Spread *pSpread) { // Start out with an empty clip rect DocRect SpreadRect; SpreadRect.MakeEmpty(); //If we have not been passed a spread... if (pSpread == NULL) { //Then let's get the first spread of the current document Document* pdocCurrent=Document::GetCurrent(); ERROR2IF(pdocCurrent==NULL, DocRect(0,0,0,0), "BaseBitmapFilter - no current document"); //And finally the current spread PORTNOTE("spread", "Multi-spread warning!") pSpread=GetFirstSpread(pdocCurrent); ERROR2IF(pSpread==NULL, DocRect(0,0,0,0), "BaseBitmapFilter - no spread"); } // We need to take into account the fact that some layers may not be visible Layer* pLayer = pSpread->FindFirstLayer(); while (pLayer != NULL) { // We've got a layer so check to see if it is visible // Added 8/4/97 extra checks to see if we are the special layers // and so shouldn't be included in the bounding calulations if (pLayer->IncludeLayerInBoundingCalcs()) { // This one is visible, so union it in DocRect LayerRect = pLayer->GetBoundingRect(); SpreadRect = SpreadRect.Union(LayerRect); } // Get the next sibling layer pLayer = pLayer->FindNextLayer(); } // return the found rectangle to the caller. return SpreadRect; } /******************************************************************************************** > static DocRect BaseBitmapFilter::GetSizeOfSpread(Spread *pSpread) Author: Neville_Humphrys (Xara Group Ltd) Created: 18/4/95 Inputs: pointer to the spread to use Purpose: Works out the size of the rectangle encompassing the spread. Code also used to work out the pixel size in the bitmap export options dialog box. Returns: Size of the rectangle encompassing the spread. SeeAlso: BmpPrefsDlg::RecalculateSize; BaseBitmapFilter::PrepareToExport; ********************************************************************************************/ DocRect BaseBitmapFilter::GetSizeOfSpread(Spread *pSpread) { // Start out with an empty clip rect DocRect SpreadRect; SpreadRect.MakeEmpty(); if (pSpread == NULL) { ERROR3("BaseBitmapFilter::GetSizeOfSpread null spread"); return SpreadRect; } // build a rectangle out of all the pages in the selected spread Node *pPage = pSpread->FindFirstPageInSpread(); ERROR3IF(pPage == NULL, "Spread has no pages"); while (pPage) { if (pPage->GetRuntimeClass() == CC_RUNTIME_CLASS(Page) ) SpreadRect = SpreadRect.Union(( (Page*)pPage)->GetPageRect() ); pPage = pPage->FindNext(); } ERROR3IF(SpreadRect.IsEmpty(),"Current spread has no pages"); return SpreadRect; } /******************************************************************************************** > static BOOL BaseBitmapFilter::GetSizeOfBitmap(INT32 *PixelWidth, INT32 *PixelHeight) Author: Neville_Humphrys (Xara Group Ltd) Created: 25/4/95 Inputs: - Outputs: PixelWidth bitmap width in pixels PixelHeight bitmap height in pixels Purpose: Works out the size of the bitmap in the bitmap export options dialog box. Returns: True if completed ok. SeeAlso: BmpPrefsDlg::RecalculateSize; BaseBitmapFilter::PrepareToExport; ********************************************************************************************/ BOOL BaseBitmapFilter::GetSizeOfBitmap(INT32 *PixelWidth, INT32 *PixelHeight) { #ifdef DO_EXPORT ERROR2IF(pExportBitmap==NULL,FALSE,"BaseBitmapFilter::GetSizeOfBitmap no bitmap"); ERROR2IF(PixelWidth==NULL,FALSE,"BaseBitmapFilter::GetSizeOfBitmap no PixelWidth"); ERROR2IF(PixelHeight==NULL,FALSE,"BaseBitmapFilter::GetSizeOfBitmap no PixelHeight"); // Set return values in case of early exit *PixelWidth = 0; *PixelHeight = 0; // Get a pointer to the actual bitmap so that we can get some details from it. OILBitmap *pOilBitmap = pExportBitmap->ActualBitmap; ERROR3IF(pOilBitmap == NULL,"BaseBitmapFilter::GetSizeOfBitmap null oil bitmap pointer"); if (pOilBitmap) { BitmapInfo BmInfo; pOilBitmap->GetInfo(&BmInfo); *PixelWidth = BmInfo.PixelWidth; *PixelHeight = BmInfo.PixelHeight; } return TRUE; #else return FALSE; #endif } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::IsThisBppOk(UINT32 Bpp) Author: Neville_Humphrys (Xara Group Ltd) Created: 27/4/95 Inputs: Bpp or Colour depth. Returns: TRUE if this filter can cope with this colour depth, FALSE otherwise. Purpose: Check if this Bitmap filter can cope with saving at this Bpp/Colour depth. SeeAlso: OpMenuExport::DoWithParam; ********************************************************************************************/ BOOL BaseBitmapFilter::IsThisBppOk(UINT32 Bpp) { // Base class version so always return FALSE. return FALSE; } /******************************************************************************************** > virtual UINT32 BaseBitmapFilter::GetExportMsgID() Author: Neville_Humphrys (Xara Group Ltd) Created: 18/09/95 Returns: The id of the message to put on the progress display whilst exporting. Purpose: Used to get the message id to be used during export. Virtual, so that two stage exporters can change the message. SeeAlso: DoExport; ********************************************************************************************/ UINT32 BaseBitmapFilter::GetExportMsgID() { if (GeneratingOptimisedPalette()) return _R(IDS_GENOPTPALMSGID); // "Generating optimised palette..." else return Filter::GetExportMsgID(); } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::GenerateOptimisedPalette(Spread *pSpread, UINT32 Depth, double DPI, BOOL SnapToBrowserPalette, UINT32 NumColsInPalette = 0, BOOL UsePrimaryCols = TRUE) Author: Will_Cowling (Xara Group Ltd) Created: 30/5/96 Inputs: pSpread = ptr to spread Depth = The BPP of the bitmap DPI = the dpi of the bitmap NumColsInPalette = prefered number of cols in palette (0 = select maximum allowed) (only applies when Depth == 8) UsePrimaryCols = Put primary colours in palette (only applies when Depth == 8) SnapToBrowserPalette= TRUE if the palette should be snapped to the browser palette after generation Returns: TRUE if Palette generated ok Purpose: Generates an optimised palette to use during export SeeAlso: - ********************************************************************************************/ BOOL BaseBitmapFilter::GenerateOptimisedPalette(Spread *pSpread, UINT32 Depth, double DPI, BOOL SnapToBrowserPalette, UINT32 NumColsInPalette, BOOL UsePrimaryCols) { #ifdef DO_EXPORT if (Depth > 8) { pOptimisedPalette = NULL; return TRUE; } TRACEUSER( "Neville", _T("Trying to generate an optimised palette ...\n") ); WeAreGeneratingOptPalette = TRUE; // Don't use rendering matrix when exporting BMPs as it uses coordinates as is Matrix Identity; // Don't use view scale; set to 1 FIXED16 Scale(1); // Only use special 8bpp palette if the UsePrimaryColours flag is TRUE BOOL use8bpp = ((Depth == 8) && UsePrimaryCols); GRenderOptPalette* pPalRegion = new GRenderOptPalette(ClipRect, Identity, Scale, 32, DPI, use8bpp); if (pPalRegion) { // we need a View to Attach to, so that: // default Quality setting // CalcPixelWidth etc get called DocView *View = DocView::GetCurrent(); if (View) { // Attach to the right device. (note no DC) pPalRegion->AttachDevice(View, NULL, pSpread); } else ERROR2(FALSE,"BaseBitmapFilter::GenerateOptimisedPalette no current view"); RenderInStrips = TRUE; // Now do an export render pass, using the Palette Region if (ExportRender(pPalRegion)) { UINT32 MaxColours = 1U< MaxColours) NumColsInPalette = MaxColours; // All went ok, so extract the Optimised palette from the Region pOptimisedPalette = pPalRegion->GetOptimisedPalette(MaxColours, NumColsInPalette, GetNumReservedColours(), SnapToBrowserPalette); if (pOptimisedPalette) TRACEUSER( "Neville", _T("Blimey. We got an optimised palette to use.\n") ); } delete pPalRegion; } WeAreGeneratingOptPalette = FALSE; #endif return TRUE; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::GenerateOptimisedPalette(Spread *pSpread, BitmapExportOptions *pOptions, BOOL SnapToBrowserPalette) Author: Mark_Neves (Xara Group Ltd) Created: 16/1/97 Inputs: pSpread = ptr to spread pOptions = ptr to bitmap export options SnapToBrowserPalette = If TRUE, snap all optimised palette entries to the browser palette Returns: TRUE if Palette generated ok Purpose: Generates an optimised palette to use during export This is an alternative interface to GenerateOptimisedPalette(Spread *pSpread, UINT32 Depth, double DPI, UINT32 NumColsInPalette, BOOL UsePrimaryCols); WEBSTER - markn 16/1/97 SeeAlso: - ********************************************************************************************/ BOOL BaseBitmapFilter::GenerateOptimisedPalette(Spread *pSpread, BitmapExportOptions *pOptions, BOOL SnapToBrowserPalette) { if (pSpread != NULL && pOptions != NULL) { return GenerateOptimisedPalette(pSpread, pOptions->GetDepth(), pOptions->GetDPI(), SnapToBrowserPalette, pOptions->GetNumColsInPalette(), pOptions->GetUseSystemColours() ); } return FALSE; } void BaseBitmapFilter::AlterPaletteContents( LPLOGPALETTE pPalette ) { return; } /******************************************************************************************** > static BOOL BaseBitmapFilter::GeneratingOptimisedPalette() Author: Will_Cowling (Xara Group Ltd) Created: 30/5/96 Inputs: - Returns: TRUE if we are in the middle of generating an optimised Palette Purpose: Find out if we are currently generating an optimised palette or not SeeAlso: - ********************************************************************************************/ BOOL BaseBitmapFilter::GeneratingOptimisedPalette() { return WeAreGeneratingOptPalette; } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::WriteFileHeader(void) Author: Gerry_Iles (Xara Group Ltd) Created: 12/6/96 Inputs: - Returns: FALSE if failed else TRUE Purpose: To write out the file specific header data SeeAlso: - ********************************************************************************************/ BOOL BaseBitmapFilter::WriteFileHeader(void) { return(TRUE); } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::WritePreFrame(void) Author: Gerry_Iles (Xara Group Ltd) Created: 12/6/96 Inputs: - Returns: FALSE if failed else TRUE Purpose: To write out any frame specific info before the image SeeAlso: - ********************************************************************************************/ BOOL BaseBitmapFilter::WritePreFrame(void) { return(TRUE); } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::WriteFileHeader(void) Author: Gerry_Iles (Xara Group Ltd) Created: 12/6/96 Inputs: - Returns: FALSE if failed else TRUE Purpose: To write out the image itself This base class version actually calls the WriteToFile() function so that derived classes do not have to implement any of the multi-image stuff SeeAlso: - ********************************************************************************************/ BOOL BaseBitmapFilter::WriteFrame(void) { return(WriteToFile(TRUE)); } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::WritePostFrame(void) Author: Gerry_Iles (Xara Group Ltd) Created: 12/6/96 Inputs: - Returns: FALSE if failed else TRUE Purpose: To write out any frame specific info after the image SeeAlso: - ********************************************************************************************/ BOOL BaseBitmapFilter::WritePostFrame(void) { return(TRUE); } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::WriteFileEnd(void) Author: Gerry_Iles (Xara Group Ltd) Created: 12/6/96 Inputs: - Returns: FALSE if failed else TRUE Purpose: To write out the file specific data at the end of the file This base class version calls EndWriteToFile() so that derived classes do not have to implement the multi-image stuff SeeAlso: - ********************************************************************************************/ BOOL BaseBitmapFilter::WriteFileEnd(void) { return(EndWriteToFile()); } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::WritePreSecondPass(void) Author: Peter_Arnold (Xara Group Ltd) Created: 17/6/96 Inputs: - Returns: FALSE if failed else TRUE Purpose: Called before the second pass of a two pass export so the filter can reset itself SeeAlso: - ********************************************************************************************/ BOOL BaseBitmapFilter::WritePreSecondPass(void) { return(TRUE); } /******************************************************************************************** > virtual BOOL BaseBitmapFilter::WritePostOptimisedPalette(void) Author: Peter_Arnold (Xara Group Ltd) Created: 17/6/96 Inputs: - Returns: FALSE if failed else TRUE Purpose: Called after the optimised palette has been generated but before the export of the bitmap. SeeAlso: - ********************************************************************************************/ BOOL BaseBitmapFilter::WritePostOptimisedPalette(void) { return(TRUE); } /******************************************************************************************** > UINT32 BaseBitmapFilter::GetNumReservedColours() Author: Peter_Arnold (Xara Group Ltd) Created: 31/5/96 Inputs: - Returns: The numbers of colours the filter would like to reserve. The base class reserves zero colours. Purpose: Override this to leave spaces in the palette. eg the GIF filter reserves an index for the transparency mask colour. SeeAlso: - ********************************************************************************************/ UINT32 BaseBitmapFilter::GetNumReservedColours() { return 0; } /******************************************************************************************** > CCLexFile* BaseBitmapFilter::GetExportFile() const Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Returns: A pointer to the file provided in the filter entry point (DoExport,etc.) Purpose: Support function to obtain file to export in WriteBitmapToFile ********************************************************************************************/ CCLexFile* BaseBitmapFilter::GetExportFile() const { return OutputFile; } /******************************************************************************************** > BOOL BaseBitmapFilter::GetCurrentStripInfo( ADDR* ppBits, BMP_SIZE* pWidth, BMP_SIZE* pHeight, BMP_DEPTH* pDepth) const Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Outputs: ppBits : address of ADDR variable to accept pointer to bitmap bits pWidth : address of BMP_SIZE variable to accept bitmap width pHeight: address of BMP_SIZE variable to accept bitmap height pDepth : address of BMP_DEPTH variable to accept bitmap depth Returns: TRUE if data is valid FALSE otherwise Purpose: Support function to obtain information regarding the strip we are currently exporting. Notes: This information is only valid in the WriteFrame member ********************************************************************************************/ BOOL BaseBitmapFilter::GetCurrentStripInfo( ADDR* ppBits, BMP_SIZE* pWidth, BMP_SIZE* pHeight, BMP_DEPTH* pDepth) const { LPBITMAPINFO pBitmapInfo; LPBYTE pBitmapBits; ExportRegion->GetBitmapData(&pBitmapInfo, &pBitmapBits); if (pBitmapInfo == NULL || pBitmapBits == NULL) { ERROR3("pBitmapInfo == NULL || pBitmapBits == NULL"); return FALSE; } *ppBits = pBitmapBits; *pWidth = pBitmapInfo->bmiHeader.biWidth; *pHeight = pBitmapInfo->bmiHeader.biHeight; *pDepth = pBitmapInfo->bmiHeader.biBitCount; return TRUE; } /******************************************************************************************** > BitmapExportOptions* BaseBitmapFilter::GetBitmapExportOptions() const Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Returns: Details of the data to be exported Purpose: Support function to obtain BitmapExportOptions ********************************************************************************************/ BitmapExportOptions* BaseBitmapFilter::GetBitmapExportOptions() const { ERROR3IF(m_pExportOptions != NULL && !m_pExportOptions->IS_KIND_OF(BitmapExportOptions), "m_pExportOptions isn't"); return m_pExportOptions; } /******************************************************************************************** > BOOL BaseBitmapFilter::SetExportOptions ( BitmapExportOptions* pOptions ) Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Returns: TRUE if successful FALSE otherwise Purpose: To allow that f!?@$%g MakeBitmapFilter have its wicked way ********************************************************************************************/ BOOL BaseBitmapFilter::SetExportOptions ( BitmapExportOptions* pOptions ) { ERROR3IF ( pOptions != NULL && !pOptions->IS_KIND_OF ( BitmapExportOptions ), "BitmapExportOptions is wrong kind" ); // Don't delete the old options unless specifically requested. This is to avoid the nasty // access violations that might occur otherwise. //if (m_pExportOptions && pOptions != m_pExportOptions) // delete m_pExportOptions; m_pExportOptions = pOptions; return TRUE; } /******************************************************************************************** > virtual BitmapExportOptions* BaseBitmapFilter::CreateExportOptions() const Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Returns: A pointer to a new BitmapExportOptions class Purpose: Allows derived classes to override this function to provide their own class derived from BitmapExportOptions containing filter specific information. Notes: This should never be called ********************************************************************************************/ BitmapExportOptions* BaseBitmapFilter::CreateExportOptions() const { TRACE( _T("BaseBitmapFilter::CreateExportOptions() called\n")); BitmapExportOptions* pOptions = new BitmapExportOptions(_R(IDD_EXPORTBMPOPTS), FilterType(FilterID), &FilterName); return pOptions; } /******************************************************************************************** > static LPLOGPALETTE BaseBitmapFilter::Create8bppPalette() const Author: Mark_Neves (Xara Group Ltd) Created: 8/2/97 Returns: A pointer to a 8bpp palette Purpose: Creates an 8bpp palette used when generating an 8bpp bitmap Centralises common code previously found in BMP, GIF & PNG filters The palette returned is created using CCMalloc(). The caller should use CCFree() to discard the returned palette object when no longer needed. Introduced for WEBSTER - markn 8/2/97. Made static so that the Accusoft filter can use it Notes: ********************************************************************************************/ LPLOGPALETTE BaseBitmapFilter::Create8bppPalette() { /* LPLOGPALETTE lpPalette = NULL; GDrawContext *GDC = GRenderRegion::GetDrawContext(); if (GDC != NULL) { // This should return a palette plus tell it what dithering we require // 0 = dither, not 0 for no dithering. LPLOGPALETTE lpGavPalette = GDC->SelectPalette( 0 ); if (lpGavPalette != NULL) { const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 ); lpPalette = (LPLOGPALETTE)CCMalloc( TotalPal ); if (lpPalette != NULL) { // Take a copy of that palette memcpy( lpPalette, lpGavPalette, TotalPal ); // Always make 'browser' palette instead of 'standard' palette // - Harrison 8/10/97 PaletteManager::MakePaletteBrowserCompatible(lpPalette,TRUE); } } } ERROR3IF(lpPalette == NULL, "Didnt get a palette"); // The section of code below is used when the user has deleted 1 or more colours, and then // clicked on 'Preview'. // Have to change the palette here before it is used to decide which palette colours // match each pixel in the image. if( ( BmapPrevDlg::GetNumberOfDeletedColours() ) && ( BmapPrevDlg::m_bUseExistingPalette ) ) { BOOL Deleted = FALSE; INT32 NewIndex = -1; INT32 Popularity = 0; // Go through the palette in BmapPrevDlg. for( INT32 PaletteIndex = 0; PaletteIndex < ( lpPalette->palNumEntries ); PaletteIndex++ ) { // Has this colour been deleted by the user? Deleted = BmapPrevDlg::IsThisColourDeleted( PaletteIndex ); if( Deleted ) { // If this colour has been deleted, then we need to get its // original palette order. NewIndex = BmapPrevDlg::GetOriginalPaletteOrder( PaletteIndex ); // Set flags to 255 to tell the system that this colour is not // to be used in generating the exported image. lpPalette->palPalEntry[NewIndex].peFlags = 255; } else { // Not deleted, but is the popularity of this colour = 0? Popularity = BmapPrevDlg::GetPopularityValueForColour( PaletteIndex ); if( Popularity <= 0 ) { NewIndex = BmapPrevDlg::GetOriginalPaletteOrder( PaletteIndex ); lpPalette->palPalEntry[NewIndex].peFlags = 255; } } } } ExtendedPalette LockedColoursInformation; if( BmapPrevDlg::GotLockedColours() && lpPalette) { // Copy all the locked colours information over. LockedColoursInformation = BmapPrevDlg::m_LockedColoursPalette; ExtendedPalette LockedColoursInformation2 = BmapPrevDlg::m_LockedColoursPalette2; // Go through all the locked colours that we have for( INT32 i = 0; i < LockedColoursInformation.NumberOfColours; i++ ) { // Make sure that we are not exceeding the number of colours in the current palette. if( i >= ( lpPalette->palNumEntries ) ) continue; // We want to find the nearest colour in the current palette to this locked colour. double SmallestDistance = 0.0; BOOL FirstDistanceCalc = TRUE; INT32 ClosestColourIndex = 0; // Some variables needed below INT32 Red1, Green1, Blue1; INT32 Red2, Green2, Blue2; double RedDistance, GreenDistance, BlueDistance; double Distance; INT32 LockedIndex = LockedColoursInformation.Data[ i ].ExtraInformation; Red1 = LockedColoursInformation2.Data[ LockedIndex ].Red; Green1 = LockedColoursInformation2.Data[ LockedIndex ].Green; Blue1 = LockedColoursInformation2.Data[ LockedIndex ].Blue; // Go through all the colours in the current palette. for( INT32 j = 0; j < lpPalette->palNumEntries; j++ ) { // The components of the palette colour we are looking at. Red2 = lpPalette->palPalEntry[j].peRed; Green2 = lpPalette->palPalEntry[j].peGreen; Blue2 = lpPalette->palPalEntry[j].peBlue; // Calculate the distance between each of the colour components // ( Actually the square of this value - this does not matter since we // are not interested in the absolute values, only relative ones ). RedDistance = pow( double( Red1 - Red2 ), 2 ); GreenDistance = pow( double( Green1 - Green2 ), 2 ); BlueDistance = pow( double( Blue1 - Blue2 ), 2 ); // The overall distance. Distance = ( INT32 )( RedDistance + GreenDistance + BlueDistance ); if( FirstDistanceCalc ) { // First time around, so 'Distance' must be closest yet // However, there may be an occasion where this colour is already being used by one of // the existing locked colours. In this case, we just want to completely ignore this // colour, and carry on with the next loop BOOL BeingUsed = FALSE; for( INT32 Index = 0; Index < i; Index++ ) { if( LockedColoursInformation.Data[ Index ].ExtraInformation == j ) BeingUsed = TRUE; } // If it is being used, don't do anything. if( !BeingUsed ) { FirstDistanceCalc = FALSE; SmallestDistance = Distance; ClosestColourIndex = j; } } else if( Distance <= SmallestDistance ) { // Smallest distance so far? if so remember the distance & index // Do this only if this index is not being used by another locked colour // already. To do this, have to look through the currently assigned locked // colour indices. If this index is being used, then just do nothing. BOOL BeingUsed = FALSE; for( INT32 Index = 0; Index < i; Index++ ) { if( LockedColoursInformation.Data[ Index ].ExtraInformation == j ) BeingUsed = TRUE; } if( !BeingUsed ) { SmallestDistance = Distance; ClosestColourIndex = j; } } } // Put the colour index into the locked colour palette INT32 Information = LockedColoursInformation.Data[ i ].ExtraInformation; // Update the palette which holds the original values of the locked colours. INT32 r = BmapPrevDlg::m_LockedColoursPalette2.Data[ ClosestColourIndex ].Red; INT32 g = BmapPrevDlg::m_LockedColoursPalette2.Data[ ClosestColourIndex ].Green; INT32 b = BmapPrevDlg::m_LockedColoursPalette2.Data[ ClosestColourIndex ].Blue; BmapPrevDlg::m_LockedColoursPalette2.Data[ ClosestColourIndex ].Red = BmapPrevDlg::m_LockedColoursPalette2.Data[ Information ].Red; BmapPrevDlg::m_LockedColoursPalette2.Data[ ClosestColourIndex ].Green = BmapPrevDlg::m_LockedColoursPalette2.Data[ Information ].Green; BmapPrevDlg::m_LockedColoursPalette2.Data[ ClosestColourIndex ].Blue = BmapPrevDlg::m_LockedColoursPalette2.Data[ Information ].Blue; BmapPrevDlg::m_LockedColoursPalette2.Data[ Information ].Red = r; BmapPrevDlg::m_LockedColoursPalette2.Data[ Information ].Green = g; BmapPrevDlg::m_LockedColoursPalette2.Data[ Information ].Blue = b; BmapPrevDlg::m_LockedColoursPalette.Data[ i ].ExtraInformation = ClosestColourIndex; LockedColoursInformation = BmapPrevDlg::m_LockedColoursPalette; } } return lpPalette; */ return NULL; } /******************************************************************************************** > BOOL BaseBitmapFilter::ExportImagemap(Operation *pOp, PathName* pPath, Document* pDoc) Author: Graham_Walmsley (Xara Group Ltd) Created: 9/4/97 Returns: TRUE if export was successful FALSE if there was a problem Purpose: Calls on the Imagemap Filter to export an imagemap based on the current bitmap. ********************************************************************************************/ BOOL BaseBitmapFilter::ExportImagemap(Operation *pOp, PathName* pPath, Document* pDoc) { //Check our parameters ERROR2IF(pOp == NULL, FALSE,"BaseBitmapFilter::ExportImagemap no export operation"); ERROR2IF(pPath == NULL, FALSE,"BaseBitmapFilter::ExportImagemap no export pathname"); ERROR2IF(pDoc == NULL, FALSE,"BaseBitmapFilter::DoExport no document to export"); //First, let's find the imagemap filter ImagemapFilter* pImagemapFilter=GetImagemapFilter(); //And if we haven't found it, throw an error //Note that it is entirely possible that a future (modular) build might //not have an Imagemap filter, but for the moment it's worrying ERROR2IF(pImagemapFilter==NULL, FALSE, "OK. Own up. Who nicked the Imagemap filter?"); //Create a file to export to CCDiskFile ImagemapFile(1024, FALSE, TRUE); //Now we need to set up some Imagemap Filter Options //We base these on the last set of ImagemapFilterOptions that the user exported //with, so get those options from the ImagemapFilter ImagemapFilterOptions ifoToSet=pImagemapFilter->GetFilterOptions(); // Check we are exporting an imagemap either to a file or to the clipboard if (!(ifoToSet.m_fFile || ifoToSet.m_fClipboard)) return TRUE; // Successfully done as requested (not exported an image map) if (!GetBitmapExportOptions()) return FALSE; // can't export image map with out export options //Set the DPI from our bitmap options ifoToSet.m_dDPI=GetBitmapExportOptions()->GetDPI(); //And set the selection type ifoToSet.m_stExportArea=GetBitmapExportOptions()->GetSelectionType(); // Use the path set previously in the image map options -- Jonathan 6/12/2000 //And give the filter a pointer to our export file ifoToSet.m_pfileFile=&ImagemapFile; // tell the filter where the graphic is that it is describing ifoToSet.m_GraphicPath = *pPath; //Then set our new options back into the imagemap filter pImagemapFilter->SetFilterOptions(ifoToSet); //And tell the filter to export the file BOOL ok= pImagemapFilter->PrepareAndWriteData(pDoc); //Then close the file if it's still open if (ImagemapFile.isOpen()) ImagemapFile.close(); //And return return ok; } /******************************************************************************************** > ImagemapFilter* BaseBitmapFilter::GetImagemapFilter() Author: Graham_Walmsley (Xara Group Ltd) Created: 10/4/97 Returns: A pointer to the imagemap filter Purpose: Gets a pointer to the imagemap filter This function may return NULL and the calling code should handle this case. This is in case we ever build a version of Camelot without an Imagemap Filter. All our code should cope with the Imagemap Filter not being there. ********************************************************************************************/ ImagemapFilter* BaseBitmapFilter::GetImagemapFilter() { //First get a pointer to the filter manager FilterManager* pFilterManager=Camelot.GetFilterManager(); ERROR2IF(pFilterManager==NULL, NULL, "BaseBitmapFilter::GetImagemapFilter - FilterManager does not exist"); //Then return a pointer to the imagemap filter return ((ImagemapFilter*) pFilterManager->FindFilterFromID(FILTERID_IMAGEMAP)); } /******************************************************************************************** > void BaseBitmapFilter::ExportHTMLTag(PathName* ppthToUse) Author: Graham_Walmsley (Xara Group Ltd) Created: 21/5/97 Purpose: Exports an HTML tag to the clipboard that can be used in a page of HTML to embed the bitmap that is being exported. Technical notes: Note that the width and height parameters of the bitmap come from the width and height member variables of the BitmapExportOptions member variable. *But* Colin's comments say that it's at the filter author's discretion whether to use a BitmapExportOptions object or not. So, it seems we shouldn't throw an error if we can't find a BitmapExportOptions object. So if we can't find a BFO object, we don't throw an error - we simply don't export. ********************************************************************************************/ void BaseBitmapFilter::ExportHTMLTag(PathName* ppthToUse) { //Check our parameter if (ppthToUse==NULL) { ERROR2RAW("BaseCamelotFilter::ExportHTMLTag - NULL parameter"); return; } //First get the name of the file we are exporting to String_256 strFileName=ppthToUse->GetFileName(TRUE); //Now, do we have sensible bitmap export dimensions? ERROR3IF(m_PixelWidth<=0 || m_PixelHeight<=0, "Width and Height are both 0 in BaseBitmapFilter::ExportHTMLTag"); //And if they make sense if (m_PixelWidth>0 && m_PixelHeight>0) { //Then export a tag based on that width and height String_256 strTag; strTag.MakeMsg(_R(IDS_BITMAPFILTER_HTMLTAG), &strFileName, m_PixelWidth, m_PixelHeight); //And put that string on the clipboard PORTNOTE("clipboard","Removed InternalClipboard usage") #ifndef EXCLUDE_FROM_XARALX InternalClipboard::CopyText(strTag); #endif } } void PixelAlignedFiddle(DocRect* r) { INT32 lox, loy, hix, hiy = 0; #define INFLATE_ONLY #ifdef INFLATE_ONLY INT32 fiddle = 0; // extends the export clipping box to surround the exported image // maintaining the screen antialiasing #else INT32 fiddle = 375; // shaves small amounts of aa if we think we dont need it #endif lox = ((r->lo.x + fiddle)/750) * 750; loy = ((r->lo.y + fiddle)/750) * 750; hix = ((r->hi.x + 749 - fiddle)/750) * 750; hiy = ((r->hi.y + 749 - fiddle)/750) * 750; DocRect newr(lox, loy, hix, hiy); *r = newr; } // Static function which is used by BmapPrevDlg to call the above function. void BaseBitmapFilter::CallPixelAlignedFiddle( DocRect * r ) { PixelAlignedFiddle( r ); }