gradtbl.cpp

Go to the documentation of this file.
00001 // $Id: gradtbl.cpp 1372 2006-06-27 11:23:21Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 // Classes to implement the graduation tables required for special path filling attributes.
00100 
00101 /*
00102 */
00103 
00104 #include "camtypes.h"
00105 
00106 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 #include "colormgr.h"
00108 #include "colplate.h"
00109 //#include "doccolor.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 #include "devcolor.h"
00111 #include "grndrgn.h"
00112 #include "gradtbl.h"
00113 //#include "xaracms.h"
00114 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 #include "fillramp.h"
00116 
00117 DECLARE_SOURCE("$Revision: 1372 $");
00118 
00119 CC_IMPLEMENT_DYNCREATE(GradTable, CCObject)
00120 CC_IMPLEMENT_DYNCREATE(TranspGradTable, CCObject)
00121 CC_IMPLEMENT_DYNCREATE(GradTable32, CCObject)
00122 
00123 // This will get Camelot to display the filename and linenumber of any memory allocations
00124 // that are not released at program exit
00125 #define new CAM_DEBUG_NEW
00126 
00127 
00128 /********************************************************************************************
00129  * NOTE                                                                                     *
00130  * There are now 2 functions in this file which build graduation tables. The tables are     *
00131  * actually identical in meaning, but are encoded as (a) Gavin 8bpp dither patterns, and    *
00132  * (b) RGBQUAD RGB structures or COLORREF RGB values - this is because the different        *
00133  * places that use these tables demand the different formats, and converting all the code   *
00134  * to use only one table format is non-trivial and/or inefficient.                          *
00135  *******************************************************************************************/
00136 
00137 
00138 // FillStep
00139 // This constant is used when filling grad tables for COLOURPLATE_COMPOSITE modes.
00140 //
00141 // Each ConvertColour is mindbogglingly slow (over 52 multiplies) so to get some
00142 // speed without too much loss of quality, we calculate proper values for every
00143 // 16th entry of the table, and linearly interpolate between them. Note that we can't
00144 // increase the step size beyond about 16, or rainbow fills will start going wrong.
00145 // 
00146 // Decreasing this constant to 1 will slow down Composite preview rendering an awful lot, 
00147 // but may slightly improve display quality.
00148 //
00149 const DWORD FillStep = 16;      // Number of interpolated colours between proper samples
00150 
00151 
00152 
00153 /********************************************************************************************
00154 
00155 >   GradTable::GradTable(BOOL LargeTable = FALSE)
00156 
00157     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00158     Created:    14/9/94
00159     Purpose:    Default constructor for a GradTable
00160 
00161     Notes:      Sets the default table size to 0x100 entries long
00162 
00163     SeeAlso:    GradTable::SetTableSize
00164 
00165 ********************************************************************************************/
00166 
00167 GradTable::GradTable(BOOL LargeTable)
00168 {
00169     m_bLargeTable = LargeTable;
00170     m_pTable = NULL;
00171 }
00172 
00173 
00174 
00175 /********************************************************************************************
00176 
00177 >   GradTable::~GradTable()
00178 
00179     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00180     Created:    16/10/96
00181     Purpose:    Destructor for a GradTable
00182 
00183 ********************************************************************************************/
00184 
00185 GradTable::~GradTable()
00186 {
00187     if (m_pTable != NULL)
00188     {
00189         CCFree(m_pTable);
00190         m_pTable = NULL;
00191     }
00192 }
00193 
00194 
00195 
00196 /********************************************************************************************
00197 
00198 >   INT32 GradTable::GetTableSize(GDrawContext* GD, BOOL LargeTable)
00199 
00200     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00201     Created:    17/10/96
00202     Inputs:     GD - pointer to GDraw context to use
00203                 LargeTable - if true then use a long grad table
00204     Returns:    The size in bytes of a grad table for the specified context
00205 
00206 ********************************************************************************************/
00207 
00208 INT32 GradTable::GetTableSize(GDrawContext* GD, BOOL LargeTable)
00209 {
00210     if (LargeTable)
00211     {
00212         return(GD->GetLongGraduationTableSize());
00213     }
00214     else
00215     {
00216         return(GD->GetGraduationTableSize());
00217     }
00218 }
00219 
00220 
00221 
00222 /********************************************************************************************
00223 
00224 >   INT32 GradTable::GetTableLength(GDrawContext* GD, BOOL LargeTable)
00225 
00226     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00227     Created:    17/10/96
00228     Inputs:     GD - pointer to GDraw context to use
00229                 LargeTable - if true then use a long grad table
00230     Returns:    The number of entries in a grad table for the specified context
00231 
00232 ********************************************************************************************/
00233 
00234 INT32 GradTable::GetTableLength(GDrawContext* GD, BOOL LargeTable)
00235 {
00236     if (LargeTable)
00237     {
00238         return(GD->GetLongGraduationTableLength());
00239     }
00240     else
00241     {
00242         return(GD->GetGraduationTableLength());
00243     }
00244 }
00245 
00246 
00247 /********************************************************************************************
00248 
00249 >   void GradTable::SetTableSize(BOOL LargeTable = FALSE)
00250 
00251     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
00252     Created:    17/10/96
00253 
00254     Inputs:     LargeTable - if true then use a long grad table
00255 
00256     Purpose:    To set the size of this Grad table
00257 
00258     Notes:      The table defaults to small
00259 
00260 ********************************************************************************************/
00261 
00262 void GradTable::SetTableSize(BOOL LargeTable)
00263 {
00264     // If we don't have the right table size or no table at all
00265     if ((LargeTable != m_bLargeTable) || (m_pTable == NULL))
00266     {
00267         m_bLargeTable = LargeTable;
00268 
00269         if (m_pTable != NULL)
00270         {
00271             CCFree(m_pTable);
00272             m_pTable = NULL;
00273         }
00274 
00275         GDrawContext *GD = GRenderRegion::GetStaticDrawContext();
00276 
00277         if (GD != NULL)
00278         {
00279             INT32 Size = GetTableSize(GD, m_bLargeTable);
00280             
00281             m_pTable = (GraduationTable*) CCMalloc(Size);
00282 
00283             if (m_pTable != NULL)
00284             {
00285                 m_pTable->Length = GetTableLength(GD, LargeTable);
00286             }
00287         }
00288     }
00289 }
00290 
00291 
00292 
00293 /********************************************************************************************
00294 
00295 >   BOOL GradTable::BuildTable(DocColour &StartCol, DocColour &EndCol,
00296                                 View *ContextView, EFFECTTYPE Effect,
00297                                 DWORD FirstEntry, DWORD LastEntry)
00298 
00299     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (Will)
00300     Created:    14/5/96 (14/9/94)
00301 
00302     Inputs:     StartCol, EndCol - Define the end colours of the graduation
00303                 ContextView - Points to the view in which the gradation is to be displayed.
00304                               (This is necessary for correction and separation etc. If proper
00305                               colour handling is not needed, then you may pass NULL, but
00306                               generally, this parameter should be sensible)
00307 
00308                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
00309 
00310                 TableSize   - The number of entries you wish to make the table (0x100 or
00311                               0x800)
00312 
00313     Returns:    FALSE if it fails
00314 
00315     Purpose:    Builds a GradTable from StartCol to EndCol, filling in the entire
00316                 table with appropriate GDraw dither patterns.
00317                 
00318                 == NOTE that this version of the call also implicitly sets the table size! == 
00319 
00320     SeeAlso:    GradTable::SetTableSize
00321 
00322 ********************************************************************************************/
00323                                                                                  
00324 BOOL GradTable::BuildTable(DocColour &StartCol, DocColour &EndCol,
00325                             View *ContextView, EFFECTTYPE Effect,
00326                             BOOL LargeTable)
00327 {
00328     SetTableSize(LargeTable);
00329 
00330     return(BuildTable(StartCol, EndCol, ContextView, Effect, 0, m_pTable->Length));
00331 }
00332 
00333 
00334 
00335 /********************************************************************************************
00336 
00337 >   void GradTable::FillTable(DWORD StartIndex, DWORD EndIndex,
00338                             PColourRGBT *StartDef, PColourRGBT *EndDef)
00339 
00340     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00341     Created:    21/7/96
00342 
00343     Inputs:     StartIndex, EndIndex - Define the indices into the grad fill table
00344                 between which you want to fill in the table. NOTE that Table[StartIndex]
00345                 is filled in, while table[EndIndex] is NOT.
00346                 StartDef, EndDef - Define the end colours of the graduation
00347 
00348     Purpose:    Builds a GradTable from StartIndex to EndIndex by linearly interpolating
00349                 between the StartDef and EndDef RGB colours.
00350 
00351     Notes:      In order to correctly handle Rainbow fills, you must interpolate only small
00352                 sections of the table - it is recommended that you fill no more than 16
00353                 entries of the table at a time with this linear interpolation.
00354 
00355 ********************************************************************************************/
00356 
00357 void GradTable::FillTable(DWORD StartIndex, DWORD EndIndex,
00358                             PColourRGBT *StartDef, PColourRGBT *EndDef)
00359 {
00360     GDrawContext *GD = GRenderRegion::GetStaticDrawContext();
00361 
00362     // Place the StartDef in as the first entry
00363     GD->AddToGraduationTable(RGB(StartDef->Red, StartDef->Green, StartDef->Blue),
00364                                 FALSE, m_pTable, StartIndex);
00365 
00366     // ...and start interpolating from the second entry
00367     DWORD MixStep = (1 << 24) / (EndIndex - StartIndex);
00368     DWORD MixFraction = MixStep;
00369 
00370     DWORD R,G,B;
00371     for (DWORD Index = StartIndex + 1; Index < EndIndex; Index++)
00372     {
00373         // Calculate intermediate RGB values into 8bpp values
00374         R = (StartDef->Red * (0x01000000 - MixFraction)) + (EndDef->Red * MixFraction);
00375         R >>= 24;
00376 
00377         G = (StartDef->Green * (0x01000000 - MixFraction)) + (EndDef->Green * MixFraction);
00378         G >>= 24;
00379 
00380         B = (StartDef->Blue * (0x01000000 - MixFraction)) + (EndDef->Blue * MixFraction);
00381         B >>= 24;
00382 
00383         // Get Gavin to fill in the dither entry for us (FALSE means it's an RGB Indexour)
00384         GD->AddToGraduationTable(RGB(R,G,B), FALSE, m_pTable, Index);
00385 
00386         MixFraction += MixStep;
00387     }
00388 }
00389 
00390 
00391 
00392 /********************************************************************************************
00393 
00394 >   BOOL GradTable::BuildTable(DocColour &StartCol, DocColour &EndCol,
00395                                 View *ContextView, EFFECTTYPE Effect,
00396                                 DWORD FirstEntry, DWORD LastEntry)
00397 
00398     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (Will)
00399     Created:    14/5/96 (14/9/94)
00400 
00401     Inputs:     StartCol, EndCol - Define the end colours of the graduation
00402                 ContextView - Points to the view in which the gradation is to be displayed.
00403                               (This is necessary for correction and separation etc. If proper
00404                               colour handling is not needed, then you may pass NULL, but
00405                               generally, this parameter should be sensible)
00406 
00407                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
00408 
00409                 FirstEntry  - The index of the first entry (inclusive) to fill in (0 is the first)
00410                 LastEntry   - The index of the last entry (exclusive) to fill in (TableSize is the last)
00411                                 (i.e. to fill entire table use (0,TableSize) which will fill in entries
00412                                     0..Tablesize-1)
00413 
00414     Returns:    FALSE if it fails
00415 
00416     Purpose:    Builds a GradTable from StartCol to EndCol, filling in a portion of the
00417                 table with appropriate GDraw dither patterns
00418 
00419     Notes:      GDraw requires the Start and End colours for the entire table to be
00420                 set separately in the table structure. These will be set if FirstEntry==0
00421                 and/or if LastEntry==TableSize, respectively.
00422 
00423                 No longer calls GDraw to build the table. The colours are generated
00424                 by us (mainly so that we can support proper colour correction and
00425                 separation by allowing the colour system to do its stuff)
00426 
00427                 This method could be somewhat more optimal than it is, if we start
00428                 poking around more in the internals of the colour system. For the time
00429                 being, I'm leaving it tidy, however.
00430 
00431     Errors:     ERROR2's if it runs out of memory
00432 
00433     SeeAlso:    GradTable::SetTableSize
00434 
00435 ********************************************************************************************/
00436                                                                                  
00437 BOOL GradTable::BuildTable(DocColour &StartCol, DocColour &EndCol,
00438                             View *ContextView, EFFECTTYPE Effect,
00439                             DWORD FirstEntry, DWORD LastEntry)
00440 {
00441     // The range should be within the table size. We only ERROR3, though, because
00442     // the physical table is always large enough for the maximum number of entries.
00443 
00444     ERROR3IF(FirstEntry < 0 || FirstEntry > LastEntry || LastEntry > m_pTable->Length,
00445                 "GradTable::BuildTable expects sensible First/Last Entry values");
00446 
00447     // Find a GDraw context to generate dithertable entries for us
00448     GDrawContext *GD = GRenderRegion::GetStaticDrawContext();
00449     ERROR3IF(GD == NULL, "GradTable::BuildTable - No GDraw context?!");
00450 
00451     // Determine if either the start or end colour is a spot colour - if it is, we must
00452     // coerce the fill into a "mix" (rgb) rather than rainbow fill style
00453     if (Effect != EFFECT_RGB && (StartCol.GetSpotParent() != NULL || EndCol.GetSpotParent() != NULL))
00454         Effect = EFFECT_RGB;
00455 
00456     // Get colour contexts: we need 2 - first, an RGB context for the ContextView, which
00457     // will be used to get colour-corrected/separated/etc output colour in RGB; and second,
00458     // a generic RGB or HSV context to provide a "mixing colourspace" for the graduations.
00459     ColourContext *cc = NULL;
00460     ColourContext *ccRGB = ColourManager::GetColourContext(COLOURMODEL_RGBT, ContextView);
00461 
00462     if (Effect == EFFECT_RGB)
00463         cc = ColourManager::GetColourContext(COLOURMODEL_RGBT);     // RGB fade
00464     else
00465         cc = ColourManager::GetColourContext(COLOURMODEL_HSVT);     // HSV fade
00466 
00467     // If we can't find RGB/HSV contexts, something is seriously broken
00468     ERROR3IF(cc == NULL || ccRGB == NULL,
00469             "GradTable::BuildTable - Can't find my colour context!");
00470 
00471     // Fill in the Start and End colours of the table, if we've hit them
00472     PColourRGBT Result;
00473 
00474     if (FirstEntry == 0)
00475     {
00476         ccRGB->ConvertColour(&StartCol, (ColourPacked *) &Result);
00477         m_pTable->StartColour = RGB(Result.Red, Result.Green, Result.Blue);
00478     }
00479 
00480     if (LastEntry >= m_pTable->Length)
00481     {
00482         LastEntry = m_pTable->Length;
00483         ccRGB->ConvertColour(&EndCol, (ColourPacked *) &Result);
00484         m_pTable->EndColour = RGB(Result.Red, Result.Green, Result.Blue);
00485     }
00486 
00487     const BOOL ValidColourPlate = (ccRGB->GetColourPlate() != NULL && !ccRGB->GetColourPlate()->IsDisabled());
00488 
00489     if (ValidColourPlate || 
00490         FirstEntry > 0 || 
00491         LastEntry < m_pTable->Length)
00492     {
00493         if (ValidColourPlate && ccRGB->GetColourPlate()->GetType() == COLOURPLATE_COMPOSITE)
00494         {
00495             // We're doing a composite print preview.
00496             PColourRGBT StartDef;
00497             PColourRGBT EndDef;
00498             ccRGB->ConvertColour(&StartCol, (ColourPacked *) &EndDef);
00499 
00500             DWORD StartIndex = FirstEntry;
00501             DWORD EndIndex;
00502 
00503             DocColour TempCol;
00504 
00505             while (StartIndex < LastEntry)
00506             {
00507                 // Move the last run's end colour into Start
00508                 memcpy(&StartDef, &EndDef, sizeof(PColourRGBT));
00509 
00510                 // Calculate the end of this run
00511                 EndIndex = StartIndex + FillStep;
00512                 if (EndIndex > LastEntry)
00513                     EndIndex = LastEntry;
00514     
00515                 // Calculate the colour at the end of this run, and convert into EndDef
00516                 TempCol.Mix(&StartCol, &EndCol,
00517                             ((double)(EndIndex - FirstEntry)) / ((double)(LastEntry - FirstEntry)),
00518                             cc, (Effect == EFFECT_HSV_LONG), ccRGB);
00519 
00520                 ccRGB->ConvertColour(&TempCol, (ColourPacked *) &EndDef);
00521 
00522                 // Linearly interpolate all colours in the run
00523                 FillTable(StartIndex, EndIndex, &StartDef, &EndDef);
00524 
00525                 // And step on to the next run
00526                 StartIndex = EndIndex;
00527             }
00528         }
00529         else
00530         {
00531             // We have some type of colour separation on the go - we must convert all intermediate
00532             // colours through the colour system in order to ensure the results are correct.
00533             // This is quite slow, but acceptable (ish) when printing.
00534             double MixFraction  = 0.0;
00535             // This next line requires the -1 because otherwise it doesn't reach the end colour
00536             // This is ok if LastEntry = StartEntry + 1 as MixStep will be calculated as zero
00537             // and the StartCol will be used to fill in the single entry required
00538             double denumerator = (double) (LastEntry - FirstEntry - 1);
00539             double MixStep = 0;
00540             if (denumerator != 0)
00541             {
00542                 MixStep = 1.0 / denumerator;
00543             }
00544 
00545             DocColour temp;
00546             for (DWORD col = FirstEntry; col < LastEntry; col++)
00547             {
00548                 // Create a new colour which is an appropriate mixture of the start/end colours
00549                 temp.Mix(&StartCol, &EndCol, MixFraction, cc, (Effect == EFFECT_HSV_LONG), ccRGB);
00550 
00551                 // Convert back to the raw RGB and place it in the palette.
00552                 // Note that this will colour correct and separate in an appropriate manner.
00553                 // Note also that we're using a special ConvertColour call which returns 8-bit 
00554                 // "packed" component values instead of FIXED24's.
00555                 ccRGB->ConvertColour(&temp, (ColourPacked *) &Result);
00556 
00557                 // Get GDraw to fill in the dither entry for us (FALSE means it's an RGB colour)
00558                 GD->AddToGraduationTable(RGB(Result.Red, Result.Green, Result.Blue), FALSE, m_pTable, col);
00559 
00560                 // And step to the next mix fraction value
00561                 MixFraction += MixStep;
00562             }
00563         }
00564     }
00565     else
00566     {
00567         // We're doing a completely normal view, and building the entire 256-entry table, so
00568         // call GDraw to blindly interpolate between the colours, which is much (much) faster.
00569         GD->BuildGraduationTable(m_pTable->StartColour, m_pTable->EndColour, Effect, m_pTable);
00570     } 
00571 
00572     return(TRUE);
00573 }
00574 
00575 
00576 
00577 /********************************************************************************************
00578 
00579 >   BOOL GradTable::BuildTable(DocColour &StartCol, DocColour &EndCol,
00580                                View *ContextView, EFFECTTYPE Effect,
00581                                CProfileBiasGain& BiasGain, BOOL LargeTable)
00582 
00583     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00584     Created:    4/2/2000
00585     Inputs:     StartCol, EndCol - Define the end colours of the graduation
00586                 pColList    - Define the colours and positions of a colour ramp
00587                 ContextView - Points to the view in which the gradation is to be displayed.
00588                               (This is necessary for correction and separation etc. If proper
00589                               colour handling is not needed, then you may pass NULL, but
00590                               generally, this parameter should be sensible)
00591 
00592                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
00593 
00594                 BiasGain    - The baisgain values that are to alter the fill table
00595 
00596                 TableSize   - The number of entries you wish to make the table (0x100 or
00597                               0x800)
00598     Returns:    TRUE, error thrown otherwise (but only for input variables)
00599     Purpose:    Generates a graduated fill table that is modified by biasgain values.
00600     SeeAlso:    -
00601 
00602 ********************************************************************************************/
00603 
00604 BOOL GradTable::BuildTable(DocColour &StartCol, DocColour &EndCol,
00605                             View *ContextView, EFFECTTYPE Effect,
00606                             CProfileBiasGain& BiasGain, BOOL LargeTable)
00607 {   
00608     // Find a GDraw context to generate dithertable entries for us
00609     GDrawContext *GD = GRenderRegion::GetStaticDrawContext();
00610     ERROR3IF(GD == NULL, "GradTable::BuildTable - No GDraw context?!");
00611 
00612     // Determine if either the start or end colour is a spot colour - if it is, we must
00613     // coerce the fill into a "mix" (rgb) rather than rainbow fill style
00614     if (Effect != EFFECT_RGB && (StartCol.GetSpotParent() != NULL || EndCol.GetSpotParent() != NULL))
00615         Effect = EFFECT_RGB;
00616 
00617     // Get colour contexts: we need 2 - first, an RGB context for the ContextView, which
00618     // will be used to get colour-corrected/separated/etc output colour in RGB; and second,
00619     // a generic RGB or HSV context to provide a "mixing colourspace" for the graduations.
00620     ColourContext *cc = NULL;
00621     ColourContext *ccRGB = ColourManager::GetColourContext(COLOURMODEL_RGBT, ContextView);
00622 
00623     if (Effect == EFFECT_RGB)
00624         cc = ColourManager::GetColourContext(COLOURMODEL_RGBT);     // RGB fade
00625     else
00626         cc = ColourManager::GetColourContext(COLOURMODEL_HSVT);     // HSV fade
00627 
00628     // If we can't find RGB/HSV contexts, something is seriously broken
00629     ERROR3IF(cc == NULL || ccRGB == NULL,
00630             "GradTable::BuildTable - Can't find my colour context!");
00631 
00632     // Fill in the Start and End colours of the table, if we've hit them
00633     PColourRGBT Result;
00634 
00635     // set our table size for this grad
00636     SetTableSize(LargeTable);
00637 
00638     ccRGB->ConvertColour(&StartCol, (ColourPacked *) &Result);
00639     m_pTable->StartColour = RGB(Result.Red, Result.Green, Result.Blue);
00640 
00641     ccRGB->ConvertColour(&EndCol, (ColourPacked *) &Result);
00642     m_pTable->EndColour = RGB(Result.Red, Result.Green, Result.Blue);
00643 
00644     BiasGain.SetIntervals (AFp (0), AFp (m_pTable->Length));
00645 
00646     const INT32 TableLength = m_pTable->Length;
00647     double MixFraction;
00648     DocColour temp;
00649     INT32 r, g, b;
00650     double res;
00651 
00652     for (INT32 col = 0; col < TableLength; col++)
00653     {
00654         res = BiasGain.MapInterval( AFp( col ) );
00655         
00656         MixFraction = res / TableLength;
00657         
00658         // Create a new colour which is an appropriate mixture of the start/end colours
00659         temp.Mix(&StartCol, &EndCol, MixFraction, cc, (Effect == EFFECT_HSV_LONG), ccRGB);
00660         temp.GetRGBValue (&r, &g, &b);
00661 
00662         // Get GDraw to fill in the dither entry for us (FALSE means it's an RGB colour)
00663         GD->AddToGraduationTable(RGB(r, g, b), FALSE, m_pTable, col);
00664     }
00665     
00666     return (TRUE);
00667 }
00668 
00669 
00670 
00671 /********************************************************************************************
00672 
00673 >   BOOL GradTable::BuildHighQualityRepeatTable(DocColour &StartCol, DocColour &EndCol, ColourRamp *pColourRamp,
00674                                                 View *ContextView, EFFECTTYPE Effect)
00675 
00676     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00677     Created:    4/2/2000
00678     Inputs:     StartCol, EndCol - Define the end colours of the graduation
00679                 pColourRamp - Define the colours and positions of a colour ramp
00680                 ContextView - Points to the view in which the gradation is to be displayed.
00681                               (This is necessary for correction and separation etc. If proper
00682                               colour handling is not needed, then you may pass NULL, but
00683                               generally, this parameter should be sensible)
00684 
00685                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
00686 
00687     Returns:    TRUE, error thrown otherwise (but only for input variables)
00688     Purpose:    Generates a high quality repeating graduated fill table.  Handles both
00689                 those with fill ramps and those without.
00690     SeeAlso:    -
00691 
00692 ********************************************************************************************/
00693 
00694 BOOL GradTable::BuildHighQualityRepeatTable(DocColour &StartCol, DocColour &EndCol, ColourRamp *pColourRamp,
00695                     View *ContextView, EFFECTTYPE Effect)
00696 {
00697     if (!pColourRamp)
00698     {
00699         // Find a GDraw context to generate dithertable entries for us
00700         GDrawContext *GD = GRenderRegion::GetStaticDrawContext();
00701         ERROR3IF(GD == NULL, "GradTable::BuildHighQualityRepeatTable - No GDraw context?!");
00702 
00703         // Determine if either the start or end colour is a spot colour - if it is, we must
00704         // coerce the fill into a "mix" (rgb) rather than rainbow fill style
00705         if (Effect != EFFECT_RGB && (StartCol.GetSpotParent() != NULL || EndCol.GetSpotParent() != NULL))
00706             Effect = EFFECT_RGB;
00707 
00708         // Get colour contexts: we need 2 - first, an RGB context for the ContextView, which
00709         // will be used to get colour-corrected/separated/etc output colour in RGB; and second,
00710         // a generic RGB or HSV context to provide a "mixing colourspace" for the graduations.
00711         ColourContext *cc = NULL;
00712         ColourContext *ccRGB = ColourManager::GetColourContext(COLOURMODEL_RGBT, ContextView);
00713 
00714         if (Effect == EFFECT_RGB)
00715             cc = ColourManager::GetColourContext(COLOURMODEL_RGBT);     // RGB fade
00716         else
00717             cc = ColourManager::GetColourContext(COLOURMODEL_HSVT);     // HSV fade
00718 
00719         // If we can't find RGB/HSV contexts, something is seriously broken
00720         ERROR3IF(cc == NULL || ccRGB == NULL,
00721                 "GradTable::BuildHighQualityRepeatTable - Can't find my colour context!");
00722 
00723         // Fill in the Start and End colours of the table, if we've hit them
00724         PColourRGBT Result;
00725 
00726         // set our table size for this grad
00727         SetTableSize(TRUE);
00728 
00729         ccRGB->ConvertColour(&StartCol, (ColourPacked *) &Result);
00730         ccRGB->ConvertColour(&  EndCol, (ColourPacked *) &Result);
00731         m_pTable->StartColour = RGB(Result.Red, Result.Green, Result.Blue);
00732         m_pTable->EndColour   = RGB(Result.Red, Result.Green, Result.Blue);
00733 
00734         const INT32 TableLength = m_pTable->Length;
00735         double MixFraction = 0.0;
00736         double MixStep = 0;
00737                 
00738         if (TableLength != 0)
00739             MixStep = 2.0 / TableLength;
00740 
00741         DocColour temp;
00742         INT32 r, g, b;
00743 
00744         // NOTE:  this loop could be optimised to avoid calculating the same colour value twice
00745 
00746         for (INT32 col = 0 ; (col<<1)<TableLength ; col++)
00747         {   
00748             // Create a new colour which is an appropriate mixture of the start/end colours
00749             temp.Mix(&StartCol, &EndCol, MixFraction, cc, (Effect == EFFECT_HSV_LONG), ccRGB);
00750             temp.GetRGBValue (&r, &g, &b);
00751 
00752             // Get GDraw to fill in the dither entry for us (FALSE means it's an RGB colour)
00753             GD->AddToGraduationTable(RGB(r, g, b), FALSE, m_pTable, col);
00754             GD->AddToGraduationTable(RGB(r, g, b), FALSE, m_pTable, TableLength-col-1);
00755 
00756             MixFraction += MixStep;
00757         }
00758     }
00759     else
00760     {
00761         // set our table size for this grad
00762         SetTableSize(TRUE);
00763         
00764         ColRampItem *pCTI = pColourRamp->GetFirstCol();
00765         if (pCTI!=NULL)
00766         {
00767             DocColour *pFirstCol=&StartCol, *pSecondCol;
00768             
00769             DWORD fi=0 , si=0;
00770             
00771             while (pCTI)
00772             {
00773                 // whip out the colour definition
00774                 pSecondCol = pCTI->GetColourAddr();
00775                 // calculate the index for the next colour
00776                 si = (DWORD)((pCTI->GetPosition() * m_pTable->Length)+0.5);
00777                 // build this section of the table
00778                 if (!BuildTable(*pFirstCol, *pSecondCol, ContextView, Effect, fi, si))
00779                     return FALSE;
00780                 // now skip round to the next               
00781                 pFirstCol = pSecondCol;
00782                 fi = si;
00783                 pCTI = pColourRamp->GetNextCol(pCTI);
00784             }
00785 
00786             // do the final section
00787             return BuildTable(*pSecondCol, StartCol, ContextView, Effect, si, m_pTable->Length);
00788         }               
00789     }
00790     
00791     return (TRUE);
00792 }
00793 
00794 /********************************************************************************************
00795 
00796 >   BOOL GradTable::BuildHighQualityRepeatTable(DocColour &StartCol, DocColour &EndCol,
00797                                                 View *ContextView, EFFECTTYPE Effect,
00798                                                 CProfileBiasGain& BiasGain)
00799 
00800     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00801     Created:    4/2/2000
00802     Inputs:     StartCol, EndCol - Define the end colours of the graduation
00803                 pColourRamp - Define the colours and positions of a colour ramp
00804                 ContextView - Points to the view in which the gradation is to be displayed.
00805                               (This is necessary for correction and separation etc. If proper
00806                               colour handling is not needed, then you may pass NULL, but
00807                               generally, this parameter should be sensible)
00808 
00809                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
00810 
00811                 BiasGain    - the profile to build for
00812 
00813     Returns:    TRUE, error thrown otherwise (but only for input variables)
00814     Purpose:    Generates a high quality repeating graduated fill table for the supplied profile.
00815     SeeAlso:    -
00816 
00817 ********************************************************************************************/
00818 
00819 BOOL GradTable::BuildHighQualityRepeatTable(DocColour &StartCol, DocColour &EndCol,
00820                     View *ContextView, EFFECTTYPE Effect,
00821                     CProfileBiasGain& BiasGain)
00822 {
00823     // Find a GDraw context to generate dithertable entries for us
00824     GDrawContext *GD = GRenderRegion::GetStaticDrawContext();
00825     ERROR3IF(GD == NULL, "GradTable::BuildHighQualityRepeatTable - No GDraw context?!");
00826 
00827     // Determine if either the start or end colour is a spot colour - if it is, we must
00828     // coerce the fill into a "mix" (rgb) rather than rainbow fill style
00829     if (Effect != EFFECT_RGB && (StartCol.GetSpotParent() != NULL || EndCol.GetSpotParent() != NULL))
00830         Effect = EFFECT_RGB;
00831 
00832     // Get colour contexts: we need 2 - first, an RGB context for the ContextView, which
00833     // will be used to get colour-corrected/separated/etc output colour in RGB; and second,
00834     // a generic RGB or HSV context to provide a "mixing colourspace" for the graduations.
00835     ColourContext *cc = NULL;
00836     ColourContext *ccRGB = ColourManager::GetColourContext(COLOURMODEL_RGBT, ContextView);
00837 
00838     if (Effect == EFFECT_RGB)
00839         cc = ColourManager::GetColourContext(COLOURMODEL_RGBT);     // RGB fade
00840     else
00841         cc = ColourManager::GetColourContext(COLOURMODEL_HSVT);     // HSV fade
00842 
00843     // If we can't find RGB/HSV contexts, something is seriously broken
00844     ERROR3IF(cc == NULL || ccRGB == NULL,
00845             "GradTable::BuildHighQualityRepeatTable - Can't find my colour context!");
00846 
00847     // Fill in the Start and End colours of the table, if we've hit them
00848     PColourRGBT Result;
00849 
00850     // set our table size for this grad
00851     SetTableSize(TRUE);
00852 
00853     ccRGB->ConvertColour(&StartCol, (ColourPacked *) &Result);
00854     m_pTable->StartColour = RGB(Result.Red, Result.Green, Result.Blue);
00855 
00856     ccRGB->ConvertColour(&EndCol, (ColourPacked *) &Result);
00857     m_pTable->EndColour = RGB(Result.Red, Result.Green, Result.Blue);
00858 
00859     const INT32 TableLength = m_pTable->Length;
00860     INT32 halfTableLength = TableLength/2;
00861     double MixFraction;
00862 
00863     BiasGain.SetIntervals (AFp (0), AFp (m_pTable->Length/2));
00864     
00865     DocColour temp;
00866     INT32 r, g, b;
00867     double res;
00868 
00869     BOOL secondHalf = FALSE;
00870     INT32 secondHalfVal =0;
00871 
00872     // NOTE:  this loop could be optimised to avoid calculating the same colour value twice
00873 
00874     for (INT32 col = 0; col < TableLength; col++)
00875     {   
00876         if (!secondHalf)
00877         {
00878             res = BiasGain.MapInterval( AFp( col) );
00879         }
00880         else
00881         {
00882             res = BiasGain.MapInterval( AFp( secondHalfVal) );
00883         }
00884         
00885         MixFraction = res / halfTableLength;
00886         
00887         // Create a new colour which is an appropriate mixture of the start/end colours
00888         temp.Mix(&StartCol, &EndCol, MixFraction, cc, (Effect == EFFECT_HSV_LONG), ccRGB);
00889         temp.GetRGBValue (&r, &g, &b);
00890 
00891         // Get GDraw to fill in the dither entry for us (FALSE means it's an RGB colour)
00892         GD->AddToGraduationTable(RGB(r, g, b), FALSE, m_pTable, col);
00893 
00894         if (!(col < halfTableLength))
00895         {
00896             secondHalfVal = TableLength - col;
00897             secondHalf = TRUE;
00898         }
00899     }
00900     
00901     return (TRUE);
00902 }
00903 
00904 
00905 
00906 /********************************************************************************************
00907 
00908 >   BOOL GradTable::BuildTable(DocColour &StartCol, DocColour &EndCol, ColourRamp *pColList,
00909                                 View *ContextView, EFFECTTYPE Effect,
00910                                 BOOL LargeTable)
00911 
00912     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00913     Created:    25/2/97
00914     Inputs:     StartCol, EndCol - Define the end colours of the graduation
00915                 pColList    - Define the colours and positions of a colour ramp
00916                 ContextView - Points to the view in which the gradation is to be displayed.
00917                               (This is necessary for correction and separation etc. If proper
00918                               colour handling is not needed, then you may pass NULL, but
00919                               generally, this parameter should be sensible)
00920 
00921                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
00922 
00923                 TableSize   - The number of entries you wish to make the table (0x100 or
00924                               0x800)
00925     Returns:    TRUE if record is written, FALSE if not
00926     Purpose:    Writes a colour ramp fill record to the filter
00927     SeeAlso:    -
00928 
00929 ********************************************************************************************/
00930 
00931 BOOL GradTable::BuildTable(DocColour &StartCol, DocColour &EndCol, ColourRamp *pColRamp,
00932                             View *ContextView, EFFECTTYPE Effect,
00933                             BOOL LargeTable)
00934 {
00935     // set our table size for this grad
00936     SetTableSize(LargeTable);
00937     
00938     // if we've been passed a colour table, lets use it
00939     if (pColRamp!=NULL)
00940     {
00941         ColRampItem *pCTI = pColRamp->GetFirstCol();
00942         if (pCTI!=NULL)
00943         {
00944             DocColour *pFirstCol=&StartCol, *pSecondCol;
00945             
00946             DWORD fi=0 , si=0;
00947             
00948             while (pCTI)
00949             {
00950                 // whip out the colour definition
00951                 pSecondCol = pCTI->GetColourAddr();
00952                 // calculate the index for the next colour
00953                 si = (DWORD)((pCTI->GetPosition() * m_pTable->Length)+0.5);
00954                 // build this section of the table
00955                 if (!BuildTable(*pFirstCol, *pSecondCol, ContextView, Effect, fi, si))
00956                     return FALSE;
00957                 // now skip round to the next               
00958                 pFirstCol = pSecondCol;
00959                 fi = si;
00960                 pCTI = pColRamp->GetNextCol(pCTI);
00961             }
00962 
00963             // do the final section
00964             return BuildTable(*pSecondCol, EndCol, ContextView, Effect, si, m_pTable->Length);
00965         }               
00966     }
00967 
00968     // otherwise do the normal double end linear fill.
00969     return (BuildTable(StartCol, EndCol, ContextView, Effect, 0, m_pTable->Length));
00970 }
00971 
00972 
00973 /********************************************************************************************
00974 
00975 >   BOOL GradTable::AddToTable(DocColour &Colour, ColourContext* CurrentColContext, 
00976                             BOOL HSVFlag, INT32 Index)
00977 
00978     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00979     Created:    14/9/94
00980 
00981     Inputs:     NewCol - The colour to place into the GradTable
00982                 ContextView - Points to the view in which the gradation is to be displayed.
00983                               (This is necessary for correction and separation etc. If proper
00984                               colour handling is not needed, then you may pass NULL, but
00985                               generally, this parameter should be sensible)
00986 
00987                 Index - The index of the table entry to overwrite
00988 
00989     Purpose:    Adds a colour to a GradTable, at the specified index
00990                 This is used for multi-stage fills.
00991 
00992     Errors:     -
00993 
00994 ********************************************************************************************/
00995 
00996 BOOL GradTable::AddToTable(DocColour &NewCol, View *ContextView, DWORD Index)
00997 {
00998     ColourContextRGBT *cc = (ColourContextRGBT *)
00999                             ColourManager::GetColourContext(COLOURMODEL_RGBT, ContextView);
01000 
01001     ERROR3IF(cc == NULL, "Unable to find an RGB colour context for the view");
01002     ERROR3IF(Index >= m_pTable->Length, "Illegal table index");
01003 
01004     PColourRGBT Result;
01005     cc->ConvertColour(&NewCol, (ColourPacked *) &Result);
01006 
01007     COLORREF Col = RGB(Result.Red, Result.Green, Result.Blue);
01008 
01009     // Get GDraw to fill in the table entry for us. FALSE => RGB colour
01010     return(GRenderRegion::GetStaticDrawContext()->AddToGraduationTable(Col, FALSE, m_pTable, Index));
01011 }
01012 
01013 
01014 
01015 
01016 
01017 /********************************************************************************************
01018 
01019 >   TranspGradTable::TranspGradTable(BOOL LargeTable = FALSE)
01020 
01021     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01022     Created:    17/10/96
01023     Purpose:    Default constructor for a GradTable
01024     Errors:     -
01025 
01026 ********************************************************************************************/
01027 
01028 TranspGradTable::TranspGradTable(BOOL LargeTable)
01029 {
01030     m_pTable = NULL;
01031     m_bLargeTable = LargeTable;
01032 }
01033 
01034 /********************************************************************************************
01035 
01036 >   TranspGradTable::~TranspGradTable()
01037 
01038     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01039     Created:    16/10/96
01040     Purpose:    Destructor for a TranspGradTable
01041 
01042 ********************************************************************************************/
01043 
01044 TranspGradTable::~TranspGradTable()
01045 {
01046     if (m_pTable != NULL)
01047     {
01048         CCFree(m_pTable);
01049         m_pTable = NULL;
01050     }
01051 }
01052 
01053 
01054 /********************************************************************************************
01055 
01056 >   INT32 TranspGradTable::GetTableSize(GDrawContext* GD, BOOL LargeTable)
01057 
01058     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01059     Created:    17/10/96
01060     Inputs:     GD - pointer to GDraw context to use
01061                 LargeTable - if true then use a long grad table
01062     Returns:    The size in bytes of a grad table for the specified context
01063 
01064 ********************************************************************************************/
01065 
01066 INT32 TranspGradTable::GetTableSize(GDrawContext* GD, BOOL LargeTable)
01067 {
01068     if (LargeTable)
01069     {
01070         return(GD->GetLongTransparentGraduationTableSize());
01071     }
01072     else
01073     {
01074         return(GD->GetTransparentGraduationTableSize());
01075     }
01076 }
01077 
01078 
01079 /********************************************************************************************
01080 
01081 >   INT32 TranspGradTable::GetTableLength(GDrawContext* GD, BOOL LargeTable)
01082 
01083     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01084     Created:    17/10/96
01085     Inputs:     GD - pointer to GDraw context to use
01086                 LargeTable - if true then use a long grad table
01087     Returns:    The number of entries in a grad table for the specified context
01088 
01089 ********************************************************************************************/
01090 
01091 INT32 TranspGradTable::GetTableLength(GDrawContext* GD, BOOL LargeTable)
01092 {
01093     if (LargeTable)
01094     {
01095         return(GD->GetLongTransparentGraduationTableLength());
01096     }
01097     else
01098     {
01099         return(GD->GetTransparentGraduationTableLength());
01100     }
01101 }
01102 
01103 
01104 /********************************************************************************************
01105 
01106 >   void TranspGradTable::SetTableSize(BOOL LargeTable = FALSE)
01107 
01108     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01109     Created:    17/10/96
01110 
01111     Inputs:     LargeTable - if true then use a long grad table
01112 
01113     Purpose:    To set the size of this Grad table
01114 
01115     Notes:      The table defaults to small
01116 
01117 ********************************************************************************************/
01118 
01119 void TranspGradTable::SetTableSize(BOOL LargeTable)
01120 {
01121     // If we don't have the right table size or no table at all
01122     if ((LargeTable != m_bLargeTable) || (m_pTable == NULL))
01123     {
01124         m_bLargeTable = LargeTable;
01125 
01126         if (m_pTable != NULL)
01127         {
01128             CCFree(m_pTable);
01129             m_pTable = NULL;
01130         }
01131 
01132         GDrawContext *GD = GRenderRegion::GetStaticDrawContext();
01133 
01134         if (GD != NULL)
01135         {
01136             INT32 Size = GetTableSize(GD, m_bLargeTable);
01137             
01138             m_pTable = (TransparentGradTable*) CCMalloc(Size);
01139         }
01140     }
01141 }
01142 
01143 
01144 
01145 /********************************************************************************************
01146 
01147 >   BOOL TranspGradTable::BuildTable(INT32 StartTransp, INT32 EndTransp)
01148 
01149     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01150     Created:    14/9/94
01151     Inputs:     -
01152     Purpose:    Builds a TransparentGradTable from StartTransp to EndTransp.
01153     Errors:     -
01154 
01155 ********************************************************************************************/
01156 
01157 BOOL TranspGradTable::BuildTable(INT32 StartTransp, INT32 EndTransp)
01158 {
01159     SetTableSize(m_bLargeTable);
01160 
01161     if (m_pTable == NULL)
01162         return(FALSE);
01163 
01164     GDrawContext *pContext = GRenderRegion::GetStaticDrawContext();
01165 
01166     // If we are a large table then build it ourself
01167     if (IsLarge())
01168     {
01169         const INT32 Length = GetTableLength(pContext, IsLarge());
01170 
01171         const INT32 TranspIncrement = ((EndTransp - StartTransp) << 24) / Length;
01172 
01173         INT32 Transp = StartTransp;
01174         INT32 Index;
01175 
01176         for (Index = 0; Index < Length; Index++)
01177         {
01178             m_pTable->Table[Index] = (Transp >> 24) & 0xFF;
01179             Transp += TranspIncrement;
01180         }
01181 
01182         return(TRUE);
01183     }
01184     else
01185     {
01186         // Otherwise get a GDrawContext to build it
01187         return(pContext->BuildTransparencyTable(StartTransp, EndTransp, m_pTable));
01188     }
01189 }
01190 
01191 
01192 
01193 /********************************************************************************************
01194 
01195 >   BOOL TranspGradTable::BuildTable(INT32 StartTransp, INT32 EndTransp, CProfileBiasGain& BiasGain)
01196 
01197     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01198     Created:    9/2/2000
01199     Inputs:     -
01200     Purpose:    Builds a TransparentGradTable from StartTransp to EndTransp that reflects
01201                 the supplied BiasGain values.
01202     Errors:     -
01203 
01204 ********************************************************************************************/
01205 
01206 BOOL TranspGradTable::BuildTable(INT32 StartTransp, INT32 EndTransp, CProfileBiasGain& BiasGain)
01207 {
01208     SetTableSize(FALSE);
01209 
01210     if (m_pTable == NULL)
01211         return(FALSE);
01212 
01213     GDrawContext *pContext = GRenderRegion::GetStaticDrawContext();
01214 
01215     const INT32 Length = GetTableLength(pContext, FALSE);
01216     const double RLength = 1.0/Length;
01217     BiasGain.SetIntervals (AFp (0), AFp (Length));
01218 
01219     double MixFraction;
01220     double temp;
01221     INT32 Index;
01222 
01223     for (Index = 0; Index < Length; Index++)
01224     {
01225         MixFraction = BiasGain.MapInterval( AFp( Index ) );
01226         MixFraction *= RLength;
01227         temp = StartTransp * (1-MixFraction);
01228         temp += (EndTransp * MixFraction);
01229         m_pTable->Table[Index] = static_cast<BYTE> ( temp );
01230     }
01231 
01232     return(TRUE);
01233 }
01234 
01235 
01236 /********************************************************************************************
01237 
01238 >   BOOL TranspGradTable::BuildTable(INT32 StartTransp, INT32 EndTransp, TransparencyRamp *pTranspTable)
01239 
01240     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01241     Created:    12/3/97
01242     Inputs:     StartTransp  = the current start transparency level
01243                 EndTransp    = the current end transparency level
01244                 pTranspTable = all the inbetween transparency table levels.
01245     Purpose:    Builds a TransparentGradTable from StartTransp to EndTransp with inbetween
01246                 transparency levels held in pTranspTable
01247     Errors:     -
01248 
01249 ********************************************************************************************/
01250 
01251 BOOL TranspGradTable::BuildTable(INT32 StartTransp, INT32 EndTransp, TransparencyRamp *pTranspTable)
01252 {
01253     TranspRampItem *pTTI=NULL;
01254     if (pTranspTable!=NULL) 
01255         pTTI=pTranspTable->GetFirstTransp();
01256 
01257     if (pTTI==NULL)
01258         return BuildTable(StartTransp,EndTransp);
01259 
01260     SetTableSize(m_bLargeTable);
01261 
01262     if (m_pTable == NULL)
01263         return FALSE;
01264 
01265     INT32 ei, si=0;
01266     INT32 end, start=StartTransp;
01267     
01268     GDrawContext *pContext = GRenderRegion::GetStaticDrawContext();
01269     const INT32 Length = GetTableLength(pContext, IsLarge());
01270 
01271     while (pTTI)
01272     {
01273         ei = (INT32)((pTTI->GetPosition() * (Length-1)) + 0.5);
01274         end = pTTI->GetTransparency();
01275         FillSection(si,ei,start,end);
01276         si = ei;
01277         start = end;
01278         pTTI = pTranspTable->GetNextTransp(pTTI);
01279     }
01280     ei  = Length-1;
01281     end = EndTransp;
01282     FillSection(si,ei,start,end);
01283 
01284     return TRUE;
01285 }
01286 
01287 
01288 
01289 /********************************************************************************************
01290 
01291 >   BOOL TranspGradTable::BuildHighQualityRepeatTable(INT32 StartTransp, INT32 EndTransp, CProfileBiasGain& BiasGain)
01292 
01293     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01294     Created:    21/7/2000
01295     Inputs:     StartTransp  = the current start transparency level
01296                 EndTransp    = the current end transparency level
01297                 BiasGain     = the profile to build for
01298     Purpose:    Builds a high quality repeating TransparentGradTable from StartTransp to
01299                 EndTransp that reflects the supplied BiasGain values.
01300     Errors:     -
01301 
01302 ********************************************************************************************/
01303 
01304 BOOL TranspGradTable::BuildHighQualityRepeatTable(INT32 StartTransp, INT32 EndTransp, CProfileBiasGain& BiasGain)
01305 {
01306     SetTableSize(TRUE);
01307 
01308     if (m_pTable == NULL)
01309     {
01310         return FALSE;
01311     }
01312 
01313     GDrawContext *pContext = GRenderRegion::GetStaticDrawContext();
01314 
01315     INT32 TableLength = GetTableLength (pContext, IsLarge ());
01316     INT32 halfTableLength = TableLength/2;
01317         
01318     double MixFraction = 0.0;
01319     double temp;
01320     double res;
01321     INT32 Index;
01322 
01323     BOOL secondHalf = FALSE;
01324     INT32 secondHalfVal =0;
01325 
01326     BiasGain.SetIntervals (AFp (0), AFp (halfTableLength));
01327 
01328     for (Index = 0; Index < TableLength; Index++)
01329     {
01330         if (!secondHalf)
01331         {
01332             res = BiasGain.MapInterval( AFp( Index) );
01333         }
01334         else
01335         {
01336             res = BiasGain.MapInterval( AFp( secondHalfVal) );
01337         }
01338 
01339         MixFraction = res / (halfTableLength);
01340         temp = StartTransp * (1-MixFraction);
01341         temp += (EndTransp * MixFraction);
01342         m_pTable->Table[Index] = static_cast<BYTE> ( temp );
01343             
01344         if (!(Index < halfTableLength))
01345         {
01346             secondHalfVal = TableLength - Index;
01347             secondHalf = TRUE;
01348         }
01349     }
01350 
01351     return (TRUE);
01352 }
01353 
01354 
01355 /********************************************************************************************
01356 
01357 >   BOOL TranspGradTable::BuildHighQualityRepeatTable(INT32 StartTransp, INT32 EndTransp, TransparencyRamp *pTranspTable)
01358 
01359     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01360     Created:    21/7/2000
01361     Inputs:     StartTransp  = the current start transparency level
01362                 EndTransp    = the current end transparency level
01363                 pTranspTable = the ramp to build for
01364     Purpose:    Builds a high quality repeating TransparentGradTable from StartTransp to
01365                 EndTransp.
01366     Errors:     -
01367 
01368 ********************************************************************************************/
01369 
01370 BOOL TranspGradTable::BuildHighQualityRepeatTable(INT32 StartTransp, INT32 EndTransp, TransparencyRamp *pTranspTable)
01371 {
01372     if (!pTranspTable)
01373     {
01374         SetTableSize(TRUE);
01375 
01376         if (m_pTable == NULL)
01377             return FALSE;
01378 
01379         GDrawContext *pContext = GRenderRegion::GetStaticDrawContext();
01380 
01381         INT32 TableLength = GetTableSize (pContext, IsLarge ());
01382         
01383         double MixFraction = 0.0;
01384         double MixStep = 2.0/TableLength;
01385         double temp;
01386 
01387         for (INT32 Index = 0; (Index<<1) < TableLength; Index++)
01388         {
01389             //MixFraction = BiasGain.MapInterval( AFp( Index ) );
01390             //MixFraction /= Length;
01391             temp = StartTransp * (1-MixFraction);
01392             temp += (EndTransp * MixFraction);
01393             m_pTable->Table[Index] =
01394             m_pTable->Table[TableLength-Index-1] = static_cast<BYTE> ( temp );
01395             
01396             MixFraction += MixStep;
01397         }
01398     }
01399     else
01400     {
01401         ERROR3 ("Attempt to build a multi-stage transparent fill - NOT fully implemented yet!");
01402     }
01403     
01404     return TRUE;
01405 }
01406 
01407 /********************************************************************************************
01408 
01409 >   BOOL TranspGradTable::BuildTable(INT32 StartTransp, INT32 EndTransp, CProfileBiasGain& BiasGain)
01410 
01411     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com> (modified by CGS)
01412     Created:    24/10/96 (15/2/2000)
01413     Inputs:     -
01414     Purpose:    Builds a TransparentGradTable from StartTransp to EndTransp
01415                 This function forces the table to be 256 entries (for bitmap transparency)
01416                 The function now (also) takes into account the applied transparency profile.
01417     Errors:     -
01418 
01419 ********************************************************************************************/
01420 
01421 BOOL TranspGradTable::BuildBitmapTable(INT32 StartTransp, INT32 EndTransp, CProfileBiasGain& BiasGain)
01422 {
01423     if (m_pTable != NULL)
01424     {
01425         CCFree(m_pTable);
01426         m_pTable = NULL;
01427     }
01428 
01429     m_pTable = (TransparentGradTable*) CCMalloc(256);
01430 
01431     if (m_pTable == NULL)
01432         return(FALSE);
01433 
01434     const INT32 Length = 0x100;
01435     DWORD Index;
01436 
01437     CProfileBiasGain DefaultBiasGain;
01438 
01439     // make some optimisation decisions ....
01440 
01441     if (!(BiasGain == DefaultBiasGain))
01442     {
01443         double MixFraction;
01444         double temp;
01445         double RLength = 1.0/Length;
01446         
01447         BiasGain.SetIntervals (AFp (0), AFp (0x100));
01448         
01449         for (Index= 0; Index < 0x100; Index++)
01450         {
01451             MixFraction = BiasGain.MapInterval( AFp( Index ) );
01452             MixFraction *= RLength;
01453             
01454             temp = StartTransp * (1-MixFraction);
01455             temp += (EndTransp * MixFraction);
01456 
01457             m_pTable->Table[Index] = static_cast<BYTE> ( temp );
01458         }
01459         
01460         if (BiasGain.GetIsAFeatherProfile ())
01461         {
01462             // were a feather profile - we need to do a bit of extra work to ensure that ilans
01463             // feather renders correctly.  We MUST ensure that ilans white part of the bitmap
01464             // is rendered as 100% transparent.  The following lines of code do this ....
01465 
01466             // TODO: (Gavin) Why on earth is this setting Index-2 and Index-1 to 255
01467             // when the code below overwrites Index-2 anyway?
01468             m_pTable->Table[Index-2] = static_cast<BYTE> ( 255 );
01469             m_pTable->Table[Index-1] = static_cast<BYTE> ( 255 );
01470         }
01471     }
01472     else
01473     {
01474         INT32 Transp = (StartTransp << 24) + 0x00800000;
01475         INT32 TranspStep = (EndTransp - StartTransp) * 0x010101;
01476         BYTE *pTransp = &(m_pTable->Table[0]);
01477         
01478         for (Index= 0; Index < 0x100; Index++)
01479         {
01480             pTransp[Index] = (BYTE)((Transp >> 24) & 0xFF);
01481             Transp += TranspStep;
01482         }
01483     }
01484 
01485     // TODO: (Gavin) Why on earth is this setting 0xFE and not 0xFF?
01486     m_pTable->Table[0xFE] = static_cast <BYTE> ( EndTransp );
01487     
01488     return(TRUE);
01489 }
01490 
01491 
01492 
01493 /********************************************************************************************
01494 
01495 >   BOOL TranspGradTable::BuildBitmapTable(INT32 StartTransp, INT32 EndTransp, TransparencyRamp *pTranspTable, CProfileBiasGain& BiasGain)
01496 
01497     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com> (modified by CGS)
01498     Created:    12/3/97 (15/2/2000)
01499     Inputs:     -
01500     Purpose:    Builds a TransparentGradTable from StartTransp to EndTransp
01501                 This function forces the table to be 256 entries (for bitmap transparency)
01502                 The function now (also) takes into account the applied transparency profile.
01503     Errors:     -
01504 
01505 ********************************************************************************************/
01506 
01507 BOOL TranspGradTable::BuildBitmapTable(INT32 StartTransp, INT32 EndTransp, TransparencyRamp *pTranspTable, CProfileBiasGain& BiasGain)
01508 {
01509     TranspRampItem *pTTI=NULL;
01510     if (pTranspTable!=NULL) 
01511         pTTI=pTranspTable->GetFirstTransp();
01512 
01513     if (pTTI==NULL)
01514     {
01515         return BuildBitmapTable(StartTransp, EndTransp, BiasGain);
01516     }
01517 
01518     if (m_pTable != NULL)
01519     {
01520         CCFree(m_pTable);
01521         m_pTable = NULL;
01522     }
01523 
01524     m_pTable = (TransparentGradTable*) CCMalloc(256);
01525     if (m_pTable == NULL)
01526         return(FALSE);
01527 
01528     INT32 ei, si=0;
01529     INT32 end, start = StartTransp;
01530     while (pTTI)
01531     {
01532         ei = (INT32)(pTTI->GetPosition()*255.0 + 0.5);
01533         end = pTTI->GetTransparency();
01534         FillSection(si,ei,start,end);
01535         si = ei;
01536         start = end;
01537         pTTI = pTranspTable->GetNextTransp(pTTI);
01538     }
01539     end = EndTransp;
01540     FillSection(si,255,start,end);
01541     
01542     return TRUE;
01543 }
01544 
01545 
01546 
01547 /********************************************************************************************
01548 
01549 >   void TranspGradTable::FillSection(INT32 startindex, INT32 endindex, INT32 starttransp, INT32 endtransp)
01550 
01551     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01552     Created:    14/9/94
01553     Inputs:     StartIndex, EndIndex = range of indexes to fill
01554                 starttransp
01555                 endtransp
01556     Purpose:    Builds a TransparentGradTable from StartTransp to EndTransp with inbetween
01557                 transparency levels held in pTranspTable
01558     Errors:     -
01559 
01560 ********************************************************************************************/
01561 
01562 void TranspGradTable::FillSection(INT32 startindex, INT32 endindex, INT32 starttransp, INT32 endtransp)
01563 {
01564     INT32 den = endindex-startindex;
01565     if (den<0)
01566         return;
01567 
01568     if (den==0)
01569     {
01570         m_pTable->Table[endindex] = (UINT32)endtransp;
01571     }
01572     else
01573     {
01574         INT32 t = (starttransp<<22) + 0x00200000;
01575         INT32 inc = ((endtransp-starttransp)<<22) / den;
01576         for (INT32 i=startindex; i<=endindex; i++)
01577         {
01578             m_pTable->Table[i] = (t>>22) & 0xFF;
01579             t+=inc;
01580         }
01581     }
01582 }
01583 
01584 
01585 
01586 /********************************************************************************************
01587 
01588 >   GradTable32::GradTable32()
01589 
01590     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01591     Created:    14/9/94
01592     Purpose:    Default constructor for a GradTable32
01593     Errors:     -
01594 
01595 ********************************************************************************************/
01596 
01597 GradTable32::GradTable32()
01598 {
01599 }
01600 
01601 
01602 /********************************************************************************************
01603 
01604 >   GradTable32::~GradTable32()
01605 
01606     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
01607     Created:    16/10/96
01608     Purpose:    Destructor for a GradTable32
01609 
01610 ********************************************************************************************/
01611 
01612 GradTable32::~GradTable32()
01613 {
01614 }
01615 
01616 /********************************************************************************************
01617 
01618 >   void GradTable32::SetTableSize(BOOL LargeTable = FALSE)
01619 
01620     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01621     Created:    14/5/96
01622 
01623     Inputs:     NewSize - The new size (number of entries) in this table.
01624                 May only be 0x100 or 0x800
01625 
01626     Purpose:    To set the size of this Grad table
01627 
01628     Notes:      The default table size is 0x100 entries
01629 
01630 ********************************************************************************************/
01631 
01632 void GradTable32::SetTableSize(BOOL LargeTable)
01633 {
01634 }
01635 
01636 
01637 
01638 /********************************************************************************************
01639 
01640 >   BOOL GradTable32::BuildTable(DocColour &StartCol, DocColour &EndCol,
01641                                 View *ContextView, EFFECTTYPE Effect,
01642                                 DWORD TableSize = 0x100)
01643 
01644     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (Will)
01645     Created:    14/5/96 (14/9/94)
01646 
01647     Inputs:     StartCol, EndCol - Define the end colours of the graduation
01648                 ContextView - Points to the view in which the gradation is to be displayed.
01649                               (This is necessary for correction and separation etc. If proper
01650                               colour handling is not needed, then you may pass NULL, but
01651                               generally, this parameter should be sensible)
01652 
01653                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
01654 
01655                 TableSize   - The number of entries you wish to make the table (0x100 or
01656                               0x800)
01657 
01658     Returns:    FALSE if it fails
01659 
01660     Purpose:    Builds a GradTable from StartCol to EndCol, filling in the entire
01661                 table with appropriate GDraw dither patterns.
01662                 
01663                 == NOTE that this version of the call also implicitly sets the table size! == 
01664 
01665     SeeAlso:    GradTable::SetTableSize
01666 
01667 ********************************************************************************************/
01668                                                                                  
01669 BOOL GradTable32::BuildTable(DocColour &StartCol, DocColour &EndCol,
01670                             View *ContextView, EFFECTTYPE Effect,
01671                             DWORD TableSize)
01672 {
01673     ERROR3("GradTable32::BuildTable() is rampant so don't use it\n");
01674 
01675     return(FALSE);  
01676 /*
01677     SetTableSize(TableSize);
01678 
01679     return(BuildPaletteInternal(StartCol, EndCol, ContextView, Effect,
01680                                 0, Table.Length,
01681                                 (void *)Table.Table, TRUE));
01682 */
01683 }
01684 
01685 
01686 
01687 /********************************************************************************************
01688 
01689 >   BOOL GradTable32::BuildTable(DocColour &StartCol, DocColour &EndCol,
01690                                 View *ContextView, EFFECTTYPE Effect,
01691                                 DWORD FirstEntry, DWORD LastEntry)
01692 
01693     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> (Will)
01694     Created:    14/5/96 (14/9/94)
01695 
01696     Inputs:     StartCol, EndCol - Define the end colours of the graduation
01697                 ContextView - Points to the view in which the gradation is to be displayed.
01698                               (This is necessary for correction and separation etc. If proper
01699                               colour handling is not needed, then you may pass NULL, but
01700                               generally, this parameter should be sensible)
01701 
01702                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
01703 
01704                 FirstEntry  - The index of the first entry (inclusive) to fill in (0 is the first)
01705                 LastEntry   - The index of the last entry (exclusive) to fill in (TableSize is the last)
01706                                 (i.e. to fill entire table use (0,TableSize) which will fill in entries
01707                                     0..Tablesize-1)
01708 
01709     Returns:    FALSE if it fails
01710 
01711     Purpose:    Builds a GradTable from StartCol to EndCol, filling in a portion of the
01712                 table with appropriate GDraw dither patterns
01713 
01714     Notes:      GDraw requires the Start and End colours for the entire table to be
01715                 set separately in the table structure. These will be set if FirstEntry==0
01716                 and/or if LastEntry==TableSize, respectively.
01717 
01718     SeeAlso:    GradTable::SetTableSize
01719 
01720 ********************************************************************************************/
01721                                                                                  
01722 BOOL GradTable32::BuildTable(DocColour &StartCol, DocColour &EndCol,
01723                             View *ContextView, EFFECTTYPE Effect,
01724                             DWORD FirstEntry, DWORD LastEntry)
01725 {
01726     ERROR3("GradTable32::BuildTable() is rampant so don't use it\n");
01727 
01728     return(FALSE);  
01729 /*  
01730     return(BuildPaletteInternal(StartCol, EndCol, ContextView, Effect,
01731                                 FirstEntry, LastEntry,
01732                                 (void *)Table.Table, TRUE));
01733 */
01734 }
01735 
01736 
01737 
01738 /********************************************************************************************
01739 
01740 >   static BOOL GradTable32::BuildGraduatedPalette(DocColour &StartCol, DocColour &EndCol,
01741                                         View *ContextView, EFFECTTYPE Effect,
01742                                         DWORD TableSize, COLORREF *pTable)
01743 
01744     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01745     Created:    14/5/96
01746 
01747     Inputs:     StartCol, EndCol - Define the end colours of the graduation
01748                 ContextView - Points to the view in which the gradation is to be displayed.
01749                               (This is necessary for correction and separation etc. If proper
01750                               colour handling is not needed, then you may pass NULL, but
01751                               generally, this parameter should be sensible)
01752 
01753                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
01754 
01755                 TableSize   - Number of entries in the table
01756 
01757     Outputs:    pTable      - On return, will be filled in with appropriate colours
01758 
01759     Returns:    FALSE if it fails
01760 
01761     Purpose:    Builds a Graduated Table, filling in the given table with COLORREF
01762                 entries. The entries will be colour corrected and/or separated as
01763                 appropriate to the context view.
01764 
01765     Errors:     -
01766 
01767 ********************************************************************************************/
01768                                                                                  
01769 BOOL GradTable32::BuildGraduatedPalette(DocColour &StartCol, DocColour &EndCol,
01770                                         View *ContextView, EFFECTTYPE Effect,
01771                                         DWORD TableSize, COLORREF *pTable)
01772 {
01773     CProfileBiasGain DefaultBiasGain;           // we need a 'default' profile so we call
01774                                                 // standardise the following call ....
01775     return(BuildPaletteInternal(StartCol, EndCol, ContextView, Effect, 0, TableSize,
01776                             (void *) pTable, TRUE, DefaultBiasGain));
01777 }
01778 
01779 
01780 
01781 /********************************************************************************************
01782 
01783 >   static BOOL GradTable32::BuildGraduatedPalette(DocColour &StartCol, DocColour &EndCol,
01784                                         View *ContextView, EFFECTTYPE Effect,
01785                                         DWORD FirstEntry, DWORD LastEntry,
01786                                         COLORREF *pTable)
01787     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01788     Created:    14/5/96
01789 
01790     Inputs:     StartCol, EndCol - Define the end colours of the graduation
01791                 ContextView - Points to the view in which the gradation is to be displayed.
01792                               (This is necessary for correction and separation etc. If proper
01793                               colour handling is not needed, then you may pass NULL, but
01794                               generally, this parameter should be sensible)
01795 
01796                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
01797 
01798                 FirstEntry  - The index of the first entry (inclusive) to fill in (0 is the first)
01799                 LastEntry   - The index of the last entry (exclusive) to fill in (TableSize is the last)
01800                                 (i.e. to fill entire table use (0,TableSize) which will fill in entries
01801                                     0..Tablesize-1)
01802 
01803     Outputs:    pTable      - On return, will be filled in with appropriate colours
01804 
01805     Returns:    FALSE if it fails
01806 
01807     Purpose:    Builds a Graduated Table from StartCol to EndCol, filling in the given
01808                 table with COLORREF entries. The entries will be colour corrected
01809                 and/or separated as appropriate to the context view.
01810 
01811     Errors:     Out of memory
01812 
01813 ********************************************************************************************/
01814 
01815 BOOL GradTable32::BuildGraduatedPalette(DocColour &StartCol, DocColour &EndCol,
01816                                         View *ContextView, EFFECTTYPE Effect,
01817                                         DWORD FirstEntry, DWORD LastEntry,
01818                                         COLORREF *pTable)
01819 {
01820     CProfileBiasGain DefaultBiasGain;           // we need a 'default' profile so we call
01821                                                 // standardise the following call ....
01822     return(BuildPaletteInternal(StartCol, EndCol, ContextView, Effect, FirstEntry, LastEntry,
01823                             (void *) pTable, TRUE, DefaultBiasGain));
01824 }
01825 
01826 
01827 
01828 /********************************************************************************************
01829 
01830 >   static BOOL GradTable32::BuildGraduatedPalette(DocColour &StartCol, DocColour &EndCol,
01831                                         View *ContextView, EFFECTTYPE Effect,
01832                                         DWORD TableSize, RGBQUAD *pTable)
01833 
01834     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01835     Created:    14/5/96
01836 
01837     Inputs:     StartCol, EndCol - Define the end colours of the graduation
01838                 ContextView - Points to the view in which the gradation is to be displayed.
01839                               (This is necessary for correction and separation etc. If proper
01840                               colour handling is not needed, then you may pass NULL, but
01841                               generally, this parameter should be sensible)
01842 
01843                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
01844 
01845                 TableSize   - Number of entries in the table
01846 
01847     Outputs:    pTable      - On return, will be filled in with appropriate colours
01848 
01849     Returns:    FALSE if it fails
01850 
01851     Purpose:    Builds a Graduated Table, filling in the given table with RGBQUAD
01852                 entries. The entries will be colour corrected and/or separated as
01853                 appropriate to the context view.
01854 
01855     Errors:     -
01856 
01857 ********************************************************************************************/
01858                                                                                  
01859 BOOL GradTable32::BuildGraduatedPalette(DocColour &StartCol, DocColour &EndCol,
01860                                         View *ContextView, EFFECTTYPE Effect,
01861                                         DWORD TableSize, RGBQUAD *pTable)
01862 {
01863     CProfileBiasGain DefaultBiasGain;           // we need a 'default' profile so we call
01864                                                 // standardise the following call ....
01865     return(BuildPaletteInternal(StartCol, EndCol, ContextView, Effect, 0, TableSize,
01866                             (void *) pTable, FALSE, DefaultBiasGain));
01867 }
01868 
01869 
01870 
01871 /********************************************************************************************
01872 
01873 >   static BOOL GradTable32::BuildGraduatedPalette(DocColour &StartCol, DocColour &EndCol,
01874                                         View *ContextView, EFFECTTYPE Effect,
01875                                         DWORD TableSize, RGBQUAD *pTable,
01876                                         CProfileBiasGain& BiasGain)
01877 
01878     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01879     Created:    14/2/2000
01880 
01881     Inputs:     StartCol, EndCol - Define the end colours of the graduation
01882                 ContextView - Points to the view in which the gradation is to be displayed.
01883                               (This is necessary for correction and separation etc. If proper
01884                               colour handling is not needed, then you may pass NULL, but
01885                               generally, this parameter should be sensible)
01886 
01887                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
01888 
01889                 TableSize   - Number of entries in the table
01890 
01891                 BiasGain    - The biasgain profile that is to alter the table
01892 
01893     Outputs:    pTable      - On return, will be filled in with appropriate colours
01894 
01895     Returns:    FALSE if it fails
01896 
01897     Purpose:    Builds a Graduated Table, filling in the given table with RGBQUAD
01898                 entries (taking into account the biasgain). The entries will be colour
01899                 corrected and/or separated as appropriate to the context view.
01900 
01901     Errors:     -
01902 
01903 ********************************************************************************************/
01904 
01905 BOOL GradTable32::BuildGraduatedPalette(DocColour &StartCol, DocColour &EndCol,
01906                                         View *ContextView, EFFECTTYPE Effect,
01907                                         DWORD TableSize, RGBQUAD *pTable,
01908                                         CProfileBiasGain& BiasGain)
01909 {
01910     return(BuildPaletteInternal(StartCol, EndCol, ContextView, Effect, 0, TableSize,
01911                             (void *) pTable, FALSE, BiasGain));
01912 }
01913 
01914 
01915 
01916 /********************************************************************************************
01917 
01918 >   static BOOL GradTable32::BuildGraduatedPalette(DocColour &StartCol, DocColour &EndCol,
01919                                         View *ContextView, EFFECTTYPE Effect,
01920                                         DWORD FirstEntry, DWORD LastEntry,
01921                                         RGBQUAD *pTable)
01922     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01923     Created:    14/5/96
01924 
01925     Inputs:     StartCol, EndCol - Define the end colours of the graduation
01926                 ContextView - Points to the view in which the gradation is to be displayed.
01927                               (This is necessary for correction and separation etc. If proper
01928                               colour handling is not needed, then you may pass NULL, but
01929                               generally, this parameter should be sensible)
01930 
01931                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
01932 
01933                 FirstEntry  - The index of the first entry (inclusive) to fill in (0 is the first)
01934                 LastEntry   - The index of the last entry (exclusive) to fill in (TableSize is the last)
01935                                 (i.e. to fill entire table use (0,TableSize) which will fill in entries
01936                                     0..Tablesize-1)
01937 
01938     Outputs:    pTable      - On return, will be filled in with appropriate colours
01939 
01940     Returns:    FALSE if it fails
01941 
01942     Purpose:    Builds a Graduated Table from StartCol to EndCol, filling in the given
01943                 table with RGBQUAD entries. The entries will be colour corrected
01944                 and/or separated as appropriate to the context view.
01945 
01946     Errors:     Out of memory
01947 
01948 ********************************************************************************************/
01949 
01950 BOOL GradTable32::BuildGraduatedPalette(DocColour &StartCol, DocColour &EndCol,
01951                                         View *ContextView, EFFECTTYPE Effect,
01952                                         DWORD FirstEntry, DWORD LastEntry,
01953                                         RGBQUAD *pTable)
01954 {
01955     CProfileBiasGain DefaultBiasGain;           // we need a 'default' profile so we call
01956                                                 // standardise the following call ....
01957     return(BuildPaletteInternal(StartCol, EndCol, ContextView, Effect, FirstEntry, LastEntry,
01958                             (void *) pTable, FALSE, DefaultBiasGain));
01959 }
01960 
01961 
01962 
01963 /********************************************************************************************
01964 
01965 >   static BOOL GradTable32::BuildPaletteInternal(DocColour &StartCol, DocColour &EndCol,
01966                                         View *ContextView, EFFECTTYPE Effect,
01967                                         DWORD FirstEntry, DWORD LastEntry,
01968                                         void *pTable, BOOL IsColorRef)
01969     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01970     Created:    14/5/96
01971 
01972     Inputs:     StartCol, EndCol - Define the end colours of the graduation
01973                 ContextView - Points to the view in which the gradation is to be displayed.
01974                               (This is necessary for correction and separation etc. If proper
01975                               colour handling is not needed, then you may pass NULL, but
01976                               generally, this parameter should be sensible)
01977 
01978                 Effect      - EFFECT_FADE, EFFECT_HSV_SHORT, or EFFECT_HSV_LONG
01979 
01980                 FirstEntry  - The index of the first entry (inclusive) to fill in (0 is the first)
01981                 LastEntry   - The index of the last entry (exclusive) to fill in (TableSize is the last)
01982                                 (i.e. to fill entire table use (0,TableSize) which will fill in entries
01983                                     0..Tablesize-1)
01984 
01985                 IsColorRef  -   TRUE if the pTable pointer is a (COLORREF *)
01986                                 FALSE if the pTable pointer is an (RGBQUAD *)
01987 
01988     Outputs:    pTable      - On return, will be filled in with appropriate colours, in the format
01989                                 indicated by the IsColorRef flag.
01990 
01991     Returns:    FALSE if it fails
01992 
01993     Purpose:    Builds a Graduated Table from StartCol to EndCol, filling in the given
01994                 table with either COLORREF or RGBQUAD entries.
01995                 The entries will be colour corrected and/or separated as appropriate to
01996                 the context view.
01997 
01998                 This is an internal shared function used by all the other GradTable32 
01999                 grad palette building methods
02000 
02001     Notes:      This routine supplies a simple, generic mixing loop. However, for normal
02002                 (no colour plate) rendering, this function will call the other internal
02003                 methods which are optimised for specific cases - this gives about a 3x
02004                 performance enhancement for normal rendering.
02005 
02006     Errors:     Out of memory
02007 
02008 ********************************************************************************************/
02009 
02010 BOOL GradTable32::BuildPaletteInternal(DocColour &StartCol, DocColour &EndCol,
02011                                         View *ContextView, EFFECTTYPE Effect,
02012                                         DWORD FirstEntry, DWORD LastEntry,
02013                                         void *pTable, BOOL IsColorRef,
02014                                         CProfileBiasGain& BiasGain)
02015 {
02016     ERROR3IF(pTable == NULL, "Illegal NULL param");
02017 
02018     // The range should be withion the table size. We only ERROR3, though, because
02019     // the physical table is always large enough for the maximum number of entries.
02020     ERROR3IF(FirstEntry < 0 || FirstEntry > LastEntry,
02021                 "GradTable32::BuildPaletteInternal expects sensible First/Last Entry values");
02022 
02023     // Determine if either the start or end colour is a spot colour - if it is, we must
02024     // coerce the fill into a "mix" (rgb) rather than rainbow fill style
02025     if (Effect != EFFECT_RGB && (StartCol.GetSpotParent() != NULL || EndCol.GetSpotParent() != NULL))
02026         Effect = EFFECT_RGB;
02027 
02028 
02029     // --- Optimisation - are we trying to build a simple grad table under normal rendering
02030     // circumstances? If so, special case this to make it as fast as possible. This more than
02031     // doubles the speed of table generation.
02032     ColourContext *ccRGB = ColourManager::GetColourContext(COLOURMODEL_RGBT, ContextView);
02033     ERROR3IF(ccRGB == NULL, "GradTable32::BuildPaletteInternal - Can't find my colour context!");
02034 
02035     if (ccRGB->GetColourPlate() == NULL || ccRGB->GetColourPlate()->IsDisabled())
02036     {
02037         if (Effect == EFFECT_RGB)   // RGB mix?
02038         {
02039             return(BuildPaletteInternalRGB(StartCol, EndCol, ContextView,
02040                                         FirstEntry, LastEntry, pTable, IsColorRef, BiasGain));
02041         }
02042 
02043         // HSV (rainbow) mix
02044         return(BuildPaletteInternalHSV(StartCol, EndCol, ContextView, Effect,
02045                                     FirstEntry, LastEntry, pTable, IsColorRef, BiasGain));
02046     }
02047 
02048     if (Effect == EFFECT_RGB && ccRGB->GetColourPlate()->GetType() == COLOURPLATE_COMPOSITE &&
02049         (StartCol.GetColourModel() != COLOURMODEL_CMYK || EndCol.GetColourModel() != COLOURMODEL_CMYK))
02050     {
02051         return(BuildPaletteInternalRGBComposite(StartCol, EndCol, ContextView,
02052                                                 FirstEntry, LastEntry, pTable, IsColorRef));
02053     }
02054 
02055 
02056     // --- OK, we're trying to do something special. Drop back to the generic (slow) code
02057     RGBQUAD  *pRGBTable = (RGBQUAD *)  pTable;      // Cast the table pointer to the two
02058     COLORREF *pRefTable = (COLORREF *) pTable;      // possible types
02059 
02060     // Get colour contexts: we need 2 - first, an RGB context (got above) for the ContextView, which
02061     // will be used to get colour-corrected/separated/etc output colour in RGB; and second,
02062     // a generic RGB or HSV context to provide a "mixing colourspace" for the graduations.
02063     ColourContext *cc = NULL;
02064 
02065     if (Effect == EFFECT_RGB)
02066         cc = ColourManager::GetColourContext(COLOURMODEL_RGBT);     // RGB fade
02067     else
02068         cc = ColourManager::GetColourContext(COLOURMODEL_HSVT);     // HSV fade
02069 
02070     // If we can't find RGB/HSV contexts, something is seriously broken
02071     ERROR3IF(cc == NULL, "GradTable32::BuildPaletteInternal - Can't find my colour context!");
02072 
02073     // Fill in the Start and End colours of the table, if we've hit them
02074     PColourRGBT Result;
02075 
02076     // And build our graduated palette
02077     double MixFraction  = 0.0;
02078     double MixStep      = 1.0 / (double) (LastEntry - FirstEntry - 1);
02079 
02080     DocColour temp;
02081 
02082     for (DWORD col = FirstEntry; col < LastEntry; col++)
02083     {
02084         // Create a new colour which is an appropriate mixture of the start/end colours
02085         temp.Mix(&StartCol, &EndCol, MixFraction, cc, (Effect == EFFECT_HSV_LONG), ccRGB);
02086 
02087         // Convert back to the raw RGB and place it in the palette.
02088         // Note that this will colour correct and separate in an appropriate manner.
02089         // Note also that we're using a special ConvertColour call which returns 8-bit 
02090         // "packed" component values instead of FIXED24's.
02091         ccRGB->ConvertColour(&temp, (ColourPacked *) &Result);
02092 
02093         // And add to the table
02094         if (IsColorRef)
02095         {
02096             pRefTable[col] = RGB(Result.Red, Result.Green, Result.Blue);
02097         }
02098         else
02099         {
02100             pRGBTable[col].rgbRed       = Result.Red;
02101             pRGBTable[col].rgbGreen     = Result.Green;
02102             pRGBTable[col].rgbBlue      = Result.Blue;
02103             pRGBTable[col].rgbReserved  = 0;
02104         }
02105 
02106         // And step to the next mix fraction value
02107         MixFraction += MixStep;
02108     }
02109 
02110     return(TRUE);
02111 }
02112 
02113 
02114 
02115 /********************************************************************************************
02116 
02117 >   static BOOL GradTable32::BuildPaletteInternalRGB(DocColour &StartCol, DocColour &EndCol,
02118                                                     View *ContextView,
02119                                                     DWORD FirstEntry, DWORD LastEntry,
02120                                                     void *pTable, BOOL IsColorRef,
02121                                                     CProfileBiasGain& BiasGain)
02122     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02123     Created:    10/9/96
02124 
02125     Inputs:     StartCol, EndCol - Define the end colours of the graduation
02126                 ContextView - Points to the view in which the gradation is to be displayed.
02127                               (This is necessary for correction and separation etc. If proper
02128                               colour handling is not needed, then you may pass NULL, but
02129                               generally, this parameter should be sensible)
02130 
02131                 FirstEntry  - The index of the first entry (inclusive) to fill in (0 is the first)
02132                 LastEntry   - The index of the last entry (exclusive) to fill in (TableSize is the last)
02133                                 (i.e. to fill entire table use (0,TableSize) which will fill in entries
02134                                     0..Tablesize-1)
02135 
02136                 IsColorRef  -   TRUE if the pTable pointer is a (COLORREF *)
02137                                 FALSE if the pTable pointer is an (RGBQUAD *)
02138 
02139                 BiasGain    - The profile that controls how the table is built
02140 
02141     Outputs:    pTable      - On return, will be filled in with appropriate colours, in the format
02142                                 indicated by the IsColorRef flag.
02143 
02144     Returns:    FALSE if it fails
02145 
02146     Purpose:    Builds a Graduated (RGB Mix) Table from StartCol to EndCol, filling in the given
02147                 table with either COLORREF or RGBQUAD entries.
02148 
02149                 NOTE that the generated entries will NOT be colour corrected or separated in
02150                 any way. You should not use this code when generating colour plates.
02151 
02152 ********************************************************************************************/
02153 
02154 BOOL GradTable32::BuildPaletteInternalRGB(DocColour &StartCol, DocColour &EndCol,
02155                                         View *ContextView,
02156                                         DWORD FirstEntry, DWORD LastEntry,
02157                                         void *pTable, BOOL IsColorRef, CProfileBiasGain& BiasGain)
02158 {
02159     ERROR3IF(ContextView == NULL || pTable == NULL, "Illegal NULL params");
02160 
02161     ColourContext *ccRGB = ColourManager::GetColourContext(COLOURMODEL_RGBT, ContextView);
02162     ERROR3IF(ccRGB == NULL, "No colour context");
02163 
02164     PColourRGBT StartDef;
02165     PColourRGBT EndDef;
02166 
02167     if (StartCol.IsTransparent())
02168         StartDef.Red = StartDef.Green = StartDef.Blue = 255L;   // If transparent, use white
02169     else
02170         ccRGB->ConvertColour(&StartCol, (ColourPacked *) &StartDef);
02171 
02172     if (EndCol.IsTransparent())
02173         EndDef.Red = EndDef.Green = EndDef.Blue = 255L;         // If transparent, use white
02174     else
02175         ccRGB->ConvertColour(&EndCol, (ColourPacked *) &EndDef);
02176 
02177     // Precalculate mixing fraction and step to minimise mul/div in the inner loop
02178     // We use an 8.24 bit fixed point notation (homebrew FIXED24s)
02179     DWORD MixStep = (1 << 24) / (LastEntry - FirstEntry);
02180     DWORD MixFraction = 0;
02181 
02182     if (IsColorRef)
02183     {
02184         COLORREF *pRefTable = (COLORREF *) pTable;
02185 
02186         DWORD R,G,B;
02187         for (DWORD col = FirstEntry; col < LastEntry; col++)
02188         {
02189             const DWORD InvFraction = 0x01000000 - MixFraction;
02190 
02191             // Calculate intermediate RGB values into 8bpp values
02192             R = ((StartDef.Red   * InvFraction) + (EndDef.Red   * MixFraction)) >> 24;
02193             G = ((StartDef.Green * InvFraction) + (EndDef.Green * MixFraction)) >> 24;
02194             B = ((StartDef.Blue  * InvFraction) + (EndDef.Blue  * MixFraction)) >> 24;
02195 
02196             // Fill in this table entry
02197             pRefTable[col] = RGB(R, G, B);
02198 
02199             MixFraction += MixStep;
02200         }
02201     }
02202     else
02203     {
02204         CProfileBiasGain DefaultBiasGain;           // default
02205         if (BiasGain == DefaultBiasGain)
02206         {
02207             RGBQUAD  *pRGBTable = (RGBQUAD *)  pTable;
02208 
02209             DWORD InvFraction;
02210 
02211             for (DWORD col = FirstEntry; col < LastEntry; col++)
02212             {
02213                 InvFraction = 0x01000000 - MixFraction;
02214 
02215                 // Calculate intermediate RGB values into the 8bpp table values
02216 #if defined(__WXMSW__)
02217                 pRGBTable[col].rgbRed   = static_cast<BYTE> (((StartDef.Red     * InvFraction) + (EndDef.Red    * MixFraction)) >> 24);
02218                 pRGBTable[col].rgbGreen = static_cast<BYTE> (((StartDef.Green   * InvFraction) + (EndDef.Green  * MixFraction)) >> 24);
02219                 pRGBTable[col].rgbBlue  = static_cast<BYTE> (((StartDef.Blue    * InvFraction) + (EndDef.Blue   * MixFraction)) >> 24);
02220 #else
02221                 pRGBTable[col].rgbBlue  = static_cast<BYTE> (((StartDef.Red     * InvFraction) + (EndDef.Red    * MixFraction)) >> 24);
02222                 pRGBTable[col].rgbGreen = static_cast<BYTE> (((StartDef.Green   * InvFraction) + (EndDef.Green  * MixFraction)) >> 24);
02223                 pRGBTable[col].rgbRed   = static_cast<BYTE> (((StartDef.Blue    * InvFraction) + (EndDef.Blue   * MixFraction)) >> 24);
02224 #endif
02225                 pRGBTable[col].rgbReserved  = 0;
02226 
02227                 MixFraction += MixStep;
02228             }
02229         }
02230         else
02231         {
02232             BiasGain.SetIntervals (AFp (0), AFp (LastEntry));
02233 
02234             RGBQUAD  *pRGBTable = (RGBQUAD *)  pTable;
02235 
02236             double MixFraction;
02237             double InvFraction;
02238             double RLastEntry = 1.0/LastEntry;
02239 
02240             for (DWORD col = FirstEntry; col < LastEntry; col++)
02241             {
02242                 MixFraction = (INT32) BiasGain.MapInterval( AFp( col ) );
02243                 MixFraction *= RLastEntry;
02244                 InvFraction = 1 - MixFraction;
02245 
02246                 // Calculate intermediate RGB values into the 8bpp table values
02247 #if defined(__WXMSW__)
02248                 pRGBTable[col].rgbRed   = static_cast<BYTE> (((StartDef.Red     * InvFraction) + (EndDef.Red    * MixFraction)));
02249                 pRGBTable[col].rgbGreen = static_cast<BYTE> (((StartDef.Green   * InvFraction) + (EndDef.Green  * MixFraction)));
02250                 pRGBTable[col].rgbBlue  = static_cast<BYTE> (((StartDef.Blue    * InvFraction) + (EndDef.Blue   * MixFraction)));
02251 #else
02252                 pRGBTable[col].rgbBlue  = static_cast<BYTE> (((StartDef.Red     * InvFraction) + (EndDef.Red    * MixFraction)));
02253                 pRGBTable[col].rgbGreen = static_cast<BYTE> (((StartDef.Green   * InvFraction) + (EndDef.Green  * MixFraction)));
02254                 pRGBTable[col].rgbRed   = static_cast<BYTE> (((StartDef.Blue    * InvFraction) + (EndDef.Blue   * MixFraction)));
02255 #endif
02256                 pRGBTable[col].rgbReserved  = 0;
02257             }
02258         }
02259     }
02260 
02261     return(TRUE);
02262 }
02263 
02264 
02265 
02266 /********************************************************************************************
02267 
02268 >   static BOOL GradTable32::BuildPaletteInternalHSV(DocColour &StartCol, DocColour &EndCol,
02269                                         View *ContextView, EFFECTTYPE Effect,
02270                                         DWORD FirstEntry, DWORD LastEntry,
02271                                         void *pTable, BOOL IsColorRef, CProfileBiasGain& BiasGain)
02272     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02273     Created:    10/9/96
02274 
02275     Inputs:     StartCol, EndCol - Define the end colours of the graduation
02276                 ContextView - Points to the view in which the gradation is to be displayed.
02277                               (This is necessary for correction and separation etc. If proper
02278                               colour handling is not needed, then you may pass NULL, but
02279                               generally, this parameter should be sensible)
02280 
02281                 Effect      - EFFECT_HSV_SHORT or EFFECT_HSV_LONG
02282 
02283                 FirstEntry  - The index of the first entry (inclusive) to fill in (0 is the first)
02284                 LastEntry   - The index of the last entry (exclusive) to fill in (TableSize is the last)
02285                                 (i.e. to fill entire table use (0,TableSize) which will fill in entries
02286                                     0..Tablesize-1)
02287 
02288                 IsColorRef  -   TRUE if the pTable pointer is a (COLORREF *)
02289                                 FALSE if the pTable pointer is an (RGBQUAD *)
02290 
02291                 BiasGain    - The profile that controls how the table is built
02292 
02293     Outputs:    pTable      - On return, will be filled in with appropriate colours, in the format
02294                                 indicated by the IsColorRef flag.
02295 
02296     Returns:    FALSE if it fails
02297 
02298     Purpose:    Builds a Graduated (HSV rainbow/alt-rainbow) Table from StartCol to EndCol, filling in
02299                 the given table with either COLORREF or RGBQUAD entries.
02300 
02301                 NOTE that the generated entries will NOT be colour corrected or separated in
02302                 any way. You should not use this code when generating colour plates.
02303 
02304 ********************************************************************************************/
02305 
02306 BOOL GradTable32::BuildPaletteInternalHSV(DocColour &StartCol, DocColour &EndCol,
02307                                         View *ContextView, EFFECTTYPE Effect,
02308                                         DWORD FirstEntry, DWORD LastEntry,
02309                                         void *pTable, BOOL IsColorRef, CProfileBiasGain& BiasGain)
02310 {
02311     ERROR3IF(ContextView == NULL || pTable == NULL, "Illegal NULL params");
02312     ERROR3IF(Effect != EFFECT_HSV_SHORT && Effect != EFFECT_HSV_LONG, "Unsupported HSV effect");
02313 
02314     ColourContext *ccHSV = ColourManager::GetColourContext(COLOURMODEL_HSVT, ContextView);
02315     ERROR3IF(ccHSV == NULL, "No colour context");
02316 
02317     PColourHSVT StartDef;
02318     PColourHSVT EndDef;
02319 
02320     if (StartCol.IsTransparent())
02321     {
02322         StartDef.Hue = 0;       // If transparent, use white
02323         StartDef.Value = 255;
02324         StartDef.Saturation = 0;
02325     }
02326     else
02327         ccHSV->ConvertColour(&StartCol, (ColourPacked *) &StartDef);
02328 
02329     if (EndCol.IsTransparent())
02330     {
02331         EndDef.Hue = 0;         // If transparent, use white
02332         EndDef.Value = 255;
02333         EndDef.Saturation = 0;
02334     }
02335     else
02336         ccHSV->ConvertColour(&EndCol, (ColourPacked *) &EndDef);
02337 
02338     // When doing alt-rainbow, if one end colour has no specific hue (saturation near 0)
02339     // then use the other colour's hue (if any)
02340     //
02341     // TODO: WRONG!!! This should always be doing these two tests, not just when
02342     // the Effect equals EFFECT_HSV_LONG. Note also that the INT32 HSV colour
02343     // generation is incorrect, although I'm not too sure why. (Gavin).
02344     //
02345     if (Effect == EFFECT_HSV_LONG)
02346     {
02347         if (StartDef.Saturation < 2 && EndDef.Saturation >= 2)
02348             StartDef.Hue = EndDef.Hue;
02349         else if (StartDef.Saturation >= 2 && EndDef.Saturation < 2)
02350             EndDef.Hue = StartDef.Hue;
02351     }
02352 
02353     // Now work out which way we have to do the mix (rainbow or alt-rainbow)
02354     BOOL BlendNormally = TRUE;
02355 
02356     // Calc. the "simple" (non-wrapping) distance between the hues
02357     double StartHue = StartDef.Hue / 360.0;
02358     double EndHue   = EndDef.Hue / 360.0;
02359 
02360     const double SimpleDist = fabs(StartHue - EndHue);
02361 
02362     // Determine whether we do a simple blend, or we have to "wrap"
02363     if (SimpleDist <= 0.5)
02364         BlendNormally = (Effect != EFFECT_HSV_LONG);
02365     else
02366         BlendNormally = (Effect == EFFECT_HSV_LONG);
02367 
02368     // If we have to go the long way, then move the smaller of the two hue
02369     // values up by 360 degrees (1.0) - after blending we'll 'mod' the result
02370     // back down into gamut.
02371     if (!BlendNormally)
02372     {
02373         if (StartHue > EndHue)
02374             EndHue += 1.0;
02375         else
02376             StartHue += 1.0;
02377     }
02378 
02379     // Precalculate mixing fraction and step to minimise mul/div in the inner loop
02380     // We use an 8.24 bit fixed point notation (homebrew FIXED24s)
02381     double MixStep = 1.0 / (double)(LastEntry - FirstEntry);
02382     double MixFraction = 0.0;
02383 
02384     if (IsColorRef)
02385     {
02386         COLORREF *pRefTable = (COLORREF *) pTable;
02387 
02388         double H, S, V;
02389         for (DWORD col = FirstEntry; col < LastEntry; col++)
02390         {
02391             const double InvFraction = 1.0 - MixFraction;
02392 
02393             // Calculate intermediate RGB values into 8bpp values
02394             H =  (StartHue            * InvFraction) + (EndHue            * MixFraction);           // 0.0 - 1.0
02395             if (H > 1.0)
02396                 H -= 1.0;       // If necessary, "mod" the value back down into the 0..1 range
02397 
02398             S = ((StartDef.Saturation * InvFraction) + (EndDef.Saturation * MixFraction)) / 255.0;  // 0.0 - 1.0
02399             V =  (StartDef.Value      * InvFraction) + (EndDef.Value      * MixFraction);           // 0.0 - 255.0
02400 
02401             // Convert the HSV value to an RGB table entry
02402             if (S == 0)
02403             {
02404                 BYTE Val = (BYTE) V;
02405                 pRefTable[col] = RGB(Val, Val, Val);
02406             }
02407             else
02408             {
02409                 H *= 6.0;
02410                 const INT32 I = (INT32) floor(H);
02411                 const double F = H - I;
02412                 const double P = V * (1.0 - S);
02413                 const double Q = V * (1.0 - (S * F));
02414                 const double T = V * (1.0 - (S * (1.0 - F)));
02415 
02416                 switch (I)
02417                 {
02418                     case 1:  pRefTable[col] = RGB(BYTE(Q), BYTE(V), BYTE(P)); break;
02419                     case 2:  pRefTable[col] = RGB(BYTE(P), BYTE(V), BYTE(T)); break;
02420                     case 3:  pRefTable[col] = RGB(BYTE(P), BYTE(Q), BYTE(V)); break;
02421                     case 4:  pRefTable[col] = RGB(BYTE(T), BYTE(P), BYTE(V)); break;
02422                     case 5:  pRefTable[col] = RGB(BYTE(V), BYTE(P), BYTE(Q)); break;
02423                     default: pRefTable[col] = RGB(BYTE(V), BYTE(T), BYTE(P)); break;
02424                 }
02425             }
02426 
02427             MixFraction += MixStep;
02428         }
02429     }
02430     else
02431     {
02432         CProfileBiasGain DefaultBiasGain;           // default
02433         if (BiasGain == DefaultBiasGain)
02434         {
02435             RGBQUAD  *pRGBTable = (RGBQUAD *)  pTable;
02436 
02437             double H, S, V;
02438             for (DWORD col = FirstEntry; col < LastEntry; col++)
02439             {
02440                 const double InvFraction = 1.0 - MixFraction;
02441 
02442                 // Calculate intermediate RGB values into 8bpp values
02443                 H =  (StartHue            * InvFraction) + (EndHue            * MixFraction);           // 0.0 - 1.0
02444                 if (H > 1.0)
02445                     H -= 1.0;       // If necessary, "mod" the value back down into the 0..1 range
02446 
02447                 S = ((StartDef.Saturation * InvFraction) + (EndDef.Saturation * MixFraction)) / 255.0;  // 0.0 - 1.0
02448                 V =  (StartDef.Value      * InvFraction) + (EndDef.Value      * MixFraction);           // 0.0 - 255.0
02449 
02450                 // Convert the HSV value to an RGB table entry
02451                 if (S == 0)
02452                 {
02453                     pRGBTable[col].rgbRed = pRGBTable[col].rgbGreen = pRGBTable[col].rgbBlue = (BYTE) V;
02454                 }
02455                 else
02456                 {
02457                     H *= 6.0;
02458                     const INT32 I = (INT32) floor(H);
02459                     const double F = H - I;
02460                     const double P = V * (1.0 - S);
02461                     const double Q = V * (1.0 - (S * F));
02462                     const double T = V * (1.0 - (S * (1.0 - F)));
02463 
02464 // Define a wee macro to make this all a lot more readable
02465 #if 0
02466 #define SETRGBENTRY(P1,P2,P3) pRGBTable[col].rgbRed = (BYTE)P3; pRGBTable[col].rgbGreen = (BYTE)P2; pRGBTable[col].rgbBlue = (BYTE)P1;
02467 #else
02468 #define SETRGBENTRY(P1,P2,P3) pRGBTable[col].rgbRed = (BYTE)P1; pRGBTable[col].rgbGreen = (BYTE)P2; pRGBTable[col].rgbBlue = (BYTE)P3;
02469 #endif
02470                     switch (I)
02471                     {
02472                         case 1:  SETRGBENTRY(Q, V, P); break;
02473                         case 2:  SETRGBENTRY(P, V, T); break;
02474                         case 3:  SETRGBENTRY(P, Q, V); break;
02475                         case 4:  SETRGBENTRY(T, P, V); break;
02476                         case 5:  SETRGBENTRY(V, P, Q); break;
02477                         default: SETRGBENTRY(V, T, P); break;
02478                     }
02479 #undef SETRGBENTRY
02480                 }
02481 
02482                 pRGBTable[col].rgbReserved = 0;
02483 
02484                 MixFraction += MixStep;
02485             }
02486         }
02487         else
02488         {
02489             BiasGain.SetIntervals (AFp (0), AFp (LastEntry));
02490 
02491             RGBQUAD  *pRGBTable = (RGBQUAD *)  pTable;
02492 
02493             double MixFraction;
02494             double InvFraction;
02495             double RLastEntry = 1.0/LastEntry;
02496 
02497             double H, S, V;
02498 
02499             for (DWORD col = FirstEntry; col < LastEntry; col++)
02500             {
02501                 //const double InvFraction = 1.0 - MixFraction;
02502 
02503                 MixFraction = (INT32) BiasGain.MapInterval( AFp( col ) );
02504                 MixFraction *= RLastEntry;
02505                 InvFraction = 1 - MixFraction;
02506 
02507                 // Calculate intermediate RGB values into 8bpp values
02508                 H =  (StartHue            * InvFraction) + (EndHue            * MixFraction);           // 0.0 - 1.0
02509                 if (H > 1.0)
02510                     H -= 1.0;       // If necessary, "mod" the value back down into the 0..1 range
02511 
02512                 S = ((StartDef.Saturation * InvFraction) + (EndDef.Saturation * MixFraction)) / 255.0;  // 0.0 - 1.0
02513                 V =  (StartDef.Value      * InvFraction) + (EndDef.Value      * MixFraction);           // 0.0 - 255.0
02514 
02515                 // Convert the HSV value to an RGB table entry
02516                 if (S == 0)
02517                 {
02518                     pRGBTable[col].rgbRed = pRGBTable[col].rgbGreen = pRGBTable[col].rgbBlue = (BYTE) V;
02519                 }
02520                 else
02521                 {
02522                     H *= 6.0;
02523                     const INT32 I = (INT32) floor(H);
02524                     const double F = H - I;
02525                     const double P = V * (1.0 - S);
02526                     const double Q = V * (1.0 - (S * F));
02527                     const double T = V * (1.0 - (S * (1.0 - F)));
02528 
02529 // Define a wee macro to make this all a lot more readable
02530 #define SETRGBENTRY(P1,P2,P3) pRGBTable[col].rgbRed = (BYTE)P1; pRGBTable[col].rgbGreen = (BYTE)P2; pRGBTable[col].rgbBlue = (BYTE)P3;
02531                     switch (I)
02532                     {
02533                         case 1:  SETRGBENTRY(Q, V, P); break;
02534                         case 2:  SETRGBENTRY(P, V, T); break;
02535                         case 3:  SETRGBENTRY(P, Q, V); break;
02536                         case 4:  SETRGBENTRY(T, P, V); break;
02537                         case 5:  SETRGBENTRY(V, P, Q); break;
02538                         default: SETRGBENTRY(V, T, P); break;
02539                     }
02540 #undef SETRGBENTRY
02541                 }
02542 
02543                 pRGBTable[col].rgbReserved = 0;
02544 
02545                 MixFraction += MixStep;
02546             }
02547         }
02548     }
02549 
02550     return(TRUE);
02551 }
02552 
02553 
02554 
02555 /********************************************************************************************
02556 
02557 >   static BOOL GradTable32::BuildPaletteInternalRGBComposite(DocColour &StartCol, DocColour &EndCol,
02558                                                     View *ContextView,
02559                                                     DWORD FirstEntry, DWORD LastEntry,
02560                                                     void *pTable, BOOL IsColorRef)
02561     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02562     Created:    12/9/96
02563 
02564     Inputs:     StartCol, EndCol - Define the end colours of the graduation
02565                 ContextView - Points to the view in which the gradation is to be displayed.
02566                               (This is necessary for correction and separation etc. If proper
02567                               colour handling is not needed, then you may pass NULL, but
02568                               generally, this parameter should be sensible)
02569 
02570                 FirstEntry  - The index of the first entry (inclusive) to fill in (0 is the first)
02571                 LastEntry   - The index of the last entry (exclusive) to fill in (TableSize is the last)
02572                                 (i.e. to fill entire table use (0,TableSize) which will fill in entries
02573                                     0..Tablesize-1)
02574 
02575                 IsColorRef  -   TRUE if the pTable pointer is a (COLORREF *)
02576                                 FALSE if the pTable pointer is an (RGBQUAD *)
02577 
02578     Outputs:    pTable      - On return, will be filled in with appropriate colours, in the format
02579                                 indicated by the IsColorRef flag.
02580 
02581     Returns:    FALSE if it fails
02582 
02583     Purpose:    Builds a Graduated (RGB Mix) Table from StartCol to EndCol, filling in the given
02584                 table with either COLORREF or RGBQUAD entries.
02585                 
02586                 ** The table is constructed taking into account "Composite Print Preview" colour
02587                 ** correction. You must only call this when generating a COLOURPLATE_COPMPOSITE
02588                 ** colour plate, when doing RGB mixes of non-CMYK colours!
02589 
02590     Notes:      (Analogue of GradTable code in BuildTable() and Filltable())
02591                 For composite preview, I've only bothered to optimise the RGB mix case, as this
02592                 is by far and away the most common one.
02593 
02594     SeeAlso:    GradTable32::BuildPaletteInternal
02595 
02596 ********************************************************************************************/
02597 
02598 BOOL GradTable32::BuildPaletteInternalRGBComposite(DocColour &StartCol, DocColour &EndCol,
02599                                         View *ContextView,
02600                                         DWORD FirstEntry, DWORD LastEntry,
02601                                         void *pTable, BOOL IsColorRef)
02602 {
02603     ERROR3IF(ContextView == NULL || pTable == NULL, "Illegal NULL params");
02604 
02605     ColourContext *ccRGB = ColourManager::GetColourContext(COLOURMODEL_RGBT, ContextView);
02606     ColourContext *cc = ColourManager::GetColourContext(COLOURMODEL_RGBT);      // RGB fade
02607     ERROR3IF(cc == NULL || ccRGB == NULL, "No colour context");
02608 
02609     ERROR3IF(ccRGB->GetColourPlate() == NULL || ccRGB->GetColourPlate()->IsDisabled() ||
02610                 ccRGB->GetColourPlate()->GetType() != COLOURPLATE_COMPOSITE,
02611                     "BuildPaletteInternalRGBComposite called under incorrect conditions");
02612 
02613     ERROR3IF(StartCol.GetColourModel() == COLOURMODEL_CMYK && EndCol.GetColourModel() == COLOURMODEL_CMYK,
02614                 "BuildPaletteInternalRGBComposite called for CMYK -> CMYK fill!");
02615 
02616     COLORREF *pRefTable = (COLORREF *) pTable;
02617     RGBQUAD  *pRGBTable = (RGBQUAD *)  pTable;
02618 
02619     PColourRGBT StartDef;
02620     PColourRGBT EndDef;
02621     ccRGB->ConvertColour(&StartCol, (ColourPacked *) &EndDef);
02622 
02623     DWORD StartIndex = FirstEntry;
02624     DWORD EndIndex;
02625 
02626     DocColour TempCol;
02627 
02628     while (StartIndex < LastEntry)
02629     {
02630         // Move the last run's end colour into Start
02631         memcpy(&StartDef, &EndDef, sizeof(PColourRGBT));
02632 
02633         // Calculate the end of this run
02634         EndIndex = StartIndex + FillStep;
02635         if (EndIndex > LastEntry)
02636             EndIndex = LastEntry;
02637 
02638         // Calculate the colour at the end of this run, and convert into EndDef
02639         TempCol.Mix(&StartCol, &EndCol,
02640                     ((double)(EndIndex - FirstEntry)) / ((double)(LastEntry - FirstEntry)),
02641                     cc, FALSE, ccRGB);
02642 
02643         ccRGB->ConvertColour(&TempCol, (ColourPacked *) &EndDef);
02644 
02645         // Linearly interpolate all colours in the run (cf GradTable::FillTable code)
02646         // BLOCK
02647         {
02648             #define MFX 24
02649 
02650             // optimised code by Mike
02651 
02652             INT32 MixFracR = ((INT32)StartDef.Red)  <<MFX;
02653             INT32 MixFracG = ((INT32)StartDef.Green)<<MFX;
02654             INT32 MixFracB = ((INT32)StartDef.Blue) <<MFX;
02655             
02656             INT32 MixStepR = ((INT32)(EndDef.Red   - StartDef.Red  ))<<MFX;
02657             INT32 MixStepG = ((INT32)(EndDef.Green - StartDef.Green))<<MFX;
02658             INT32 MixStepB = ((INT32)(EndDef.Blue  - StartDef.Blue ))<<MFX;
02659             
02660             MixStepR = MixStepR / ((INT32)(EndIndex-StartIndex));
02661             MixStepG = MixStepG / ((INT32)(EndIndex-StartIndex));
02662             MixStepB = MixStepB / ((INT32)(EndIndex-StartIndex));
02663 
02664             if (IsColorRef)
02665             {
02666                 for (DWORD Index=StartIndex; Index<EndIndex; Index++)
02667                 {
02668                     // Calculate intermediate RGB values into 8bpp values
02669                     pRefTable[Index] = RGB(MixFracR>>MFX, MixFracG>>MFX, MixFracB>>MFX);
02670                     MixFracR += MixStepR;
02671                     MixFracG += MixStepG;
02672                     MixFracB += MixStepB;
02673                 }
02674             }
02675             else
02676             {
02677                 for (DWORD Index=StartIndex; Index<EndIndex; Index++)
02678                 {
02679                     // Calculate intermediate RGB values into 8bpp values
02680                     pRGBTable[Index].rgbRed     = (BYTE)(MixFracR>>MFX);
02681                     pRGBTable[Index].rgbGreen   = (BYTE)(MixFracG>>MFX);
02682                     pRGBTable[Index].rgbBlue    = (BYTE)(MixFracB>>MFX);
02683                     pRGBTable[Index].rgbReserved = 0;
02684                     MixFracR += MixStepR;
02685                     MixFracG += MixStepG;
02686                     MixFracB += MixStepB;
02687                 }
02688             }
02689 
02690             #undef MFX
02691 /*
02692             // Place the StartDef in as the first entry
02693 
02694             if (IsColorRef)
02695                 pRefTable[StartIndex] = RGB(StartDef.Red, StartDef.Green, StartDef.Blue);
02696             else
02697             {
02698                 pRGBTable[StartIndex].rgbRed    = StartDef.Red;
02699                 pRGBTable[StartIndex].rgbGreen  = StartDef.Green;
02700                 pRGBTable[StartIndex].rgbBlue   = StartDef.Blue;
02701                 pRGBTable[StartIndex].rgbReserved = 0;
02702             }
02703 
02704             // ...and start interpolating from the second entry
02705             DWORD MixStep = (1 << 24) / (EndIndex - StartIndex);
02706             DWORD MixFraction = MixStep;
02707 
02708             DWORD R,G,B;
02709 
02710             if (IsColorRef)
02711             {
02712                 for (DWORD Index = StartIndex + 1; Index < EndIndex; Index++)
02713                 {
02714                     // Calculate intermediate RGB values into 8bpp values
02715                     const DWORD InvFraction = (0x01000000 - MixFraction);
02716                     R = ((StartDef.Red   * InvFraction) + (EndDef.Red   * MixFraction)) >> 24;
02717                     G = ((StartDef.Green * InvFraction) + (EndDef.Green * MixFraction)) >> 24;
02718                     B = ((StartDef.Blue  * InvFraction) + (EndDef.Blue  * MixFraction)) >> 24;
02719 
02720                     pRefTable[Index] = RGB(R, G, B);
02721                     MixFraction += MixStep;
02722                 }
02723             }
02724             else
02725             {
02726                 for (DWORD Index = StartIndex + 1; Index < EndIndex; Index++)
02727                 {
02728                     // Calculate intermediate RGB values into 8bpp values
02729                     const DWORD InvFraction = (0x01000000 - MixFraction);
02730                     R = ((StartDef.Red   * InvFraction) + (EndDef.Red   * MixFraction)) >> 24;
02731                     G = ((StartDef.Green * InvFraction) + (EndDef.Green * MixFraction)) >> 24;
02732                     B = ((StartDef.Blue  * InvFraction) + (EndDef.Blue  * MixFraction)) >> 24;
02733 
02734                     // Fill in this table entry
02735                     pRGBTable[Index].rgbRed     = (BYTE)R;
02736                     pRGBTable[Index].rgbGreen   = (BYTE)G;
02737                     pRGBTable[Index].rgbBlue    = (BYTE)B;
02738                     pRGBTable[Index].rgbReserved = 0;
02739 
02740                     MixFraction += MixStep;
02741                 }
02742             }
02743 */
02744         }
02745 
02746         // And step on to the next run
02747         StartIndex = EndIndex;
02748     }
02749 
02750     return(TRUE);
02751 }

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