DocColour Class Reference

This class defines a colour. A DocColour stores an original definition of a colour, a cache containing the definition of the colour in the last colour context in which it was used, and sundry information. DocColours have been designed to be small things to put in attributes. More...

#include <doccolor.h>

List of all members.

Public Member Functions

 DocColour ()
 Constructor for a DocColour Initialises the colour to an RGBT value representing 'no colour'. (i.e. The same as DocColour(COLOUR_TRANS)).
 ~DocColour ()
 Destructor for a DocColour.
 DocColour (StockColour Col)
 Constructor for a DocColour Initialises it to the given predefined (stock) colours, as defined in stockcol.h (cf keyword StockColour).
 DocColour (ColourModel ColModel, ColourGeneric *Col)
 Constructor for a DocColour Initialises it to the given value.
 DocColour (ColourValue Red, ColourValue Green, ColourValue Blue)
 Constructor for a DocColour Initialises it to the given RGBT value. Values are ColourValues (FIXED24s) in the range 0.0 to 1.0.
 DocColour (const DocColour &other)
 DocColour copy constructor Notes: If copying a reference to an indexed colour, the indexed colours usage count will be incremented. If this is already a reference to an indexed colour, that indexed colours usage count will be decremented.
DocColouroperator= (const DocColour &)
 DocColour assignment operator Notes: If copying a reference to an indexed colour, the indexed colours usage count will be incremented. If this is already a reference to an indexed colour, that indexed colours usage count will be decremented.
void MakeRefToIndexedColour (IndexedColour *Other)
IndexedColourFindParentIndexedColour (void)
 Determines if a colour references an IndexedColour, and if so, gives access to the parent colour.
void MakeRefToIndexedColourDBG (IndexedColour *Other, LPCSTR TheFile=NULL, INT32 TheLine=0)
 DocColour assignment - Makes this DocColour a reference to the given Indexed Colour. The Indexed Colour cannot be deleted until this DocColour releases this claim upon it (which occurs when it is deleted or re-assigned).
IndexedColourGetSpotParent (void)
 To determine which spot colour (if any) is the ultimate spot colour parent of this DocColour. (i.e. to see which spot plate a DocColour will appear on).
BOOL operator== (const DocColour) const
 DocColour comparison operator.
BOOL operator!= (const DocColour) const
 DocColour comparison operator Notes: If comparing two references to indexed colours, they will only be considered equal if they reference the SAME indexed colour (i.e. we do not compare the indexed colours).
ColourModel GetColourModel (void) const
 {Copy} Constructor for a DocColour Notes: THIS FUNCTION DOES NOT EXIST!! DocColour::MakeRefToIndexedColour() should be used if you wish to "assign" an IndexedColour to a DocColour. To determine the colourmodel in which the given colour was defined Notes: If this is a reference to an IndexedColour, returns the colour of the referenced IndexedColour. The colour model number returned may be used as an index into the list of ColourContexts held by each document, in order to find a relevant context for the colour.
void GetSourceColour (ColourGeneric *Result)
 Determine the native definition of the given colour Notes: If this is a reference to an IndexedColour, returns the colour of the referenced IndexedColour.
BOOL IsTransparent (void) const
 Determines if a colour's "no colour" flag is set.
BOOL IsSeparable (void) const
 Determines if a colour's "IsSeparable" flag is set.
void SetSeparable (BOOL IsSeparable=TRUE)
 To set the separation/correction enable flag for a DocColour. Some colours (e.g. EOR blob colours) should not be colour-separated on screen. By default, all colours (except StockCols) will separate, but this flag can be set on "UI colours" to stop them separating.
void Mix (DocColour *BlendStart, DocColour *BlendEnd, double BlendFraction, ColourContext *BlendContext, BOOL BlendTheLongWay=FALSE, ColourContext *OutputContext=NULL)
 "Constructor" for a DocColour - generates a blended DocColour The start and end colours are blended to create this new DocColour. The amount by which they are mixed is determined by BlendFraction. The blend occurs in the colourspace described by BlendContext. Note that BlendContext may be NULL, in which case the default context for the BlendStart colour will be used. However, this is not recommended, as this will result in a blend which may be incorrect for the context(s) in use in a given document, which could give seriously wonky colours!
void ForceRounding (BOOL RoundingOn)
BOOL IsForcedToRound (void)
void SetReservedFlag (UINT32 Value)
 To set the Reserved flag of the colour info struct.
UINT32 GetReservedFlag ()
 access fn.
BOOL IsNamed ()
 to identidy if this colour is named, or was created from a named colour. Note that not all colours that were created by Named colours will have the relevant flag set, as I have only just started using it (4/2000). This fn. was really designed to be used specifically by the brush attribute replace named colours system.
void HackColReplacerPreDestruct ()
 As you might expect from the name this is a real bodge. Basically the named colour replacer used in the brush needs to store some colours which are converted index colours. To cut a long story short I'm looking at a deadline and this prevents an assert upon destruction, theres no reason for anyone else to use it.
void GetDebugDetails (StringBase *Str)
void SetRGBValue (INT32 Red, INT32 Green, INT32 Blue)
void GetRGBValue (INT32 *Red, INT32 *Green, INT32 *Blue)
void SetCMYKValue (PColourCMYK *New)
void GetCMYKValue (PColourCMYK *Result)
void GetCMYKValue (ColourContext *pContext, PColourCMYK *Result)
void SetHSVValue (INT32 h, INT32 s, INT32 v)
void GetHSVValue (INT32 *h, INT32 *s, INT32 *v)
 DocColour (INT32 Red, INT32 Green, INT32 Blue)

Protected Member Functions

void MixRGB (DocColour *BlendStart, DocColour *BlendEnd, double BlendFraction, ColourContext *BlendContext)
 Internal helper function for DocColour::Mix. This is a reasonably optimised routine for mixing RGB colours.
void MixCMYK (DocColour *BlendStart, DocColour *BlendEnd, double BlendFraction, ColourContext *BlendContext)
 Internal helper function for DocColour::Mix. This is a reasonably optimised routine for mixing CMYK colours.
void MixHSV (DocColour *BlendStart, DocColour *BlendEnd, double BlendFraction, ColourContext *BlendContext, BOOL BlendTheLongWay=FALSE)
 Internal helper function for DocColour::Mix. This is a reasonably optimised routine for mixing HSV colours.
void MixTint (IndexedColour *SpotParent, IndexedColour *StartTint, IndexedColour *EndTint, double BlendFraction)
 Internal helper function for DocColour::Mix. This method is used to mix the DocColours to an IndexedColour result when one or both of the end colours are tints. This simply linearly interpolates the tint values.
void InitialiseInfoField (ColourModel ColModel)
 Private shared code for construction of DocColour objects Initialises the 'Info' structure to default values Scope: private.
void ZapSourceColour ()

Protected Attributes

ColourInfo Info
ColourPacked SourceColour
ColourPacked CachedColour

Friends

class ColourContext


Detailed Description

This class defines a colour. A DocColour stores an original definition of a colour, a cache containing the definition of the colour in the last colour context in which it was used, and sundry information. DocColours have been designed to be small things to put in attributes.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
DocColours cannot be used on their own, however. They have meaning only within the scope of a given colour context.

DocColours can be defined in any of the available colour models.

DocColours are stored to "low" (32-bit) precision, except when they are references to IndexedColours (which are 128-bit precision). However, colour calculations, and access to values stored in colours are generally only available through the 128bit interface.

Notes: NOTE that any use of a DocColour may result in updating its cache, so you must NOT treat DocColours as const anywhere. Also, work on original DocColours rather than copies if you want the cache to be kept fresh on the original.

See also:
IndexedColour; ColourModel; ColourContext Documentation: HowToUse.doc

Definition at line 179 of file doccolor.h.


Constructor & Destructor Documentation

DocColour::DocColour  ) 
 

Constructor for a DocColour Initialises the colour to an RGBT value representing 'no colour'. (i.e. The same as DocColour(COLOUR_TRANS)).

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
-

Definition at line 185 of file doccolor.cpp.

00186 {
00187     ZapSourceColour();
00188     InitialiseInfoField(COLOURMODEL_RGBT);
00189 
00190     SourceColour.RGBT.Red           = 0;    // Black & 100% Transparent
00191     SourceColour.RGBT.Green         = 0;
00192     SourceColour.RGBT.Blue          = 0;
00193     SourceColour.RGBT.Transparent   = 255;
00194 
00195     Info.NoColour = TRUE;                   // And also 'no colour' transparent
00196 }

DocColour::~DocColour  ) 
 

Destructor for a DocColour.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
-

Definition at line 215 of file doccolor.cpp.

