00001 // $Id: colcontx.cpp 1402 2006-07-04 09:26:38Z 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 // colcontx.cpp - ColourContext and derived classes 00099 00100 /* 00101 */ 00102 00103 00104 #include "camtypes.h" 00105 00106 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00107 #include "colcontx.h" 00108 #include "colormgr.h" 00109 #include "colourix.h" 00110 #include "colplate.h" 00111 //#include "doccolor.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00112 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00113 //#include "jason.h" 00114 //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00115 #include "scunit.h" 00116 00117 #if defined(EXCLUDE_FROM_RALPH) || defined(EXCLUDE_FROM_XARALX) 00118 #undef NO_XARACMS 00119 #define NO_XARACMS 00120 #endif 00121 00122 #ifndef NO_XARACMS 00123 #include "xaracms.h" 00124 #endif 00125 00126 CC_IMPLEMENT_MEMDUMP(ColourContext, ListItem) 00127 CC_IMPLEMENT_MEMDUMP(ColourContextRGBT, ColourContext) 00128 CC_IMPLEMENT_MEMDUMP(ColourContextWebRGBT, ColourContextRGBT) 00129 CC_IMPLEMENT_MEMDUMP(ColourContextCMYK, ColourContext) 00130 CC_IMPLEMENT_MEMDUMP(ColourContextHSVT, ColourContext) 00131 CC_IMPLEMENT_MEMDUMP(ColourContextGreyT, ColourContext) 00132 00133 #define new CAM_DEBUG_NEW 00134 00135 /* NOTE WELL ALL YE WHO ENTER HERE 00136 * 00137 * If you are implementing a new context class, have a look at the implementation 00138 * of RGBT, which is a simple base model. Note that you may also find it useful 00139 * to look at CMYK, as it overrides the ConvertColourInternal to do special stuff. 00140 */ 00141 00142 00143 00144 /* DefaultColourContexts 00145 * 00146 * This is a 'global' array of default colour contexts for each of the 00147 * possible 16 colour models Camelot can support. When defining/converting 00148 * colours, a default colour context is implicitly specified, if no colour 00149 * context is given. 00150 * Access is via the static function ColourContext::GetDefault() 00151 */ 00152 00153 ColourContextArray ColourContext::GlobalDefaultContext = 00154 { 00155 { NULL, NULL, NULL, NULL, 00156 NULL, NULL, NULL, NULL, 00157 NULL, NULL, NULL, NULL, 00158 NULL, NULL, NULL, NULL } 00159 }; 00160 00161 00162 00163 /* NextColourContextHandle 00164 * 00165 * This variable keeps track of the current handle - each colour context must have a 00166 * unique handle - this is used in colour caches to identify the context in which 00167 * they are currently cached, so that they know when the cache is invalid. 00168 */ 00169 00170 ColourContextHandle ColourContext::NextColourContextHandle = 1; 00171 00172 00173 00174 00175 /******************************************************************************************** 00176 00177 > void ColourContext::ColourContext(View *Scope) 00178 00179 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00180 Created: 31/03/94 00181 Inputs: Scope - The view within which this context is to be used, or NULL 00182 for a global (non-view-specific) context 00183 Outputs: - 00184 Returns: - 00185 Purpose: Constructor for a Colour context. This is shared code used by 00186 all derived ColourContextXXXX classes. You cannot create 00187 vanilla ColourContext objects (virtual functions abound) 00188 00189 Notes: The usage count for a colour context defaults to 0 00190 ("not in use"). When using colour contexts, you should always 00191 register them with the global ColContextList object (see 00192 ColourContextList::AddContext for details) 00193 00194 When created, relevant conversion parameters (gamma correction 00195 etc) are passed in to the constructor.The context stores these 00196 parameters so it can quickly compare itself to another context, 00197 but it may defer creation of tables and other essential stuff 00198 until the Init() function is called (when it is added to the 00199 list of available colour contexts). Nobody but the context list 00200 can call the Init() function. 00201 00202 The passed-in Scope may be NULL, in which case global scope is 00203 used. However, if you're using this within the scope of any 00204 view, note that you must set up ScopeView properly or colour 00205 separated output of some colour models will be incorrect. 00206 00207 Errors: - 00208 SeeAlso: ColourContextRGBT::ColourContextRGBT; 00209 ColourContextCMYK::ColourContextCMYK; 00210 ColourContextHSVT::ColourContextHSVT; 00211 ColourContextList::AddContext 00212 00213 ********************************************************************************************/ 00214 00215 ColourContext::ColourContext(View *Scope) 00216 { 00217 MyHandle = NextColourContextHandle++; 00218 00219 ScopeView = Scope; 00220 00221 UsageCount = 0; 00222 00223 ColPlate = NULL; 00224 00225 PORTNOTE("other","Removed HCMTRANSFORM usage") 00226 #ifndef EXCLUDE_FROM_XARALX 00227 CMSTransform = NULL; 00228 #endif 00229 // ColourModel and Model-specific data must be dealt with in the 00230 // constructor/Init() for the derived ColourContextXXXX class 00231 } 00232 00233 00234 00235 /******************************************************************************************** 00236 00237 > void ColourContext::~ColourContext(void) 00238 00239 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00240 Created: 31/03/94 00241 00242 Purpose: Colour context destructor 00243 00244 Notes: This destroys any attached ColourPlate descriptor 00245 00246 SeeAlso: ColourContextList::AddContext 00247 00248 ********************************************************************************************/ 00249 00250 ColourContext::~ColourContext() 00251 { 00252 ENSURE(UsageCount == 0, "ColourContext deleted while still in use!"); 00253 00254 if (ColPlate != NULL) 00255 { 00256 delete ColPlate; 00257 ColPlate = NULL; 00258 } 00259 00260 #ifndef NO_XARACMS 00261 if (CMSTransform != NULL) 00262 { 00263 if (GetApplication()->GetCMSManager() != NULL) 00264 GetApplication()->GetCMSManager()->DestroyTransform(CMSTransform); 00265 CMSTransform = NULL; 00266 } 00267 #endif 00268 } 00269 00270 00271 00272 /******************************************************************************************** 00273 00274 > BOOL ColourContext::Init(void) 00275 00276 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00277 Created: 11/04/94 00278 Inputs: - 00279 Outputs: - 00280 Returns: TRUE if it succeeds 00281 FALSE if it fails (and it'll set an error description) 00282 Purpose: Colour context initialiser. This is called by the ColourContextList 00283 when it wishes to add a context to the list, and makes the context 00284 ready for use. This allows the list to compare contexts, and only 00285 initialise a given context when it knows the initialisation is 00286 absolutely necessary (e.g. allocating a large chunk of memory or 00287 calculating a complex table is avoided until we are sure there are 00288 no equivalent contexts already available) 00289 This function is overridden by colour contexts which actually need to 00290 do some initialisation other than just storing a few values away. 00291 Errors: - 00292 SeeAlso: ColourContextList::AddContext 00293 00294 ********************************************************************************************/ 00295 00296 BOOL ColourContext::Init(void) 00297 { 00298 ENSURE(UsageCount == 0, "ColourContext initialised when in use?!?!"); 00299 00300 IncrementUsage(); // We are now in use. UsageCount is now 1 00301 return(TRUE); // Initialisation succeeded 00302 } 00303 00304 00305 00306 /******************************************************************************************** 00307 00308 > void ColourContext::DecrementUsage(void) 00309 00310 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00311 Created: 31/03/94 00312 Inputs: - 00313 Outputs: - 00314 Returns: TRUE if the object is still in use 00315 Purpose: Decrements usage-count for a colour context. This count allows us to 00316 determine when we can delete unused contexts. 00317 00318 Notes: The usage count for a colour context defaults to 0 00319 ("not in use"). When using colour contexts, you should always 00320 register them with the global ColContextList object (see 00321 ColourContextList::AddContext for details) 00322 00323 Errors: ENSURE fails if the usage count goes negative, indicating the context 00324 is being 'released' more times than it is 'claimed'. 00325 SeeAlso: ColourContext::IncrementUsage; ColourContextList::AddContext 00326 00327 ********************************************************************************************/ 00328 00329 BOOL ColourContext::DecrementUsage(void) 00330 { 00331 ENSURE(UsageCount > 0, "ColourContext::DecrementUsage - Usage count is negative!"); 00332 return((--UsageCount) != 0); 00333 } 00334 00335 00336 00337 /******************************************************************************************** 00338 00339 > virtual void ColourContext::PackColour(ColourGeneric *Source, ColourPacked *Result) 00340 00341 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00342 Created: 31/03/94 00343 Inputs: Source - A ColourGeneric structure defining the colour in the model 00344 pertaining to this colour context. 00345 Result - A Packed colour structure in the same model, into which the result 00346 is copied. 00347 00348 Outputs: - 00349 Returns: - 00350 Purpose: Converts 128-bit colour representation to 32-bit packed form 00351 00352 Notes: This function operates on the colour using a generic component pattern 00353 Colours such as ColourHSVT do not conform to this pattern and thus must 00354 be unpacked with derived methods (ColourContextHSVT::UnpackColour) 00355 However, this function will work on any 4-component model which uses 8bits 00356 and 32-bits respectively for all 4 components, and the same 8.24 fixedpoint 00357 32-bit representation. 00358 00359 Scope: Private (used internally by friend class DocColour) 00360 Errors: - 00361 SeeAlso: ColourContext::UnpackColour 00362 00363 ********************************************************************************************/ 00364 00365 void ColourContext::PackColour(ColourGeneric *Source, ColourPacked *Result) 00366 { 00367 PColourGeneric *bob = (PColourGeneric *) Result; 00368 00369 bob->Component1 = PackColour256(Source->Component1); 00370 bob->Component2 = PackColour256(Source->Component2); 00371 bob->Component3 = PackColour256(Source->Component3); 00372 bob->Component4 = PackColour256(Source->Component4); 00373 } 00374 00375 00376 00377 00378 /******************************************************************************************** 00379 00380 > virtual void ColourContext::UnpackColour(ColourPacked *Source, ColourGeneric *Result) 00381 00382 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00383 Created: 31/03/94 00384 Inputs: Source - A Packed Colour structure defining the colour in the model 00385 pertaining to this colour context. 00386 Result - A ColourGeneric structure in the same model, into which the 00387 result is copied. 00388 Outputs: - 00389 Returns: - 00390 Purpose: Converts 32-bit packed colour representation to 128-bit form 00391 00392 Notes: This function operates on the colour using a generic component pattern 00393 Colours such as ColourHSVT do not conform to this pattern and thus must 00394 be unpacked with derived methods (ColourContextHSVT::UnpackColour) 00395 However, this function will work on any 4-component model which uses 8bits 00396 and 32-bits respectively for all 4 components, and the same 8.24 fixedpoint 00397 32-bit representation. 00398 00399 Scope: Private (used internally by friend class DocColour) 00400 Errors: - 00401 SeeAlso: ColourContext::PackColour 00402 00403 ********************************************************************************************/ 00404 00405 void ColourContext::UnpackColour(ColourPacked *Source, ColourGeneric *Result) 00406 { 00407 PColourGeneric *bob = (PColourGeneric *) Source; 00408 00409 UnpackColour256(bob->Component1, &Result->Component1); 00410 UnpackColour256(bob->Component2, &Result->Component2); 00411 UnpackColour256(bob->Component3, &Result->Component3); 00412 UnpackColour256(bob->Component4, &Result->Component4); 00413 } 00414 00415 00416 00417 /******************************************************************************************** 00418 00419 > virtual BOOL ColourContext::IsDifferent(ColourContext *Other) const 00420 00421 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00422 Created: 13/04/94 00423 Inputs: Other - a colour context to compare ourselves to 00424 Outputs: - 00425 Returns: TRUE if the other colour context object is different from 00426 ourself, or FALSE if it is an exactly equivalent context. 00427 Purpose: Determine if two colour contexts are not exactly equivalent 00428 Errors: - 00429 SeeAlso: - 00430 00431 ********************************************************************************************/ 00432 00433 00434 BOOL ColourContext::IsDifferent(ColourContext *Other) const 00435 { 00436 if (Other == this) 00437 return(FALSE); // Different object? (Nope) 00438 00439 if (Other->ScopeView != ScopeView) 00440 return(TRUE); // Different Scope Views? 00441 00442 return(Other->ColModel != ColModel); // Different Colour Model? 00443 } 00444 00445 00446 00447 00448 /******************************************************************************************** 00449 00450 > virtual void ColourContext::ConvertColourBase(ColourContext *SourceContext, 00451 ColourGeneric *Source, ColourGeneric *Result 00452 IndexedColour *SourceIxCol = NULL) 00453 00454 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00455 Created: 31/03/94 00456 Inputs: SourceContext - The context in which the source is defined 00457 00458 Source - A ColourGeneric to convert 00459 00460 Result - A ColourGeneric structure to recieve the resulting converted colour, 00461 as defined in this ColourContext. 00462 00463 SourceIxCol - NULL, or a pointer to the IndexedColour we are converting. 00464 This is used only for handling spot colour separations, to determine if 00465 the colour is a given spot colour or tint thereof. 00466 00467 Outputs: Result - will be returned with the converted colour 00468 00469 Purpose: Converts a Colour into this colour context, from the default colour context 00470 implied by the given colour model 00471 Post-processing (as described by the attached ColourPlate object) will 00472 be applied to generate colour separations (etc) as required. 00473 00474 The converted colour will be supplied from a cache where possible 00475 00476 Notes: It is up to the caller to update caches etc if necessary 00477 This is used as a base on which ConvertColourInternal methods are built 00478 00479 ColourContextCMYK overrides this base class method to provide direct 00480 passthrough of CMYK colours into a CMYK output context. (passthrough 00481 otherwise only occurs if the source & destination contexts are the 00482 same object) 00483 00484 Scope: private to colcontx.cpp 00485 Errors: - 00486 SeeAlso: ColourContext::ConvertColour 00487 00488 ********************************************************************************************/ 00489 00490 void ColourContext::ConvertColourBase(ColourContext *SourceContext, 00491 ColourGeneric *Source, ColourGeneric *Result, 00492 IndexedColour *SourceIxCol) 00493 { 00494 #ifndef NO_XARACMS 00495 // Last minute bodge for Composite preview of CMYK colours in RGB space 00496 // This is done here cos it's much faster, and gets around pre/post filter problems 00497 // with CMYK colours which aren't IndexedColours (like intermediate blend/gradfill DocColours) 00498 if (ColPlate != NULL && ColPlate->GetType() == COLOURPLATE_COMPOSITE && 00499 GetColourModel() == COLOURMODEL_RGBT && 00500 SourceContext->GetColourModel() == COLOURMODEL_CMYK) 00501 { 00502 // If it's a CMYK colour, then it's already in printer gamut, so we only apply 00503 // the backward colour correction factor to it. 00504 // Note that this means we chuck away the normal colour conversion system! 00505 XaraCMS* lpCMSMan = GetApplication()->GetCMSManager(); 00506 if (lpCMSMan != NULL) 00507 { 00508 ColourCMYK Def; 00509 memcpy(&Def, Source, sizeof(ColourGeneric)); 00510 00511 lpCMSMan->ConvertColourForPaperView(&Def, (ColourRGBT *) Result); 00512 return; 00513 } 00514 } 00515 #endif 00516 00517 // Copy the source colour into a temporary variable 00518 ColourGeneric FilteredSource; 00519 memcpy(&FilteredSource, Source, sizeof(ColourGeneric)); 00520 00521 // Call the SourceContext to allow it to pre-filter the colour. This is used to 00522 // provide colour separations and other doody features when converting CMYK colours 00523 // - when converting non-CMYK colours, this is usually done in the OutputFilter (below) 00524 if (ColPlate != NULL && !ColPlate->IsDisabled()) 00525 SourceContext->ApplyInputFilter(ColPlate, this, &FilteredSource, SourceIxCol); 00526 00527 // ----- 00528 // Call levels expected: 00529 // 1 inline ConvertColour checks if can satisfy from cache 00530 // 2 function ConvertColourInternal does any short cuts it can, such 00531 // as CMYK->CMYK passthrough 00532 // 3 Call ConvertColourBase, which 00533 // a) Checks if in same colour model, and implements passthrough, or 00534 // b) Converts colour properly via CIET space 00535 00536 if (SourceContext == this) 00537 { 00538 // The SourceContext and Destination context are identical, so we can 00539 // just copy the definition directly across. 00540 memcpy(Result, &FilteredSource, sizeof(ColourGeneric)); 00541 } 00542 else 00543 { 00544 DColourCIET IntermediateResult; 00545 00546 SourceContext->ConvertToCIET(&FilteredSource, &IntermediateResult); 00547 ConvertFromCIET(&IntermediateResult, Result); 00548 } 00549 00550 00551 // Call the DestinationContext (derived class of this) to apply any output filtering - 00552 // non-CMYK colour conversions will separate the colour (as appropriate) here 00553 if (ColPlate != NULL && !ColPlate->IsDisabled()) 00554 ApplyOutputFilter(ColPlate, SourceContext, Result, SourceIxCol); 00555 } 00556 00557 00558 00559 00560 /******************************************************************************************** 00561 00562 > void ColourContext::ConvertColourInternal(DocColour *Source, ColourGeneric *Result) 00563 00564 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00565 Created: 31/03/94 00566 Inputs: Source - A Colour to convert 00567 Result - A ColourGeneric structure to recieve the resulting converted colour, 00568 as defined in this ColourContext. 00569 Outputs: - 00570 Returns: - 00571 Purpose: Converts a Colour into this colour context. 00572 The converted colour will be supplied from a cache where possible 00573 00574 Notes: This is used internally. It is only called by the inlined conversion 00575 functions if they fail to return a cached result 00576 Errors: - 00577 SeeAlso: ColourContext::ConvertColour 00578 00579 ********************************************************************************************/ 00580 00581 void ColourContext::ConvertColourInternal(DocColour *Source, ColourGeneric *Result) 00582 { 00583 if (Source->Info.SourceColourModel == COLOURMODEL_INDEXED) 00584 { 00585 IndexedColour *SrcIndexed = Source->SourceColour.Indexed.Colour; 00586 00587 // Convert the indexed colour to our context 00588 ConvertColour(SrcIndexed, Result); 00589 00590 // If IndexedColour, we do NOT want the colour cached at the DocColour 00591 // level (else if the IxCol changes, we'd have to search for all related 00592 // DocCols to fix their caches... erg!) 00593 return; 00594 } 00595 00596 // Unpack the 32-bit colour into a 128-bit structure, and then invoke the 00597 // shared internal conversion routine. 00598 ColourGeneric SourceDefn; 00599 00600 // If this DocColour should not be separated (it's a UI colour), then disable 00601 // any active colour plate to stop it separating the output - we'll save and restore 00602 // its previous state around the call to ConvertColourBase 00603 BOOL WasDisabled = TRUE; 00604 if (ColPlate != NULL) 00605 { 00606 WasDisabled = ColPlate->IsDisabled(); 00607 ColPlate->SetDisabled(!Source->IsSeparable()); 00608 } 00609 00610 // Check if we're doing a spot colour plate. We either get the colour's source colour, 00611 // or if it shouldn't appear on the plate, we get White. 00612 if (ColPlate != NULL && !ColPlate->IsDisabled() && ColPlate->GetType() == COLOURPLATE_SPOT) 00613 { 00614 // We're doing a SPOT colour plate, but this colour is a local DocColour, so 00615 // it cannot possibly be a tint on this plate, so we just return white. 00616 GetGlobalDefault(Source->GetColourModel())->GetWhite(&SourceDefn); 00617 } 00618 else 00619 { 00620 // Unpack the colour 00621 GetGlobalDefault(Source->GetColourModel())->UnpackColour(&Source->SourceColour, &SourceDefn); 00622 } 00623 00624 // Assume that the source context is a global default. Generally, this should be true, 00625 // as all source colours should be defined in terms of logical colour models. 00626 ConvertColourBase(GetGlobalDefault(Source->GetColourModel()), 00627 &SourceDefn, Result); 00628 00629 // And restore the previous ColourPlate "disabled" state 00630 if (ColPlate != NULL) 00631 ColPlate->SetDisabled(WasDisabled); 00632 00633 PackColour(Result, &Source->CachedColour); // And update the cache 00634 00635 // Update cache flags - I am the context in which the cache is defined 00636 Source->Info.OCContextHandle = MyHandle; 00637 Source->Info.CacheColourModel = ColModel; 00638 } 00639 00640 00641 00642 /******************************************************************************************** 00643 00644 > void ColourContext::ConvertColourInternal(DocColour *Source, ColourPacked *Result) 00645 00646 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00647 Created: 14/04/94 00648 Inputs: Source - A Colour to convert 00649 Result - A PColourGeneric structure to recieve the resulting converted colour, 00650 as defined in this ColourContext. 00651 Outputs: - 00652 Returns: - 00653 Purpose: Converts a Colour into this colour context. 00654 The converted colour will be supplied from a cache where possible (this check 00655 is made by the caller function ConvertColour) 00656 Scope: PRIVATE - for use only by 'friend' rendering classes: 00657 OSRenderRegion, GRenderRegion 00658 Errors: - 00659 SeeAlso: ColourContext::ConvertColour 00660 00661 ********************************************************************************************/ 00662 00663 void ColourContext::ConvertColourInternal(DocColour *Source, ColourPacked *Result) 00664 { 00665 ColourGeneric NewResult; 00666 ConvertColourInternal(Source, &NewResult); // Convert 00667 00668 PackColour(&NewResult, Result); // Pack the colour into Result... 00669 00670 if (Source->Info.SourceColourModel != COLOURMODEL_INDEXED) 00671 { 00672 // And (if not an IndexedColour) update the cache 00673 Source->Info.OCContextHandle = MyHandle; 00674 Source->Info.CacheColourModel = ColModel; 00675 memcpy(&Source->CachedColour, Result, sizeof(ColourPacked)); 00676 } 00677 } 00678 00679 00680 00681 /******************************************************************************************** 00682 00683 > void ColourContext::ConvertColour(IndexedColour *Source, ColourGeneric *Result) 00684 00685 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00686 Created: 31/03/94 00687 Inputs: Source - An IndexedColour to convert 00688 Result - A ColourGeneric structure to recieve the resulting converted colour, 00689 as defined in this ColourContext. 00690 Outputs: - 00691 Returns: - 00692 Purpose: Converts an indexed colour into this colour context. 00693 The converted colour will be supplied from a cache where possible 00694 Errors: - 00695 SeeAlso: - 00696 00697 ********************************************************************************************/ 00698 00699 void ColourContext::ConvertColour(IndexedColour *Source, ColourGeneric *Result) 00700 { 00701 ENSURE(UsageCount > 0, "Colour context being used when not initialised!"); 00702 00703 if (Source->Info.OCContextHandle != MyHandle) // Uncached so convert it into the cache 00704 { 00705 // Ask the colour to get its source colour for us. If this is a Linked/Tint colour, 00706 // this could well involve getting another colour's definition, converting it, and 00707 // generally giving us an extended tour of stack city. 00708 ColourGeneric SourceColour; 00709 Source->GetSourceColour(&SourceColour); 00710 00711 // Check if we're doing a spot colour plate. We either get the colour's source colour, 00712 // or if it shouldn't appear on the plate, we get White. 00713 if (ColPlate != NULL && !ColPlate->IsDisabled()) 00714 { 00715 switch(ColPlate->GetType()) 00716 { 00717 case COLOURPLATE_SPOT: 00718 // If we're doing a spot plate and this isn't a descendant of the spot colour 00719 // then we must eliminate it from this plate. We must also check that it's a "true" 00720 // spot/tint, as opposed to a tint which is really a process colour. 00721 if ((!Source->IsADescendantOf(ColPlate->GetSpotColour())) || 00722 (!Source->IsSpotOrTintOfSpot())) 00723 { 00724 // Fill it with whatever White is defined as in the source context 00725 GetGlobalDefault(Source->GetColourModel())->GetWhite(&SourceColour); 00726 } 00727 break; 00728 00729 case COLOURPLATE_CYAN: 00730 case COLOURPLATE_MAGENTA: 00731 case COLOURPLATE_YELLOW: 00732 case COLOURPLATE_KEY: 00733 // If we're doing a process plate, eliminate any spot colours (or tints) from it 00734 if (Source->IsSpotOrTintOfSpot()) 00735 { 00736 // Fill it with whatever White is defined as in the source context 00737 GetGlobalDefault(Source->GetColourModel())->GetWhite(&SourceColour); 00738 } 00739 break; 00740 default: 00741 break; 00742 } 00743 } 00744 00745 ConvertColourBase(GetGlobalDefault(Source->GetColourModel()), 00746 &SourceColour, &Source->CachedColour, 00747 Source); 00748 00749 Source->Info.OCContextHandle = MyHandle; 00750 Source->Info.CacheColourModel = ColModel; 00751 } 00752 00753 // Copy the result from our cache 00754 memcpy(Result, &Source->CachedColour, sizeof(ColourGeneric)); 00755 } 00756 00757 00758 00759 /******************************************************************************************** 00760 00761 > void ColourContext::ConvertColour(ColourContext *SourceContext, 00762 ColourGeneric *SourceColour, 00763 ColourGeneric *Result) 00764 00765 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00766 Created: 31/03/94 00767 Inputs: SourceContext - The colour context in which the Source Colour is defined 00768 Source - A ColourGeneric structure defining a colour to convert, in the 00769 given SourceContext 00770 Result - A ColourGeneric structure to recieve the resulting converted colour, 00771 as defined in this ColourContext. 00772 Outputs: - 00773 Returns: - 00774 Purpose: Converts a colour in any arbitrary colour context into this colour context. 00775 The converted colour will be supplied from a cache where possible 00776 Errors: - 00777 SeeAlso: - 00778 00779 ********************************************************************************************/ 00780 00781 void ColourContext::ConvertColour(ColourContext *SourceContext, 00782 ColourGeneric *SourceColour, 00783 ColourGeneric *Result) 00784 { 00785 ENSURE(UsageCount > 0, "Colour context being used when not initialised!"); 00786 00787 // This may look like an opportunity for optimisation, but 00788 // ConvertColourBase is actually an inline function 00789 ConvertColourBase(SourceContext, SourceColour, Result); 00790 } 00791 00792 00793 00794 /******************************************************************************************** 00795 00796 > virtual void ColourContext::CreateExternalTransform(void) 00797 00798 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 00799 Created: 12/05/96 00800 Inputs: - 00801 Returns: - 00802 Purpose: Create an external transform to be used during colour conversions from 00803 RGB to the current RCS space. This function uses the Winoil CMS Manager 00804 to create the transform. Both forward and backward transforms use logical 00805 RGB descriptions. 00806 00807 ********************************************************************************************/ 00808 00809 void ColourContext::CreateExternalTransform() 00810 { 00811 // We do nothing here. If no one creates an external transform, the default 00812 // internal one will be used. To create an external transform, call the derived class 00813 // function, not this one as you can see it does nothing. 00814 } 00815 00816 00817 /******************************************************************************************** 00818 00819 > virtual void ColourContext::ApplyInputFilter(ColourPlate *FilterDescription, 00820 ColourContext *DestContext, 00821 ColourGeneric *OutputColour, 00822 IndexedColour *SourceIxCol); 00823 00824 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00825 Created: 22/1/96 00826 Inputs: FilterDescription - A ColourPlate describing how the colour is to be filtered 00827 00828 DestContext - Points to the context to which the OutputColour will be 00829 converted after we return it. 00830 00831 OutputColour - The colour to be filtered 00832 00833 SourceIxCol - NULL, or the original IndexedColour which is being converted. 00834 This is used for handling spot colour separation correctly. 00835 00836 Outputs: OutputColour - Will be modified as appropriate to the current colour 00837 filtering options (see Purpose) 00838 00839 Purpose: All colour conversions call this function for the SOURCE context 00840 immediately before converting the colour. This gives the input colour 00841 context the chance to apply a filtering process to the colour. 00842 00843 This is usually used to provide colour separations. Often, this function 00844 will do nothing to the output colour - generally it is only used by CMYK 00845 contexts in order to colour-separate the colour in CMYK space. 00846 00847 SeeAlso: ColourContext::ConvertColourBase 00848 00849 ********************************************************************************************/ 00850 00851 void ColourContext::ApplyInputFilter(ColourPlate *FilterDescription, ColourContext *DestContext, 00852 ColourGeneric *OutputColour, IndexedColour *SourceIxCol) 00853 { 00854 // ERROR3IF(FilterDescription == NULL || DestContext == NULL || OutputColour == NULL, "Illegal NULL params"); 00855 // 00856 // if (FilterDescription == NULL) 00857 // return; 00858 // 00859 } 00860 00861 00862 00863 /******************************************************************************************** 00864 00865 > virtual void ColourContext::ApplyOutputFilter(ColourPlate *FilterDescription, 00866 ColourContext *SourceContext, 00867 ColourGeneric *OutputColour, 00868 IndexedColour *SourceIxCol); 00869 00870 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00871 Created: 22/1/96 00872 Inputs: FilterDescription - A ColourPlate describing how the colour is to be filtered 00873 00874 SourceContext - Points to the context from which the OutputColour has just 00875 been converted. 00876 00877 OutputColour - The colour to be filtered 00878 00879 SourceIxCol - NULL, or the IndexedColour which was the source of the colour 00880 being converted. This is only used for information when preparing spot colour 00881 separations. 00882 00883 Outputs: OutputColour - Will be modified as appropriate to the current colour 00884 filtering options (see Purpose) 00885 00886 Purpose: All colour conversions call this function for the DEST context immediately 00887 prior to returning the converted colour to the caller. This gives the output 00888 colour context the chance to apply an output filtering process to the output 00889 colour. 00890 00891 This is usually used to provide colour separations, and may also be used 00892 to apply some colour corrections. Often, this function will do nothing 00893 to the output colour. 00894 00895 SeeAlso: ColourContext::ConvertColourBase 00896 00897 ********************************************************************************************/ 00898 00899 void ColourContext::ApplyOutputFilter(ColourPlate *FilterDescription, ColourContext *SourceContext, 00900 ColourGeneric *OutputColour, IndexedColour *SourceIxCol) 00901 { 00902 // ERROR3IF(FilterDescription == NULL || SourceContext == NULL || OutputColour == NULL, "Illegal NULL params"); 00903 // 00904 // if (FilterDescription == NULL) 00905 // return; 00906 } 00907 00908 00909 00910 /******************************************************************************************** 00911 00912 > void ColourContext::SetColourPlate(ColourPlate *NewColourPlate) 00913 00914 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00915 Created: 31/01/96 00916 Inputs: NULL (to disable colour seps), or points to the new ColourPlate descriptor object 00917 NOTE that the ColourPlate object now belongs to the ColourContext, and will be 00918 deleted by the context when it is finished with it. 00919 00920 Purpose: Sets a colour separation/plate for this context 00921 00922 Notes: The ColourPlate object now belongs to the ColourContext, and will be 00923 deleted by the context when it is finished with it. 00924 00925 (To remove the ColourPlate again in a way that does not delete the ColourPlate, 00926 call ColourContext::DetachColourPlate rather than SetColourPlate(NULL)) 00927 00928 The Context's cache handle will be changed so that all cached colours 00929 in this output context are effectively 'flushed'. 00930 00931 SeeAlso: ColourPlate; ColourContext::ApplyOutputFilter; ColourContext::GetColourPlate; 00932 ColourContext::DetachColourPlate 00933 00934 ********************************************************************************************/ 00935 00936 void ColourContext::SetColourPlate(ColourPlate *NewColourPlate) 00937 { 00938 // Trying to set ColourPlate to the one we're already using - ignore them! 00939 if (ColPlate == NewColourPlate) 00940 return; 00941 00942 // Delete our current ColourPlate 00943 if (ColPlate != NULL) 00944 { 00945 delete ColPlate; 00946 ColPlate = NULL; 00947 } 00948 00949 // Remember our new ColourPlate filter descriptor 00950 ColPlate = NewColourPlate; 00951 00952 // Change our context handle so that all cached colours in this context 00953 // are effectively "flushed" 00954 ColourPlateHasChanged(); 00955 } 00956 00957 00958 00959 /******************************************************************************************** 00960 00961 > ColourPlate *ColourContext::DetachColourPlate(void) 00962 00963 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00964 Created: 11/6/96 00965 00966 Returns: The pointer to the previously attached ColourPlate (may be NULL) 00967 00968 Purpose: Detaches the ColourPlate (if any) currently attached to this ColourContext. 00969 The context will no longer use the colour plate descriptor, and will return 00970 to default colour separation/correction actions. 00971 00972 ** The caller is now responsible for deleting the returned object ** 00973 00974 Notes: The Context's cache handle will be changed so that all cached colours 00975 in this output context are effectively 'flushed'. 00976 00977 SeeAlso: ColourPlate; ColourContext::GetColourPlate; ColourContext::SetColourPlate 00978 00979 ********************************************************************************************/ 00980 00981 ColourPlate *ColourContext::DetachColourPlate(void) 00982 { 00983 ColourPlate *OldColourPlate = ColPlate; 00984 00985 if (ColPlate != NULL) 00986 { 00987 ColPlate = NULL; 00988 00989 // Change our context handle so that all cached colours in this context 00990 // are effectively "flushed" 00991 ColourPlateHasChanged(); 00992 } 00993 00994 return(OldColourPlate); 00995 } 00996 00997 00998 00999 /******************************************************************************************** 01000 01001 > ColourPlate *ColourContext::GetColourPlate(void) 01002 01003 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01004 Created: 31/01/96 01005 01006 Returns: NULL if Colour separation is disabled on this context, else a pointer 01007 to a ColourPlate descriptor object which describes the current colour 01008 separation/filtering options. 01009 01010 Purpose: Reads the colour separation/plate for this context 01011 01012 SeeAlso: ColourPlate; ColourContext::ApplyOutputFilter; ColourContext::SetColourPlate 01013 01014 ********************************************************************************************/ 01015 01016 ColourPlate *ColourContext::GetColourPlate(void) 01017 { 01018 return(ColPlate); 01019 } 01020 01021 01022 01023 /******************************************************************************************** 01024 01025 > void ColourContext::ColourPlateHasChanged(void) 01026 01027 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01028 Created: 9/5/96 01029 01030 Purpose: Effectively flushes the caches of all colours currently cached in this 01031 ColourContext, so that on the next redraw they will re-convert. 01032 01033 Notes: This is achieved by generating a new unique handle for this Context. 01034 Note that after 65536 handles, we will start re-using handles, and 01035 things will look bad if we inadvertently use the same handle for 2 01036 contexts. This is an extremely unlikely occurrence, but please do 01037 not call this function unless it is absolutely necessary, to minimise 01038 the number of handle changes that occur. 01039 01040 This function is automatically called whenever you change the 01041 ColourPlate attached to this context in any way. 01042 01043 Scope: Intended as an internal routine; also called by ColourPlate class 01044 Should not be called by anyone else 01045 01046 SeeAlso: ColourContext::SetColourPlate; IndexedColour; DocColour 01047 01048 ********************************************************************************************/ 01049 01050 void ColourContext::ColourPlateHasChanged(void) 01051 { 01052 // We need to change this context's "MyHandle" so that all cached colours for this 01053 // context are treated as non-cached again, and will be converted correctly for 01054 // the new output filter. 01055 MyHandle = NextColourContextHandle++; 01056 } 01057 01058 01059 01060 /******************************************************************************************** 01061 01062 > virtual BOOL ColourContext::SetComponentUnitGroup(UINT32 ComponentID, 01063 UnitGroup* pComponentUnitGroup) 01064 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 01065 Created: 02/05/96 01066 Inputs: ComponentIndex : the number of the component (1..GetComponentCount()) 01067 ComponentUnitGroup : pointer to the required UnitGroup for the component 01068 Outputs: - 01069 Returns: TRUE if set OK 01070 FALSE otherwise 01071 Purpose: Allows the UnitGroup of the given component in the ColourModel to be set 01072 Errors: ERROR2IF ComponentIndex < 1 or greater than number of components in model 01073 01074 ********************************************************************************************/ 01075 01076 BOOL ColourContext::SetComponentUnitGroup(UINT32 ComponentID, UnitGroup* pComponentUnitGroup) 01077 { 01078 ERROR2IF(ComponentID < 1 || ComponentID > GetComponentCount(), FALSE, "Invalid Index"); 01079 ERROR2IF(pComponentUnitGroup == NULL, FALSE, "Invalid UnitGroup"); 01080 01081 ERROR3IF(!pComponentUnitGroup->IS_KIND_OF(UnitGroup), "Invalid UnitGroup"); 01082 01083 UnitGroup** pUnitGroupArray = GetComponentUnitGroups(); 01084 ERROR3IF(!(pUnitGroupArray[ComponentID - 1]->IS_KIND_OF(UnitGroup)), 01085 "ColourContext::GetComponentUnitGroup - Not UnitGroup array"); 01086 01087 pUnitGroupArray[ComponentID - 1] = pComponentUnitGroup; 01088 return TRUE; 01089 } 01090 01091 01092 01093 /******************************************************************************************** 01094 01095 > virtual UnitGroup *ColourContext::GetComponentUnitGroup(UINT32 ComponentID) 01096 01097 Author: Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com> 01098 Created: 02/05/96 01099 Inputs: ComponentID - the number of the component (1..GetComponentCount()) 01100 Outputs: - 01101 Returns: A pointer to the desired UnitGroup 01102 Purpose: Provides the UnitGroup of the given component in the ColourModel 01103 Errors: ERROR2IF ComponentIndex < 1 or greater than number of components in model 01104 See Also: ColourContextCMYK::GetComponentUnitGroups() 01105 ColourContextGreyT::GetComponentUnitGroups() 01106 ColourContextHSVT::GetComponentUnitGroups() 01107 ColourContextRGBT::GetComponentUnitGroups() 01108 01109 ********************************************************************************************/ 01110 01111 UnitGroup *ColourContext::GetComponentUnitGroup(UINT32 ComponentID) 01112 { 01113 ERROR2IF(ComponentID < 1 || ComponentID > GetComponentCount(), FALSE, "Invalid ID"); 01114 UnitGroup** pUnitGroupArray = GetComponentUnitGroups(); 01115 ERROR3IF(!(pUnitGroupArray[ComponentID - 1]->IS_KIND_OF(UnitGroup)), 01116 "ColourContext::GetComponentUnitGroup - Not UnitGroup array"); 01117 01118 return pUnitGroupArray[ComponentID - 1]; 01119 } 01120 01121 01122 01123 01124 01125 01126 01127 01128 01129 01130 01131 01132 01133 01134 01135 01136 01137 01138 /******************************************************************************************** 01139 01140 > void ColourContextRGBT::ColourContextRGBT(View *Scope, double GammaValue = 1.0) 01141 01142 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01143 Created: 31/03/94 01144 Inputs: Scope - The view in which this context is to be used, or NULL 01145 GammaValue - A gamma-correction gamma factor. You know... Gamma. 01146 Heck, if you don't know what a gamma value is, then don't pass 01147 anything in, because it has a good default value. 01148 Outputs: - 01149 Returns: - 01150 Purpose: Constructor for an RGBT Colour context 01151 01152 Notes: Colour Contexts should not be created and used directly. See the 01153 notes in the SeeAlso's for instructions on proper care and use. 01154 01155 Errors: - 01156 SeeAlso: ColourContext::ColourContext; ColourContextList::AddContext 01157 01158 ********************************************************************************************/ 01159 01160 ColourContextRGBT::ColourContextRGBT(View *Scope, double GammaValue) 01161 : ColourContext(Scope) 01162 { 01163 ColModel = COLOURMODEL_RGBT; 01164 Gamma = GammaValue; 01165 01166 CreateExternalTransform(); 01167 } 01168 01169 01170 01171 /******************************************************************************************** 01172 01173 > ColourContextWebRGBT::ColourContextWebRGBT(View *Scope, double GammaValue) 01174 : ColourContextRGBT(Scope, GammaValue) 01175 01176 Author: Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> 01177 Created: ??/11/99 01178 Inputs: Scope - The view in which this context is to be used, or NULL 01179 GammaValue - A gamma-correction gamma factor. You know... Gamma. 01180 Heck, if you don't know what a gamma value is, then don't pass 01181 anything in, because it has a good default value. 01182 Outputs: - 01183 Returns: - 01184 Purpose: Constructor for an RGBT Web Colour context 01185 01186 Notes: Colour Contexts should not be created and used directly. See the 01187 notes in the SeeAlso's for instructions on proper care and use. 01188 01189 Errors: - 01190 SeeAlso: ColourContext::ColourContext; ColourContextList::AddContext 01191 01192 ********************************************************************************************/ 01193 01194 ColourContextWebRGBT::ColourContextWebRGBT(View *Scope, double GammaValue) 01195 : ColourContextRGBT(Scope, GammaValue) 01196 { 01197 ColModel = COLOURMODEL_RGBT; 01198 } 01199 01200 01201 01202 /******************************************************************************************** 01203 01204 > void ColourContextRGBT::CreateExternalTransform(void) 01205 01206 Author: Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> 01207 Created: 12/05/96 01208 Inputs: - 01209 Returns: - 01210 Purpose: Create an external transform to be used during colour conversions from 01211 RGB to the current RCS space. This function uses the Winoil CMS Manager 01212 to create the transform. Both forward and backward transforms use logical 01213 RGB descriptions. 01214 01215 ********************************************************************************************/ 01216 01217 void ColourContextRGBT::CreateExternalTransform() 01218 { 01219 #ifndef NO_XARACMS 01220 CMSColourSpace cmsSpace; 01221 XaraCMS* lpCMSMan = GetApplication()->GetCMSManager(); 01222 01223 if (lpCMSMan != NULL) 01224 { 01225 // first read our internal colour calibration space 01226 lpCMSMan->GetLogicalProfile(&cmsSpace); 01227 01228 // set this as the active colour profile 01229 UINT32 err = lpCMSMan->SetProfile(cmsSpace); 01230 01231 // if we haven't got an error, create that transform 01232 if (err==0) 01233 CMSTransform = lpCMSMan->CreateTransform(DISPLAY_RCS); 01234 } 01235 #endif 01236 } 01237 01238 01239 /******************************************************************************************** 01240 01241 > void ColourContextRGBT::ConvertToCIET(ColourGeneric *Source, DColourCIET *Result) 01242 01243 Author: Jason_