00001 // $Id: bmpcomp.cpp 1708 2006-08-17 17:13:38Z gerry $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 00099 // Kernel level parts of bitmap lists 00100 00101 /* 00102 */ 00103 00104 #include "camtypes.h" 00105 #include "bmpcomp.h" 00106 //#include "bmplist.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00107 //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00108 #include "bitmpinf.h" 00109 #include "bmpsrc.h" 00110 #include "ccbuffil.h" 00111 //#include "list.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00112 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00113 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00114 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00115 //#include "will.h" 00116 #include "nativeps.h" // The old style EPS native filter, used in v1.1 00117 00118 #include "clipint.h" 00119 #include "nodebmp.h" 00120 //#include "progress.h" 00121 00122 #include "toollist.h" 00123 #include "objchge.h" 00124 #include "csrstack.h" 00125 00126 #include "clipint.h" 00127 #include "ophist.h" 00128 #include "sgliboil.h" 00129 //#include "will2.h" 00130 00131 #include "expbmp.h" // ExportedBitmaps handling class 00132 #include "impbmp.h" // ImportedBitmaps handling class 00133 //#include "camfiltr.h" // BaseCamelotFilter - version 2 native filter - in camtypes.h [AUTOMATICALLY REMOVED] 00134 #include "cxftags.h" // TAG_DEFINEBITMAP_**** 00135 #include "cxfile.h" // CXF_UNKNOWN_SIZE 00136 //#include "cxfrech.h" // CXaraFileRecordHandler - in camtypes.h [AUTOMATICALLY REMOVED] 00137 #include "expcol.h" // ExportedColours handling class 00138 //#include "cxfrec.h" // CXaraFileRecord handler - in camtypes.h [AUTOMATICALLY REMOVED] 00139 //#include "tim.h" // _R(IDT_CANT_FIND_FILTER) 00140 //#include "filtrres.h" // _R(IDS_DONT_SUPPORT_BITMAP_TYPE) _R(IDS_NATIVE_BITMAPWARNING) 00141 #include "bitfilt.h" // BaseBitmapFlter 00142 //#include "fixmem.h" // CCMalloc, CCFree - in camtypes.h [AUTOMATICALLY REMOVED] 00143 00144 CC_IMPLEMENT_MEMDUMP( BitmapList, List ) 00145 CC_IMPLEMENT_DYNAMIC( BitmapListComponentClass, DocComponentClass ) 00146 CC_IMPLEMENT_DYNAMIC( BitmapListComponent, DocComponent ) 00147 00148 // Declare smart memory handling in Debug builds 00149 #define new CAM_DEBUG_NEW 00150 00151 /********************************************************************************************** 00152 00153 > BitmapList::BitmapList() 00154 00155 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00156 Created: 12/12/94 00157 Inputs: - 00158 Outputs: - 00159 Returns: - 00160 Purpose: BitmapList constructor 00161 00162 **********************************************************************************************/ 00163 00164 BitmapList::BitmapList() 00165 { 00166 ParentDoc = NULL; // Document containing this list 00167 } 00168 00169 /********************************************************************************************** 00170 00171 > BitmapList::~BitmapList() 00172 00173 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00174 Created: 12/12/94 00175 Inputs: - 00176 Outputs: - 00177 Returns: - 00178 Purpose: BitmapList destructor 00179 00180 **********************************************************************************************/ 00181 00182 BitmapList::~BitmapList() 00183 { 00184 ListItem* pItem = GetHead(); 00185 ListItem* pNextItem; 00186 00187 while (pItem) 00188 { 00189 pNextItem = GetNext(pItem); 00190 00191 KernelBitmap* pBmp = (KernelBitmap*)pItem; 00192 00193 ERROR3IF(pBmp->GetParentBitmapList() != this, "Bad ParentList ptr found in bitmap (during BitmapList destructor)"); 00194 00195 // if this bitmap is used by a brush we don't want to delete it here. 00196 if (!pBmp->IsUsedByBrush()) 00197 delete pBmp; // This should remove it from the list first 00198 else 00199 { 00200 pBmp->Detach(); 00201 RemoveItem(pBmp); 00202 } 00203 00204 pItem = pNextItem; 00205 } 00206 00207 // Tidy up the global bitmap list 00208 Camelot.GetGlobalBitmapList()->DeleteAllUnusedBitmaps(); 00209 } 00210 00211 /********************************************************************************************** 00212 00213 > void BitmapList::Init(BaseDocument *ParentDocument) 00214 00215 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00216 Created: 12/12/94 00217 Inputs: ParentDocument - the parent document of this Bitmap list 00218 Purpose: BitmapList initialiser. MUST be called after constructing a BitmapList 00219 in order to correctly initialise it. Note that if ParentDocument is not 00220 set to a useful value, some operations on Bitmap lists will fail. 00221 00222 **********************************************************************************************/ 00223 00224 void BitmapList::Init(BaseDocument *ParentDocument) 00225 { 00226 ERROR3IF(ParentDocument == NULL, "NULL ParentDoc in BitmapList::Init!\n"); 00227 00228 // Ensure the default bitmap is always in the list. 00229 KernelBitmap* Default = new KernelBitmap(); 00230 Default->Attach(this); 00231 00232 ParentDoc = ParentDocument; 00233 } 00234 00235 /********************************************************************************************** 00236 00237 > BOOL BitmapList::AddItem(KernelBitmap *Item) 00238 00239 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00240 Created: 12/12/94 00241 Returns: TRUE 00242 Purpose: Adds an item to the tail of the Bitmaplist, and incremeants it's usage count. 00243 (Unless it's already in the list, in which case it's usage count is just 00244 bumped up). 00245 00246 **********************************************************************************************/ 00247 00248 BOOL BitmapList::AddItem(KernelBitmap *Item) 00249 { 00250 ERROR3IF(Item == NULL, "Trying to add NULL item to Bitmap List"); 00251 00252 if (Item == NULL) 00253 return FALSE; 00254 00255 // Is this Bitmap already in the list ? 00256 LISTPOS pos = FindPosition((ListItem*)Item); 00257 00258 if (pos == NOT_IN_LIST || pos == EMPTY_LIST) 00259 { 00260 // It's not in the list yet, so add it on the end 00261 AddTail((ListItem*)Item); 00262 00263 if (ParentDoc != NULL) 00264 { 00265 BROADCAST_TO_ALL(BitmapListChangedMsg(this)); 00266 } 00267 00268 return TRUE; 00269 } 00270 else 00271 { 00272 // It's already in the list, so just return 00273 // (It's usage count has already been incremeanted) 00274 return FALSE; 00275 } 00276 } 00277 00278 /********************************************************************************************** 00279 00280 > BOOL BitmapList::RemoveItem(KernelBitmap *Item) 00281 00282 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00283 Created: 12/12/94 00284 Returns: TRUE 00285 Purpose: Removes an item from the list. 00286 00287 **********************************************************************************************/ 00288 00289 BOOL BitmapList::RemoveItem(KernelBitmap *Item) 00290 { 00291 ERROR3IF(Item == NULL, "Trying to remove NULL item from Bitmap List"); 00292 00293 if (Item == NULL) 00294 return FALSE; 00295 00296 // Is this Bitmap in the list ? 00297 LISTPOS pos = FindPosition((ListItem*)Item); 00298 00299 if (pos != NOT_IN_LIST || pos == EMPTY_LIST) 00300 { 00301 // It's not in the list yet, so add it on the end 00302 List::RemoveItem((ListItem*)Item); 00303 Item->m_pParentList = NULL; 00304 00305 if (ParentDoc != NULL) 00306 { 00307 BROADCAST_TO_ALL(BitmapListChangedMsg(this)); 00308 } 00309 00310 return TRUE; 00311 } 00312 else 00313 { 00314 // It's not in the list, so just return 00315 return FALSE; 00316 } 00317 } 00318 00319 /********************************************************************************************** 00320 00321 > BOOL BitmapList::MoveBefore(KernelBitmap *InsertPoint, KernelBitmap *ItemToMove) 00322 00323 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00324 Created: 12/12/94 00325 Returns: TRUE 00326 Purpose: Re-arranges the bitmaps in the list. 00327 00328 **********************************************************************************************/ 00329 00330 BOOL BitmapList::MoveBefore(KernelBitmap *InsertPoint, KernelBitmap *ItemToMove) 00331 { 00332 List::RemoveItem((ListItem*)ItemToMove); 00333 List::InsertBefore((ListItem*)InsertPoint, (ListItem*)ItemToMove); 00334 00335 if (ParentDoc != NULL) 00336 { 00337 BROADCAST_TO_ALL(BitmapListChangedMsg(this)); 00338 } 00339 00340 return TRUE; 00341 } 00342 00343 /********************************************************************************************** 00344 00345 > BOOL BitmapList::MoveAfter(KernelBitmap *InsertPoint, KernelBitmap *ItemToMove) 00346 00347 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00348 Created: 12/12/94 00349 Returns: TRUE 00350 Purpose: Re-arranges the bitmaps in the list. 00351 00352 **********************************************************************************************/ 00353 00354 BOOL BitmapList::MoveAfter(KernelBitmap *InsertPoint, KernelBitmap *ItemToMove) 00355 { 00356 List::RemoveItem((ListItem*)ItemToMove); 00357 List::InsertAfter((ListItem*)InsertPoint, (ListItem*)ItemToMove); 00358 00359 if (ParentDoc != NULL) 00360 { 00361 BROADCAST_TO_ALL(BitmapListChangedMsg(this)); 00362 } 00363 00364 return TRUE; 00365 } 00366 00367 /********************************************************************************************** 00368 00369 > BaseDocument *BitmapList::GetParentDocument(void) 00370 00371 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00372 Created: 12/12/94 00373 Returns: The document in which this Bitmap list resides 00374 Purpose: To find the parent document of this Bitmap list 00375 00376 **********************************************************************************************/ 00377 00378 BaseDocument *BitmapList::GetParentDocument(void) 00379 { 00380 ERROR3IF(ParentDoc == NULL, "Uninitialised BitmapList detected!"); 00381 return(ParentDoc); 00382 } 00383 00384 /********************************************************************************************** 00385 00386 > KernelBitmap* BitmapList::FindDuplicateBitmap(OILBitmap* pBitmap) 00387 00388 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00389 Created: 14/8/96 00390 Purpose: Looks to see if an identical bitmap is already in the bitmap list 00391 00392 **********************************************************************************************/ 00393 00394 KernelBitmap* BitmapList::FindDuplicateBitmap(OILBitmap* pOILBitmap) 00395 { 00396 ListItem* pItem = GetHead(); 00397 while (pItem != NULL) 00398 { 00399 KernelBitmap* pBmp = (KernelBitmap*)pItem; 00400 00401 if (pBmp->ActualBitmap && 00402 pBmp->ActualBitmap != pOILBitmap && 00403 *pBmp->ActualBitmap == *pOILBitmap) 00404 { 00405 return pBmp; 00406 } 00407 00408 pItem = GetNext(pItem); 00409 } 00410 00411 return NULL; 00412 } 00413 00414 /********************************************************************************************** 00415 00416 > KernelBitmap* BitmapList::FindDefaultBitmap() 00417 00418 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00419 Created: 10/8/96 00420 Purpose: Finds the default bitmap in this bitmap list 00421 00422 **********************************************************************************************/ 00423 00424 KernelBitmap* BitmapList::FindDefaultBitmap() 00425 { 00426 ListItem* pItem = GetHead(); 00427 while (pItem != NULL) 00428 { 00429 KernelBitmap* pBmp = (KernelBitmap*)pItem; 00430 00431 if (pBmp->ActualBitmap && 00432 pBmp->ActualBitmap == OILBitmap::Default) 00433 { 00434 return pBmp; 00435 } 00436 00437 pItem = GetNext(pItem); 00438 } 00439 00440 return NULL; 00441 } 00442 00443 00444 /******************************************************************************************** 00445 00446 > BOOL BitmapListComponentClass::Init() 00447 00448 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00449 Created: 12/12/94 00450 Returns: TRUE if all went well; 00451 FALSE if not. 00452 Purpose: Register the Bitmap list document component with the main application. 00453 Errors: Out of memory. 00454 SeeAlso: DocComponent 00455 00456 ********************************************************************************************/ 00457 00458 BOOL BitmapListComponentClass::Init() 00459 { 00460 // Instantiate a component class to register with the application. 00461 BitmapListComponentClass *pClass = new BitmapListComponentClass; 00462 if (pClass == NULL) 00463 return FALSE; 00464 00465 // Register it 00466 GetApplication()->RegisterDocComponent(pClass); 00467 00468 // All ok 00469 return TRUE; 00470 } 00471 00472 00473 /******************************************************************************************** 00474 00475 > BOOL BitmapListComponentClass::AddComponent(BaseDocument *pDocument) 00476 00477 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00478 Created: 12/12/94 00479 Inputs: pDocument - the document to add the Bitmap list to. 00480 Returns: TRUE if the Bitmap list was added ok; 00481 FALSE if not. 00482 Purpose: Add a Bitmap list component to the specified document. 00483 Errors: Out of memory 00484 SeeAlso: BitmapListComponentClass 00485 00486 ********************************************************************************************/ 00487 00488 BOOL BitmapListComponentClass::AddComponent(BaseDocument *pDocument) 00489 { 00490 // Check to see if this document already has a Bitmap list; if so, leave it alone. 00491 if (pDocument->GetDocComponent(CC_RUNTIME_CLASS(BitmapListComponent)) != NULL) 00492 return TRUE; 00493 00494 // No Bitmap list - try to create a new one for this document. 00495 BitmapList *pList = new BitmapList; 00496 if(pList == NULL) 00497 return FALSE; 00498 00499 pList->Init(pDocument); // Let the BitmapList know what its parent document is 00500 00501 // Ok - create the Bitmap list component using this list. 00502 BitmapListComponent *pComponent = new BitmapListComponent(pList); 00503 if (pComponent == NULL) 00504 { 00505 // Out of memory... 00506 delete pList; 00507 return FALSE; 00508 } 00509 00510 // All ok - add the component to the document. 00511 pDocument->AddDocComponent(pComponent); 00512 return TRUE; 00513 } 00514 00515 00516 00517 /******************************************************************************************** 00518 00519 > BitmapListComponent::BitmapListComponent() 00520 00521 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00522 Created: 12/12/94 00523 Purpose: Construct a Bitmap list component. DO NOT use this constructor. It gives 00524 and ERROR3 (and sets up this in a semi-safe default state) 00525 SeeAlso: BitmapListComponent 00526 00527 ********************************************************************************************/ 00528 00529 BitmapListComponent::BitmapListComponent() 00530 { 00531 ERROR3("BitmapListComponent constructed with default constructor!?\n"); 00532 } 00533 00534 00535 00536 /******************************************************************************************** 00537 00538 > BitmapListComponent::BitmapListComponent(BitmapList *pBmpList) 00539 00540 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00541 Created: 12/12/94 00542 Inputs: pColList - the Bitmap list to use for this Bitmap list componet. 00543 Purpose: Construct a Bitmap list component using the given Bitmap list. 00544 Errors: ENSURE if pColList is NULL. 00545 SeeAlso: BitmapListComponent 00546 00547 ********************************************************************************************/ 00548 00549 BitmapListComponent::BitmapListComponent(BitmapList *pBmpList) 00550 { 00551 ENSURE(pBmpList != NULL, "NULL Bitmap list in Bitmap list component constructor!"); 00552 00553 // Install this Bitmap list. 00554 pBitmaps = pBmpList; 00555 00556 // Initialise Exporter bitmap list 00557 pExportedBitmaps = NULL; 00558 00559 // Initialise Importer bitmap list 00560 pImportedBitmaps = NULL; 00561 00562 // Our link to the BaseCamelotFilter 00563 pCamFilter = NULL; 00564 // Set our variable so that we warn about a possible replacement only once 00565 WarnedBefore = FALSE; 00566 00567 // Initialise Exporter bitmap list (used for EPS only) 00568 pBitmapsToExport = NULL; 00569 } 00570 00571 /******************************************************************************************** 00572 00573 > BitmapListComponent::~BitmapListComponent() 00574 00575 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00576 Created: 12/12/94 00577 Purpose: Clean up a Bitmap list component's data structures - deletes the Bitmap 00578 list. 00579 Errors: - 00580 SeeAlso: BitmapListComponent 00581 00582 ********************************************************************************************/ 00583 00584 BitmapListComponent::~BitmapListComponent() 00585 { 00586 // Delete our Bitmap list. 00587 delete pBitmaps; 00588 00589 // As we have finished with it now, destroy the list of imported bitmaps 00590 if (pImportedBitmaps) 00591 { 00592 delete pImportedBitmaps; 00593 pImportedBitmaps = NULL; 00594 } 00595 00596 // As we have finished with it now, destroy the list of exported bitmaps 00597 if (pExportedBitmaps) 00598 { 00599 delete pExportedBitmaps; 00600 pExportedBitmaps = NULL; 00601 } 00602 00603 if (pBitmapsToExport) 00604 { 00605 delete pBitmapsToExport; 00606 pBitmapsToExport = NULL; 00607 } 00608 } 00609 00610 00611 00612 /******************************************************************************************** 00613 00614 > BOOL BitmapListComponent::EPSStartImport(EPSFilter *pFilter) 00615 00616 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00617 Created: 12/12/94 00618 Inputs: pFilter - the EPS filter that is being used to import a file. 00619 Purpose: Inform the Bitmap list document component that an EPS import is about to 00620 start. 00621 SeeAlso: DocComponent 00622 00623 ********************************************************************************************/ 00624 00625 BOOL BitmapListComponent::EPSStartImport(EPSFilter *pFilter) 00626 { 00627 return FALSE; 00628 } 00629 00630 /******************************************************************************************** 00631 00632 > void BitmapListComponent::EPSEndImport(EPSFilter *pFilter, BOOL Success) 00633 00634 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00635 Created: 12/12/94 00636 Inputs: pFilter - the EPS filter that is being used to import a file. 00637 Success - TRUE => The import was successful; 00638 FALSE => The import failed - abandon any changes. 00639 Purpose: Inform the Bitmap list document component that an EPS import has just 00640 finished. 00641 SeeAlso: DocComponent 00642 00643 ********************************************************************************************/ 00644 00645 void BitmapListComponent::EPSEndImport(EPSFilter *pFilter, BOOL Success) 00646 { 00647 } 00648 00649 /******************************************************************************************** 00650 00651 > BOOL BitmapListComponent::EPSStartExport(EPSFilter *pFilter) 00652 00653 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00654 Created: 12/12/94 00655 Inputs: pFilter - the EPS filter that is being used to import a file. 00656 Purpose: Inform the Bitmap list document component that an EPS export is about to 00657 start. 00658 SeeAlso: DocComponent 00659 00660 ********************************************************************************************/ 00661 00662 BOOL BitmapListComponent::EPSStartExport(EPSFilter *pFilter) 00663 { 00664 #ifdef DO_EXPORT 00665 ERROR3IF(pBitmapsToExport != NULL, "Why is there an export bitmap list already ?"); 00666 00667 // Build the list of bitmaps to export here ... 00668 pBitmapsToExport = new ExportedBitmaps(); 00669 00670 ERROR3IF(pBitmapsToExport == NULL, "Couldn't create bitmap export list !!"); 00671 if (pBitmapsToExport == NULL) 00672 return FALSE; 00673 00674 Document* ParentDoc = (Document*)pBitmaps->GetParentDocument(); 00675 ERROR3IF(ParentDoc == NULL, "Bitmap list has no parent document !!"); 00676 if (ParentDoc == NULL) 00677 { 00678 delete pBitmapsToExport; 00679 pBitmapsToExport = NULL; 00680 return FALSE; 00681 } 00682 00683 UINT32 BitmapNumber = 0; 00684 00685 // Scan the document's tree for bitmap references 00686 Node* pNode = Node::DocFindFirstDepthFirst(ParentDoc); 00687 while (pNode != NULL) 00688 { 00689 // Ignore hidden nodes 00690 if (!pNode->IsNodeHidden()) 00691 { 00692 INT32 Count = 0; 00693 00694 // Does this node have any bitmaps in it ? 00695 KernelBitmap* pBitmap = pNode->EnumerateBitmaps(Count++); 00696 00697 while (pBitmap != NULL) 00698 { 00699 // Check for a deleted bitmap 00700 if (pBitmap->HasBeenDeleted()) 00701 { 00702 ERROR2IF(pBitmap->GetParentBitmapList() == NULL, 0L, "Deleted bitmap has no parent list"); 00703 00704 // Use the default bitmap instead 00705 pBitmap = pBitmap->GetParentBitmapList()->FindDefaultBitmap(); 00706 00707 // There should always be a default bitmap at the start of the list 00708 ERROR2IF(pBitmap == NULL, 0L, "Couldn't find the default bitmap"); 00709 } 00710 00711 // Found a bitmap reference, so ... 00712 // .. if this bitmap is not in the export list, add it 00713 if (pBitmapsToExport->GetBitmap(pBitmap) == NULL) 00714 pBitmapsToExport->AddBitmap(pBitmap, BitmapNumber++); 00715 00716 pBitmap = pNode->EnumerateBitmaps(Count++); 00717 } 00718 } 00719 00720 // Move onto the next node in the tree 00721 pNode = pNode->DocFindNextDepthFirst(); 00722 } 00723 #endif 00724 return TRUE; 00725 } 00726 00727 /******************************************************************************************** 00728 00729 > void BitmapListComponent::EPSEndExport(EPSFilter *pFilter, BOOL Success) 00730 00731 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00732 Created: 12/12/94 00733 Inputs: pFilter - the EPS filter that is being used to import a file. 00734 Success - TRUE => The import was successful; 00735 FALSE => The import failed - abandon any changes. 00736 Purpose: Inform the Bitmap list document component that an EPS export has just 00737 finished. 00738 SeeAlso: DocComponent 00739 00740 ********************************************************************************************/ 00741 00742 void BitmapListComponent::EPSEndExport(EPSFilter *pFilter) 00743 { 00744 #ifdef DO_EXPORT 00745 if (pBitmapsToExport) 00746 { 00747 delete pBitmapsToExport; 00748 pBitmapsToExport = NULL; 00749 } 00750 #endif 00751 } 00752 00753 /******************************************************************************************** 00754 00755 > BOOL BitmapListComponent::WriteEPSComments(EPSFilter *pFilter) 00756 00757 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00758 Created: 12/12/94 00759 Inputs: pFilter - the filter being used to import the EPS file. 00760 Returns: TRUE if the Bitmap table was written successfully; 00761 FALSE if not. 00762 Purpose: Writes out the Bitmap table in the form of EPS comments in the 'header' 00763 comments of the EPS file. 00764 Errors: Out of disk space, and similar disk errors. 00765 SeeAlso: DocComponent::WriteEPSComments; 00766 DocComponent 00767 00768 ********************************************************************************************/ 00769 00770 BOOL BitmapListComponent::WriteEPSComments(EPSFilter *pFilter) 00771 { 00772 return TRUE; 00773 } 00774 00775 00776 /******************************************************************************************** 00777 00778 > BOOL BitmapListComponent::WriteScript(EPSFilter* pFilter) 00779 00780 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00781 Created: 18/1/95 00782 Inputs: pFilter - the EPS filter that is being used to export a file. 00783 Returns: TRUE if the Script for this component was written out successfully; 00784 FALSE if not (e.g. out of disk space etc) 00785 Purpose: This is called after all the Comments, Prolog etc have been output so that 00786 DocComponents get a chance to do something right at the start of the real 00787 EPS data, but before the tree starts to be exported. 00788 (The base class does nothing) 00789 SeeAlso: DocComponent::WriteEPSSetup; 00790 DocComponent::WriteEPSProlog; 00791 DocComponent::ProcessEPSComment; 00792 DocComponent; 00793 EPSFIlter 00794 00795 ********************************************************************************************/ 00796 00797 BOOL BitmapListComponent::WriteScript(EPSFilter* pFilter) 00798 { 00799 #ifdef DO_EXPORT 00800 // This only happens in Native EPS 00801 if (pFilter->IS_KIND_OF(CamelotNativeEPSFilter)) 00802 { 00803 // Find out the context to save to 00804 EPSExportDC *pDC = pFilter->GetExportDC(); 00805 00806 // Make sure that there's a bitmap list to export. 00807 if (pBitmapsToExport == NULL) 00808 { 00809 ERROR3 ( "Why isn't there an export bitmap list (in WriteScript) ?" ); 00810 return FALSE; 00811 } 00812 00813 // Something to mark the start of the bitmap pool 00814 pDC->OutputToken(_T("%%BeginCamelotBitmapPool")); 00815 pDC->OutputNewLine(); 00816 00817 // Tell the filter we are starting to save the bitmap pool 00818 ((CamelotNativeEPSFilter*)pFilter)->IsSavingBitmapPool = TRUE; 00819 00820 // Find the number of Bitmaps 00821 INT32 TotalBitmaps = pBitmapsToExport->GetCount(); 00822 00823 // Output a comment saying how many bitmaps we have 00824 pDC->OutputToken(_T("%%BitmapPoolCount")); 00825 pDC->OutputValue(TotalBitmaps); 00826 pDC->OutputNewLine(); 00827 00828 INT32 BitmapNum = 0; 00829 00830 // Find the first bitmap in the list again 00831 ExportBitmap* pExportBitmap = pBitmapsToExport->EnumerateBitmaps(); 00832 00833 while (pExportBitmap != NULL) 00834 { 00835 ERROR3IF(pExportBitmap->RecordNumber != BitmapNum, "Bad bitmap number found when saving bitmap pool"); 00836 00837 // Save the bitmap out 00838 ExportBitmapPoolItem(BitmapNum, pFilter, pDC, pExportBitmap->pBmp); 00839 00840 BitmapNum++; 00841 00842 // Find the next one 00843 pExportBitmap = pBitmapsToExport->EnumerateBitmaps(pExportBitmap); 00844 } 00845 00846 // Tell the filter we are starting to save the bitmap pool 00847 ((CamelotNativeEPSFilter*)pFilter)->IsSavingBitmapPool = FALSE; 00848 00849 // Something to mark the start of the bitmap pool 00850 pDC->OutputToken(_T("%%EndCamelotBitmapPool")); 00851 pDC->OutputNewLine(); 00852 } 00853 00854 #endif 00855 return TRUE; 00856 } 00857 00858 00859 00860 /******************************************************************************************** 00861 00862 > BOOL BitmapListComponent::ExportBitmapPoolItem(INT32 BitmapNum, EPSFilter* pFilter, 00863 EPSExportDC* pDC, KernelBitmap* pBitmap) 00864 00865 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00866 Created: 19/1/95 00867 Inputs: BitmapNum - The number of the Kernel bitmap in the pool 00868 pFilter - The filter that things are being saved in 00869 pDC - The DC that the saving is happening in 00870 pBitmap - The Kernel Bitmap to be saved 00871 Returns: TRUE if it worked, FALSE if not 00872 Purpose: Does the actual saving for a bitmap pool item. This uses the cbmp token to 00873 represent the Camelot BitMap Pool object. 00874 00875 ********************************************************************************************/ 00876 00877 BOOL BitmapListComponent::ExportBitmapPoolItem(INT32 BitmapNum, EPSFilter* pFilter, EPSExportDC* pDC, KernelBitmap* pBitmap) 00878 { 00879 #ifdef DO_EXPORT 00880 ERROR2IF(pBitmap->HasBeenDeleted(), FALSE, "Trying to export a deleted bitmap"); 00881 00882 if (pFilter->IS_KIND_OF(CamelotNativeEPSFilter)) 00883 { 00884 // ...then the bitmap object token. 00885 pDC->OutputValue(BitmapNum); // Output the number of the bitmap 00886 pDC->OutputValue(INT32(0)); // Bitmap pool type (ready for expansion) 00887 pDC->OutputToken(_T("cbmp")); // Bitmap pool token 00888 pDC->OutputNewLine(); 00889 00890 // ...and then the bitmap data itself. 00891 pFilter->ExportBitmap(*pBitmap); 00892 00893 // Tell caller we rendered ourselves ok 00894 return TRUE; 00895 } 00896 #endif 00897 return FALSE; 00898 } 00899 00900 00901 /******************************************************************************************** 00902 00903 > ProcessEPSResult BitmapListComponent::ProcessEPSComment(EPSFilter *pFilter, 00904 const char *pComment) 00905 00906 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00907 Created: 12/12/94 00908 Inputs: pFilter - the EPS filter that is being used to import a file. 00909 pComment - pointer to the comment to process. 00910 Returns: EPSCommentUnknown - This EPS comment is not recognised by the document 00911 component. 00912 EPSCommentError - This EPS comment was recognised by this document 00913 component, but it contained an error. 00914 EPSCommentOK - This EPS comment was recognised as a legal comment by 00915 this document component, and was processed 00916 successfully. 00917 Purpose: Process an EPS comment - if this is a Bitmap table comment, this component 00918 will claim it and try to decode it. 00919 Errors: Badly formed EPS comment. 00920 SeeAlso: DocComponent::ProcessEPSComment 00921 00922 ********************************************************************************************/ 00923 00924 ProcessEPSResult BitmapListComponent::ProcessEPSComment(EPSFilter *pFilter, 00925 const char *pComment) 00926 { 00927 // Ignore all comments 00928 return EPSCommentUnknown; 00929 } 00930 00931 00932 00933 00934 /******************************************************************************************** 00935 00936 > void BitmapListComponent::EndOfEPSComment(EPSFilter *pFilter) 00937 00938 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00939 Created: 12/12/94 00940 Inputs: pFilter - the EPS filter that is being used to import a file. 00941 Purpose: Informs the document component that the comment it has been decoding has 00942 now finished, and it should take whatever action required to act on 00943 the comment. 00944 SeeAlso: DocComponent::EndOfPESComment 00945 00946 ********************************************************************************************/ 00947 00948 void BitmapListComponent::EndOfEPSComment(EPSFilter *pFilter) 00949 { 00950 // Do any cleanup we need to here after loading in a Bitmap table... 00951 } 00952 00953 00954 00955 /******************************************************************************************** 00956 00957 > INT32 BitmapListComponent::GetSizeOfExport(Filter *pFilter) 00958 00959 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00960 Created: 27/01/95 00961 Inputs: pFilter - the export filter that will be used. 00962 Returns: An approximation of the size of data that will be exported by this 00963 bitmap list, in terms of nodes. (see NodeRenderable::GetSizeOfExport). 00964 Purpose: Find out how many nodes will be exported when this bitmap list is exported. 00965 The node can use the filter to find out how it will be exported, e.g. 00966 bitmap lists should return a value that reflects whether or not bitmap 00967 indirection is possible with this filter and so on. 00968 NB. This is virtual - the default implementation just returns 1 - only 00969 override if this is not accurate. 00970 SeeAlso: Node::NeedsToExport; Node::ExportRender; NodeRenderable::GetSizeOfExport 00971 00972 ********************************************************************************************/ 00973 00974 INT32 BitmapListComponent::GetSizeOfExport(Filter *pFilter) 00975 { 00976 #ifdef DO_EXPORT 00977 // Check if this filter supports bitmap pools 00978 if (pFilter->GetBitmapSupportLevel() != IndirectedBitmapSupport) 00979 // No - just return 1. 00980 return 1; 00981 00982 ERROR3IF(pBitmapsToExport == NULL, "Why isn't there an export bitmap list (in GetSizeOfExport) ?"); 00983 if (pBitmapsToExport == NULL) 00984 return 1; 00985 00986 INT32 TotalScanlines = 0; 00987 00988 // Find the first bitmap in the list again 00989 ExportBitmap* pExportBitmap = pBitmapsToExport->EnumerateBitmaps(); 00990 00991 while (pExportBitmap != NULL) 00992 { 00993 KernelBitmap* pBitmap = pExportBitmap->pBmp; 00994 00995 // Get information on this bitmap. 00996 BitmapInfo Info; 00997 if (!pBitmap->ActualBitmap->GetInfo(&Info)) 00998 // Failed for some reason - bodge the answer. 00999 return 1; 01000 01001 // Add the number of scanlines to our total 01002 TotalScanlines += Info.PixelHeight; 01003 01004 // Find the next one 01005 pExportBitmap = pBitmapsToExport->EnumerateBitmaps(pExportBitmap); 01006 } 01007 01008 // Return size to caller. 01009 if (TotalScanlines == 0) 01010 return 1; 01011 else 01012 return TotalScanlines; 01013 #else 01014 return 0; 01015 #endif 01016 } 01017 01018 01019 01020 /******************************************************************************************** 01021 01022 > virtual BOOL BitmapListComponent::StartComponentCopy(); 01023 01024 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01025 Created: 12/12/94 01026 Inputs: - 01027 Outputs: - 01028 Returns: TRUE if it succeeded. FALSE if the copy must be aborted 01029 Purpose: This function gets called to prepare for a copy of Bitmaps into 01030 the document. It sets up the various arrays and other thangs which the 01031 Bitmap copy will need. 01032 Errors: ENSURE failure if called when a component copy is already under way. 01033 Errors will be reported if memory is unavailable 01034 SeeAlso: BitmapListComponent::EndComponentCopy; 01035 BitmapListComponent::AbortComponentCopy; 01036 BitmapListComponent::CopyBitmapAcross 01037 01038 ********************************************************************************************/ 01039 01040 BOOL BitmapListComponent::StartComponentCopy() 01041 { 01042 return(TRUE); 01043 } 01044 01045 01046 01047 /******************************************************************************************** 01048 01049 > virtual BOOL BitmapListComponent::EndComponentCopy(); 01050 01051 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01052 Created: 12/12/94 01053 Inputs: - 01054 Outputs: - 01055 Returns: TRUE if it succeeded 01056 Purpose: Will commit all changes made by doing the component copy, returning TRUE. 01057 Errors: - 01058 Notes: May be called multiple times - subsequent calls will be ignored 01059 01060 SeeAlso: BitmapListComponent::StartComponentCopy; 01061 BitmapListComponent::AbortComponentCopy; 01062 BitmapListComponent::CopyBitmapAcross 01063 01064 ********************************************************************************************/ 01065 01066 BOOL BitmapListComponent::EndComponentCopy() 01067 { 01068 return(TRUE); 01069 } 01070 01071 01072 /******************************************************************************************** 01073 01074 > virtual void BitmapListComponent::AbortComponentCopy(); 01075 01076 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01077 Created: 12/12/94 01078 Inputs: - 01079 Outputs: - 01080 Returns: - 01081 Purpose: Will abort all changes made for component copies. 01082 This means that things such as the Bitmaps referenced by the nodes 01083 you have just copied do not exist, so you must clean up to the state 01084 the document was in before you strated copying. 01085 Errors: - 01086 Notes: May be called even if StartComponentCopy has not been called. 01087 May be called multiple times 01088 SeeAlso: BitmapListComponent::EndComponentCopy; 01089 BitmapListComponent::AbortComponentCopy; 01090 BitmapListComponent::CopyBitmapAcross 01091 01092 ********************************************************************************************/ 01093 01094 void BitmapListComponent::AbortComponentCopy() 01095 { 01096 } 01097 01098 01099 /******************************************************************************************** 01100 ********************************************************************************************/ 01101 01102 // Remove the following code on all builds but those who want it 01103 01104 /******************************************************************************************** 01105 ********************************************************************************************/ 01106 01107 /******************************************************************************************** 01108 01109 > BOOL BitmapListComponent::StartImport(BaseCamelotFilter *pFilter) 01110 01111 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01112 Created: 11/6/96 01113 Inputs: pFilter - the BaseCamelotFilter filter that is being used to import a file. 01114 Returns: TRUE if the component was able to prepare for importing; 01115 FALSE if not (e.g. out of memory) 01116 Purpose: Inform the bitmap list document component that a Native or Web import is 01117 about to start. 01118 SeeAlso: DocComponent 01119 01120 ********************************************************************************************/ 01121 01122 BOOL BitmapListComponent::StartImport(BaseCamelotFilter *pFilter) 01123 { 01124 TRACEUSER( "Neville", _T("BitmapListComponent::StartImport\n") ); 01125 if (pFilter == NULL) 01126 { 01127 ERROR3("BitmapListComponent::StartExport filter is null!"); 01128 return TRUE; 01129 } 01130 01131 // Save this in our link to the BaseCamelotFilter 01132 pCamFilter = pFilter; 01133 // Set our variable so that we warn about a possible replacement only once 01134 WarnedBefore = FALSE; 01135 01136 // Set up and start the imported bitmap list 01137 pImportedBitmaps = new ImportedBitmaps(); 01138 if (pImportedBitmaps == NULL) 01139 return FALSE; 01140 01141 return TRUE; 01142 } 01143 01144 /******************************************************************************************** 01145 01146 > BOOL BitmapListComponent::EndImport(BaseCamelotFilter *pFilter, BOOL Success) 01147 01148 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01149 Created: 11/6/96 01150 Inputs: pFilter - the BaseCamelotFilter filter that is being used to import a file. 01151 Success - TRUE => The import was successful; 01152 FALSE => The import failed - abandon any changes. 01153 Returns: TRUE if the component was able to end the importing; 01154 FALSE if not (e.g. out of memory) 01155 Purpose: Inform the bitmap list document component that a Native or Web import has 01156 just finished. 01157 SeeAlso: DocComponent 01158 01159 ********************************************************************************************/ 01160 01161 BOOL BitmapListComponent::EndImport(BaseCamelotFilter *pFilter, BOOL Success) 01162 { 01163 TRACEUSER( "Neville", _T("BitmapListComponent::EndImport\n") ); 01164 if (pFilter == NULL) 01165 { 01166 ERROR3("BitmapListComponent::EndImport filter is null!"); 01167 return TRUE; 01168 } 01169 01170 // As we have finished with it now, destroy the list of imported bitmaps 01171 if (pImportedBitmaps) 01172 { 01173 delete pImportedBitmaps; 01174 pImportedBitmaps = NULL; 01175 } 01176 01177 // Null our link to the BaseCamelotFilter 01178 pCamFilter = NULL; 01179 // Set our variable so that we warn about a possible replacement only once 01180 WarnedBefore = FALSE; 01181 01182 return TRUE; 01183 } 01184 01185 /******************************************************************************************** 01186 01187 > KernelBitmap* BitmapListComponent::GetReadBitmapReference(INT32 BitmapRef) 01188 01189 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01190 Created: 11/6/96 01191 Inputs: BitmapRef - The bitmap reference or record number that the record handler has loaded 01192 from the record. 01193 Outputs: - 01194 Returns: pBitmap - A pointer to return the required kernel bitmap 01195 Purpose: Try and convert a bitmap reference i.e. record number into a previously 01196 imported bitmap definition which should now be an kernel bitmap in the document. 01197 SeeAlso: - 01198 01199 ********************************************************************************************/ 01200 01201 KernelBitmap* BitmapListComponent::GetReadBitmapReference(INT32 BitmapRef) 01202 { 01203 TRACEUSER( "Neville", _T("GetReadBitmapReference for ref %d\n"), BitmapRef ); 01204 01205 // First check to see if the bitmap refers to any of the built in bitmaps. 01206 // These will have negative record numbers 01207 KernelBitmap* pBitmap = NULL; 01208 if (BitmapRef <= 0) 01209 { 01210 // The only one that exists at present is the default bitmap 01211 if (REF_DEFAULTBITMAP_BUILTIN) 01212 { 01213 // Its the default one so just construct a new kernel bitmap which 01214 // refers to this and return this to the caller 01215 pBitmap = KernelBitmap::MakeKernelBitmap(NULL, NULL); 01216 } 01217 else 01218 { 01219 // If we have a pFilter then ask the default warning handle to append our message 01220 if (pCamFilter) 01221 { 01222 if (!WarnedBefore) 01223 { 01224 pCamFilter->AppendWarning(_R(IDS_NATIVE_BITMAPWARNING)); 01225 WarnedBefore = TRUE; 01226 } 01227 01228 // We have warned the user about problems so just construct a new kernel bitmap which 01229 // is the default one and return this to the caller 01230 pBitmap = KernelBitmap::MakeKernelBitmap(NULL, NULL); 01231 } 01232 else 01233 ERROR2(NULL,"BitmapListComponent::GetReadBitmapReference negative BitmapRef is unknown"); 01234 } 01235 } 01236 else 01237 { 01238 // Try and find the specified record number in our colour list 01239 pBitmap = pImportedBitmaps->GetBitmap(BitmapRef); 01240 // If not found then this is a problem as a bitmap must have been defined before its being 01241 // referenced 01242 if (pBitmap == NULL) 01243 { 01244 // If we have a pFilter then ask the default warning handle to append our message 01245 if (pCamFilter) 01246 { 01247 if (!WarnedBefore) 01248 { 01249 pCamFilter->AppendWarning(_R(IDS_NATIVE_BITMAPWARNING)); 01250 WarnedBefore = TRUE; 01251 } 01252 01253 // We have warned the user about problems so just construct a new kernel bitmap which 01254 // is the default one and return this to the caller 01255 pBitmap = KernelBitmap::MakeKernelBitmap(NULL, NULL); 01256 } 01257 else 01258 ERROR2(NULL,"BitmapListComponent::GetReadBitmapReference BitmapRef cannot be found"); 01259 } 01260 } 01261 01262 return pBitmap; 01263 } 01264 01265 /******************************************************************************************** 01266 01267 > BOOL BitmapListComponent::LoadBitmapDefinition(CXaraFileRecordHandler *pXFileRecHandler, CXaraFile * pCXFile, 01268 INT32 Tag, UINT32 Size, UINT32 RecordNumber) 01269 01270 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01271 Created: 11/6/96 01272 Inputs: pXFileRecHandler - The CXaraFileRecordHandler that is being used to provide read functions etc. 01273 pCXFile - The CXaraFile that is being used to provide read functions etc. 01274 Tag - The tag of the record and hence the type of bitmap being imported 01275 Size - The size of this bitmap record 01276 RecordNumber - The record number for this bitmap record 01277 Returns: TRUE if the record was succesfully imported; 01278 FALSE if not (e.g. out of memory) 01279 Purpose: Try and import a bitmap definition record into the document. 01280 SeeAlso: - 01281 01282 ********************************************************************************************/ 01283 01284 BOOL BitmapListComponent::LoadBitmapDefinition(CXaraFileRecordHandler *pXFileRecHandler, 01285 CXaraFile * pCXFile, 01286 INT32 Tag, UINT32 Size, UINT32 RecordNumber) 01287 { 01288 ERROR2IF(pXFileRecHandler == NULL,FALSE,"BitmapListComponent::LoadBitmapDefinition NULL pXFileRecHandler"); 01289 ERROR2IF(pCXFile == NULL,FALSE,"BitmapListComponent::LoadBitmapDefinition NULL pCXFile"); 01290 ERROR2IF(pImportedBitmaps == NULL,FALSE,"BitmapListComponent::LoadBitmapDefinition NULL pImportedBitmaps"); 01291 01292 BOOL ok = TRUE; 01293 01294 // Get the underlying file stream class, CCFile, that we are using to load the file 01295 CCLexFile* pFile = pCXFile->GetCCFile(); 01296 ERROR2IF(pFile == NULL,FALSE,"BitmapListComponent::LoadBitmapDefinition CCFile pointer is NULL"); 01297 // Note present position in file 01298 FilePos pos = pFile->tellIn(); 01299 01300 // Get the underlying BaseCamelotFilter, which we will use to handle the progress bar updates 01301 // and other useful things 01302 CamelotRecordHandler * pCamRecHandler = (CamelotRecordHandler *)pXFileRecHandler; 01303 BaseCamelotFilter *pFilter = pCamRecHandler->GetBaseCamelotFilter(); 01304 01305 // We use this for file for the import, but we might need to change it 01306 // if we use a BitmapSource 01307 CCLexFile* pPseudoFile = pFile; 01308 01309 // First get the name of the bitmap and other details stored in the record 01310 String_256 BitmapName; 01311 if (ok) ok = pCXFile->Read(BitmapName, BitmapName.MaxLength()); 01312 01313 // Some bitmaps might have a compressed and uncompressed format 01314 // At present, this only happens for bitmaps 01315 BOOL Compressed = FALSE; 01316 // Work out which filter is required from the tag on the record 01317 UINT32 SearchFilter = 0; 01318 // Assume we won't need a BitmapSource 01319 BitmapSource* pSource = NULL; 01320 BOOL ReadPalette = FALSE; 01321 switch (Tag) 01322 { 01323 case TAG_DEFINEBITMAP_BMP: 01324 SearchFilter = FILTERID_BMP; 01325 break; 01326 case TAG_DEFINEBITMAP_GIF: 01327 SearchFilter = FILTERID_TI_GIF; 01328 break; 01329 case TAG_DEFINEBITMAP_JPEG: 01330 SearchFilter = FILTERID_IMPORT_JPEG; 01331 break; 01332 case TAG_DEFINEBITMAP_PNG: 01333 SearchFilter = FILTERID_PNG; 01334 break; 01335 case TAG_DEFINEBITMAP_BMPZIP: 01336 SearchFilter = FILTERID_BMP; 01337 Compressed = TRUE; 01338 break; 01339 case TAG_DEFINEBITMAP_JPEG8BPP: 01340 SearchFilter = FILTERID_IMPORT_JPEG; 01341 Compressed = TRUE; 01342 ReadPalette = TRUE; 01343 break; 01344 01345 default: 01346 // Not a known tag, so fall through below and use the default bitmap 01347 // warn the user and skip the definition 01348 //ERROR1(FALSE, _R(IDS_DONT_SUPPORT_BITMAP_TYPE)); 01349 break; 01350 } 01351 01352 // If we have a filter to search for then find it. 01353 Filter *pBmpFilter = NULL; 01354 if (SearchFilter != 0) 01355 { 01356 // Try and find the bitmap filter to use to load that bitmap in 01357 // Go get the first filter in the list 01358 pBmpFilter = Filter::GetFirst(); 01359 while ((pBmpFilter != NULL) && (pBmpFilter->FilterID != SearchFilter)) 01360 { 01361 // Try the next filter 01362 pBmpFilter = Filter::GetNext(pBmpFilter); 01363 } 01364 } 01365 01366 // Check that the Filter existed 01367 KernelBitmap *pBitmap = NULL; 01368 if (pBmpFilter == NULL) 01369 { 01370 // We have no filter present to load it. In the case of RALPH and even in Camelot, 01371 // the best course of action will be to use a default bitmap instead. 01372 // In the case of Camelot, warn the user that this has happened. 01373 pBitmap = KernelBitmap::MakeKernelBitmap(NULL, NULL); 01374 01375 // Code below will clean this up so that:- 01376 // - we skip the bitmap definition 01377 // - we add the record number to the loaded list so that records which access this definition 01378 // get something rather than an error. 01379 01380 // If we have a pFilter then ask the default warning handle to append our message 01381 if (pFilter) 01382 { 01383 if (!WarnedBefore) 01384 { 01385 pFilter->AppendWarning(_R(IDS_NATIVE_BITMAPWARNING)); 01386 WarnedBefore = TRUE; 01387 } 01388 } 01389 else 01390 { 01391 // Shouldn't happen, as pFilter should never be null 01392 // But Warn the user about the problem, just in case it does happen 01393 InformWarning(_R(IDW_CANNOTLOADBITMAPDEF)); 01394 } 01395 //ERROR1(FALSE, _R(IDT_CANT_FIND_FILTER)); 01396 } 01397 else 01398 { 01399 // Load the bitmap definition in using that filter 01400 TRACEUSER( "Neville", _T("LoadBitmapDefinition Name %s RecordNumber %d\n"),(TCHAR*)BitmapName, RecordNumber); 01401 01402 // Now use that filter to load in the bitmap 01403 //INT32 BitmapType = 0; 01404 //BitmapInfo Info; 01405 BOOL IsNew = FALSE; 01406 BaseBitmapFilter *pBitmapFilter = (BaseBitmapFilter *)pBmpFilter; 01407 UINT32 NumberOfPaletteEntries = 0; 01408 RGBTRIPLE * pPalette = NULL; 01409 01410 if (ReadPalette) 01411 { 01412 // If we are an 8bpp JPEG then we must have saved out the palette 01413 // So load that in before anybody else gets a look in 01414 // First, read the number of entries (this is number of entries - 1) 01415 BYTE Entries = 0; 01416 if (ok) ok = pCXFile->Read(&Entries); 01417 NumberOfPaletteEntries = Entries + 1; 01418 if (ok && NumberOfPaletteEntries > 0) 01419 { 01420 pPalette = (RGBTRIPLE*)CCMalloc(NumberOfPaletteEntries * sizeof(RGBTRIPLE)); 01421 RGBTRIPLE * pPal = pPalette; 01422 // Now read the palette entries in 01423 for (UINT32 i = 0; i < NumberOfPaletteEntries; i++) 01424 { 01425 if (ok) ok = pCXFile->Read(&pPal->rgbtRed); 01426 if (ok) ok = pCXFile->Read(&pPal->rgbtGreen); 01427 if (ok) ok = pCXFile->Read(&pPal->rgbtBlue); 01428 pPal++; 01429 } 01430 } 01431 } 01432 01433 // WEBSTER - markn 10/2/97 01434 // New flag so that pPseudoFile only gets deleted when it should 01435 BOOL DeletePseudoFile = FALSE; 01436 01437 // Do we need to create a BitmapSource from this import? 01438 if (pBitmapFilter->IsFormatLossy()) 01439 { 01440 // Create a new bitmap source the size of the current record minus a bit 01441 OFFSET SourceSize = Size - (pFile->tellIn() - pos); 01442 pSource = pBitmapFilter->CreateBitmapSource(SourceSize); 01443 if (pSource == NULL || !pSource->IsOK()) 01444 { 01445 ok = FALSE; 01446 } 01447 // Now create a file that can fill it 01448 if (ok) 01449 { 01450 pPseudoFile = (CCLexFile*)new CCBufferFile(pFile); 01451 if (pPseudoFile == NULL) 01452 { 01453 ok = FALSE; 01454 } 01455 else 01456 DeletePseudoFile = TRUE; // WEBSTER - markn 10/2/97 - New flag so that pPseudoFile only gets deleted when it should 01457 } 01458 // and provide the filter with something to work with 01459 if (ok) pSource->AttachToBufferFile((CCBufferFile*)pPseudoFile); 01460 } 01461 01462 // Import that bitmap 01463 // If we have a palette then we need to convert the 24bpp image into an 8bpp image 01464 // using the supplied palette 01465 if (ok) ok = KernelBitmap::ImportBitmap(pPseudoFile, pBitmapFilter, pFilter, Compressed, 01466 pPalette, NumberOfPaletteEntries, 01467 &pBitmap, &IsNew); 01468 01469 if (ok && IsNew) 01470 { 01471 // Set the name in it 01472 pBitmap->ActualBitmap->SetName(BitmapName); 01473 // Associate the new bitmap with its source...if there is one 01474 if (pSource != NULL) 01475 { 01476 pBitmap->SetOriginalSource(pSource, pBitmapFilter); 01477 pBitmap->SetAsLossy(); 01478 } 01479 } 01480 else 01481 { 01482 // Throw away the source as we already have it or don't need it 01483 if (pSource != NULL) 01484 { 01485 delete pSource; 01486 } 01487 } 01488 01489 if (pPalette != NULL) 01490 { 01491 CCFree(pPalette); 01492 pPalette = NULL; 01493 } 01494 01495 // If we have a BitmapSource we should have had a file to use it with 01496 // Delete it 01497 if (pSource != NULL) 01498 { 01499 ERROR3IF(pPseudoFile == NULL, "pPseudoFile == NULL"); 01500 // WEBSTER - markn 10/2/97 01501 // New flag so that pPseudoFile only gets deleted when it should 01502 if (DeletePseudoFile && pPseudoFile != NULL) 01503 { 01504 delete pPseudoFile; 01505 pPseudoFile = NULL; 01506 } 01507 } 01508 } 01509 01510 if (!ok) 01511 { 01512 TRACEALL( _T("==============Failed to load bitmap in, try and recover situation\n") ); 01513 // Try some limited error recovery 01514 // First set the flag to true so it thinks everything went ok 01515 ok = TRUE; 01516 // If it has thrown a file exception error then we will need to reset the good flag 01517 // so file access still works ok 01518 pFile->SetGoodState(); 01519 // We should now fall through and skip to the end of this record/start of next 01520 // ready to read in the next bit of data. 01521 // REM Any errors will be set, we could inform error at this point but the user should get 01522 // a more friendly, a bitmap failed to load properly, using defaults. 01523 } 01524 01525 // Only do this if everything went ok 01526 if (ok) 01527 { 01528 // Note the current position in the file 01529 FilePos newpos = pFile->tellIn(); 01530 TRACEUSER( "Neville", _T("newpos %d, pos %d, newpos-pos %d should = Size %d\n"),newpos,pos,newpos-pos,Size); 01531 if (newpos - pos != (INT32)Size) 01532 { 01533 // The bitmap filter has been naughty and left the file 01534 // pointer sitting somewhere different to where it should. 01535 // We need to now fix this to where it should be 01536 pFile->seekIn(pos + Size); 01537 } 01538 } 01539 01540 // If have a genuine bitmap then add it to the loaded list 01541 // If the bitmap is null then the reference will use the default instead. 01542 if (pBitmap != NULL) 01543 pImportedBitmaps->AddBitmap(pBitmap, RecordNumber); 01544 01545 return ok; 01546 } 01547 01548 /******************************************************************************************** 01549 ********************************************************************************************/ 01550 01551 01552 /******************************************************************************************** 01553 01554 > BOOL BitmapListComponent::StartExport(BaseCamelotFilter *pFilter) 01555 01556 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01557 Created: 11/6/96 01558 Returns: TRUE if the component was able to prepare for exporting; 01559 FALSE if not (e.g. out of memory) 01560 Inputs: pFilter - the BaseCamelotFilter filter that is being used to export a file. 01561 Purpose: Inform the bitmap list document component that a Web or Native export is 01562 about to start. 01563 SeeAlso: DocComponent 01564 01565 ********************************************************************************************/ 01566 01567 BOOL BitmapListComponent::StartExport(BaseCamelotFilter *pFilter) 01568 { 01569 #ifdef DO_EXPORT 01570 TRACEUSER( "Neville", _T("BitmapListComponent::StartExport\n") ); 01571 // Mark all bitmaps as unsaved 01572 if (pFilter == NULL) 01573 { 01574 ERROR3("BitmapListComponent::StartExport filter is null!"); 01575 return TRUE; 01576 } 01577 01578 // Set up and start the exported bitmap list 01579 pExportedBitmaps = new ExportedBitmaps(); 01580 if (pExportedBitmaps == NULL) 01581 return FALSE; 01582 #endif 01583 return TRUE; 01584 } 01585 01586 /******************************************************************************************** 01587 01588 > BOOL BitmapListComponent::EndExport(BaseCamelotFilter *pFilter, BOOL Success) 01589 01590 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01591 Created: 11/6/96 01592 Inputs: pFilter - the BaseCamelotFilter filter that is being used to import a file. 01593 Success - True if everything went swimmingly, False if just a clean up is required. 01594 Purpose: Inform the bitmap list document component that a Web or Native export has 01595 just finished. 01596 Returns: TRUE if the component was able to end the importing; 01597 FALSE if not (e.g. out of memory) 01598 SeeAlso: DocComponent 01599 01600 ********************************************************************************************/ 01601 01602 BOOL BitmapListComponent::EndExport(BaseCamelotFilter *pFilter, BOOL Success) 01603 { 01604 #ifdef DO_EXPORT 01605 // ERROR2IF(pExportedBitmaps == NULL, FALSE, "BitmapListComponent::EndExport no pExportedBitmaps!"); 01606 // If we error about the pExportedBitmaps then we assume that the EndImport has been called. 01607 // This may not be the case if we are in clean up mode. So just handle it! 01608 01609 TRACEUSER( "Neville", _T("BitmapListComponent::EndExport\n") ); 01610 if (pFilter == NULL) 01611 { 01612 ERROR3("BitmapListComponent::EndExport filter is null!"); 01613 return TRUE; 01614 } 01615 01616 // Check if Web or Native, if Web do nothing 01617 // If Native and we are not just in clean up mode, Save out any unsaved bitmaps 01618 //if (!pFilter->IsWebFilter() && Success) 01619 //{ 01620 //TRACEUSER( "Neville", _T("BitmapListComponent::EndExport exporting unsaved bitmaps\n")); 01621 /* // Count the number of Bitmaps 01622 INT32 TotalBitmaps = 0; 01623 KernelBitmap* pBitmap = (KernelBitmap*) pBitmaps->GetHead(); 01624 01625 while (pBitmap != NULL) 01626 { 01627 // Find the next one 01628 if (pBitmap->GetUsageCount() > 0) 01629 TotalBitmaps++; // Only count this bitmap if it really used 01630 01631 pBitmap = (KernelBitmap*) pBitmaps->GetNext(pBitmap); 01632 } 01633 //} 01634 */ 01635 // As we have finished with it now, destroy the list of exported bitmaps 01636 if (pExportedBitmaps) 01637 { 01638 delete pExportedBitmaps; 01639 pExportedBitmaps = NULL; 01640 } 01641 01642 #if 0 01643 if(Success) 01644 SGLibOil::ExportWav(pFilter); 01645 #endif 01646 01647 #endif 01648 return TRUE; 01649 } 01650 01651 /******************************************************************************************** 01652 01653 > INT32 BitmapListComponent::GetWriteBitmapReference(KernelBitmap* pBitmap, BaseCamelotFilter *pFilter) 01654 01655 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01656 Created: 11/6/96 01657 Inputs: pBitmap - The document bitmap to save 01658 pFilter - The filter to use for saving 01659 Outputs: - 01660 Returns: The bitmap reference for the kernel bitmap ready for writing in a record. 01661 This will be zero if a problem has occurred. May return -1 if it does not 01662 need to save anything i.e if the bitmap is not in use. 01663 01664 Purpose: Return the bitmap reference to the caller, who will then use it to write the 01665 bitmap in the record that they are preparing to save to a Web or Native file. 01666 In the process of getting the bitmap reference, the bitmap definition record 01667 for the bitmap reference will be generated and saved to the file. 01668 In the web format, the bitmap may have been reduced in resolution, 01669 colour resolution or cropped to try and reduce the size saved out. 01670 NOTE: As this does save information into the record stream, it *MUST* be called 01671 before the caller has called StartRecord() as otherwise the records will become 01672 intertwined! 01673 SeeAlso: DocComponent 01674 01675 ********************************************************************************************/ 01676 01677 INT32 BitmapListComponent::GetWriteBitmapReference(KernelBitmap* pBitmap, BaseCamelotFilter *pFilter) 01678 { 01679 #ifdef DO_EXPORT 01680 ERROR2IF(pBitmap == NULL,0L,"BitmapListComponent::GetWriteBitmapReference null pBitmap"); 01681 ERROR2IF(pFilter == NULL,0L,"BitmapListComponent::GetWriteBitmapReference null pFilter"); 01682 01683 INT32 RecordNumber = 0L; 01684 01685 // Check for a deleted bitmap 01686 if (pBitmap->HasBeenDeleted()) 01687 { 01688 ERROR2IF(pBitmap->GetParentBitmapList() == NULL, 0L, "Deleted bitmap has no parent list"); 01689 01690 // Use the default bitmap instead 01691 pBitmap = pBitmap->GetParentBitmapList()->FindDefaultBitmap(); 01692 01693 // There should always be a default bitmap in the list 01694 ERROR2IF(pBitmap == NULL, 0L, "Couldn't find the default bitmap"); 01695 } 01696 01697 // Check if the bitmap is the default one 01698 // We could save this as a unique -ve reference but this implies we have the bitmap 01699 // bound into ALL exes i.e. RALPH and the viewer. Which makes them 77k bigger. Not many 01700 // people will use the default bitmap and if they do will not assume that it is assumed. 01701 // They will want and expect the document to contain the bitmap so that it is standalone. 01702 // Also, what happens if we change the default. Then we need the old and the new default 01703 // bound in! 01704 //if (pBitmap->IsDefaultBitmap()) 01705 //{ 01706 // If so then there is no point in saving out the definition, just save out 01707 // our unique identifier for this bitmap i.e. pass this back to the caller 01708 // return REF_DEFAULTBITMAP_BUILTIN; 01709 //} 01710 01711 // Save out that bitmap definition into the file using the bitmap compression value 01712 // possibly requested by the user 01713 RecordNumber = SaveBitmapDefinition(pBitmap, pFilter); 01714 01715 return RecordNumber; 01716 #else 01717 return 0; 01718 #endif 01719 } 01720 01721 01722 /******************************************************************************************** 01723 01724 > BOOL BitmapListComponent::WriteBitmapPropertiesRecord(KernelBitmap* pBitmap, BaseCamelotFilter *pFilter, INT32 BmpRef) 01725 01726 Author: Andy_Hills (Xara Group Ltd) <camelotdev@xara.com> 01727 Created: 31/10/00 01728 Inputs: pBitmap - The document bitmap to save 01729 pFilter - The filter to use for saving 01730 BmpRef - The bitmap reference 01731 Outputs: - 01732 Returns: TRUE on success. 01733 Purpose: Helper function for SaveBitmapDefinition. 01734 Write out 'bitmap properties' record. 01735 This contains: 01736 * A bitmap reference (INT32). This specifies the bitmap to which the 01737 properties apply. (This will usually be the bitmap record which 01738 immediately preceded this bmp properties record.) 01739 * A single flag byte. The LSB stores the value of the 'smooth when 01740 scaled up' flag - 1 for yes, 0 for no. Other bits could be used to 01741 record other boolean bmp properties; for now these are set to 0. 01742 * 7 more bytes for future use. Some of this space should be used to 01743 store GIF animation info (which is presently not saved). 01744 The remainder of the space is reserved for possible future additions 01745 to the bmp properties dialogue. 01746 SeeAlso: SaveBitmapDefinition 01747 01748 ********************************************************************************************/ 01749 01750 BOOL BitmapListComponent::WriteBitmapPropertiesRecord(KernelBitmap* pBitmap, BaseCamelotFilter *pFilter, INT32 BmpRef) 01751 { 01752 BOOL ok = TRUE; 01753 01754 // populate the record 01755 BYTE Flags = 0x00; 01756 if (pBitmap->GetInterpolation()) Flags |= 0x01; 01757 01758 // Find out whether we need to make an XPE record or not... 01759 PORTNOTE("other","KernelBitmap::GetXPEInfo removed") 01760 #ifndef EXCLUDE_FROM_XARALX 01761 if (pFilter->GetSaveXPEBitmaps() == FALSE) 01762 { 01763 KernelBitmap* pMaster = NULL; 01764 IXMLDOMDocumentPtr pEditList = NULL; 01765 pBitmap->GetXPEInfo(pMaster, pEditList); 01766 if (pMaster!=NULL && pEditList!=NULL) 01767 { 01768 // Get master bitmap reference number (writing out the bitmap if necessary) 01769 INT32 MasterRecord = 0; 01770 MasterRecord = GetWriteBitmapReference(pMaster, pFilter); 01771 01772 // Only write out new record style if we really have to... 01773 // (Helps forward compatibility) 01774 if (MasterRecord!=0) 01775 { 01776 // Create a new style XPE bitmap properties record 01777 CXaraFileRecord Rec(TAG_XPE_BITMAP_PROPERTIES); 01778 01779 BSTR bstrValue; 01780 HRESULT hr; 01781 hr = pEditList->get_xml(&bstrValue); 01782 if (SUCCEEDED(hr)) 01783 { 01784 ok = Rec.Init(); 01785 if (ok) ok = Rec.WriteReference(BmpRef); // bitmap reference 01786 if (ok) ok = Rec.WriteBYTE(Flags); // flags 01787 01788 // TODO: write GIF animation properties here 01789 01790 // reserved bytes 01791 for( INT32 i=0; i<7; i++ ) 01792 { 01793 if (ok) ok = Rec.WriteBYTE(0); 01794 } 01795 01796 // Now write out XPE stuff 01797 if (ok) ok = Rec.WriteReference(MasterRecord); // Master bitmap record number 01798 if (ok) ok = Rec.WriteUnicode(pBitmap->GetName()); // Oil Bitmap name 01799 if (ok) ok = Rec.WriteBSTR(bstrValue); // UNICODE xml string edits list 01800 01801 // Write the record 01802 if (ok) ok = pFilter->Write(&Rec); 01803 01804 return ok; 01805 } 01806 } 01807 } 01808 } 01809 #endif 01810 01811 // Fallback to the original BITMAP PROPERTIES record style 01812 // Create an old style properties record 01813 CXaraFileRecord Rec(TAG_BITMAP_PROPERTIES,TAG_BITMAP_PROPERTIES_SIZE); 01814 01815 ok = Rec.Init(); 01816 if (ok) ok = Rec.WriteReference(BmpRef); // bitmap reference 01817 if (ok) ok = Rec.WriteBYTE(Flags); // flags 01818 01819 // TODO: write GIF animation properties here 01820 01821 // reserved bytes 01822 for( INT32 i=0; i<7; i++ ) 01823 { 01824 if (ok) ok = Rec.WriteBYTE(0); 01825 } 01826 01827 // Write the record 01828 if (ok) ok = pFilter->Write(&Rec); 01829 01830 return ok; 01831 } 01832 01833 01834 /******************************************************************************************** 01835 01836 > INT32 BitmapListComponent::SaveBitmapDefinition(KernelBitmap* pBitmap, BaseCamelotFilter *pFilter) 01837 01838 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01839 Created: 12/6/96 01840 Inputs: pBitmap - The document bitmap to save 01841 pFilter - The filter to use for saving 01842 Outputs: - 01843 Returns: The bitmap reference for the kernel bitmap ready for writing in a record. 01844 This will be zero if a problem has occurred. May return -1 if it does not 01845 need to save anything i.e if the bitmap is not in use. 01846 01847 Purpose: This actually saves out the bitmap definition into the file and returns the 01848 bitmap reference or record number to the caller. They will then be able to 01849 use it to write the bitmap in the record that they are preparing to save to 01850 a Web or Native file. 01851 SeeAlso: DocComponent 01852 01853 ********************************************************************************************/ 01854 01855 INT32 BitmapListComponent::SaveBitmapDefinition(KernelBitmap* pBitmap, BaseCamelotFilter *pFilter) 01856 { 01857 #ifdef DO_EXPORT 01858 ERROR2IF(pBitmap == NULL,0L,"BitmapListComponent::GetWriteBitmapReference null pBitmap"); 01859 ERROR2IF(pFilter == NULL,0L,"BitmapListComponent::GetWriteBitmapReference null pFilter"); 01860 01861 INT32 RecordNumber = 0L; 01862 01863 // Check for a deleted bitmap 01864 if (pBitmap->HasBeenDeleted()) 01865 { 01866 ERROR2IF(pBitmap->GetParentBitmapList() == NULL, 0L, "Deleted bitmap has no parent list"); 01867 01868 // Use the default bitmap instead 01869 pBitmap = pBitmap->GetParentBitmapList()->FindDefaultBitmap(); 01870 01871 // There should always be a default bitmap in the list 01872 ERROR2IF(pBitmap == NULL, 0L, "Couldn't find the default bitmap"); 01873 } 01874 01875 // **** 01876 // **** Saved this bitmap before? 01877 // **** 01878 01879 // Only write this record out if we have not done so already 01880 // Check by seeing if the bitmap is already in our exported bitmap list 01881 ExportBitmap* pExportBitmap = NULL; 01882 pExportBitmap = pExportedBitmaps->GetBitmap(pBitmap); 01883 // If it is then do not save this bitmap 01884 if (pExportBitmap) 01885 { 01886 // Just return the record number as the bitmap reference to the caller 01887 return pExportBitmap->RecordNumber; 01888 } 01889 01890 PORTNOTE("other", "Removed live effects stuff") 01891 #ifndef EXCLUDE_FROM_XARALX 01892 // Check to see whether we can save a simple placeholder, relying on the 01893 // XPE to regenerate the bitmap from master and edits when it's reloaded. 01894 if (pFilter->GetSaveXPEBitmaps() == FALSE) 01895 { 01896 KernelBitmap* pMaster = NULL; 01897 IXMLDOMDocumentPtr pEdits = NULL; 01898 pBitmap->GetXPEInfo(pMaster, pEdits); 01899 if (pMaster != NULL && pEdits != NULL) 01900 { 01901 // Yes, we have a valid set of XPE info so we can regenerate on loading 01902 UINT32 recnum = pFilter->WriteXPEBitmapPlaceHolder(pBitmap->GetName()); 01903 if (recnum!=0) 01904 { 01905 BOOL bOK = FALSE; 01906 01907 // write out a bitmap properties record 01908 bOK = WriteBitmapPropertiesRecord(pBitmap, pFilter, recnum); 01909 if (!bOK) return 0L; 01910 01911 // Now add this exported bitmap definition record to our exported list for later reuse 01912 pExportedBitmaps->AddBitmap(pBitmap, recnum); 01913 01914 return recnum; 01915 } 01916 } 01917 } 01918 #endif 01919 01920 BOOL ok = TRUE; 01921 // Find out what bitmap compression was requested by the user 01922 // Could use BMPZIP which could be deemed to mean no compression 01923 // > 100 means use PNG 01924 // 0-100 use JPEG with this quality setting 01925 // Of course, only do this if we are in web mode 01926 INT32 Compression = pFilter->GetBitmapCompression(); 01927 01928 // Get details of the bitmap 01929 BitmapInfo Info; 01930 String_256 BitmapName; 01931 pBitmap->ActualBitmap->GetInfo(&Info); 01932 BitmapName = pBitmap->ActualBitmap->GetName(); 01933 01934 // double Dpi = Info.PixelDepth; 01935 UINT32 Height = Info.PixelHeight; 01936 UINT32 NumberOfPaletteEntries = Info.NumPaletteEntries; // 0 for no palette 01937 01938 UINT32 SearchFilter = 0; 01939 INT32 Tag = TAG_DEFINEBITMAP_BMP; 01940 01941 // See if we have a BitmapSource for the bitmap we're exporting 01942 BitmapSource* pSource = NULL; 01943 BaseBitmapFilter* pDummyFilter; 01944 BOOL bUseOriginalSource = pBitmap->GetOriginalSource(&pSource, &pDummyFilter); 01945 BOOL WritePalette = FALSE; 01946 01947 if (!bUseOriginalSource) 01948 { 01949 // We don't already have a compressed source so pick a filter 01950 01951 UINT32 Bpp = Info.PixelDepth; 01952 // Check if the bitmap has a transparent colour or masking colour present. 01953 // If so then we may need to change our saving strategy 01954 INT32 TransparentColour = -1; 01955 if (Bpp <= 8) 01956 pBitmap->ActualBitmap->GetTransparencyIndex(&TransparentColour); 01957 01958 switch (Bpp) 01959 { 01960 case 1: 01961 case 4: 01962 // Cannot use JPEG as only for 8,24bpp 01963 // Both GIF and PNG support transparency 01964 // So always use the PNG filter. 01965 Tag = TAG_DEFINEBITMAP_PNG; 01966 SearchFilter = FILTERID_PNG; 01967 break; 01968 case 8: 01969 // JPEG does not support transparency, so if this is set then use PNG 01970 if (TransparentColour == -1) 01971 { 01972 // If it is 8bpp and there is a no transparent colour present 01973 // then we can JPEG the bitmap or PNG it. Using Accusoft this will save 01974 // out the bitmap as a 24bpp JPEGd bitmap. 01975 // If compression is between 0 and 100 then use JPEG 01976 // otherwise use PNG 01977 if (Compression >= 0 && Compression <= 100) 01978 { 01979 // Check if greyscale or not. If greyscale then legal JPEG so save as normal 01980 // otherwise save as special 8BPP JPEG record 01981 if (pBitmap->IsGreyscale()) 01982 { 01983 Tag = TAG_DEFINEBITMAP_JPEG; 01984 SearchFilter = FILTERID_EXPORT_JPEG; 01985 } 01986 else 01987 { 01988 Tag = TAG_DEFINEBITMAP_JPEG8BPP; 01989 SearchFilter = FILTERID_EXPORT_JPEG; 01990 WritePalette = TRUE; 01991 } 01992 } 01993 else 01994 { 01995 Tag = TAG_DEFINEBITMAP_PNG; 01996 SearchFilter = FILTERID_PNG; 01997 } 01998 } 01999 else 02000 { 02001 // If it is 8bpp and there is a transparent colour present 02002 // then we must use PNG to save out this colour 02003 Tag = TAG_DEFINEBITMAP_PNG; 02004 SearchFilter = FILTERID_PNG; 02005 } 02006 break; 02007 case 24: 02008 // If compression is between 0 and 100 then use JPEG 02009 // otherwise use PNG 02010 if (Compression >= 0 && Compression <= 100) 02011 { 02012 Tag = TAG_DEFINEBITMAP_JPEG; 02013 SearchFilter = FILTERID_EXPORT_JPEG; 02014 } 02015 else if (Compression >= 201 && Compression <= 300) 02016 { 02017 // If compression is between 201 and 300 then use JPEG 02018 // where the bitmap came from a lossy source 02019 if (pBitmap->IsLossy()) 02020 { 02021 Tag = TAG_DEFINEBITMAP_JPEG; 02022 SearchFilter = FILTERID_EXPORT_JPEG; 02023 Compression -= 200; // Get quality in the correct range 02024 } 02025 else 02026 { 02027 Tag = TAG_DEFINEBITMAP_PNG; 02028 SearchFilter = FILTERID_PNG; 02029 } 02030 } 02031 else 02032 { 02033 Tag = TAG_DEFINEBITMAP_PNG; 02034 SearchFilter = FILTERID_PNG; 02035 } 02036 break; 02037 case 32: 02038 if (Compression >= 0 && Compression <= 200) 02039 { 02040 // Definitely use PNG is this case 02041 Tag = TAG_DEFINEBITMAP_PNG; 02042 SearchFilter = FILTERID_PNG; 02043 } 02044 else 02045 { 02046 // If compression indicates JPEG where possible then use 02047 // JPEG where the bitmap came from a lossy source and has 02048 // no transparency in its alpha channel 02049 if (pBitmap->IsLossy() && !pBitmap->IsTransparent()) 02050 { 02051 Tag = TAG_DEFINEBITMAP_JPEG; 02052 SearchFilter = FILTERID_EXPORT_JPEG; 02053 Compression -= 200; // Get quality in the correct range 02054 } 02055 else 02056 { 02057 Tag = TAG_DEFINEBITMAP_PNG; 02058 SearchFilter = FILTERID_PNG; 02059 } 02060 } 02061 break; 02062 default: 02063 ERROR2(0,"BitmapListComponent::SaveBitmapDefinition bad pixel depth"); 02064 } 02065 } 02066 else 02067 { 02068 // We have a BitmapSource... 02069 // but we don't have the right filter...get rid of this hack! 02070 // FilterManager* pFilterManager = Camelot->GetFilterManager(); 02071 // pFilter = pFilterManager->FindComplementaryFilter(pDummyFilter); 02072 Tag = TAG_DEFINEBITMAP_JPEG; 02073 SearchFilter = FILTERID_EXPORT_JPEG; 02074 // Now check if we have done a 24bpp to 8bpp conversion job on this 02075 // The way we can tell this is if the bitmap is 8bpp and not greyscale 02076 UINT32 Bpp = Info.PixelDepth; 02077 if (Bpp == 8 && !pBitmap->IsGreyscale()) 02078 { 02079 Tag = TAG_DEFINEBITMAP_JPEG8BPP; 02080 WritePalette = TRUE; 02081 } 02082 } 02083 02084 // Try and find the bitmap filter to use to load that bitmap in 02085 // Go get the first filter in the list 02086 Filter *pBmpFilter = Filter::GetFirst(); 02087 while ((pBmpFilter != NULL) && (pBmpFilter->FilterID != SearchFilter)) 02088 { 02089 // Try the next filter 02090 pBmpFilter = Filter::GetNext(pBmpFilter); 02091 } 02092 02093 // Check that the Filter existed 02094 ERROR2IF(pBmpFilter == NULL,0,"BitmapListComponent::SaveBitmapDefinition can't find export filter!"); 02095 02096 // Start writing our record data out to file 02097 UINT32 Size = 0; 02098 // If there is a string name, then add it to this size 02099 // REMEMBER: We save out unicode strings and so we need to double the length of the returned string length 02100 // but only if we are not being compiled as Unicode 02101 Size += (BitmapName.Length() + 1) * SIZEOF_XAR_UTF16; 02102 if (WritePalette) 02103 { 02104 // If we are an 8bpp JPEG then we must save out the palette so that on loading we can 02105 // convert the 24bpp JPEG back into 8bpp using this palette 02106 Size += 1; // For the number of palette entries 02107 Size += NumberOfPaletteEntries * sizeof(RGBTRIPLE); 02108 } 02109 02110 RecordNumber = pFilter->StartStreamedRecord(Tag, Size); 02111 //RecordNumber = pFilter->StartRecord(Tag, Size); 02112 // If we had a problem starting the record up then exit now 02113 if (RecordNumber <= 0) 02114 return RecordNumber; 02115 02116 // Write out the name to disc 02117 ok = pFilter->Write(BitmapName); 02118 02119 // Possibly write palette information into the record 02120 if (WritePalette) 02121 { 02122 TRACEUSER( "Neville", _T("8bpp JPEG write palette size %d to file\n"), NumberOfPaletteEntries ); 02123 // If we are an 8bpp JPEG then we must save out the palette so that on loading we can 02124 // convert the 24bpp JPEG back into 8bpp using this palette 02125 // Saves number of palette entries followed by the palette in RGB triples 02126 pBitmap->WritePalette(pFilter); 02127 } 02128 02129 // Write out the bitmap data to file 02130 // First get the CCFile that we are using for writing out the data 02131 CCLexFile* pFile = pFilter->GetCCFile(); 02132 // The WriteBitmapToFile function is only available in bitmap filters so we need 02133 // to convert our pointer to that type of filter 02134 BaseBitmapFilter *pBitmapFilter = (BaseBitmapFilter *)pBmpFilter; 02135 // On the first pass this will be null as we are trying to work out the export size 02136 // so that we get the progress bar correct. 02137 if (pFile) 02138 { 02139 // Ensure all current data is flushed to file otherwise some filters 02140 // may screw up the file. 02141 pFile->flush(); 02142 02143 // Check to see if we haven't already got it compressed 02144 if (bUseOriginalSource) 02145 { 02146 // We have,so write out the source & don't degrade it 02147 ERROR2IF(pSource == NULL, 0L, "pSource == NULL"); 02148 pFilter->WriteBitmapSource(*pSource, Height); 02149 } 02150 else 02151 { 02152 // We are on the real pass so go and export that bitmap data to file 02153 pBitmapFilter->WriteBitmapToFile(pBitmap, pFilter, pFile, Compression); 02154 } 02155 } 02156 else 02157 { 02158 if (WritePalette) 02159 { 02160 // If we are on the fake pass and saving the palette then include the number of 02161 // palette entries in the count. 02162 pFilter->IncProgressBarCount(NumberOfPaletteEntries); 02163 } 02164 02165 // We are on the fake pass so add the height of the bitmap onto the progress bar count 02166 // as this is what we will use the update the progress bar 02167 pFilter->IncProgressBarCount(Height); 02168 } 02169 02170 // Ask for the record to be ended and hence items like the size in the record header 02171 // to be cleaned up and hence made correct 02172 if (ok) ok = pFilter->EndStreamedRecord(); 02173 02174 // write out a bitmap properties record 02175 if (ok) ok = WriteBitmapPropertiesRecord(pBitmap, pFilter, RecordNumber); 02176 02177 // If we have had a problem at any of the stages then return that to the caller 02178 if (!ok) 02179 return 0L; 02180 02181 // Now add this exported bitmap definition record to our exported list for later reuse 02182 if (ok) ok = pExportedBitmaps->AddBitmap(pBitmap, RecordNumber); 02183 02184 return RecordNumber; 02185 #else 02186 return 0; 02187 #endif 02188 }