00216 {
00217     // If we are a reference to an indexed colour, tell that colour that we are
00218     // no longer referencing it
00219     if (Info.SourceColourModel == COLOURMODEL_INDEXED)
00220         SourceColour.Indexed.Colour->DecrementUsage();
00221 }

DocColour::DocColour StockColour  Col  ) 
 

Constructor for a DocColour Initialises it to the given predefined (stock) colours, as defined in stockcol.h (cf keyword StockColour).

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
06/04/94
Parameters:
Col - Identifies the stock colour to create [INPUTS]
- [OUTPUTS]
Returns:
-
Notes: ALL StockColours are non-separable colours! i.e. they should only be applied to user-interface rendering

Returns:
Errors: -
See also:
StockColour

Definition at line 250 of file doccolor.cpp.

00251 {
00252     ZapSourceColour();
00253     PColourValue Red = 0, Green = 0, Blue = 0, Transparent = 0;
00254 
00255     InitialiseInfoField(COLOURMODEL_RGBT);
00256 
00257     switch (Col)
00258     {
00259         case COLOUR_TRANS:
00260             Red = Green = Blue = Transparent = 255;
00261             Info.NoColour = TRUE;
00262             break;
00263 
00264         case COLOUR_BLACK:
00265         case COLOUR_UNSELECTEDBLOB:
00266         case COLOUR_FILLDEFAULT:
00267         case COLOUR_LINEDEFAULT:
00268         case COLOUR_XORDRAG:
00269             break;
00270 
00271         case COLOUR_DKGREY:
00272             Red = Green = Blue =  64;
00273             break;
00274 
00275         case COLOUR_MIDGREY:
00276             Red = Green = Blue = 128;
00277             break;
00278 
00279         case COLOUR_XOREDIT:
00280             Red = 64;
00281             Green = 64;
00282             Blue = 230;
00283             break;
00284 
00285         case COLOUR_LTGREY:
00286         case COLOUR_BEZIERLINE:
00287             Red = Green = Blue = 192;
00288             break;
00289 
00290         case COLOUR_WHITE:
00291             Red = Green = Blue = 255;
00292             break;
00293 
00294         case COLOUR_RED:
00295         case COLOUR_XORSELECT:
00296         case COLOUR_TOOLBLOB:
00297         case COLOUR_SELECTEDBLOB:
00298         case COLOUR_BEZIERBLOB:
00299             Red     = 255;
00300             break;
00301 
00302         case COLOUR_GREEN:
00303             Green   = 255;
00304             break;
00305 
00306         case COLOUR_BLUE:
00307         case COLOUR_XORNEW:
00308         case COLOUR_GRID:
00309             Blue    = 255;
00310             break;
00311 
00312         case COLOUR_CYAN:
00313             Green  = Blue = 255;
00314             break;
00315 
00316         case COLOUR_MAGENTA:
00317             Red = Blue = 255;
00318             break;
00319 
00320         case COLOUR_YELLOW:
00321             Red = Green = 255;
00322             break;
00323     }
00324 
00325 
00326     SourceColour.RGBT.Red           = Red;
00327     SourceColour.RGBT.Green         = Green;
00328     SourceColour.RGBT.Blue          = Blue;
00329     SourceColour.RGBT.Transparent   = Transparent;
00330 
00331     Info.IsSeparable = FALSE;
00332 }

DocColour::DocColour ColourModel  ColModel,
ColourGeneric Col
 

Constructor for a DocColour Initialises it to the given value.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
Parameters:
ColModel - Colour model in which Col is defined [INPUTS] Col - definition of the colour in model ColModel
- [OUTPUTS]
Returns:
-
Notes: Note the existence of the macros: DOCCOLOUR_RGBT(Colour_RGBT *col) DOCCOLOUR_CMYK(Colour_CMYK *col) DOCCOLOUR_HSVT(Colour_HSVT *col) DOCCOLOUR_CIET(COLOUR_CIET *col) which can be used to create DocColours from ColourRGBT etc structs e.g. ColourRGBT AnRGBTColourDefn; DocColour MyRGBT = DOCCOLOUR_RGBT(&AnRGBTColourDefn); These macros are defined in doccolor.h

Returns:
Errors: -
See also:
-

Definition at line 403 of file doccolor.cpp.

00404 {
00405     ZapSourceColour();
00406     InitialiseInfoField(ColModel);
00407     DEFAULTCONTEXT(ColModel)->PackColour(Col, &SourceColour);
00408 }

DocColour::DocColour ColourValue  Red,
ColourValue  Green,
ColourValue  Blue
 

Constructor for a DocColour Initialises it to the given RGBT value. Values are ColourValues (FIXED24s) in the range 0.0 to 1.0.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
Parameters:
Red; Green; Blue - The RGB definition of the colour [INPUTS]
- [OUTPUTS]
Returns:
-
Notes: DocColours no longer support transparency/transtype.

Returns:
Errors: -
See also:
-

Definition at line 357 of file doccolor.cpp.

00358 {
00359     ZapSourceColour();
00360     ColourRGBT temp;
00361 
00362     InitialiseInfoField( COLOURMODEL_RGBT );
00363 
00364     temp.Red            = Red;          // Copy data into 128-bit struct, then pack
00365     temp.Green          = Green;        // it into our 32-bit store.
00366     temp.Blue           = Blue;
00367     temp.Transparent    = 0;
00368 
00369     DEFAULTCONTEXT(COLOURMODEL_RGBT)->PackColour( (ColourGeneric *)&temp, &SourceColour );
00370 }

DocColour::DocColour const DocColour Other  ) 
 

DocColour copy constructor Notes: If copying a reference to an indexed colour, the indexed colours usage count will be incremented. If this is already a reference to an indexed colour, that indexed colours usage count will be decremented.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/04/94
Parameters:
Other - colour to copy [INPUTS]
- [OUTPUTS]
Returns:

Errors: -

Definition at line 430 of file doccolor.cpp.

00431 {
00432     ENSURE(Other.Info.SourceColourModel < MAX_COLOURMODELS,
00433             "Attempt to use illegal colour model!");
00434 
00435     Info = Other.Info;
00436     CachedColour = Other.CachedColour;
00437     SourceColour = Other.SourceColour;
00438 
00439     if (Info.SourceColourModel == COLOURMODEL_INDEXED)
00440     {
00441         ENSURE(SourceColour.Indexed.Colour != NULL,
00442                 "Corrupted DocColour (NULL IndexedColour ref) detected");
00443 
00444         SourceColour.Indexed.Colour->IncrementUsage();
00445         ENSURE(Info.CacheColourModel == 0, "RefToIndexedColour DocColour has a cache!!");
00446 
00447 #ifdef TRACECOLOURIX
00448 TRACE( _T(">> Construct DocColour(DocColour => ColourIx %x) @ %x\n"), (INT32)SourceColour.Indexed.Colour, (INT32)this);
00449 #endif
00450     }
00451 }

DocColour::DocColour INT32  Red,
INT32  Green,
INT32  Blue
 

Definition at line 1612 of file doccolor.cpp.

01613 {
01614     ZapSourceColour();
01615     InitialiseInfoField(COLOURMODEL_RGBT);
01616 
01617     SourceColour.RGBT.Red   = (PColourValue) Red;
01618     SourceColour.RGBT.Green = (PColourValue) Green;
01619     SourceColour.RGBT.Blue  = (PColourValue) Blue;
01620     SourceColour.RGBT.Transparent = 0;
01621 }


Member Function Documentation

IndexedColour * DocColour::FindParentIndexedColour void   )  [inline]
 

Determines if a colour references an IndexedColour, and if so, gives access to the parent colour.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
7/6/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
NULL if this is an immediate colour else a pointer to the IndexedColour which this DocColour references
See also:
DocColour::MakeRefToIndexedColour

Definition at line 413 of file doccolor.h.

00414 {
00415     if (Info.SourceColourModel != COLOURMODEL_INDEXED)
00416         return(NULL);
00417 
00418     return(SourceColour.Indexed.Colour);
00419 }

void DocColour::ForceRounding BOOL  RoundingOn  )  [inline]
 

Definition at line 246 of file doccolor.h.

00246 { Info.ForceRounding = RoundingOn; };

void DocColour::GetCMYKValue ColourContext pContext,
PColourCMYK Result
 

Definition at line 1715 of file doccolor.cpp.

01716 {
01717     if (pContext!=NULL)
01718     {
01719         ERROR3IF(pContext->GetColourModel() != COLOURMODEL_CMYK, "Colour context is not CMYK!");
01720         pContext->ConvertColour(this, (ColourPacked *) Result);
01721         return;
01722     }
01723 
01724     ColourContext *CCcmyk = ColourContext::GetGlobalDefault(COLOURMODEL_CMYK);
01725     ERROR3IF(CCcmyk == NULL, "No default CMYK colour context?!");
01726 
01727     CCcmyk->ConvertColour(this, (ColourPacked *) Result);
01728 }

