00001 // $Id: bitmapcache.cpp 1282 2006-06-09 09:46:49Z alex $ 00002 // BitmapCache.cpp: implementation of the CBitmapCache class. 00003 // 00005 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00006 ================================XARAHEADERSTART=========================== 00007 00008 Xara LX, a vector drawing and manipulation program. 00009 Copyright (C) 1993-2006 Xara Group Ltd. 00010 Copyright on certain contributions may be held in joint with their 00011 respective authors. See AUTHORS file for details. 00012 00013 LICENSE TO USE AND MODIFY SOFTWARE 00014 ---------------------------------- 00015 00016 This file is part of Xara LX. 00017 00018 Xara LX is free software; you can redistribute it and/or modify it 00019 under the terms of the GNU General Public License version 2 as published 00020 by the Free Software Foundation. 00021 00022 Xara LX and its component source files are distributed in the hope 00023 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00024 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00025 See the GNU General Public License for more details. 00026 00027 You should have received a copy of the GNU General Public License along 00028 with Xara LX (see the file GPL in the root directory of the 00029 distribution); if not, write to the Free Software Foundation, Inc., 51 00030 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00031 00032 00033 ADDITIONAL RIGHTS 00034 ----------------- 00035 00036 Conditional upon your continuing compliance with the GNU General Public 00037 License described above, Xara Group Ltd grants to you certain additional 00038 rights. 00039 00040 The additional rights are to use, modify, and distribute the software 00041 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00042 library and any other such library that any version of Xara LX relased 00043 by Xara Group Ltd requires in order to compile and execute, including 00044 the static linking of that library to XaraLX. In the case of the 00045 "CDraw" library, you may satisfy obligation under the GNU General Public 00046 License to provide source code by providing a binary copy of the library 00047 concerned and a copy of the license accompanying it. 00048 00049 Nothing in this section restricts any of the rights you have under 00050 the GNU General Public License. 00051 00052 00053 SCOPE OF LICENSE 00054 ---------------- 00055 00056 This license applies to this program (XaraLX) and its constituent source 00057 files only, and does not necessarily apply to other Xara products which may 00058 in part share the same code base, and are subject to their own licensing 00059 terms. 00060 00061 This license does not apply to files in the wxXtra directory, which 00062 are built into a separate library, and are subject to the wxWindows 00063 license contained within that directory in the file "WXXTRA-LICENSE". 00064 00065 This license does not apply to the binary libraries (if any) within 00066 the "libs" directory, which are subject to a separate license contained 00067 within that directory in the file "LIBS-LICENSE". 00068 00069 00070 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00071 ---------------------------------------------- 00072 00073 Subject to the terms of the GNU Public License (see above), you are 00074 free to do whatever you like with your modifications. However, you may 00075 (at your option) wish contribute them to Xara's source tree. You can 00076 find details of how to do this at: 00077 http://www.xaraxtreme.org/developers/ 00078 00079 Prior to contributing your modifications, you will need to complete our 00080 contributor agreement. This can be found at: 00081 http://www.xaraxtreme.org/developers/contribute/ 00082 00083 Please note that Xara will not accept modifications which modify any of 00084 the text between the start and end of this header (marked 00085 XARAHEADERSTART and XARAHEADEREND). 00086 00087 00088 MARKS 00089 ----- 00090 00091 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00092 designs are registered or unregistered trademarks, design-marks, and/or 00093 service marks of Xara Group Ltd. All rights in these marks are reserved. 00094 00095 00096 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00097 http://www.xara.com/ 00098 00099 =================================XARAHEADEREND============================ 00100 */ 00101 00102 #include "camtypes.h" 00103 00104 //#include "bitmapcache.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00105 00106 /********************************************************************************************* 00107 00108 Preference: Percentage of RAM devoted to cache 00109 Section: Cacheing 00110 Range: 0 - 100 (although greater values are acceptable) 00111 Purpose: How much RAM to devote to cacheing bitmaps 00112 SeeAlso: - 00113 00114 **********************************************************************************************/ 00115 INT32 CBitmapCache::CacheRAMPercent = 25; // 25% of free RAM or 25% of half total RAM 00116 00117 00118 UINT32 AFXAPI HashKey(const CBitmapCacheKey& key) 00119 { 00120 return key.Hash(); 00121 } 00122 00123 00124 00125 00127 // Construction/Destruction 00129 00130 CBitmapCache::CBitmapCache() 00131 { 00132 m_lMaxDataSize = 0; 00133 m_lCurrentDataSize = 0; 00134 m_lMaxHashTableLoad = 0; 00135 } 00136 00137 00138 00139 00140 /******************************************************************************************** 00141 00142 > UINT32 CBitmapCache::Initialise() 00143 00144 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00145 Created: 11/06/2004 00146 Inputs: - 00147 Outputs: - 00148 Returns: - 00149 Purpose: - 00150 Errors: - 00151 SeeAlso: - 00152 00153 ********************************************************************************************/ 00154 void CBitmapCache::Initialise() 00155 { 00156 // Declare the section that the magnetic options will live in 00157 BOOL Worked = Camelot.DeclareSection(TEXT("Cache"), 2); 00158 00159 // declare the 2 prefs that there are 00160 if (Worked) Camelot.DeclarePref(TEXT("Cache"), TEXT("CacheRAMPercent"), &CacheRAMPercent, 0, 200); 00161 00162 // Set up the default maximum cache size 00163 m_lMaxDataSize = CalcRecommendedMaximumDataSize(); 00164 TRACEUSER( "Phil", _T("Recommended Cache Size = %I64d\n"), m_lMaxDataSize); 00165 00166 // Make the hash table big enough for however many average 80*80*32BPP pixel bitmaps 00167 // will fit into the configured maximum cache size. Make the hash table twice that size 00168 // to keep it sparse and thus running more efficiently and ensure that it's prime. 00169 m_lMaxHashTableLoad = (UINT32) m_lMaxDataSize/(80*80*4); 00170 // InitHashTable(PrimeAbove(m_lMaxHashTableLoad*2), TRUE); 00171 } 00172 00173 00174 00175 00176 /******************************************************************************************** 00177 00178 > void CBitmapCache::DeInitialise() 00179 00180 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00181 Created: 18/06/2004 00182 Inputs: - 00183 Outputs: - 00184 Returns: - 00185 Purpose: - 00186 Errors: - 00187 SeeAlso: - 00188 00189 ********************************************************************************************/ 00190 void CBitmapCache::DeInitialise() 00191 { 00192 // Get rid of all cached bitmaps... 00193 /* POSITION pos = GetStartPosition(); 00194 while (pos) 00195 { 00196 CBitmapCacheKey key; 00197 CCachedBitmap bitmap; 00198 GetNextAssoc(pos, key, bitmap); 00199 00200 RemoveKey(key); 00201 m_lCurrentDataSize -= bitmap.GetBitmapSize(); 00202 FreeDIB(bitmap.pbmpInfo, bitmap.pbmpBits); 00203 } 00204 */ CCacheKeyMap::iterator pos; 00205 for ( pos=m_map.begin() ; pos!=m_map.end() ; pos++ ) 00206 { 00207 CBitmapCacheKey key = pos->first; 00208 CCachedBitmap bitmap = pos->second; 00209 // m_map.erase(key); 00210 m_lCurrentDataSize -= bitmap.GetBitmapSize(); 00211 FreeDIB(bitmap.pbmpInfo, bitmap.pbmpBits); 00212 } 00213 m_map.clear(); 00214 } 00215 00216 00217 00218 00219 /******************************************************************************************** 00220 00221 > void CBitmapCache::RemoveLowPriorityBitmaps(const INT32 maxpriority = CACHEPRIORITY_TEMPBITMAP_HIGH) 00222 00223 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00224 Created: 15/09/2004 00225 Inputs: - 00226 Outputs: - 00227 Returns: - 00228 Purpose: - 00229 Errors: - 00230 SeeAlso: - 00231 00232 ********************************************************************************************/ 00233 void CBitmapCache::RemoveLowPriorityBitmaps(const INT32 maxpriority) 00234 { 00235 // Get rid of all cached bitmaps... 00236 /* POSITION pos = GetStartPosition(); 00237 while (pos) 00238 { 00239 CBitmapCacheKey key; 00240 CCachedBitmap bitmap; 00241 GetNextAssoc(pos, key, bitmap); 00242 00243 if (bitmap.nPriority <= maxpriority) 00244 { 00245 RemoveKey(key); 00246 m_lCurrentDataSize -= bitmap.GetBitmapSize(); 00247 FreeDIB(bitmap.pbmpInfo, bitmap.pbmpBits); 00248 } 00249 } 00250 */ CCacheKeyMap::iterator pos; 00251 for ( pos=m_map.begin() ; pos!=m_map.end() ; ) 00252 { 00253 CBitmapCacheKey key = pos->first; 00254 CCachedBitmap bitmap = pos->second; 00255 pos++; 00256 if (bitmap.nPriority <= maxpriority) 00257 { 00258 m_map.erase(key); 00259 m_lCurrentDataSize -= bitmap.GetBitmapSize(); 00260 FreeDIB(bitmap.pbmpInfo, bitmap.pbmpBits); 00261 } 00262 } 00263 } 00264 00265 00266 00267 00268 /******************************************************************************************** 00269 00270 > UINT32 CBitmapCache::StoreBitmap() 00271 00272 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00273 Created: 11/06/2004 00274 Inputs: key 00275 Bitmap 00276 Outputs: - 00277 Returns: - 00278 Purpose: Places a bitmap in the cache (making room if necessary by removing others) 00279 Errors: - 00280 SeeAlso: - 00281 00282 ********************************************************************************************/ 00283 void CBitmapCache::StoreBitmap(const CBitmapCacheKey& key, const CCachedBitmap& bitmap) 00284 { 00285 /* 00286 #if _DEBUG 00287 if ((UINT32)m_nCount >= m_lMaxHashTableLoad) 00288 { 00289 TRACE( _T("BitmapCache hash table moving into inefficient zone!\n")); 00290 // ERROR3("BitmapCache hash table moving into inefficient zone\n"); 00291 } 00292 #endif 00293 */ 00294 // ENSURE(bitmap.rectCachedRect.IsValid(), "Invalid rect in CBitmapCache::StoreBitmap"); 00295 ENSURE(bitmap.pbmpInfo->bmiHeader.biCompression==BI_RGB || bitmap.pbmpInfo->bmiHeader.biCompression==0x80000001, 00296 "Invalid compression type in StoreBitmap"); 00297 00298 // Remove the previous entry for this key, if there was one... 00299 CCachedBitmap cbmp = RemoveBitmap(key); // Watch out - doesn't release bitmap memory! 00300 if (bitmap.pbmpBits!=cbmp.pbmpBits && bitmap.pbmpInfo!=cbmp.pbmpInfo) // Only release the bitmap if we're not still using it 00301 cbmp.Release(); // But this does! 00302 00303 UINT32 newitemsize = bitmap.GetBitmapSize(); 00304 UINT32 priority = bitmap.nPriority; 00305 while ((UINT64)(m_lCurrentDataSize+newitemsize) > m_lMaxDataSize) 00306 { 00307 CCachedBitmap cbmp = RemoveRandomBitmap(priority); // Remove random bitmap from cache 00308 if (cbmp.IsValid()) 00309 { 00310 ERROR3IF(bitmap.pbmpInfo==cbmp.pbmpInfo || bitmap.pbmpBits==cbmp.pbmpBits, 00311 "RemoveRandomBitmap found the same bitmap we're trying to Store! Something's gone horribly wrong!\n"); 00312 TRACE( _T("Removing bitmap to make room in cache!\n") ); 00313 cbmp.Release(); 00314 } 00315 else 00316 { 00317 // We have run out of room in the cache for this priority level 00318 TRACEUSER( "Phil", _T("Changing priority to make room in cache\n")); 00319 if (priority < CACHEPRIORITY_TEMPBITMAP_HIGH) 00320 { 00321 // We can try to remove higher-priority temp bitmaps... 00322 // (But not the very highest, permanent bitmaps...) 00323 priority = CACHEPRIORITY_TEMPBITMAP_HIGH; 00324 } 00325 else 00326 { 00327 // We have no more room to remove any temporary bitmaps 00328 // ARGH!!!! Now what? 00329 ERROR3("Bitmap Cache is full!"); 00330 break; // Just gobble up the user's memory! 00331 } 00332 } 00333 } 00334 00335 m_lCurrentDataSize += newitemsize; 00336 // SetAt(key, (CCachedBitmap)bitmap); 00337 m_map.insert(pair<CBitmapCacheKey, CCachedBitmap>(key,(CCachedBitmap)bitmap)); 00338 } 00339 00340 00341 00342 00343 /******************************************************************************************** 00344 00345 > CCachedBitmap CBitmapCache::RemoveBitmap(const CBitmapCacheKey& key) 00346 00347 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00348 Created: 11/06/2004 00349 Inputs: key 00350 Outputs: - 00351 Returns: Pointer to bitmap or NULL if not found 00352 Purpose: Removes either the specified bitmap from the cache or a selected bitmap 00353 according to the removal policy 00354 NOTE! It's up to the caller to delete the bitmap returned!!! 00355 Errors: - 00356 SeeAlso: - 00357 00358 ********************************************************************************************/ 00359 CCachedBitmap CBitmapCache::RemoveBitmap(const CBitmapCacheKey& key) 00360 { 00361 CCachedBitmap bitmap; 00362 00363 if (m_map.size()==0) 00364 return bitmap; 00365 00366 if (key.IsValid()) 00367 { 00368 // Then we must remove the specified bitmap from the cache 00369 if (Lookup(key, bitmap)) 00370 { 00371 m_lCurrentDataSize -= bitmap.GetBitmapSize(); 00372 m_map.erase(key); 00373 // RemoveKey(key); 00374 } 00375 } 00376 00377 return bitmap; 00378 } 00379 00380 00381 00382 00383 /******************************************************************************************** 00384 00385 > CCachedBitmap CBitmapCache::RemoveRandomBitmap(const INT32 maxpriority = CACHEPRIORITY_TEMPBITMAP_HIGH) 00386 00387 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00388 Created: 11/06/2004 00389 Inputs: key 00390 Outputs: - 00391 Returns: Pointer to bitmap or NULL if not found 00392 Purpose: Removes either the specified bitmap from the cache or a selected bitmap 00393 according to the removal policy 00394 NOTE! It's up to the caller to delete the bitmap returned!!! 00395 NOTE! This routine only uses the primary association array of the hash table 00396 The chains of values stored in the same slot are ignored at first 00397 (but obviously will be considered later on if their head item 00398 has been removed) 00399 Errors: - 00400 SeeAlso: - 00401 00402 ********************************************************************************************/ 00403 CCachedBitmap CBitmapCache::RemoveRandomBitmap(const INT32 maxpriority) 00404 { 00405 // ENSURE(m_nHashTableSize!=0, "Zero-sized hash table found in RemoveRandomBitmap\n"); 00406 /* 00407 // Implement cache removal policy - remove a random bitmap 00408 // 00409 // Select a bitmap of our choosing for removal 00410 // The removal policy is random (ish) 00411 // Must be Order(0) complexity 00412 // 00413 CCachedBitmap bitmap; 00414 00415 00416 UINT32 startitem = rand() % m_nHashTableSize; 00417 UINT32 item = startitem; 00418 CAssoc* pAssoc = NULL; 00419 do 00420 { 00421 pAssoc = m_pHashTable[item]; 00422 item++; 00423 if (item==m_nHashTableSize) 00424 item = 0; 00425 00426 // If we have found a value, check whether it's of equal or lesser "value" 00427 // than the one we're trying to store before throwing it out... 00428 if (pAssoc) 00429 { 00430 // bitmap = (CCachedBitmap)pAssoc->value; // Get value in a form we can use 00431 if (((CCachedBitmap)pAssoc->value).nPriority <= maxpriority) // Check whether value's priority is <= priority limit 00432 break; // If so, we'll get rid of this one 00433 else 00434 pAssoc = NULL; 00435 } 00436 } 00437 while (item != startitem); 00438 00439 if (pAssoc) 00440 { 00441 // Remove the bitmap that we found from the cache... 00442 bitmap = (CCachedBitmap)pAssoc->value; 00443 m_lCurrentDataSize -= bitmap.GetBitmapSize(); 00444 RemoveKey(pAssoc->key); 00445 } 00446 00447 return bitmap; 00448 */ 00449 // Implement cache removal policy - remove a random bitmap 00450 // 00451 // Select a bitmap of our choosing for removal 00452 // The removal policy is random (ish) 00453 // Must be Order(0) complexity 00454 // 00455 // Pick a random start point iterate 00456 // through the map from there... 00457 // 00458 srand((unsigned)time(NULL)); 00459 UINT32 item = rand()%(UINT32)m_map.size(); 00460 CCacheKeyMap::iterator pos; 00461 for ( pos=m_map.begin() ; item-- ; pos++ ) 00462 ; 00463 CCacheKeyMap::iterator spos = pos; 00464 do 00465 { 00466 if ( pos==m_map.end() ) 00467 pos = m_map.begin() ; 00468 CBitmapCacheKey key = pos->first; 00469 CCachedBitmap bitmap = pos->second; 00470 if ( bitmap.nPriority<=maxpriority ) // Check whether value's priority is <= priority limit 00471 { 00472 m_lCurrentDataSize -= bitmap.GetBitmapSize(); 00473 m_map.erase(key); 00474 return bitmap; 00475 } 00476 pos++; 00477 } while ( pos!=spos ); 00478 return m_map.begin()->second; 00479 } 00480 00481 00482 00483 00484 /******************************************************************************************** 00485 00486 > BOOL CBitmapCache::RemoveAllOwnedBitmaps(const CBitmapCacheKey& key, 00487 const BOOL bOpaqueOnly, 00488 const INT32 maxpriority = CACHEPRIORITY_TEMPBITMAP_HIGH) 00489 00490 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00491 Created: 11/06/2004 00492 Inputs: key 00493 Outputs: - 00494 Returns: TRUE if removed one or more bitmap associated with the owner of this key 00495 FALSE otherwise 00496 Purpose: Removes all bitmaps from the cache that have the owner specified in the 00497 key... 00498 Errors: - 00499 SeeAlso: - 00500 00501 ********************************************************************************************/ 00502 BOOL CBitmapCache::RemoveAllOwnedBitmaps(const CBitmapCacheKey& key, 00503 const BOOL bOpaqueOnly, 00504 const INT32 maxpriority) 00505 { 00506 BOOL bRemovedSome = FALSE; 00507 CCachedBitmap abitmap; 00508 00509 if (!key.IsValid()) 00510 return FALSE; 00511 00512 if (m_map.size()==0) 00513 return FALSE; 00514 00515 // Use the owner information stored in the keys to find all bitmap entries 00516 // in the hash table with the same owner... 00517 /* POSITION pos = GetStartPosition(); 00518 while (pos) 00519 { 00520 CBitmapCacheKey akey; 00521 GetNextAssoc(pos, akey, abitmap); 00522 00523 if (akey.pOwner == key.pOwner && abitmap.nPriority <= maxpriority) 00524 { 00525 if (bOpaqueOnly==FALSE || !abitmap.IsTransparent()) 00526 { 00527 RemoveKey(akey); 00528 m_lCurrentDataSize -= abitmap.GetBitmapSize(); 00529 FreeDIB(abitmap.pbmpInfo, abitmap.pbmpBits); 00530 bRemovedSome = TRUE; 00531 } 00532 } 00533 } 00534 */ CCacheKeyMap::iterator pos; 00535 for ( pos=m_map.begin() ; pos!=m_map.end() ; ) 00536 { 00537 CBitmapCacheKey akey = pos->first; 00538 CCachedBitmap abitmap = pos->second; 00539 pos++; 00540 if (akey.pOwner == key.pOwner && abitmap.nPriority <= maxpriority) 00541 { 00542 if (bOpaqueOnly==FALSE || !abitmap.IsTransparent()) 00543 { 00544 m_map.erase(akey); 00545 m_lCurrentDataSize -= abitmap.GetBitmapSize(); 00546 FreeDIB(abitmap.pbmpInfo, abitmap.pbmpBits); 00547 bRemovedSome = TRUE; 00548 } 00549 } 00550 } 00551 00552 return bRemovedSome; 00553 } 00554 00555 00556 00557 00558 /******************************************************************************************** 00559 00560 > CCachedBitmap CBitmapCache::FindNextOwnedBitmap(POSITION& pos, 00561 CBitmapCacheKey& key, 00562 const BOOL bOpaqueOnly, 00563 const INT32 maxpriority = CACHEPRIORITY_TEMPBITMAP_HIGH) 00564 00565 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00566 Created: 11/06/2004 00567 Inputs: key 00568 Outputs: - 00569 Returns: TRUE is removed one or more bitmap associated with the owner of this key 00570 FALSE otherwise 00571 Purpose: Removes all bitmaps from the cache that have the owner specified in the 00572 key... 00573 Errors: - 00574 SeeAlso: - 00575 00576 ********************************************************************************************/ 00577 CCachedBitmap CBitmapCache::FindNextOwnedBitmap(CCacheKeyMap::iterator &pos, 00578 CBitmapCacheKey& key, 00579 const BOOL bOpaqueOnly, 00580 const INT32 maxpriority) 00581 { 00582 // BOOL bRemovedSome = FALSE; 00583 CCachedBitmap abitmap; 00584 00585 if (!key.IsValid()) 00586 return abitmap; 00587 00588 if (m_map.size()==0) 00589 return abitmap; 00590 00591 // Use the owner information stored in the keys to find all bitmap entries 00592 // in the hash table with the same owner... 00593 /* while (pos) 00594 { 00595 CBitmapCacheKey akey; 00596 GetNextAssoc(pos, akey, abitmap); 00597 00598 if (akey.pOwner == key.pOwner && abitmap.nPriority <= maxpriority) 00599 { 00600 if (bOpaqueOnly==FALSE || !abitmap.IsTransparent()) 00601 { 00602 key = akey; // Return the key we found 00603 return abitmap; // along with the bitmap we found 00604 } 00605 } 00606 } 00607 */ 00608 while (pos!=m_map.end()) 00609 { 00610 CBitmapCacheKey akey = pos->first; 00611 CCachedBitmap abitmap = pos->second; 00612 pos++; 00613 if (akey.pOwner == key.pOwner && abitmap.nPriority <= maxpriority) 00614 { 00615 if (bOpaqueOnly==FALSE || !abitmap.IsTransparent()) 00616 { 00617 key = akey; // Return the key we found 00618 return abitmap; // along with the bitmap we found 00619 } 00620 } 00621 } 00622 00623 return CCachedBitmap(); 00624 } 00625 00626 00627 00628 00629 /******************************************************************************************** 00630 00631 > void CBitmapCache::SetMaximumDataSize(UINT64 maxsize) 00632 00633 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00634 Created: 11/06/2004 00635 Inputs: - 00636 Outputs: - 00637 Returns: - 00638 Purpose: - 00639 Errors: - 00640 SeeAlso: - 00641 00642 ********************************************************************************************/ 00643 void CBitmapCache::SetMaximumDataSize(UINT64 maxsize) 00644 { 00645 m_lMaxDataSize = maxsize; 00646 } 00647 00648 00649 00650 00651 /******************************************************************************************** 00652 00653 > UINT64 CBitmapCache::GetMaximumDataSize() 00654 00655 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00656 Created: 11/06/2004 00657 Inputs: - 00658 Outputs: - 00659 Returns: - 00660 Purpose: - 00661 Errors: - 00662 SeeAlso: - 00663 00664 ********************************************************************************************/ 00665 UINT64 CBitmapCache::GetMaximumDataSize() 00666 { 00667 return m_lMaxDataSize; 00668 } 00669 00670 00671 00672 00673 /******************************************************************************************** 00674 00675 > UINT32 CBitmapCache::GetCurrentDataSize() 00676 00677 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00678 Created: 11/06/2004 00679 Inputs: - 00680 Outputs: - 00681 Returns: - 00682 Purpose: - 00683 Errors: - 00684 SeeAlso: - 00685 00686 ********************************************************************************************/ 00687 UINT32 CBitmapCache::GetCurrentDataSize() 00688 { 00689 return m_lCurrentDataSize; 00690 } 00691 00692 00693 00694 00695 /******************************************************************************************** 00696 00697 > UINT64 CBitmapCache::CalcRecommendedMaximumDataSize() 00698 00699 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00700 Created: 11/06/2004 00701 Inputs: - 00702 Outputs: - 00703 Returns: Recommended max cache size in current memory environment 00704 Purpose: Work out how much RAM this machine can afford to devote 00705 to the bitmap cache. 00706 Never use more than 50% of physical RAM 00707 Never use more RAM than is free 00708 Use CachRAMPercent preference to decide percentage of free ram to grab 00709 Errors: - 00710 SeeAlso: - 00711 00712 ********************************************************************************************/ 00713 UINT64 CBitmapCache::CalcRecommendedMaximumDataSize() 00714 { 00715 UINT64 ullPhysRAM = 0; 00716 UINT32 LoadPercentage = 0; 00717 00718 GetMemoryStatus(&ullPhysRAM, &LoadPercentage); 00719 00720 // Don't use more than 50% of physical ram in the Bitmap Cache 00721 if (LoadPercentage<50) LoadPercentage = 50; // If <50% in use pretend that 50% is used (never use more than 50%) 00722 return ullPhysRAM * (100-LoadPercentage) * CacheRAMPercent / 10000; 00723 } 00724 00725 00726 00727 00728 /******************************************************************************************** 00729 00730 > UINT32 CBitmapCache::PrimeAbove(UINT32 number) 00731 00732 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> (from the Internet) 00733 Created: 11/06/2004 00734 Inputs: number to start from 00735 Outputs: - 00736 Returns: prime number above the starting value 00737 Purpose: Computes the first prime number equal to or greater than a specified number. 00738 Errors: - 00739 SeeAlso: - 00740 00741 ********************************************************************************************/ 00742 /* 00743 UINT32 CBitmapCache::PrimeAbove(UINT32 number) 00744 { 00745 if (number < 4) return (number) ; // 0, 1, 2, and 3 are prime. 00746 if ((number % 2) == 0) number++ ; // Prime must be odd. 00747 00748 for ( ; ; ) 00749 { 00750 // Check for possible divisors. The "divisor > dividend" test is similar 00751 // to checking 2 .. sqrt(N) as possible divisors, but avoids the need for 00752 // linking to the math library. 00753 00754 for ( UINT32 divisor = 3 ; ; divisor+=2 ) 00755 { 00756 if ((number % divisor) == 0) 00757 break ; // Not prime - divisor found. 00758 if (divisor > (number / divisor)) 00759 return number ; // Prime - no divisors found. 00760 } 00761 00762 number += 2 ; // Check next odd number. 00763 } 00764 } 00765 */ 00766 00767 00768 00769 #ifdef _DEBUG 00770 /******************************************************************************************** 00771 00772 > void CBitmapCache::DebugDump() 00773 00774 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00775 Created: 02/11/2004 00776 Inputs: - 00777 Outputs: - 00778 Returns: - 00779 Purpose: - 00780 Errors: - 00781 SeeAlso: - 00782 00783 ********************************************************************************************/ 00784 void CBitmapCache::DebugDump() 00785 { 00786 TRACE( _T("Contents of Bitmap Cache:\n")); 00787 /* POSITION pos = GetStartPosition(); 00788 while (pos) 00789 { 00790 CBitmapCacheKey key; 00791 CCachedBitmap bitmap; 00792 GetNextAssoc(pos, key, bitmap); 00793 00794 TRACE( _T("Bitmap: %x (%d*%d, %d) Priority: %d Owner: %x %d %s\n"), 00795 bitmap.pbmpInfo, 00796 bitmap.pbmpInfo->bmiHeader.biWidth, 00797 bitmap.pbmpInfo->bmiHeader.biHeight, 00798 bitmap.GetBitmapSize(), 00799 bitmap.nPriority, 00800 key.pOwner, 00801 key.nOption, 00802 ((CCObject*)key.pOwner)->GetRuntimeClass()->m_lpszClassName 00803 ); 00804 } 00805 */ CCacheKeyMap::iterator pos; 00806 for ( pos=m_map.begin() ; pos!=m_map.end() ; pos++ ) 00807 { 00808 CBitmapCacheKey key = pos->first; 00809 CCachedBitmap bitmap = pos->second; 00810 TRACE( _T("Bitmap: %x (%d*%d, %d) Priority: %d Owner: %x %d %s\n"), 00811 bitmap.pbmpInfo, 00812 bitmap.pbmpInfo->bmiHeader.biWidth, 00813 bitmap.pbmpInfo->bmiHeader.biHeight, 00814 bitmap.GetBitmapSize(), 00815 bitmap.nPriority, 00816 key.pOwner, 00817 key.nOption, 00818 ((CCObject*)key.pOwner)->GetRuntimeClass()->m_lpszClassName 00819 ); 00820 } 00821 } 00822 #endif 00823 00824 00825 00826 00828 // Construction/Destruction 00830 00831 CCachedBitmap::CCachedBitmap() 00832 { 00833 pbmpInfo = NULL; 00834 pbmpBits = NULL; 00835 // rectCachedRect = DocRect(0,0,0,0); 00836 coord0 = DocCoord(0,0); 00837 coord1 = DocCoord(0,0); 00838 coord2 = DocCoord(0,0); 00839 nPriority = 0; 00840 } 00841 00842 CCachedBitmap::CCachedBitmap(LPBITMAPINFO pNewInfo, LPBYTE pNewBits, INT32 nNewPriority) 00843 { 00844 pbmpInfo = pNewInfo; 00845 pbmpBits = pNewBits; 00846 // rectCachedRect = DocRect(0,0,0,0); 00847 coord0 = DocCoord(0,0); 00848 coord1 = DocCoord(0,0); 00849 coord2 = DocCoord(0,0); 00850 nPriority = nNewPriority; 00851 } 00852 00853 CCachedBitmap::CCachedBitmap(const CCachedBitmap& cbmp) 00854 { 00855 pbmpInfo = cbmp.pbmpInfo; 00856 pbmpBits = cbmp.pbmpBits; 00857 // rectCachedRect = cbmp.rectCachedRect; 00858 coord0 = cbmp.coord0; 00859 coord1 = cbmp.coord1; 00860 coord2 = cbmp.coord2; 00861 nPriority = cbmp.nPriority; 00862 } 00863 00864 00865 CCachedBitmap::CCachedBitmap(UINT32 Width, UINT32 Height, UINT32 Depth, DocRect rect, INT32 nNewPriority) 00866 { 00867 ENSURE(rect.IsValid(), "Attempt to create a cached bitmap with an invalid rectangle!"); 00868 pbmpInfo = AllocDIB(Width, Height, Depth, &pbmpBits); 00869 // rectCachedRect = rect; 00870 coord0 = DocCoord(rect.lo.x, rect.lo.y); 00871 coord1 = DocCoord(rect.hi.x, rect.lo.y); 00872 coord2 = DocCoord(rect.lo.x, rect.hi.y); 00873 nPriority = nNewPriority; 00874 } 00875 00876 00877 CCachedBitmap::~CCachedBitmap() 00878 { 00879 // if (pbmpInfo && pbmpBits) DON'T DO THIS!!! 00880 // DIBUtil::FreeDIB(pbmpInfo, pbmpBits); 00881 pbmpInfo = NULL; 00882 pbmpBits = NULL; 00883 } 00884 00885 00886 00887 00888 /******************************************************************************************** 00889 00890 > void CCachedBitmap::Release() 00891 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00892 Created: 21/06/2004 00893 Inputs: - 00894 Outputs: - 00895 Returns: TRUE if this key is valid 00896 FALSE otherwise 00897 Purpose: Test whether this object has been constructed correctly 00898 Errors: - 00899 SeeAlso: - 00900 00901 ********************************************************************************************/ 00902 void CCachedBitmap::Release() 00903 { 00904 FreeDIB(pbmpInfo, pbmpBits); 00905 } 00906 00907 00908 00909 00910 /******************************************************************************************** 00911 00912 > CCachedBitmap CCachedBitmap::Copy() 00913 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00914 Created: 21/10/2004 00915 Inputs: - 00916 Outputs: - 00917 Returns: - 00918 Purpose: Copy this cached bitmap (actually copy the bitmap, not just the bitmap pointers) 00919 Errors: - 00920 SeeAlso: - 00921 00922 ********************************************************************************************/ 00923 CCachedBitmap CCachedBitmap::Copy() 00924 { 00925 CCachedBitmap copybmp(*this); 00926 INT32 lHRes = pbmpInfo->bmiHeader.biXPelsPerMeter; 00927 INT32 lVRes = pbmpInfo->bmiHeader.biYPelsPerMeter; 00928 DIBUtil::CopyBitmap(pbmpInfo, pbmpBits, ©bmp.pbmpInfo, ©bmp.pbmpBits); 00929 if (copybmp.pbmpInfo) 00930 { 00931 copybmp.pbmpInfo->bmiHeader.biXPelsPerMeter = lHRes; 00932 copybmp.pbmpInfo->bmiHeader.biYPelsPerMeter = lVRes; 00933 } 00934 return copybmp; 00935 } 00936 00937 00938 00939 00940 /******************************************************************************************** 00941 00942 > CCachedBitmap::operator==() 00943 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00944 Created: 10/06/2004 00945 Inputs: - 00946 Outputs: - 00947 Returns: TRUE if this key is exactly the same the the specified key 00948 Purpose: Test whether this object has been constructed correctly 00949 Required by CTypedPtrMap 00950 Errors: - 00951 SeeAlso: - 00952 00953 ********************************************************************************************/ 00954 bool CCachedBitmap::operator==(const CCachedBitmap& cbmp) const 00955 { 00956 return (pbmpInfo == cbmp.pbmpInfo && 00957 pbmpBits == cbmp.pbmpBits && 00958 // rectCachedRect == cbmp.rectCachedRect && 00959 coord0 == cbmp.coord0 && 00960 coord1 == cbmp.coord1 && 00961 coord2 == cbmp.coord2 && 00962 nPriority == cbmp.nPriority 00963 ); 00964 } 00965 00966 00967 00968 00969 /******************************************************************************************** 00970 00971 > CCachedBitmap::operator=() 00972 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00973 Created: 10/06/2004 00974 Inputs: - 00975 Outputs: - 00976 Returns: TRUE if this key is exactly the same the the specified key 00977 Purpose: Test whether this object has been constructed correctly 00978 Required by CTypedPtrMap 00979 Errors: - 00980 SeeAlso: - 00981 00982 ********************************************************************************************/ 00983 const CCachedBitmap& CCachedBitmap::operator=(const CCachedBitmap& cbmp) 00984 { 00985 pbmpInfo = cbmp.pbmpInfo; 00986 pbmpBits = cbmp.pbmpBits; 00987 // rectCachedRect = cbmp.rectCachedRect; 00988 coord0 = cbmp.coord0; 00989 coord1 = cbmp.coord1; 00990 coord2 = cbmp.coord2; 00991 nPriority = cbmp.nPriority; 00992 return cbmp; 00993 } 00994 00995 /******************************************************************************************** 00996 00997 > BOOL CCachedBitmap::IsValid() const 00998 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00999 Created: 10/06/2004 01000 Inputs: - 01001 Outputs: - 01002 Returns: TRUE if this key is valid 01003 FALSE otherwise 01004 Purpose: Test whether this object has been constructed correctly 01005 Errors: - 01006 SeeAlso: - 01007 01008 ********************************************************************************************/ 01009 BOOL CCachedBitmap::IsValid() const 01010 { 01011 return (pbmpInfo!=NULL && pbmpBits!=NULL); 01012 } 01013 01014 01015 01016 01017 /******************************************************************************************** 01018 01019 > UINT32 CCachedBitmap::GetBitmapSize() const 01020 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01021 Created: 18/06/2004 01022 Inputs: - 01023 Outputs: - 01024 Returns: Size of bitmap in bytes 01025 Purpose: Find the size of this bitmap 01026 Errors: - 01027 SeeAlso: - 01028 01029 ********************************************************************************************/ 01030 UINT32 CCachedBitmap::GetBitmapSize() const 01031 { 01032 return (pbmpInfo->bmiHeader.biSizeImage); 01033 } 01034 01035 01036 01037 01038 /******************************************************************************************** 01039 01040 > BOOL CCachedBitmap::IsTransparent() const 01041 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01042 Created: 29/06/2004 01043 Inputs: - 01044 Outputs: - 01045 Returns: TRUE if cached bitmap is 32BPP (transparent) 01046 Purpose: Find out whether this bitmap has a transparency channel or not 01047 Errors: - 01048 SeeAlso: - 01049 01050 ********************************************************************************************/ 01051 BOOL CCachedBitmap::IsTransparent() const 01052 { 01053 return (pbmpInfo->bmiHeader.biCompression!=BI_RGB); 01054 } 01055 01056 01057 01058 01059 /******************************************************************************************** 01060 01061 > UINT32 CCachedBitmap::GetBPP() const 01062 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01063 Created: 30/06/2004 01064 Inputs: - 01065 Outputs: - 01066 Returns: Bits Per Pixel 01067 Purpose: Get bit depth of cached bitmap 01068 Errors: - 01069 SeeAlso: - 01070 01071 ********************************************************************************************/ 01072 UINT32 CCachedBitmap::GetBPP() const 01073 { 01074 return (pbmpInfo->bmiHeader.biBitCount); 01075 } 01076 01077 01078 01079 01080 /******************************************************************************************** 01081 01082 > void CCachedBitmap::Transform(TransformBase& Trans) 01083 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01084 Created: 21/20/2004 01085 Inputs: Transform to apply to the stored coords of this bitmap 01086 Outputs: - 01087 Returns: - 01088 Purpose: Transform the cached bitmap so that it can be distorted/repositioned 01089 Errors: - 01090 SeeAlso: - 01091 01092 ********************************************************************************************/ 01093 void CCachedBitmap::Transform(TransformBase& Trans) 01094 { 01095 // Trans.Transform((DocCoord*)&rectCachedRect, 2); 01096 Trans.Transform(&coord0, 3); 01097 } 01098 01099 01100 01101 01102 /******************************************************************************************** 01103 01104 > DocRect CCachedBitmap::GetCachedRect() 01105 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01106 Created: 21/20/2004 01107 Inputs: - 01108 Outputs: - 01109 Returns: DocRect - upright rectangle containing all points in stored parallelogram 01110 Purpose: Transform the cached bitmap so that it can be distorted/repositioned 01111 Errors: - 01112 SeeAlso: - 01113 01114 ********************************************************************************************/ 01115 DocRect CCachedBitmap::GetCachedRect() 01116 { 01117 DocRect r(coord0, coord0); 01118 r.IncludePoint(coord1); 01119 r.IncludePoint(coord2); 01120 r.IncludePoint(DocCoord(coord2.x+coord1.x-coord0.x, coord2.y+coord1.y-coord0.y)); 01121 01122 return r; 01123 } 01124 01125 01126 01127 01128 /******************************************************************************************** 01129 01130 > void CCachedBitmap::SetCachedRect(DocRect r) 01131 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01132 Created: 21/20/2004 01133 Inputs: - 01134 Outputs: - 01135 Returns: DocRect - upright rectangle containing all points in stored parallelogram 01136 Purpose: Transform the cached bitmap so that it can be distorted/repositioned 01137 Errors: - 01138 SeeAlso: - 01139 01140 ********************************************************************************************/ 01141 void CCachedBitmap::SetCachedRect(DocRect r) 01142 { 01143 coord0 = r.lo; 01144 coord1 = DocCoord(r.hi.x, r.lo.y); 01145 coord2 = DocCoord(r.lo.x, r.hi.y); 01146 } 01147 01148 01149 01150 01151 /******************************************************************************************** 01152 01153 > void CCachedBitmap::SetCachedParallelogram(DocCoord* pCoords, UINT32 numCoords) 01154 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01155 Created: 28/07/2005 01156 Inputs: - 01157 Outputs: - 01158 Returns: - 01159 Purpose: Store parallelogram details 01160 Errors: - 01161 SeeAlso: - 01162 01163 ********************************************************************************************/ 01164 void CCachedBitmap::SetCachedParallelogram(DocCoord* pCoords, UINT32 numCoords) 01165 { 01166 coord0 = pCoords[0]; 01167 coord1 = pCoords[1]; 01168 coord2 = pCoords[2]; 01169 } 01170 01171 01172 01173