00001 // $Id: colcomp.cpp 1315 2006-06-14 09:51:34Z 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 // The document component for the document's colour list. 00100 00101 /* 00102 */ 00103 00104 #include "camtypes.h" 00105 00106 #include "colcomp.h" 00107 00108 //#include "basedoc.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00109 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00110 #include "collist.h" 00111 #include "colormgr.h" 00112 //#include "colmodel.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00113 #include "aw_eps.h" 00114 #include "cameleps.h" 00115 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00116 #include "ccdc.h" 00117 #include "colourix.h" 00118 //#include "doccolor.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00119 //#include "tim.h" 00120 //#include "resource.h" 00121 //#include "grndrgn.h" 00122 #include "impcol.h" 00123 //#include "jason.h" 00124 #include "unicdman.h" 00125 //#include "sgcolour.h" 00126 00127 //#include "camfiltr.h" // BaseCamelotFilter - version 2 native filter - in camtypes.h [AUTOMATICALLY REMOVED] 00128 #include "cxftags.h" // TAG_DEFINERGBCOLOUR TAG_DEFINECOMPLEXCOLOUR 00129 //#include "cxfdefs.h" // SIZE_DEFINERGBCOLOUR SIZE_DEFINECOMPLEXCOLOUR - in camtypes.h [AUTOMATICALLY REMOVED] 00130 #include "cxfcols.h" // REF_DEFAULTCOLOUR_TRANSPARENT 00131 #include "cxfile.h" // CXF_UNKNOWN_SIZE 00132 #include "expcol.h" // ExportedColours handling class 00133 //#include "cxfrec.h" // CXaraFileRecord handler - in camtypes.h [AUTOMATICALLY REMOVED] 00134 //#include "filtrres.h" // _R(IDS_NATIVE_COLOURWARNING) 00135 00136 DECLARE_SOURCE("$Revision: 1315 $"); 00137 00138 // Declare smart memory handling in Debug builds 00139 #define new CAM_DEBUG_NEW 00140 00141 CC_IMPLEMENT_DYNAMIC(ColourListComponentClass, DocComponentClass) 00142 CC_IMPLEMENT_DYNAMIC(ColourListComponent, DocComponent) 00143 00144 // The error limit to use when comparing colour definitions 00145 #define COL_ACCURACY (0.00001) 00146 00147 // This is our special linked value for native/web files 00148 const FIXED24 LinkValue = FIXED24(-8.0); 00149 00150 // If we do no load a colour definition, then this is the colour that we will use instead 00151 #define REPLACEMENTCOLOUR COLOUR_BLACK 00152 00153 // WEBSTER - markn 14/2/97 00154 // Introduced WEBSTER_IGNORE_NAME_MATCHING so that Webster can ignore the name when 00155 // trying to find an identical colour 00156 // Set to FALSE if you want it to behave the same as v1.5 00157 #ifndef WEBSTER 00158 #define WEBSTER_IGNORE_NAME_MATCHING FALSE 00159 #else 00160 #define WEBSTER_IGNORE_NAME_MATCHING TRUE 00161 #endif // WEBSTER 00162 00163 /******************************************************************************************** 00164 ********************************************************************************************/ 00165 00166 /******************************************************************************************** 00167 00168 > BOOL ColourListComponentClass::Init() 00169 00170 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00171 Created: 02/08/94 00172 Returns: TRUE if all went well; 00173 FALSE if not. 00174 Purpose: Register the colour list document component with the main application. 00175 Errors: Out of memory. 00176 SeeAlso: DocComponent 00177 00178 ********************************************************************************************/ 00179 00180 BOOL ColourListComponentClass::Init() 00181 { 00182 // Instantiate a component class to register with the application. 00183 ColourListComponentClass *pClass = new ColourListComponentClass; 00184 if (pClass == NULL) 00185 return FALSE; 00186 00187 // Register it 00188 GetApplication()->RegisterDocComponent(pClass); 00189 00190 // All ok 00191 return TRUE; 00192 } 00193 00194 00195 /******************************************************************************************** 00196 00197 > BOOL ColourListComponentClass::AddComponent(BaseDocument *pDocument) 00198 00199 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00200 Created: 02/08/94 00201 Inputs: pDocument - the document to add the colour list to. 00202 Returns: TRUE if the colour list was added ok; 00203 FALSE if not. 00204 Purpose: Add a colour list component to the specified document. 00205 Errors: Out of memory 00206 SeeAlso: ColourListComponentClass 00207 00208 ********************************************************************************************/ 00209 00210 BOOL ColourListComponentClass::AddComponent(BaseDocument *pDocument) 00211 { 00212 // Check to see if this document already has a colour list; if so, leave it alone. 00213 if (pDocument->GetDocComponent(CC_RUNTIME_CLASS(ColourListComponent)) != NULL) 00214 return TRUE; 00215 00216 // No colour list - try to create a new one for this document. 00217 ColourList *pList = new ColourList; 00218 if(pList == NULL) 00219 return FALSE; 00220 00221 pList->Init( pDocument ); // Let the ColourList know what its parent document is 00222 00223 // Ok - create the colour list component using this list. 00224 ColourListComponent *pComponent = new ColourListComponent(pList); 00225 if (pComponent == NULL) 00226 { 00227 // Out of memory... 00228 delete pList; 00229 return FALSE; 00230 } 00231 00232 // All ok - add the component to the document. 00233 pDocument->AddDocComponent(pComponent); 00234 return true; 00235 } 00236 00237 00238 00239 /******************************************************************************************** 00240 00241 > ColourListComponent::ColourListComponent() 00242 00243 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00244 Created: 8/11/94 00245 Purpose: Construct a colour list component. DO NOT use this constructor. It gives 00246 and ERROR3 (and sets up this in a semi-safe default state) 00247 SeeAlso: ColourListComponent 00248 00249 ********************************************************************************************/ 00250 00251 ColourListComponent::ColourListComponent() 00252 { 00253 ERROR3("ColourListComponent constructed with default constructor!?\n"); 00254 00255 // We don't have a colour list! Eek! 00256 pIndexedColours = NULL; 00257 00258 // Initialise importer colour maps etc 00259 pNewColours = NULL; 00260 00261 // Initialise Exporter colour list 00262 pExportedColours = NULL; 00263 00264 // Initialise IndexedColour ComponentCopy array pointers 00265 SourceColours = NULL; 00266 DestColours = NULL; 00267 ColourTableSize = 32; 00268 00269 // Our link to the BaseCamelotFilter 00270 pCamFilter = NULL; 00271 // Set our variable so that we warn about a possible replacement only once 00272 WarnedBefore = FALSE; 00273 } 00274 00275 00276 00277 /******************************************************************************************** 00278 00279 > ColourListComponent::ColourListComponent(ColourList *pColList) 00280 00281 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00282 Created: 02/08/94 00283 Inputs: pColList - the colour list to use for this colour list componet. 00284 Purpose: Construct a colour list component using the given colour list. 00285 00286 Notes: NOTE that the list you pass in now "belongs" to this CLC, and it 00287 will be automatically deleted when you delete this CLC object. 00288 00289 Errors: ENSURE if pColList is NULL. 00290 SeeAlso: ColourListComponent 00291 00292 ********************************************************************************************/ 00293 00294 ColourListComponent::ColourListComponent(ColourList *pColList) 00295 { 00296 ENSURE(pColList != NULL, "NULL colour list in colour list component constructor!"); 00297 00298 // Install this colour list. 00299 pIndexedColours = pColList; 00300 00301 // Initialise importer colour tables etc 00302 pNewColours = NULL; 00303 00304 // Initialise Exporter colour list 00305 pExportedColours = NULL; 00306 00307 // Initialise IndexedColour ComponentCopy array pointers 00308 SourceColours = NULL; 00309 DestColours = NULL; 00310 ColourTableSize = 32; 00311 00312 // Our link to the BaseCamelotFilter 00313 pCamFilter = NULL; 00314 // Set our variable so that we warn about a possible replacement only once 00315 WarnedBefore = FALSE; 00316 } 00317 00318 /******************************************************************************************** 00319 00320 > ColourListComponent::~ColourListComponent() 00321 00322 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00323 Created: 08/09/94 00324 Purpose: Clean up a colour list component's data structures - deletes the colour 00325 list. 00326 Errors: ENSURE if IndexedColour copying stuff has not been cleaned up (this will 00327 occur if End/AbortComponentCopy is not called after a component copy) 00328 SeeAlso: ColourListComponent 00329 00330 ********************************************************************************************/ 00331 00332 ColourListComponent::~ColourListComponent() 00333 { 00334 // Delete our colour list. 00335 if (pIndexedColours != NULL) 00336 { 00337 pIndexedColours->DeleteAll(); 00338 00339 delete pIndexedColours; 00340 pIndexedColours = NULL; 00341 } 00342 00343 // Sanity check to see if we've done something terrible... 00344 ENSURE(SourceColours == NULL && DestColours == NULL, 00345 "Someone failed to EndComponentCopy before destructing a ColourListComponent"); 00346 00347 // As we have finished with it now, destroy the list of exported colours 00348 if (pExportedColours) 00349 { 00350 delete pExportedColours; 00351 pExportedColours = NULL; 00352 } 00353 } 00354 00355 /******************************************************************************************** 00356 ********************************************************************************************/ 00357 00358 // Saving/loading code for the new native/web file format 00359 00360 /******************************************************************************************** 00361 ********************************************************************************************/ 00362 00363 /******************************************************************************************** 00364 00365 > BOOL ColourListComponent::StartImport(BaseCamelotFilter *pFilter) 00366 00367 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00368 Created: 21/5/96 00369 Inputs: pFilter - the BaseCamelotFilter filter that is being used to import a file. 00370 Returns: TRUE if the component was able to prepare for importing; 00371 FALSE if not (e.g. out of memory) 00372 Purpose: Inform the colour list document component that a Native or Web import is 00373 about to start. 00374 SeeAlso: DocComponent 00375 00376 ********************************************************************************************/ 00377 00378 BOOL ColourListComponent::StartImport(BaseCamelotFilter *pFilter) 00379 { 00380 TRACEUSER( "Neville",_T("ColourListComponent::StartImport\n") ); 00381 if (pFilter == NULL) 00382 { 00383 ERROR3("ColourListComponent::StartImport filter is null!"); 00384 return TRUE; 00385 } 00386 00387 // Save this in our link to the BaseCamelotFilter 00388 pCamFilter = pFilter; 00389 // Set our variable so that we warn about a possible replacement only once 00390 WarnedBefore = FALSE; 00391 00392 // Get a colour table and don't do strict checking (as per Camelot EPS and Native EPS). 00393 pNewColours = new ImportedColours(this, FALSE); 00394 if ((pNewColours == NULL) || !pNewColours->Init()) 00395 return FALSE; 00396 00397 // We keep a record of how nested we are with respect to linking colours, e.g. 00398 // links of links of links. 00399 // A nesting of 0 is no nesting. 00400 // Do this so that we are consistent with the EPS form 00401 LinkNesting = 0; 00402 00403 return TRUE; 00404 } 00405 00406 /******************************************************************************************** 00407 00408 > BOOL ColourListComponent::EndImport(BaseCamelotFilter *pFilter, BOOL Success) 00409 00410 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00411 Created: 21/5/96 00412 Inputs: pFilter - the BaseCamelotFilter filter that is being used to import a file. 00413 Success - TRUE => The import was successful; 00414 FALSE => The import failed - abandon any changes. 00415 Returns: TRUE if the component was able to end the importing; 00416 FALSE if not (e.g. out of memory) 00417 Purpose: Inform the colour list document component that a Native or Web import has 00418 just finished. 00419 SeeAlso: DocComponent 00420 00421 ********************************************************************************************/ 00422 00423 BOOL ColourListComponent::EndImport(BaseCamelotFilter *pFilter, BOOL Success) 00424 { 00425 TRACEUSER( "Neville", _T("ColourListComponent::EndImport\n") ); 00426 if (pFilter == NULL) 00427 { 00428 ERROR3("ColourListComponent::EndImport filter is null!"); 00429 return TRUE; 00430 } 00431 00432 // If we didn't even get to initialise, then return quietly. 00433 if (pNewColours == NULL) 00434 { 00435 ERROR3("ColourListComponent::EndImport pNewColours is null!"); 00436 return TRUE; 00437 } 00438 00439 // Import is finished, so add any outstanding colours to the document (if the 00440 // import was successful), and delete the colour table 00441 if (Success) 00442 { 00443 // Try and sort the imported colour list by the entry number that was saved 00444 // in the colour definition on export. This was the colour's position in 00445 // the indexed colour list. 00446 pNewColours->SortColoursByEntryNumber(); 00447 00448 // Adds the colours to the system, with undo 00449 pNewColours->AddColoursToDocument(); 00450 } 00451 else 00452 { 00453 // Import failed - destroy all the colours. 00454 pNewColours->DestroyColours(); 00455 } 00456 00457 // Finally, delete the IndexedColour table. 00458 delete pNewColours; 00459 pNewColours = NULL; 00460 00461 // Null our link to the BaseCamelotFilter 00462 pCamFilter = NULL; 00463 // Set our variable so that we warn about a possible replacement only once 00464 WarnedBefore = FALSE; 00465 00466 return TRUE; 00467 } 00468 00469 /******************************************************************************************** 00470 00471 > BOOL ColourListComponent::GetDocColour(INT32 ColourRef, CXaraFileRecord* pCXFileRec, DocColour* pDocColour) 00472 00473 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00474 Created: 30/5/96 00475 Inputs: ColourRef - The colour reference or record number that the record handler has loaded 00476 from the record. 00477 Outputs: pDocColour - A pointer to return the required doc colour in 00478 Returns: TRUE if the colour reference was succesfully converted into a DocColour; 00479 FALSE if not (e.g. out of memory) 00480 Purpose: Try and convert a colour reference i.e. record number into a previously 00481 imported colour definition which should now be an indexed colour in the document. 00482 SeeAlso: ColourRecordHandler; 00483 00484 ********************************************************************************************/ 00485 00486 BOOL ColourListComponent::GetDocColour(INT32 ColourRef, DocColour* pDocColour) 00487 { 00488 ERROR2IF(pDocColour == NULL,FALSE,"ColourListComponent::GetDocColour NULL pCXFileRec"); 00489 ERROR2IF(pNewColours == NULL,FALSE,"ColourListComponent::ImportSimpleColour NULL pNewColours"); 00490 //TRACEUSER( "Neville", _T("GetDocColour for ref %d\n"), ColourRef); 00491 00492 // First check to see if the colour refers to any of the built in colours. 00493 // These will have negative record numbers 00494 if (ColourRef < 0) 00495 { 00496 // At present, we only use the one colour reference 00497 StockColour defaultcolour = COLOUR_NONE; 00498 switch (ColourRef) 00499 { 00500 case REF_DEFAULTCOLOUR_TRANSPARENT: 00501 defaultcolour = COLOUR_TRANS; 00502 break; 00503 case REF_DEFAULTCOLOUR_BLACK: 00504 defaultcolour = COLOUR_BLACK; 00505 break; 00506 case REF_DEFAULTCOLOUR_WHITE: 00507 defaultcolour = COLOUR_WHITE; 00508 break; 00509 case REF_DEFAULTCOLOUR_RED: 00510 defaultcolour = COLOUR_RED; 00511 break; 00512 case REF_DEFAULTCOLOUR_GREEN: 00513 defaultcolour = COLOUR_GREEN; 00514 break; 00515 case REF_DEFAULTCOLOUR_BLUE: 00516 defaultcolour = COLOUR_BLUE; 00517 break; 00518 case REF_DEFAULTCOLOUR_CYAN: 00519 defaultcolour = COLOUR_CYAN; 00520 break; 00521 case REF_DEFAULTCOLOUR_MAGENTA: 00522 defaultcolour = COLOUR_MAGENTA; 00523 break; 00524 case REF_DEFAULTCOLOUR_YELLOW: 00525 defaultcolour = COLOUR_YELLOW; 00526 break; 00527 default: 00528 { 00529 defaultcolour = REPLACEMENTCOLOUR; 00530 // It is an unknown default colour reference 00531 // We will warn the user and use a replacement colour instead 00532 // If we have a pFilter then ask the default warning handle to append our message 00533 if (pCamFilter) 00534 { 00535 if (!WarnedBefore) 00536 { 00537 pCamFilter->AppendWarning(_R(IDS_NATIVE_COLOURWARNING)); 00538 WarnedBefore = TRUE; 00539 } 00540 00541 } 00542 else 00543 ERROR2(FALSE,"ColourListComponent::GetDocColour negative ColourRef is unknown"); 00544 break; 00545 } 00546 } 00547 00548 // Make ourselves the required colour 00549 DocColour * pReplacementCol = new DocColour(defaultcolour); 00550 // Make the return colour this 00551 *pDocColour = *pReplacementCol; 00552 // And now delete that temp replacement colour 00553 delete pReplacementCol; 00554 } 00555 else 00556 { 00557 // In case of early exit set the return DocColour pointer to NULL, i.e. nothing found 00558 //*pDocColour = NULL; 00559 00560 // Try and find the specified record number in our colour list 00561 IndexedColour *pCol = pNewColours->GetColour(ColourRef); 00562 // If not found then this is a problem as a colour must have been defined before its being 00563 // referenced 00564 // We will warn the user and use a replacement colour instead 00565 if (pCol == NULL) 00566 { 00567 // If we have a pFilter then ask the default warning handle to append our message 00568 if (pCamFilter) 00569 { 00570 if (!WarnedBefore) 00571 { 00572 pCamFilter->AppendWarning(_R(IDS_NATIVE_COLOURWARNING)); 00573 WarnedBefore = TRUE; 00574 } 00575 00576 // Make ourselves a colour to use instead 00577 DocColour * pReplacementCol = new DocColour(REPLACEMENTCOLOUR); 00578 // Make the return colour this 00579 *pDocColour = *pReplacementCol; 00580 // And now delete that temp replacement colour 00581 delete pReplacementCol; 00582 } 00583 else 00584 ERROR2(FALSE,"ColourListComponent::GetDocColour ColourRef cannot be found"); 00585 } 00586 else 00587 { 00588 // Make the specified DocColour referencing this IndexedColour. 00589 pDocColour->MakeRefToIndexedColour(pCol); 00590 } 00591 } 00592 00593 return TRUE; 00594 } 00595 00596 /******************************************************************************************** 00597 00598 > BOOL ColourListComponent::ImportSimpleColour(CXaraFileRecord* pCXFileRec) 00599 00600 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00601 Created: 30/5/96 00602 Inputs: pCXFileRec - The CXaraFileRecord that is being used to provide read functions etc. 00603 Returns: TRUE if the record was succesfully imported; 00604 FALSE if not (e.g. out of memory) 00605 Purpose: Try and import a simple RGB colour definition record into the document. 00606 SeeAlso: ColourRecordHandler; 00607 00608 ********************************************************************************************/ 00609 00610 BOOL ColourListComponent::ImportSimpleColour(CXaraFileRecord* pCXFileRec) 00611 { 00612 ERROR2IF(pCXFileRec == NULL,FALSE,"ColourListComponent::ImportSimpleColour NULL pCXFileRec"); 00613 ERROR2IF(pNewColours == NULL,FALSE,"ColourListComponent::ImportSimpleColour NULL pNewColours"); 00614 00615 //TRACEUSER( "Neville", _T("ImportSimpleColour\n")); 00616 // Read in the simple RGB colour 00617 BYTE Red; 00618 BYTE Green; 00619 BYTE Blue; 00620 BOOL ok = pCXFileRec->ReadBYTE(&Red); 00621 if (ok) ok = pCXFileRec->ReadBYTE(&Green); 00622 if (ok) ok = pCXFileRec->ReadBYTE(&Blue); 00623 00624 NewColourInfo ColourInfo; 00625 // Flag we are importing a web/native style colour and so use the specified parent and not 00626 // the context form. 00627 ColourInfo.RecordNumber = pCXFileRec->GetRecordNumber(); 00628 ColourInfo.WebNativeColour = TRUE; 00629 ColourRGBT NewRGBT; 00630 String_64 ColName; //(TEXT("_")); 00631 // Make the name unique by adding a text form of the record number 00632 TCHAR *pNewName = (TCHAR *)ColName; 00633 camSnprintf( pNewName, 64, _T("_%d"), ColourInfo.RecordNumber ); 00634 00635 NewRGBT.Red = (double)((double)Red/256.0); 00636 NewRGBT.Green = (double)((double)Green/256.0); 00637 NewRGBT.Blue = (double)((double)Blue/256.0); 00638 if (ok) ok = pNewColours->AddColour(&ColName, &NewRGBT, &ColourInfo); 00639 00640 return ok; 00641 } 00642 00643 /******************************************************************************************** 00644 00645 > BOOL ColourListComponent::ImportColourDefinition(CXaraFileRecord* pCXFileRec) 00646 00647 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00648 Created: 28/5/96 00649 Inputs: pCXFileRec - The CXaraFileRecord that is being used to provide read functions etc. 00650 Returns: TRUE if the record was succesfully imported; 00651 FALSE if not (e.g. out of memory) 00652 Purpose: Try and import a colour definition record into the document. 00653 SeeAlso: ColourRecordHandler; 00654 00655 ********************************************************************************************/ 00656 00657 BOOL ColourListComponent::ImportColourDefinition(CXaraFileRecord* pCXFileRec) 00658 { 00659 ERROR2IF(pCXFileRec == NULL,FALSE,"ColourListComponent::ImportColourDefinition NULL pCXFileRec"); 00660 ERROR2IF(pNewColours == NULL,FALSE,"ColourListComponent::ImportColourDefinition NULL pNewColours"); 00661 00662 00663 // Check for special types (NB a colour cannot be both a spot colour and a linked colour). 00664 NewColourInfo ColourInfo; 00665 // BOOL Linked = FALSE; 00666 // Flag we are importing a web/native style colour and so use the specified parent and not 00667 // the context form. 00668 ColourInfo.RecordNumber = pCXFileRec->GetRecordNumber(); 00669 ColourInfo.WebNativeColour = TRUE; 00670 //IndexedColour *pParent = NULL; 00671 00672 // Read in the simple RGB colour, which we won't need 00673 BYTE Red; 00674 BYTE Green; 00675 BYTE Blue; 00676 BOOL ok = pCXFileRec->ReadBYTE(&Red); 00677 if (ok) ok = pCXFileRec->ReadBYTE(&Green); 00678 if (ok) ok = pCXFileRec->ReadBYTE(&Blue); 00679 00680 // read in the colour model 00681 ColourModel ColModel = COLOURMODEL_RGBT; 00682 BYTE temp; 00683 if (ok) ok = pCXFileRec->ReadBYTE(&temp); 00684 ColModel = (ColourModel)temp; 00685 00686 // read in the colour type 00687 ExportColourType ColType = EXPORT_COLOURTYPE_NORMAL; 00688 if (ok) ok = pCXFileRec->ReadBYTE(&temp); 00689 ColType = (ExportColourType)temp; 00690 00691 // read in the entry number that this colour should be in the list of colours 00692 UINT32 EntryNumber = 0; 00693 if (ok) ok = pCXFileRec->ReadUINT32(&EntryNumber); 00694 ColourInfo.EntryNumber = EntryNumber; 00695 00696 // read in the record number of the parent colour 00697 UINT32 ParentColour = 0; 00698 if (ok) ok = pCXFileRec->ReadUINT32(&ParentColour); 00699 // Now convert this into a indexed colour pointer, if required 00700 if (ok && (ColType == EXPORT_COLOURTYPE_LINKED || ColType == EXPORT_COLOURTYPE_TINT || 00701 ColType == EXPORT_COLOURTYPE_SHADE)) 00702 { 00703 TRACEUSER( "Neville", _T("Trying to find parent reference %d\n"),ParentColour); 00704 ColourInfo.pParentCol = pNewColours->GetColour(ParentColour); 00705 if (ColourInfo.pParentCol == NULL) 00706 { 00707 TRACEUSER( "Neville", _T("Cannot convert parent colour reference %d into an IndexedColour\n"),ParentColour); 00708 ERROR2(FALSE,"Cannot find parent IndexedColour"); 00709 } 00710 } 00711 00712 // Read in the four colour components 00713 UINT32 Comp1 = 0; 00714 if (ok) ok = pCXFileRec->ReadUINT32(&Comp1); 00715 UINT32 Comp2 = 0; 00716 if (ok) ok = pCXFileRec->ReadUINT32(&Comp2); 00717 UINT32 Comp3 = 0; 00718 if (ok) ok = pCXFileRec->ReadUINT32(&Comp3); 00719 UINT32 Comp4 = 0; 00720 if (ok) ok = pCXFileRec->ReadUINT32(&Comp4); 00721 00722 String_64 ColName; 00723 if (ok) ok = pCXFileRec->ReadUnicode(&ColName);//, ColName.MaxLength()); 00724 00725 if (ColName.Length() == 0 ) 00726 { 00727 // We are an unnamed colour and so make up a name based on the record number 00728 // This is so that all the existing import code can be reused. 00729 // Make the name unique by adding a text form of the record number 00730 TCHAR *pNewName = (TCHAR *)ColName; 00731 camSnprintf( pNewName, 64, _T("_%d"), ColourInfo.RecordNumber ); 00732 } 00733 TRACEUSER( "Neville", _T("ImportColourDefinition Name %s RecordNumber %d, EntryNumber %d\n"),(TCHAR*)ColName,ColourInfo.RecordNumber,EntryNumber); 00734 00735 // We had a problem reading the colour definition so stop now 00736 if (!ok) 00737 return FALSE; 00738 00739 // Read the colour components according to the colour model. 00740 switch (ColType) 00741 { 00742 case EXPORT_COLOURTYPE_NORMAL: 00743 // Set the correct colour type 00744 ColourInfo.Type = COLOURTYPE_NORMAL; 00745 // Fall through below 00746 case EXPORT_COLOURTYPE_SPOT: 00747 case EXPORT_COLOURTYPE_LINKED: 00748 // Set the correct colour type 00749 if (ColType == EXPORT_COLOURTYPE_SPOT) 00750 ColourInfo.Type = COLOURTYPE_SPOT; 00751 else if (ColType == EXPORT_COLOURTYPE_LINKED) 00752 ColourInfo.Type = COLOURTYPE_LINKED; 00753 00754 // These all require the same handling 00755 // Linked colours save out the components in the normal fashion 00756 switch (ColModel) 00757 { 00758 case COLOURMODEL_RGBT: 00759 { 00760 ColourRGBT NewRGBT; 00761 ReadRGB(&NewRGBT, &ColourInfo, Comp1, Comp2, Comp3, Comp4); 00762 if (!pNewColours->AddColour(&ColName, &NewRGBT, &ColourInfo)) 00763 return FALSE; 00764 } 00765 break; 00766 00767 case COLOURMODEL_CMYK: 00768 { 00769 ColourCMYK NewCMYK; 00770 ReadCMYK(&NewCMYK, &ColourInfo, Comp1, Comp2, Comp3, Comp4); 00771 if (!pNewColours->AddColour(&ColName, &NewCMYK, &ColourInfo)) 00772 return FALSE; 00773 } 00774 break; 00775 00776 case COLOURMODEL_HSVT: 00777 { 00778 ColourHSVT NewHSVT; 00779 ReadHSV(&NewHSVT, &ColourInfo, Comp1, Comp2, Comp3, Comp4); 00780 if (!pNewColours->AddColour(&ColName, &NewHSVT, &ColourInfo)) 00781 return FALSE; 00782 } 00783 break; 00784 00785 case COLOURMODEL_GREYT: 00786 { 00787 ColourGreyT NewGreyT; 00788 ReadGrey(&NewGreyT, &ColourInfo, Comp1); 00789 if (!pNewColours->AddColour(&ColName, &NewGreyT, &ColourInfo)) 00790 return FALSE; 00791 } 00792 break; 00793 00794 default: 00795 ERROR3("ColourListComponent::ImportColourDefinition unknown colour model!"); 00796 break; 00797 } 00798 break; 00799 00800 case EXPORT_COLOURTYPE_TINT: 00801 { 00802 // Set the correct colour type 00803 ColourInfo.Type = COLOURTYPE_TINT; 00804 00805 // Read in the tint value from the colour definition record 00806 ReadTint(&ColourInfo, Comp1); 00807 00808 // Now, try and add that to the system 00809 if (!pNewColours->AddTintOrShade(&ColName, &ColourInfo)) 00810 return FALSE; 00811 } 00812 break; 00813 00814 case EXPORT_COLOURTYPE_SHADE: 00815 { 00816 // Set the correct colour type 00817 ColourInfo.Type = COLOURTYPE_TINT; 00818 00819 // Read in the shade value from the colour definition record 00820 ReadShade(&ColourInfo, Comp1, Comp2); 00821 00822 // Now, try and add that to the system 00823 if (!pNewColours->AddTintOrShade(&ColName, &ColourInfo)) 00824 return FALSE; 00825 } 00826 break; 00827 00828 default: 00829 ERROR3("ColourListComponent::ImportColourDefinition unknown colourtype!"); 00830 break; 00831 } 00832 00833 return ok; 00834 } 00835 00836 /******************************************************************************************** 00837 00838 > BOOL ColourListComponent::ReadRGB(ColourRGBT *pCol, NewColourInfo *pColourInfo, 00839 UINT32 Comp1, UINT32 Comp2, UINT32 Comp3, UINT32 Comp4) 00840 00841 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00842 Created: 29/5/96 00843 Inputs: pCol - RGB colour data to fill in 00844 pColourInfo - pointer to the colour info to fill in 00845 Comp1 .. 4 - colour components read in from the record 00846 Outputs: The data in the pCol and pColourInfo will have been filled in 00847 Returns: True if value read ok, False otherwise. 00848 Purpose: Read the RGB values from a Camelot RGB colour definition record. 00849 SeeAlso: ColourListComponent::ImportColourDefinition; 00850 00851 ********************************************************************************************/ 00852 00853 BOOL ColourListComponent::ReadRGB(ColourRGBT *pCol, NewColourInfo *pColourInfo, 00854 UINT32 Comp1, UINT32 Comp2, UINT32 Comp3, UINT32 Comp4) 00855 { 00856 ERROR2IF(pCol == NULL,FALSE,"ColourListComponent::ReadRGB NULL pCol"); 00857 ERROR2IF(pColourInfo == NULL,FALSE,"ColourListComponent::ReadRGB NULL pColourInfo"); 00858 00859 BOOL Linked = (pColourInfo != NULL) && (pColourInfo->Type == COLOURTYPE_LINKED); 00860 00861 // read the Red colour component in 00862 FIXED24 Value24 = 0.0; 00863 Value24.SetAsFixed24(Comp1); 00864 if (Linked && (Value24 == LinkValue)) 00865 pColourInfo->Inherits[0] = TRUE; 00866 else 00867 pCol->Red = Value24; 00868 00869 // read the Green colour component in 00870 Value24.SetAsFixed24(Comp2); 00871 if (Linked && (Value24 == LinkValue)) 00872 pColourInfo->Inherits[1] = TRUE; 00873 else 00874 pCol->Green = Value24; 00875 00876 // read the Blue colour component in 00877 Value24.SetAsFixed24(Comp3); 00878 if (Linked && (Value24 == LinkValue)) 00879 pColourInfo->Inherits[2] = TRUE; 00880 else 00881 pCol->Blue = Value24; 00882 00883 // No transparency 00884 pCol->Transparent = 0.0; 00885 00886 return TRUE; 00887 } 00888 00889 /******************************************************************************************** 00890 00891 > BOOL ColourListComponent::ReadCMYK(ColourCMYK *pCol, NewColourInfo *pColourInfo, 00892 UINT32 Comp1, UINT32 Comp2, UINT32 Comp3, UINT32 Comp4) 00893 00894 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00895 Created: 29/5/96 00896 Inputs: pCol - RGB colour data to fill in 00897 pColourInfo - pointer to the colour info to fill in 00898 Comp1 .. 4 - colour components read in from the record 00899 Outputs: The data in the pCol and pColourInfo will have been filled in 00900 Returns: True if value read ok, False otherwise. 00901 Purpose: Read the CMYK values from a Camelot CMYK colour definition record. 00902 SeeAlso: ColourListComponent::ImportColourDefinition; 00903 00904 ********************************************************************************************/ 00905 00906 BOOL ColourListComponent::ReadCMYK(ColourCMYK *pCol, NewColourInfo *pColourInfo, 00907 UINT32 Comp1, UINT32 Comp2, UINT32 Comp3, UINT32 Comp4) 00908 { 00909 ERROR2IF(pCol == NULL,FALSE,"ColourListComponent::ReadCMYK NULL pCol"); 00910 ERROR2IF(pColourInfo == NULL,FALSE,"ColourListComponent::ReadCMYK NULL pColourInfo"); 00911 00912 BOOL Linked = (pColourInfo != NULL) && (pColourInfo->Type == COLOURTYPE_LINKED); 00913 00914 // read the Cyan colour component in 00915 FIXED24 Value24 = 0.0; 00916 Value24.SetAsFixed24(Comp1); 00917 if (Linked && (Value24 == LinkValue)) 00918 pColourInfo->Inherits[0] = TRUE; 00919 else 00920 pCol->Cyan = Value24; 00921 00922 // read the Magenta colour component in 00923 Value24.SetAsFixed24(Comp2); 00924 if (Linked && (Value24 == LinkValue)) 00925 pColourInfo->Inherits[1] = TRUE; 00926 else 00927 pCol->Magenta = Value24; 00928 00929 // read the Yellow colour component in 00930 Value24.SetAsFixed24(Comp3); 00931 if (Linked && (Value24 == LinkValue)) 00932 pColourInfo->Inherits[2] = TRUE; 00933 else 00934 pCol->Yellow = Value24; 00935 00936 // read the Key colour component in 00937 Value24.SetAsFixed24(Comp4); 00938 if (Linked && (Value24 == LinkValue)) 00939 pColourInfo->Inherits[3] = TRUE; 00940 else 00941 pCol->Key = Value24; 00942 00943 return TRUE; 00944 } 00945 00946 /******************************************************************************************** 00947 00948 > BOOL ColourListComponent::ReadHSV(ColourHSVT *pCol, NewColourInfo *pColourInfo, 00949 UINT32 Comp1, UINT32 Comp2, UINT32 Comp3, UINT32 Comp4) 00950 00951 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00952 Created: 29/5/96 00953 Inputs: pCol - HSVT colour data to fill in 00954 pColourInfo - pointer to the colour info to fill in 00955 Comp1 .. 4 - colour components read in from the record 00956 Outputs: The data in the pCol and pColourInfo will have been filled in 00957 Returns: True if value read ok, False otherwise. 00958 Purpose: Read the HSV values from a Camelot HSV colour definition record. 00959 SeeAlso: ColourListComponent::ImportColourDefinition; 00960 00961 ********************************************************************************************/ 00962 00963 BOOL ColourListComponent::ReadHSV(ColourHSVT *pCol, NewColourInfo *pColourInfo, 00964 UINT32 Comp1, UINT32 Comp2, UINT32 Comp3, UINT32 Comp4) 00965 { 00966 ERROR2IF(pCol == NULL,FALSE,"ColourListComponent::ReadHSV NULL pCol"); 00967 ERROR2IF(pColourInfo == NULL,FALSE,"ColourListComponent::ReadHSV NULL pColourInfo"); 00968 00969 BOOL Linked = (pColourInfo != NULL) && (pColourInfo->Type == COLOURTYPE_LINKED); 00970 00971 // read the Hue colour component in 00972 FIXED24 Value24 = 0.0; 00973 Value24.SetAsFixed24(Comp1); 00974 if (Linked && (Value24 == LinkValue)) 00975 pColourInfo->Inherits[0] = TRUE; 00976 else 00977 pCol->Hue = Value24; 00978 00979 // read the Saturation colour component in 00980 Value24.SetAsFixed24(Comp2); 00981 if (Linked && (Value24 == LinkValue)) 00982 pColourInfo->Inherits[1] = TRUE; 00983 else 00984 pCol->Saturation = Value24; 00985 00986 // read the Value colour component in 00987 Value24.SetAsFixed24(Comp3); 00988 if (Linked && (Value24 == LinkValue)) 00989 pColourInfo->Inherits[2] = TRUE; 00990 else 00991 pCol->Value = Value24; 00992 00993 // No transparency 00994 pCol->Transparent = 0.0; 00995 00996 return TRUE; 00997 } 00998 00999 /******************************************************************************************** 01000 01001 > BOOL ColourListComponent::ReadGrey(ColourGreyT *pCol, NewColourInfo *pColourInfo, UINT32 Comp1) 01002 01003 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01004 Created: 29/5/96 01005 Inputs: pCol - Grey colour data to fill in 01006 pColourInfo - pointer to the colour info to fill in 01007 Comp1 - the first of the colour components read in from the record 01008 Outputs: The data in the pCol and pColourInfo will have been filled in 01009 Returns: True if value read ok, False otherwise. 01010 Purpose: Read the Grey values from a Camelot Grey colour definition record. 01011 SeeAlso: ColourListComponent::ImportColourDefinition; 01012 01013 ********************************************************************************************/ 01014 01015 BOOL ColourListComponent::ReadGrey(ColourGreyT *pCol, NewColourInfo *pColourInfo, UINT32 Comp1) 01016 { 01017 ERROR2IF(pCol == NULL,FALSE,"ColourListComponent::ReadGrey NULL pCol"); 01018 ERROR2IF(pColourInfo == NULL,FALSE,"ColourListComponent::ReadGrey NULL pColourInfo"); 01019 01020 BOOL Linked = (pColourInfo != NULL) && (pColourInfo->Type == COLOURTYPE_LINKED); 01021 01022 // read the grey Intensity colour component in 01023 FIXED24 Value24 = 0.0; 01024 Value24.SetAsFixed24(Comp1); 01025 if (Linked && (Value24 == LinkValue)) 01026 pColourInfo->Inherits[0] = TRUE; 01027 else 01028 pCol->Intensity = Value24; 01029 01030 // Clear the reserved words to 0. 01031 pCol->Reserved1 = 0.0; 01032 pCol->Reserved2 = 0.0; 01033 01034 // No transparency 01035 pCol->Transparent = 0.0; 01036 01037 return TRUE; 01038 } 01039 01040 /******************************************************************************************** 01041 01042 > BOOL ColourListComponent::ReadTint(NewColourInfo *pColourInfo, UINT32 Comp1) 01043 01044 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01045 Created: 29/5/96 01046 Inputs: pColourInfo - pointer to the colour info to fill in 01047 Comp1 - the first of the colour components read in from the record 01048 Outputs: The data in the pCol and pColourInfo will have been filled in 01049 Returns: True if value read ok, False otherwise. 01050 Purpose: Read the tint values from a Camelot tint colour definition record. 01051 SeeAlso: ColourListComponent::ImportColourDefinition; 01052 01053 ********************************************************************************************/ 01054 01055 BOOL ColourListComponent::ReadTint(NewColourInfo *pColourInfo, UINT32 Comp1) 01056 { 01057 ERROR2IF(pColourInfo == NULL,FALSE,"ColourListComponent::ReadTint NULL pColourInfo"); 01058 01059 BOOL Linked = (pColourInfo != NULL) && (pColourInfo->Type == COLOURTYPE_LINKED); 01060 01061 // read the grey Intensity colour component in 01062 FIXED24 Value24 = 0.0; 01063 Value24.SetAsFixed24(Comp1); 01064 if (Linked && (Value24 == LinkValue)) 01065 pColourInfo->Inherits[0] = TRUE; 01066 01067 pColourInfo->TintValue = Value24; 01068 01069 pColourInfo->Type = COLOURTYPE_TINT; 01070 // And flag the fact that this "tint" is a tint rather than a shade! 01071 pColourInfo->TintIsShade = FALSE; 01072 01073 return TRUE; 01074 } 01075 01076 /******************************************************************************************** 01077 01078 > BOOL ColourListComponent::ReadShade(NewColourInfo *pColourInfo, UINT32 Comp1, UINT32 Comp2) 01079 01080 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01081 Created: 29/5/96 01082 Inputs: pColourInfo - pointer to the colour info to fill in 01083 Comp1 .. 2 - the first two colour components read in from the record 01084 Outputs: The data in the pCol and pColourInfo will have been filled in 01085 Returns: True if value read ok, False otherwise. 01086 Purpose: Read the shade values from a Camelot shade colour definition record. 01087 SeeAlso: ColourListComponent::ImportColourDefinition; 01088 01089 ********************************************************************************************/ 01090 01091 BOOL ColourListComponent::ReadShade(NewColourInfo *pColourInfo, UINT32 Comp1, UINT32 Comp2) 01092 { 01093 ERROR2IF(pColourInfo == NULL,FALSE,"ColourListComponent::ReadShade NULL pColourInfo"); 01094 01095 BOOL Linked = (pColourInfo != NULL) && (pColourInfo->Type == COLOURTYPE_LINKED); 01096 01097 FIXED24 Value24 = 0.0; 01098 Value24.SetAsFixed24(Comp1); 01099 if (Linked && (Value24 == LinkValue)) 01100 pColourInfo->Inherits[0] = TRUE; 01101 pColourInfo->TintValue = Value24; 01102 01103 Value24.SetAsFixed24(Comp2); 01104 if (Linked && (Value24 == LinkValue)) 01105 pColourInfo->Inherits[1] = TRUE; 01106 pColourInfo->ShadeValue = Value24; 01107 01108 pColourInfo->Type = COLOURTYPE_TINT; 01109 // And flag the fact that this "tint" is a really a shade! 01110 pColourInfo->TintIsShade = TRUE; 01111 01112 return TRUE; 01113 } 01114 01115 01116 /******************************************************************************************** 01117 ********************************************************************************************/ 01118 01119 01120 /******************************************************************************************** 01121 01122 > BOOL ColourListComponent::StartExport(BaseCamelotFilter *pFilter) 01123 01124 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01125 Created: 21/5/96 01126 Returns: TRUE if the component was able to prepare for exporting; 01127 FALSE if not (e.g. out of memory) 01128 Inputs: pFilter - the BaseCamelotFilter filter that is being used to export a file. 01129 Purpose: Inform the colour list document component that a WEb or Native export is 01130 about to start. 01131 SeeAlso: DocComponent 01132 01133 ********************************************************************************************/ 01134 01135 BOOL ColourListComponent::StartExport(BaseCamelotFilter *pFilter) 01136 { 01137 #ifdef DO_EXPORT 01138 TRACEUSER( "Neville", _T("ColourListComponent::StartExport\n")); 01139 // Mark all colours as unsaved 01140 if (pFilter == NULL) 01141 { 01142 ERROR3("ColourListComponent::StartExport filter is null!"); 01143 return TRUE; 01144 } 01145 01146 // Save this in our link to the BaseCamelotFilter 01147 pCamFilter = pFilter; 01148 01149 // Set up and start the exported colour list 01150 pExportedColours = new ExportedColours(); 01151 if (pExportedColours == NULL) 01152 return FALSE; 01153 #endif 01154 return TRUE; 01155 } 01156 01157 /******************************************************************************************** 01158 01159 > BOOL ColourListComponent::EndExport(BaseCamelotFilter *pFilter) 01160 01161 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01162 Created: 21/5/96 01163 Inputs: pFilter - the BaseCamelotFilter filter that is being used to import a file. 01164 Success - True if everything went swimmingly, False if just a clean up is required. 01165 Purpose: Inform the colour list document component that a Web or Native export has 01166 just finished. 01167 Returns: TRUE if the component was able to end the importing; 01168 FALSE if not (e.g. out of memory) 01169 SeeAlso: DocComponent 01170 01171 ********************************************************************************************/ 01172 01173 BOOL ColourListComponent::EndExport(BaseCamelotFilter *pFilter, BOOL Success) 01174 { 01175 #ifdef DO_EXPORT 01176 // ERROR2IF(pExportedColours == NULL, FALSE, "ColourListComponent::EndExport no pExportedColours!"); 01177 // If we error about the pExportedColours then we assume that the EndImport has been called. 01178 // This may not be the case if we are in clean up mode. So just handle it! 01179 01180 TRACEUSER( "Neville", _T("ColourListComponent::EndExport\n")); 01181 if (pFilter == NULL) 01182 { 01183 ERROR3("ColourListComponent::EndExport filter is null!"); 01184 return TRUE; 01185 } 01186 01187 // Check if we should be saving unused colours or not. Usually this is controlled by the 01188 // user in Web files and always done in Native files. 01189 // Do not do if we are just in clean up mode or have no pExportedColours (indicating in clean up mode) 01190 if (!pFilter->IsWebFilter() && !pFilter->GetRemoveUnusedColours() && Success && pExportedColours) 01191 { 01192 TRACEUSER( "Neville", _T("ColourListComponent::EndExport exporting unsaved colours\n")); 01193 // Iterate over the document's list of named IndexedColours... 01194 IndexedColour *pCol = (IndexedColour *) pIndexedColours->GetHead(); 01195 BOOL ok = TRUE; 01196 while (ok && pCol != NULL) 01197 { 01198 if (!pCol->IsDeleted()) 01199 { 01200 // The colour is in use - save it to the file. 01201 ok = SaveColourAndParents(pCol, pFilter, 0); 01202 } 01203 01204 // Try the next colour 01205 pCol = (IndexedColour *) pIndexedColours->GetNext(pCol); 01206 } 01207 01208 // Iterate over the document's list of unnamed IndexedColours... 01209 List *pUnnamedColours = pIndexedColours->GetUnnamedColours(); 01210 01211 pCol = (IndexedColour *) pUnnamedColours->GetHead(); 01212 01213 ok = TRUE; 01214 while (ok && pCol != NULL) 01215 { 01216 if (!pCol->IsDeleted() && pCol->IsInUse()) 01217 { 01218 // The colour is in use and is not deleted 01219 // - save it to the file. 01220 ok = SaveColourAndParents(pCol, pFilter, 0); 01221 } 01222 01223 // Try the next colour 01224 pCol = (IndexedColour *) pUnnamedColours->GetNext(pCol); 01225 } 01226 } 01227 01228 #endif 01229 return TRUE; 01230 } 01231 01232 01233 01234 /******************************************************************************************** 01235 01236 > virtual void ColourListComponent::CleanUpAfterExport(BOOL Success) 01237 01238 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01239 Created: 21/8/96 01240 Inputs: Success - True if everything went swimmingly, False if the export failed 01241 01242 Purpose: Inform the document component that a Web or Native export has just finished. 01243 01244 Notes: This is called after EndExport, so that the component can clean up any 01245 during-export data structures. This allows situations like: PrintComponent 01246 wants to save a colour reference in it's EndExport call, but is called after 01247 the ColourComponent EndExport. The ColourComponent EndExport does not delete 01248 its data structures, so is still able to supply colour references to other 01249 components' EndExport functions. 01250 01251 SeeAlso: ColourListComponent::EndExport; DocComponent::CleanUpAfterExport 01252 01253 ********************************************************************************************/ 01254 01255 void ColourListComponent::CleanUpAfterExport(BOOL Success) 01256 { 01257 #ifdef DO_EXPORT 01258 // As we have finished with it now, destroy the list of exported colours 01259 if (pExportedColours) 01260 { 01261 delete pExportedColours; 01262 pExportedColours = NULL; 01263 } 01264 01265 // Null our link to the BaseCamelotFilter 01266 pCamFilter = NULL; 01267 01268 #endif 01269 return; 01270 } 01271 01272 01273 01274 /******************************************************************************************** 01275 01276 > INT32 ColourListComponent::GetWriteColourReference(DocColour* pDocColour, BaseCamelotFilter *pFilter) 01277 01278 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01279 Created: 24/5/96 01280 Inputs: pDocCololour - The document colour to save 01281 pFilter - The filter to use for saving 01282 Outputs: - 01283 Returns: The colour reference for the doccolour ready for writing in a record. 01284 This will be zero if a problem has occurred. May return -1 if it does not 01285 need to save anything i.e if the colour is not in use and not named. 01286 01287 Purpose: Return the colour reference to the caller, who will then use it to write the 01288 colour in the record that they are preparing to save to a Web or Native file. 01289 In the process of getting the colour reference, the colour definition record 01290 for the colour reference will be generated and saved to the file. In Web format 01291 this will just be the simple colour record, in native files this will be the 01292 full colour definition, possibly preceeded by the parents for the colour, as 01293 these must be saved before the children as the children must have a valid 01294 colour reference. 01295 NOTE: As this does save information into the record stream, it *MUST* be called 01296 before the caller has called StartRecord() as otherwise the records will become 01297 intertwined! 01298 Errors: - 01299 SeeAlso: IndexedColour; SaveComplexColour; SaveSimpleColour; SaveColourAndParents; 01300 01301 ********************************************************************************************/ 01302 01303 INT32 ColourListComponent::GetWriteColourReference(DocColour* pDocColour, BaseCamelotFilter *pFilter) 01304 { 01305 #ifdef DO_EXPORT 01306 ERROR2IF(pDocColour == NULL,0L,"ColourListComponent::GetWriteColourReference null pDocColour"); 01307 ERROR2IF(pFilter == NULL,0L,"ColourListComponent::GetWriteColourReference null pFilter"); 01308 01309 INT32 RecordNumber = 0L; 01310 01311 // First, check to see if the doc colour is transparent. If so then just return the default 01312 // default reference for this 01313 if (pDocColour->IsTransparent()) 01314 return REF_DEFAULTCOLOUR_TRANSPARENT; 01315 01316 // Get the indexed colour which this DocColour refers to, if any. 01317 IndexedColour * pCol = pDocColour->FindParentIndexedColour(); 01318 if (pCol) 01319 { 01320 // Its an indexed colour so either save it as a simple colour or a complex colour 01321 // depending on whether we are in Web or Native mode. 01322 if (pFilter->IsWebFilter()) 01323 { 01324 // We are in Web mode so save the simple colour 01325 RecordNumber = SaveSimpleColour(pCol, pFilter); 01326 } 01327 else 01328 { 01329 // We are in Web mode so save the simple colour 01330 RecordNumber = SaveColourAndParents(pCol, pFilter); 01331 } 01332 } 01333 else 01334 { 01335 // its a simple colour, so save this out as a simple colour. 01336 if (pFilter->IsWebFilter()) 01337 { 01338 // its a simple colour, so just save this as a simple colour. 01339 // We must add the RGB colours to our exported list, so that we only save the 01340 // definition out once. 01341 RecordNumber = SaveSimpleColour(pDocColour, pFilter, TRUE); 01342 } 01343 else 01344 { 01345 // TODO: 01346 // Could change this later to save out a complex colour in native files so that 01347 // these are converted to indexed colours on loading. Jason reckons this is favourable. 01348 // If we save it as a simple colour then there are bound to be conversion errors as 01349 // we are going from 24 bit components down to 8 bits and then back. 01350 01351 // Find a global colour context to convert this colour into RGB for us. 01352 ColourContextRGBT *cc = (ColourContextRGBT *)ColourManager::GetColourContext(COLOURMODEL_RGBT); 01353 ERROR3IF(cc == NULL, "ColourListComponent::GetWriteColourReference No global RGB colour context!? Something is very broken"); 01354 if (cc == NULL) 01355 return 0L; 01356 01357 // And convert the colour into a *packed* (8-bit components) colour structure 01358 PColourRGBT Result; 01359 cc->ConvertColour(pDocColour, (ColourPacked *)&Result); 01360 01361 // Only write this record out if we have not done so already 01362 // Check by seeing if the colour is already in our exported colour list 01363 ExportColour* pExportCol = NULL; 01364 pExportCol = pExportedColours->GetColour(&Result); 01365 // If it is then do not save this colour 01366 if (pExportCol) 01367 { 01368 // Just return the record number as the colour reference to the caller 01369 RecordNumber = pExportCol->RecordNumber; 01370 } 01371 else 01372 { 01373 // Create ourselves a new indexed colour to put our data in 01374 // Use the DocColour we have been supplied with, this should create an unnamed colour by default 01375 IndexedColour *pNewCol = new IndexedColour(*pDocColour); 01376 if (pNewCol) 01377 { 01378 // DY 3/5/2000 Now that I am now using the Reserved flag to indicate whether or not a doccolour 01379 // was created from a named colour and then de-indexed. For details see LineDefinition::ConvertIndexedColours 01380 // This means that if we get a doccolour with that flag set it was originally created by an indexed colour, so 01381 // we can call our function to find the parent 01382 01383 01384 IndexedColour* pIndexedCol = NULL; 01385 if (pDocColour->IsNamed()) 01386 { 01387 // Diccon, this is a named colour that was originally generated from an indexed colour but 01388 // subsequently de-indexed for various reasons. Its original parent should be in the list 01389 // somewhere 01390 pIndexedCol = GetIndexedParentOfColour(*pDocColour); 01391 01392 } 01393 else 01394 pNewCol->SetUnnamed(); 01395 01396 // Now save out the colour data in a complex colour record out to file 01397 // We cannot ask the routine to add this colour to the exported list as it is 01398 // not a REAL indexed colour in the indexed colour list, so say False. 01399 if (pIndexedCol == NULL) 01400 RecordNumber = SaveComplexColour(pNewCol, pFilter, FALSE); 01401 else 01402 // if we found an indexed colour then save out normally - DY 01403 RecordNumber = SaveColourAndParents(pIndexedCol, pFilter); 01404 01405 if (RecordNumber > 0) 01406 { 01407 // Add this colour to our list of exported items 01408 /*BOOL ok =*/ pExportedColours->AddColour(&Result, RecordNumber); 01409 // Should return this error to the caller but not fatal so just continue 01410 } 01411 01412 // We have finished with our indexed colour and so remove it 01413 delete pNewCol; 01414 } 01415 else 01416 { 01417 // We failed to create the complex colour so we have no choice but to save 01418 // it as a simple colour. 01419 // We must add the RGB colours to our exported list, so that we only save the 01420 // definition out once. 01421 RecordNumber = SaveSimpleColour(pDocColour, pFilter, TRUE); 01422 } 01423 } 01424 } 01425 } 01426 01427 return RecordNumber; 01428 #endif 01429 return 0L; 01430 } 01431 01432 /******************************************************************************************** 01433 01434 > INT32 ColourListComponent::SaveSimpleColour(IndexedColour *pCol, BaseCamelotFilter *pFilter) 01435 01436 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01437 Created: 21/5/96 01438 Inputs: pCol - The (root) colour to save 01439 pFilter - The filter to use for saving 01440 Outputs: - 01441 Returns: The record number for this colour, if it has been saved correctly or zero 01442 if a problem has occurred. May return -1 if it does not need to save anything 01443 i.e if the colour is not in use and not named. 01444 Purpose: Save out an indexed colour to a Web or Native file. Returns a record number or 01445 colour reference to the caller ready for use by somebody else to save in their 01446 record. 01447 This is the Web file form of saving colours. 01448 Errors: - 01449 SeeAlso: - 01450 01451 ********************************************************************************************/ 01452 01453 INT32 ColourListComponent::SaveSimpleColour(IndexedColour *pCol, BaseCamelotFilter *pFilter) 01454 { 01455 #ifdef DO_EXPORT 01456 ERROR2IF(pCol == NULL || pFilter == NULL, 0L, "ColourListComponent::SaveSimpleColour no pCol or pFilter supplied!"); 01457 ERROR2IF(pExportedColours == NULL, 0L, "ColourListComponent::SaveSimpleColour no pExportedColours!"); 01458 01459 // Use same condition as SaveColourAndChildren so that if the colour is unnamed 01460 // and it's not actually used anywhere, don't bother saving it. 01461 // This optimises out temporary locals that are no longer needed. At the worst, 01462 // if something goes horribly wrong, this just means that some locals might turn up 01463 // as CMYK definitions on reloading, but this shouldn't cause any problems unless 01464 // something deeply scary has happened to the colour system. 01465 if (!pCol->IsNamed() && !pCol->IsInUse()) 01466 return -1L; 01467 01468 // Only write this record out if we have not done so already 01469 // Check by seeing if the colour is already in our exported colour list 01470 ExportColour* pExportCol = NULL; 01471 pExportCol = pExportedColours->GetColour(pCol); 01472 // If it is then do not save this colour 01473 if (pExportCol) 01474 { 01475 // Just return the record number as the colour reference to the caller 01476 return pExportCol->RecordNumber; 01477 } 01478 01479 // Create a DocColour referencing this IndexedColour. 01480 DocColour SimpleColour; 01481 SimpleColour.MakeRefToIndexedColour(pCol); 01482 01483 // Save this as a document colour, don't check the export colour list as we are an indexed colour 01484 // really and so have cope with the list ourselves. 01485 INT32 RecordNumber = SaveSimpleColour(&SimpleColour, pFilter, FALSE); 01486 // returns 0 if there was a problem, exit now 01487 if (RecordNumber == 0) 01488 return RecordNumber; 01489 01490 // Add this colour to our list of exported items 01491 BOOL ok = pExportedColours->AddColour(pCol, RecordNumber); 01492 // If we have had a problem at any of the stages then return that to the caller 01493 if (!ok) 01494 return 0L; 01495 01496 // Everything went tickety boo, so return the record number to the caller. 01497 return RecordNumber; 01498 #else 01499 return 0L; 01500 #endif 01501 } 01502 01503 /******************************************************************************************** 01504 01505 > INT32 ColourListComponent::SaveSimpleColour(DocColour *pDocCol, BaseCamelotFilter *pFilter, 01506 BOOL CheckSimpleColourList = FALSE) 01507 01508 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01509 Created: 21/5/96 01510 Inputs: pDocCol - The document colour to save 01511 pFilter - The filter to use for saving 01512 CheckSimpleColourList - If TRUE then check the export colour list to see if we 01513 have saved this simple colour before 01514 If FALSE then this is an indexed colour so don't search 01515 the export colour list 01516 Outputs: - 01517 Returns: The record number for this colour, if it has been saved correctly or zero 01518 if a problem has occurred. May return -1 if it does not need to save anything 01519 i.e if the colour is not in use and not named. 01520 Purpose: Save out a document colour to a Web or Native file. Returns a record number or 01521 colour reference to the caller ready for use by somebody else to save in their 01522 record. 01523 This is the Web file form of saving colours. 01524 Errors: - 01525 SeeAlso: - 01526 01527 ********************************************************************************************/ 01528 01529 INT32 ColourListComponent::SaveSimpleColour(DocColour *pDocCol, BaseCamelotFilter *pFilter, 01530 BOOL CheckSimpleColourList) 01531 { 01532 #ifdef DO_EXPORT 01533 ERROR2IF(pDocCol == NULL || pFilter == NULL, 0L, "ColourListComponent::SaveSimpleColour no pCol or pFilter supplied!"); 01534 01535 // Find a global colour context to convert this colour into RGB for us. 01536 ColourContextRGBT *cc = (ColourContextRGBT *)ColourManager::GetColourContext(COLOURMODEL_RGBT); 01537 ERROR3IF(cc == NULL, "ColourListComponent::SaveSimpleColour No global RGB colour context!? Something is very broken"); 01538 if (cc == NULL) 01539 return 0L; 01540 01541 // And convert the colour into a *packed* (8-bit components) colour structure 01542 PColourRGBT Result; 01543 cc->ConvertColour(pDocCol, (ColourPacked *)&Result); 01544 01545 // If this is a simple colour rather than a simple colour of an indexed colour then 01546 // check to see if we have saved it already. If so then just return the record number 01547 if (CheckSimpleColourList) 01548 { 01549 // Only write this record out if we have not done so already 01550 // Check by seeing if the colour is already in our exported colour list 01551 ExportColour* pExportCol = NULL; 01552 pExportCol = pExportedColours->GetColour(&Result); 01553 // If it is then do not save this colour 01554 if (pExportCol) 01555 { 01556 // Just return the record number as the colour reference to the caller 01557 return pExportCol->RecordNumber; 01558 } 01559 } 01560 01561 // And finally, read the bytes out of the packed colour struct. 01562 BYTE RedByteValue = Result.Red; 01563 BYTE GreenByteValue = Result.Green; 01564 BYTE BlueByteValue = Result.Blue; 01565 01566 INT32 RecordNumber = 0L; 01567 if (RedByteValue == 0xFF && GreenByteValue == 0xFF && BlueByteValue == 0xFF) 01568 { 01569 RecordNumber = REF_DEFAULTCOLOUR_WHITE; 01570 } 01571 else if (RedByteValue == 0x00 && GreenByteValue == 0x00 && BlueByteValue == 0x00) 01572 { 01573 RecordNumber = REF_DEFAULTCOLOUR_BLACK; 01574 } 01575 else if (RedByteValue == 0xFF && GreenByteValue == 0x00 && BlueByteValue == 0x00) 01576 { 01577 RecordNumber = REF_DEFAULTCOLOUR_RED; 01578 } 01579 else if (RedByteValue == 0x00 && GreenByteValue == 0xFF && BlueByteValue == 0x00) 01580 { 01581 RecordNumber = REF_DEFAULTCOLOUR_GREEN; 01582 } 01583 else if (RedByteValue == 0x00 && GreenByteValue == 0x00 && BlueByteValue == 0xFF) 01584 { 01585 RecordNumber = REF_DEFAULTCOLOUR_BLUE; 01586 } 01587 else if (RedByteValue == 0x00 && GreenByteValue == 0xFF && BlueByteValue == 0xFF) 01588 { 01589 RecordNumber = REF_DEFAULTCOLOUR_CYAN; 01590 } 01591 else if (RedByteValue == 0xFF && GreenByteValue == 0x00 && BlueByteValue == 0xFF) 01592 { 01593 RecordNumber = REF_DEFAULTCOLOUR_MAGENTA; 01594 } 01595 else if (RedByteValue == 0xFF && GreenByteValue == 0xFF && BlueByteValue == 0x00) 01596 { 01597 RecordNumber = REF_DEFAULTCOLOUR_YELLOW; 01598 } 01599 else 01600 { 01601 BOOL ok = TRUE; 01602 // Write the data out to the file 01603 //INT32 RecordNumber = pFilter->StartRecord(TAG_DEFINERGBCOLOUR, TAG_DEFINERGBCOLOUR_SIZE); 01604 CXaraFileRecord Rec(TAG_DEFINERGBCOLOUR,TAG_DEFINERGBCOLOUR_SIZE); 01605 ok = Rec.Init(); 01606 01607 if (ok) ok = Rec.WriteBYTE(RedByteValue); 01608 if (ok) ok = Rec.WriteBYTE(GreenByteValue); 01609 if (ok) ok = Rec.WriteBYTE(BlueByteValue); 01610 01611 // Finally, write the record out to file 01612 // In the process get the record number that this was written out as 01613 if (ok) RecordNumber = pFilter->WriteDefinitionRecord(&Rec); 01614 01615 // If we have had a problem at any of the stages then return that to the caller 01616 if (!ok || RecordNumber <= 0) 01617 return 0L; 01618 } 01619 01620 // If this is a simple colour rather than a simple colour of an indexed colour then 01621 // add it to the list so that we do not save out the definition twice! 01622 if (CheckSimpleColourList) 01623 { 01624 // Add this colour to our list of exported items 01625 BOOL ok = pExportedColours->AddColour(&Result, RecordNumber); 01626 // If we have had a problem at any of the stages then return that to the caller 01627 if (!ok) 01628 return 0L; 01629 } 01630 01631 // Everything went tickety boo, so return the record number to the caller. 01632 return RecordNumber; 01633 #else 01634 return 0L; 01635 #endif 01636 } 01637 01638 // Simple macro to make the code in SaveColourAndParents() a bit neater. 01639 #define LINKED_COLOUR(ID) (Linked && pCol->InheritsComponent((ID))) 01640 01641 /******************************************************************************************** 01642 01643 > INT32 ColourListComponent::SaveColourAndParents(IndexedColour *pCol, BaseCamelotFilter *pFilter, 01644 INT32 NestingLevel = 0) 01645 01646 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01647 Created: 21/5/96 01648 Inputs: pCol - The (root) colour to save 01649 pFilter - The filter to use for saving 01650 NestingLevel - How many parental levels up we have gone so far 01651 Outputs: - 01652 Returns: The record number for this colour, if it has been saved correctly or zero 01653 if a problem has occurred. May return -1 if it does not need to save anything 01654 i.e if the colour is not in use and not named. 01655 Purpose: Save out an indexed colour to a Web or Native file. Returns a record number or 01656 colour reference to the caller ready for use by somebody else to save in their 01657 record. 01658 This is the Web file form of saving colours. 01659 Purpose: Save out an indexed colour in its complex form usually to a Native file. 01660 If it has any parents then these must be saved out before it, as the colour 01661 reference for the parent *MUST* be a real record number which has been 01662 previously saved into the stream. 01663 Returns a record number or colour reference to the caller ready for use by 01664 somebody else to save in their record. 01665 This is the Native file form of saving colours. 01666 Errors: - 01667 SeeAlso: - 01668 01669 ********************************************************************************************/ 01670 01671 INT32 ColourListComponent::SaveColourAndParents(IndexedColour *pCol, BaseCamelotFilter *pFilter, 01672 INT32 NestingLevel) 01673 { 01674 #ifdef DO_EXPORT 01675 ERROR2IF(pCol == NULL || pFilter == NULL, 0L, "ColourListComponent::SaveColourAndParents no pCol or pFilter!"); 01676 ERROR2IF(pExportedColours == NULL, 0L, "ColourListComponent::SaveColourAndParents no pExportedColours!"); 01677 01678 // Use same condition as SaveColourAndChildren so that if the colour is unnamed 01679 // and it's not actually used anywhere, don't bother saving it. 01680 // This optimises out temporary locals that are no longer needed. At the worst, 01681 // if something goes horribly wrong, this just means that some locals might turn up 01682 // as CMYK definitions on reloading, but this shouldn't cause any problems unless 01683 // something deeply scary has happened to the colour system. 01684 if (!pCol->IsNamed() && !pCol->IsInUse()) 01685 return -1L; 01686 01687 // Check for silly recursion errors [not that you can get circular references with 01688 // the amazingly strict and careful checking done by the IndexedColour class. 01689 // Same test as SaveColourAndChildren. 01690 ERROR2IF(NestingLevel > 200, 0L, "ColourListComponent::SaveColourAndParents - Rampant linked colour nesting detected!"); 01691 01692 // **** 01693 // **** First, save parents of this colour, if any and if not saved previously 01694 // **** 01695 01696 // Before we save out this colour, we must check if it has a parent, if so then 01697 // we must save out the parents first as we must reference parents by a record 01698 // number and hence it must have already been saved! 01699 01700 // So, recurse and save out any parents of this colour (links or tints)... 01701 01702 // Get all the named colours that are immediate children of this colour 01703 // This only returns a parent if this is a colour with a valid parent e.g. tint 01704 IndexedColour *pParent = pCol->FindLinkedParent(); 01705 //IndexedColour *pParentCol = pParent; 01706 ExportColour* pExportCol = NULL; 01707 while (pParent != NULL) 01708 { 01709 if (!pParent->IsDeleted()) 01710 { 01711 // Found a parent - save out via recursion so we save all its ascendants in the 01712 // right order... 01713 // To save time, check here if this parent is already in our list, if it this 01714 // then no point in recursing through the chain of parents as they all have already 01715 // been saved. 01716 pExportCol = pExportedColours->GetColour(pParent); 01717 // If it is NULL then we have not already saved this colour, so do so. 01718 if (pExportCol == NULL) 01719 SaveColourAndParents(pParent, pFilter, NestingLevel + 1); 01720 } 01721 01722 // Try the next colour 01723 pParent = pParent->FindLinkedParent(); 01724 } 01725 01726 // **** 01727 // **** Saved this colour before? 01728 // **** 01729 01730 // Only write this record out if we have not done so already 01731 // Check by seeing if the colour is already in our exported colour list 01732 pExportCol = pExportedColours->GetColour(pCol); 01733 // If it is then do not save this colour 01734 if (pExportCol) 01735 { 01736 // Just return the record number as the colour reference to the caller 01737 return pExportCol->RecordNumber; 01738 } 01739 01740 // Now save out the colour data in a complex colour record out to file 01741 // We want this indexed colour adding to the exported list and so say TRUE 01742 INT32 RecordNumber = SaveComplexColour(pCol, pFilter, TRUE); 01743 01744 // Everything went tickety boo, so return the record number to the caller. 01745 return RecordNumber; 01746 #else 01747 return 0L; 01748 #endif 01749 } 01750 01751 /******************************************************************************************** 01752 01753 > INT32 ColourListComponent::SaveComplexColour(IndexedColour *pCol, BaseCamelotFilter *pFilter, 01754 BOOL AddColourToList = TRUE) 01755 01756 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01757 Created: 4/6/96 01758 Inputs: pCol - The (root) colour to save 01759 pFilter - The filter to use for saving 01760 AddColourToList - True if we are to add this colour to the exported colour list 01761 - False if the caller has already done this 01762 Outputs: - 01763 Returns: The record number for this colour, if it has been saved correctly or zero 01764 if a problem has occurred. May return -1 if it does not need to save anything 01765 i.e if the colour is not in use and not named. 01766 Purpose: Actually save out an indexed colour to a Web or Native file in a complex colour 01767 record. Returns a record number or colour reference to the caller ready for use 01768 by somebody else to save in their record. 01769 If it has any parents then these must be saved out before it, as the colour 01770 reference for the parent *MUST* be a real record number which has been 01771 previously saved into the stream. 01772 Returns a record number or colour reference to the caller ready for use by 01773 somebody else to save in their record. 01774 This is the Native file form of saving colours. 01775 Errors: - 01776 SeeAlso: SaveColourAndParents; GetWriteColourReference; 01777 01778 ********************************************************************************************/ 01779 INT32 ColourListComponent::SaveComplexColour(IndexedColour *pCol, BaseCamelotFilter *pFilter, 01780 BOOL AddColourToList) 01781 { 01782 #ifdef DO_EXPORT 01783 01784 ERROR2IF(pCol == NULL || pFilter == NULL, 0L, "ColourListComponent::SaveComplexColour no pCol or pFilter!"); 01785 ERROR2IF(pExportedColours == NULL, 0L, "ColourListComponent::SaveComplexColour no pExportedColours!"); 01786 01787 // When GetColourLinePosition is TRUE, it means that we want to save the colour's pos on the colour 01788 // line, so that it can be imported in the correct order. 01789 // 01790 // This is set to AddColourToList by default - i.e. assume that if it's being added to the list of exported 01791 // colours, then we probably want to preserve the colour' pos 01792 BOOL GetColourLinePosition = AddColourToList; 01793 01794 // **** 01795 // **** Get the information on the colour 01796 // **** 01797 01798 // Get information on the colour - ask for its full identifier rather than just the name, 01799 // so we get a unique id for unnamed colours rather than just "Local colour" 01800 ColourModel Model = pCol->GetColourModel(); 01801 ColourGeneric GenCol; 01802 IndexedColourType ColType = pCol->GetType(); 01803 pCol->GetSourceColour(&GenCol); 01804 String_64 ColName = *(pCol->GetName(TRUE)); 01805 if (ColName[0] == '_') 01806 { 01807 // We have an unnamed colour and so the name should be blank 01808 ColName.Empty(); 01809 01810 // If it's an unnamed colour, then it's assumed it's not on the colour line, so we 01811 // won't need to find it's pos on the colour line 01812 GetColourLinePosition = FALSE; 01813 } 01814 01815 //TCHAR *ColName = (TCHAR *) (*(pCol->GetName(TRUE))); 01816 01817 // Find a global colour context to convert this colour into RGB for us. 01818 ColourContextRGBT *cc = (ColourContextRGBT *)ColourManager::GetColourContext(COLOURMODEL_RGBT); 01819 ERROR3IF(cc == NULL, "ColourListComponent::SaveComplexColour No global RGB colour context!? Something is very broken"); 01820 if (cc == NULL) 01821 return 0L; 01822 01823 BOOL ok = FALSE; 01824 // Create a DocColour referencing this IndexedColour. 01825 DocColour SimpleColour; 01826 SimpleColour.MakeRefToIndexedColour(pCol); 01827 01828 // And convert the colour into a *packed* (8-bit components) colour structure 01829 PColourRGBT Result; 01830 cc->ConvertColour(&SimpleColour, (ColourPacked *)&Result); 01831 01832 // And finally, read the bytes out of the packed colour struct. 01833 BYTE RedByteValue = Result.Red; 01834 BYTE GreenByteValue = Result.Green; 01835 BYTE BlueByteValue = Result.Blue; 01836 01837 // **** 01838 // **** Save the record 01839 // **** 01840 01841 // Write the data out to the file 01842 UINT32 Size = TAG_DEFINECOMPLEXCOLOUR_SIZE; 01843 // If there is a string name, then add it to this size 01844 // REMEMBER: We save out unicode strings and so we need to double the length of the returned string length 01845 Size += (ColName.Length() + 1) * SIZEOF_XAR_UTF16; 01846 01847 // INT32 RecordNumber = pFilter->StartRecord(TAG_DEFINECOMPLEXCOLOUR, Size); 01848 CXaraFileRecord Rec(TAG_DEFINECOMPLEXCOLOUR, Size); 01849 ok = Rec.Init(); 01850 01851 // Start with the simple RGB colour 01852 if (ok) ok = Rec.WriteBYTE(RedByteValue); 01853 if (ok) ok = Rec.WriteBYTE(GreenByteValue); 01854 if (ok) ok = Rec.WriteBYTE(BlueByteValue); 01855 01856 // Now write out the colour model... 01857 if (ok) ok = Rec.WriteBYTE((BYTE)Model); 01858 01859 // Now write out the colour type... 01860 // Include flags about linking in colour type? 01861 // If the colour is linked, we save out the component as an illegal known value 01862 // Convert the colour types into export colour types 01863 // Should be a straight conversion but just in case... 01864 ExportColourType ExpColType=EXPORT_COLOURTYPE_NORMAL; 01865 switch (ColType) 01866 { 01867 case COLOURTYPE_NORMAL: ExpColType = EXPORT_COLOURTYPE_NORMAL; break; 01868 case COLOURTYPE_SPOT: ExpColType = EXPORT_COLOURTYPE_SPOT; break; 01869 case COLOURTYPE_LINKED: ExpColType = EXPORT_COLOURTYPE_LINKED; break; 01870 case COLOURTYPE_TINT: 01871 if (pCol->TintIsShade()) 01872 ExpColType = EXPORT_COLOURTYPE_SHADE; 01873 else 01874 ExpColType = EXPORT_COLOURTYPE_TINT; 01875 break; 01876 default: 01877 ERROR3("ColourListComponent::SaveColour - Unknown colour model!"); 01878 break; 01879 } 01880 if (ok) ok = Rec.WriteBYTE((BYTE)ExpColType); 01881 01882 // Write out the entry number this colour is in the indexed colour list 01883 UINT32 ColourListNumber = 0L; 01884 // If GetColourLinePosition is False then the indexed colour is not on the colour line. 01885 // so do NOT try and go through the list of colours to find its pos number, just use zero. 01886 if (GetColourLinePosition) 01887 ColourListNumber = GetIndexColourNumber(pCol); 01888 if (ok) ok = Rec.WriteUINT32(ColourListNumber); 01889 01890 // Write out the reference number of the parent colour 01891 UINT32 ParentColourRef = 0L; 01892 IndexedColour *pParentCol = pCol->FindLinkedParent(); 01893 ExportColour* pExportCol = NULL; 01894 if (pParentCol) 01895 { 01896 // If there is a parent then recover the record number from the exported colours list 01897 pExportCol = pExportedColours->GetColour(pParentCol); 01898 ERROR2IF(pExportCol == NULL,FALSE,"ColourListComponent::SaveComplexColour Not exported parent before child!"); 01899 ParentColourRef = pExportCol->RecordNumber; 01900 TRACEUSER( "Neville", _T("Saving parent reference %d\n"),ParentColourRef); 01901 } 01902 01903 if (ok) ok = Rec.WriteReference(ParentColourRef); 01904 01905 BOOL Linked = (ColType == COLOURTYPE_LINKED); 01906 switch (ColType) 01907 { 01908 01909 case COLOURTYPE_NORMAL: 01910 case COLOURTYPE_SPOT: 01911 case COLOURTYPE_LINKED: 01912 { 01913 // These all require the same handling 01914 // Linked colours save out the components in the normal fashion 01915 01916 // Now write out the colour component values depending on the model in use... 01917 switch (Model) 01918 { 01919 case COLOURMODEL_RGBT: 01920 // Now add the RGB components. 01921 // Stored as FIXED24s. 01922 ColourRGBT *pRGBT; 01923 pRGBT = (ColourRGBT *) &GenCol; 01924 if (ok) ok = Rec.WriteUINT32(AddComponentValue(pRGBT->Red, LINKED_COLOUR(1))); 01925 if (ok) ok = Rec.WriteUINT32(AddComponentValue(pRGBT->Green, LINKED_COLOUR(2))); 01926 if (ok) ok = Rec.WriteUINT32(AddComponentValue(pRGBT->Blue, LINKED_COLOUR(3))); 01927 if (ok) ok = Rec.WriteUINT32(AddComponentValue(pRGBT->Transparent, LINKED_COLOUR(4))); 01928 break; 01929 01930 case COLOURMODEL_HSVT: 01931 // Now add the HSV components. 01932 ColourHSVT *pHSVT; 01933 pHSVT = (ColourHSVT *) &GenCol; 01934 if (ok) ok = Rec.WriteUINT32(AddComponentValue(pHSVT->Hue, LINKED_COLOUR(1))); 01935 if (ok) ok = Rec.WriteUINT32(AddComponentValue(pHSVT->Saturation, LINKED_COLOUR(2))); 01936 if (ok) ok = Rec.WriteUINT32(AddComponentValue(pHSVT->Value, LINKED_COLOUR(3))); 01937 if (ok) ok = Rec.WriteUINT32(0); // pad to 4 colour components 01938 break; 01939 01940 case COLOURMODEL_CMYK: 01941 // Now add the CMYK components. 01942 ColourCMYK *pCMYK; 01943 pCMYK = (ColourCMYK *) &GenCol; 01944 if (ok) ok = Rec.WriteUINT32(AddComponentValue(pCMYK->Cyan, LINKED_COLOUR(1))); 01945 if (ok) ok = Rec.WriteUINT32(AddComponentValue(pCMYK->Magenta, LINKED_COLOUR(2))); 01946 if (ok) ok = Rec.WriteUINT32(AddComponentValue(pCMYK->Yellow, LINKED_COLOUR(3))); 01947 if (ok) ok = Rec.WriteUINT32(AddComponentValue(pCMYK->Key, LINKED_COLOUR(4))); 01948 break; 01949 01950 case COLOURMODEL_GREYT: 01951 // greyscale colour. 01952 ColourGreyT *pGreyT; 01953 pGreyT = (ColourGreyT *) &GenCol; 01954 if (ok) ok = Rec.WriteUINT32(AddComponentValue(pGreyT->Intensity, LINKED_COLOUR(1))); 01955 if (ok) ok = Rec.WriteUINT32(0); // pad to 4 colour components 01956 if (ok) ok = Rec.WriteUINT32(0); // pad to 4 colour components 01957 if (ok) ok = Rec.WriteUINT32(0); // pad to 4 colour components 01958 break; 01959 01960 default: 01961 ERROR3("ColourListComponent::SaveColour - Unknown colour model!"); 01962 break; 01963 } 01964 break; 01965 } 01966 01967 case COLOURTYPE_TINT: 01968 { 01969 // If we have a tint colour then this needs special handling 01970 FIXED24 TintVal(0.0); 01971 FIXED24 ShadeVal(0.0); 01972 // Is the tint a tint or is it really a shade 01973 // Add tint identifier to colour definition 01974 if (pCol->TintIsShade()) 01975 { 01976 ShadeVal = pCol->GetShadeValueX(); 01977 TintVal = pCol->GetShadeValueY(); 01978 if (ok) ok = Rec.WriteUINT32(AddComponentValue(ShadeVal, LINKED_COLOUR(1))); 01979 if (ok) ok = Rec.WriteUINT32(AddComponentValue(TintVal, LINKED_COLOUR(1))); 01980 if (ok) ok = Rec.WriteUINT32(0); // pad to 4 colour components 01981 if (ok) ok = Rec.WriteUINT32(0); // pad to 4 colour components 01982 } 01983 else 01984 { 01985 TintVal = pCol->GetTintValue(); 01986 if (ok) ok = Rec.WriteUINT32(AddComponentValue(TintVal, LINKED_COLOUR(1))); 01987 if (ok) ok = Rec.WriteUINT32(0); // pad to 4 colour components 01988 if (ok) ok = Rec.WriteUINT32(0); // pad to 4 colour components 01989 if (ok) ok = Rec.WriteUINT32(0); // pad to 4 colour components 01990 } 01991 break; 01992 } 01993 default: 01994 ERROR3("ColourListComponent::SaveColour - Unknown colour type!"); 01995 break; 01996 } 01997 01998 // Write out the name of the colour 01999 if (ok) ok = Rec.WriteUnicode(ColName); 02000 02001 // Finally, write the record out to file 02002 INT32 RecordNumber = 0L; 02003 if (ok) RecordNumber = pFilter->WriteDefinitionRecord(&Rec); 02004 02005 // Has the caller handled adding this to the colour list already? No, so do it oursleves. 02006 if (AddColourToList && RecordNumber > 0) 02007 { 02008 // Add this colour to our list of exported items 02009 ok = pExportedColours->AddColour(pCol, RecordNumber); 02010 } 02011 //TRACEUSER( "Neville", _T("Saving colour %s, number %d, entry number %d\n"),(TCHAR*)ColName, RecordNumber, ColourListNumber); 02012 02013 // If we have had a problem at any of the stages then return that to the caller 02014 if (!ok) 02015 return 0L; 02016 02017 // Everything went tickety boo, so return the record number to the caller. 02018 return RecordNumber; 02019 #else 02020 return 0L; 02021 #endif 02022 } 02023 02024 /******************************************************************************************** 02025 02026 > UINT32 ColourListComponent::AddComponentValue(FIXED24 ComponentValue, BOOL Inherited) 02027 02028 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 02029 Created: 28/5/96 02030 Inputs: ComponentValue - the value to be returned. 02031 Inherited - TRUE => This component is inherited, so just output a known illegal value 02032 FALSE => This component is not inherited, so output the 02033 actual value to the string 02034 Outputs: - 02035 Returns: The colour component as a UINT32 ready to write out to file. 02036 Purpose: Returns either the colour component value or if it is inherited, a known illegal 02037 value which we can intepret on import to be an overridden value. 02038 Doing it in a function centralises the syntax of inherited components. 02039 Errors: - 02040 SeeAlso: ColourListComponent::SaveColourAndParents 02041 02042 ********************************************************************************************/ 02043 02044 UINT32 ColourListComponent::AddComponentValue(FIXED24 ComponentValue, BOOL Inherited) 02045 { 02046 // Construct the colour component value 02047 UINT32 ColourValue = 0L; 02048 02049 // If this is a linked colour, and this component is inherited, then just add a '-'. 02050 if (Inherited) 02051 { 02052 ColourValue = FIXED24(-8.0).GetAsFixed24(); 02053 } 02054 else 02055 { 02056 // We have to output the component.... 02057 ColourValue = ComponentValue.GetAsFixed24(); 02058 } 02059 02060 return ColourValue; 02061 } 02062 02063 /******************************************************************************************** 02064 02065 > INT32 ColourListComponent::GetIndexColourNumber(IndexedColour *pCol) 02066 02067 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 02068 Created: 21/5/96 02069 Inputs: pCol - the indexed colour to search out the number for. 02070 Returns: The number of this indexed colour in the list of colours (i.e.position) 02071 Purpose: Work out the index of this colour in the list of indexed colours so that we 02072 can try and load back the colours in the same order. 02073 Unfortunately, the only way it seems that we can work out this number is by 02074 counting back to the start of the indexed colour list. Doh! 02075 SeeAlso: IndexedColour 02076 02077 ********************************************************************************************/ 02078 02079 INT32 ColourListComponent::GetIndexColourNumber(IndexedColour *pCol) 02080 { 02081 ERROR2IF(pCol==NULL,0,"ColourListComponent::GetIndexColourNumber no Colour pointer"); 02082 ERROR2IF(pIndexedColours==NULL,0,"ColourListComponent::GetIndexColourNumber no pIndexedColours"); 02083 02084 INT32 number = 0; 02085 02086 // Due to pants list class, we need to check that there is a previous memember before we 02087 // call GetPrev, otherwise it ensures all over the place. Why it can't just return NULL! 02088 if (pIndexedColours->IsEmpty()) 02089 return number; 02090 02091 // Go from this item to the start of the inddexed colour list, counting items as we go 02092 while (pCol) 02093 { 02094 pCol = (IndexedColour *) pIndexedColours->GetPrev(pCol); 02095 // If the colour is not deleted then count it 02096 if (pCol && !pCol->IsDeleted()) 02097 number ++; 02098 } 02099 02100 return number; 02101 } 02102 02103 02104 /******************************************************************************************** 02105 ********************************************************************************************/ 02106 02107 // Remove the preceeding code on all builds but those who want it 02108 02109 /******************************************************************************************** 02110 ********************************************************************************************/ 02111 02112 /******************************************************************************************** 02113 02114 > BOOL ColourListComponent::EPSStartImport(EPSFilter *pFilter) 02115 02116 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02117 Created: 03/08/94 02118 Inputs: pFilter - the EPS filter that is being used to import a file. 02119 Purpose: Inform the colour list document component that an EPS import is about to 02120 start. 02121 SeeAlso: DocComponent 02122 02123 ********************************************************************************************/ 02124 02125 BOOL ColourListComponent::EPSStartImport(EPSFilter *pFilter) 02126 { 02127 // Is this a Camelot EPS filter? 02128 BOOL CamelotEPS = pFilter->IS_KIND_OF(CamelotEPSFilter); 02129 02130 // Get a colour table (and don't do strict checking if we are loading Camelot EPS). 02131 pNewColours = new ImportedColours(this, !CamelotEPS); 02132 if ((pNewColours == NULL) || !pNewColours->Init()) 02133 return FALSE; 02134 02135 // We keep a record of how nested we are with respect to linking colours, e.g. 02136 // links of links of links. 02137 // A nesting of 0 is no nesting. 02138 LinkNesting = 0; 02139 02140 // Must have worked 02141 return TRUE; 02142 } 02143 02144 /******************************************************************************************** 02145 02146 > void ColourListComponent::EPSEndImport(EPSFilter *pFilter, BOOL Success) 02147 02148 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02149 Created: 03/08/94 02150 Inputs: pFilter - the EPS filter that is being used to import a file. 02151 Success - TRUE => The import was successful; 02152 FALSE => The import failed - abandon any changes. 02153 Purpose: Inform the colour list document component that an EPS import has just 02154 finished. 02155 SeeAlso: DocComponent 02156 02157 ********************************************************************************************/ 02158 02159 void ColourListComponent::EPSEndImport(EPSFilter *pFilter, BOOL Success) 02160 { 02161 ERROR3IF(pNewColours == NULL, "No colour table in EndEPSImport"); 02162 02163 // If we didn't even get to initialise, then return quietly. 02164 if (pNewColours == NULL) 02165 return; 02166 02167 // Import is finished, so add any outstanding colours to the document (if the 02168 // import was successful), and delete the colour table 02169 if (Success) 02170 { 02171 pNewColours->AddColoursToDocument(); 02172 } 02173 else 02174 { 02175 // Import failed - destroy all the colours. 02176 pNewColours->DestroyColours(); 02177 } 02178 02179 // Finally, delete the IndexedColour table. 02180 delete pNewColours; 02181 pNewColours = NULL; 02182 } 02183 02184 02185 02186 /******************************************************************************************** 02187 02188 > void ColourListComponent::AddNewColour(IndexedColour *pNewCol) 02189 02190 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02191 Created: 08/08/94 02192 Inputs: pNewCol - the colour to add. 02193 Purpose: Adds an indexed colour to the colour list (which in turn ensures that 02194 it has a unique colour name) 02195 SeeAlso: ColourList::AddItem 02196 02197 ********************************************************************************************/ 02198 02199 void ColourListComponent::AddNewColour(IndexedColour *pNewCol) 02200 { 02201 ERROR3IF(pNewCol == NULL, 02202 "ColourListComponent::AddNewColour: The colour to add is NULL!"); 02203 ERROR3IF(pIndexedColours == NULL, 02204 "ColourListComponent::AddNewColour: I have no IndexedColour list!"); 02205 02206 // Add the colour, ensuring that it has a unique name 02207 pIndexedColours->AddItem(pNewCol); 02208 } 02209 02210 02211 02212 /******************************************************************************************** 02213 02214 > BOOL ColourListComponent::WriteEPSComments(EPSFilter *pFilter) 02215 02216 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02217 Created: 02/08/94 02218 Inputs: pFilter - the filter being used to import the EPS file. 02219 Returns: TRUE if the colour table was written successfully; 02220 FALSE if not. 02221 Purpose: Writes out the colour table in the form of EPS comments in the 'header' 02222 comments of the EPS file. 02223 02224 Notes: IMPORTANT: Version 1.1 file extensions (Jason, 7/9/95 & 14/10/95) 02225 For this version, Shade colours have been added. 02226 To retain backward compatability, 02227 all shades and their children are written into a second colour table 02228 (a %%JWColourTable). This means old loader code will skip them and use 02229 the inlined CMYK definitions, thus retaining the appearance of the document 02230 while only losing unsupported colour linking info. 02231 Thus, we do a 2-pass scheme. The first pass will (by use of default params 02232 in SaveColourAndChildren) fail to save out any shades and children. 02233 The second pass then saves all shades and their parents and children. 02234 Note this means parent colours can be saved twice, but these will be 02235 happily merged on loading, so no bad effects occur. 02236 02237 Shades are only saved out in CamelotEPS. In Artworks EPS mode, they 02238 become standalone named colours. 02239 02240 Errors: Out of disk space, and similar disk errors. 02241 SeeAlso: DocComponent::WriteEPSComments; 02242 DocComponent 02243 02244 ********************************************************************************************/ 02245 02246 BOOL ColourListComponent::WriteEPSComments(EPSFilter *pFilter) 02247 { 02248 #ifdef DO_EXPORT 02249 if (pFilter->IsKindOf(CC_RUNTIME_CLASS(ArtWorksEPSFilter))) 02250 { 02251 // Is it a Camelot specific filter? 02252 BOOL CamelotEPS = pFilter->IsKindOf(CC_RUNTIME_CLASS(CamelotEPSFilter)); 02253 02254 // Output the colour table in ArtWorks format. 02255 EPSExportDC *pDC = pFilter->GetExportDC(); 02256 02257 // The ArtWorks EPS comment: 02258 pDC->OutputToken(_T("%%AWColourTable")); 02259 pDC->OutputNewLine(); 02260 02261 // Iterate over the document's list of named IndexedColours... 02262 IndexedColour *pCol = (IndexedColour *) pIndexedColours->GetHead(); 02263 02264 while (pCol != NULL) 02265 { 02266 if (!pCol->IsDeleted() && 02267 ((pCol->GetType() == COLOURTYPE_NORMAL) || 02268 (pCol->GetType() == COLOURTYPE_SPOT))) 02269 { 02270 // The colour is in use and is not a linked colour or tint - save it to 02271 // the EPS file. 02272 SaveColourAndChildren(pCol, pDC, CamelotEPS); 02273 02274 } 02275 02276 // Try the next colour 02277 pCol = (IndexedColour *) pIndexedColours->GetNext(pCol); 02278 } 02279 02280 // Iterate over the document's list of unnamed IndexedColours... 02281 List *pUnnamedColours = pIndexedColours->GetUnnamedColours(); 02282 02283 pCol = (IndexedColour *) pUnnamedColours->GetHead(); 02284 02285 while (pCol != NULL) 02286 { 02287 if (!pCol->IsDeleted() && pCol->IsInUse() && 02288 ((pCol->GetType() == COLOURTYPE_NORMAL) || 02289 (pCol->GetType() == COLOURTYPE_SPOT))) 02290 { 02291 // The colour is in use and is not a linked colour or tint - save it to 02292 // the EPS file. 02293 SaveColourAndChildren(pCol, pDC, CamelotEPS); 02294 } 02295 02296 // Try the next colour 02297 pCol = (IndexedColour *) pUnnamedColours->GetNext(pCol); 02298 } 02299 02300 02301 // --- PASS 2 - version 1.1 second colour table for shades and other extensions 02302 if (CamelotEPS) 02303 { 02304 // This variable is used to stop us outputting the colour table section 02305 // if it is not needed - we only output the header line when we write the 02306 // first colour out to this table. 02307 BOOL HaveOutputHeader = FALSE; 02308 02309 // Iterate over the document's list of named IndexedColours... 02310 IndexedColour *pCol = (IndexedColour *) pIndexedColours->GetHead(); 02311 02312 while (pCol != NULL) 02313 { 02314 if (!pCol->IsDeleted() && 02315 ((pCol->GetType() == COLOURTYPE_NORMAL) || 02316 (pCol->GetType() == COLOURTYPE_SPOT))) 02317 { 02318 // The colour is in use and is not a linked colour or tint - save it to 02319 // the EPS file. 02320 if (ColourOrChildIsShade(pCol)) 02321 { 02322 if (!HaveOutputHeader) 02323 { 02324 // Output the header comment if we haven't already done so 02325 pDC->OutputToken(_T("%%JWColourTable")); 02326 pDC->OutputNewLine(); 02327 HaveOutputHeader = TRUE; 02328 } 02329 02330 SaveColourAndChildren(pCol, pDC, CamelotEPS, 0, TRUE); 02331 } 02332 } 02333 02334 // Try the next colour 02335 pCol = (IndexedColour *) pIndexedColours->GetNext(pCol); 02336 } 02337 02338 // Iterate over the document's list of unnamed IndexedColours... 02339 List *pUnnamedColours = pIndexedColours->GetUnnamedColours(); 02340 02341 pCol = (IndexedColour *) pUnnamedColours->GetHead(); 02342 02343 while (pCol != NULL) 02344 { 02345 if (!pCol->IsDeleted() && pCol->IsInUse() && 02346 ((pCol->GetType() == COLOURTYPE_NORMAL) || 02347 (pCol->GetType() == COLOURTYPE_SPOT))) 02348 { 02349 // The colour is in use and is not a linked colour or tint - save it to 02350 // the EPS file. 02351 if (ColourOrChildIsShade(pCol)) 02352 { 02353 if (!HaveOutputHeader) 02354 { 02355 // Output the header comment if we haven't already done so 02356 pDC->OutputToken(_T("%%JWColourTable")); 02357 pDC->OutputNewLine(); 02358 HaveOutputHeader = TRUE; 02359 } 02360 02361 SaveColourAndChildren(pCol, pDC, CamelotEPS, 0, TRUE); 02362 } 02363 } 02364 02365 // Try the next colour 02366 pCol = (IndexedColour *) pUnnamedColours->GetNext(pCol); 02367 } 02368 02369 } 02370 } 02371 #endif 02372 // All ok. 02373 return TRUE; 02374 } 02375 02376 /******************************************************************************************** 02377 02378 > void ColourListComponent::AddComponentValue(char *ColDef, char *Format, 02379 double ComponentValue, BOOL Inherited) 02380 02381 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02382 Created: 05/12/94 02383 Inputs: ColDef - the current colour definition string, which this routine should 02384 append the component value to. 02385 Format - the printf format to use when converting the value to ASCII. 02386 ComponentValue - the value to add to the string. 02387 Inherited - TRUE => This component is inherited, so just output a '-' 02388 FALSE => This component is not inherited, so output the 02389 actual value to the string 02390 Outputs: ColDef - the updated colour definition string, with the value converted to 02391 ASCII (taking into account the Inherited flag), and appended (with 02392 a leading space so the values don't join together). 02393 Purpose: Add a colour component value to a colour definition string. This is used 02394 to build up the entries in the EPS colour table. It also centralises the 02395 syntax of inherited components. 02396 Errors: - 02397 SeeAlso: ColourListComponent::SaveColourAndChildren 02398 02399 ********************************************************************************************/ 02400 02401 void ColourListComponent::AddComponentValue( PTSTR ColDef, PCTSTR Format, 02402 double ComponentValue, BOOL Inherited) 02403 { 02404 // Construct the colour component value 02405 TCHAR CompVal[20]; 02406 02407 // If this is a linked colour, and this component is inherited, then just add a '-'. 02408 if (Inherited) 02409 { 02410 camStrcpy( CompVal, _T("-") ); 02411 } 02412 else 02413 { 02414 // We have to output the component.... 02415 camSnprintf( CompVal, 20, const_cast<TCHAR *>(Format), ComponentValue ); 02416 } 02417 02418 // Add the value onto the end of the string 02419 camStrcat( ColDef, _T(" ") ); 02420 camStrcat( ColDef, CompVal ); 02421 } 02422 02423 02424 02425 /******************************************************************************************** 02426 02427 > BOOL ColourListComponent::ColourOrChildIsShade(IndexedColour *pCol) 02428 02429 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 02430 Created: 7/9/95 02431 Inputs: pCol - The (root) colour to check 02432 02433 Returns: TRUE if this colour or a descendant is a Shade colour 02434 02435 Purpose: To determine if a colour is a Shade or has descendants which are Shades. 02436 02437 ********************************************************************************************/ 02438 02439 BOOL ColourListComponent::ColourOrChildIsShade(IndexedColour *pCol) 02440 { 02441 // Check if this colour exists 02442 if (pCol->IsDeleted()) 02443 return(FALSE); 02444 02445 // Check if this colour is a shade 02446 if (pCol->GetType() == COLOURTYPE_TINT && pCol->TintIsShade()) 02447 return(TRUE); 02448 02449 // If this has no children, then no point in scanning further 02450 if (!pCol->HasLinkedChildren()) 02451 return(FALSE); 02452 02453 02454 // Ask all the named colours that are immediate children of this colour 02455 IndexedColour *pChild = (IndexedColour *) pIndexedColours->GetHead(); 02456 02457 while (pChild != NULL) 02458 { 02459 if (!pChild->IsDeleted() && pChild->FindLinkedParent() == pCol) 02460 { 02461 // Found a child - recurse on it 02462 if (ColourOrChildIsShade(pChild)) 02463 return(TRUE); 02464 } 02465 02466 // Try the next colour 02467 pChild = (IndexedColour *) pIndexedColours->GetNext(pChild); 02468 } 02469 02470 // Get all the unnamed colours that are immediate children of this colour 02471 List *pUnnamedList = pIndexedColours->GetUnnamedColours(); 02472 pChild = (IndexedColour *) pUnnamedList->GetHead(); 02473 02474 while (pChild != NULL) 02475 { 02476 if (!pChild->IsDeleted() && pChild->FindLinkedParent() == pCol) 02477 { 02478 // Found a child - recurse on it 02479 if (ColourOrChildIsShade(pChild)) 02480 return(TRUE); 02481 } 02482 02483 // Try the next colour 02484 pChild = (IndexedColour *) pUnnamedList->GetNext(pChild); 02485 } 02486 02487 return(FALSE); 02488 } 02489 02490 02491 02492 // Simple macro to make the code in SaveColourAndChildren() a bit neater. 02493 #define LINKED(ID) (Linked && pCol->InheritsComponent((ID))) 02494 02495 /******************************************************************************************** 02496 02497 > BOOL ColourListComponent::SaveColourAndChildren(IndexedColour *pCol, EPSExportDC *pDC, 02498 BOOL CamelotEPS, INT32 NestingLevel = 0, 02499 BOOL SaveShades = FALSE) 02500 02501 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02502 Created: 05/12/94 02503 Inputs: pCol - The (root) colour to save 02504 pDC - The EPS export DC to save to 02505 CamelotEPS - TRUE if exporting Camelot EPS 02506 NestingLevel- The nesting level of tint/shade/link colours. Used in 02507 recursion - external callers should pass in 0 02508 SaveShades - Indicates if Shades and their children should be saved. Used 02509 in version 1.1 CamelotEPS to save out 2 colour tables, the 02510 second of which includes the shades. (In this way, we could 02511 retain load-compatability with older versions) 02512 Outputs: - 02513 Returns: - 02514 Purpose: Save out an indexed colour to an EPS file, and all the colours that rely 02515 on it, i.e. any other indexed colours which are tints of, or links to, this 02516 colour. 02517 Errors: - 02518 SeeAlso: - 02519 02520 ********************************************************************************************/ 02521 02522 BOOL ColourListComponent::SaveColourAndChildren(IndexedColour *pCol, EPSExportDC *pDC, 02523 BOOL CamelotEPS, INT32 NestingLevel, 02524 BOOL SaveShades) 02525 { 02526 #ifdef DO_EXPORT 02527 02528 // (Jason 27/10/95) If the colour is unnamed and it's not actually used anywhere, 02529 // don't bother saving it. This optimises out temporary locals that are no longer 02530 // needed. At the worst, if something goes horribly wrong, this just means that 02531 // some locals might turn up as CMYK definitions on reloading, but this shouldn't 02532 // cause any problems unless something deeply scary has happened to the colour system. 02533 if (!pCol->IsNamed() && !pCol->IsInUse()) 02534 return(TRUE); 02535 02536 // Check for silly recursion errors [not that you can get circular references with 02537 // the amazingly strict and careful checking done by the IndexedColour class - JW ;-] 02538 ERROR2IF(NestingLevel > 200, FALSE, "Rampant linked colour nesting detected!"); 02539 02540 // First, save out this indexed colour. 02541 ColourModel Model = pCol->GetColourModel(); 02542 02543 // Buffer to build up colour defs in. 02544 TCHAR ColDef[256]; 02545 camStrcpy(ColDef, _T("%%+")); 02546 02547 // Buffer for temporary strings 02548 TCHAR TmpBuf[256]; 02549 02550 // Get information on the colour - ask for its full identifier rather than just the name, 02551 // so we get a unique id for unnamed colours rather than just "Local colour" 02552 ColourGeneric GenCol; 02553 IndexedColourType ColType = pCol->GetType(); 02554 pCol->GetSourceColour(&GenCol); 02555 TCHAR *ColName = (TCHAR *) (*(pCol->GetName(TRUE))); 02556 02557 // Special check - Shades are only properly preserved in CamelotEPS. In all others, they 02558 // are treated as unlinked, normal colours, so that they will be read happily. 02559 if (!CamelotEPS && ColType == COLOURTYPE_TINT && pCol->TintIsShade()) 02560 { 02561 ColType = COLOURTYPE_NORMAL; 02562 } 02563 02564 // If we shouldn't be saving shade colours or their children on this pass, then don't 02565 // do anything for them this time. 02566 if (!SaveShades && ColType == COLOURTYPE_TINT && pCol->TintIsShade()) 02567 return(TRUE); 02568 02569 // If saving shades, then don't bother with non-shade colours which have no children, as 02570 // they do not need to be output. 02571 if (SaveShades && (ColType != COLOURTYPE_TINT || !pCol->TintIsShade()) && !pCol->HasLinkedChildren()) 02572 return(TRUE); 02573 02574 // Check for tints 02575 if (ColType == COLOURTYPE_TINT) 02576 { 02577 FIXED24 TintVal(0.0); 02578 FIXED24 ShadeVal(0.0); 02579 02580 // Add tint identifier to colour definition 02581 if (pCol->TintIsShade()) 02582 { 02583 camStrcat(ColDef, _T("d")); // Is a shaDe 02584 TintVal = pCol->GetShadeValueY(); // Note that it is written out as "Y X" 02585 ShadeVal = pCol->GetShadeValueX(); // to make backward compatability easier 02586 } 02587 else 02588 { 02589 camStrcat(ColDef, _T("t")); // Is a Tint 02590 TintVal = pCol->GetTintValue(); 02591 } 02592 02593 ERROR3IF(NestingLevel < 1, "Bad nesting when saving a tint/shade colour"); 02594 02595 // Get tint/shade value as an integer in range 0 - 100. 02596 INT32 Tint = (INT32) ((TintVal.MakeDouble() * 100.0) + ((TintVal < 0) ? -0.5 : 0.5)); 02597 INT32 Shade = (INT32) ((ShadeVal.MakeDouble() * 100.0) + ((ShadeVal < 0) ? -0.5 : 0.5)); 02598 02599 if (NestingLevel > 1) 02600 { 02601 // Write out the nesting level 02602 camSnprintf(TmpBuf, 256, _T(" %d"), NestingLevel); 02603 camStrcat(ColDef, TmpBuf); 02604 } 02605 02606 // Add the colour name and tint value 02607 if (pCol->TintIsShade()) 02608 camSnprintf(TmpBuf, 256, _T(" (%s) %d %d"), ColName, Tint, Shade); 02609 else 02610 camSnprintf(TmpBuf, 256, _T(" (%s) %d"), ColName, Tint); 02611 camStrcat(ColDef, TmpBuf); 02612 } 02613 else 02614 { 02615 // Is this a linked colour? 02616 BOOL Linked = (ColType == COLOURTYPE_LINKED); 02617 02618 // We only do linked colours in CamelotEPS 02619 Linked = Linked && CamelotEPS; 02620 02621 02622 if (Linked) 02623 { 02624 // Mark this as a linked colour 02625 camStrcat(ColDef, _T("l")); 02626 } 02627 else if (CamelotEPS && (ColType == COLOURTYPE_SPOT)) 02628 { 02629 // Mark this as a spot colour 02630 camStrcat(ColDef, _T("s")); 02631 } 02632 02633 // Save out colour model, nesting level and colour name 02634 switch (Model) 02635 { 02636 case COLOURMODEL_RGBT: 02637 camStrcat(ColDef, _T("r")); 02638 break; 02639 02640 case COLOURMODEL_HSVT: 02641 camStrcat(ColDef, _T("h")); 02642 break; 02643 02644 case COLOURMODEL_CMYK: 02645 camStrcat(ColDef, _T("c")); 02646 break; 02647 02648 case COLOURMODEL_GREYT: 02649 // Special case - only Camelot can handle greyscales - ArtWorks can't. 02650 if (CamelotEPS) 02651 camStrcat(ColDef, _T("g")); 02652 else 02653 camStrcat(ColDef, _T("r")); 02654 break; 02655 02656 default: 02657 break; 02658 } 02659 02660 // Add nesting level, if needed 02661 if (NestingLevel > 1) 02662 { 02663 // Write out the nesting level 02664 camSnprintf(TmpBuf, 256, _T(" %d"), NestingLevel); 02665 camStrcat(ColDef, TmpBuf); 02666 } 02667 02668 // Add colour name 02669 camStrcat(ColDef , _T(" (")); 02670 camStrcat(ColDef, ColName); 02671 camStrcat(ColDef, _T(")")); 02672 02673 // Now write out the colour component values... 02674 switch (Model) 02675 { 02676 case COLOURMODEL_RGBT: 02677 // Now add the RGB components. 02678 ColourRGBT *pRGBT; 02679 pRGBT = (ColourRGBT *) &GenCol; 02680 02681 AddComponentValue(ColDef, _T("%.3f"), pRGBT->Red.MakeDouble(), LINKED(1)); 02682 AddComponentValue(ColDef, _T("%.3f"), pRGBT->Green.MakeDouble(), LINKED(2)); 02683 AddComponentValue(ColDef, _T("%.3f"), pRGBT->Blue.MakeDouble(), LINKED(3)); 02684 break; 02685 02686 case COLOURMODEL_HSVT: 02687 // Now add the HSV components. 02688 ColourHSVT *pHSVT; 02689 pHSVT = (ColourHSVT *) &GenCol; 02690 02691 AddComponentValue(ColDef, _T("%.1f"), pHSVT->Hue.MakeDouble() * 360.0, LINKED(1)); 02692 AddComponentValue(ColDef, _T("%.1f"), pHSVT->Saturation.MakeDouble() * 100.0, LINKED(2)); 02693 AddComponentValue(ColDef, _T("%.1f"), pHSVT->Value.MakeDouble() * 100.0, LINKED(3)); 02694 break; 02695 02696 case COLOURMODEL_CMYK: 02697 // Now add the CMYK components. 02698 ColourCMYK *pCMYK; 02699 pCMYK = (ColourCMYK *) &GenCol; 02700 02701 AddComponentValue(ColDef, _T("%.3f"), pCMYK->Cyan.MakeDouble(), LINKED(1)); 02702 AddComponentValue(ColDef, _T("%.3f"), pCMYK->Magenta.MakeDouble(), LINKED(2)); 02703 AddComponentValue(ColDef, _T("%.3f"), pCMYK->Yellow.MakeDouble(), LINKED(3)); 02704 AddComponentValue(ColDef, _T("%.3f"), pCMYK->Key.MakeDouble(), LINKED(4)); 02705 break; 02706 02707 case COLOURMODEL_GREYT: 02708 // ArtWorks doesn't have explicit greyscale colours - use RGB model. 02709 ColourGreyT *pGreyT; 02710 pGreyT = (ColourGreyT *) &GenCol; 02711 double Intensity; 02712 Intensity = pGreyT->Intensity.MakeDouble(); 02713 if (CamelotEPS) 02714 { 02715 // General greyscale format...just add the intensity component 02716 AddComponentValue(ColDef, _T("%.3f"), Intensity, LINKED(1)); 02717 } 02718 else 02719 { 02720 // Fake a greyscale for ArtWorks with an RGB colour 02721 // where R = G = B. 02722 for (INT32 i = 1; i <= 3; i++) 02723 { 02724 AddComponentValue(ColDef, _T("%.3f"), Intensity, FALSE); 02725 } 02726 } 02727 break; 02728 02729 default: 02730 ERROR3("Unknown colour type found in EPS export!"); 02731 break; 02732 } 02733 } 02734 02735 // Output colour definition to the EPS file 02736 pDC->OutputToken(ColDef); 02737 pDC->OutputNewLine(); 02738 02739 02740 // (Jason 27/10/95) If it doesn't have linked children, don't recurse. 02741 // On large files, this saves a *lot* of time (O(n*n) becomes O(n)), because 02742 // (a) linked colours are only usually used sporadically, and (b) local colours, 02743 // which make up the bulk of saved colours, cannot have any children. 02744 if (!pCol->HasLinkedChildren()) 02745 return(TRUE); 02746 02747 02748 // ---------- recurse ---------- 02749 02750 02751 // Now recurse to save out any children of this colour (links or tints)... 02752 02753 // Get all the named colours that are immediate children of this colour 02754 IndexedColour *pChild = (IndexedColour *) pIndexedColours->GetHead(); 02755 02756 while (pChild != NULL) 02757 { 02758 if (!pChild->IsDeleted() && pChild->FindLinkedParent() == pCol) 02759 { 02760 // Found a child - save out via recursion so we save all its descendants in the 02761 // right order... 02762 SaveColourAndChildren(pChild, pDC, CamelotEPS, NestingLevel + 1, SaveShades); 02763 } 02764 02765 // Try the next colour 02766 pChild = (IndexedColour *) pIndexedColours->GetNext(pChild); 02767 } 02768 02769 // Get all the unnamed colours that are immediate children of this colour 02770 List *pUnnamedList = pIndexedColours->GetUnnamedColours(); 02771 02772 pChild = (IndexedColour *) pUnnamedList->GetHead(); 02773 02774 while (pChild != NULL) 02775 { 02776 if (!pChild->IsDeleted() && pChild->FindLinkedParent() == pCol) 02777 { 02778 // Found a child - save out via recursion so we save all its descendants in the 02779 // right order... 02780 SaveColourAndChildren(pChild, pDC, CamelotEPS, NestingLevel + 1, SaveShades); 02781 } 02782 02783 // Try the next colour 02784 pChild = (IndexedColour *) pUnnamedList->GetNext(pChild); 02785 } 02786 #endif 02787 return TRUE; 02788 } 02789 02790 02791 /******************************************************************************************** 02792 02793 > ProcessEPSResult ColourListComponent::ProcessEPSComment(EPSFilter *pFilter, 02794 const char *pComment) 02795 02796 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02797 Created: 02/08/94 02798 Inputs: pFilter - the EPS filter that is being used to import a file. 02799 pComment - pointer to the comment to process. 02800 Returns: EPSCommentUnknown - This EPS comment is not recognised by the document 02801 component. 02802 EPSCommentError - This EPS comment was recognised by this document 02803 component, but it contained an error. 02804 EPSCommentOK - This EPS comment was recognised as a legal comment by 02805 this document component, and was processed 02806 successfully. 02807 Purpose: Process an EPS comment - if this is a colour table comment, this component 02808 will claim it and try to decode it. 02809 02810 Notes: IMPORTANT 02811 There is a new colour field (which should only be put in a JWColourTable 02812 in CamelotEPS) which starts a comment line with "%%+x". The remainder of the 02813 line is undefined, but is treated as a valid line. This will make it possible 02814 to add data to the colour list in future without losing backward compatability 02815 or having to add yet another colour table type! 02816 If you use this, make sure your code happily *ignores* unknown x extensions. 02817 02818 Errors: Badly formed EPS comment. 02819 SeeAlso: DocComponent::ProcessEPSComment 02820 02821 ********************************************************************************************/ 02822 02823 ProcessEPSResult ColourListComponent::ProcessEPSComment(EPSFilter *pFilter, 02824 PCTSTR pComment) 02825 { 02826 if (pFilter->IsKindOf(CC_RUNTIME_CLASS(ArtWorksEPSFilter))) 02827 { 02828 // Is it a Camelot specific filter? 02829 BOOL CamelotEPS = pFilter->IsKindOf(CC_RUNTIME_CLASS(CamelotEPSFilter)); 02830 02831 // ArtWorks EPS (or derivative) 02832 if (camStrncmp(pComment, _T("%%AWColourTable"), 15) == 0) 02833 { 02834 // Found a colour table 02835 return EPSCommentOK; 02836 } 02837 else if (camStrncmp(pComment, _T("%%JWColourTable"), 15) == 0) 02838 { 02839 // Found a version 1.1 extended colour table 02840 return EPSCommentOK; 02841 } 02842 else if (camStrncmp(pComment, _T("%%+"), 3) == 0) 02843 { 02844 // Found a colour - add it to the colour list for the document. 02845 02846 // Take a copy of this comment 02847 TCHAR Comment[256]; 02848 camStrcpy(Comment, pComment); 02849 02850 // Find out the colour model (c, h, r, or t) 02851 INT32 i = 3; 02852 TCHAR ColModel = Comment[i++]; 02853 02854 // Check for special types (NB a colour cannot be both a spot colour and 02855 // a linked colour). 02856 NewColourInfo ColourInfo; 02857 BOOL Linked = FALSE; 02858 02859 // Is it a spot colour? 02860 if (ColModel == 's') 02861 { 02862 ColourInfo.Type = COLOURTYPE_SPOT; 02863 ColModel = Comment[i++]; 02864 } 02865 else if (ColModel == 'l') 02866 { 02867 // It's a link, then find out the colour model of the linked colour. 02868 Linked = TRUE; 02869 ColourInfo.Type = COLOURTYPE_LINKED; 02870 ColModel = Comment[i++]; 02871 } 02872 02873 // If a tint/shade or link, find the nesting level, if any 02874 INT32 ColourNesting = 0; 02875 if ((ColModel == 't') || (ColModel == 'd') || Linked) 02876 { 02877 // Skip until we find a digit, a '(' or a terminator 02878 while (!isdigit(Comment[i]) && (Comment[i] != '(') && (Comment[i] != 0)) 02879 i++; 02880 02881 // Is there a nesting level? 02882 if (isdigit(Comment[i])) 02883 { 02884 // Yes - extract it and skip past it. 02885 ColourNesting = camAtol(Comment+i); 02886 02887 while (isdigit(Comment[i])) 02888 i++; 02889 } 02890 else 02891 { 02892 // Must be level 1 02893 ColourNesting = 1; 02894 } 02895 } 02896 02897 // Do we need to alter the link context? 02898 if (ColourNesting == 0) 02899 { 02900 // Normal colour 02901 pNewColours->RestoreContextTo(0); 02902 } 02903 else if (ColourNesting <= LinkNesting) 02904 { 02905 // Falling back to a previous nesting level - restore context to one 02906 // less than the nesting of this link/tint 02907 // (because we want to link/tint the colour one level below this one 02908 // in the nesting). 02909 LinkNesting = ColourNesting - 1; 02910 pNewColours->RestoreContextTo(LinkNesting); 02911 } 02912 02913 // Find the colour name 02914 while ((Comment[i] != '(') && (Comment[i] != 0)) 02915 i++; 02916 02917 // Got it - copy it out of the string (skip the opening parenthesis) 02918 TCHAR ColName[128]; 02919 i = ExtractString(Comment, i+1, ColName); 02920 String_64 ColNameS = ColName; 02921 02922 // Copied the name - skip any whitespace 02923 while (((Comment[i] == ' ') || (Comment[i] == '\t')) && 02924 (Comment[i] != 0)) 02925 { 02926 i++; 02927 } 02928 02929 // Check for the overprint flag 02930 if (Comment[i] == 'o') 02931 { 02932 // Ignore it for now... 02933 i++; 02934 while (((Comment[i] == ' ') || (Comment[i] == '\t')) && 02935 (Comment[i] != 0)) 02936 { 02937 i++; 02938 } 02939 } 02940 02941 02942 // Validate the colour model for this filter. 02943 if ((ColModel != 'r') && (ColModel != 'c') && // Rgb, Cmyk 02944 (ColModel != 'h') && (ColModel != 't')) // Hsv, Tint 02945 { 02946 // Reject outright if this is an ArtWorks file 02947 if (!CamelotEPS) 02948 { 02949 pFilter->HandleEPSError(); 02950 return EPSCommentSyntaxError; 02951 } 02952 } 02953 02954 // Do we need to save the context before adding this colour? 02955 if (Linked || (ColModel == 't') || (ColModel == 'd')) 02956 { 02957 pNewColours->SaveContext(); 02958 LinkNesting++; 02959 } 02960 02961 // Read the colour components according to the colour model. 02962 switch (ColModel) 02963 { 02964 case 'r': 02965 case 'R': 02966 { 02967 ColourRGBT NewRGBT; 02968 ReadEPS_RGB(&NewRGBT, Comment + i, &ColourInfo); 02969 if (!pNewColours->AddColour(&ColNameS, &NewRGBT, &ColourInfo)) 02970 return EPSCommentSystemError; 02971 } 02972 break; 02973 02974 case 'c': 02975 { 02976 ColourCMYK NewCMYK; 02977 ReadEPS_CMYK(&NewCMYK, Comment + i, &ColourInfo); 02978 if (!pNewColours->AddColour(&ColNameS, &NewCMYK, &ColourInfo)) 02979 return EPSCommentSystemError; 02980 } 02981 break; 02982 02983 case 'h': 02984 case 'H': 02985 { 02986 ColourHSVT NewHSVT; 02987 ReadEPS_HSV(&NewHSVT, Comment + i, &ColourInfo); 02988 if (!pNewColours->AddColour(&ColNameS, &NewHSVT, &ColourInfo)) 02989 return EPSCommentSystemError; 02990 } 02991 break; 02992 02993 case 't': // Tint 02994 { 02995 UINT32 Tint = ReadEPS_Tint(Comment + i); 02996 02997 if (!pNewColours->AddTint(&ColNameS, Tint)) 02998 return EPSCommentSystemError; 02999 } 03000 break; 03001 03002 case 'd': // Shade - saved in same format as tint, so re-use ReadEPS_Tint method 03003 { 03004 INT32 ShadeX; 03005 INT32 ShadeY; 03006 ReadEPS_Shade(Comment + i, &ShadeX, &ShadeY); 03007 03008 if (!pNewColours->AddShade(&ColNameS, ShadeX, ShadeY)) 03009 return EPSCommentSystemError; 03010 } 03011 break; 03012 03013 case 'G': 03014 case 'g': 03015 { 03016 ColourGreyT NewGreyT; 03017 ReadEPS_Grey(&NewGreyT, Comment + i, &ColourInfo); 03018 03019 // Bodge for version 2 03020 // We really want black to be defined as CMYK so that it colour separates 03021 // more cleanly (and also merges on import better with new docs). Prior to v2, 03022 // the default black was defined as a greyscale so we sit on it during import 03023 // and turn it into a CMYK colour. 03024 if (NewGreyT.Intensity == 0 && ColNameS == String_64(TEXT("Black"))) 03025 { 03026 ColourCMYK Bodge; 03027 Bodge.Cyan = Bodge.Magenta = Bodge.Yellow = 0; 03028 Bodge.Key = 1.0; 03029 03030 if (!pNewColours->AddColour(&ColNameS, &Bodge, &ColourInfo)) 03031 return EPSCommentSystemError; 03032 } 03033 else 03034 { 03035 if (!pNewColours->AddColour(&ColNameS, &NewGreyT, &ColourInfo)) 03036 return EPSCommentSystemError; 03037 } 03038 } 03039 break; 03040 } 03041 03042 // Parsed this colour ok. 03043 return EPSCommentOK; 03044 } 03045 } 03046 // Ignore all other comments 03047 return EPSCommentUnknown; 03048 } 03049 03050 03051 /******************************************************************************************** 03052 03053 > INT32 ColourListComponent::ExtractString(const char *Comment, INT32 Start, char *String) 03054 03055 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 03056 Created: 07/08/94 03057 Inputs: Comment - pointer to the comment. 03058 Start - offset into Comment of the first character of the string (not 03059 including the first opening parenthesis). 03060 Outputs: String - the PostScript string. 03061 Returns: The offset to the first character after the closing parenthesis of 03062 the string. 03063 Purpose: Copy a PostScript string out of the given EPS comment. It handles 03064 nested parentheses - e.g. a string like (Hello (there)) will be 03065 correctly returned in String as "Hello (there)". 03066 The end of the comment is also taken as terminating the string. 03067 03068 ********************************************************************************************/ 03069 03070 INT32 ColourListComponent::ExtractString( PCTSTR Comment, INT32 Start, PTSTR String) 03071 { 03072 // INT32 i = Start; 03073 // INT32 j = 0; 03074 // INT32 StringNesting = 1; 03075 03076 // Look for the last closing Parenthesis in this string... 03077 const TCHAR *End = camStrrchr(Comment, ')'); 03078 03079 if ((End == NULL) || (End < (Comment + Start))) 03080 { 03081 // Something's gone wrong - don't extract string and put a warning where the colour name 03082 // should be. 03083 camStrcpy( String, _T("Colour Import Error") ); 03084 return Start; 03085 } 03086 03087 // Copy the colour name from the comment into the string provided, and NULL 03088 // terminate it. 03089 INT32 NameLength = End - Comment; 03090 NameLength -= Start; 03091 03092 camStrncpy( String, Comment + Start, NameLength ); 03093 String[NameLength] = 0; 03094 03095 // Return the next character position after the string's closing parenthesis. 03096 return Start + NameLength + 1; 03097 } 03098 03099 /******************************************************************************************** 03100 03101 > void ColourListComponent::ReadEPS_RGB(ColourRGBT *pCol, char *pComment, 03102 NewColourInfo *pColourInfo) 03103 03104 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 03105 Created: 03/08/94 03106 Inputs: pCol - the colour to initialise from the comment. 03107 pComment - pointer to the comment fields to use. 03108 pColourInfo - if NULL, then this is not a linked colour 03109 if non-NULL, then this is a linked colour, and the fields 03110 should be filled in according to the inheritance flags 03111 found in the colour definition. 03112 Purpose: Read the RGB components from an ArtWorks EPS colour table comment, and 03113 initialise an indexed colour object using these values. 03114 The comment passed in is expected to be a pointer to the character just 03115 after the colour name/overprint flag, i.e. the start of the colour 03116 description. Leading white space is permissible. 03117 SeeAlso: ColourListComponent::ReadEPS_CMYK; ColourListComponent::ReadEPS_HSV; 03118 ColourListComponent::ReadEPS_Tint 03119 03120 ********************************************************************************************/ 03121 03122 void ColourListComponent::ReadEPS_RGB( ColourRGBT *pCol, PTSTR pComment, 03123 NewColourInfo *pColourInfo ) 03124 { 03125 BOOL Linked = (pColourInfo != NULL) && (pColourInfo->Type == COLOURTYPE_LINKED); 03126 03127 PTSTR pszTokMark = NULL ; 03128 PTSTR Value = camStrtok(pComment, _T(" \t"), &pszTokMark); 03129 if (Value != NULL) 03130 { 03131 if (Linked && (camStrcmp(Value, _T("-") ) == 0)) 03132 pColourInfo->Inherits[0] = TRUE; 03133 else 03134 pCol->Red = camStrtof( Value, &pszTokMark ); 03135 } 03136 03137 Value = camStrtok( NULL, _T(" \t"), &pszTokMark ); 03138 if (Value != NULL) 03139 { 03140 if (Linked && (camStrcmp(Value, _T("-") ) == 0)) 03141 pColourInfo->Inherits[1] = TRUE; 03142 else 03143 pCol->Green = camStrtof( Value, &pszTokMark ); 03144 } 03145 03146 Value = camStrtok( NULL, _T(" \t"), &pszTokMark ); 03147 if (Value != NULL) 03148 { 03149 if (Linked && (camStrcmp(Value, _T("-") ) == 0)) 03150 pColourInfo->Inherits[2] = TRUE; 03151 else 03152 pCol->Blue = camStrtof( Value, &pszTokMark ); 03153 } 03154 03155 // No transparency 03156 pCol->Transparent = 0.0; 03157 } 03158 03159 /******************************************************************************************** 03160 03161 > void ColourListComponent::ReadEPS_CMYK(ColourCMYK *pCol, char *pComment, 03162 NewColourInfo *pColourInfo) 03163 03164 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 03165 Created: 03/08/94 03166 Inputs: pCol - the colour to initialise from the comment. 03167 pComment - pointer to the comment fields to use. 03168 Purpose: Read the CMYK components from an ArtWorks EPS colour table comment, and 03169 initialise an indexed colour object using these values. 03170 The comment passed in is expected to be a pointer to the character just 03171 after the colour name/overprint flag, i.e. the start of the colour 03172 description. Leading white space is permissible. 03173 SeeAlso: ColourListComponent::ReadEPS_RGB; ColourListComponent::ReadEPS_HSV; 03174 ColourListComponent::ReadEPS_Tint 03175 03176 ********************************************************************************************/ 03177 03178 void ColourListComponent::ReadEPS_CMYK(ColourCMYK *pCol, PTSTR pComment, 03179 NewColourInfo *pColourInfo) 03180 { 03181 BOOL Linked = (pColourInfo != NULL) && (pColourInfo->Type == COLOURTYPE_LINKED); 03182 03183 TCHAR *State = NULL; 03184 TCHAR *Value = camStrtok(pComment, _T(" \t"), &State); 03185 if (Value != NULL) 03186 { 03187 if (Linked && (camStrcmp(Value, _T("-")) == 0)) 03188 pColourInfo->Inherits[0] = TRUE; 03189 else 03190 pCol->Cyan = camAtof(Value); 03191 } 03192 03193 Value = camStrtok(NULL, _T(" \t"), &State); 03194 if (Value != NULL) 03195 { 03196 if (Linked && (camStrcmp(Value, _T("-")) == 0)) 03197 pColourInfo->Inherits[1] = TRUE; 03198 else 03199 pCol->Magenta = camAtof(Value); 03200 } 03201 03202 Value = camStrtok(NULL, _T(" \t"), &State); 03203 if (Value != NULL) 03204 { 03205 if (Linked && (camStrcmp(Value, _T("-")) == 0)) 03206 pColourInfo->Inherits[2] = TRUE; 03207 else 03208 pCol->Yellow = camAtof(Value); 03209 } 03210 03211 Value = camStrtok(NULL, _T(" \t"), &State); 03212 if (Value != NULL) 03213 { 03214 if (Linked && (camStrcmp(Value, _T("-")) == 0)) 03215 pColourInfo->Inherits[3] = TRUE; 03216 else 03217 pCol->Key = camAtof(Value); 03218 } 03219 03220 } 03221 03222 /******************************************************************************************** 03223 03224 > void ColourListComponent::ReadEPS_HSV(ColourHSVT *pCol, char *pComment, 03225 NewColourInfo *pColourInfo) 03226 03227 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 03228 Created: 03/08/94 03229 Inputs: pCol - the colour to initialise from the comment. 03230 pComment - pointer to the comment fields to use. 03231 Purpose: Read the HSV components from an ArtWorks EPS colour table comment, and 03232 initialise an indexed colour object using these values. 03233 The comment passed in is expected to be a pointer to the character just 03234 after the colour name/overprint flag, i.e. the start of the colour 03235 description. Leading white space is permissible. 03236 SeeAlso: ColourListComponent::ReadEPS_RGB; ColourListComponent::ReadEPS_CMYK; 03237 ColourListComponent::ReadEPS_Tint 03238 03239 ********************************************************************************************/ 03240 03241 void ColourListComponent::ReadEPS_HSV(ColourHSVT *pCol, PTSTR pComment, 03242 NewColourInfo *pColourInfo) 03243 { 03244 BOOL Linked = (pColourInfo != NULL) && (pColourInfo->Type == COLOURTYPE_LINKED); 03245 03246 TCHAR *State = NULL; 03247 TCHAR *Value = camStrtok(pComment, _T(" \t"), &State); 03248 if (Value != NULL) 03249 { 03250 if (Linked && (camStrcmp(Value, _T("-")) == 0)) 03251 pColourInfo->Inherits[0] = TRUE; 03252 else 03253 pCol->Hue = camAtof(Value) / 360.0; 03254 } 03255 03256 Value = camStrtok(NULL, _T(" \t"), &State); 03257 if (Value != NULL) 03258 { 03259 if (Linked && (camStrcmp(Value, _T("-")) == 0)) 03260 pColourInfo->Inherits[1] = TRUE; 03261 else 03262 pCol->Saturation = camAtof(Value) / 100.0; 03263 } 03264 03265 Value = camStrtok(NULL, _T(" \t"), &State); 03266 if (Value != NULL) 03267 { 03268 if (Linked && (camStrcmp(Value, _T("-")) == 0)) 03269 pColourInfo->Inherits[2] = TRUE; 03270 else 03271 pCol->Value = camAtof(Value) / 100.0; 03272 } 03273 03274 // No transparency 03275 pCol->Transparent = 0.0; 03276 03277 } 03278 03279 /******************************************************************************************** 03280 03281 > void ColourListComponent::ReadEPS_Grey(ColourGreyT *pCol, char *pComment, 03282 NewColourInfo *pColourInfo) 03283 03284 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 03285 Created: 03/08/94 03286 Inputs: pCol - the colour to initialise from the comment. 03287 pComment - pointer to the comment fields to use. 03288 Purpose: Read the HSV components from an ArtWorks EPS colour table comment, and 03289 initialise an indexed colour object using these values. 03290 The comment passed in is expected to be a pointer to the character just 03291 after the colour name/overprint flag, i.e. the start of the colour 03292 description. Leading white space is permissible. 03293 SeeAlso: ColourListComponent::ReadEPS_RGB; ColourListComponent::ReadEPS_CMYK; 03294 ColourListComponent::ReadEPS_Tint 03295 03296 ********************************************************************************************/ 03297 03298 void ColourListComponent::ReadEPS_Grey(ColourGreyT *pCol, PTSTR pComment, 03299 NewColourInfo *pColourInfo) 03300 { 03301 BOOL Linked = (pColourInfo != NULL) && (pColourInfo->Type == COLOURTYPE_LINKED); 03302 03303 TCHAR * State=NULL; 03304 TCHAR *Value = camStrtok(pComment, _T(" \t"), &State); 03305 if (Value != NULL) 03306 { 03307 if (Linked && (camStrcmp(Value, _T("-")) == 0)) 03308 pColourInfo->Inherits[0] = TRUE; 03309 else 03310 pCol->Intensity = camAtof(Value); 03311 } 03312 03313 // Clear the reserved words to 0. 03314 pCol->Reserved1 = 0.0; 03315 pCol->Reserved2 = 0.0; 03316 03317 // No transparency 03318 pCol->Transparent = 0.0; 03319 } 03320 03321 /******************************************************************************************** 03322 03323 > void ColourListComponent::ReadEPS_Tint(char *pComment) 03324 03325 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 03326 Created: 07/08/94 03327 Inputs: pComment - pointer to the comment fields to use. 03328 Purpose: Read the tint value from an ArtWorks style tint colour definition comment. 03329 03330 (OR Read the shade value out of a CamelotEPS shade ("d") comment. Shades 03331 are stored in identical; format to tints) 03332 03333 SeeAlso: ColourListComponent::ReadEPS_RGB; ColourListComponent::ReadEPS_CMYK; 03334 ColourListComponent::ReadEPS_HSVT 03335 03336 ********************************************************************************************/ 03337 03338 UINT32 ColourListComponent::ReadEPS_Tint( PTSTR pComment ) 03339 { 03340 PTSTR pszTokMark = NULL; 03341 PTSTR Value = camStrtok( pComment, _T(" \t"), &pszTokMark ); 03342 INT32 Tint = 0; 03343 if (Value != NULL) 03344 { 03345 // Get the tint value 03346 Tint = camStrtol( Value, &pszTokMark, 10 ); 03347 if (Tint < 0) 03348 Tint = 0; 03349 } 03350 03351 return (UINT32) Tint; 03352 } 03353 03354 03355 03356 /******************************************************************************************** 03357 03358 > void ColourListComponent::ReadEPS_Shade(char *pComment, INT32 *ResultX, INT32 *ResultY) 03359 03360 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 03361 Created: 13/10/95 03362 Inputs: pComment - pointer to the comment fields to use. 03363 03364 Outputs: ResultX,ResultY - returned with the shade values 03365 03366 Purpose: Read the shade values from a Camelot shade colour definition comment. 03367 03368 (OR Read the shade value out of a CamelotEPS shade ("d") comment. Shades 03369 are stored in identical; format to tints) 03370 03371 Notes: Old style shades had only one relative value (Y). If this is missing, 03372 then an appropriate default is chosen such that it all still works. 03373 03374 SeeAlso: ColourListComponent::ReadEPS_RGB; ColourListComponent::ReadEPS_CMYK; 03375 ColourListComponent::ReadEPS_HSVT 03376 03377 ********************************************************************************************/ 03378 03379 void ColourListComponent::ReadEPS_Shade( PTSTR pComment, INT32 *ResultX, INT32 *ResultY) 03380 { 03381 PTSTR pszTokMark = NULL; 03382 PTSTR Value = camStrtok( pComment, _T(" \t"), &pszTokMark ); 03383 INT32 Val = 0; 03384 if( Value != NULL ) 03385 Val = camStrtol( Value, &pszTokMark, 10 ); 03386 03387 *ResultY = (INT32)Val; 03388 03389 Value = camStrtok( NULL, _T(" \t"), &pszTokMark ); 03390 if (Value != NULL) 03391 { 03392 Val = camStrtol( Value, &pszTokMark, 10 ); 03393 03394 TRACEUSER( "Jason", _T("Load new shade %ld %ld\n"), Val, (INT32)*ResultY); 03395 } 03396 else 03397 { 03398 // There is no second token - it must be in the old save format 03399 // The old value was a 0-100 shade-to-black, so to convert into the new 03400 // format we just negate it. Happy Happy Bodge Bodge. 03401 *ResultY = -(*ResultY); 03402 03403 // And set a sensible X value 03404 Val = 0; 03405 TRACEUSER( "Jason", _T("Load OLD shade %ld %ld\n"), Val, (INT32)*ResultY); 03406 } 03407 03408 *ResultX = (INT32)Val; 03409 } 03410 03411 03412 03413 03414 /******************************************************************************************** 03415 03416 > void ColourListComponent::EndOfEPSComment(EPSFilter *pFilter) 03417 03418 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 03419 Created: 02/08/94 03420 Inputs: pFilter - the EPS filter that is being used to import a file. 03421 Purpose: Informs the document component that the comment it has been decoding has 03422 now finished, and it should take whatever action required to act on 03423 the comment. 03424 SeeAlso: DocComponent::EndOfPESComment 03425 03426 ********************************************************************************************/ 03427 03428 void ColourListComponent::EndOfEPSComment(EPSFilter *pFilter) 03429 { 03430 // Do any cleanup we need to here after loading in a colour table... 03431 } 03432 03433 03434 03435 /******************************************************************************************** 03436 03437 > IndexedColour *ColourListComponent::FindNamedColour(const char *pName, 03438 DocColour *ColDef = NULL, 03439 UINT32 Tint = 100, 03440 BOOL Strict = FALSE) 03441 03442 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 03443 Created: 04/08/94 03444 Inputs: pName - the name of the colour to find. 03445 ColDef - the colour definition that it should match. 03446 Tint - the tint value applied to ColDef (NB it should already have been 03447 applied); 100 = same colour, 0 = white. 03448 03449 Strict - not used (obsolete) 03450 03451 Returns: Pointer to the indexed colour that corresponds to the file's named colour; 03452 or NULL if the colour could not be found (the caller should fall back to 03453 an immediate colour in this case). 03454 Purpose: Given the name of an imported named colour, return the relevant indexed 03455 colour. This allows attributes to be added when importing that use 03456 named colours. 03457 If ColDef is not NULL, then the Indexed colour found is checked to see 03458 if it agrees with the definition in ColDef - if not, then a new indexed 03459 colour is made, and a pointer to that is returned instead. This means we 03460 can cope with brain-damaged formats that have two or more named colours 03461 with the same format. It also makes it easy to cope with formats that 03462 use unnamed colours, as we just keep making colours called "Unnamed colour" 03463 or similar, and this function works it all out for us. 03464 03465 If the named colour is not found, and ColDef is not NULL, then again a 03466 new Indexed colour is created, and a pointer to it is returned. 03467 03468 NB. The name of the indexed colour returned MAY NOT have the same name as 03469 specified in pName, because it may clash with colours already in the 03470 document, and hence may have been mangled to make it unambiguous. 03471 03472 ********************************************************************************************/ 03473 03474 IndexedColour *ColourListComponent::FindNamedColour( PCTSTR pName, 03475 DocColour *ColDef, 03476 UINT32 Tint, 03477 BOOL Strict) 03478 { 03479 // Sanity check 03480 ENSURE(pNewColours != NULL, "Someone asked for an imported colour when there is no import going on!"); 03481 03482 if (pNewColours == NULL) 03483 return NULL; 03484 03485 // Special case for tinted colours - if the Tint is not 100%, then we must look for 03486 // or create a tinted version of the colour. 03487 if (Tint != 100) 03488 { 03489 // Create a new name to indicate this is tinted 03490 String_64 NewName(pName); 03491 03492 // Work out where to add the tint comment to the colour name. 03493 // Comment is of the form: " (xx% tint)", which is 11 characters long. 03494 INT32 Len = NewName.Length(); 03495 if (Len > 50) 03496 { 03497 // This should give us enough room for our tint comment 03498 Len = 50; 03499 } 03500 03501 TCHAR *pNewName = (TCHAR *)NewName; 03502 camSnprintf( pNewName + Len, 64 - Len, _T(" (%d%% tint)"), Tint ); 03503 03504 // Ok - we have a name - recurse so we can get a new colour (or use an existing 03505 // one created by this bit of code). 03506 return FindNamedColour(NewName, ColDef); 03507 } 03508 03509 // Find the colour in the imported colour table. 03510 IndexedColour *pColour; 03511 PColourCMYK CMYK; 03512 ColDef->GetCMYKValue(&CMYK); 03513 pColour = pNewColours->GetColour( pName, &CMYK ); 03514 03515 // Is there one that fits the bill? 03516 if (pColour != NULL) 03517 return pColour; 03518 03519 // Colour not found - can we make a new one? 03520 if (ColDef != NULL) 03521 { 03522 // Yes - add a new colour... 03523 03524 // Make a proper definition: 03525 ColourCMYK FullCMYK; 03526 FullCMYK.Cyan = FIXED24( ((double) CMYK.Cyan) / 255.0 ); 03527 FullCMYK.Magenta = FIXED24( ((double) CMYK.Magenta) / 255.0 ); 03528 FullCMYK.Yellow = FIXED24( ((double) CMYK.Yellow) / 255.0 ); 03529 FullCMYK.Key = FIXED24( ((double) CMYK.Key) / 255.0 ); 03530 03531 // And use it to add the colour 03532 String_64 NewName(pName); 03533 if (pNewColours->AddColour(&NewName, &FullCMYK)) 03534 { 03535 // It worked - return the colour created 03536 return pNewColours->GetColour( pName, &CMYK ); 03537 } 03538 else 03539 { 03540 // Failed to add a new colour 03541 return NULL; 03542 } 03543 } 03544 03545 // Can't make a new one without a colour definition - give up. 03546 return NULL; 03547 } 03548 03549 03550 /******************************************************************************************** 03551 03552 > BOOL ColourListComponent::FindIdenticalColour(IndexedColour *pColour, 03553 IndexedColour **pResult) 03554 03555 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 03556 Created: 07/08/94 03557 Inputs: pColour - the colour to match with. 03558 Outputs: pResult - pointer to the matching colour, if found; 03559 NULL otherwise. 03560 Returns: TRUE if a colour with this *name* was found in the document; 03561 FALSE if not. 03562 Purpose: Find out if there is already a colour exactly the same as the one passed 03563 in in the existing colour list. If so, return a pointer to it, otherwise 03564 return NULL. 03565 Also indicates whether or not a colour with this name already exists in the 03566 document, regardless of whether the colour data is the same. 03567 03568 ********************************************************************************************/ 03569 03570 BOOL ColourListComponent::FindIdenticalColour(IndexedColour *pColour, 03571 IndexedColour **pResult) 03572 { 03573 IndexedColour *pItem = (IndexedColour *) pIndexedColours->GetHead(); 03574 03575 BOOL FoundSameName = FALSE; 03576 03577 // Get the name/ID for this colour. TRUE is passed in so that unnamed colours return 03578 // their unique id string rather than "Local colour" 03579 String_64 *Name1 = pColour->GetName(TRUE); 03580 03581 while (pItem != NULL) 03582 { 03583 // Don't bother with deleted colours 03584 if (!pItem->IsDeleted()) 03585 { 03586 // WEBSTER - markn 14/2/97 03587 // Introduced WEBSTER_IGNORE_NAME_MATCHING so that Webster can ignore the name when 03588 // trying to find an identical colour 03589 03590 #if WEBSTER_IGNORE_NAME_MATCHING 03591 if (pIndexedColours != NULL) 03592 { 03593 if (!pItem->IsDifferent(*pColour, COL_ACCURACY)) 03594 { 03595 if (ColourSGallery::CanAddColourToGallery(pItem,pIndexedColours)) 03596 { 03597 *pResult = pItem; 03598 return TRUE; 03599 } 03600 } 03601 } 03602 #else 03603 // Compare names 03604 String_64 *Name2 = pItem->GetName(TRUE); 03605 if ((*Name1) == (*Name2)) 03606 { 03607 FoundSameName = TRUE; 03608 03609 // Name is the same - what about colour model + definition? 03610 if (!pItem->IsDifferent(*pColour, COL_ACCURACY)) 03611 { 03612 // The colour defn the same too - it's a match 03613 *pResult = pItem; 03614 return TRUE; 03615 } 03616 } 03617 #endif // WEBSTER_IGNORE_NAME_MATCHING 03618 } 03619 03620 // Try the next colour 03621 pItem = (IndexedColour *) pIndexedColours->GetNext(pItem); 03622 } 03623 03624 // No match - tell caller whether we found one with the same name. 03625 *pResult = NULL; 03626 return FoundSameName; 03627 } 03628 03629 03630 03631 03632 03633 03634 03635 03636 /******************************************************************************************** 03637 03638 > IndexedColour *ColourListComponent::ExactMatchExists(IndexedColour *SourceColour) 03639 03640 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 03641 Created: 18/10/94 03642 03643 Inputs: SourceColour - The colour to match 03644 Returns: A pointer to the IndexedColour in this document which exactly matches the 03645 given SourceColour, or NULL if no matching colour exists. 03646 03647 Purpose: Determine if a colour is already available in the paste-destination document 03648 This allows us to merge IndexedColours on the clipboard with those in the 03649 target document when doing a paste operation. 03650 03651 Notes: Exact match means: Another non-deleted colour which is not IsDifferent 03652 and which has an identical (sortof - see below) name string. 03653 03654 SPECIAL behaviour: The name string match now ignores digits on the end 03655 of the string. This is so that if you copy and paste "Red" such that the pasted 03656 colour is "Red 2", a subsequent paste will match the source "Red" and the 03657 destination "Red 2", rather than adding an identical "Red 3"! 03658 03659 Unnamed colours will never match. 03660 03661 SeeAlso: ColourListComponent::CopyColourAcross 03662 03663 ********************************************************************************************/ 03664 03665 IndexedColour *ColourListComponent::ExactMatchExists(IndexedColour *SourceColour) 03666 { 03667 // If it's an unnamed (local) colour, then we don't bother looking for a match 03668 if (!SourceColour->IsNamed()) 03669 return(NULL); 03670 03671 IndexedColour *pItem = (IndexedColour *) pIndexedColours->GetHead(); 03672 03673 // --- First check for any *exact* matches 03674 // Get the name/ID for this colour. TRUE is passed in so that unnamed colours return 03675 // their unique id string rather than "Local colour" (hmmm... we aren't checking 03676 // unnamed colours, so this is a bit of a moot point! ;-) 03677 String_64 SourceName = *(SourceColour->GetName(TRUE)); 03678 03679 while (pItem != NULL) 03680 { 03681 if (!pItem->IsDeleted() && !pItem->IsDifferent(*SourceColour)) // not different, so check name 03682 { 03683 if (SourceName.CompareTo(*pItem->GetName(TRUE)) == 0) // If has same name then... 03684 return(pItem); // Return it as match 03685 } 03686 03687 // Try the next colour 03688 pItem = (IndexedColour *) pIndexedColours->GetNext(pItem); 03689 } 03690 03691 03692 // --- Second, check for near-matches. 03693 // This is an exact match except it ignores the space and digits appended to a name 03694 // in the quest for a unique name. This means if the name "Red" is in use, and we paste 03695 // a different colour called "Red" it will add "Red 2" the first paste, but subsequent 03696 // pastes will match "Red 2" and simply merge with that colour (rather than adding Red 2 03697 // Red 3, Red 4, ect ad infinitum!) 03698 pItem = (IndexedColour *) pIndexedColours->GetHead(); 03699 while (pItem != NULL) 03700 { 03701 if (!pItem->IsDeleted() && !pItem->IsDifferent(*SourceColour)) // not different, so check name 03702 { 03703 // Get the string as a TCHAR array so we can actually do something with it (grr) 03704 TCHAR *StrPtr = (TCHAR *) (*pItem->GetName(TRUE)); 03705 03706 // Find the zero terminator 03707 INT32 Index = 0; 03708 while (StrPtr[Index] != (TCHAR)'\0') 03709 Index++; 03710 03711 // Now make index point at the last character 03712 Index -= 1; 03713 if (Index > 0) 03714 { 03715 if (UnicodeManager::IsDBCSLeadByte(StrPtr[Index-1])) 03716 Index -= 1; 03717 } 03718 03719 // Scan backwards, skipping all digits that we find 03720 INT32 EndIndex = Index; 03721 while (Index > 0) 03722 { 03723 if (!StringBase::IsNumeric(StrPtr[Index])) 03724 break; 03725 03726 Index -= 1; 03727 if (Index > 0) 03728 { 03729 if (UnicodeManager::IsDBCSLeadByte(StrPtr[Index-1])) 03730 Index -= 1; 03731 } 03732 } 03733 03734 // Now, if we found digits, scan back over this char if it is a space 03735 if (Index > 0 && Index < EndIndex && StrPtr[Index] == (TCHAR)' ') 03736 { 03737 // Rightoh. This looks like an auto-generated unique-name, so does the text 03738 // without the unique-ness number match our name? 03739 String_64 ToCheck; 03740 pItem->GetName(TRUE)->Left(&ToCheck, Index); 03741 03742 if (SourceName.CompareTo(ToCheck) == 0) 03743 return(pItem); // Yep - the names match 03744 } 03745 } 03746 03747 // Try the next colour 03748 pItem = (IndexedColour *) pIndexedColours->GetNext(pItem); 03749 } 03750 03751 // No match was found for this colour 03752 return(NULL); 03753 } 03754 03755 03756 03757 /******************************************************************************************** 03758 03759 > virtual BOOL ColourListComponent::StartComponentCopy(); 03760 03761 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 03762 Created: 10/9/94 03763 Inputs: - 03764 Outputs: - 03765 Returns: TRUE if it succeeded. FALSE if the copy must be aborted 03766 Purpose: This function gets called to prepare for a copy of indexed colours into 03767 the document. It sets up the various arrays and other thangs which the 03768 colour copy will need. 03769 Errors: ENSURE failure if called when a component copy is already under way. 03770 Errors will be reported if memory is unavailable 03771 SeeAlso: ColourListComponent::EndComponentCopy; 03772 ColourListComponent::AbortComponentCopy; 03773 ColourListComponent::CopyColourAcross 03774 03775 ********************************************************************************************/ 03776 03777 BOOL ColourListComponent::StartComponentCopy() 03778 { 03779 // Make sure the fn has not been called before 03780 if (SourceColours != NULL || DestColours != NULL) 03781 { 03782 ERROR3("StartComponentCopy already called"); 03783 return(TRUE); 03784 } 03785 03786 ColourTableSize = 64; // Start off with 64-entry table. This may grow if 03787 // we find we have a lot of colours to copy over 03788 03789 SourceColours = (IndexedColour **) CCMalloc(ColourTableSize * sizeof(IndexedColour *)); 03790 if (SourceColours == NULL) 03791 { 03792 InformError(); // Out of memory - inform the user 03793 return(FALSE); 03794 } 03795 03796 DestColours = (IndexedColour **) CCMalloc((ColourTableSize+1) * sizeof(IndexedColour *)); 03797 if (DestColours == NULL) 03798 { 03799 InformError(); // Out of memory - inform the user 03800 03801 CCFree(SourceColours); // And release our other memory - we can't use it now 03802 SourceColours = NULL; 03803 return(FALSE); 03804 } 03805 03806 MergeColours = (BOOL *) CCMalloc(ColourTableSize * sizeof(BOOL)); 03807 if (MergeColours == NULL) 03808 { 03809 InformError(); // Out of memory - inform the user 03810 03811 CCFree(SourceColours); // And release our other memory - we can't use it now 03812 CCFree(DestColours); 03813 SourceColours = DestColours = NULL; 03814 return(FALSE); 03815 } 03816 03817 // Initialise the arrays 03818 for (INT32 i = 0; i < ColourTableSize; i++) 03819 { 03820 SourceColours[i] = DestColours[i] = NULL; 03821 MergeColours[i] = FALSE; 03822 } 03823 03824 DestColours[ColourTableSize] = NULL; // And add a NULL terminator to dest. list 03825 03826 return(TRUE); 03827 } 03828 03829 03830 03831 /******************************************************************************************** 03832 03833 > virtual BOOL ColourListComponent::EndComponentCopy() 03834 03835 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 03836 Created: 10/9/94 03837 03838 Returns: TRUE if it succeeded 03839 Purpose: Will commit all changes made by doing the component copy, returning TRUE. 03840 Any new colours will be inserted as instructed by the InsertBefore parameter. 03841 If some colours will not be insterted because they were merged, then a report 03842 to this effect can be given if desired. 03843 03844 Notes: May be called multiple times - subsequent calls will be ignored 03845 03846 Overrides the base class method. Calls an internal variant on this method. 03847 03848 SeeAlso: ColourListComponent::StartComponentCopy; 03849 ColourListComponent::AbortComponentCopy; 03850 ColourListComponent::CopyColourAcross 03851 03852 ********************************************************************************************/ 03853 03854 BOOL ColourListComponent::EndComponentCopy() 03855 { 03856 return(ColourListComponent::EndComponentCopy(NULL, FALSE)); 03857 } 03858 03859 03860 03861 /******************************************************************************************** 03862 03863 > virtual BOOL ColourListComponent::EndComponentCopy(IndexedColour *InsertBefore, 03864 BOOL Report); 03865 03866 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 03867 Created: 10/9/94 03868 Inputs: InsertBefore - NULL to insert at the end of the colour list, else a pointer 03869 the the IndexedColour before which you wish to insert the colours. 03870 03871 Report - FALSE to do it quietly, TRUE if you'd like a report given if any colours 03872 were merged (used by the colour gallery when copying colours, as merged colours 03873 will fail to appear in the chunk of copied colours, which can confuse the user) 03874 03875 Returns: TRUE if it succeeded 03876 Purpose: Will commit all changes made by doing the component copy, returning TRUE. 03877 Any new colours will be inserted as instructed by the InsertBefore parameter. 03878 If some colours will not be insterted because they were merged, then a report 03879 to this effect can be given if desired. 03880 03881 Notes: May be called multiple times - subsequent calls will be ignored 03882 03883 WARNING: This is NOT an override of the base class method. Be careful 03884 03885 SeeAlso: ColourListComponent::StartComponentCopy; 03886 ColourListComponent::AbortComponentCopy; 03887 ColourListComponent::CopyColourAcross 03888 03889 ********************************************************************************************/ 03890 03891 BOOL ColourListComponent::EndComponentCopy(IndexedColour *InsertBefore, BOOL Report) 03892 { 03893 BOOL NeedToReport = FALSE; 03894 03895 if (SourceColours != NULL) // Free the source mapping array 03896 { 03897 CCFree(SourceColours); 03898 SourceColours = NULL; 03899 } 03900 03901 if (DestColours != NULL) 03902 { 03903 // Add the colours in the 'Destination' array to the ColourList for the dest. doc. 03904 // We only add those colours which have not been merged with existing colours in the 03905 // destination list. The AddItem() call ensures their names are unique in this doc. 03906 INT32 i; 03907 for ( i = 0; i < ColourTableSize; i++) 03908 { 03909 if (DestColours[i] != NULL && !MergeColours[i]) 03910 { 03911 if (InsertBefore == NULL || !DestColours[i]->IsNamed()) 03912 pIndexedColours->AddItem(DestColours[i]); 03913 else 03914 pIndexedColours->InsertBefore(InsertBefore, DestColours[i]); 03915 } 03916 } 03917 03918 // Now, remove all merged colours from the list of colours to be 'unhidden' for undo 03919 // NOTE that DestColours is guaranteed to be NULL terminated 03920 03921 // We delete each merged colour from the list by copying the first valid list item 03922 // over the top of the merged item; we keep track of the valid list start with 03923 // 'ListStart'. Once finished, we pass any remainder of the array to UnHideColours 03924 INT32 ListStart = 0; 03925 for (i = 0; i < ColourTableSize; i++) 03926 { 03927 if (DestColours[i] == NULL) // Stop at NULL terminator 03928 break; 03929 03930 if (MergeColours[i] || !DestColours[i]->IsNamed()) 03931 { 03932 // A merged or unnamed colour - copy list item '0' over it, so that we do not 03933 // try to do any undo record for it. 03934 DestColours[i] = DestColours[ListStart]; 03935 DestColours[ListStart] = NULL; 03936 ListStart++; 03937 03938 NeedToReport = TRUE; 03939 } 03940 } 03941 03942 if (DestColours[ListStart] != NULL) // If there are non-merged named colours, create undo 03943 ColourManager::UnHideColours(pIndexedColours, &DestColours[ListStart]); 03944 03945 // Lose our workspace array of pointers to these colours 03946 CCFree(DestColours); 03947 DestColours = NULL; 03948 } 03949 03950 if (MergeColours != NULL) // Free the 'merged'-flag array 03951 { 03952 CCFree(MergeColours); 03953 MergeColours = NULL; 03954 } 03955 03956 // If the caller wants us to, report (if necessary) that some of the colours 03957 // were not copied, as they were already present in the dest. doc 03958 if (Report && NeedToReport) 03959 InformMessage(_R(IDS_COLOURSMERGED), _R(IDS_OK)); 03960 03961 return(TRUE); 03962 } 03963 03964 03965 03966 /******************************************************************************************** 03967 03968 > virtual void ColourListComponent::AbortComponentCopy(); 03969 03970 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 03971 Created: 10/9/94 03972 Inputs: - 03973 Outputs: - 03974 Returns: - 03975 Purpose: Will abort all changes made for component copies. 03976 This means that things such as the colours referenced by the nodes 03977 you have just copied do not exist, so you must clean up to the state 03978 the document was in before you strated copying. 03979 Errors: - 03980 Notes: May be called even if StartComponentCopy has not been called. 03981 May be called multiple times 03982 03983 SeeAlso: ColourListComponent::EndComponentCopy; 03984 ColourListComponent::AbortComponentCopy; 03985 ColourListComponent::CopyColourAcross 03986 03987 ********************************************************************************************/ 03988 03989 void ColourListComponent::AbortComponentCopy() 03990 { 03991 // Clean up by deleting all the new indexedColours we created. We hope that by the 03992 // time we do this, all DocColours referencing these colours will have been vaped. 03993 if (DestColours != NULL) 03994 { 03995 for (INT32 i = 0; i < ColourTableSize; i++) 03996 { 03997 if (DestColours[i] != NULL && !MergeColours[i]) 03998 { 03999 delete DestColours[i]; 04000 DestColours[i] = NULL; 04001 } 04002 } 04003 } 04004 04005 // And release our working arrays 04006 if (SourceColours != NULL) 04007 { 04008 CCFree(SourceColours); 04009 SourceColours = NULL; 04010 } 04011 04012 if (DestColours != NULL) 04013 { 04014 CCFree(DestColours); 04015 DestColours = NULL; 04016 } 04017 04018 if (MergeColours != NULL) 04019 { 04020 CCFree(MergeColours); 04021 MergeColours = NULL; 04022 } 04023 } 04024 04025 04026 04027 /******************************************************************************************** 04028 04029 > INT32 ColourListComponent::ExtendTables(void) 04030 04031 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 04032 Created: 28/11/94 (Separated from CopyColourAcross) 04033 Inputs: - 04034 Outputs: (The mapping arrays may have been moved by realloc) 04035 Returns: -1 if it fails (it will have already reported the error 04036 else the index of the first free entry in the mapping tables 04037 04038 Purpose: Called by Component Copy routines to extend the size of the copy mapping 04039 tables (SourceColours[], DestColours[], and MergeColours[]). This returns 04040 the index of the first free entry in the new tables, or -1 if it fails. 04041 04042 Errors: Memory errors are reported immediately 04043 04044 SeeAlso: ColourListComponent::StartComponentCopy; 04045 ColourListComponent::AbortComponentCopy; 04046 ColourListComponent::EndComponentCopy 04047 04048 ********************************************************************************************/ 04049 04050 INT32 ColourListComponent::ExtendTables(void) 04051 { 04052 INT32 i = ColourTableSize; // Set the index to the first new array entry 04053 04054 ColourTableSize += 64; // Increase the size of our mapping arrays 04055 IndexedColour **TempArray; 04056 04057 // Realloc the Source array, with error handling 04058 TempArray = (IndexedColour **) CCRealloc(SourceColours, 04059 ColourTableSize * sizeof(IndexedColour *)); 04060 if (TempArray == NULL) 04061 { 04062 InformError(); 04063 return(-1); 04064 } 04065 04066 SourceColours = TempArray; // Realloc succeeded - set the new SourceColour ptr 04067 04068 // Realloc the Dest array, with error handling 04069 TempArray = (IndexedColour **) CCRealloc(DestColours, 04070 (ColourTableSize+1) * sizeof(IndexedColour *)); 04071 if (TempArray == NULL) 04072 { 04073 InformError(); 04074 return(-1); 04075 } 04076 04077 DestColours = TempArray; // Realloc succeeded - set the new DestColour ptr 04078 04079 // Realloc the 'Merged'-flag array, with error handling 04080 BOOL *TempBoolArray = (BOOL *) CCRealloc(MergeColours, 04081 ColourTableSize * sizeof(BOOL)); 04082 if (TempBoolArray == NULL) 04083 { 04084 InformError(); 04085 return(-1); 04086 } 04087 04088 MergeColours = TempBoolArray; // Realloc succeeded - set the new MergeColour ptr 04089 04090 // Initialise the new portions of the arrays 04091 for (INT32 j = i; j < ColourTableSize; j++) 04092 { 04093 SourceColours[j] = DestColours[j] = NULL; 04094 MergeColours[j] = FALSE; 04095 } 04096 04097 DestColours[ColourTableSize] = NULL; // And add a NULL terminator to dest. list 04098 04099 return(i); 04100 } 04101 04102 04103 04104 /******************************************************************************************** 04105 04106 > IndexedColour *ColourListComponent::MapColour(IndexedColour *SourceColour, 04107 BOOL *AlreadyThere = NULL, 04108 BOOL SourceIsUnique = FALSE) 04109 04110 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 04111 Created: 29/10/94 04112 04113 Inputs: SourceColour - pointer to an IndexedColour to map 04114 04115 (AlreadyThere is an output only) 04116 04117 SourceIsUnique - FALSE (the default) if you're copying existing document 04118 colours around, and therefore could attempt to copy the 04119 same colour multiple times. 04120 04121 TRUE if you can guarantee that this colour will only be 04122 copied once. This is used only for copying library colours 04123 into a document in the colour gallery (where it uses a temporary 04124 IndexedColour, which causes problems when several different 04125 colours accidentally map to the same temporary memory allocation, 04126 thus causing rampant incorrect colour merging to occur). 04127 04128 Outputs: AlreadyThere - (if non-NULL) is filled in with TRUE if the colour was merged 04129 or FALSE if a new colour had to be created. 04130 04131 Returns: NULL if it fails (the error will have been reported) 04132 Otherwise, a pointer to the IndexedColour resulting from the mapping 04133 04134 Purpose: Used internally in ColourListComponent Component Copy routines. 04135 This method keeps track of mappings between source document and destination 04136 document colours. It determines the mapping from source to dest, and returns 04137 the appropriate destination-docuemnt IndexedColour. This may be a new colour 04138 which will later be added to the destination document or a colour already in 04139 the dest. doc (merged colour). Once an IndexedColour is mapped, future calls 04140 to this method will be very efficient (a simple table search and lookup of 04141 the previous mapping) 04142 04143 Notes: This method is recursive. This allows it to cope with a chain of parent 04144 tint/link colours which may or may not be mapped already. Special care 04145 is taken to ensure that only destination-document references are left 04146 at the end of the copy operation (as obviously, references to the source 04147 doc are highly dangerous, and usually fatal) 04148 04149 SeeAlso: ColourListComponent::StartComponentCopy; 04150 ColourListComponent::AbortComponentCopy; 04151 ColourListComponent::EndComponentCopy 04152 04153 ********************************************************************************************/ 04154 04155 IndexedColour *ColourListComponent::MapColour(IndexedColour *SourceColour, 04156 BOOL *AlreadyThere, BOOL SourceIsUnique) 04157 { 04158 if (AlreadyThere != NULL) // Set a safe return value 04159 *AlreadyThere = FALSE; 04160 04161 // First, check if the colour is already mapped; if so, just return its mapping 04162 // If SourceIsUnique, then we know no two source colours will never be the same, 04163 // and to fix a temporary-colour-reuse (2 colours in the same memory location) 04164 // problem in colour gallery library colour copies, we don't cache the mappings. 04165 // This is fine, because those copies only copy each colour once, so there is 04166 // no need to cache mappings for them anyway. 04167 if (!SourceIsUnique) 04168 { 04169 INT32 i = 0; 04170 while (i < ColourTableSize && SourceColours[i] != NULL && SourceColours[i] != SourceColour) 04171 i++; 04172 04173 if (i < ColourTableSize && SourceColours[i] == SourceColour) 04174 { 04175 // If it was merged, return a value indicating that case 04176 if (AlreadyThere != NULL && MergeColours[i]) 04177 *AlreadyThere = TRUE; 04178 04179 return(DestColours[i]); 04180 } 04181 } 04182 04183 // Next, copy the colour being mapped 04184 IndexedColour *DestColour = new IndexedColour(*SourceColour); 04185 if (DestColour == NULL) 04186 return(NULL); 04187 04188 04189 // Now ensure our parent/ancestors are mapped, ... 04190 IndexedColour *SourceParent = SourceColour->FindLinkedParent(); 04191 IndexedColour *DestParent = NULL; 04192 if (SourceParent != NULL) 04193 { 04194 DestParent = MapColour(SourceParent); 04195 if (DestParent == NULL) 04196 { 04197 delete DestColour; 04198 return(NULL); 04199 } 04200 } 04201 04202 // ... and set the copied colour's parent to the mapped (dest doc) parent, rather than 04203 // the source doc version of the parent. 04204 // Note that if this is not a tint/linked colour, this has the side effect of ensuring 04205 // that Parent is NULL, rather than referencing a parent in a different document 04206 DestColour->SetLinkedParent(DestParent, DestColour->GetType()); 04207 04208 04209 // Finally, map ourselves... 04210 // Find a blank entry in the mapping tables 04211 INT32 i = 0; 04212 while (i < ColourTableSize && SourceColours[i] != NULL) 04213 i++; 04214 04215 if (i >= ColourTableSize) // If no free entries, extend them and get first free entry 04216 i = ExtendTables(); 04217 04218 if (i < 0) // We failed - no memory for tables 04219 { 04220 delete DestColour; 04221 return(NULL); 04222 } 04223 04224 // Check if there is already a matching colour in the dest. document. 04225 // If there is one, then chuck away DestColour, and use the matching colour instead 04226 IndexedColour *MatchColour = ExactMatchExists(DestColour); 04227 if (MatchColour != NULL) 04228 { 04229 delete DestColour; 04230 DestColour = MatchColour; 04231 04232 if (AlreadyThere != NULL) // And return info to indicate that the colour is merged 04233 *AlreadyThere = TRUE; 04234 } 04235 04236 // And finally, write the new entry into the mapping tables 04237 // (but only if we need to cache the mappings - NOTE that we need to store a 04238 // mapping (at least to the extent of having a destination part of the mapping) 04239 // or the new colours won't be added in EndComponentCopy. Unfortunately this 04240 // means we need a source mapping that isn't NULL or it all falls apart. 04241 if (SourceIsUnique) 04242 SourceColours[i] = (IndexedColour *) 1; // Yeek! Have to stop this being null 04243 else 04244 SourceColours[i] = SourceColour; 04245 04246 DestColours[i] = DestColour; 04247 MergeColours[i] = (MatchColour != NULL); 04248 04249 return(DestColour); // And return the result of the mapping operation 04250 04251 return NULL; 04252 } 04253 04254 04255 04256 /******************************************************************************************** 04257 04258 > ColCompCopyResult CopyColourAcross(DocColour* pDocColour, BOOL SourceIsUnique = FALSE); 04259 04260 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 04261 Created: 10/9/94 04262 04263 Inputs: pDocColour - The colour which resulted from copying across from one document 04264 to our document. 04265 04266 SourceIsUnique - FALSE (the default) if you're copying existing document 04267 colours around, and therefore could attempt to copy the 04268 same colour multiple times. 04269 04270 TRUE if you can guarantee that this colour will only be 04271 copied once. This is used only for copying library colours 04272 into a document in the colour gallery (where it uses a temporary 04273 IndexedColour, which causes problems when several different 04274 colours accidentally map to the same temporary memory allocation, 04275 thus causing rampant incorrect colour merging to occur). 04276 ** ONLY USE THIS IF YOU REALLY REALLY BELIEVE YOU MUST - ** 04277 ** IT SHOULD NOT BE NECESSARY UNDER NORMAL CIRCUMSTANCES ** 04278 04279 Returns: CCCOPY_FAILED = 0/FALSE - if it failed, in which case the error has been reported 04280 04281 CCCOPY_NEWCOLOUR - if it succeeded by creating a new colour 04282 04283 CCCOPY_MERGEDCOLOUR - if it succeeded by merging (using an existing colour) 04284 04285 Purpose: If the DocColour references an IndexedColour then a copy of that IxColour is 04286 made and remembered. The DocColour is then changed to reference the new 04287 indexed colour. On calling EndComponentCopy, these new IndexedColours will 04288 be added to the document. If a failure occurs at any stage, you must 04289 *immediately* undo the entire copy operation, deleting all the nodes 04290 referencing the new colours we've created, before calling AbortComponentCopy 04291 04292 Chains of linked/tint IndexedColours are also handled properly. 04293 04294 Notes: If this function returns FALSE, you MUST clean up and then call 04295 AbortComponentCopy to clean up. 04296 04297 Errors: Memory errors are reported immediately 04298 If StartComponentCopy has not been called, or an internal consistency failure 04299 occurs (our working array pointer(s) are NULL), an ERROR2 will be reported. 04300 04301 SeeAlso: ColourListComponent::StartComponentCopy; 04302 ColourListComponent::AbortComponentCopy; 04303 ColourListComponent::EndComponentCopy 04304 04305 ********************************************************************************************/ 04306 04307 ColCompCopyResult ColourListComponent::CopyColourAcross(DocColour* pDocColour, BOOL SourceIsUnique) 04308 { 04309 IndexedColour *SourceColour = pDocColour->FindParentIndexedColour(); 04310 04311 if (SourceColour == NULL) // Doesn't reference an IndexedColour, so return success 04312 return(CCCOPY_MERGEDCOLOUR); 04313 04314 if (SourceColours == NULL || DestColours == NULL || MergeColours == NULL) 04315 { 04316 ERROR2RAW("ColourListComponent::CopyColourAcross called without a prior StartComponentCopy"); 04317 InformError(); 04318 return(CCCOPY_FAILED); 04319 } 04320 04321 BOOL WasMerged = FALSE; 04322 IndexedColour *NewColour = MapColour(SourceColour, &WasMerged, SourceIsUnique); 04323 if (NewColour == NULL) // An error (no memory) occurred - abort component copy 04324 return(CCCOPY_FAILED); 04325 04326 // Fix the colour to reference the destination copy of the indexed colour 04327 pDocColour->MakeRefToIndexedColour(NewColour); 04328 return((WasMerged) ? CCCOPY_MERGEDCOLOUR : CCCOPY_NEWCOLOUR); 04329 04330 return CCCOPY_FAILED; 04331 } 04332 04333 04334 /******************************************************************************************** 04335 04336 > IndexedColour* ColourListComponent::GetIndexedParentOfColour(DocColour Colour) 04337 04338 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04339 Created: 17/5/2000 04340 Inputs: Colour - the doccolour that was originally created from an indexed colour 04341 Outputs: - 04342 Returns: the indexed colour that originally created Colour, if there is one, else NULL 04343 Purpose: It is possible for us to create doccolours from indexed colours and then convert 04344 them so that they are standalone. This method goes through all the indexed 04345 colours to try and find out which indexed colour (if any) originally created the input 04346 04347 ********************************************************************************************/ 04348 04349 IndexedColour* ColourListComponent::GetIndexedParentOfColour(DocColour Colour) 04350 { 04351 ColourList* pList = GetColourList(); 04352 if (pList == NULL) 04353 return NULL; 04354 04355 ColourGeneric ColDef; 04356 ColourContext *cc = ColourManager::GetColourContext(Colour.GetColourModel()); 04357 ERROR2IF(cc == NULL, NULL, "Can't find colour context?!"); 04358 DocColour ConvertedDocCol; 04359 04360 IndexedColour* pItem = (IndexedColour*)pList->GetHead(); 04361 04362 // what we have to do is get each indexed colour as a standalone definition then 04363 // ask it to make a doccolour. If this is the same as our input then we have our match 04364 while (pItem != NULL) 04365 { 04366 // Get the IndexedColour definition as a standalone colour definition 04367 cc->ConvertColour(pItem, &ColDef); 04368 04369 // Make the DocColour into a simple standalone "lookalike" of the parent colour 04370 ConvertedDocCol = DocColour(Colour.GetColourModel(), &ColDef); 04371 04372 // now test to see if its the same, if so we've got what we want 04373 if (ConvertedDocCol == Colour) 04374 break; 04375 04376 pItem = (IndexedColour*)pList->GetNext(pItem); 04377 04378 04379 } 04380 return pItem; 04381 }