void DocColour::GetCMYKValue PColourCMYK Result  ) 
 

Definition at line 1708 of file doccolor.cpp.

01709 {
01710     ColourContext *CCcmyk = ColourContext::GetGlobalDefault(COLOURMODEL_CMYK);
01711     CCcmyk->ConvertColour(this, (ColourPacked *) Result);
01712 }

ColourModel DocColour::GetColourModel void   )  const
 

{Copy} Constructor for a DocColour Notes: THIS FUNCTION DOES NOT EXIST!! DocColour::MakeRefToIndexedColour() should be used if you wish to "assign" an IndexedColour to a DocColour. To determine the colourmodel in which the given colour was defined Notes: If this is a reference to an IndexedColour, returns the colour of the referenced IndexedColour. The colour model number returned may be used as an index into the list of ColourContexts held by each document, in order to find a relevant context for the colour.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
A Colour Model identifying the model in which the colour is defined

Errors: -

See also:
DocColour::GetSourceColour

Definition at line 490 of file doccolor.cpp.

00491 {
00492     ENSURE(Info.SourceColourModel < MAX_COLOURMODELS,
00493             "DocColour based on illegal colour model!");
00494 
00495     // If colour is a reference to an indexed colour, return indexed colour's
00496     // colour model
00497     if (Info.SourceColourModel == COLOURMODEL_INDEXED)
00498     {
00499         ENSURE(SourceColour.Indexed.Colour != NULL,
00500                 "Corrupted DocColour (NULL IndexedColour ref) detected");
00501         return(SourceColour.Indexed.Colour->GetColourModel());
00502     }
00503 
00504     return((ColourModel) Info.SourceColourModel);
00505 }

void DocColour::GetDebugDetails StringBase Str  ) 
 

Definition at line 1732 of file doccolor.cpp.

01733 {
01734     String_256 TempStr;
01735 
01736     if (Info.IsSeparable)
01737         *Str += TEXT(" Sep ");
01738     else
01739         *Str += TEXT(" NotSep ");
01740 
01741     if (Info.SourceColourModel == COLOURMODEL_INDEXED)
01742     {
01743         ENSURE(SourceColour.Indexed.Colour != NULL,
01744                 "Corrupted DocColour (NULL IndexedColour ref) detected");
01745 
01746         String_64 *pIndexedName = SourceColour.Indexed.Colour->GetName();
01747 //      TempStr._MakeMsg(TEXT(" (#1%s) ref->"), 
01748 //                       pIndexedName); // This is a reference to an indexed col
01749 //      (*Str) += TempStr;
01750         (*Str) += TEXT(" (");
01751         (*Str) += (*pIndexedName);
01752         (*Str) += TEXT(") ref ->");
01753         SourceColour.Indexed.Colour->GetDebugDetails(Str);
01754         return;
01755     }
01756         
01757 
01758     if (Info.NoColour)
01759         TempStr._MakeMsg( TEXT(" colour=transparent\r\n"));
01760     else
01761     {       
01762         ColourContext *cc = ColourContext::GetGlobalDefault((ColourModel) Info.SourceColourModel);
01763         ColourGeneric col;
01764 
01765         String_32 ModelName;
01766         cc->GetModelName(&ModelName);
01767         cc->UnpackColour(&SourceColour, &col);
01768 
01769         TempStr._MakeMsg( TEXT(" colour=#1%s(#2%ld, #3%ld, #4%ld, #5%ld)\r\n"), (TCHAR *) ModelName,
01770                             (INT32) (col.Component1.MakeDouble()*100), (INT32) (col.Component2.MakeDouble()*100),
01771                             (INT32) (col.Component3.MakeDouble()*100), (INT32) (col.Component4.MakeDouble()*100));
01772     }
01773 
01774     (*Str) += TempStr;
01775 }

void DocColour::GetHSVValue INT32 *  h,
INT32 *  s,
INT32 *  v
 

Definition at line 1678 of file doccolor.cpp.

01679 {
01680     ColourContextHSVT *CChsvt = (ColourContextHSVT *)ColourContext::GetGlobalDefault(COLOURMODEL_HSVT);
01681     ColourHSVT result;
01682     ColourPacked bob;
01683 
01684     CChsvt->ConvertColour((DocColour *)this, (ColourGeneric *)&result);
01685     CChsvt->PackColour((ColourGeneric *)&result, (ColourPacked *)&bob);
01686 
01687     *h  = (INT32) bob.HSVT.Hue;
01688     *s  = (INT32) bob.HSVT.Saturation;
01689     *v  = (INT32) bob.HSVT.Value;
01690 }

UINT32 DocColour::GetReservedFlag  ) 
 

access fn.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/4/2000
Parameters:
- [INPUTS]
Returns:
the Reserved Flag of the ColourInfo struct
See also:

Definition at line 634 of file doccolor.cpp.

00635 {
00636     return Info.Reserved;
00637 }

void DocColour::GetRGBValue INT32 *  Red,
INT32 *  Green,
INT32 *  Blue
 

Definition at line 1644 of file doccolor.cpp.

01645 {
01646     ColourContextRGBT *CCrgbt = (ColourContextRGBT *)ColourContext::GetGlobalDefault(COLOURMODEL_RGBT);
01647     ColourRGBT result;
01648     ColourPacked bob;
01649 
01650     CCrgbt->ConvertColour((DocColour *)this, (ColourGeneric *)&result);
01651     CCrgbt->PackColour((ColourGeneric *)&result, (ColourPacked *)&bob);
01652 
01653     *Red    = (INT32) bob.RGBT.Red;
01654     *Green  = (INT32) bob.RGBT.Green;
01655     *Blue   = (INT32) bob.RGBT.Blue;
01656 }

void DocColour::GetSourceColour ColourGeneric Result  ) 
 

Determine the native definition of the given colour Notes: If this is a reference to an IndexedColour, returns the colour of the referenced IndexedColour.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
Parameters:
Result - pointer to structure to recieve the colour [INPUTS]
- [OUTPUTS]
Returns:
The native definition of the colour. This is a ColourPacked containing the colour as defined in its original Colour Model (cf DocColour::GetColourModel)

Errors: -

See also:
DocColour::GetColourModel

Definition at line 528 of file doccolor.cpp.

00529 {
00530     ENSURE(Info.SourceColourModel < MAX_COLOURMODELS,
00531             "DocColour based on illegal colour model!");
00532 
00533     // If colour is reference to indexed colour, ask the indexed colour for the
00534     // original colour definition, else return our own definition.
00535     if (Info.SourceColourModel == COLOURMODEL_INDEXED)
00536     {
00537         ENSURE(SourceColour.Indexed.Colour != NULL,
00538                 "Corrupted DocColour (NULL IndexedColour ref) detected");
00539         SourceColour.Indexed.Colour->GetSourceColour(Result);
00540     }
00541     else
00542         DEFAULTCONTEXT(Info.SourceColourModel)->
00543                                         UnpackColour(&SourceColour, Result);
00544 
00545     if (Info.ForceRounding)
00546     {
00547         // Our ForceRounding flag is on, so we must round all components to the closest
00548         // half percentage value. This is a bodge to correct for representational errors
00549         // in PANTONE library colours.
00550         double temp;
00551 
00552         temp = Result->Component1.MakeDouble();
00553         temp = (floor((temp * 200.0) + 0.5)) / 200.0;   // Round to nearest 200th
00554         Result->Component1 = temp;
00555 
00556         temp = Result->Component2.MakeDouble();
00557         temp = (floor((temp * 200.0) + 0.5)) / 200.0;   // Round to nearest 200th
00558         Result->Component2 = temp;
00559 
00560         temp = Result->Component3.MakeDouble();
00561         temp = (floor((temp * 200.0) + 0.5)) / 200.0;   // Round to nearest 200th
00562         Result->Component3 = temp;
00563 
00564         temp = Result->Component4.MakeDouble();
00565         temp = (floor((temp * 200.0) + 0.5)) / 200.0;   // Round to nearest 200th
00566         Result->Component4 = temp;
00567     }
00568 }

IndexedColour * DocColour::GetSpotParent void   ) 
 

To determine which spot colour (if any) is the ultimate spot colour parent of this DocColour. (i.e. to see which spot plate a DocColour will appear on).

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
25/6/96
Returns:
NULL if this DocColour does not reference an indexed colour, or if the referenced colour is not a spot colour, else A pointer to the ultimate parent spot colour of this colour.
Notes: This only returns a non-NULL result if this colour is a TRUE tint of a spot colour (as opposed to a tint of a process colour).

Definition at line 1525 of file doccolor.cpp.

