00001 // $Id: colourix.cpp 1333 2006-06-16 20:34:16Z 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 // colourix.cpp - Indexed colour class 00099 00100 /* 00101 */ 00102 00103 00104 #include "camtypes.h" 00105 00106 #include "colcontx.h" 00107 #include "colourix.h" 00108 #include "colormgr.h" 00109 //#include "doccolor.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00110 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00111 //#include "jason.h" 00112 00113 CC_IMPLEMENT_DYNAMIC(IndexedColour, ListItem) 00114 00115 // Declare smart memory handling in Debug builds 00116 #define new CAM_DEBUG_NEW 00117 00118 00119 #ifndef WEBSTER // there are never spot colours in WEBSTER Martin 15/07/97 00120 BOOL IndexedColour::SpotsAreProcess = FALSE; 00121 #else 00122 BOOL IndexedColour::SpotsAreProcess = TRUE; 00123 #endif 00124 00125 /******************************************************************************************** 00126 00127 > void IndexedColour::InitialiseInfoFields(void) 00128 00129 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00130 Created: 30/03/94 00131 Inputs: - 00132 Outputs: - 00133 Returns: - 00134 Purpose: Private shared code for construction of IndexedColour objects 00135 Initialises the 'Info' structure to default values 00136 Scope: private 00137 Errors: - 00138 SeeAlso: - 00139 00140 ********************************************************************************************/ 00141 00142 void IndexedColour::InitialiseInfoFields(ColourModel ColModel) 00143 { 00144 UsageCount = 0; // We are not in-use yet 00145 ChildUsage = 0; 00146 00147 Name = NULL; // This colour has no name 00148 00149 ParentColour = NULL; // We are not linked to another colour by default 00150 00151 Info.OCContextHandle = 0; // Set colour model, and remember we're not cached 00152 Info.SourceColourModel = ColModel; 00153 Info.CacheColourModel = COLOURMODEL_NOTCACHED; 00154 00155 Info.InheritComponent1 = // By default, override all components in linked colour 00156 Info.InheritComponent2 = 00157 Info.InheritComponent3 = 00158 Info.InheritComponent4 = FALSE; 00159 00160 Info.ColourType = COLOURTYPE_NORMAL; // Is normal (not spot/tint/linked) colour 00161 00162 Info.Deleted = FALSE; // Not a deleted (hidden) colour 00163 00164 Info.IsNamed = FALSE; 00165 } 00166 00167 00168 00169 /******************************************************************************************** 00170 00171 > IndexedColour::IndexedColour() 00172 00173 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00174 Created: 30/03/94 00175 Inputs: - 00176 Outputs: - 00177 Returns: - 00178 Purpose: Constructor for an IndexedColour object 00179 Initialises the colour to the RGBT value for Opaque Black 00180 Errors: - 00181 SeeAlso: - 00182 00183 ********************************************************************************************/ 00184 00185 IndexedColour::IndexedColour() 00186 { 00187 InitialiseInfoFields(COLOURMODEL_RGBT); 00188 00189 SourceColour.Component1 = 0; // Black & No-colour (in RGBT) 00190 SourceColour.Component2 = 0; 00191 SourceColour.Component3 = 0; 00192 SourceColour.Component4 = 1.0; // 100% transparent 00193 } 00194 00195 00196 00197 /******************************************************************************************** 00198 00199 > IndexedColour::~IndexedColour() 00200 00201 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00202 Created: 30/03/94 00203 Inputs: - 00204 Outputs: - 00205 Returns: - 00206 Purpose: Destructor for an IndexedColour object 00207 Errors: - 00208 SeeAlso: - 00209 00210 ********************************************************************************************/ 00211 00212 IndexedColour::~IndexedColour() 00213 { 00214 ERROR3IF(UsageCount < 0, "IndexedColour UsageCount is negative"); 00215 00216 #ifdef _DEBUG 00217 if (UsageCount != 0) 00218 { 00219 if (IsNamed()) 00220 TRACE( _T("\n>> Named IndexedColour %p ('%s') is still referenced %ld times\n"), 00221 this, (TCHAR *)(*Name), (INT32)UsageCount); 00222 else 00223 TRACE( _T("\n>> Unnamed IndexedColour %p is still referenced %ld times\n"), 00224 this, (INT32)UsageCount); 00225 00226 // Now, ask SimpleCCObject to wugg through all current objects to see if we can find something 00227 // that could be the pointer back at us! 00228 extern void CheckForUsedPointer(void *ThePointer); 00229 00230 TRACE( _T(" References to this object were found in:\n")); 00231 CheckForUsedPointer(this); 00232 TRACE( _T("\n")); 00233 } 00234 00235 ERROR3IF(UsageCount > 0, "IndexedColour deleted while still in use"); 00236 00237 if (ChildUsage != 0) 00238 { 00239 if (IsNamed()) 00240 { 00241 TRACEUSER( "Jason", _T("Jason: Named IndexedColour %p ('%s') is still LINKED %ld times\n"), 00242 this, (TCHAR *)(*Name), (INT32)ChildUsage); 00243 } 00244 else 00245 { 00246 TRACEUSER( "Jason", _T("Jason: Unnamed IndexedColour %p is still LINKED %ld times\n"), 00247 this, (INT32)ChildUsage); 00248 } 00249 } 00250 #endif 00251 00252 // If we are linked to another colour, we need to de-reference it 00253 if (ParentColour != NULL) 00254 ParentColour->DecrementChildUsage(); 00255 00256 if (Name != NULL) 00257 delete Name; 00258 } 00259 00260 00261 00262 /******************************************************************************************** 00263 00264 > IndexedColour::IndexedColour(const IndexedColour& Col) 00265 00266 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00267 Created: 05/05/94 00268 Inputs: - 00269 Outputs: - 00270 Returns: - 00271 Purpose: Copy constructor for an IndexedColour object 00272 Errors: - 00273 SeeAlso: - 00274 00275 ********************************************************************************************/ 00276 00277 IndexedColour::IndexedColour(const IndexedColour& Col) 00278 { 00279 Info = Col.Info; 00280 memcpy(&SourceColour, &Col.SourceColour, sizeof(ColourGeneric)); 00281 memcpy(&CachedColour, &Col.CachedColour, sizeof(ColourGeneric)); 00282 00283 // If we are copying a linked/tint colour, we make ourselves linked to their parent 00284 ParentColour = Col.ParentColour; 00285 if (ParentColour != NULL) 00286 ParentColour->IncrementChildUsage(); 00287 00288 UsageCount = 0; 00289 ChildUsage = 0; 00290 00291 Info.IsNamed = FALSE; 00292 Name = NULL; 00293 00294 // Nasty casting to get around this messy const problem. 00295 if (((IndexedColour *)&Col)->IsNamed()) 00296 SetName(*(Col.Name)); // Copy the string, not the string-pointer 00297 } 00298 00299 00300 00301 /******************************************************************************************** 00302 00303 > IndexedColour::IndexedColour(const DocColour& Col) 00304 00305 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00306 Created: 9/11/94 00307 Inputs: Col - A DocColour from which to take the definition of this new IndexedCol 00308 Outputs: - 00309 Returns: - 00310 Purpose: Copy constructor for an IndexedColour object. 00311 00312 Notes: If the DocColour is immediate (does not reference an IndexedColour) then 00313 the indexedcolour uses its colour definition - NOTE that this creates an 00314 UNNAMED colour by default (SetName it afterwards). 00315 00316 If the DocColour references an IndexedColour, the referenced colour is copied 00317 00318 Tints and Linked colours are copied and remain tints/linked (Gosh!) 00319 00320 Named/Unnamed colours will be copied as Named/Unnamed colours (Gosh!) 00321 00322 The name is copied verbatim (i.e it is not changed to 'Copy of X') 00323 00324 Errors: - 00325 SeeAlso: IndexedColour::SetName 00326 00327 ********************************************************************************************/ 00328 00329 IndexedColour::IndexedColour(const DocColour& Col) 00330 { 00331 // Find the parent IndexedColour, if any. Nasty cast to remove compiler warning 00332 IndexedColour *Def = ((DocColour *) &Col)->FindParentIndexedColour(); 00333 00334 if (Def != NULL) 00335 { 00336 // The DocColour references an IndexedColour, so copy the parent IndexedColour 00337 Info = Def->Info; 00338 memcpy(&SourceColour, &Def->SourceColour, sizeof(ColourGeneric)); 00339 memcpy(&CachedColour, &Def->CachedColour, sizeof(ColourGeneric)); 00340 00341 // If we are copying a linked/tint colour, we need to link ourselves to its parent 00342 ParentColour = Def->ParentColour; 00343 if (ParentColour != NULL) 00344 ParentColour->IncrementChildUsage(); 00345 00346 UsageCount = 0; 00347 ChildUsage = 0; 00348 00349 Info.IsNamed = FALSE; 00350 Name = NULL; 00351 if (Def->IsNamed()) 00352 SetName(*(Def->Name)); // Copy the string, not the string-pointer 00353 } 00354 else 00355 { 00356 // This is an immediate DocColour, so copy its definition into our SourceColour 00357 InitialiseInfoFields(Col.GetColourModel()); 00358 ((DocColour *) &Col)->GetSourceColour(&SourceColour); 00359 } 00360 } 00361 00362 00363 00364 /******************************************************************************************** 00365 00366 > IndexedColour::IndexedColour(ColourValue Red, ColourValue Green, ColourValue Blue, 00367 ColourValue Transparent = 0, 00368 UINT32 TransType = TRANSTYPE_DEFAULT) 00369 00370 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00371 Created: 30/03/94 00372 Inputs: Red; Green; Blue - The RGB definition of the colour 00373 00374 Transparent - The transparency of the colour - IGNORED! 00375 TransType - The transparency type of the colour - IGNORED! 00376 00377 Outputs: - 00378 Returns: - 00379 Purpose: Constructor for an IndexedColour object 00380 Initialises the colour to the given Extended RGBT value 00381 00382 Notes: Colours no longer support transparency. The transparency fields are 00383 ignored. 00384 00385 Errors: - 00386 SeeAlso: - 00387 00388 ********************************************************************************************/ 00389 00390 IndexedColour::IndexedColour(ColourValue Red, ColourValue Green, ColourValue Blue, 00391 ColourValue Transparent, UINT32 TransType) 00392 { 00393 InitialiseInfoFields(COLOURMODEL_RGBT); 00394 SourceColour.Component1 = Red; 00395 SourceColour.Component2 = Green; 00396 SourceColour.Component3 = Blue; 00397 SourceColour.Component4 = Transparent; 00398 } 00399 00400 00401 00402 /******************************************************************************************** 00403 00404 > IndexedColour::IndexedColour(ColourModel ColModel, ColourGeneric *Col) 00405 00406 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00407 Created: 30/03/94 00408 Inputs: ColModel - The colour model in which Col is defined 00409 Col - The definition, in the given colour model, of the colour 00410 Outputs: - 00411 Returns: - 00412 Purpose: Constructor for an IndexedColour object 00413 Initialises the colour to the given value in the given colour model 00414 NOTE that if you have a ColourABCD structure, you can pass this in 00415 as a single parameter, and inline functions will convert the call 00416 into a call to this function on your behalf. 00417 i.e. you can use IndexedColour((ColourRGBT *)Bob); -- See colour.h 00418 Errors: - 00419 SeeAlso: - 00420 00421 ********************************************************************************************/ 00422 00423 IndexedColour::IndexedColour(ColourModel ColModel, ColourGeneric *Col) 00424 { 00425 InitialiseInfoFields(ColModel); 00426 memcpy(&SourceColour, Col, sizeof(ColourGeneric)); 00427 } 00428 00429 00430 00431 /******************************************************************************************** 00432 00433 > IndexedColour& IndexedColour::operator=(const IndexedColour& Other) 00434 00435 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00436 Created: 12/10/94 00437 Inputs: Other - colour to copy 00438 Outputs: - 00439 Returns: 00440 Purpose: IndexedColour assignment operator 00441 Copies the definition of one IndexedColour into another 00442 Notes: The name field is copied verbatim - if you want it to say 'Copy of ...' 00443 then you'll have to prepend this text yourself. 00444 Errors: ERROR2 if you try to copy a colour over itself 00445 00446 ********************************************************************************************/ 00447 00448 IndexedColour& IndexedColour::operator=(const IndexedColour& Other) 00449 { 00450 ERROR2IF(&Other == this, *this, "Attempt to copy an IndexedColour over itself!"); 00451 00452 Info = Other.Info; 00453 memcpy(&SourceColour, &Other.SourceColour, sizeof(ColourGeneric)); 00454 memcpy(&CachedColour, &Other.CachedColour, sizeof(ColourGeneric)); 00455 00456 if (ParentColour != NULL) // Delink from old parent (if any) 00457 ParentColour->DecrementChildUsage(); 00458 00459 ParentColour = Other.ParentColour; 00460 if (ParentColour != NULL) // Link to new parent (if any) 00461 ParentColour->IncrementChildUsage(); 00462 00463 // UsageCount = 0; // These DO NOT CHANGE! We still have people referencing us 00464 // ChildUsage = 0; // and we must not forget about them! 00465 00466 Info.IsNamed = FALSE; 00467 if (((IndexedColour *)&Other)->IsNamed()) 00468 SetName(*(Other.Name)); // Copy the string, not the string-pointer 00469 00470 return(*this); 00471 } 00472 00473 00474 00475 /******************************************************************************************** 00476 00477 > IndexedColourType IndexedColour::GetType(void) const 00478 00479 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00480 Created: 13/10/94 00481 Returns: The type of this colour: 00482 MonoOn 00483 COLOURTYPE_NORMAL, COLOURTYPE_SPOT, COLOURTYPE_TINT, COLOURTYPE_LINKED 00484 MonoOff 00485 00486 Purpose: Determines the type of this colour 00487 00488 Notes: If this colour is linked to a deleted colour, then for sneaky undo reasons 00489 it (internally) remains linked. However, it pretends to the outside world 00490 that it is in fact a normal colour. 00491 00492 SeeAlso: IndexedColour::SetType; IndexedColour::FindLinkedParent; 00493 IndexedColour::SetLinkedParent 00494 00495 ********************************************************************************************/ 00496 00497 IndexedColourType IndexedColour::GetType(void) const 00498 { 00499 if ((Info.ColourType == (UINT32) COLOURTYPE_LINKED || 00500 Info.ColourType == (UINT32) COLOURTYPE_TINT) && 00501 ParentColour != NULL && ParentColour->IsDeleted()) 00502 { 00503 return(COLOURTYPE_NORMAL); 00504 } 00505 00506 // If the global "SpotsareProcess" flag is set, then spots pretend to be normal 00507 // Unnamed/Local colours also cannot be spots, so in case we accidentally get into the 00508 // wrong state, we make sure never to return a silly result. 00509 if (Info.ColourType == COLOURTYPE_SPOT && (SpotsAreProcess || !Info.IsNamed)) 00510 return(COLOURTYPE_NORMAL); 00511 00512 return((IndexedColourType) Info.ColourType); 00513 } 00514 00515 00516 00517 /******************************************************************************************** 00518 00519 > BOOL IndexedColour::IsSpotOrTintOfSpot(void) const 00520 00521 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00522 Created: 12/6/96 00523 00524 Returns: TRUE if this colour is either a spot colour or a tint of a spot colour 00525 00526 Purpose: Determines if this colour is either a spot colour or a true tint of a 00527 spot colour. (Tints can unfortunately be made from non-spot colour 00528 parents, so you need to call this function to determine if a tint 00529 really is cleanly derived from a spot colour, or if it must be treated 00530 as a simple process colour) 00531 00532 Thus, this returns TRUE if the colour itself is a Spot, or 00533 if it is a Tint and its parent returns TRUE from IsSpotOrTintOfSpot(). 00534 00535 Notes: If a colour in the tint chain is deleted, then all children must 00536 become process (non true-tint) colours, so this will return FALSE 00537 00538 ********************************************************************************************/ 00539 00540 BOOL IndexedColour::IsSpotOrTintOfSpot(void) const 00541 { 00542 if (Info.Deleted) 00543 return(FALSE); 00544 00545 IndexedColourType Type = GetType(); 00546 if (Type == COLOURTYPE_SPOT) 00547 return(TRUE); // Is it a true spot colour? 00548 00549 if (Type != COLOURTYPE_TINT || TintIsShade()) 00550 return(FALSE); // It's not even a tint 00551 00552 if (ParentColour == NULL) 00553 return(FALSE); // We have no parent colour 00554 00555 // OK, we're a tint of something. Recurse to find out if that something 00556 // is a true tint or a spot colour. 00557 return(ParentColour->IsSpotOrTintOfSpot()); 00558 } 00559 00560 00561 00562 /******************************************************************************************** 00563 00564 > ColourModel IndexedColour::GetColourModel(void) const 00565 00566 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00567 Created: 30/03/94 00568 Inputs: - 00569 Outputs: - 00570 Returns: The colour model in which the IndexedColour was defined 00571 00572 Purpose: To determine the colour model in which an IndexedColour is defined 00573 00574 Notes: If this colour is a TINT, the parent colour's colour model is returned, 00575 as tints cannot be defined in a different model to their parents 00576 00577 Errors: - 00578 SeeAlso: IndexedColour::GetSourceColour 00579 00580 ********************************************************************************************/ 00581 00582 ColourModel IndexedColour::GetColourModel(void) const 00583 { 00584 // If we're a tint, return our parent's colour. NOTE that we do not call GetType() 00585 // as we want to ask our parent even if it is 'deleted' for UNDO reasons. 00586 if (Info.ColourType == COLOURTYPE_TINT && ParentColour != NULL) 00587 return(ParentColour->GetColourModel()); 00588 00589 return((ColourModel) Info.SourceColourModel); 00590 } 00591 00592 00593 00594 /******************************************************************************************** 00595 00596 > void IndexedColour::GetSourceColour(ColourGeneric *Result) 00597 00598 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00599 Created: 30/03/94 00600 Inputs: - 00601 Outputs: - 00602 Returns: The colour definition of this IndexedColour, in its native colour model 00603 Purpose: Gets the definition of the IndexedColour. 00604 00605 Notes: If the colour is Tint/Linked, this may involve a recursive set of calls which 00606 will convert and override each parent colour up the chain until the 00607 resulting colour definition for this colour is eventually produced at 00608 the end. 00609 00610 Errors: - 00611 SeeAlso: IndexedColour::GetColourModel 00612 00613 ********************************************************************************************/ 00614 00615 void IndexedColour::GetSourceColour(ColourGeneric *Result) 00616 { 00617 ERROR3IF(Result == &SourceColour, 00618 "Illegal attempt to GetSourceColour into a colour's own SourceColour field!"); 00619 00620 if (ParentColour == NULL || ParentColour == this || 00621 (Info.ColourType != COLOURTYPE_LINKED && Info.ColourType != COLOURTYPE_TINT)) 00622 { 00623 // We are not linked to a parent colour (or the link is scarily illegal to ourself!) 00624 // (ParentColour == NULL OR we are not tint/linked) 00625 // - simply copy our own colour definition, checking that this is not an internal 00626 // call to get a source colour definition into our own source colour! 00627 if (&SourceColour != Result) 00628 memcpy(Result, &SourceColour, sizeof(ColourGeneric)); 00629 } 00630 else 00631 { 00632 ERROR3IF(ParentColour == NULL || ParentColour == this || 00633 ParentColour->IsADescendantOf(this), 00634 "Consistency failure in IndexedColour parent linkage"); 00635 00636 // Ask our parent for its colour definition - recurse! 00637 ParentColour->GetSourceColour(Result); 00638 00639 // Get our 'parent' colour context 00640 ColourContext *cc = ColourContext::GetGlobalDefault(GetColourModel()); 00641 ERROR3IF(cc == NULL, "IndexedColour::GetSourceColour - illegal colour context in use?!"); 00642 00643 // Now, override the colour as necessary 00644 // NOTE that we do NOT call GetType(), as this might return COLOURTYPE_NORMAL for tints/linked 00645 // colours which have 'deleted' parents. This is due to nasty UNDO considerations - we retain 00646 // our linked parent internally when it is 'deleted'. 00647 if (Info.ColourType == COLOURTYPE_LINKED) 00648 { 00649 // If necessary, convert the Result colour into our own colour model 00650 if (ParentColour->GetColourModel() != GetColourModel()) 00651 { 00652 ColourContext *ccSource = ColourContext::GetGlobalDefault(ParentColour->GetColourModel()); 00653 00654 if (ccSource != NULL) // Shouldn't happen, but let's be safe 00655 { 00656 ColourGeneric Source; 00657 memcpy(&Source, Result, sizeof(ColourGeneric)); 00658 00659 cc->ConvertColour(ccSource, &Source, Result); 00660 } 00661 } 00662 00663 // **** ToDo !!!! Override by copying OR Inherit by scaling !!!! 00664 00665 // This is a linked colour. Override the given components with our own values 00666 if (!Info.InheritComponent1) 00667 Result->Component1 = SourceColour.Component1; 00668 if (!Info.InheritComponent2) 00669 Result->Component2 = SourceColour.Component2; 00670 if (!Info.InheritComponent3) 00671 Result->Component3 = SourceColour.Component3; 00672 if (!Info.InheritComponent4) 00673 Result->Component4 = SourceColour.Component4; 00674 } 00675 else if (Info.ColourType == COLOURTYPE_TINT) 00676 { 00677 // This is a tint. Component 1 of our 'SourceColour' is the tinting value 00678 // We get our 'parent' colour context to work out how to apply the tint/shade 00679 if (TintIsShade()) 00680 cc->ApplyShade(SourceColour.Component1, SourceColour.Component2, Result); // Shade it 00681 else 00682 cc->ApplyTint(SourceColour.Component1, Result); // Tint it 00683 } 00684 else 00685 { 00686 ERROR3("Unknown/Illegal colour type in IndexedColour::GetSourceColour"); 00687 } 00688 } 00689 } 00690 00691 00692 00693 /******************************************************************************************** 00694 00695 > BOOL IndexedColour::IsDifferent(const IndexedColour &Other) 00696 00697 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00698 Created: 1/8/94 00699 Inputs: Other - the other indexed colour to which 'this' will be compared 00700 Outputs: - 00701 Returns: TRUE if the two colours are considered different 00702 FALSE if they are considered the same 00703 Purpose: To determine if two indexed colours share a common definition. 00704 00705 This is defined as: Same Colour model, and source colour definitions 00706 and both are linked to/tint of the same colour (or none), and the 'no colour' 00707 (and if linked: inheritance bits; if tint: tinting values) and colour type 00708 match exactly. 00709 00710 NOTE especially that this does NOT compare the names of the colours 00711 00712 ********************************************************************************************/ 00713 00714 BOOL IndexedColour::IsDifferent(const IndexedColour &Other) 00715 { 00716 if (GetType() != Other.GetType()) 00717 return(TRUE); 00718 00719 if (GetColourModel() != Other.GetColourModel()) 00720 return(TRUE); 00721 00722 // If this is a linked colour, check if their inheritance flags match 00723 if (GetType() == COLOURTYPE_LINKED) 00724 { 00725 if (ParentColour != Other.ParentColour) 00726 return(TRUE); 00727 00728 if (Info.InheritComponent1 != Other.Info.InheritComponent1 || 00729 Info.InheritComponent2 != Other.Info.InheritComponent2 || 00730 Info.InheritComponent3 != Other.Info.InheritComponent3 || 00731 Info.InheritComponent4 != Other.Info.InheritComponent4) 00732 return(TRUE); 00733 } 00734 00735 // If this is a tint, it has no components in the regular sense. 00736 // Return immediately with the result of comparing the tint values 00737 if (GetType() == COLOURTYPE_TINT) 00738 { 00739 if (ParentColour != Other.ParentColour) 00740 return(TRUE); 00741 00742 if (TintIsShade() != Other.TintIsShade()) 00743 return(TRUE); 00744 00745 if (TintIsShade()) 00746 { 00747 return(GetShadeValueX() != Other.GetShadeValueX() || 00748 GetShadeValueY() != Other.GetShadeValueY()); 00749 } 00750 00751 return(GetTintValue() != Other.GetTintValue()); 00752 } 00753 00754 if (GetColourModel() == COLOURMODEL_GREYT) 00755 { 00756 // We ignore the 2nd and 3rd components as they are not used. 00757 // (Should not be necessary, as these components should be zeroed anyway) 00758 if (SourceColour.Component1 != Other.SourceColour.Component1 || 00759 SourceColour.Component4 != Other.SourceColour.Component4) 00760 return(TRUE); 00761 } 00762 else 00763 { 00764 if (SourceColour.Component1 != Other.SourceColour.Component1 || 00765 SourceColour.Component2 != Other.SourceColour.Component2 || 00766 SourceColour.Component3 != Other.SourceColour.Component3 || 00767 SourceColour.Component4 != Other.SourceColour.Component4) 00768 return(TRUE); 00769 } 00770 00771 return(FALSE); 00772 } 00773 00774 00775 00776 /******************************************************************************************** 00777 00778 > BOOL IndexedColour::IsDifferent(const IndexedColour &Other, FIXED24 ErrorLimit) 00779 00780 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00781 Created: 1/8/94 00782 Inputs: Other - the other indexed colour to which 'this' will be compared 00783 Outputs: - 00784 Returns: TRUE if the two colours are considered different 00785 FALSE if they are considered the same 00786 Purpose: To determine if two indexed colours share a common definition. 00787 00788 This is defined as: Same Colour model, and source colour definitions 00789 and both are linked to/tint of the same colour (or none), and the 'no colour' 00790 (and if linked: inheritance bits; if tint: tinting values) and colour type 00791 match within the limits specified by ErrorLimit. 00792 00793 This version of the function takes an accuracy parameter, to allow 00794 'rough' comparisons to be made. This is used when importing colours so 00795 that we don't have to store 32bit colour values in EPS files and so on 00796 in order for them to be recognised as an existing colour when re-importing. 00797 00798 NOTE especially that this does NOT compare the names of the colours 00799 00800 ********************************************************************************************/ 00801 00802 #define OUTSIDE_LIMIT(a,b) ((ABS((a) - (b))) > (ErrorLimit)) 00803 00804 BOOL IndexedColour::IsDifferent(const IndexedColour &Other, FIXED24 ErrorLimit) 00805 { 00806 if (GetType() != Other.GetType()) 00807 return(TRUE); 00808 00809 if (GetColourModel() != Other.GetColourModel()) 00810 return(TRUE); 00811 00812 // If this is a linked colour, check if their inheritance flags match 00813 if (GetType() == COLOURTYPE_LINKED) 00814 { 00815 if (ParentColour != Other.ParentColour) 00816 return(TRUE); 00817 00818 if (Info.InheritComponent1 != Other.Info.InheritComponent1 || 00819 Info.InheritComponent2 != Other.Info.InheritComponent2 || 00820 Info.InheritComponent3 != Other.Info.InheritComponent3 || 00821 Info.InheritComponent4 != Other.Info.InheritComponent4) 00822 return(TRUE); 00823 } 00824 00825 // If this is a tint, it has no components in the regular sense. 00826 // Return immediately with the result of comparing the tint values 00827 if (GetType() == COLOURTYPE_TINT) 00828 { 00829 if (ParentColour != Other.ParentColour) 00830 return(TRUE); 00831 00832 if (TintIsShade() != Other.TintIsShade()) 00833 return(TRUE); 00834 00835 if (TintIsShade()) 00836 { 00837 return( OUTSIDE_LIMIT(GetShadeValueX(), Other.GetShadeValueX()) || 00838 OUTSIDE_LIMIT(GetShadeValueY(), Other.GetShadeValueY()) ); 00839 } 00840 00841 return( OUTSIDE_LIMIT(GetTintValue(), Other.GetTintValue()) ); 00842 } 00843 00844 // Special case for greyscales... 00845 if (GetColourModel() == COLOURMODEL_GREYT) 00846 { 00847 // We ignore the 2nd and 3rd components as they are not used. 00848 if (OUTSIDE_LIMIT(SourceColour.Component1, Other.SourceColour.Component1) || 00849 OUTSIDE_LIMIT(SourceColour.Component4, Other.SourceColour.Component4)) 00850 return(TRUE); 00851 } 00852 else 00853 { 00854 if (OUTSIDE_LIMIT(SourceColour.Component1, Other.SourceColour.Component1) || 00855 OUTSIDE_LIMIT(SourceColour.Component2, Other.SourceColour.Component2) || 00856 OUTSIDE_LIMIT(SourceColour.Component3, Other.SourceColour.Component3) || 00857 OUTSIDE_LIMIT(SourceColour.Component4, Other.SourceColour.Component4)) 00858 return(TRUE); 00859 } 00860 00861 return(FALSE); 00862 } 00863 00864 // Ensure we don't use this macro out of its intended scope - it uses 'ErrorLimit'! 00865 #undef OUTSIDE_LIMIT 00866 00867 00868 00869 /******************************************************************************************** 00870 00871 > String_64 *IndexedColour::GetName(BOOL ReturnTrueID = FALSE) 00872 00873 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00874 Created: 02/04/94 00875 00876 Inputs: ReturnTrueID - FALSE (the default) to retrieve the 'normal' name. If this 00877 colour is unnamed, the string "Unnamed" will be returned. 00878 TRUE (*use with care*) to return a unique id for this colour. If unnamed, 00879 this will return a unique name string like "_362180". This is only intended 00880 for use by the import/export system. 00881 00882 Outputs: - 00883 Returns: A pointer to a String_64 containing the name of this indexed colour 00884 If it is named, the return value is always the name 00885 If it is unnamed, then either "Unnamed" or a unique id "_1234567" will be 00886 returned. 00887 00888 Purpose: To find the name of an IndexedColour (or the ID of an unnamed indexed colour) 00889 Errors: - 00890 00891 ********************************************************************************************/ 00892 00893 String_64 *IndexedColour::GetName(BOOL ReturnTrueID) 00894 { 00895 static String_64 Default(_R(IDS_LOCALCOLOUR)); 00896 00897 if (IsNamed()) 00898 { 00899 if (Name != NULL) 00900 return(Name); 00901 } 00902 else 00903 { 00904 if (ReturnTrueID) 00905 { 00906 // If we're an unnamed colour, then we generate an "ID" (not a name, honest, guv!) 00907 // which is unique. This is used for export/import to recognise unnamed colours 00908 00909 if (Name == NULL) 00910 { 00911 Name = new String_64; 00912 if (Name != NULL) 00913 Name->_MakeMsg( TEXT("_#1%ld"), (UINT32)(UINT_PTR)(this) ); 00914 } 00915 00916 if (Name != NULL) 00917 return(Name); 00918 } 00919 } 00920 00921 return(&Default); 00922 } 00923 00924 00925 00926 /******************************************************************************************** 00927 00928 > void IndexedColour::SetName(const StringBase &NewName, [BOOL ForceNamed = TRUE]) 00929 00930 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00931 Created: 05/04/94 00932 Inputs: NewName - A StringBase which will be *copied* as this colours new name. 00933 NOTE that this name will be truncated to a maximum length of 63 characters, 00934 and any underscore characters within it will be converted to spaces 00935 00936 ForceNamed - if TRUE (the default), this forces the colour to become 'named' 00937 and will strip out underline characters from it. 00938 If FALSE (*use with care*) this will leave the colour in its current state, 00939 (i.e. won't make an unnamed colour named) and will retain underlines. This is 00940 only intended for use by importers for handling export/import of unnamed 00941 colours. 00942 00943 Purpose: To set the name of an IndexedColour. 00944 The name will be truncated to a maximum length of 63 characters. 00945 00946 Notes: Any underscore characters in the name will be converted to spaces, on the 00947 grounds that the export system uses underscores as a special name identifier 00948 to recognise unnamed colours. Suffice to say we just don't allow underscores 00949 00950 If NewName is NULL, or if we fail to allocate space for the name to 00951 be stored, the colour will revert to having no name. 00952 00953 Setting the name of an IndexedColour makes it a Named IndexedColour 00954 (Trust me, that is less silly than it sounds! ;-) 00955 00956 SeeAlso: IndexedColour::SetUnnamed; IndexedColour::IsNamed 00957 00958 ********************************************************************************************/ 00959 00960 void IndexedColour::SetName(const StringBase &NewName, BOOL ForceNamed) 00961 { 00962 if (ForceNamed) 00963 Info.IsNamed = TRUE; 00964 00965 if (Name == NULL) 00966 Name = new String_64; // If this fails, Name will just be NULL, which is safe 00967 00968 if (Name != NULL) 00969 { 00970 if (ForceNamed) 00971 { 00972 const TCHAR *Src = (const TCHAR *)NewName; 00973 TCHAR *Dest = (TCHAR *)(*Name); 00974 00975 // Copy up to 63 chars across 00976 camStrncpy(Dest, Src, 63); 00977 00978 // convert underscores into spaces 00979 Name->SwapChar(TCHAR('_'), TCHAR(' ')); 00980 } 00981 else 00982 { 00983 NewName.Left(Name, 63); // Truncate to 63 chars max, and copy 00984 } 00985 } 00986 } 00987 00988 00989 00990 /******************************************************************************************** 00991 00992 > void IndexedColour::SetUnnamed(void) 00993 00994 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00995 Created: 05/04/94 00996 00997 Purpose: To UNset the name of an IndexedColour, forcing it back to being Unnamed 00998 00999 ********************************************************************************************/ 01000 01001 void IndexedColour::SetUnnamed(void) 01002 { 01003 Info.IsNamed = FALSE; 01004 01005 if (Name != NULL) 01006 delete Name; 01007 01008 Name = NULL; 01009 } 01010 01011 01012 01013 /******************************************************************************************** 01014 01015 > BOOL IndexedColour::IsADescendantOf(IndexedColour *TestParent) 01016 01017 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01018 Created: 17/11/94 01019 Inputs: TestParent - the parent/ancestor colour we wish to test for 01020 Returns: TRUE if this is indeed a descendant of the given colour 01021 01022 Purpose: Recursively backtracks through the chain of LinkedParent links to determine 01023 if this colour is in any way (directly or indirectly) linked to the given 01024 Parent colour, and might therefore be affected by any change to said colour. 01025 01026 Notes: To determine if a colour is the *direct* parent of another, use 01027 if (TestParent == ThisColour->FindLinkedParent()) 01028 01029 If the TestParent is THIS colour, the return value is TRUE (i.e Yes, a change 01030 to the 'Parent' colour will affect 'this' colour!). {This is also an end-of- 01031 recursion clause} 01032 01033 This method only calculates descendant information for LINKED/TINT colours. 01034 Non-linked/tint colours will always spell the end of the search. 01035 01036 Is quite happy if TestParent is NULL - will always return FALSE in this case 01037 01038 ********************************************************************************************/ 01039 01040 BOOL IndexedColour::IsADescendantOf(IndexedColour *TestParent) 01041 { 01042 if (TestParent == NULL) // Silly test! Of course it's not! 01043 return(FALSE); 01044 01045 if (this == TestParent) // We are the colour being tested - we are related 01046 return(TRUE); 01047 // We cannot be descended, as we're a normal colour 01048 if (GetType() == COLOURTYPE_NORMAL || GetType() == COLOURTYPE_SPOT) 01049 return(FALSE); 01050 01051 if (ParentColour == NULL) // We have no parent, so cannot be descended from anything 01052 return(FALSE); 01053 // Ask our parent to check back in the family tree 01054 return(ParentColour->IsADescendantOf(TestParent)); 01055 } 01056 01057 01058 01059 /******************************************************************************************** 01060 01061 > IndexedColour *IndexedColour::FindLinkedParent(void) 01062 01063 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01064 Created: 12/10/94 01065 Returns: The colour upon which this Tint or Linked colour is based. 01066 (If this colour is not a Tint or Linked colour, or if it is a 01067 deleted (hidden for undo) colour, the return value is NULL) 01068 01069 Notes: If you need to know what colour this colour *was* linked to, as the 01070 colour editor does when the user is randomly plonking about with the 01071 colour type, then call FindLastLinkedParent instead. 01072 01073 Purpose: Finds the colour upon which a tint/based-on colour is based, if any. 01074 Can also be used to determine if a colour is a tint/basedon colour. 01075 01076 SeeAlso: IndexedColour::FindLastLinkedParent 01077 01078 ********************************************************************************************/ 01079 01080 IndexedColour *IndexedColour::FindLinkedParent(void) 01081 { 01082 if (IsDeleted()) 01083 return(NULL); 01084 01085 if (GetType() != COLOURTYPE_TINT && GetType() != COLOURTYPE_LINKED) 01086 return(NULL); 01087 01088 return(FindLastLinkedParent()); 01089 } 01090 01091 01092 01093 /******************************************************************************************** 01094 01095 > IndexedColour *IndexedColour::FindOldestAncestor(void) 01096 01097 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01098 Created: 20/6/96 01099 Returns: The utimate colour upon which this Tint or Linked colour is based. 01100 Note that if this colour has no parent, it will return itself! 01101 01102 Purpose: Finds the colour upon which a tint/based-on colour is based, if any. 01103 Can also be used to determine if a colour is a tint/basedon colour. 01104 01105 This is similar to FindLinkedParent, except it traverses all parent links 01106 until it finds the ultimate parent of the entire linked-colour tree 01107 in which this colour resides. 01108 01109 SeeAlso: IndexedColour::FindLinkedParent 01110 01111 ********************************************************************************************/ 01112 01113 IndexedColour *IndexedColour::FindOldestAncestor(void) 01114 { 01115 IndexedColour *Ptr = FindLinkedParent(); 01116 IndexedColour *Last = this; 01117 01118 while (Ptr != NULL) 01119 { 01120 Last = Ptr; 01121 Ptr = Ptr->FindLinkedParent(); 01122 } 01123 01124 return(Last); 01125 } 01126 01127 01128 01129 /******************************************************************************************** 01130 01131 > void IndexedColour::SetLinkedParent(IndexedColour *Parent, 01132 IndexedColourType NewType = COLOURTYPE_LINKED) 01133 01134 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01135 Created: 12/10/94 01136 Inputs: Parent - the new Linked/Tint parent IndexedColour, or 01137 NULL to remove any existing link 01138 01139 NewType - The ColourType to set this to. Note that for NORMAL/SPOT, the 01140 parent field must be NULL; For LINKED/TINT, it must point at a valid 01141 Named IndexedColour. If this is not the case, an ERROR3 will occur. 01142 01143 Purpose: To make a colour linked to or a tint of another colour. 01144 This links the colour to the parent. 01145 01146 Notes: Generally, the colour's colour model and definition will be unaffected. 01147 However, if the colour was previously linked/tint, and it is being made 01148 into a standalone colour, the existing linked colour definition will be 01149 read, and then placed into SourceColour as a standalone version of the 01150 previous linked definition. (i.e. the colour's appearance will not change 01151 but the link will be broken) 01152 01153 If the colour was not already a COLOURTYPE_LINKED when it is being made 01154 LINKED, all components will be set to override the parent. 01155 01156 If the colour was not already a COLOURTYPE_TINT when it is being made 01157 a TINT, it will be set to be a 100% tint (no tinting at all) 01158 01159 When making a COLOURTYPE_TINT colour, it will be a TINT, not a SHADE. 01160 To make a shade, make it COLOURTYPE_TINT then call SetTintOrShade(TRUE); 01161 If it was already a COLOURTYPE_TINT, the tint/shade state is unaffected. 01162 01163 The colour's output cache is flushed by this call 01164 01165 It is your responsibility to confirm overwriting the colour. It is also 01166 your responsibility to inform the system that this colour has changed, by 01167 calling ColourManager::ColourHasChanged 01168 01169 IMPORTANT NOTE: This method allows you to do things like making a colour 01170 'normal' (supposedly not linked), but still set a parent colour. This is 01171 a potentially dangerous practice so be very careful. (It is allowed so that 01172 the colour editor can cunningly remember what a colour was last linked 01173 to, in order to be far more helpful to the user). 01174 01175 Scope: private? Generally speaking, you should not be calling this method, unless 01176 you are the colour editor, or a load/import filter. 01177 01178 SeeAlso: IndexedColour::GetLinkedParent; IndexedColour::GetLastLinkedParent; 01179 IndexedColour::SetInheritsComponent; 01180 IndexedColour::SetType; IndexedColourType; 01181 ColourManager::ColourHasChanged 01182 01183 Errors: ERROR3 if you try to do anythign totally stupid (circular linking, 01184 linking to deleted colours, linking to unnamed colours, etc) 01185 01186 ********************************************************************************************/ 01187 01188 void IndexedColour::SetLinkedParent(IndexedColour *Parent, IndexedColourType NewType) 01189 { 01190 if (this == Parent) 01191 { 01192 ERROR3("Illegal attempt to make an IndexedColour Linked to itself"); 01193 return; 01194 } 01195 01196 if (Parent != NULL && Parent->IsADescendantOf(this)) 01197 { 01198 // Our new parent-to-be is already a linked child of us! 01199 ERROR3("Illegal attempt to generate circular reference in Colour linking"); 01200 return; 01201 } 01202 01203 if (Parent != NULL && !Parent->IsNamed()) 01204 { 01205 ERROR3("Illegal attempt to use UNNAMED IndexedColour as a linked parent"); 01206 return; 01207 } 01208 01209 if (Parent!= NULL && Parent->IsDeleted()) 01210 { 01211 ERROR3("Illegal attempt to use 'DELETED' IndexedColour as a linked parent"); 01212 return; 01213 } 01214 01215 01216 switch(NewType) 01217 { 01218 case COLOURTYPE_LINKED: 01219 if (GetType() != COLOURTYPE_LINKED) 01220 { 01221 Info.InheritComponent1 = // Override all components for now 01222 Info.InheritComponent2 = 01223 Info.InheritComponent3 = 01224 Info.InheritComponent4 = FALSE; 01225 } 01226 break; 01227 01228 01229 case COLOURTYPE_TINT: 01230 if (GetType() != COLOURTYPE_TINT) 01231 { 01232 SetType(NewType); // Set type now to stop the next call ENSURE'ing 01233 SetTintOrShade(FALSE); // Make it a real tint (not a shade "tint") 01234 SetTintValue(FIXED24(1.0)); // 100% tint (the colour) for now 01235 } 01236 01237 // Swapping from Tint to Shade (which are both COLOURTYPE_TINT will need to do this, 01238 // so we do it even if it is supposely chnaging to the same "type" 01239 if (Parent != NULL) 01240 Info.SourceColourModel = (UINT32) Parent->GetColourModel(); 01241 break; 01242 01243 01244 default: // COLOURTYPE_NORMAL, COLOURTYPE_SPOT 01245 if (FindLastLinkedParent() != NULL) 01246 { 01247 // If this was previously a tint/linked colour, then copy the resulting 01248 // colour definition into this colour to make it standalone again. 01249 01250 ColourGeneric NewSourceColour; 01251 GetSourceColour(&NewSourceColour); 01252 memcpy(&SourceColour, &NewSourceColour, sizeof(ColourGeneric)); 01253 } 01254 break; 01255 } 01256 01257 if (ParentColour != NULL) 01258 ParentColour->DecrementChildUsage(); 01259 01260 ParentColour = Parent; // Set the new linked/tint parent colour 01261 01262 if (ParentColour != NULL) 01263 ParentColour->IncrementChildUsage(); 01264 01265 InvalidateCache(); // Invalidate the output colour cache 01266 SetType(NewType); // And set the new type of the colour 01267 } 01268 01269 01270 01271 /******************************************************************************************** 01272 01273 > BOOL IndexedColour::SetType(IndexedColourType NewType) 01274 01275 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01276 Created: 1/11/94 01277 Returns: TRUE if this caused the type of this colour to be changed 01278 FALSE if the new type is the same as the old type 01279 01280 Purpose: Sets the type of this colour: 01281 MonoOn 01282 COLOURTYPE_NORMAL, COLOURTYPE_SPOT, COLOURTYPE_TINT, COLOURTYPE_LINKED 01283 MonoOff 01284 01285 Notes: If you wish to make a colour Linked or a Tint, then you should set its type 01286 at the same time as its parent-link in SetLinkedParent(). If you wish to 01287 make a linked/tint colour normal again, then you should also use 01288 SetLinkedParent. 01289 01290 On second thoughts, you shouldn't be calling this method! 01291 01292 Scope: private 01293 01294 SeeAlso: IndexedColour::SetType; IndexedColour::FindLinkedParent; 01295 IndexedColour::SetLinkedParent 01296 01297 ********************************************************************************************/ 01298 01299 BOOL IndexedColour::SetType(IndexedColourType NewType) 01300 { 01301 BOOL Result = (NewType != (IndexedColourType) Info.ColourType); 01302 01303 if ((INT32)NewType < 0 || (INT32)NewType > 3) 01304 { 01305 ERROR3("Attempt to set invalid colour type"); 01306 return(FALSE); 01307 } 01308 01309 Info.ColourType = (UINT32) NewType; 01310 01311 if (Result) // If the colour has changed, invalidate the output cache 01312 InvalidateCache(); 01313 01314 return(Result); 01315 } 01316 01317 01318 01319 /******************************************************************************************** 01320 01321 > BOOL IndexedColour::InheritsComponent(UINT32 ComponentID) 01322 01323 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01324 Created: 12/10/94 01325 Inputs: ComponentID: a number [1..4] indicating which component of the colour 01326 you wish to find out about. 01327 01328 Returns: TRUE if the component is inherited from the parent 01329 FALSE if the component overrides the parent, or if the colour isn't linked 01330 01331 Purpose: To determine if a given component of a colour is inherited from its linked 01332 parent colour. Always returns FALSE if a colour is not linked. 01333 01334 Notes: Should be used in conjunction with the appropriate ColourContext for this 01335 colour's colour model to determine if *valid* components of a colour are 01336 inherited from their parent colour. If asked about an invalid component, 01337 the result will be indeterminate (generally FALSE, but somebody may have 01338 set it to TRUE without checking if it is a valid component) 01339 01340 SeeAlso: IndexedColour::GetType(); ColourContext::GetComponentName; 01341 IndexedColour::SetInheritsComponent 01342 01343 ********************************************************************************************/ 01344 01345 BOOL IndexedColour::InheritsComponent(UINT32 ComponentID) 01346 { 01347 ERROR3IF(ComponentID < 1 || ComponentID > 4, 01348 "Bad colour component index passed to IndexedColour::InheritsComponent"); 01349 01350 if (GetType() == COLOURTYPE_LINKED) 01351 { 01352 switch(ComponentID) 01353 { 01354 case 1: 01355 return(Info.InheritComponent1); 01356 01357 case 2: 01358 return(Info.InheritComponent2); 01359 01360 case 3: 01361 return(Info.InheritComponent3); 01362 01363 case 4: 01364 return(Info.InheritComponent4); 01365 } 01366 } 01367 01368 return(FALSE); 01369 } 01370 01371 01372 01373 /******************************************************************************************** 01374 01375 > BOOL IndexedColour::SetInheritsComponent(UINT32 ComponentID, BOOL Inherits) 01376 01377 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01378 Created: 12/10/94 01379 Inputs: ComponentID: a number [1..4] indicating which component of the colour 01380 you wish to set inheritance information for. 01381 Inherits - TRUE if the component is to be inherited from the parent 01382 FALSE if the component is to override the parent 01383 01384 Returns: TRUE if this results in the stored value actually changing 01385 01386 Purpose: To set if a given component of a colour is inherited from its linked 01387 parent colour. 01388 01389 Errors: In a debug build, will give an ERROR3 if the colour is not linked 01390 or if the index given is out of range. 01391 In all builds, incorrect parameters will be ignored. 01392 01393 Notes: Should be used in conjunction with the appropriate ColourContext for this 01394 colour's colour model to determine if a component is *valid* before you 01395 try to set it. 01396 01397 SeeAlso: IndexedColour::GetType(); ColourContext::GetComponentName; 01398 IndexedColour::InheritsComponent 01399 01400 ********************************************************************************************/ 01401 01402 BOOL IndexedColour::SetInheritsComponent(UINT32 ComponentID, BOOL Inherits) 01403 { 01404 BOOL Result = FALSE; 01405 01406 ERROR3IF(ComponentID < 1 || ComponentID > 4, 01407 "Bad colour component index passed to IndexedColour::InheritsComponent"); 01408 01409 ERROR3IF(GetType() != COLOURTYPE_LINKED, 01410 "Attempt to set Component Inheritance for non-Linked colour"); 01411 01412 UINT32 ItInherits = (Inherits) ? 1 : 0; 01413 01414 if (GetType() == COLOURTYPE_LINKED) 01415 { 01416 switch(ComponentID) 01417 { 01418 case 1: 01419 Result = (Info.InheritComponent1 != ItInherits); 01420 Info.InheritComponent1 = ItInherits; 01421 break; 01422 01423 case 2: 01424 Result = (Info.InheritComponent2 != ItInherits); 01425 Info.InheritComponent2 = ItInherits; 01426 break; 01427 01428 case 3: 01429 Result = (Info.InheritComponent3 != ItInherits); 01430 Info.InheritComponent3 = ItInherits; 01431 break; 01432 01433 case 4: 01434 Result = (Info.InheritComponent4 != ItInherits); 01435 Info.InheritComponent4 = ItInherits; 01436 break; 01437 } 01438 } 01439 01440 if (Result) // If the colour has changed, invalidate the output cache 01441 InvalidateCache(); 01442 01443 return(Result); 01444 } 01445 01446 01447 01448 /******************************************************************************************** 01449 01450 > void IndexedColour::SetTintValue(FIXED24 NewTintValue) 01451 01452 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01453 Created: 17/11/94 01454 Inputs: NewTintValue - the new tint value, in the range 0.0 to 1.0 01455 Any value outside this range will be clipped to 0.0 or 1.0 01456 Outputs: - 01457 Returns: - 01458 Purpose: Sets a new tint value for a Tint colour. Will generate ENSURE failures in 01459 the debug build if the colour is not a tint 01460 01461 This also forces a Tint to be a true tint (not a shade) 01462 01463 Notes: Internally, tint is currently stored in the SourceColour.Component1 field. 01464 This should not be relied upon externally. 01465 01466 SeeAlso: IndexedColour::SetShadeValues 01467 01468 ********************************************************************************************/ 01469 01470 void IndexedColour::SetTintValue(FIXED24 NewTintValue) 01471 { 01472 if (GetType() != COLOURTYPE_TINT) 01473 { 01474 ERROR3("Your puny attempt to set the tint value for a non-tint colour has been ignored"); 01475 return; 01476 } 01477 01478 Info.InheritComponent1 = FALSE; // Force it to be a tint (not a shade) 01479 01480 if (NewTintValue <= FIXED24(0.0)) 01481 NewTintValue = 0; 01482 01483 if (NewTintValue >= FIXED24(1.0)) 01484 NewTintValue = FIXED24(1.0); 01485 01486 SourceColour.Component1 = NewTintValue; 01487 01488 InvalidateCache(); // The colour has changed, so invalidate the output cache 01489 } 01490 01491 01492 01493 /******************************************************************************************** 01494 01495 > FIXED24 IndexedColour::GetTintValue(void) const 01496 01497 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01498 Created: 17/11/94 01499 Inputs: - 01500 Outputs: - 01501 Returns: A FIXED24 value between 0.0 and 1.0 representing the Tint for this colour 01502 01503 Note that a spot colour returns 1.0 (a 100% tint - 100% ink density), and 01504 any process (non-spot/tint) colour returns 0.0 (a 0% tint, i.e. no ink). 01505 01506 Purpose: Gets the current Tint value for the colour. 01507 01508 NOTE that the returned tint value simply indicates how much this colour 01509 tints its parent colour (if at all). If you want to know how much ink will 01510 actually be produced for this colour, then you want to use 01511 GetAccumulatedTintValue() instead. 01512 01513 Notes: Internally, tint is currently stored in the SourceColour.Component1 field 01514 This should not be relied upon externally. 01515 01516 SeeAlso: IndexedColour::GetAccumulatedTintValue 01517 01518 ********************************************************************************************/ 01519 01520 FIXED24 IndexedColour::GetTintValue(void) const 01521 { 01522 if (GetType() == COLOURTYPE_SPOT) 01523 return(FIXED24(1.0)); // Spot colour is a 100% tint 01524 01525 if (GetType() != COLOURTYPE_TINT || TintIsShade()) 01526 return(FIXED24(0.0)); // Any process colour is a 0% tint 01527 01528 return(SourceColour.Component1); // Any tint is a (Tint)% tint 01529 } 01530 01531 01532 01533 /******************************************************************************************** 01534 01535 > FIXED24 IndexedColour::GetAccumulatedTintValue(void) const 01536 01537 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01538 Created: 20/6/96 01539 01540 Returns: A FIXED24 value between 0.0 and 1.0 representing the accumulated Tint for 01541 this colour. See Purpose for details. 01542 01543 Purpose: To determine the accumulated tint value of any colour. 01544 01545 If this is not a true tint colour, returns 0.0 (a 0% tint, i.e. white) 01546 01547 If this is a spot colour, returns 1.0 (i.e. 100% ink) 01548 01549 If this is a true tint of a spot ink, it returns the overall ink density 01550 that should be used. With a simple tint-of-spot tint, this is the normal 01551 tint value, but if there are a chain of tints, the tint values are 01552 cumulative, i.e. a 50% tint of a 50% tint of Red gives a _25%_ ink density. 01553 01554 Thus, if you apply the GetAccumulatedTintVlaue() to the GetOldestAncestor() 01555 colour, you will arrive at the right output colour. (This isn't actually 01556 how screen values for tints are produced, but the cumulative tint is used 01557 when mixing tints in blends, and most importantly when outputting separated 01558 Spot ink plates! 01559 01560 Notes: The cumulative value is simply the tint values of each colour in turn in the 01561 parent-colour chain multiplied together (where process colours are treated 01562 as a tint value of 0.0 and the ultimate spot colour is 1.0) 01563 01564 ********************************************************************************************/ 01565 01566 FIXED24 IndexedColour::GetAccumulatedTintValue(void) 01567 { 01568 double Tint = 1.0; 01569 IndexedColour *Ptr = this; 01570 01571 while (Ptr != NULL && Tint > 0.0) 01572 { 01573 Tint *= Ptr->GetTintValue().MakeDouble(); 01574 01575 Ptr = Ptr->FindLinkedParent(); 01576 } 01577 01578 return(FIXED24(Tint)); 01579 } 01580 01581 01582 01583 /******************************************************************************************** 01584 01585 > void IndexedColour::SetShadeValues(FIXED24 NewShadeValueX, FIXED24 NewShadeValueY) 01586 01587 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01588 Created: 24/8/95 01589 Inputs: NewShadeValueX - the new Shade Saturation value, in the range -1.0 to 1.0 01590 NewShadeValueY - the new Shade Brightness value, in the range -1.0 to 1.0 01591 Outputs: - 01592 Returns: - 01593 Purpose: Sets new shade values for a Shade colour. Will generate ENSURE failures in 01594 the debug build if the colour is not a Tint/Shade 01595 01596 This also forces a Tint to be a shade (not a true tint) 01597 01598 Notes: Internally, tint/shade is currently stored in the SourceColour.Component1 field. 01599 And now the Component2 field as well. Bodgy city dude. 01600 This should not be relied upon externally. 01601 01602 SeeAlso: IndexedColour::SetTintValue 01603 01604 ********************************************************************************************/ 01605 01606 void IndexedColour::SetShadeValues(FIXED24 NewShadeValueX, FIXED24 NewShadeValueY) 01607 { 01608 if (GetType() != COLOURTYPE_TINT) 01609 { 01610 ERROR3("Your puny attempt to set the shade values for a non-shade colour has been ignored"); 01611 return; 01612 } 01613 01614 Info.InheritComponent1 = TRUE; // Force it to be a shade 01615 01616 01617 if (NewShadeValueX <= FIXED24(-1.0)) 01618 NewShadeValueX = FIXED24(-1.0); 01619 01620 if (NewShadeValueX >= FIXED24(1.0)) 01621 NewShadeValueX = FIXED24(1.0); 01622 01623 SourceColour.Component1 = NewShadeValueX; 01624 01625 01626 if (NewShadeValueY <= FIXED24(-1.0)) 01627 NewShadeValueY = FIXED24(-1.0); 01628 01629 if (NewShadeValueY >= FIXED24(1.0)) 01630 NewShadeValueY = FIXED24(1.0); 01631 01632 SourceColour.Component2 = NewShadeValueY; 01633 01634 01635 InvalidateCache(); // The colour has changed, so invalidate the output cache 01636 } 01637 01638 01639 01640 /******************************************************************************************** 01641 01642 > FIXED24 IndexedColour::GetShadeValueX(void) const 01643 01644 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01645 Created: 24/8/95 01646 Inputs: - 01647 Outputs: - 01648 Returns: A FIXED24 value between -1.0 and 1.0 representing the Shade for this colour 01649 This value is the half of the shading settings for affecting Saturation 01650 (If the colour is not a Tint/Shade, debug builds will ENSURE, and all builds will 01651 return 1.0 (a 100% shade)) 01652 01653 Purpose: Gets the current Shade Saturation value for the colour 01654 01655 Notes: Internally, tint/shade is currently stored in the SourceColour.Component1 field 01656 And now the Component2 field as well. Bodgy city dude. 01657 This should not be relied upon externally. 01658 01659 ********************************************************************************************/ 01660 01661 FIXED24 IndexedColour::GetShadeValueX(void) const 01662 { 01663 if (GetType() != COLOURTYPE_TINT || !Info.InheritComponent1) 01664 { 01665 ERROR3("Attempt to read tint value for a non-shade colour"); 01666 return(FIXED24(1.0)); 01667 } 01668 01669 return(SourceColour.Component1); 01670 } 01671 01672 01673 01674 /******************************************************************************************** 01675 01676 > FIXED24 IndexedColour::GetShadeValueY(void) const 01677 01678 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01679 Created: 24/8/95 01680 Inputs: - 01681 Outputs: - 01682 Returns: A FIXED24 value between -1.0 and 1.0 representing the Shade for this colour 01683 This value is the half of the shading settings for affecting Brightness 01684 (If the colour is not a Tint/Shade, debug builds will ENSURE, and all builds will 01685 return 1.0 (a 100% shade)) 01686 01687 Purpose: Gets the current Shade Brightness value for the colour 01688 01689 Notes: Internally, tint/shade is currently stored in the SourceColour.Component1 field 01690 And now the Component2 field as well. Bodgy city dude. 01691 This should not be relied upon externally. 01692 01693 ********************************************************************************************/ 01694 01695 FIXED24 IndexedColour::GetShadeValueY(void) const 01696 { 01697 if (GetType() != COLOURTYPE_TINT || !Info.InheritComponent1) 01698 { 01699 ERROR3("Attempt to read tint value for a non-shade colour"); 01700 return(FIXED24(1.0)); 01701 } 01702 01703 return(SourceColour.Component2); 01704 } 01705 01706 01707 01708 /******************************************************************************************** 01709 01710 > void IndexedColour::SetTintOrShade(BOOL IsATint) 01711 01712 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01713 Created: 24/8/95 01714 01715 Inputs: IsATint - TRUE to make this Tint a true Tint, FALSE to make it a Shade 01716 01717 Purpose: Sets a COLOURTYPE_TINT colour to be either a Tint (fade-to-white) or 01718 a shade (fade-to-black) colour. The tint/shade fraction is unchnaged (the 01719 colour will just toggle between being darker and lighter!) 01720 01721 Notes: Internally, tint/shade is currently stored in the SourceColour.Component1 field 01722 This should not be relied upon externally. 01723 01724 ********************************************************************************************/ 01725 01726 void IndexedColour::SetTintOrShade(BOOL IsATint) 01727 { 01728 if (GetType() != COLOURTYPE_TINT) 01729 { 01730 ERROR3("Attempt to set tint/shade value for a non-tint colour"); 01731 return; 01732 } 01733 01734 Info.InheritComponent1 = IsATint ? 1 : 0; 01735 } 01736 01737 01738 01739 /******************************************************************************************** 01740 01741 > BOOL IndexedColour::TintIsShade(void) const 01742 01743 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01744 Created: 24/8/95 01745 01746 Returns: TRUE if this COLOURTYPE_TINT colour is a true Tint, FALSE if it's a Shade 01747 01748 Purpose: Determines if a COLOURTYPE_TINT colour is really a tint or a shade 01749 01750 Notes: COLOURTYPE_TINT has two "subtypes" (tint-to white (tint) and tint-to-black 01751 (shade)). These are differentiated by a single flag, and are otherwise 01752 implemented identically. Thus, if it's type is "Tint" then it could be a 01753 shade! (Nasty, but gets around a shortage of flag bits, and also allows 01754 us to continue using screeds of old code which doesn't know the difference 01755 between tints and shades and doesn't need to know) 01756 01757 Internally, tint/shade is currently stored in the SourceColour.Component1 field 01758 This should not be relied upon externally. 01759 01760 ********************************************************************************************/ 01761 01762 BOOL IndexedColour::TintIsShade(void) const 01763 { 01764 if (Info.ColourType != COLOURTYPE_TINT) 01765 { 01766 ERROR3("TintIsShade() called for non-tint/shade colour"); 01767 return(FALSE); 01768 } 01769 01770 return(Info.InheritComponent1); 01771 } 01772 01773 01774 01775 /******************************************************************************************** 01776 01777 > void IndexedColour::SwapWith(IndexedColour *Other) 01778 01779 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01780 Created: 14/6/94 01781 Inputs: Other - The colour to swap with 01782 Outputs: - 01783 Returns: - 01784 Purpose: This swaps the definitions of the two IndexedColours. 01785 01786 Notes: This is used to provide undo/redo via the OpColourChange defined 01787 in colormgr.cpp/.h, as when we undo a change to an IndexedColour, 01788 the definition must remain at the same memory address so that all 01789 references to it in the document do not need to be fixed. 01790 01791 The implementation swaps the Info, SourceColour, & Name fields 01792 (i.e. the colour definition) ONLY. That is, the usage count for 01793 each object and the caches are not swapped. The caches for both 01794 colours are in fact flushed, to guarantee their integrity. 01795 01796 ********************************************************************************************/ 01797 01798 #define JASONSWAP(X,Y,VARTYPE) \ 01799 { \ 01800 VARTYPE T; \ 01801 memcpy(&(T), &(X), sizeof(VARTYPE)); \ 01802 memcpy(&(X), &(Y), sizeof(VARTYPE)); \ 01803 memcpy(&(Y), &(T), sizeof(VARTYPE)); \ 01804 } 01805 01806 void IndexedColour::SwapWith(IndexedColour *Other) 01807 { 01808 // Components to copy are: 01809 // Info 01810 // SourceColour 01811 // ParentColour pointer 01812 // Name POINTER 01813 // CachedColour -- We are discarding the cache anyway so ignore 01814 // UsageCount -- We wish to keep the usage counts intact, as it is 01815 // ChildUsage the number of refs to THIS object. 01816 // Thus, only the first 4 in this list are copied. 01817 01818 JASONSWAP(Info, Other->Info, IndexedColourInfo); 01819 JASONSWAP(SourceColour, Other->SourceColour, ColourGeneric); 01820 01821 // Swap the Name POINTER 01822 String_64 *NameTemp = Name; 01823 Name = Other->Name; 01824 Other->Name = NameTemp; 01825 01826 // Swap the linked/tint Parent Colour pointer 01827 IndexedColour *ParentTemp = ParentColour; 01828 ParentColour = Other->ParentColour; 01829 Other->ParentColour = ParentTemp; 01830 01831 // And invalidate the caches just to be on the safe side 01832 Info.CacheColourModel = Other->Info.CacheColourModel = COLOURMODEL_NOTCACHED; 01833 Info.OCContextHandle = Other->Info.OCContextHandle = 0; 01834 } 01835 01836 #undef JASONSWAP 01837 01838 01839 01840 /******************************************************************************************** 01841 01842 > void IndexedColour::GetDebugDetails(StringBase* Str) 01843 01844 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01845 Created: 4/5/94 01846 Inputs: Str - string to receive the debug details 01847 Outputs: - 01848 Returns: - 01849 Purpose: To get information on this colour for display in the Debug Tree 01850 Errors: - 01851 01852 ********************************************************************************************/ 01853 01854 void IndexedColour::GetDebugDetails(StringBase* Str) 01855 { 01856 String_256 TempStr; 01857 ColourContext *cc = ColourContext::GetGlobalDefault(GetColourModel()); 01858 ColourGeneric col; 01859 01860 String_8 UnnamedString(TEXT("N")); 01861 if (!IsNamed()) 01862 UnnamedString = TEXT("U"); 01863 01864 GetSourceColour(&col); 01865 01866 String_32 ModelName; 01867 cc->GetModelName(&ModelName); 01868 01869 String_32 Type(TEXT("")); 01870 switch(GetType()) 01871 { 01872 case COLOURTYPE_SPOT: 01873 Type._MakeMsg(TEXT(" Spot")); 01874 break; 01875 01876 case COLOURTYPE_TINT: 01877 if (TintIsShade()) 01878 TempStr._MakeMsg( TEXT(" Shade, resulting in")); 01879 else 01880 TempStr._MakeMsg( TEXT(" #1%ld% Tint, resulting in"), 01881 (INT32) (GetTintValue().MakeDouble()*100)); 01882 break; 01883 01884 case COLOURTYPE_LINKED: 01885 Type._MakeMsg(TEXT(" Linked, resulting in")); 01886 break; 01887 01888 default: 01889 break; 01890 } 01891 01892 01893 TempStr._MakeMsg( TEXT(" #1%sIxCol (#2%s) =#3%s #4%s(#5%ld, #6%ld, #7%ld, #8%ld)\r\n"), 01894 (TCHAR *) UnnamedString, 01895 (TCHAR *) *(GetName(TRUE)), 01896 (TCHAR *) Type, 01897 (TCHAR *) ModelName, 01898 (INT32) (col.Component1.MakeDouble()*100), 01899 (INT32) (col.Component2.MakeDouble()*100), 01900 (INT32) (col.Component3.MakeDouble()*100), 01901 (INT32) (col.Component4.MakeDouble()*100)); 01902 01903 (*Str) += TempStr; 01904 } 01905 01906 01907 01908 /******************************************************************************************** 01909 01910 > static void IndexedColour::ForceSpotsToBeProcess(BOOL ForceOn) 01911 01912 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01913 Created: 26/8/96 01914 01915 Inputs: ForceOn - TRUE to force spots to process, FALSE to let them be spots 01916 01917 Purpose: To set the global colour flag. When the flag is TRUE, all spot colours 01918 in the entire program are forced to act as "normal" colours; when set 01919 FALSE, all spot colours behave normally. 01920 01921 Notes: In many ways this would be better as a localised option, at least 01922 limited to the selected document, but this is much more difficult to 01923 achieve, and anyway, it's better that spot colours are effectively 01924 disabled by this flag, so that it becomes obvious that spot colours 01925 are no longer special. 01926 01927 This calls ColourManager::SelViewContextHasChanged() to make all 01928 the appropriate colour interfaces update themselves correctly. 01929 (Yeah, it's not quite the right name for what the message does, 01930 but this is just as fundamental a change as context changing) 01931 01932 ********************************************************************************************/ 01933 01934 void IndexedColour::ForceSpotsToBeProcess(BOOL ForceOn) 01935 { 01936 SpotsAreProcess = ForceOn; 01937 ColourManager::SelViewContextHasChanged(); 01938 } 01939