// $Id: bmplist.cpp 1488 2006-07-20 15:31:34Z phil $ /* @@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============================ */ // Kernel level parts of bitmap lists /* */ #include "camtypes.h" //#include "bmplist.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "bitmpinf.h" //#include "list.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "will.h" //#include "native.h" // The new designed native filter, used for v2 //#include "nativeps.h" // The old style EPS native filter, used in v1.1 #include "clipint.h" #include "nodebmp.h" #include "progress.h" #include "toollist.h" #include "objchge.h" #include "csrstack.h" //#include "clipint.h" #include "ophist.h" //#include "will2.h" #include "bmpcomp.h" //#include "nodecach.h" // for CacheCompound specific tests in cleaning up GlobalList CC_IMPLEMENT_MEMDUMP( GlobalBitmapList, List ) //CC_IMPLEMENT_MEMDUMP( GreyscaleBitmapList, List ) CC_IMPLEMENT_DYNAMIC(BitmapListChangedMsg, Msg) #if !defined(EXCLUDE_FROM_RALPH) CC_IMPLEMENT_DYNCREATE(OpDeleteBitmap,Operation); #endif // Declare smart memory handling in Debug builds #define new CAM_DEBUG_NEW // Preference for the maximum size of the greyscale bitmap list //INT32 GreyscaleBitmapList::m_lMaxSize = 2 * 1024 * 1024; // 2MB default max size /********************************************************************************************** > GlobalBitmapList::GlobalBitmapList() Author: Will_Cowling (Xara Group Ltd) Created: 14/12/94 Inputs: - Outputs: - Returns: - Purpose: GlobalBitmapList constructor **********************************************************************************************/ GlobalBitmapList::GlobalBitmapList() { } /********************************************************************************************** > GlobalBitmapList::~GlobalBitmapList() Author: Will_Cowling (Xara Group Ltd) Created: 14/12/94 Inputs: - Outputs: - Returns: - Purpose: GlobalBitmapList destructor **********************************************************************************************/ GlobalBitmapList::~GlobalBitmapList() { } /********************************************************************************************** > BOOL GlobalBitmapList::Init() Author: Will_Cowling (Xara Group Ltd) Created: 6/2/95 Returns: FALSE if failed. Purpose: Initialise the GlobalBitmapList **********************************************************************************************/ BOOL GlobalBitmapList::Init() { // GreyscaleBitmapList::Init(); #if !defined(EXCLUDE_FROM_RALPH) return OpDeleteBitmap::Init(); #else return TRUE; #endif } /********************************************************************************************** > BOOL GlobalBitmapList::DeInit() Author: Will_Cowling (Xara Group Ltd) Created: 6/2/95 Returns: FALSE if failed. Purpose: DeInitialise the GlobalBitmapList **********************************************************************************************/ BOOL GlobalBitmapList::DeInit() { // First deinit the global bitmap list GlobalBitmapList* pBmpList = GetApplication()->GetGlobalBitmapList(); ListItem* pItem = pBmpList->GetHead(); while (pItem != NULL) { ListItem* pNext = pBmpList->GetNext(pItem); OILBitmap* pBitmap = (OILBitmap*)pItem; ERROR3IF(pBitmap->IsTemp(), "Warning. Found temp bitmap in global bitmap list"); if (pBitmap == OILBitmap::Default) { // Don't delete the default bitmap, just remove it from the list pBitmap->RemoveFromGlobalList(); } else { delete pBitmap; // This will remove it from the list before deleting it } pItem = pNext; } // Now deinit the greyscale bitmap list // GreyscaleBitmapList::DeInit(); return TRUE; } /********************************************************************************************** > BOOL GlobalBitmapList::AddItem(OILBitmap *Item) Author: Will_Cowling (Xara Group Ltd) Created: 14/12/94 Returns: TRUE Purpose: Adds an item to the tail of the GlobalBitmaplist **********************************************************************************************/ BOOL GlobalBitmapList::AddItem(OILBitmap *Item) { ERROR3IF(Item == NULL, "Trying to add NULL item to Global Bitmap List"); if (Item == NULL) return FALSE; // Is this Bitmap already in the list ? LISTPOS pos = FindPosition((ListItem*)Item); if (pos == NOT_IN_LIST || pos == EMPTY_LIST) { // It's not in the list yet, so add it on the end AddTail((ListItem*)Item); return TRUE; } else { // It's already in the list, so just return return FALSE; } } /********************************************************************************************** > ListItem* GlobalBitmapList::GetFirstBitmapName(String_256* BitmapName) Author: Will_Cowling (Xara Group Ltd) Created: 14/12/94 Returns: The bitmap found at the head of the List, or NULL if none found. Purpose: Find the names of the bitmaps in the list **********************************************************************************************/ ListItem* GlobalBitmapList::GetFirstBitmapName(String_256* BitmapName) { ListItem* First = GetHead(); while (First != NULL) { if (!((OILBitmap*)First)->HasBeenDeleted()) { *BitmapName = ((OILBitmap*)First)->GetName(); return First; } First = GetNext(First); } return NULL; } /********************************************************************************************** > ListItem* GlobalBitmapList::GetNextBitmapName(ListItem* Prev, String_256* BitmapName) Author: Will_Cowling (Xara Group Ltd) Created: 14/12/94 Returns: The next bitmap in the List, or NULL if none found. Purpose: Find the names of the bitmaps in the list **********************************************************************************************/ ListItem* GlobalBitmapList::GetNextBitmapName(ListItem* Prev, String_256* BitmapName) { ListItem* Next = GetNext(Prev); while (Next != NULL) { if (!((OILBitmap*)Next)->HasBeenDeleted()) { *BitmapName = ((OILBitmap*)Next)->GetName(); return Next; } Next = GetNext(Next); } return NULL; } /********************************************************************************************** > OILBitmap* GlobalBitmapList::GetBitmapFromName(String_256* BitmapName) Author: Will_Cowling (Xara Group Ltd) Created: 14/12/94 Returns: Ptr to Bitmap of the name given, or NULL if not found. Purpose: Finds a bitmap with a particular name. **********************************************************************************************/ OILBitmap* GlobalBitmapList::GetBitmapFromName(String_256* BitmapName) { ListItem* pItem = GetHead(); while (pItem != NULL) { OILBitmap* pBmp = (OILBitmap*)pItem; if (!pBmp->HasBeenDeleted()) { if (*BitmapName == pBmp->GetName()) return pBmp; } pItem = GetNext(pItem); } return NULL; } /********************************************************************************************** > void GlobalBitmapList::MakeNameUnique(String_256* BitmapName) Author: Will_Cowling (Xara Group Ltd) Created: 14/12/94 Purpose: Ensures a bitmap name is unique. **********************************************************************************************/ void GlobalBitmapList::MakeNameUnique(String_256* BitmapName) { ListItem* Bitmap = GetHead(); INT32 Number = 1; String_256 Name = *BitmapName; while (Bitmap != NULL) { if ( Name == ((OILBitmap*)Bitmap)->GetName() ) { // This name already exists, so lets make it unique String_256 Str; camSnprintf( Str, 256, TEXT("%d"), Number++ ); Name = (*BitmapName); Name += Str; Bitmap = GetHead(); // Start at the beginning again } else { Bitmap = GetNext(Bitmap); } } *BitmapName = Name; } /********************************************************************************************** > OILBitmap* GlobalBitmapList::FindDuplicateBitmap(OILBitmap* pBitmap) Author: Will_Cowling (Xara Group Ltd) Created: 14/8/96 Purpose: Looks to see if an identical bitmap is already in the bitmap list **********************************************************************************************/ OILBitmap* GlobalBitmapList::FindDuplicateBitmap(OILBitmap* pOILBitmap) { ListItem* pItem = GetHead(); while (pItem != NULL) { OILBitmap* pBmp = (OILBitmap*)pItem; ERROR3IF(pBmp == pOILBitmap, "Why is this bitmap already in the list ?"); if (pBmp != pOILBitmap && *pBmp == *pOILBitmap) { return pBmp; } pItem = GetNext(pItem); } return NULL; } /********************************************************************************************** > INT32 GlobalBitmapList::GetDocumentBitmapCount(Document* pDoc) Author: Will_Cowling (Xara Group Ltd) Created: 14/8/96 Purpose: Find how many bitmaps are being used by this document **********************************************************************************************/ INT32 GlobalBitmapList::GetDocumentBitmapCount(Document* pDoc) { INT32 Count = 0; INT32 DefaultIsUsed = FALSE; if (pDoc != NULL) { // Now get the actual bitmap list BitmapList* Bitmaps = pDoc->GetBitmapList(); if (Bitmaps) { // Go through all the bitmaps in the list ListItem *Ptr = Bitmaps->GetHead(); while (Ptr != NULL) { KernelBitmap* Bmp = (KernelBitmap*)Ptr; if (Bmp->IsDefaultBitmap() && !DefaultIsUsed) { if (Bmp->IsUsedInDocument(pDoc)) DefaultIsUsed = TRUE; } else if (Bmp->IsUsedInDocument(pDoc)) { Count++; } Ptr = Bitmaps->GetNext(Ptr); } } } if (DefaultIsUsed) Count++; return Count; } /********************************************************************************************** > INT32 GlobalBitmapList::GetDocumentBitmapSize(Document* pDoc) Author: Will_Cowling (Xara Group Ltd) Created: 14/8/96 Purpose: Find the total size of the bitmaps being used by this document **********************************************************************************************/ INT32 GlobalBitmapList::GetDocumentBitmapSize(Document* pDoc) { INT32 Mem = 0; INT32 DefaultIsUsed = FALSE; if (pDoc != NULL) { // Now get the actual bitmap list BitmapList* Bitmaps = pDoc->GetBitmapList(); if (Bitmaps) { // Go through all the bitmaps in the list ListItem *Ptr = Bitmaps->GetHead(); while (Ptr != NULL) { KernelBitmap* Bmp = (KernelBitmap*)Ptr; if (Bmp->IsDefaultBitmap() && !DefaultIsUsed) { if (Bmp->IsUsedInDocument(pDoc)) DefaultIsUsed = TRUE; } else if (Bmp->IsUsedInDocument(pDoc)) { Mem += Bmp->ActualBitmap->GetBitmapSize(); } Ptr = Bitmaps->GetNext(Ptr); } } } if (DefaultIsUsed) { Mem += OILBitmap::Default->GetBitmapSize(); } return Mem; } /********************************************************************************************** > BOOL GlobalBitmapList::IsUsedInDocument(Document * pDoc, OILBitmap* pOILBmp) Author: Neville_Humphrys (Xara Group Ltd) Created: 12/8/97 Inputs: pDoc Document to check bitmap list of pOILBmp the OIL bitmap to find in the list Returns: True if the bitmap is found, False otherwise Purpose: Checks if the specified OIL bitmap is in the bitmap list of the specified document. SeeAlso: DeleteAllUnusedBitmaps; **********************************************************************************************/ BOOL GlobalBitmapList::IsUsedInDocument(Document * pDoc, OILBitmap* pOILBmp) { ERROR2IF(pDoc == NULL || pOILBmp == NULL,FALSE,"GlobalBitmapList::IsUsedInDocument Bad params!"); // Get the bitmap list for the specified document BitmapList* pBitmaps = pDoc->GetBitmapList(); if (pBitmaps) { ListItem* pKBmp = pBitmaps->GetHead(); while (pKBmp) { KernelBitmap* pBmp = (KernelBitmap*)pKBmp; if (pBmp->ActualBitmap == pOILBmp) { // Found a copy of the bitmap and so return TRUE return TRUE; } PORTNOTETRACE("other","GlobalBitmapList::IsUsedInDocument - skip XPE master bit"); #ifndef EXCLUDE_FROM_XARALX // Check whether this bitmap is an XPE master if (pBmp->ActualBitmap) { OILBitmap* pMaster = NULL; IXMLDOMDocumentPtr pInfo = NULL; pBmp->ActualBitmap->GetXPEInfo(pMaster, pInfo); if (pMaster == pOILBmp) return TRUE; } #endif pKBmp = pBitmaps->GetNext(pKBmp); } } // Bitmap not found and so return FALSE return FALSE; } /********************************************************************************************** > void GlobalBitmapList::DeleteAllUnusedBitmaps() Author: Will_Cowling (Xara Group Ltd) Created: 14/8/96 Purpose: Called when a document is deleted, to delete all the unused bitmaps **********************************************************************************************/ void GlobalBitmapList::DeleteAllUnusedBitmaps() { InternalClipboard::AttrsHaveChanged(); // As we now have two clipboards, we need to sort out both InternalClipboard::Swap(); // Swap to alternative clipboard InternalClipboard::AttrsHaveChanged(); InternalClipboard::Swap(); // Swap back to orignal clipboard ListItem* pItem = GetHead(); while (pItem != NULL) { OILBitmap* pOILBmp = (OILBitmap*)pItem; ERROR3IF(pOILBmp->IsAFractal(), "There's a fractal in the global list ! How'd that happen ?"); BOOL IsUsed = FALSE; if (pOILBmp == OILBitmap::Default) { IsUsed = TRUE; } // DY 16/3/2000, we don't want to delete bitmaps that are used by brushes when the // document they are in is deleted. if (pOILBmp->IsUsedByBrush()) { IsUsed = TRUE; } else { // Go though all the documents Document* pDoc = (Document*)GetApplication()->Documents.GetHead(); while (pDoc != NULL) { if (IsUsedInDocument(pDoc, pOILBmp)) { IsUsed = TRUE; break; } // Move onto the next document pDoc = (Document*)GetApplication()->Documents.GetNext(pDoc); } #if !defined(EXCLUDE_FROM_RALPH) // Now check the ClipBoard to see if the Bitmap is in there if (!IsUsed && IsBitmapOnClipBoard(pOILBmp)) { IsUsed = TRUE; //break; } // Should do this but will ERROR2 on exit as the clipboard has no doc components // Should be ok as we now clear out the bitmap lists when the clipboard is cleared /*if (!IsUsed) { Document * pClipDoc = InternalClipboard::Instance(); if (pClipDoc && IsUsedInDocument(pClipDoc, pOILBmp)) { IsUsed = TRUE; } } */ // As we now have two clipboards, we need to check both // Now check the ClipBoard to see if the Bitmap is in there if (!IsUsed) { InternalClipboard::Swap(); // Swap to alternative clipboard if (IsBitmapOnClipBoard(pOILBmp)) { IsUsed = TRUE; // break; } InternalClipboard::Swap(); // Swap back to orignal clipboard } // Should do this but will ERROR2 on exit as the clipboard has no doc components // Should be ok as we now clear out the bitmap lists when the clipboard is cleared /*if (!IsUsed) { Document * pClipDoc = InternalClipboard::Other(); if (pClipDoc && IsUsedInDocument(pClipDoc, pOILBmp)) . { IsUsed = TRUE; } } */ #endif } // Get next item before we delete this item pItem = GetNext(pItem); if (!IsUsed) { delete pOILBmp; // Delete if not used pOILBmp = NULL; } } } /********************************************************************************************** > BOOL GlobalBitmapList::IsBitmapOnClipBoard(OILBitmap* pOILBmp) Author: Will_Cowling (Xara Group Ltd) Created: 14/8/96 Purpose: Check to see if a bitmap is used on the clipboard **********************************************************************************************/ BOOL GlobalBitmapList::IsBitmapOnClipBoard(OILBitmap* pOILBmp) { #if !defined(EXCLUDE_FROM_RALPH) // Clear out any Cached attrs on the Clipboard Node* Subtree = (Node*) InternalClipboard::GetInsertionLayer(); if (!Subtree) return FALSE; Range ClipRange(Subtree->FindFirstChild(), Subtree->FindLastChild(), RangeControl(TRUE,TRUE,TRUE,TRUE)); // Go though all the nodes on the clipboard Node* Current = ClipRange.FindFirst(); while (Current != NULL) { // And search right down each subtree Node* pNodeToCheck = Current->FindFirstDepthFirst(); while (pNodeToCheck != NULL) { // See if this node uses the bitmap INT32 Count = 0; // Does this node have any bitmaps in it ? KernelBitmap* pKernelBmp = pNodeToCheck->EnumerateBitmaps(Count++); while (pKernelBmp != NULL) { // Found a bitmap reference, but ... is it the one we want ? if (pKernelBmp->GetActualBitmap() == pOILBmp) { return TRUE; } // Check whether this bitmap is an XPE master if (pKernelBmp->GetActualBitmap()) { PORTNOTE("other","Removed IXMLDOMDocumentPtr usage") #ifndef EXCLUDE_FROM_XARALX OILBitmap* pMaster = NULL; IXMLDOMDocumentPtr pInfo = NULL; pKernelBmp->GetActualBitmap()->GetXPEInfo(pMaster, pInfo); if (pMaster == pOILBmp) return TRUE; #endif } pKernelBmp = pNodeToCheck->EnumerateBitmaps(Count++); } pNodeToCheck = pNodeToCheck->FindNextDepthFirst(Current); } Current = ClipRange.FindNext(Current); } #endif return FALSE; } /********************************************************************************************** > GreyscaleBitmapList* GlobalBitmapList::GetGreyscaleBitmapList() Author: Will_Cowling (Xara Group Ltd) Created: 14/8/96 Purpose: Get a pointer to the greyscale bitmap list **********************************************************************************************/ //GreyscaleBitmapList* GlobalBitmapList::GetGreyscaleBitmapList() //{ // return &GreyscaleBitmaps; //} #ifdef _DEBUG void GlobalBitmapList::DumpGlobalBitmapListToTrace() { TRACEALL( _T("\nDumping Global bitmap list ...\n\n") ); INT32 TotalSize = 0; INT32 Count = 0; ListItem* pItem = GetHead(); while (pItem != NULL) { OILBitmap* pBmp = (OILBitmap*)pItem; if (pBmp->HasBeenDeleted()) { TRACEALL( _T("OILBitmap @ %x, (Deleted)\n"), pBmp); } else { TRACEALL( _T("OILBitmap @ %x, '%s', Size=%d bytes"), pBmp, (TCHAR*)pBmp->GetName(), pBmp->GetBitmapSize()); if (pBmp->IsGreyscale()) TRACEALL( _T(", (Greyscale)") ); TRACEALL( _T("\n") ); TotalSize += pBmp->GetBitmapSize(); } Count++; pItem = GetNext(pItem); } TRACEALL( _T("\n") ); TRACEALL( _T("Total bitmaps = %d\n"), Count ); TRACEALL( _T("Total size = %d bytes\n\n"), TotalSize ); } #endif #if 0 /********************************************************************************************** > GreyscaleBitmapList::GreyscaleBitmapList() Author: Will_Cowling (Xara Group Ltd) Created: 14/12/94 Inputs: - Outputs: - Returns: - Purpose: GreyscaleBitmapList constructor **********************************************************************************************/ GreyscaleBitmapList::GreyscaleBitmapList() { m_CurrentSize = 0; } /********************************************************************************************** > GreyscaleBitmapList::~GreyscaleBitmapList() Author: Will_Cowling (Xara Group Ltd) Created: 14/12/94 Inputs: - Outputs: - Returns: - Purpose: GreyscaleBitmapList destructor **********************************************************************************************/ GreyscaleBitmapList::~GreyscaleBitmapList() { } /********************************************************************************************** > BOOL GreyscaleBitmapList::Init() Author: Will_Cowling (Xara Group Ltd) Created: 6/2/95 Returns: FALSE if failed. Purpose: Initialise the GreyscaleBitmapList **********************************************************************************************/ BOOL GreyscaleBitmapList::Init() { if (Camelot.DeclareSection("Screen", 1)) { Camelot.DeclarePref( NULL, "MaxGreyscaleCacheSize", (UINT32*)&m_lMaxSize); } GreyscaleBitmapList* pGreyList = GetApplication()->GetGlobalBitmapList()->GetGreyscaleBitmapList(); pGreyList->SetMaxGreyscaleSize(m_lMaxSize); return TRUE; } /********************************************************************************************** > BOOL GreyscaleBitmapList::DeInit() Author: Will_Cowling (Xara Group Ltd) Created: 6/2/95 Returns: FALSE if failed. Purpose: DeInitialise the GreyscaleBitmapList **********************************************************************************************/ BOOL GreyscaleBitmapList::DeInit() { GreyscaleBitmapList* pGreyList = GetApplication()->GetGlobalBitmapList()->GetGreyscaleBitmapList(); ListItem* pItem = pGreyList->GetHead(); while (pItem != NULL) { ListItem* pNext = pGreyList->GetNext(pItem); OILBitmap* pBitmap = (OILBitmap*)pItem; delete pBitmap; // This will remove it from the list before deleting it pItem = pNext; } return TRUE; } /********************************************************************************************** > BOOL GreyscaleBitmapList::AddItem(OILBitmap *Item) Author: Will_Cowling (Xara Group Ltd) Created: 14/12/94 Returns: TRUE Purpose: Adds an item to the tail of the GreyscaleBitmaplist **********************************************************************************************/ BOOL GreyscaleBitmapList::AddItem(OILBitmap *Item) { ERROR3IF(Item == NULL, "Trying to add NULL item to Greyscale Bitmap List"); if (Item == NULL) return FALSE; ERROR2IF(!Item->IsGreyscale(), FALSE, "Trying to add a non-grey bitmap to Greyscale Bitmap List"); // Is this Bitmap already in the list ? LISTPOS pos = FindPosition((ListItem*)Item); if (pos == NOT_IN_LIST || pos == EMPTY_LIST) { // It's not in the list yet, so add it on the end AddTail((ListItem*)Item); TRACEUSER( "Will", _T("Added new Greyscale bitmap to list\n") ); // Check we haven't gone over the maximum size for the list CheckSizeIsOk(); return TRUE; } else { // It's already in the list, so just return return FALSE; } } /********************************************************************************************** > ListItem* GreyscaleBitmapList::RemoveItem(ListItem* Item) Author: Phil_Martin (Xara Group Ltd) Created: 18/03/2004 Returns: TRUE Purpose: Adds an item to the tail of the GreyscaleBitmaplist **********************************************************************************************/ ListItem* GreyscaleBitmapList::RemoveItem(ListItem* Item) { m_CurrentSize -= ((OILBitmap*)Item)->GetBitmapSize(); return List::RemoveItem(Item); } void GreyscaleBitmapList::AddHead(ListItem* Item) { List::AddHead(Item); m_CurrentSize += ((OILBitmap*)Item)->GetBitmapSize(); } void GreyscaleBitmapList::AddTail(ListItem* Item) { List::AddTail(Item); m_CurrentSize += ((OILBitmap*)Item)->GetBitmapSize(); } ListItem* GreyscaleBitmapList::RemoveHead() { ListItem* pItem = List::RemoveHead(); if (pItem) m_CurrentSize -= ((OILBitmap*)pItem)->GetBitmapSize(); return pItem; } ListItem* GreyscaleBitmapList::RemoveTail() { ListItem* pItem = List::RemoveTail(); if (pItem) m_CurrentSize -= ((OILBitmap*)pItem)->GetBitmapSize(); return pItem; } LISTPOS GreyscaleBitmapList::InsertBefore(LISTPOS here, ListItem* item) { ERROR3("Not implemented"); return 0; } ListItem* GreyscaleBitmapList::InsertBefore(ListItem* here, ListItem* item) { ERROR3("Not implemented"); return NULL; } LISTPOS GreyscaleBitmapList::InsertAfter(LISTPOS here, ListItem* item) { ERROR3("Not implemented"); return 0; } ListItem* GreyscaleBitmapList::InsertAfter(ListItem* here, ListItem* item) { ERROR3("Not implemented"); return NULL; } /********************************************************************************************** > INT32 GreyscaleBitmapList::GetCurrentGreyscaleSize() Author: Will_Cowling (Xara Group Ltd) Created: 14/8/96 Purpose: Gets the current total size of the list **********************************************************************************************/ INT32 GreyscaleBitmapList::GetCurrentGreyscaleSize() { /* INT32 CurrentSize = 0; OILBitmap* pItem = (OILBitmap*)GetHead(); while (pItem) { INT32 ItemSize = pItem->GetBitmapSize(); CurrentSize += ItemSize; pItem = (OILBitmap*)GetNext(pItem); } return CurrentSize; */ return m_CurrentSize; } /********************************************************************************************** > void GreyscaleBitmapList::SetMaxGreyscaleSize(INT32 NewMaxSize) Author: Will_Cowling (Xara Group Ltd) Created: 14/8/96 Purpose: Sets the maximum size that the list can grow to **********************************************************************************************/ void GreyscaleBitmapList::SetMaxGreyscaleSize(INT32 NewMaxSize) { if (NewMaxSize < 0) NewMaxSize = 0; if (NewMaxSize > 16*1024*1024) // 16MB should be plenty for a few years NewMaxSize = 16*1024*1024; m_lMaxSize = NewMaxSize; TRACEUSER( "Will", _T("Setting MaxGreyscaleSize to %d bytes\n"), m_lMaxSize ); // And check the list is not bigger than the new size CheckSizeIsOk(); } /********************************************************************************************** > INT32 GreyscaleBitmapList::GetMaxGreyscaleSize() Author: Will_Cowling (Xara Group Ltd) Created: 14/8/96 Purpose: Gets the current maximum size that the list can grow to **********************************************************************************************/ INT32 GreyscaleBitmapList::GetMaxGreyscaleSize() { return m_lMaxSize; } /********************************************************************************************** > void GreyscaleBitmapList::CheckSizeIsOk() Author: Will_Cowling (Xara Group Ltd) Created: 14/8/96 Purpose: Ensures the list is smaller than the max list size, and throws away bitmaps from the start of the list if not **********************************************************************************************/ void GreyscaleBitmapList::CheckSizeIsOk() { INT32 CurrentSize = GetCurrentGreyscaleSize(); INT32 MaxSize = GetMaxGreyscaleSize(); TRACEUSER( "Will", _T("CheckSizeIsOk, current size is %d bytes, max is %d bytes\n"), CurrentSize, MaxSize ); if (CurrentSize > MaxSize) { // How many bytes do we need to remove ? INT32 SizeToRemove = CurrentSize - MaxSize; INT32 SizeRemoved = 0; TRACEUSER( "Will", _T("Trying to remove %d bytes from greyscale list\n"), SizeToRemove ); OILBitmap* pItem = (OILBitmap*)GetHead(); if (pItem == NULL) return; while (pItem && (SizeRemoved < SizeToRemove)) { OILBitmap* pNextItem = (OILBitmap*)GetNext(pItem); INT32 ItemSize = pItem->GetBitmapSize(); // Remove it from this list RemoveItem(pItem); // and delete it delete pItem; SizeRemoved += ItemSize; pItem = pNextItem; } TRACEUSER( "Will", _T("New size is %d bytes\n"), CurrentSize - SizeRemoved ); ERROR3IF(SizeRemoved < SizeToRemove, "Couldn't free enough memory in Greyscale list"); } } #ifdef _DEBUG void GreyscaleBitmapList::DumpGreyscaleBitmapListToTrace() { TRACEALL( _T("\nDumping Greyscale bitmap list ...\n\n") ); INT32 TotalSize = 0; INT32 Count = 0; ListItem* pItem = GetHead(); while (pItem != NULL) { OILBitmap* pBmp = (OILBitmap*)pItem; TRACEALL( _T("Grey bitmap @ %x, '%s', Size=%d bytes\n"), pBmp, (TCHAR*)pBmp->GetName(), pBmp->GetBitmapSize()); TotalSize += pBmp->GetBitmapSize(); Count++; pItem = GetNext(pItem); } TRACEALL( _T("\n")); TRACEALL( _T("Total bitmaps = %d\n"), Count); TRACEALL( _T("Total size = %d bytes\n"), TotalSize); TRACEALL( _T("Max size = %d bytes\n\n"), GetMaxGreyscaleSize()); } #endif #endif // 0 #if !defined(EXCLUDE_FROM_RALPH) //----------------------------------------------------------------------------------------------- // OpDeleteBitmap - Delete all references to a bitmap, and remove it from memory /******************************************************************************************** > BOOL OpDeleteBitmap::Init() Author: Will_Cowling (Xara Group Ltd) Created: 16/2/95 Returns: TRUE if the operation could be successfully initialised FALSE if no more memory could be allocated Purpose: OpDeleteBitmap initialiser method Errors: ERROR will be called if there was insufficient memory to allocate the operation. SeeAlso: - ********************************************************************************************/ BOOL OpDeleteBitmap::Init() { return (RegisterOpDescriptor( 0, 0, CC_RUNTIME_CLASS(OpDeleteBitmap), OPTOKEN_DELETEBITMAP, OpDeleteBitmap::GetState, 0, /* help ID */ 0, 0 /* bitmap ID */)); } /******************************************************************************************** > OpState OpDeleteBitmap::GetState(String_256*, OpDescriptor*) Author: Will_Cowling (Xara Group Ltd) Created: 16/2/95 Returns: The state of the OpDeleteBitmap operation Purpose: For finding the OpDeleteBitmap's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpDeleteBitmap::GetState(String_256* UIDescription, OpDescriptor*) { OpState OpSt; return(OpSt); } /******************************************************************************************** > void OpDeleteBitmap::DoDelete(OILBitmap* BmpToDelete) Author: Will_Cowling (Xara Group Ltd) Created: 16/2/95 Inputs: pOpParam: Param1 contains a pointer to the OILBitmap to delete. Purpose: Frees the memory used by a bitmap Errors: - SeeAlso: - ********************************************************************************************/ void OpDeleteBitmap::DoDelete(OILBitmap* pBmpToDelete) { // Declared up 'ere, 'cus of the goto thingy Document* Doc; OILBitmap* poBmp = NULL; // Set the busy cursor . . . String_64 StatusText = String_64(_R(IDS_K_BMPLIST_DELBMPOPEN)); StatusText += pBmpToDelete->GetName(); StatusText += String_64(_R(IDS_K_BMPLIST_DELBMPCLOSE)); BeginSlowJob(-1, FALSE, &StatusText); // Remember the current document Document* pCurrent = Document::GetCurrent(); ObjChangeFlags cFlags; cFlags.TransformNode = TRUE; // The node is going to be changed to point at a // different bitmap, which is a Bit like transforming // it I suppose ? cFlags.Attribute = TRUE; // Needed to make Blends re-calc themselves ObjChangeParam ObjChange(OBJCHANGE_STARTING,cFlags,NULL,NULL); // Don't do anything if the bitmap is NULL, or if it's the default bitmap if (pBmpToDelete == NULL || pBmpToDelete == OILBitmap::Default) goto EndOperation; ERROR3IF(pBmpToDelete->HasBeenDeleted(), "This bitmap has been deleted already !"); // ------------------------------------------------------------- // If this bitmap is an XPE master bitmap then we must unlink poBmp = (OILBitmap*) GetApplication()->GetGlobalBitmapList()->GetHead(); while (poBmp) { if (poBmp->m_pMasterBitmap == pBmpToDelete) { poBmp->RebuildXPEBitmap(); // Ensure that we have a generated bitmap poBmp->DestroyXPEInfo(); // Unlink this bitmap from the master being deleted } poBmp = (OILBitmap*) GetApplication()->GetGlobalBitmapList()->GetNext(poBmp); } // ------------------------------------------------------------- // Go though all the documents Doc = (Document*)GetApplication()->Documents.GetHead(); while (Doc != NULL) { // Set the document to be current, because the bitmap system needs this // so it knows which bitmap list to look at. Doc->SetCurrent(); // First we look at the doc component bitmap list to see if the bitmap // we deleted is in there somewhere BOOL BitmapIsInList = FALSE; BitmapList* pBitmaps = Doc->GetBitmapList(); if (pBitmaps != NULL) { KernelBitmap* pBitmap = (KernelBitmap*)pBitmaps->GetHead(); while (pBitmap) { if (pBitmap->GetActualBitmap() == pBmpToDelete) { // We've found the bitmap, so flag thaat we need to // scan the tree BitmapIsInList = TRUE; break; } pBitmap = (KernelBitmap*)pBitmaps->GetNext(pBitmap); } } if (BitmapIsInList) { // If the bitmap was found in the list somewhere, then we need to scan // though the document tree, and make sure we redraw any nodes that // use the bitmap BOOL DocModified = FALSE; // Scan the document's tree for bitmap references Node* pNode = Node::DocFindFirstDepthFirst(Doc); while (pNode != NULL) { // Ignore hidden nodes if (!pNode->IsNodeHidden()) { INT32 Count = 0; // Does this node have any bitmaps in it ? KernelBitmap* pBitmap = pNode->EnumerateBitmaps(Count++); while (pBitmap != NULL) { // Found a bitmap reference, but ... is it the one that we deleted ? if (pBitmap->GetActualBitmap() == pBmpToDelete) { // pBmpToDelete is being deleted, so we MUST reset any bitmapref // that references it to the default (otherwise we still reference the // deleted bitmap) .... if (IS_A (pNode, NodeBitmap)) { // i'm only willing to do this for NodeBitmaps! Not sure about // any other type of node that overides the EnumerateBitmaps function // (they look scary). NodeBitmap* pBitmap = (NodeBitmap*) pNode; pBitmap->GetBitmapRef ()->SetBitmap (pBitmaps->FindDefaultBitmap()); } // Make sure the node is redrawn ForceRedrawOfNode(Doc, pNode, &ObjChange); DocModified = TRUE; } pBitmap = pNode->EnumerateBitmaps(Count++); } } // Move onto the next node in the tree pNode = pNode->DocFindNextDepthFirst(); } if (DocModified) { // Flag that the document has changed Doc->SetModified(TRUE); } } // Move onto the next document Doc = (Document*)GetApplication()->Documents.GetNext(Doc); } // Now delete the bitmap data pBmpToDelete->DeleteData(); // and make sure all the bitmap list are updated ... // (this needs to be done after the bitmap data is deleted) Doc = (Document*)GetApplication()->Documents.GetHead(); while (Doc != NULL) { BROADCAST_TO_ALL(BitmapListChangedMsg(Doc->GetBitmapList())); Doc = (Document*)GetApplication()->Documents.GetNext(Doc); } // Restore the current document if (pCurrent) pCurrent->SetCurrent(); EndOperation: ObjChange.Define(OBJCHANGE_FINISHED,cFlags,NULL,NULL); UpdateAllChangedNodes(&ObjChange); EndSlowJob(); End(); } /******************************************************************************************** > void OpDeleteBitmap::ForceRedrawOfNode(Document* Doc, Node* pNodeToRedraw, ObjChangeParam* pObjChange) Author: Will_Cowling (Xara Group Ltd) Created: 27/6/95 Inputs: - Purpose: - Errors: - SeeAlso: - ********************************************************************************************/ void OpDeleteBitmap::ForceRedrawOfNode(Document* Doc, Node* pNodeToRedraw, ObjChangeParam* pObjChange) { /*BOOL Allowed =*/ pNodeToRedraw->AllowOp(pObjChange); // Ignore the Allowed state, do it regardless ... // Force a redraw on the object and it's parent. Node* pParent = pNodeToRedraw; Spread* pSpread = pNodeToRedraw->FindParentSpread(); while (pSpread != NULL && pParent != NULL) { Node* pPrevParent = pParent->FindParent(); if (pPrevParent && pPrevParent->IsLayer()) { DocRect Bounds = ((NodeRenderableBounded*)pParent)->GetBoundingRect(); Doc->ForceRedraw(pSpread, Bounds, FALSE, pParent); } pParent = pPrevParent; } } #endif