01526 {
01527     IndexedColour *Parent = FindParentIndexedColour();
01528     if (Parent != NULL)
01529     {
01530         if (!Parent->IsSpotOrTintOfSpot())          // If we aren't a TRUE tint, return NULL
01531             return(NULL);
01532 
01533         Parent = Parent->FindOldestAncestor();      // ...else find our spot parent
01534         if (Parent->IsSpotOrTintOfSpot())           // (and check just to be really safe)
01535             return(Parent);
01536     }
01537 
01538     // no parent, or it's not a spot colour
01539     return(NULL);
01540 }

void DocColour::HackColReplacerPreDestruct  ) 
 

As you might expect from the name this is a real bodge. Basically the named colour replacer used in the brush needs to store some colours which are converted index colours. To cut a long story short I'm looking at a deadline and this prevents an assert upon destruction, theres no reason for anyone else to use it.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
10/6/2000
Parameters:
- [INPUTS]
Returns:
-
See also:

Definition at line 696 of file doccolor.cpp.

00697 {
00698     Info.SourceColourModel = MAX_COLOURMODELS;
00699 }

void DocColour::InitialiseInfoField ColourModel  ColModel  )  [protected]
 

Private shared code for construction of DocColour objects Initialises the 'Info' structure to default values Scope: private.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
-

Definition at line 150 of file doccolor.cpp.

00151 {
00152     ENSURE((INT32) ColModel < MAX_COLOURMODELS,
00153             "Attempt to use illegal colour model!");
00154 
00155     Info.Reserved           = 0;        // Reserved - set to zero for safety
00156 
00157     Info.OCContextHandle    = 0;
00158     Info.SourceColourModel  = ColModel;
00159     Info.CacheColourModel   = COLOURMODEL_NOTCACHED;
00160 
00161     Info.IsSeparable        = TRUE;
00162 
00163     Info.ForceRounding      = FALSE;
00164 
00165     Info.NoColour           = FALSE;
00166 }

BOOL DocColour::IsForcedToRound void   )  [inline]
 

Definition at line 247 of file doccolor.h.

00247 { return(Info.ForceRounding); };

BOOL DocColour::IsNamed void   ) 
 

to identidy if this colour is named, or was created from a named colour. Note that not all colours that were created by Named colours will have the relevant flag set, as I have only just started using it (4/2000). This fn. was really designed to be used specifically by the brush attribute replace named colours system.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/4/2000
Parameters:
- [INPUTS]
Returns:
TRUE, if this colour is named, or if it has the flag set that indicates that it was created by a named colour
See also:

Definition at line 658 of file doccolor.cpp.

00659 {
00660     BOOL RetVal = FALSE;
00661     
00662     // first try the parent colour
00663     IndexedColour* pParent = FindParentIndexedColour();
00664     if (pParent != NULL)
00665     {
00666         if (pParent->IsNamed())
00667             RetVal = TRUE;
00668     }
00669     
00670     // now try the flags
00671     if (Info.Reserved == COL_NAMED)
00672         RetVal = TRUE;
00673 
00674     return RetVal;
00675 }

BOOL DocColour::IsSeparable void   )  const [inline]
 

Determines if a colour's "IsSeparable" flag is set.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
17/5/96
Returns:
TRUE if the colour is allowed to be colour separated and/or corrected during colour conversions.
See also:
DocColour::SetSeparable

Definition at line 390 of file doccolor.h.

00391 {
00392     return(Info.IsSeparable);
00393 }

BOOL DocColour::IsTransparent void   )  const [inline]
 

Determines if a colour's "no colour" flag is set.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/04/94
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
TRUE if the colour is "no colour" ("transparent").
See also:
-

Definition at line 370 of file doccolor.h.

00371 {
00372     return(Info.NoColour);
00373 }

void DocColour::MakeRefToIndexedColour IndexedColour Other  ) 
 

Definition at line 1481 of file doccolor.cpp.

01482 {
01483     ENSURE(Other != NULL,
01484         "NULL IndexedColour pointer passed to DocColour::MakeRefToIndexedColour!");
01485 
01486     if (Info.SourceColourModel == COLOURMODEL_INDEXED)
01487     {
01488         ENSURE(SourceColour.Indexed.Colour != NULL,
01489                 "Corrupted DocColour (NULL IndexedColour ref) detected");
01490         SourceColour.Indexed.Colour->DecrementUsage();
01491     }
01492 
01493     Info.NoColour           = FALSE;
01494     Info.SourceColourModel  = COLOURMODEL_INDEXED;
01495     Info.CacheColourModel   = COLOURMODEL_NOTCACHED;    // NEVER cache indexed colours
01496     Info.OCContextHandle    = 0;
01497     Info.IsSeparable        = TRUE;                     // IxCols are always separable
01498 
01499     SourceColour.Indexed.Colour = Other;
01500     Other->IncrementUsage();
01501 }

void DocColour::MakeRefToIndexedColourDBG IndexedColour Other,
LPCSTR  TheFile = NULL,
INT32  TheLine = 0
 

DocColour assignment - Makes this DocColour a reference to the given Indexed Colour. The Indexed Colour cannot be deleted until this DocColour releases this claim upon it (which occurs when it is deleted or re-assigned).

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
03/05/94
Parameters:
Other - Indexed colour to assign [INPUTS]
- [OUTPUTS]
Returns:
Notes: This is not done as an "operator=" because it does NOT make an independent copy of the other colour, merely a reference to it; I force you to use this method in order to remind you of this. This makes the given DocColour a reference to an Indexed Colour, incrementing the usage count of that indexed colour. If this is already a reference to an indexed colour, that indexed colours usage count will be decremented.

Returns:
Errors: -
See also:
DocColour:FindParentIndexedColour

Definition at line 1466 of file doccolor.cpp.

01467 {
01468 #ifdef TRACECOLOURIX
01469     TRACE( _T(">> DocColour @ %x ref ColourIx: %x @ %s line %ld\n"), (INT32)this, (INT32)Other, TheFile, TheLine);
01470 #endif
01471 
01472 // Disable the debugging macro so that the function code will compile
01473 #undef MakeRefToIndexedColour
01474 // ---------
01475 
01476     MakeRefToIndexedColour(Other);
01477 }

void DocColour::Mix DocColour BlendStart,
DocColour BlendEnd,
double  BlendFraction,
ColourContext BlendContext,
BOOL  BlendTheLongWay = FALSE,
ColourContext OutputContext = NULL
 

"Constructor" for a DocColour - generates a blended DocColour The start and end colours are blended to create this new DocColour. The amount by which they are mixed is determined by BlendFraction. The blend occurs in the colourspace described by BlendContext. Note that BlendContext may be NULL, in which case the default context for the BlendStart colour will be used. However, this is not recommended, as this will result in a blend which may be incorrect for the context(s) in use in a given document, which could give seriously wonky colours!

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
11/11/94 (moved from constructor, 29/5/96)
Parameters:
BlendStart - The start DocColour [INPUTS]
BlendEnd - The end DocColour

BlendFraction - The amount by which the two colours should be blended, in the range 0.0 to 1.0. Blending is linear in the given colourspace, achieved by the equation

Result = (BlendStart * (1.0-BlendFraction)) + (BlendEnd * BlendFraction)

BlendContext - the colour context in which the blend will take place (may be NULL, but this is NOT recommended) (Note that this is ignored if either colour is a Spot) (Note that if both end colours are CMYK, and Mix effect is used, a CMYK context is used instead, so that CMYK grads colour separate properly)

BlendTheLongWay - (ONLY used if the BlendContext points to an HSV context) This indicates whether to do 'rainbow' (shortest distance- FALSE) or 'alt-rainbow' (longest distance- TRUE) HSV colour blending.

OutputContext - Normally, this should be NULL. However, if you're doing a colour separation involving spot colours, you should pass the output colour context in here, so that spots can be correctly separated. The output for mixing a spot colour will then be a greyscale ink intensity, correctly colour separated, and with its IsSeparable flag FALSE so that it is not colour separated or corrected a second time when output. It is safe to always pass the output context in here, as this function will always work out the appropriate behviour.

If blending is requested in HSV space, the extra parameter BlendTheLongWay is required, to determine if blending is done in a "Rainbow" or "Alt-Rainbow" fashion.

Notes: Note that although this may be slow, you must mix colours using this method, or colour correction/separation may not occur.

The blend method specified by BlendContext & BlendTheLongWay is ignored if either of the colours is a spot colour - these are always coerced into simple "Mix" fills/blends, as otherwise the printed output and colour representation on screen will be totally different!

If both end colours reference the same IndexedColour, and the mixing method is Mix (RGB) or Rainbow (HSV, BlendTheLongWay==FALSE), then all intermediate colours are identical, and are thus returned referencing the original indexed colour.

