// $Id: makebmp.cpp 1282 2006-06-09 09:46:49Z alex $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ // /* */ #include "camtypes.h" #include "makebmp.h" //#include "resource.h" //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "page.h" //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "nodebmp.h" #include "bitmpinf.h" #include "bmpfiltr.h" //#include "simon.h" //#include "will3.h" //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "clikmods.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "nodetxtl.h" #include "grndbmp.h" #include "wrkrect.h" #include "colplate.h" #include "colcontx.h" #include "bmapprev.h" //#include "rrcaps.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "resimmap.h" //_R(IDE_EXPORT_NODRAWING) #include "palman.h" // PaletteManager::Get4bppBrowserPalette DECLARE_SOURCE("$Revision: 1282 $"); CC_IMPLEMENT_DYNCREATE(OpConvertToBitmap, SelOperation); CC_IMPLEMENT_DYNAMIC(MakeBitmapFilter, TI_GIFFilter); CC_IMPLEMENT_DYNCREATE(MakeBitmapExportOptions, MaskedFilterExportOptions) #define new CAM_DEBUG_NEW DPI MakeBitmapExportOptions::g_Dpi = 96.0; BMP_DEPTH MakeBitmapExportOptions::g_Depth = 8; DITHER MakeBitmapExportOptions::g_Dither = XARADITHER_ERROR_DIFFUSION; PALETTE MakeBitmapExportOptions::g_Palette = PAL_OPTIMISED; BOOL MakeBitmapExportOptions::g_TranspBkGnd = TRUE; FilterType MakeBitmapFilter::s_FilterType = MAKE_BITMAP_FILTER; //----------------------------------------------------------------------------------------------- // OpConvertToBitmap - Convert one or more objects into a bitmap /******************************************************************************************** > OpConvertToBitmap::OpConvertToBitmap() Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 Inputs: - Outputs: - Returns: - Purpose: OpConvertToBitmap constructor Errors: - SeeAlso: - ********************************************************************************************/ OpConvertToBitmap::OpConvertToBitmap(): SelOperation() { } /******************************************************************************************** > BOOL OpConvertToBitmap::Init() Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 Returns: TRUE if the operation could be successfully initialised FALSE if no more memory could be allocated Purpose: OpConvertToBitmap initialiser method Errors: ERROR will be called if there was insufficient memory to allocate the operation. SeeAlso: - ********************************************************************************************/ BOOL OpConvertToBitmap::Init() { MakeBitmapFilter::Initialise(); return (RegisterOpDescriptor( 0, _R(IDS_CONVERTTOBITMAPOP), CC_RUNTIME_CLASS(OpConvertToBitmap), OPTOKEN_CONVERTTOBITMAP, OpConvertToBitmap::GetState, 0, /* help ID */ 0, 0 /* bitmap ID */)); } /******************************************************************************************** > OpState OpConvertToBitmap::GetState(String_256*, OpDescriptor*) Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 Returns: The state of the OpConvertToBitmap operation Purpose: For finding the OpConvertToBitmap's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpConvertToBitmap::GetState(String_256* UIDescription, OpDescriptor*) { OpState OpSt; String_256 DisableReason; // Ensure that a document exists if (Document::GetSelected() == NULL) { // There is no selected document OpSt.Greyed = TRUE; // Load reason why operation is disabled DisableReason = String_256(_R(IDS_NO_DOC)); *UIDescription = DisableReason; return OpSt; } // Obtain the current selections Range Sel(*(GetApplication()->FindSelection())); // This operation is disabled if there are no nodes selected, or if none of the selected // objects can become a NodePath. Node* FirstSelected = Sel.FindFirst(); OpSt.Greyed = FALSE; if (FirstSelected == NULL) { OpSt.Greyed = TRUE; // Load reason why operation is disabled DisableReason = String_256(_R(IDS_NO_OBJECTS_SELECTED)); *UIDescription = DisableReason; } return(OpSt); } /******************************************************************************************** > void OpConvertToBitmap::Do(OpDescriptor*) Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 Inputs: - Purpose: Convert the selection into a bitmap Errors: - SeeAlso: - ********************************************************************************************/ void OpConvertToBitmap::Do(OpDescriptor*) { // We want to include bevel/contour/shadow controller nodes in our bitmap-copy // deliberations, so set PromoteToParent on a copy of the app's SelRange. SelRange Sel(*(GetApplication()->FindSelection())); RangeControl rg = Sel.GetRangeControlFlags(); rg.PromoteToParent = TRUE; Sel.Range::SetRangeControl(rg); // Find the first node which is selected Node* CurrentNode = Sel.FindFirst(); ERROR3IF(CurrentNode == NULL, "Called ConvertToBitmap with no nodes selected"); // In the retail build it is best to do nothing if we find there are no selected nodes if (CurrentNode != NULL) // No nodes selected so End { // We need to invalidate the region if (!DoInvalidateNodesRegions(Sel, TRUE)) goto EndOperation; if (!DoStartSelOp(FALSE,FALSE)) // Try to record the selection state , don't goto EndOperation; // render the blobs though // Create a special Bitmap filter, that creates a bitmap // and puts it in the tree MakeBitmapFilter* pBitmapFilter = new MakeBitmapFilter(); if (pBitmapFilter == NULL) { FailAndExecute(); goto EndOperation; } KernelBitmap* pBitmapToCreate = NULL; if (!pBitmapFilter->DoCreateBitmap(this, Document::GetSelected(), &pBitmapToCreate)) { delete pBitmapFilter; FailAndExecute(); goto EndOperation; } if (!pBitmapFilter->InsertBitmapIntoDocument(this, pBitmapToCreate, Document::GetSelected())) { delete pBitmapToCreate; delete pBitmapFilter; FailAndExecute(); goto EndOperation; } delete pBitmapFilter; if (!DoInvalidateNodesRegions(*(GetApplication()->FindSelection()), TRUE)) { // We need to invalidate the region FailAndExecute(); goto EndOperation; } } EndOperation: SelRange* pRng = GetApplication()->FindSelection(); End(); } /******************************************************************************************** > static BOOL MakeBitmapExportOptions::Declare() Author: Colin_Barfoot (Xara Group Ltd) (from Will) Created: 29/10/96 Returns: TRUE if successfully declared preferences FALSE otherwise Purpose: To declare preferences associated with these export options ********************************************************************************************/ BOOL MakeBitmapExportOptions::Declare() { if (Camelot.DeclareSection("Filters", 10)) { Camelot.DeclarePref( NULL, "CreateBitmapDPI", &g_Dpi, 1, 3000 ); Camelot.DeclarePref( NULL, "CreateBitmapDepth", &g_Depth, 1, 32 ); Camelot.DeclarePref( NULL, "CreateBitmapDither", (INT32*)&g_Dither, 0, XARADITHER_MAX ); Camelot.DeclarePref( NULL, "CreateBitmapPalette", (INT32*)&g_Palette, 0, 1 ); Camelot.DeclarePref( NULL, "CreateBitmapBkGnd", &g_TranspBkGnd, FALSE, TRUE ); } // All ok return TRUE; } /******************************************************************************************** > MakeBitmapExportOptions::MakeBitmapExportOptions( const FilterType FilterID, const StringBase* pFilterName) Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Purpose: Default constructor for a MakeBitmapExportOptions object (mainly to allow CreateBitmapCopy to store its own defaults) ********************************************************************************************/ MakeBitmapExportOptions::MakeBitmapExportOptions( const FilterType FilterID, const StringBase* pFilterName) : MaskedFilterExportOptions(_R(IDD_EXPORTBMPOPTS), FilterID, pFilterName) { } /******************************************************************************************** > BitmapExportOptions *MakeBitmapExportOptions::MakeCopy() Author: Neville_Humphrys (Xara Group Ltd) from Stefan code Created: 2/7/97 Purpose: Makes a copy object of this object See Also: BitmapExportOptions::CopyFrom(); BitmapExportOptions::MakeCopy(); ********************************************************************************************/ BitmapExportOptions *MakeBitmapExportOptions::MakeCopy() { // Get the runtime class info on this object CCRuntimeClass *pCCRuntimeClass = GetRuntimeClass(); // Create another object of the same type MakeBitmapExportOptions *temp = (MakeBitmapExportOptions *) pCCRuntimeClass->CreateObject(); if (temp != NULL) temp->CopyFrom(this); // copy the contents accross return temp; } /******************************************************************************************** > virtual BOOL MakeBitmapExportOptions::CopyFrom(BitmapExportOptions *pSource) Author: Neville_Humphrys (Xara Group Ltd) from Stefan code Created: 2/7/97 Inputs: pSource - the other BitmapExportOptions object to copy the data from Purpose: Sets the contents of this object from the passed object See Also: BitmapExportOptions::MakeCopy() ********************************************************************************************/ BOOL MakeBitmapExportOptions::CopyFrom(BitmapExportOptions *pSource) { // copy the base class first if (!MaskedFilterExportOptions::CopyFrom(pSource)) return FALSE; // must be the same class, otherwise the base class function above returns FALSE MakeBitmapExportOptions *pOther = (MakeBitmapExportOptions *)pSource; return TRUE; } /******************************************************************************************** > virtual BOOL MakeBitmapExportOptions::Equal(BitmapExportOptions *pSource) Author: Neville_Humphrys (Xara Group Ltd) from Stefan code Created: 2/7/97 Inputs: pSource - the other BitmapExportOptions object to copy the data from Purpose: Compares the contents of this and pOther objects Returns: TRUE, if objects are equal, FALSE otherwise See Also: BitmapExportOptions::MakeCopy() ********************************************************************************************/ /* BOOL MakeBitmapExportOptions::Equal(BitmapExportOptions *pSource) { BOOL ok = TRUE; // compare the base classes first ok = MaskedFilterExportOptions::Equal(pSource); // must be the same class, otherwise the base class function above returns FALSE MakeBitmapExportOptions *pOther = (MakeBitmapExportOptions *)pSource; // Compare any variables unique to our class here return ok; } */ /******************************************************************************************** > virtual BOOL MakeBitmapExportOptions::RetrieveDefaults() Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Purpose: See BitmapExportInfo for interface details: gets GIF specific preferences ********************************************************************************************/ BOOL MakeBitmapExportOptions::RetrieveDefaults() { BOOL ok = FALSE; if (MaskedFilterExportOptions::RetrieveDefaults()) { SetDPI(g_Dpi); SetDepth(g_Depth); SetDither(g_Dither); ok = TRUE; } return ok; } /******************************************************************************************** > virtual BOOL MakeBitmapExportOptions::SetAsDefaults() const Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Purpose: Provides additional implementation to set GIF specific info as defaults See Also: BitmapExportInfo::SetAsDefaults() ********************************************************************************************/ BOOL MakeBitmapExportOptions::SetAsDefaults() const { BOOL ok = FALSE; if (MaskedFilterExportOptions::SetAsDefaults()) { g_Dpi = GetDPI(); g_Depth = GetDepth(); g_Dither = GetDither(); g_TranspBkGnd = WantTransparent(); ok = TRUE; } return ok; } //----------------------------------------------------------------------------------------------- // MakeBitmapFilter - Dummy filter, used to render the selection into a bitmap /******************************************************************************************** > MakeBitmapFilter::MakeBitmapFilter() Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 Purpose: Constructor for an MakeBitmapFilter object. The object should be initialised before use. SeeAlso: MakeBitmapFilter::Init ********************************************************************************************/ MakeBitmapFilter::MakeBitmapFilter() : TI_GIFFilter () { pTheBitmap = NULL; } /******************************************************************************************** > static BOOL MakeBitmapFilter::Initialise() Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 Returns: TRUE if the filter was initialised ok, FALSE otherwise. Purpose: Initialise an MakeBitmapFilter object. Errors: Will fail if not enough memory to initialise. SeeAlso: EPSStack ********************************************************************************************/ BOOL MakeBitmapFilter::Initialise() { if (!MakeBitmapExportOptions::Declare()) return FALSE; if (Camelot.DeclareSection("Filters", 10)) { Camelot.DeclarePref( NULL, "DoTwoColourRounding", &GRenderOptPalette::DoTwoColourRoundingToPrimary, FALSE, TRUE ); } // All ok return TRUE; } /******************************************************************************************** > BOOL MakeBitmapFilter::DoCreateBitmap(Operation *pOp, Document *pDoc, KernelBitmap** ppBitmap) Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 Purpose: Exports the current selection as a bitmap, via the virtual fns of the inherited class. Returns: TRUE if worked, FALSE if failed. SeeAlso: GetExportOptions; PrepareToExport; ExportRenderNodes; CleanUpAfterExport; ********************************************************************************************/ BOOL MakeBitmapFilter::DoCreateBitmap(Operation *pOp, Document *pDoc, KernelBitmap** ppBitmap) { ERROR3IF(ppBitmap == NULL, "NULL bitmap pointer passed to MakeBitmapFilter::DoCreateBitmap"); if (ppBitmap == NULL) return FALSE; pTheBitmap = NULL; *ppBitmap = NULL; // 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); // remember the document in the class variable TheDocument = pDoc; // 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. RangeControl rg = GetApplication()->FindSelection()->GetRangeControlFlags(); rg.PromoteToParent = TRUE; GetApplication()->FindSelection()->Range::SetRangeControl(rg); SelRange Rng(*(GetApplication()->FindSelection())); // now, run through the selection selecting all nodes under all compound nodes // if we don't do this then all compound nodes aren't rendered correctly with transparent // bitmaps Node * pNode = Rng.FindFirst(FALSE); while (pNode) { pNode->SetSelected(FALSE); pNode->SetSelected(TRUE); pNode = Rng.FindNext(pNode, FALSE); } rg.PromoteToParent = FALSE; GetApplication()->FindSelection()->Range::SetRangeControl(rg); GetApplication()->UpdateSelection(); DocRect ClipRect = GetApplication()->FindSelection()->GetBoundingRect(); 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 != SELECTION) { BOOL UseDrawingBounds = TRUE; 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 = SELECTION; UseDrawingBounds = FALSE; } } } if (UseDrawingBounds) { // Work out the size of the rectangle encompassing the drawing (visible layers only) ClipRect = GetSizeOfDrawing(pSpread); } } // Create somewhere to put the user options and fill them up MakeBitmapExportOptions* pMakeBmpExportOptions = (MakeBitmapExportOptions*)CreateExportOptions(); if (pMakeBmpExportOptions == NULL) { Error::SetError(_R(IDS_OUT_OF_MEMORY)); return FALSE; } pMakeBmpExportOptions->RetrieveDefaults(); pMakeBmpExportOptions->SetDepth(32); // create bmp copies shoulda always default to being 32 bit pMakeBmpExportOptions->SetSelectionType(Selection); // Set the BaseBitmapFilter member so we can use base class functionality - blurghh SetExportOptions(pMakeBmpExportOptions); BOOL ok = GetExportOptions( (BitmapExportOptions*)pMakeBmpExportOptions ); BOOL IsAnimation = BmapPrevDlg::m_pExportOptions == NULL; BaseBitmapFilter * pNewFilter = this; BitmapExportOptions * pExportOptions = BmapPrevDlg::m_pExportOptions; if (!IsAnimation) { pNewFilter = pExportOptions->FindBitmapFilterForTheseExportOptions(); // from the exporting point of view we should always have been using png options // set them to the png options for the export part if (pNewFilter) pNewFilter->SetExportOptions(pExportOptions); // gets the real export options that the prevdlg has set up for us BmapPrevDlg::m_pExportOptions = NULL; // take responsibility for this data } else { // the animation export didn't bring up the dlg so never set BmapPrevDlg::m_pExportOptions // so continue with these options pExportOptions = (BitmapExportOptions*)pMakeBmpExportOptions; } SetExportOptions(pExportOptions); if (!ok) { SetExportOptions(NULL); // deletes the filter ptr and nulls it delete pExportOptions; return FALSE; // if cancelled } //////////////// SMFIX pExportOptions->MarkValid(); SetDepthToRender(pExportOptions->GetDepth()); // 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, pExportOptions->GetDepth(), pExportOptions->GetDPI(), pExportOptions->GetSelectionType(), pExportOptions->GetDither())) { pNewFilter->SetExportOptions(NULL); SetExportOptions(NULL); delete pExportOptions; CleanUpAfterExport(); return FALSE; } RenderInStrips = FALSE; if (!ExportRender(ExportRegion)) { pNewFilter->SetExportOptions(NULL); // deletes the filter ptr and nulls it SetExportOptions(NULL); delete pExportOptions; CleanUpAfterExport(); return FALSE; } // Now get the converted 32Bit BMP pTheBitmap = GetTheBitmap(pExportOptions); // if we`ve got a transparency index AND we`ve got a 32 Bit Render region with alpha channel info // then we can quickly do if(pExportOptions->GetDepth() <= 8 && pExportOptions->GetTransparencyIndex() != -1 && pTheBitmap) { // What we do now is to go throught the bitmap setting the relavent pixels to transparent // depending on the alpha channel info held in the 32 bit version. if(!ApplyTransparentColoursToBitmap(pTheBitmap,pExportOptions)) { pNewFilter->SetExportOptions(NULL); // deletes the filter ptr and nulls it return FALSE; } // Now make sure the bitmap knows that it has a transparent colour! pTheBitmap->SetTransparencyIndex(pExportOptions->GetTransparencyIndex()); } // Set pointer to the bitmap we have created *ppBitmap = pTheBitmap; pNewFilter->SetExportOptions(NULL); // deletes the filter ptr and nulls it SetExportOptions(NULL); delete pExportOptions; CleanUpAfterExport(); return *ppBitmap != NULL; //////////////// SMFIX } /******************************************************************************************** > virtual KernelBitmap* MakeBitmapFilter::GetTheBitmap () Author: Will_Cowling (Xara Group Ltd) Created: 16/6/96 Purpose: Creates a kernel bitmap from the Export RenderRegion Returns: Ptr to the bitmap, or NULL if error ********************************************************************************************/ KernelBitmap* MakeBitmapFilter::GetTheBitmap(BitmapExportOptions *pExportOptions) { // SMFIX dont use member vars of the class to store stuff like the palette // take all the info from the export options ptr OILBitmap* pOilBitmap = ExportRegion->ExtractBitmapCopy ( pExportOptions->GetLogicalPalette(), pDestBMInfo, pDestBMBytes, pExportOptions->GetTransparencyIndex()); if (pOilBitmap == NULL) { CleanUpAfterExport (); return NULL; } // Err... Lets make sure that the DPI is set up correctly form the options! LPBITMAPINFOHEADER pInfoHeader = pOilBitmap->GetBitmapInfoHeader(); if(pInfoHeader) { INT32 NewPPM = (INT32)((10000.0 * pExportOptions->GetDPI()) / 254.0); pInfoHeader->biXPelsPerMeter = NewPPM; pInfoHeader->biYPelsPerMeter = NewPPM; } // Make a kernel bitmap from the oily one return KernelBitmap::MakeKernelBitmap ( pOilBitmap ); } /******************************************************************************************** > BOOL MakeBitmapFilter::InsertBitmapIntoDocument(UndoableOperation *pOp, KernelBitmap* KernelBmp, Document* DestDoc) Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 Purpose: Exports the current selection as a bitmap, via the virtual fns of the inherited class. Returns: TRUE if worked, FALSE if failed. SeeAlso: GetExportOptions; PrepareToExport; ExportRenderNodes; CleanUpAfterExport; ********************************************************************************************/ BOOL MakeBitmapFilter::InsertBitmapIntoDocument(UndoableOperation *pOp, KernelBitmap* KernelBmp, Document* DestDoc) { Spread *pSpread; DocCoord Origin; // Remember the selection rect, before we change it DocRect SelRect = GetApplication()->FindSelection()->GetBoundingRect(); // For now, position Draw objects on 1st page of spread 1 PORTNOTE("spread", "Multi-spread warning!") pSpread = GetFirstSpread(DestDoc); Page *pPage = (Page *) pSpread->FindFirstPageInSpread(); ERROR3IF(!pPage->IsKindOf(CC_RUNTIME_CLASS(Page)), "MakeBitmapFilter::InsertBitmapIntoDocument: Could not find first Page"); // Use bottom left of page as origin DocRect PageRect = pPage->GetPageRect(); Origin.x = PageRect.lo.x; Origin.y = PageRect.hi.y; // Get a new NodeBitmap object to import into. NodeBitmap *pNodeBitmap = new NodeBitmap; if ((pNodeBitmap == NULL) || (!pNodeBitmap->SetUpPath(12,12))) return FALSE; // Attach the Imported Bitmap to our Node pNodeBitmap->GetBitmapRef()->Attach(KernelBmp, DestDoc); //GetDocument()); if (pNodeBitmap->GetBitmap() != KernelBmp) delete KernelBmp; // It didn't use the bitmap we gave it, so we can delete it // 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); DocRect BoundsRect; BoundsRect.lo = Origin; BoundsRect.hi.x = BoundsRect.lo.x + Info.RecommendedWidth; BoundsRect.hi.y = BoundsRect.lo.y + Info.RecommendedHeight; // 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; return FALSE; } // Set the default attrs // This MUST be done before the NodeBitmap is Inserted into the tree if (!pNodeBitmap->ApplyDefaultBitmapAttrs(pOp)) return FALSE; // Insert the node, but don't invalidate its region if (!pOp->DoInsertNewNode(pNodeBitmap, pSpread, FALSE)) { // It didn't work - delete the sub-tree we just created, and report error. delete pNodeBitmap; return FALSE; } // bitmap is currently positioned so its bottom left hand // corner is at the top left of the page // By default we'll move it down so the top-left of the bitmap is on the top-left of the page INT32 XTranslate = 0; INT32 YTranslate = -Info.RecommendedHeight; ClickModifiers ClickMods = ClickModifiers::GetClickModifiers(); if (ClickMods.Adjust && !SelRect.IsEmpty()) { // If shift is down, then we'll try and place the bitmap exactly on top of the selection DocCoord SelectionCentre(SelRect.lo.x + (SelRect.Width()/2), SelRect.lo.y + (SelRect.Height()/2)); XTranslate = SelectionCentre.x - Origin.x - (Info.RecommendedWidth/2); YTranslate = SelectionCentre.y - Origin.y - (Info.RecommendedHeight/2); } else { // Otherwise we'll try and centre it within the current view Spread* pCurrentSpread; DocCoord ViewCentre; if (FindCentreInsertionPosition(&pCurrentSpread, &ViewCentre)) { /* Karim 19/01/2000 * Ensure that the bmp is pixel-aligned as close to the centre as possible. * XTranslate = ViewCentre.x - Origin.x - (Info.RecommendedWidth/2); YTranslate = ViewCentre.y - Origin.y - (Info.RecommendedHeight/2); /**/ DocCoord PixAlignBmpOrigin( ViewCentre.x - Info.RecommendedWidth/2, ViewCentre.y - Info.RecommendedHeight/2 ); INT32 FullDPI = GRenderRegion::GetDefaultDPI(); MILLIPOINT PixWidth = (INT32)((IN_MP_VAL / (double)FullDPI) + 0.5); PixAlignBmpOrigin.x -= PixAlignBmpOrigin.x % PixWidth; PixAlignBmpOrigin.y -= PixAlignBmpOrigin.y % PixWidth; XTranslate = PixAlignBmpOrigin.x - Origin.x; YTranslate = PixAlignBmpOrigin.y - Origin.y; } } Trans2DMatrix Xlate(XTranslate, YTranslate); pNodeBitmap->Transform(Xlate); // Ensure Sel Bounds are correct after translation GetApplication()->UpdateSelection(); return TRUE; } /******************************************************************************************** > BOOL MakeBitmapFilter::FindCentreInsertionPosition(Spread** Spread, DocCoord* Position) Author: Will_Cowling (Xara Group Ltd) (from Simon) Created: 12/6/96 Inputs: - Outputs: Spread: The spread to place the clipboard objects on Position:The centre of the view (Spread coords) Purpose: Finds the centre insertion position for clipboard objects ********************************************************************************************/ BOOL MakeBitmapFilter::FindCentreInsertionPosition(Spread** Spread, DocCoord* Position) { // --------------------------------------------------------------------------------- // Find out which spread is in the centre of the view // this is the spread that the pasted objects will be placed on // Obtain the current DocView DocView* CurDocView = DocView::GetCurrent(); ENSURE(CurDocView != NULL, "The current DocView is NULL"); if (CurDocView == NULL) return FALSE; // No DocView // Get the view rect WorkRect WrkViewRect = CurDocView->GetViewRect(); if (WrkViewRect.IsEmpty() || (!WrkViewRect.IsValid()) ) return FALSE; // Defensive // Determine the centre of the view WorkCoord WrkCentreOfView; WrkCentreOfView.x = WrkViewRect.lox + (WrkViewRect.Width()/2); WrkCentreOfView.y = WrkViewRect.loy + (WrkViewRect.Height()/2); // FindEnclosing spread requires an OilCoord OilCoord OilCentreOfView = WrkCentreOfView.ToOil(CurDocView->GetScrollOffsets()); // Find out which spread to insert the pasteboard objects onto (*Spread) = CurDocView->FindEnclosingSpread(OilCentreOfView); if ((*Spread) == NULL) return FALSE; // There is no spread // Phew // --------------------------------------------------------------------------------- // Now lets find the spread coordinate of the centre of the view DocRect DocViewRect = CurDocView->GetDocViewRect(*Spread); if ( DocViewRect.IsEmpty() || (!DocViewRect.IsValid()) ) { ERROR3("DocViewRect is invalid"); return FALSE; // Defensive } // Find the centre of the DocViewRect DocCoord DocCentreOfView; DocCentreOfView.x = DocViewRect.lox + (DocViewRect.Width()/2); DocCentreOfView.y = DocViewRect.loy + (DocViewRect.Height()/2); // -------------------------------------------------------------------------------- // Now convert from DocCoords to spread coords DocRect PhysSpreadRect = (*Spread)->GetPasteboardRect(); (*Position).x = DocCentreOfView.x - PhysSpreadRect.lo.x; (*Position).y = DocCentreOfView.y - PhysSpreadRect.lo.y; return TRUE; } /******************************************************************************************** > virtual void MakeBitmapFilter::CleanUpAfterExport() Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 Purpose: Cleans up the memory allocated at the end of Exporting or when exporting has been aborted for some reason. Does its cleaning up and then calls the baseclass version to do its stuff, - used when the import process ends, either normally or abnormally. Override if extra things are required. SeeAlso: BaseBitmapFilter::PrepareToExport(); BaseBitmapFilter::CleanUpAfterExport(); Scope: Protected ********************************************************************************************/ void MakeBitmapFilter::CleanUpAfterExport() { // Call the baseclass version to do its stuff MaskedFilter::CleanUpAfterExport(); } /******************************************************************************************** > virtual BOOL MakeBitmapFilter::GetExportOptions(BitmapExportOptions* pOptions) Author: Colin_Barfoot (Xara Group Ltd) Created: 12/11/96 Purpose: See BaseBitmapFilter for interface details ********************************************************************************************/ BOOL MakeBitmapFilter::GetExportOptions(BitmapExportOptions* pOptions) { ERROR2IF(pOptions == NULL, FALSE, "pOptions NULL"); ERROR3IF(!pOptions->IS_KIND_OF(MakeBitmapExportOptions), "pOptions isn't"); BOOL Ok = FALSE; OpDescriptor* pOpDes = OpDescriptor::FindOpDescriptor(OPTOKEN_GIFTABDLG); if (pOpDes != NULL) { // Graeme (18-9-00) // We need to ensure that the correct file type is set up. The bitmap copy filter // uses the PNG settings, and so it's necessary to convince the dialogue that we // are exporting as a PNG to avoid relics from an earlier export to confuse matters. BmapPrevDlg::m_pthExport.SetType ( String_256 ( "png" ) ); // set up the data for the export options dialog OpParam Param((INT32)pOptions, (INT32)this); // invoke the dialog pOpDes->Invoke(&Param); // SMFIX // we have brought the dlg up so get the options from the dlg as the graphic type may have changed pOptions = BmapPrevDlg::m_pExportOptions; Ok = BmapPrevDlg::m_bClickedOnExport; } else { ERROR3("Unable to find OPTOKEN_BMAPPREVDLG"); } // Return whether or not it worked. return Ok; } /******************************************************************************************** > virtual UINT32 MakeBitmapFilter::GetExportMsgID() Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 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. Overides the baseclass form of the function so that during the two stage export process it can change the message. SeeAlso: DoExport; ********************************************************************************************/ UINT32 MakeBitmapFilter::GetExportMsgID() { if (GeneratingOptimisedPalette()) return _R(IDS_GENOPTPALMSGID); // "Generating optimised palette..." else return _R(IDS_MAKEBITMAPMSGID); // "Creating bitmap ..." } /******************************************************************************************** > virtual BOOL MakeBitmapFilter::WriteToFile( BOOL End ) Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 Inputs: End is TRUE if this is the last block of the file. Returns: TRUE if worked, FALSE if errored. Purpose: Physically put the bitmap into the disk. NOTE - ONLY COPES WITH End=TRUE currently Most of the work now is down by WriteDataToFile as this is a static form and there is a similar version in the Accusoft DLL. This can therefore be used to pass work onto the Accusoft DLL, for the cases we don't cope with. End is ignored now and should always be set to TRUE. SeeAlso: WriteDataToFile(); AccusoftFilters::WriteToFile; AccusoftFilters::WriteDataToFile; ********************************************************************************************/ BOOL MakeBitmapFilter::WriteToFile( BOOL End ) { // All ok return TRUE; } /******************************************************************************************** > BOOL MakeBitmapFilter::EndWriteToFile( ) Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 Inputs: - Purpose: Cleans up after writing the bitmap data out to a file. Inherited classes override this to write in different file formats. This is slightly different to most other bitmap filters in that it is here that the data actually gets written out to file, after doing the transparency translation, if required. Returns: TRUE if worked, FALSE if failed. ********************************************************************************************/ BOOL MakeBitmapFilter::EndWriteToFile( ) { // All ok return TRUE; } /******************************************************************************************** > virtual BOOL MakeBitmapFilter::IsThisBppOk(UINT32 Bpp) Author: Will_Cowling (Xara Group Ltd) Created: 11/6/96 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: OpConvertToBitmap::DoWithParam; ********************************************************************************************/ BOOL MakeBitmapFilter::IsThisBppOk(UINT32 Bpp) { return (Bpp == 24 || Bpp == 8 || Bpp == 4 || Bpp == 1); } /******************************************************************************************** > virtual BitmapExportOptions* MakeBitmapFilter::CreateExportOptions() const Author: Colin_Barfoot (Xara Group Ltd) Created: 29/10/96 Purpose: See BaseBitmapFilter for details Notes: Provides a MakeBitmapExportOptions class ********************************************************************************************/ BitmapExportOptions* MakeBitmapFilter::CreateExportOptions() const { MakeBitmapExportOptions* pExportOptions = new MakeBitmapExportOptions(MAKE_BITMAP_FILTER, &FilterName); return (BitmapExportOptions*)pExportOptions; }