impcol.cpp

Go to the documentation of this file.
00001 // $Id: impcol.cpp 1282 2006-06-09 09:46:49Z alex $
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 // Encapsulates a set of colours imported from a file.
00100 
00101 /*
00102 */
00103 
00104 #include "camtypes.h"
00105 
00106 #include "impcol.h"
00107 
00108 #include "colcomp.h"    // colour document component
00109 //#include "resource.h"
00110 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 #include "colormgr.h"
00112 #include "progress.h"
00113 //#include "ben.h"
00114 //#include "filtrres.h" // _R(IDS_NATIVE_SORTCOLOURS)
00115 
00116 DECLARE_SOURCE("$Revision: 1282 $");
00117 
00118 
00119 NewColourInfo::NewColourInfo()
00120 {
00121     // Initially a normal colour
00122     Type = COLOURTYPE_NORMAL;
00123 
00124     // If linked, defaults to no inheritance.
00125     for (INT32 i = 0; i < 4; i++)
00126         Inherits[i] = FALSE;
00127 
00128     // If tinted, then no change in colour
00129     TintValue = 100.0;
00130 
00131     // By default tints are normal tints, not shades.
00132     TintIsShade = FALSE;
00133 
00134 // New bits for native/web file filter
00135     // By default we are not defining a web or native style colour
00136     WebNativeColour = FALSE;
00137     // By default this colour has not been imported yet so flag this in our variables
00138     pParentCol = NULL;
00139     RecordNumber = 0L;
00140     EntryNumber = 0L;
00141 }
00142 
00143 /********************************************************************************************
00144 
00145 >   class ContextItem : public ListItem
00146 
00147     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00148     Created:    01/12/94
00149     Purpose:    Provides information on a context level - see ColourImportContext for
00150                 more detail.
00151     SeeAlso:    ColourImportContext
00152 
00153 ********************************************************************************************/
00154 
00155 class ContextItem : public ListItem
00156 {
00157     CC_DECLARE_MEMDUMP(ContextItem)
00158 
00159 public:
00160     ContextItem(IndexedColour *pContext) : pCol(pContext) {}
00161 
00162 public:
00163     IndexedColour *pCol;
00164 
00165 private:
00166     // Prevent default constructor from being used.
00167     ContextItem();
00168 };
00169 
00170 
00171 
00172 
00173 CC_IMPLEMENT_MEMDUMP(NewColour, ListItem)
00174 CC_IMPLEMENT_MEMDUMP(NewColourList, List)
00175 CC_IMPLEMENT_MEMDUMP(ImportedColours, CCObject)
00176 CC_IMPLEMENT_MEMDUMP(ColourImportContext, List)
00177 CC_IMPLEMENT_MEMDUMP(ContextItem, ListItem)
00178 
00179 
00180 // Declare smart memory handling in Debug builds
00181 #define new CAM_DEBUG_NEW
00182 
00183 
00184 ColourImportContext::ColourImportContext()
00185 {
00186 }
00187 
00188 ColourImportContext::~ColourImportContext()
00189 {
00190     // Just lose all the items in our list.
00191     DeleteAll();
00192 }
00193 
00194 BOOL ColourImportContext::Init()
00195 {
00196     // Add an initial context item
00197     ContextItem *pItem = new ContextItem(NULL);
00198     if (pItem == NULL)
00199         return FALSE;
00200 
00201     // Add to the list
00202     AddTail(pItem);
00203 
00204     // All ok
00205     return TRUE;
00206 }
00207 
00208 
00209 void ColourImportContext::SetContext(IndexedColour *pCol)
00210 {
00211     // Get the current context item (always the last)
00212     ContextItem *pItem = (ContextItem *) GetTail();
00213 
00214     // Update its colour pointer
00215     pItem->pCol = pCol;
00216 }
00217 
00218 
00219 IndexedColour *ColourImportContext::GetContext()
00220 {
00221     // Get the current context item (always the last)
00222     ContextItem *pItem = (ContextItem *) GetTail();
00223 
00224     // Return its colour pointer
00225     return pItem->pCol;
00226 }
00227 
00228 BOOL ColourImportContext::SaveContext()
00229 {
00230     // Get a pointer to the current context node
00231     ContextItem *pCurrentItem = (ContextItem *) GetTail();
00232 
00233     // Add a new context node to the end of the list, and give it the same
00234     // context as the current context node.
00235     ContextItem *pItem = new ContextItem(pCurrentItem->pCol);
00236     if (pItem == NULL)
00237         return FALSE;
00238 
00239     // Add to the list
00240     AddTail(pItem);
00241 
00242     // All ok
00243     return TRUE;
00244 }
00245 
00246 BOOL ColourImportContext::RestoreContext()
00247 {
00248     // Make sure we can do this - must always have at least one node
00249     if (GetCount() <= 1)
00250     {
00251         ERROR3("Bad call to ColourImportContext::RestoreContext()");
00252         return FALSE;
00253     }
00254 
00255     // Remove and delete the last context item
00256     delete RemoveTail();
00257 
00258     // All ok
00259     return TRUE;
00260 }
00261 
00262 BOOL ColourImportContext::RestoreContextTo(UINT32 NewLevel)
00263 {
00264     // How many should we delete?
00265     INT32 NumToDelete = (INT32) (GetCount() - NewLevel) - 1;
00266 
00267     // Make sure this is a legal request.
00268     if (NumToDelete < 0)
00269         // No - return failure
00270         return FALSE;
00271 
00272     // Ok - delete this many items
00273     while (NumToDelete > 0)
00274     {
00275         if (!RestoreContext())
00276         {
00277             ERROR3("Bad call to ColourImportContext::RestoreContextTo()");
00278             return FALSE;
00279         }
00280 
00281         NumToDelete--;
00282     }
00283 
00284     // All ok
00285     return TRUE;
00286 }
00287 
00288 
00289 
00290 /********************************************************************************************
00291 
00292 >   NewColour::NewColour(IndexedColour *pNewCol, BOOL AlreadyExists)
00293 
00294     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00295     Created:    30/11/94
00296     Inputs:     pNewCol - the colour to put in the list.
00297                 AlreadyExists - TRUE if pNewCol points to a colour that already exists in
00298                                 the destination document;
00299                                 FALSE if pNewCol poinst to a brand new colour.
00300     Purpose:    Create a new colour list item from the given indexed colour.
00301     SeeAlso:    NewColourList; NewColourList::AddColour
00302 
00303 ********************************************************************************************/
00304 
00305 NewColour::NewColour(IndexedColour *pNewCol, BOOL AlreadyExists)
00306 {
00307     // Initialise to sensible values.
00308     pCol = pNewCol;
00309     AlreadyExistsInDoc = AlreadyExists;
00310     Duplicate = FALSE;
00311     pNextDuplicate = NULL;
00312 
00313     // Get CMYK version of this colour for comparisons - this looks a bit nasty, but 
00314     // actually I think it's the cleanest way of doing this.
00315     DocColour TempCol;
00316     TempCol.MakeRefToIndexedColour(pNewCol);
00317     TempCol.GetCMYKValue(&ColDefn);
00318 
00319     // New web/native filter bits
00320     RecordNumber = 0L;
00321     EntryNumber = 0L;
00322 }
00323 
00324 
00325 /********************************************************************************************
00326 
00327 >   BOOL NewColour::AddDuplicateColour(IndexedColour **pNewCol,
00328                                        BOOL AlreadyExists)
00329 
00330     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00331     Created:    30/11/94
00332     Inputs:     pNewCol - (pointer to a) pointer to the IndexedColour object to link to pMaster
00333                           because they both have the same colour name.
00334 
00335                 AlreadyExists - TRUE => pNewCol matches a colour that is already in the
00336                                         destination document.
00337                                FALSE => pNewCol does not match any colours in the 
00338                                         destination document.
00339 
00340     Outputs:    pNewCol pointer is updated to point at the colour to use for the colour
00341                 passed in (see below).
00342 
00343     Returns:    TRUE if the duplicate could be added;
00344                 FALSE if out of memory => ERROR1
00345 
00346     Purpose:    Add another definition of a colour to an existing colour definition.
00347                 i.e. We have a new colour but we have already found a definition of this
00348                 colour name while importing, so we have duplicate colour names, so the
00349                 IndexedColour object pointed to by pNewCol should be linked to the
00350                 existing item (with which it shares a colour name).
00351 
00352     Notes:      AddDuplicateColour handles 2 types of duplicates:
00353                 
00354                 1) Duplicated name, but different colour definitions. In this case, the
00355                 dupes are remembered and added to the document (the colour list will ensure
00356                 they have unique names when finally added)
00357 
00358                 2) Exact duplicate (now possible with parents of shade colours which might
00359                 be defined twice in a CamEPS document). These are deleted out of hand,
00360                 and the pNewCol pointer is updated to point at the original/first definition
00361                 of the identical colour.
00362 
00363     Errors:     Out of memory => ERROR1
00364     SeeAlso:    NewColour; ImportedColours::AddColour
00365 
00366 ********************************************************************************************/
00367 
00368 BOOL NewColour::AddDuplicateColour(IndexedColour **pNewCol, BOOL AlreadyExists)
00369 {
00370     ERROR3IF(pNewCol == NULL || *pNewCol == NULL, "Illegal NULL param");
00371 
00372     // --- First, check if this colour is a real duplicate or just a duplicate in name
00373     // If it is a duplicate name, then we keep a copy around, but if it is a complete
00374     // duplicate, then we want to vape it and NOT put it in the dupes list - Jason
00375 
00376     // NOTE: We *ONLY* do this if the colour is not already part of the existing document
00377     // (i.e. was merged with an existing exact match colour in the doc), i.e. if !AlreadyExists
00378 
00379     if (!AlreadyExists)
00380     {
00381         NewColour *Ptr = this;
00382         while (Ptr != NULL)
00383         {
00384             if (!(*pNewCol)->IsDifferent(*(Ptr->pCol)))
00385             {
00386                 delete (*pNewCol);          // delete the identical twin
00387                 *pNewCol = Ptr->pCol;       // and return the pointer pointing at the original definition
00388                 return(TRUE);
00389             }
00390 
00391             Ptr = Ptr->pNextDuplicate;
00392         }
00393     }   
00394 
00395     // --- And now back to our regularly scheduled programme...
00396 
00397 
00398 
00399     // First, try to make a new item
00400     NewColour *pNewItem = new NewColour(*pNewCol, AlreadyExists);
00401     if (pNewItem == NULL)
00402         return FALSE;
00403 
00404     // Mark this object as being a duplicate
00405     Duplicate = TRUE;
00406 
00407     // Ok, link to this object (at end of the one-way list)...
00408     NewColour *pLast = this;
00409     while (pLast->pNextDuplicate != NULL)
00410         pLast = pLast->pNextDuplicate;
00411 
00412     // Found end of list - link it in and mark it as being a duplicate
00413     pLast->pNextDuplicate = pNewItem;
00414     pNewItem->Duplicate = TRUE;
00415 
00416     // Worked ok
00417     return TRUE;
00418 }
00419 
00420 
00421 /********************************************************************************************
00422 
00423 >   NewColour *NewColourList::AddColour(IndexedColour *pCol)
00424 
00425     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00426     Created:    30/11/94
00427     Inputs:     pCol - the new colour to add to the document.
00428                 AlreadyExists - TRUE if pNewCol points to a colour that already exists in
00429                                 the destination document;
00430                                 FALSE if pNewCol poinst to a brand new colour.
00431     Returns:    Pointer to the newly added colour, or 
00432                 NULL if out of memory => ERROR1
00433     Purpose:    Add a new colour to the list of colours.
00434     Errors:     Out of memory => ERROR1
00435     SeeAlso:    NewColour
00436 
00437 ********************************************************************************************/
00438 
00439 NewColour *NewColourList::AddColour(IndexedColour *pCol, BOOL AlreadyExists)
00440 {
00441     NewColour *pNewCol = new NewColour(pCol, AlreadyExists);
00442 
00443     // Check for out of memory
00444     if (pNewCol == NULL)
00445         return NULL;
00446 
00447     // Add to the list and return success
00448     AddTail(pNewCol);
00449     return pNewCol;
00450 }
00451 
00452 
00453 /********************************************************************************************
00454 
00455 >   DWORD NewColourList::GetCount()
00456 
00457     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00458     Created:    01/12/94
00459     Returns:    Number of colours in this list.
00460     Purpose:    Find out how many colours are held in this list - this includes any
00461                 duplicates.
00462 
00463 ********************************************************************************************/
00464 
00465 DWORD NewColourList::GetCount() const
00466 {
00467     DWORD Count = 0;
00468     NewColour *pItem = (NewColour *) GetHead();
00469 
00470     while (pItem != NULL)
00471     {
00472         // Count this item
00473         Count++;
00474 
00475         // Count any duplicates
00476         NewColour *pDup = pItem->pNextDuplicate;
00477 
00478         while (pDup != NULL)
00479         {
00480             // Count this duplicate
00481             Count++;
00482 
00483             // Try next duplicate
00484             pDup = pDup->pNextDuplicate;
00485         }
00486 
00487         // Try next item
00488         pItem = (NewColour *) GetNext(pItem);
00489     }
00490 
00491     return Count;
00492 }
00493 
00494 
00495 
00496 /********************************************************************************************
00497 
00498 >   ImportedColours::ImportedColours(ColourListComponent *TheColourComponent,
00499                                      BOOL Strict)
00500 
00501     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00502     Created:    30/11/94
00503     Inputs:     TheColourComponent - the relevant colour component for this import.
00504                 Strict - TRUE => when servicing calls to GetColour(), check the CMYK
00505                                  colour definition for a match in case a colour is being
00506                                  used which wasn't declared in the colour table (this is
00507                                  what we do for ArtWorks EPS).
00508                         FALSE => don't bother checking CMYK - just use the name to look
00509                                  up the colour - we use this for Camelot EPS because we
00510                                  know we don't save out brain damaged EPS like ArtWorks
00511                                  does.
00512     Purpose:    Create a table of imported colours (initially empty).
00513     SeeAlso:    ImportedColours::Init
00514 
00515 ********************************************************************************************/
00516 
00517 ImportedColours::ImportedColours(ColourListComponent *TheColourComponent, BOOL Strict)
00518 {
00519     // Remember this document component
00520     pColourComponent = TheColourComponent;
00521 
00522     // Do we check CMYK values when matching colours?
00523     StrictColourMatching = Strict;
00524 
00525     // No hash table yet
00526     pColourMap = NULL;
00527 }
00528 
00529 /********************************************************************************************
00530 
00531 >   ImportedColours::~ImportedColours()
00532 
00533     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00534     Created:    30/11/94
00535     Inputs:     -
00536     Outputs:    -
00537     Returns:    -
00538     Purpose:    Destroy a table of imported colours.  This should only be done after calling
00539                 AddColoursToDocument() or DestroyColours() - an ERROR3 will occur if this
00540                 is not done.
00541     Errors:     Colours should be explicitly added to the document or deleted from this
00542                 table before this function is called => ERROR3
00543     SeeAlso:    ImportedColours::AddColoursToDocument; ImportedColours::DestroyColours
00544 
00545 ********************************************************************************************/
00546 
00547 ImportedColours::~ImportedColours()
00548 {
00549     // MORE STUFF HERE...
00550 
00551     // Trash the hash table
00552     delete pColourMap;
00553     pColourMap = NULL;
00554 }
00555 
00556 /********************************************************************************************
00557 
00558 >   BOOL ImportedColours::Init()
00559 
00560     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00561     Created:    30/11/94
00562     Inputs:     -
00563     Outputs:    -
00564     Returns:    -
00565     Purpose:    Initialise the table of imported colours
00566     Errors:     -
00567     SeeAlso:    -
00568 
00569 ********************************************************************************************/
00570 
00571 BOOL ImportedColours::Init()
00572 {
00573     // Get a hash table for the colour names...
00574     try
00575     {
00576         pColourMap = new CMapStringToNewColour;
00577     }
00578     catch( CMemoryException )
00579     {
00580         ERROR(_R(IDS_OUT_OF_MEMORY), FALSE);
00581     }
00582 
00583     // Check our document's colour list component...
00584     if (pColourComponent == NULL)
00585     {
00586         // Whoops - something's up
00587         delete pColourMap;
00588         pColourMap = NULL;
00589         ERROR2(FALSE, "NULL colour list component!");
00590     }
00591 
00592     // Ininitalise the colour linking context.
00593     if (!Context.Init())
00594         return FALSE;
00595 
00596     // All ok
00597     return TRUE;
00598 }
00599 
00600 /********************************************************************************************
00601 
00602 >   BOOL ImportedColours::AddColour(const String_64 *pColName, 
00603                                     ColourCMYK *pCMYK,  
00604                                     NewColourInfo *pColourInfo = NULL)
00605 
00606     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00607     Created:    30/11/94
00608     Inputs:     pColName - the name of the colour to add
00609                 pCMYK - the definition of the colour to add
00610                 pColourInfo - if NULL, then it is a normal colour;
00611                               if non-NULL then colour is special in some way, i.e. a tint
00612                                 or a linked colour or a spot colour.
00613     Returns:    TRUE if the colour could be added;
00614                 FALSE if not
00615     Purpose:    Add the specified colour to the colour table.  If the colour name clashes
00616                 with any already added or already in the destination document, this does not
00617                 matter as the name specified in pColName is what should be used to access
00618                 this colour again.
00619                 If pColourInfo specifies a linked or tinted colour, then this colour
00620                 is also linked to the colour currently specified by the colour link 
00621                 context (see SaveContext and RestoreContextTo).
00622     Errors:     -
00623     SeeAlso:    ImportedColours; ImportedColours::GetColour;
00624                 ImportedColours::SaveContext; ImportedColours::RestoreContextTo
00625 
00626 ********************************************************************************************/
00627 
00628 BOOL ImportedColours::AddColour(const String_64 *pColName, ColourCMYK *pCMYK, 
00629                                 NewColourInfo *pColourInfo)
00630 {
00631     IndexedColour *pNewCol = new INDEXEDCOLOUR_CMYK(pCMYK);
00632     return AddColour(pColName, &pNewCol, pColourInfo);
00633 }
00634 
00635 /********************************************************************************************
00636 
00637 >   BOOL ImportedColours::AddColour(const String_64 *pColName, 
00638                                     ColourRGBT *pRGB,
00639                                     NewColourInfo *pColourInfo = NULL)
00640 
00641     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00642     Created:    30/11/94
00643     Inputs:     pColName - the name of the colour to add
00644                 pRGB - the definition of the colour to add
00645                 pColourInfo - if NULL, then it is a normal colour;
00646                               if non-NULL then colour is special in some way, i.e. a tint
00647                                 or a linked colour or a spot colour.
00648     Returns:    TRUE if the colour could be added;
00649                 FALSE if not
00650     Purpose:    Add the specified colour to the colour table.  If the colour name clashes
00651                 with any already added or already in the destination document, this does not
00652                 matter as the name specified in pColName is what should be used to access
00653                 this colour again.
00654                 If pColourInfo specifies a linked or tinted colour, then this colour
00655                 is also linked to the colour currently specified by the colour link 
00656                 context (see SaveContext and RestoreContextTo).
00657     Errors:     -
00658     SeeAlso:    ImportedColours; ImportedColours::GetColour;
00659                 ImportedColours::SaveContext; ImportedColours::RestoreContextTo
00660 
00661 ********************************************************************************************/
00662 
00663 BOOL ImportedColours::AddColour(const String_64 *pColName, ColourRGBT *pRGB, 
00664                                 NewColourInfo *pColourInfo)
00665 {
00666     IndexedColour *pNewCol = new INDEXEDCOLOUR_RGBT(pRGB);
00667     return AddColour(pColName, &pNewCol, pColourInfo);
00668 }
00669 
00670 /********************************************************************************************
00671 
00672 >   BOOL ImportedColours::AddColour(const String_64 *pColName, 
00673                                     ColourHSVT *pHSV,
00674                                     NewColourInfo *pColourInfo = NULL)
00675 
00676     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00677     Created:    30/11/94
00678     Inputs:     pColName - the name of the colour to add
00679                 pHSV - the definition of the colour to add
00680                 pColourInfo - if NULL, then it is a normal colour;
00681                               if non-NULL then colour is special in some way, i.e. a tint
00682                                 or a linked colour or a spot colour.
00683     Returns:    TRUE if the colour could be added;
00684                 FALSE if not
00685     Purpose:    Add the specified colour to the colour table.  If the colour name clashes
00686                 with any already added or already in the destination document, this does not
00687                 matter as the name specified in pColName is what should be used to access
00688                 this colour again.
00689                 If pColourInfo specifies a linked or tinted colour, then this colour
00690                 is also linked to the colour currently specified by the colour link 
00691                 context (see SaveContext and RestoreContextTo).
00692     Errors:     -
00693     SeeAlso:    ImportedColours; ImportedColours::GetColour;
00694                 ImportedColours::SaveContext; ImportedColours::RestoreContextTo
00695 
00696 ********************************************************************************************/
00697 
00698 BOOL ImportedColours::AddColour(const String_64 *pColName, ColourHSVT *pHSV, 
00699                                 NewColourInfo *pColourInfo)
00700 {
00701     IndexedColour *pNewCol = new INDEXEDCOLOUR_HSVT(pHSV);
00702     return AddColour(pColName, &pNewCol, pColourInfo);
00703 }
00704 
00705 /********************************************************************************************
00706 
00707 >   BOOL ImportedColours::AddColour(const String_64 *pColName, 
00708                                     ColourGreyT *pGrey,
00709                                     NewColourInfo *pColourInfo = NULL)
00710 
00711     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00712     Created:    30/11/94
00713     Inputs:     pColName - the name of the colour to add
00714                 pGrey - the definition of the colour to add
00715                 pColourInfo - if NULL, then it is a normal colour;
00716                               if non-NULL then colour is special in some way, i.e. a tint
00717                                 or a linked colour or a spot colour.
00718     Returns:    TRUE if the colour could be added;
00719                 FALSE if not
00720     Purpose:    Add the specified colour to the colour table.  If the colour name clashes
00721                 with any already added or already in the destination document, this does not
00722                 matter as the name specified in pColName is what should be used to access
00723                 this colour again.
00724                 If pColourInfo specifies a linked or tinted colour, then this colour
00725                 is also linked to the colour currently specified by the colour link 
00726                 context (see SaveContext and RestoreContextTo).
00727     Errors:     -
00728     SeeAlso:    ImportedColours; ImportedColours::GetColour;
00729                 ImportedColours::SaveContext; ImportedColours::RestoreContextTo
00730 
00731 ********************************************************************************************/
00732 
00733 BOOL ImportedColours::AddColour(const String_64 *pColName, ColourGreyT *pGrey,
00734                                 NewColourInfo *pColourInfo)
00735 {
00736     IndexedColour *pNewCol = new INDEXEDCOLOUR_GREYT(pGrey);
00737     return AddColour(pColName, &pNewCol, pColourInfo);
00738 }
00739 
00740 /********************************************************************************************
00741 
00742 >   BOOL ImportedColours::AddColour(const String_64 *pColName, 
00743                                     ImportedNewColour *pCol,
00744                                     NewColourInfo *pColourInfo = NULL)
00745 
00746     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00747     Created:    18 03 95
00748     Inputs:     pColName - the name of the colour to add
00749                 pGrey - the definition of the colour to add
00750                 pColourInfo - if NULL, then it is a normal colour;
00751                               if non-NULL then colour is special in some way, i.e. a tint
00752                                 or a linked colour or a spot colour.
00753     Returns:    TRUE if the colour could be added;
00754                 FALSE if not
00755     Purpose:    Add the specified colour to the colour table.  If the colour name clashes
00756                 with any already added or already in the destination document, this does not
00757                 matter as the name specified in pColName is what should be used to access
00758                 this colour again.
00759                 If pColourInfo specifies a linked or tinted colour, then this colour
00760                 is also linked to the colour currently specified by the colour link 
00761                 context (see SaveContext and RestoreContextTo).
00762                 This version adds a colour of from any colour model (supported by other
00763                 AddColour functions)
00764     Errors:     -
00765     SeeAlso:    ImportedColours; ImportedColours::GetColour;
00766                 ImportedColours::SaveContext; ImportedColours::RestoreContextTo
00767 
00768 ********************************************************************************************/
00769 
00770 BOOL ImportedColours::AddColour(const String_64 *pColName, ImportedNewColour *pCol,
00771                                 NewColourInfo *pColourInfo)
00772 {
00773     switch(pCol->Model)
00774     {
00775         case COLOURMODEL_RGBT:
00776             return AddColour(pColName, (ColourRGBT *)&pCol->Colour, pColourInfo);
00777             break;
00778 
00779         case COLOURMODEL_CMYK:
00780             return AddColour(pColName, (ColourCMYK *)&pCol->Colour, pColourInfo);
00781             break;
00782 
00783         case COLOURMODEL_HSVT:
00784             return AddColour(pColName, (ColourHSVT *)&pCol->Colour, pColourInfo);
00785             break;
00786 
00787         case COLOURMODEL_GREYT:
00788             return AddColour(pColName, (ColourGreyT *)&pCol->Colour, pColourInfo);
00789             break;
00790 
00791         default:
00792             break;
00793     }
00794     
00795     ERROR3("Colour model presented to ImportedColours::AddColour is not a recognised model");
00796 
00797     return FALSE;
00798 }
00799 
00800 /********************************************************************************************
00801 
00802 >   BOOL ImportedColours::AddTintOrShade(const String_64 *pColName, NewColourInfo *pLinkInfo)
00803 
00804     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00805     Created:    29/5/96
00806     Inputs:     pColName - the name of the colour to add
00807                 pLinkInfo - the colour information data
00808     Returns:    TRUE if the colour could be added;
00809                 FALSE if not
00810     Purpose:    Add the specified tint or shade to the colour table.
00811                 Assumes the vital tint information has already been filled in.
00812     Errors:     -
00813     SeeAlso:    ColourListComponent::ReadTint; ColourListComponent::ReadShade;
00814                 ColourListComponent::ImportColourDefinition;
00815 
00816 ********************************************************************************************/
00817 
00818 BOOL ImportedColours::AddTintOrShade(const String_64 *pColName, NewColourInfo *pColourInfo)
00819 {
00820     // Get a new colour to add
00821     IndexedColour *pNewCol = new IndexedColour;
00822 
00823     // Assumes tint and shade information already set up, this includes:-
00824     // pColourInfo->Type = COLOURTYPE_TINT;
00825     // pColourInfo->TintValue = 0.0; (FIXED24);
00826     // If shade then
00827     // pColourInfo->ShadeValue = 0.0; (FIXED24);
00828 
00829     return AddColour(pColName, &pNewCol, pColourInfo);
00830 }
00831 
00832 /********************************************************************************************
00833 
00834 >   BOOL ImportedColours::AddTint(const String_64 *pColName, UINT32 Tint)
00835 
00836     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00837     Created:    30/11/94
00838     Inputs:     pColName - the name of the colour to add
00839                 Tint - the tint value (between 0 and 100)
00840     Returns:    TRUE if the colour could be added;
00841                 FALSE if not
00842     Purpose:    Add the specified colour to the colour table.  If the colour name clashes
00843                 with any already added or already in the destination document, this does not
00844                 matter as the name specified in pColName is what should be used to access
00845                 this colour again.
00846                 This colour is a tint of the colour currently specified by the colour link 
00847                 context (see SaveContext and RestoreContextTo).
00848     Errors:     -
00849     SeeAlso:    ImportedColours; ImportedColours::GetColour;
00850                 ImportedColours::SaveContext; ImportedColours::RestoreContextTo
00851 
00852 ********************************************************************************************/
00853 
00854 BOOL ImportedColours::AddTint(const String_64 *pColName, UINT32 Tint)
00855 {
00856     // Get a new colour to add
00857     IndexedColour *pNewCol = new IndexedColour;
00858 
00859     // Set up the tint information
00860     NewColourInfo ColourInfo;
00861     ColourInfo.Type = COLOURTYPE_TINT;
00862 
00863     // Convert 0 <-> 100 to 0.0 <-> 1.0 and pass in as FIXED24.
00864     ColourInfo.TintValue = FIXED24(((double) Tint) / 100.0);
00865 
00866     return AddColour(pColName, &pNewCol, &ColourInfo);
00867 }
00868 
00869 
00870 
00871 /********************************************************************************************
00872 
00873 >   BOOL ImportedColours::AddShade(const String_64 *pColName, INT32 ShadeX, INT32 ShadeY)
00874 
00875     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (copied from code by Tim)
00876     Created:    7/9/95 (30/11/94)
00877     Inputs:     pColName - the name of the colour to add
00878                 ShadeX - the shade X value (between -100 and 100)
00879                 ShadeY - the shade Y value (between -100 and 100)
00880 
00881     Returns:    TRUE if the colour could be added;
00882                 FALSE if not
00883     Purpose:    Add the specified colour to the colour table.  If the colour name clashes
00884                 with any already added or already in the destination document, this does not
00885                 matter as the name specified in pColName is what should be used to access
00886                 this colour again.
00887                 This colour is a shade of the colour currently specified by the colour link 
00888                 context (see SaveContext and RestoreContextTo).
00889     Errors:     -
00890     SeeAlso:    ImportedColours; ImportedColours::GetColour;
00891                 ImportedColours::SaveContext; ImportedColours::RestoreContextTo
00892 
00893 ********************************************************************************************/
00894 
00895 BOOL ImportedColours::AddShade(const String_64 *pColName, INT32 ShadeX, INT32 ShadeY)
00896 {
00897     // Get a new colour to add
00898     IndexedColour *pNewCol = new IndexedColour;
00899 
00900     // Set up the tint information
00901     NewColourInfo ColourInfo;
00902     ColourInfo.Type = COLOURTYPE_TINT;
00903 
00904     // And flag the fact that this "tint" is really a shade!
00905     ColourInfo.TintIsShade = TRUE;
00906 
00907     // Convert -100 <-> 100 to -1.0 <-> 1.0 and pass in as FIXED24.
00908     ColourInfo.TintValue = FIXED24(((double) ShadeX) / 100.0);
00909     ColourInfo.ShadeValue = FIXED24(((double) ShadeY) / 100.0);
00910 
00911     return AddColour(pColName, &pNewCol, &ColourInfo);
00912 }
00913 
00914 
00915 
00916 /********************************************************************************************
00917 
00918 >   BOOL ImportedColours::AddColour(const String_64 *pColName, IndexedColour **pNewCol,
00919                                     NewColourInfo *pColourInfo)
00920 
00921     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00922     Created:    30/11/94
00923 
00924     Modified:   Jason (8/9/95) - Now handles exact duplicates as well as duplicate names
00925                 (This is needed for new shade-colour saving system which does nasty
00926                 things in order to retain backward compatability with old loaders)
00927 
00928     Inputs:     pColName - the name of the colour
00929                 pNewCol - ptr to ptr to the new indexed colour to use (if NULL then just
00930                           returns FALSE immediately) (see also Outputs)
00931                 pColourInfo - if NULL, then it is a normal colour;
00932                               if non-NULL then colour is special in some way, i.e. a tint
00933                                 or a linked colour or a spot colour.
00934 
00935     Outputs:    If *pNewCol points to an IndexedColour which already has an *identical*
00936                 twin colour (i.e. exactly the same colour appears twice in the doc) then
00937                 *pNewCol will be modified to point at the first incarnation of the colour,
00938                 and the IndexedColour you passed in will be deleted.
00939                 DO NOT use the previous IndexedColour pointer - only use the pointer as
00940                 passed back from this method.
00941 
00942     Returns:    TRUE if the colour was added ok;    
00943                 FALSE otherwise
00944     Purpose:    Generic routine for adding a colour to the table of imported colours.
00945                 All the other AddColour() routines map onto this.
00946 
00947     Errors:     Out of memory => ERROR1
00948                 pNewCol is NULL => returns FALSE (no error set)
00949     SeeAlso:    ImportedColours
00950     Scope:      Protected
00951 
00952 ********************************************************************************************/
00953 
00954 BOOL ImportedColours::AddColour(const String_64 *pColName, IndexedColour **pNewIndexedCol,
00955                                 NewColourInfo *pColourInfo)
00956 {
00957     // Do we have a valid colour?
00958     if (pNewIndexedCol == NULL || *pNewIndexedCol == NULL)
00959         // No!
00960         return FALSE;
00961 
00962     // First, set the colour name to the one supplied. If it is unnamed, then we want
00963     // to set its unique-ID string to the value from the file. At the end of the import,
00964     // we will use SetUnnamed to force it to re-generate a unique name so that it is
00965     // (a) merged properly during import, and (b) doesn't clash with another colour
00966     // already in the same document once it is added.
00967     //String_64 Name = *pColName;
00968     //(*pNewIndexedCol)->SetName(*pColName, (ColName[0] != '_'));
00969     TCHAR ch = (*pColName)[0];
00970     (*pNewIndexedCol)->SetName(*pColName, (ch != '_'));
00971 
00972 
00973     if (pColourInfo != NULL)
00974     {
00975         // Link the colour if required
00976         if ((pColourInfo->Type == COLOURTYPE_LINKED) ||
00977             (pColourInfo->Type == COLOURTYPE_TINT))
00978         {
00979             IndexedColour *pParent = NULL;
00980             if (pColourInfo->WebNativeColour)
00981             {
00982                 pParent = pColourInfo->pParentCol;
00983             }
00984             else
00985             {
00986                 // Importing a non-native or web file colour and so use the context of the colour
00987                 // to define its parent.
00988                 // Get the current colour context
00989                 pParent = Context.GetContext();
00990                 ERROR2IF(pParent == NULL, FALSE, "NULL parent when creating linked colour!");
00991             }
00992 
00993             // Link to it - either as a linked colour or a tint
00994             if (pColourInfo->Type == COLOURTYPE_LINKED)
00995             {
00996                 // Linked colour
00997                 (*pNewIndexedCol)->SetLinkedParent(pParent, COLOURTYPE_LINKED);
00998 
00999                 // Set inheritance flags...
01000                 for (INT32 i = 0; i < 4; i++)
01001                     (*pNewIndexedCol)->SetInheritsComponent(i + 1, pColourInfo->Inherits[i]);
01002             }
01003             else
01004             {
01005                 // Tinted colour
01006                 (*pNewIndexedCol)->SetLinkedParent(pParent, COLOURTYPE_TINT);
01007 
01008                 // Set tint/shade value as appropriate. This makes the 'tint' colour a
01009                 // tint or shade. (Shades are special cases of tints for historical reasons)
01010                 if (pColourInfo->TintIsShade)
01011                     (*pNewIndexedCol)->SetShadeValues(pColourInfo->TintValue, pColourInfo->ShadeValue);
01012                 else
01013                     (*pNewIndexedCol)->SetTintValue(pColourInfo->TintValue);
01014             }
01015         }
01016         else if (pColourInfo->Type == COLOURTYPE_SPOT)
01017         {
01018             // Mark this as a spot colour (in case the caller hasn't already)
01019             (*pNewIndexedCol)->SetLinkedParent(NULL, COLOURTYPE_SPOT);
01020         }
01021     }
01022 
01023     // Is there a colour the same as this in the destination document already?
01024     IndexedColour *pIdenticalCol;
01025     pColourComponent->FindIdenticalColour(*pNewIndexedCol, &pIdenticalCol);
01026 
01027     BOOL AlreadyExists = (pIdenticalCol != NULL);
01028 
01029 /*
01030     Phil, 01/03/2004
01031     If we remove colours from the document before we have added our list of imported colours
01032     anything could come along and add colours back in the meantime.
01033     (e.g. GradFillAttribute::GradFillAttribute)
01034     So leave colours in the list and only move them later on...
01035 */
01036     if (AlreadyExists)
01037     {
01038         // Graeme (5/4/00) - This code now changes the colour list so that an
01039         // existing colour is repositioned where the original definition was.
01040 
01041         // Delete the new one because it duplicates one already in the document.
01042         delete *pNewIndexedCol;
01043 
01044         // Make pNewIndexedCol point to the existing colour
01045         *pNewIndexedCol = pIdenticalCol;
01046 
01047         // Set AlreadyExists to be FALSE so that the colour is included.
01048         AlreadyExists = FALSE;
01049     }
01050 
01051     NewColour *pNewColour = NULL;
01052 
01053     // If we are in web/native filter mode then we MUST always add a new colour item as this
01054     // is where we save the record number which will be reused later. So we must stop the 
01055     // name look up and adding duplicates as this adds the new colour to the a list inside
01056     // the duplicated name that is in the ColourMap.
01057     BOOL WebNative = (pColourInfo && pColourInfo->WebNativeColour);
01058 
01059     // First, check to see if we already have a definition of this colour *NAME*
01060     if( !WebNative && pColourMap->Lookup( *pColName, pNewColour ) )
01061     {
01062         // Yes - mark the current definition as a duplicate and add this new one to it.
01063         if (!pNewColour->AddDuplicateColour(pNewIndexedCol, AlreadyExists))
01064             // Error encountered.
01065             return FALSE;
01066     }
01067     else
01068     {
01069         // No - but is it already in the destination document?
01070         //
01071         // (i.e. is there a colour in the document with the same 
01072         //  name, colour model and definition?)
01073         //
01074         // If yes - add a new colour that references the already existing colour, and
01075         // mark it as being such;
01076         //
01077         // If no  - it's a new colour, so add it to the list.
01078 
01079         pNewColour = Colours.AddColour(*pNewIndexedCol, AlreadyExists);
01080 
01081         if (pNewColour == NULL)
01082             // out of memory
01083             return FALSE;
01084 
01085         // Either way, add it to the colour name map
01086         try
01087         {
01088             (*pColourMap)[ *pColName ] = pNewColour;
01089         }
01090         catch( CMemoryException )
01091         {
01092             // Could not do it - report error to caller.
01093             ERROR(_R(IDS_OUT_OF_MEMORY), FALSE);
01094         }
01095 
01096         // If we are in web/native filter mode then save the record number that we
01097         // have been passed in in the NewColourInfo
01098         // At the same time save out the entry number for where we want this colour in the list
01099         // of colours
01100         if (pColourInfo && pColourInfo->WebNativeColour)
01101         {
01102             pNewColour->RecordNumber = pColourInfo->RecordNumber;
01103             pNewColour->EntryNumber = pColourInfo->EntryNumber;
01104         }
01105     }
01106 
01107     // We added the colour ok so set it as the current context colour
01108     // Note that AddDuplicateColour may have changed our pointer to point at a different
01109     // (identical) colour, but it will always point at the correct colour for us to use here.
01110     Context.SetContext(*pNewIndexedCol);
01111 
01112     // All ok
01113     return TRUE;
01114 }
01115 
01116 
01117 /********************************************************************************************
01118 
01119 >   void ImportedColours::SaveContext()
01120 
01121     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01122     Created:    30/11/94
01123     Inputs:     -
01124     Outputs:    -
01125     Returns:    -
01126     Purpose:    None
01127     Errors:     -
01128     SeeAlso:    -
01129 
01130 ********************************************************************************************/
01131 
01132 void ImportedColours::SaveContext()
01133 {
01134     Context.SaveContext();
01135 }
01136 
01137 /********************************************************************************************
01138 
01139 >   void ImportedColours::RestoreContextTo(UINT32 Level)
01140 
01141     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01142     Created:    30/11/94
01143     Inputs:     -
01144     Outputs:    -
01145     Returns:    -
01146     Purpose:    None
01147     Errors:     -
01148     SeeAlso:    -
01149 
01150 ********************************************************************************************/
01151 
01152 void ImportedColours::RestoreContextTo(UINT32 Level)
01153 {
01154     if (Context.RestoreContextTo(Level) == FALSE)
01155     {
01156         ERROR3("Unbalanced colour import context");
01157     }
01158 }
01159 
01160 /********************************************************************************************
01161 
01162 >   IndexedColour *ImportedColours::GetColour(const char *ColName)
01163 
01164     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01165     Created:    30/11/94
01166     Inputs:     ColName - the colour name to look for.
01167     Returns:    Pointer to the indexed colour if successful;
01168                 NULL if not found.
01169     Purpose:    Find a named colour in the import list.  This look up is obviously done
01170                 purely on the colour name, and as such is a slightly risky thing to do,
01171                 especially when importing such flaky file formats as EPS - use the
01172                 version of GetColour that takes a PColourCMYK value to provide more
01173                 reliable colour lookup.
01174     SeeAlso:    ImportedColours
01175 
01176 ********************************************************************************************/
01177 
01178 IndexedColour *ImportedColours::GetColour( PCTSTR ColName )
01179 {
01180     // Do we have a definition of this colour name?
01181     NewColour *pNewColour=NULL;
01182     if( pColourMap->Lookup( ColName, pNewColour ) )
01183     {
01184         // Yes - return the first entry
01185         return pNewColour->pCol;
01186     }
01187     else
01188     {
01189         // No - return failure.
01190         return NULL;
01191     }
01192 }
01193 
01194 // This macro takes signed or unsigned values, and returns TRUE if they are equal, or
01195 // different by one.
01196 #define WITHIN_ONE(a,b) (Abs((INT32) (a) - (INT32) (b)) <= 1)
01197 
01198 /********************************************************************************************
01199 
01200 >   IndexedColour *ImportedColours::GetColour(const char *ColName, const PColourCMYK *Defn)
01201 
01202     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01203     Created:    30/11/94
01204     Inputs:     ColName - the colour name to look for.
01205                 Defn - pointer to the CMYK values specified in the imported file.
01206     Returns:    Pointer to the indexed colour if successful;
01207                 NULL if not found.
01208     Purpose:    Searches for a named colour.  If the colour name has had duplicate
01209                 definitions during this import, then the colour definition is compared
01210                 against the values pointed to by Defn (converting to CMYK first if needed).
01211     Errors:     -
01212     SeeAlso:    ImportedColours
01213 
01214 ********************************************************************************************/
01215 
01216 IndexedColour *ImportedColours::GetColour( PCTSTR ColName, const PColourCMYK *Defn )
01217 {
01218     // Do we have a definition of this colour name?
01219     NewColour *pNewColour=NULL;
01220     if( pColourMap->Lookup( ColName, pNewColour ) )
01221     {
01222         // Should we check colour values before returning this colour?
01223         if (StrictColourMatching || (pNewColour->pNextDuplicate != NULL))
01224         {
01225             // Yes - find a colour from this entry that matches the colour definition too...
01226             while (pNewColour != NULL) 
01227             {
01228                 // Is this a match?
01229                 // NB. We allow them to be out by one to cope with rounding problems.
01230                 //     This is ok, because it will only happen in ArtWorks EPS files,
01231                 //     and then only on colours that are 1 out in the colour definition,
01232                 //     so I don't think anyone's going to notice!  -- Tim
01233                 if (WITHIN_ONE(pNewColour->ColDefn.Cyan,    Defn->Cyan)    &&
01234                     WITHIN_ONE(pNewColour->ColDefn.Magenta, Defn->Magenta) &&
01235                     WITHIN_ONE(pNewColour->ColDefn.Yellow,  Defn->Yellow)  &&
01236                     WITHIN_ONE(pNewColour->ColDefn.Key,     Defn->Key))
01237                 {
01238                     // Yes - quit loop
01239                     break;
01240                 }
01241 
01242                 // Otherwise try next colour
01243                 pNewColour = pNewColour->pNextDuplicate;
01244             }
01245 
01246             // Did we find one?
01247             if (pNewColour != NULL)
01248             {
01249                 // Yes - return it to the caller.
01250                 return pNewColour->pCol;
01251             }
01252             else
01253             {
01254                 // No - return failure
01255                 return NULL;
01256             }
01257         }
01258         else
01259         {
01260             // No checking needed -just return this colour
01261             return pNewColour->pCol;
01262         }
01263     }
01264     else
01265     {
01266         // No - return failure.
01267         return NULL;
01268     }
01269 }
01270 
01271 // Just to be safe...
01272 #undef WITHIN_ONE
01273 
01274 
01275 /********************************************************************************************
01276 
01277 >   BOOL ImportedColours::AddColoursToDocument()
01278 
01279     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01280     Created:    30/11/94
01281     Inputs:     -
01282     Outputs:    -
01283     Returns:    -
01284     Purpose:    None
01285     Errors:     -
01286     SeeAlso:    -
01287 
01288 ********************************************************************************************/
01289 
01290 BOOL ImportedColours::AddColoursToDocument()
01291 {
01292     // Make an array for the new colours
01293     INT32 NumNewColours = Colours.GetCount();
01294     INT32 TableSize = sizeof(IndexedColour *) * (NumNewColours + 1);
01295     IndexedColour **pNewArray = (IndexedColour **) CCMalloc(TableSize);
01296     if (pNewArray == NULL)
01297     {
01298         // Out of memory.
01299         return FALSE;
01300     }
01301 
01302     // set up a slow job
01303     String_64 ImportMessage(_R(IDT_ADDCOLOURSTODOC));
01304     BeginSlowJob( NumNewColours, TRUE, &ImportMessage );
01305     INT32 Done = 0;
01306     
01307     // Copy the colour pointers into this array
01308     INT32 i = 0;
01309     NewColour *pColour = (NewColour *) Colours.GetHead();
01310     List *pUnnamedColours = pColourComponent->GetColourList()->GetUnnamedColours();
01311 
01312     while (pColour != NULL)
01313     {
01314         // Remove this colour from the list, and add it (and all duplicates of it) to the 
01315         // palette and the array, but only if it is not already in the document,and it
01316         // is not an unnamed colour (i.e. its name starts with an underscore).
01317         Colours.RemoveItem(pColour);
01318 
01319         while (pColour != NULL)
01320         {
01321             // Is it an unnamed colour?
01322             if (!pColour->pCol->IsNamed())      // Is it an unnamed colour?
01323             {
01324                 // Yes - add to the unnamed colour list (no need for undo)
01325                 // We force it unnamed again now to ensure it generates a new unique
01326                 // ID for its destination document, rather than using the
01327                 // unique-within-file id used during import.
01328                 pColour->pCol->SetUnnamed();
01329                 pUnnamedColours->AddTail(pColour->pCol);
01330             }
01331             else
01332             {
01333                 // It's a named colour - may be already in the doc, may be not
01334                 IndexedColour* pIdenticalColour;
01335                 pColourComponent->FindIdenticalColour(pColour->pCol, &pIdenticalColour);
01336                 if (pIdenticalColour)
01337                 {
01338                     // Already in the doc so just move the existing colour
01339                     // into the required position in the list by unlinking and relinking...
01340                     ColourList *pColourList = pColourComponent->GetColourList ();
01341                     if ( pColourList->RemoveItem ( pIdenticalColour ) != NULL )
01342                     {
01343                         pColourComponent->AddNewColour(pIdenticalColour);
01344                         pNewArray[i++] = pIdenticalColour;
01345                     }
01346 
01347                 }
01348                 else
01349                 {
01350                     pColourComponent->AddNewColour(pColour->pCol);
01351                     pNewArray[i++] = pColour->pCol;
01352                 }
01353             }
01354 
01355             // Try next duplicate and delete this item.
01356             NewColour *pTmp = pColour;
01357             pColour = pColour->pNextDuplicate;
01358             delete pTmp;
01359         }
01360 
01361         // Try the next colour
01362         pColour = (NewColour *) Colours.GetHead();
01363     
01364         // do progess bar stuff
01365         Done++;
01366         if(Done % 0xf == 0)
01367             ContinueSlowJob(Done);
01368     }
01369 
01370     // Terminate the list of pointers
01371     pNewArray[i] = NULL;
01372 
01373     // Add these colours|.
01374     ColourManager::UnHideColours(pColourComponent->GetColourList(), pNewArray);
01375 
01376     // Destroy the list of added colours (UnHideColours copied it, so our copy is useless now)
01377     CCFree(pNewArray);
01378     pNewArray = NULL;
01379 
01380     // Destroy the colour map
01381     delete pColourMap;
01382     pColourMap = NULL;
01383 
01384     // finish the slow job
01385     ContinueSlowJob(NumNewColours);
01386     EndSlowJob();
01387     
01388     // All ok
01389     return TRUE;
01390 }
01391 
01392 /********************************************************************************************
01393 
01394 >   BOOL ImportedColours::DestroyColours()
01395 
01396     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
01397     Created:    30/11/94
01398     Inputs:     -
01399     Outputs:    -
01400     Returns:    -
01401     Purpose:    None
01402     Errors:     -
01403     SeeAlso:    -
01404 
01405 ********************************************************************************************/
01406 
01407 BOOL ImportedColours::DestroyColours()
01408 {
01409     NewColour *pColour = (NewColour *) Colours.GetHead();
01410 
01411     while (pColour != NULL)
01412     {
01413         // Remove this colour from the list, and delete the indexed colour it points to
01414         // (if it is not already in the document).
01415         Colours.RemoveItem(pColour);
01416 
01417         while (pColour != NULL)
01418         {
01419             if (!pColour->AlreadyExistsInDoc)
01420             {
01421                 // It's a brand new colour - delete it.
01422                 // Except we don't because it causes an error.
01423 
01424                 // NB.  This is a temporary bodge to stop us from getting Indexed colour
01425                 //      deleted while in use errors - they happen because the undo 
01426                 //      system does not delete the nodes added by InsertNode() yet.
01427                 //      When it does, then we can uncomment this line.  As it stands we
01428                 //      we get a memory leak of new colours when an import fails, but
01429                 //      what the hell - it's only a bodge.
01430 
01431                 //delete pColour->pCol;
01432             }
01433 
01434             // Try next duplicate and delete this item.
01435             NewColour *pTmp = pColour;
01436             pColour = pColour->pNextDuplicate;
01437             delete pTmp;
01438         }
01439 
01440         // Try the next colour
01441         pColour = (NewColour *) Colours.GetHead();
01442     }
01443 
01444     // All done
01445     return TRUE;
01446 }
01447 
01448 /********************************************************************************************
01449 
01450 >   IndexedColour *ImportedColours::GetColour(INT32 ReqRecordNumber)
01451 
01452     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01453     Created:    30/5/96
01454     Inputs:     ReqRecordNumber - the record number to search the list for
01455     Returns:    Pointer to the indexed colour if successful;
01456                 NULL if not found.
01457     Purpose:    Searches for a previously imported colour definition. Used by the native/web
01458                 filter to convert a colour reference in a record to an IndexedColour. This
01459                 must have already been imported in the file as the rule is that reference to
01460                 colours can only be made if the colour definition has already been output.
01461     Errors:     -
01462     SeeAlso:    ImportedColours; ColourListComponent::ImportColourDefinition;
01463 
01464 ********************************************************************************************/
01465 
01466 IndexedColour *ImportedColours::GetColour(INT32 ReqRecordNumber)
01467 {
01468     // Work our way through the list of imported colours until we find the required record number
01469     NewColour *pColour = (NewColour *) Colours.GetHead();
01470     while (pColour != NULL)
01471     {
01472         if (pColour->RecordNumber == ReqRecordNumber)
01473             return pColour->pCol;
01474 
01475         // Try the next colour
01476         pColour = (NewColour *) Colours.GetNext(pColour);
01477     }
01478 
01479     // Something went a bit wrong and we didn't find the requested record number
01480     // return NULL to the caller 
01481     return NULL;
01482 }
01483 
01484 /********************************************************************************************
01485 
01486 >   BOOL ImportedColours::SortColoursByEntryNumber()
01487 
01488     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01489     Created:    31/5/96
01490     Inputs:     -
01491     Outputs:    -
01492     Returns:    True if the operation completed successfully
01493                 False if it failed in some way.
01494     Purpose:    Sorts the list of imported colours by the EntryNumber that is saved in the 
01495                 colour definition in the native file format so that we load the list back in
01496                 the same order that it was in when the document was saved. This because when
01497                 we save the colours we cannot save the list in the order they are defined in
01498                 the colour list as we must save parent colours before children so that the 
01499                 children can reference the parent.
01500                 Borrowed code from SuperGallery::ApplySortNow as we need a much simpler version.
01501     Errors:     -
01502     SeeAlso:    ImportedColours; ColourListComponent::ImportColourDefinition;
01503                 ColourListComponent::EndImport; SuperGallery::ApplySortNow
01504 
01505 ********************************************************************************************/
01506 
01507 BOOL ImportedColours::SortColoursByEntryNumber()
01508 {
01509     INT32 NumItems = 0;
01510 
01511     // Count the number of items we have to sort
01512     NewColour *pColour = (NewColour *) Colours.GetHead();
01513     while (pColour != NULL)
01514     {
01515         if (pColour->pCol->IsNamed())       // Is it an named colour?
01516             NumItems++;
01517         pColour = (NewColour *) Colours.GetNext(pColour);
01518     }
01519 
01520     // Start progress indicators, with a percentage based upon the number of items.
01521     // We will update twice for each group (after qsort and shuffle-items stages)
01522     String_64 Description(_R(IDS_NATIVE_SORTCOLOURS));
01523     BeginSlowJob(NumItems * 2, FALSE, &Description);
01524     INT32 NumItemsToSort = 0;
01525 
01526     if (NumItems > 1)
01527     {
01528         // Get memory for an array of pointers to these items
01529         NewColour **SortArray = (NewColour **)CCMalloc(NumItems * sizeof(NewColour *));
01530         if (SortArray == NULL)
01531             return FALSE;
01532 
01533         // Fill in the array with pointers to display items to sort
01534         INT32 i = 0;
01535         NewColour *pColour = (NewColour *) Colours.GetHead();
01536         while (pColour != NULL)
01537         {
01538             if (pColour->pCol->IsNamed())       // Is it an named colour?
01539                 SortArray[i++] = pColour;
01540             pColour = (NewColour *) Colours.GetNext(pColour);
01541         }
01542 
01543         // Sort the array of pointers
01544         qsort(SortArray, NumItems, sizeof(NewColour *), ImportedColours::SortComparator);
01545 
01546         NumItemsToSort += NumItems;
01547         // Update percentage complete for the number of items processed
01548         ContinueSlowJob(NumItemsToSort);
01549 
01550         // Now, take the sorted array, and rearrange the items to be in that order      
01551         // Special case the first item
01552         NewColour *pPrevColour = (NewColour *) Colours.GetPrev(SortArray[0]);
01553         if (pPrevColour != NULL)
01554         {
01555             Colours.RemoveItem(SortArray[0]);
01556             Colours.InsertBefore(SortArray[1], SortArray[0]);
01557         }
01558 
01559         // Then whip through the rest of the items
01560         for (i = 1; i < NumItems; i++)
01561         {
01562             pPrevColour = (NewColour *) Colours.GetPrev(SortArray[i]);
01563             if (pPrevColour != SortArray[i-1])
01564             {
01565                 Colours.RemoveItem(SortArray[i]);
01566                 Colours.InsertAfter(SortArray[i-1], SortArray[i]);
01567             }
01568         }
01569 
01570         // Free our temporary workspace
01571         CCFree(SortArray);
01572     }
01573     
01574     // End the progress bar that we started
01575     EndSlowJob();
01576 
01577     // We seem to have sorted the items ok
01578     return TRUE;
01579 }
01580 
01581 /********************************************************************************************
01582 
01583 >   static INT32 __cdecl ImportedColours::SortComparator(const void *Item1, const void *Item2)
01584 
01585     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01586     Created:    31/5/96
01587     Inputs:     Item1, Item2 - the display nodes to be compared
01588     Returns:    negative (I am lesser), 0 (we are equal), or positive (I am greater)
01589                 result of comparing the items with the EntryNumber stored in each item in
01590                 the loaded colour list.
01591     Purpose:    'qsort' comparator function, used when quicksorting the loaded colour list
01592     SeeAlso:    ImportedColours::SortColoursByEntryNumber()
01593                 SuperGallery::SortComparator; SuperGallery::ApplySortNow
01594 
01595 ********************************************************************************************/
01596 
01597 INT32 __cdecl ImportedColours::SortComparator(const void *Item1, const void *Item2)
01598 {
01599     NewColour *pColourItem1 = *((NewColour **)Item1);
01600     NewColour *pColourItem2 = *((NewColour **)Item2);
01601 
01602     if (pColourItem1 == NULL || pColourItem2 == NULL)
01603     {
01604         ERROR3("ImportedColours::SortComparator bad pointers!");    
01605         return 0;
01606     }
01607 
01608     if (pColourItem1->EntryNumber < pColourItem2->EntryNumber)
01609         return(-1);
01610 
01611     return((pColourItem1->EntryNumber == pColourItem2->EntryNumber) ? 0 : 1);
01612 }

Generated on Sat Nov 10 03:45:31 2007 for Camelot by  doxygen 1.4.4