If both the end colours are tints of the same spot colour, then two things can occur: If OutputContext != NULL, we presume the mix is temporary for rendering to that context, so produce an RGB mix or separated Ink density value for the context. If OutputContext == NULL, we presume you're doing a make shapes on a blend or similar, so we create a new local colour for each mix, which is a permanent proper tint of the parent spot ink.

Definition at line 777 of file doccolor.cpp.

00780 {
00781 //  if (BlendFraction >= 1.0)
00782 //      BlendFraction = 0.999999999;
00783     
00784 //  ERROR3IF(BlendFraction < 0.0 || BlendFraction > 1.0,
00785 //              "DocColour::DocColour Blend: Illegal Blend fraction!");
00786 
00787     ERROR3IF(BlendStart == NULL || BlendEnd == NULL,
00788                 "DocColour::DocColour Blend: NULL input parameters!");
00789 
00790     // Make sure that this colour is not a reference to an IndexedColour, otherwise
00791     // if/when we InitialiseInfoField() below, we'll forget the reference, and trigger
00792     // lots of bogus "IndexedColour deleted while in use" warnings
00793     if (Info.SourceColourModel == COLOURMODEL_INDEXED)
00794     {
00795         SourceColour.Indexed.Colour->DecrementUsage();
00796         Info.SourceColourModel  = COLOURMODEL_RGBT;
00797     }
00798 
00799     // If either the start of end colour is a spot/tint colour, then we will coerce
00800     // this mix into a simple RGB mix, not a Hue mix, by grabbing the default RGB context
00801     // We also special-case a Mix/Rainbow from an IndexedColour to itself, by simply making 
00802     // the mixed step another reference to that colour (but not for alt-rainbow!)
00803     BOOL IncludesSpots = FALSE;         // Remember if we've got to worry about spots
00804 
00805     IndexedColour *StartParent  = BlendStart->FindParentIndexedColour();
00806     IndexedColour *EndParent    = BlendEnd->FindParentIndexedColour();
00807 
00808 
00809     // --- Are blend start/end colours identical? - we might optimise them out if they are
00810     if (StartParent != NULL && StartParent == EndParent)
00811     {
00812         // If it's an RGB Mix or an HSV Rainbow (short way) then all mixes are identical to
00813         // the original colour, so just return that instead.
00814         if ( BlendContext != NULL &&
00815              ( BlendContext->GetColourModel () == COLOURMODEL_RGBT || 
00816              ( BlendContext->GetColourModel () == COLOURMODEL_HSVT && !BlendTheLongWay ) ) )
00817         {
00818             // Make ourselves a reference to the parent colour
00819             MakeRefToIndexedColour ( StartParent );
00820             return;
00821         }
00822     }
00823 
00824 
00825     // --- Determine if one or both of the colours are spot/tint colours
00826     // (When separating, we must treat blends including spot colours very specially)
00827     if (StartParent != NULL && StartParent->IsSpotOrTintOfSpot())
00828         IncludesSpots = TRUE;
00829     else if (EndParent != NULL && EndParent->IsSpotOrTintOfSpot())
00830         IncludesSpots = TRUE;
00831 
00832     if (IncludesSpots)
00833     {
00834         // The blend includes spot colours, so must be coerced into an RGB "Mix"
00835         BlendContext = ColourManager::GetColourContext(COLOURMODEL_RGBT);
00836 
00837         IndexedColour *StartSpot = BlendStart->GetSpotParent();
00838         IndexedColour *EndSpot   = BlendEnd->GetSpotParent();
00839 
00840         if (OutputContext == NULL)
00841         {
00842             // Doing Make Shapes, so should make permanent IndexedColour tints, if
00843             // both the end colours are tints of the same spot colour
00844             if (StartSpot != NULL && StartSpot == EndSpot)
00845             {
00846                 MixTint(StartSpot, StartParent, EndParent, BlendFraction);
00847                 return;
00848             }
00849             // else drop through to normal RGB mixing code (which means the colours
00850             // become process colours. Damn! -- but there's nothing we can do about it)
00851         }
00852         else
00853         {
00854             ColourPlate *ColPlate = OutputContext->GetColourPlate();
00855 
00856             if (ColPlate != NULL && !ColPlate->IsDisabled())
00857             {
00858                 // Make us into a CMYK with the ink value in our Key component
00859                 // The Key is calculated below (in the if statement) but we'll do the common stuff here
00860                 InitialiseInfoField(COLOURMODEL_CMYK);
00861                 SourceColour.CMYK.Cyan = SourceColour.CMYK.Magenta = 
00862                                             SourceColour.CMYK.Yellow = 0;
00863 
00864                 if (ColPlate->GetType() == COLOURPLATE_SPOT)
00865                 {
00866                     // We're rendering to a spot plate, so we want to output an ink density value.
00867                     // Thus, we create a CMYK value, and place the ink density in the Key component.
00868                     // We will then set it non-separable so that it is not separated a second time
00869                     // (see after this if statement)
00870                     // (NOTE: IF both ends are tints of this spot plate, we'll interpolate the tint. If
00871                     // only one end is a spot colour, then the other end will become a 0% tint, i.e. white)
00872 
00873                     // Duh!  We need to check which spot plate we are doing or spot colours end up
00874                     // being printed on all spot plates!
00875 
00876                     IndexedColour* pPlateSpot = ColPlate->GetSpotColour();
00877 
00878                     // Work out the start and end tint values for use with the common ancestor (if any).
00879                     double StartValue = 0.0;
00880                     if (StartSpot != NULL && StartSpot == pPlateSpot)
00881                         StartValue = StartParent->GetAccumulatedTintValue().MakeDouble();
00882 
00883                     double EndValue  = 0.0;
00884                     if (EndSpot != NULL && EndSpot == pPlateSpot)
00885                         EndValue = EndParent->GetAccumulatedTintValue().MakeDouble();
00886 
00887                     // Linearly interpolate the tint values
00888                     double NewTint = (StartValue * (1.0 - BlendFraction)) + (EndValue * (BlendFraction));
00889 
00890                     SourceColour.CMYK.Key = (PColourValue) (NewTint * 255.0);
00891                 }
00892                 else
00893                 {
00894                     // Generate separated RGB versions of the end colours
00895                     ColourRGBT SeparatedStart;
00896                     if (BlendStart->IsTransparent())
00897                         OutputContext->GetWhite((ColourGeneric *) &SeparatedStart);
00898                     else
00899                         OutputContext->ConvertColour(BlendStart, (ColourGeneric *) &SeparatedStart);
00900 
00901                     ColourRGBT SeparatedEnd;
00902                     if (BlendEnd->IsTransparent())
00903                         OutputContext->GetWhite((ColourGeneric *) &SeparatedEnd);
00904                     else
00905                         OutputContext->ConvertColour(BlendEnd, (ColourGeneric *) &SeparatedEnd);
00906 
00907 
00908                     if (ColPlate->IsMonochrome())
00909                     {
00910                         // We're doing a monochrome sep
00911                         // The separated colour should be a greyscale, but let's just check
00912                         ERROR3IF(SeparatedStart.Red != SeparatedStart.Green ||
00913                                  SeparatedStart.Red != SeparatedStart.Blue,
00914                                  "Separated colour is not a greyscale! Doh!");
00915 
00916                         ERROR3IF(SeparatedEnd.Red != SeparatedEnd.Green ||
00917                                  SeparatedEnd.Red != SeparatedEnd.Blue,
00918                                  "Separated colour is not a greyscale! Doh!");
00919 
00920                         // Assuming that R==G==B, use the R levels as ink intensities, and generate
00921                         // this into the Key component
00922                         double temp;
00923                         BlendFraction *= 255.0;
00924                         temp = SeparatedStart.Red.MakeDouble() * (255.0 - BlendFraction);
00925                         temp += SeparatedEnd.Red.MakeDouble() * BlendFraction;
00926                         SourceColour.CMYK.Key = 255 - ((PColourValue) (temp + 0.5));
00927                     }
00928                     else
00929                     {
00930                         // We're doing a colour (e.g. screen preview in shades of Cyan or whatever)
00931                         // separation, so just mix the colour in RGB for previewing)
00932 
00933                         // Override the CMYK setting we just did above!
00934                         InitialiseInfoField(COLOURMODEL_RGBT);
00935 
00936                         // Now, generate an RGB mixed value
00937                         double temp;
00938                         BlendFraction *= 255.0;
00939                         temp = SeparatedStart.Red.MakeDouble() * (255.0 - BlendFraction);
00940                         temp += SeparatedEnd.Red.MakeDouble() * BlendFraction;
00941                         SourceColour.RGBT.Red = (PColourValue) (temp + 0.5);
00942 
00943                         temp = SeparatedStart.Green.MakeDouble() * (255.0 - BlendFraction);
00944                         temp += SeparatedEnd.Green.MakeDouble() * BlendFraction;
00945                         SourceColour.RGBT.Green = (PColourValue) (temp + 0.5);
00946 
00947                         temp = SeparatedStart.Blue.MakeDouble() * (255.0 - BlendFraction);
00948                         temp += SeparatedEnd.Blue.MakeDouble() * BlendFraction;
00949                         SourceColour.RGBT.Blue = (PColourValue) (temp + 0.5);
00950                     }
00951                 }
00952 
00953                 // Finally, set ourselves non-separable so that we are not colour corrected
00954                 // or separated a second time during output!
00955                 SetSeparable(FALSE);
00956 
00957                 // Let's get out of here before we're spotted! (sorry, last bad joke, I promise)
00958                 return;
00959             }
00960             // else drop through to do a normal RGB mix
00961         }
00962         // else drop through to do a normal RGB mix
00963     }
00964 
00965     // --- Check for CMYK -> CMYK fill
00966     // If we're doing an RGB mix and both colours are CMYK, then we will use CMYK mixing
00967     // instead of RGB, so that CMYK grads separate properly
00968     if (BlendContext != NULL && BlendContext->GetColourModel() == COLOURMODEL_RGBT &&
00969             BlendStart->GetColourModel() == COLOURMODEL_CMYK &&
00970             BlendEnd->GetColourModel() == COLOURMODEL_CMYK)
00971     {
00972         BlendContext = ColourManager::GetColourContext(COLOURMODEL_CMYK);
00973     }
00974 
00975 
00976     // OK, so we're not picking at our spots (I lied about that being the last bad joke).
00977     // In that case, do a normal mix
00978     if (BlendContext == NULL)
00979     {
00980         BlendContext = ColourManager::GetColourContext(BlendStart->GetColourModel());
00981         ERROR3IF(BlendContext == NULL, "Can't find a default ColourContext for blend colour space");
00982     }
00983 
00984     switch(BlendContext->GetColourModel())
00985     {
00986         case COLOURMODEL_RGBT:
00987             MixRGB(BlendStart, BlendEnd, BlendFraction, BlendContext);
00988             break;
00989 
00990         case COLOURMODEL_CMYK:
00991             MixCMYK(BlendStart, BlendEnd, BlendFraction, BlendContext);
00992             break;
00993 
00994         case COLOURMODEL_HSVT:
00995             MixHSV(BlendStart, BlendEnd, BlendFraction, BlendContext, BlendTheLongWay);
00996             break;
00997 
00998         default:
00999             ERROR3("DocColour::Mix unimplemented for BlendContext other then RGB or HSV");
01000             break;
01001     }
01002 
01003     // Finally, if both the start and end colour were non-separable, all intermediate
01004     // blended colours will also come out non-separable. This only usually has an effect with
01005     // the "print on all plates" attribute, which overrides the rendering colour with
01006     // special pre-separated greyscales
01007     if (!BlendStart->IsSeparable() && !BlendEnd->IsSeparable())
01008         SetSeparable(FALSE);
01009 }

