bmpcomp.cpp

Go to the documentation of this file.
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 }

Generated on Sat Nov 10 03:44:27 2007 for Camelot by  doxygen 1.4.4