void DocColour::MixCMYK DocColour BlendStart,
DocColour BlendEnd,
double  BlendFraction,
ColourContext BlendContext
[protected]
 

Internal helper function for DocColour::Mix. This is a reasonably optimised routine for mixing CMYK colours.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/6/96
Parameters:
BlendStart - The start DocColour [INPUTS] BlendEnd - The end DocColour BlendFraction - Blending amount between 0.0 and 1.0 BlendContext - the RGB colour context in which the blend will take place
See also:
DocColour::Mix

Definition at line 1114 of file doccolor.cpp.

01116 {
01117     ERROR3IF(BlendStart == NULL || BlendEnd == NULL || BlendContext == NULL, "Illegal NULL params");
01118     ERROR3IF(BlendContext->GetColourModel() != COLOURMODEL_CMYK,
01119              "DocColour::MixRGB is optimised for CMYK colours only!");
01120 
01121     InitialiseInfoField(COLOURMODEL_CMYK);
01122 
01123     ColourGeneric StartDef;
01124     if (BlendStart->IsTransparent())                    // If no-colour, then...
01125     {
01126         BlendContext->GetWhite(&StartDef);              // ... use white
01127 
01128         if (BlendEnd->IsTransparent())                  // If both ends no-colour, return no-colour
01129             Info.NoColour = TRUE;
01130     }
01131     else
01132         BlendContext->ConvertColour(BlendStart, &StartDef);     // else use start colour
01133 
01134     // If 0.0 then StartDef now has the colour to use (no blending necessary)
01135     // If BOTH colours are transparent, we will be NoColour, so no need to blend
01136     if (BlendFraction > 0.0 && !Info.NoColour)
01137     {
01138         ColourGeneric EndDef;
01139         if (BlendEnd->IsTransparent())                          // If no-colour then use white
01140             BlendContext->GetWhite(&EndDef);
01141         else
01142             BlendContext->ConvertColour(BlendEnd, &EndDef);
01143 
01144         // Precalculate the blending fractions. Optimisation - Multiply by 255 here to save
01145         // doing it for each component when we convert them into bytes below.
01146         BlendFraction *= 255.0;
01147         const double InverseFraction = (255.0 - BlendFraction);
01148 
01149         double temp;
01150 
01151         // Mix the CMYK components into a 0..255 byte, and store into our packed colour definition
01152         temp = StartDef.Component1.MakeDouble() * InverseFraction;
01153         temp += EndDef.Component1.MakeDouble() * BlendFraction;
01154         SourceColour.CMYK.Cyan = (PColourValue) (temp + 0.5);
01155 
01156         temp = StartDef.Component2.MakeDouble() * InverseFraction;
01157         temp += EndDef.Component2.MakeDouble() * BlendFraction;
01158         SourceColour.CMYK.Magenta = (PColourValue) (temp + 0.5);
01159 
01160         temp = StartDef.Component3.MakeDouble() * InverseFraction;
01161         temp += EndDef.Component3.MakeDouble() * BlendFraction;
01162         SourceColour.CMYK.Yellow = (PColourValue) (temp + 0.5);
01163 
01164         temp = StartDef.Component4.MakeDouble() * InverseFraction;
01165         temp += EndDef.Component4.MakeDouble() * BlendFraction;
01166         SourceColour.CMYK.Key = (PColourValue) (temp + 0.5);
01167     }
01168     else
01169     {
01170         // Pack the start colour straight into our SourceColour
01171         BlendContext->PackColour(&StartDef, &SourceColour);
01172     }
01173 }

void DocColour::MixHSV DocColour BlendStart,
DocColour BlendEnd,
double  BlendFraction,
ColourContext BlendContext,
BOOL  BlendTheLongWay = FALSE
[protected]
 

Internal helper function for DocColour::Mix. This is a reasonably optimised routine for mixing HSV colours.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/6/96
Parameters:
BlendStart - The start DocColour [INPUTS] BlendEnd - The end DocColour BlendFraction - Blending amount between 0.0 and 1.0 BlendContext - the HSV colour context in which the blend will take place BlendTheLongWay - FALSE for rainbow, TRUE for Alt-Rainbow mixing
See also:
DocColour::Mix

Definition at line 1198 of file doccolor.cpp.

01200 {
01201     ERROR3IF(BlendStart == NULL || BlendEnd == NULL || BlendContext == NULL, "Illegal NULL params");
01202     ERROR3IF(BlendContext->GetColourModel() != COLOURMODEL_HSVT,
01203                  "DocColour::MixHSV is optimised for HSV colours only!");
01204 
01205     InitialiseInfoField(COLOURMODEL_HSVT);
01206 
01207     ColourHSVT StartDef;
01208     if (BlendStart->IsTransparent())                            // If no-colour then use white
01209     {
01210         BlendContext->GetWhite((ColourGeneric *) &StartDef);
01211 
01212         if (BlendEnd->IsTransparent())                          // If both ends no-colour, return no-colour
01213             Info.NoColour = TRUE;
01214     }
01215     else
01216         BlendContext->ConvertColour(BlendStart, (ColourGeneric *) &StartDef);
01217 
01218     // If 0.0 then StartDef now has the colour to use (no blending necessary)
01219     // If BOTH colours are transparent, we will be NoColour, so no need to blend
01220     if (BlendFraction > 0.0 && !Info.NoColour)
01221     {
01222         ColourHSVT EndDef;
01223         if (BlendEnd->IsTransparent())                          // If no-colour then use white
01224             BlendContext->GetWhite((ColourGeneric *) &EndDef);
01225         else
01226             BlendContext->ConvertColour(BlendEnd, (ColourGeneric *) &EndDef);
01227 
01228         if (BlendTheLongWay)
01229         {
01230             // In Alt-rainbow blend, if exaclty one of the colours has undefined hue (it has 0 saturation
01231             // i.e. is black./grey/white), then Gavin decides to go to the Hue of the other colour
01232             // (i.e. do a full rainbow) rather than going to hue 0.
01233             if (StartDef.Saturation.MakeDouble() < 0.01 && EndDef.Saturation.MakeDouble() >= 0.01)
01234             {
01235                 // Start has no hue, but End does, so copy Hue from End
01236                 StartDef.Hue = EndDef.Hue;
01237             }
01238             else if (StartDef.Saturation.MakeDouble() >= 0.01 && EndDef.Saturation.MakeDouble() < 0.01)
01239             {
01240                 // End has no hue, but Start does, so copy Hue from Start
01241                 EndDef.Hue = StartDef.Hue;
01242             }
01243         }
01244 
01245         const double InverseFraction = 1.0 - BlendFraction;
01246 
01247         // HSV blend! We can go 2 ways, as HSV can 'wrap' from 1.0 back to 0.0
01248         BOOL BlendNormally = TRUE;
01249 
01250         // Calc. the "simple" (non-wrapping) distance between the hues
01251         double StartHue     = StartDef.Hue.MakeDouble();
01252         double EndHue       = EndDef.Hue.MakeDouble();
01253 
01254         const double SimpleDist = fabs(StartHue - EndHue);
01255 
01256         // Determine whether we do a simple blend, or we have to "wrap"
01257         if (SimpleDist <= 0.5)
01258             BlendNormally = !(BlendTheLongWay);
01259         else
01260             BlendNormally = BlendTheLongWay;
01261 
01262         // If we have to go the long way, then move the smaller of the two hue
01263         // values up by 360 degrees (1.0) - after blending we'll 'mod' the result
01264         // back down into gamut.
01265         if (!BlendNormally)
01266         {
01267             if (StartHue > EndHue)
01268                 EndHue += 1.0;
01269             else
01270                 StartHue += 1.0;
01271         }
01272 
01273         // Do the blend
01274         double temp;
01275         temp = StartHue * InverseFraction;
01276         temp +=  EndHue * BlendFraction;
01277 
01278         // And if we had to 'wrap', we must 'mod' the value back down into gamut
01279         if (temp > 1.0)
01280             temp -= 1.0;
01281 
01282         StartDef.Hue = temp;
01283 
01284         temp = StartDef.Saturation.MakeDouble() * InverseFraction;
01285         temp +=  EndDef.Saturation.MakeDouble() * BlendFraction;
01286         StartDef.Saturation = temp;
01287 
01288         temp = StartDef.Value.MakeDouble() * InverseFraction;
01289         temp +=  EndDef.Value.MakeDouble() * BlendFraction;
01290         StartDef.Value = temp;
01291     }
01292 
01293     // Pack the colour straight into our SourceColour
01294     BlendContext->PackColour((ColourGeneric *) &StartDef, &SourceColour);
01295 }

void DocColour::MixRGB DocColour BlendStart,
DocColour BlendEnd,
double  BlendFraction,
ColourContext BlendContext
[protected]
 

Internal helper function for DocColour::Mix. This is a reasonably optimised routine for mixing RGB colours.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/6/96
Parameters:
BlendStart - The start DocColour [INPUTS] BlendEnd - The end DocColour BlendFraction - Blending amount between 0.0 and 1.0 BlendContext - the RGB colour context in which the blend will take place
See also:
DocColour::Mix

Definition at line 1033 of file doccolor.cpp.

01035 {
01036     ERROR3IF(BlendStart == NULL || BlendEnd == NULL || BlendContext == NULL, "Illegal NULL params");
01037     ERROR3IF(BlendContext->GetColourModel() != COLOURMODEL_RGBT,
01038              "DocColour::MixRGB is optimised for RGB colours only!");
01039 
01040     InitialiseInfoField(COLOURMODEL_RGBT);
01041 
01042     ColourGeneric StartDef;
01043     if (BlendStart->IsTransparent())                    // If no-colour, then...
01044     {
01045         BlendContext->GetWhite(&StartDef);              // ... use white
01046 
01047         if (BlendEnd->IsTransparent())                  // If both ends no-colour, return no-colour
01048             Info.NoColour = TRUE;
01049     }
01050     else
01051         BlendContext->ConvertColour(BlendStart, &StartDef);     // else use start colour
01052 
01053     // If 0.0 then StartDef now has the colour to use (no blending necessary)
01054     // If BOTH colours are transparent, we will be NoColour, so no need to blend
01055     if (BlendFraction > 0.0 && !Info.NoColour)
01056     {
01057         ColourGeneric EndDef;
01058         if (BlendEnd->IsTransparent())                          // If no-colour then use white
01059             BlendContext->GetWhite(&EndDef);
01060         else
01061             BlendContext->ConvertColour(BlendEnd, &EndDef);
01062 
01063         // Precalculate the blending fractions. Optimisation - Multiply by 255 here to save
01064         // doing it for each component when we convert them into bytes below.
01065         BlendFraction *= 255.0;
01066         const double InverseFraction = (255.0 - BlendFraction);
01067 
01068         double temp;
01069 
01070         // Mix the RGB components into a 0..255 byte, and store into our packed colour definition
01071         temp = StartDef.Component1.MakeDouble() * InverseFraction;
01072         temp += EndDef.Component1.MakeDouble() * BlendFraction;
01073         SourceColour.RGBT.Red = (PColourValue) (temp + 0.5);
01074 
01075         temp = StartDef.Component2.MakeDouble() * InverseFraction;
01076         temp += EndDef.Component2.MakeDouble() * BlendFraction;
01077         SourceColour.RGBT.Green = (PColourValue) (temp + 0.5);
01078 
01079         temp = StartDef.Component3.MakeDouble() * InverseFraction;
01080         temp += EndDef.Component3.MakeDouble() * BlendFraction;
01081         SourceColour.RGBT.Blue = (PColourValue) (temp + 0.5);
01082 
01083         // We don't bother with component 4, as RGB doesn't use it
01084     }
01085     else
01086     {
01087         // Pack the start colour straight into our SourceColour
01088         BlendContext->PackColour(&StartDef, &SourceColour);
01089     }
01090 }

void DocColour::MixTint IndexedColour SpotParent,
IndexedColour StartTint,
IndexedColour EndTint,
double  BlendFraction
[protected]
 

Internal helper function for DocColour::Mix. This method is used to mix the DocColours to an IndexedColour result when one or both of the end colours are tints. This simply linearly interpolates the tint values.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/6/96
Parameters:
SpotParent - The IndexedColour which both tints share in common. This [INPUTS] MUST be the ultimate spot colour, not a tint half way down the linked chain.
StartTint - The tint colour for the start of the blend. Must be a true tint of SpotParent EndTint - The tint colour for the end of the blend. Must be a true tint of SpotParent

BlendFraction - Blending amount between 0.0 and 1.0

See also:
DocColour::Mix

Definition at line 1327 of file doccolor.cpp.

01329 {
01330     ERROR3IF(SpotParent == NULL || StartTint == NULL || EndTint == NULL,
01331                 "Illegal NULL params");
01332 
01333     ERROR3IF(SpotParent->GetType() != COLOURTYPE_SPOT, "SpotParent must be a spot colour!");
01334 
01335     ERROR3IF(!StartTint->IsSpotOrTintOfSpot(), "StartTint must be a true tint!");
01336     ERROR3IF(!EndTint->IsSpotOrTintOfSpot(), "EndTint must be a true tint!");
01337 
01338     ColourList *ColList = ColourManager::GetCurrentColourList();
01339     if (ColList == NULL)
01340     {
01341         ERROR3("No current colour list?!");
01342         return;
01343     }
01344 
01345     IndexedColour *MixedLocal = new IndexedColour;
01346     if (MixedLocal == NULL)
01347     {
01348         ERROR3("Couldn't create IndexedColour local mix");
01349         return;
01350     }
01351 
01352     // Work out the start and end tint values _for use with the common ancestor_.
01353     double StartValue = StartTint->GetAccumulatedTintValue().MakeDouble();
01354     double EndValue  = EndTint->GetAccumulatedTintValue().MakeDouble();
01355 
01356     // Linearly interpolate the tint values
01357     double NewTint = (StartValue * (1.0 - BlendFraction)) + (EndValue * (BlendFraction));
01358 
01359     // Fill in the new local colour appropriately
01360     MixedLocal->SetLinkedParent(SpotParent, COLOURTYPE_TINT);
01361     MixedLocal->SetTintValue(NewTint);
01362     MixedLocal->SetUnnamed();       // Ensure it's unnamed (local)
01363 
01364     // Add the local colour to the unnamed colour list
01365     ColList->AddItem(MixedLocal);
01366 
01367     // And make this DocColour reference the new local
01368     MakeRefToIndexedColour(MixedLocal);
01369 }

BOOL DocColour::operator!= const DocColour  Other  )  const
 

DocColour comparison operator Notes: If comparing two references to indexed colours, they will only be considered equal if they reference the SAME indexed colour (i.e. we do not compare the indexed colours).

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/04/94
Parameters:
Other - colour to compare ourselves against [INPUTS]
- [OUTPUTS]
Returns:
FALSE if we are identical to the other colour. NOTE that this will only be the case if we are both defined in the same colour model (i.e. pure red defined in HSVT is NOT equal to pure red in RGBT)

Errors: -

See also:
DocColour::GetColourModel

Definition at line 1601 of file doccolor.cpp.

01602 {
01603     return (Info.NoColour != Other.Info.NoColour ||
01604             Info.SourceColourModel != Other.Info.SourceColourModel ||
01605             memcmp(&SourceColour, &Other.SourceColour, sizeof(ColourPacked)) != 0 );
01606 }

DocColour & DocColour::operator= const DocColour Other  ) 
 

DocColour assignment operator Notes: If copying a reference to an indexed colour, the indexed colours usage count will be incremented. If this is already a reference to an indexed colour, that indexed colours usage count will be decremented.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/04/94
Parameters:
Other - colour to copy [INPUTS]
- [OUTPUTS]
Returns:
NOTE - SUPER IMPORTANT! This requires that the DocColour has been initialised by its constructor! You cannot thus treat an area of uninitialised memory as a DocColour and then try to initialise it using the copy constructor, as this could cause a fatal attempt to dereference a pointer. (This will hopefully be trapped by ENSURES)

If you need to initialise such a chunk of memory as a DocColour, then you'll need to call the Constructor in a special way. Ask Tim for details of how to do this.

Returns:
Errors: -

Definition at line 1400 of file doccolor.cpp.

01401 {
01402     ENSURE(Info.SourceColourModel < MAX_COLOURMODELS,
01403             "Attempt to use illegal colour model!");
01404 
01405     if (Info.SourceColourModel == COLOURMODEL_INDEXED)
01406     {
01407         ENSURE(SourceColour.Indexed.Colour != NULL,
01408                 "Corrupted DocColour (NULL IndexedColour ref) detected");
01409 
01410         CC_ASSERT_VALID(SourceColour.Indexed.Colour);
01411 
01412         SourceColour.Indexed.Colour->DecrementUsage();
01413     }
01414 
01415     Info = Other.Info;
01416     CachedColour = Other.CachedColour;
01417     SourceColour = Other.SourceColour;
01418 
01419     if (Info.SourceColourModel == COLOURMODEL_INDEXED)
01420     {
01421         ENSURE(SourceColour.Indexed.Colour != NULL,
01422                 "Corrupted DocColour (NULL IndexedColour ref) detected");
01423 
01424         SourceColour.Indexed.Colour->IncrementUsage();
01425         ENSURE(Info.CacheColourModel == 0, "RefToIndexedColour DocColour has a cache!!");
01426 
01427 #ifdef TRACECOLOURIX
01428 TRACE( _T(">> DocColour @ %x = (DocColour => ColourIx %x)\n"), (INT32)this, (INT32)SourceColour.Indexed.Colour);
01429 #endif
01430     }
01431 
01432     return(*this);
01433 }

BOOL DocColour::operator== const DocColour  Other  )  const
 

DocColour comparison operator.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
14/04/94
Parameters:
Other - colour to compare ourselves against [INPUTS]
- [OUTPUTS]
Returns:
TRUE if we are 'identical' to the other colour.
Notes: When comparing 2 colours, they will be considered equal if: They are both 'no colour' (fully transparent), or They are *exactly* equal, i.e. the same colour defined in the same colour model (Pure RGB red is NOT equal to pure HSV red)

Note that for this comparison, references to indexedcolours are compared as references, i.e. it does NOT compare the definitions of IndexedColours, only the pointer to the IndexedColours (so IndexedColour references are essentially treated as another colour model)

Returns:
Errors: -
See also:
DocColour::GetColourModel

Definition at line 1569 of file doccolor.cpp.

01570 {
01571     if (Info.NoColour && Other.Info.NoColour)
01572         return(TRUE);
01573 
01574     return (Info.NoColour == Other.Info.NoColour &&
01575             Info.SourceColourModel == Other.Info.SourceColourModel &&
01576             memcmp(&SourceColour, &Other.SourceColour, sizeof(ColourPacked)) == 0 );
01577 }

void DocColour::SetCMYKValue PColourCMYK New  ) 
 

Definition at line 1693 of file doccolor.cpp.

01694 {
01695     if (Info.SourceColourModel == COLOURMODEL_INDEXED)
01696     {
01697         ENSURE(SourceColour.Indexed.Colour != NULL,
01698                 "Corrupted DocColour (NULL IndexedColour ref) detected");
01699         SourceColour.Indexed.Colour->DecrementUsage();
01700     }
01701 
01702     InitialiseInfoField(COLOURMODEL_CMYK);
01703 
01704     memcpy(&SourceColour, New, sizeof(PColourCMYK));
01705 }

void DocColour::SetHSVValue INT32  h,
INT32  s,
INT32  v
 

Definition at line 1659 of file doccolor.cpp.

01661 {
01662     if (Info.SourceColourModel == COLOURMODEL_INDEXED)
01663     {
01664         ENSURE(SourceColour.Indexed.Colour != NULL,
01665                 "Corrupted DocColour (NULL IndexedColour ref) detected");
01666         SourceColour.Indexed.Colour->DecrementUsage();
01667     }
01668 
01669     InitialiseInfoField(COLOURMODEL_HSVT);
01670 
01671     SourceColour.HSVT.Hue           = (PColourValue) h;
01672     SourceColour.HSVT.Saturation    = (PColourValue) s;
01673     SourceColour.HSVT.Value         = (PColourValue) v;
01674     SourceColour.HSVT.Transparent   = 0;    
01675 }

void DocColour::SetReservedFlag UINT32  Value  ) 
 

To set the Reserved flag of the colour info struct.

Author:
Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
Date:
12/4/2000
Parameters:
Value - the value to set the flag to [INPUTS]
See also:
My use of this flag can be seen in LineDefinition::ConvertIndexedColours and PathProcessorBrush::RenderAttributes. If you want to use this flag for your own purposes I suggest that you take a look at what I've done to make sure there will be no conflict.

Definition at line 614 of file doccolor.cpp.

00615 {
00616     Info.Reserved = Value;
00617 }

void DocColour::SetRGBValue INT32  Red,
INT32  Green,
INT32  Blue
 

Definition at line 1625 of file doccolor.cpp.

01627 {
01628     if (Info.SourceColourModel == COLOURMODEL_INDEXED)
01629     {
01630         ENSURE(SourceColour.Indexed.Colour != NULL,
01631                 "Corrupted DocColour (NULL IndexedColour ref) detected");
01632         SourceColour.Indexed.Colour->DecrementUsage();
01633     }
01634 
01635     InitialiseInfoField(COLOURMODEL_RGBT);
01636 
01637     SourceColour.RGBT.Red   = (PColourValue) Red;
01638     SourceColour.RGBT.Green = (PColourValue) Green;
01639     SourceColour.RGBT.Blue  = (PColourValue) Blue;
01640     SourceColour.RGBT.Transparent = 0;  
01641 }

void DocColour::SetSeparable BOOL  IsSeparable = TRUE  ) 
 

To set the separation/correction enable flag for a DocColour. Some colours (e.g. EOR blob colours) should not be colour-separated on screen. By default, all colours (except StockCols) will separate, but this flag can be set on "UI colours" to stop them separating.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/03/94
Parameters:
IsSeparable - TRUE if this colour will be allowed to be separated and [INPUTS] colour-corrected during conversions FALSE if this colour shouldn't be separated
See also:
DocColour::IsSeparable

Definition at line 591 of file doccolor.cpp.

00592 {
00593     Info.IsSeparable = IsSeparable;
00594 }

void DocColour::ZapSourceColour  )  [inline, protected]
 

Definition at line 314 of file doccolor.h.

00314 {memset(&SourceColour, 0, sizeof(SourceColour)); memset(&CachedColour, 0, sizeof(CachedColour)); }


Friends And Related Function Documentation

friend class ColourContext [friend]
 

Definition at line 181 of file doccolor.h.


Member Data Documentation

ColourPacked DocColour::CachedColour [protected]
 

Definition at line 305 of file doccolor.h.

ColourInfo DocColour::Info [protected]
 

Definition at line 303 of file doccolor.h.

ColourPacked DocColour::SourceColour [protected]
 

Definition at line 304 of file doccolor.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:53:41 2007 for Camelot by  doxygen 1.4.4