fillramp.cpp

Go to the documentation of this file.
00001 // $Id: fillramp.cpp 1282 2006-06-09 09:46:49Z 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 
00100 #include "camtypes.h"
00101 #include "fillramp.h"
00102 //#include "paths.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00103 //#include "docrect.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00104 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00105 #include "blobs.h"
00106 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 #include "blendatt.h"
00110 #include "colormgr.h"
00111 #include "colcomp.h"        // for ColourListComponent
00112 //#include "camfiltr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 
00114 // Place any IMPLEMENT type statements here
00115 CC_IMPLEMENT_DYNCREATE(RampItem, ListItem);
00116 CC_IMPLEMENT_DYNCREATE(ColRampItem, RampItem);
00117 CC_IMPLEMENT_DYNCREATE(TranspRampItem, RampItem);
00118 
00119 CC_IMPLEMENT_DYNAMIC(FillRamp, List);
00120 CC_IMPLEMENT_DYNAMIC(ColourRamp, FillRamp);
00121 CC_IMPLEMENT_DYNAMIC(TransparencyRamp, FillRamp);
00122 
00123 // We want better memory tracking
00124 // Declare smart memory handling in Debug builds
00125 #define new CAM_DEBUG_NEW
00126 
00127 
00128 
00129 /***********************************************************************************************
00130 
00131 >   RampItem::RampItem()
00132     RampItem::RampItem(float pos)
00133     RampItem::RampItem(const RampItem &other)
00134 
00135     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00136     Created:    2/2/97
00137     Purpose:    Constructors for ramp items
00138 
00139 ***********************************************************************************************/
00140 
00141 RampItem::RampItem()
00142 {
00143     Position=0.0f;
00144     Selected=FALSE;
00145 }
00146 
00147 RampItem::RampItem(float pos)
00148 {
00149     Position=pos;
00150     Selected=FALSE;
00151     ClampPosition();
00152 }
00153 
00154 RampItem::RampItem(const RampItem &other)
00155 {
00156     Position=other.GetPosition();
00157     Selected=other.GetSelState();
00158 }
00159 
00160 
00161 /***********************************************************************************************
00162 
00163 >   void RampItem::ClampPosition()
00164 
00165     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00166     Created:    2/2/97
00167     Purpose:    Make sure the position field is in range
00168 
00169 ***********************************************************************************************/
00170 
00171 void RampItem::ClampPosition()
00172 {
00173     if (Position<0.01f) Position=0.01f;
00174     if (Position>0.99f) Position=0.99f;
00175 }
00176 
00177 
00178 /***********************************************************************************************
00179 
00180 >   void RampItem::SetPosition(float pos)
00181 
00182     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00183     Created:    2/2/97
00184     Inputs:     pos = a position value,  0<=pos<=1
00185     Purpose:    Set the position in the ramp for this colour
00186 
00187 ***********************************************************************************************/
00188 
00189 void RampItem::SetPosition(float pos)
00190 {
00191     Position=pos;
00192     ClampPosition();
00193 }
00194 
00195 /***********************************************************************************************
00196 
00197 >   void RampItem::SetSelState(BOOL selstate)
00198 
00199     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00200     Created:    2/2/97
00201     Inputs:     a bool to set the state
00202     Purpose:    Set the state of the selection flag in this colour ramp item
00203 
00204 ***********************************************************************************************/
00205 
00206 void RampItem::SetSelState(BOOL selstate)
00207 {
00208     Selected=selstate;
00209 }
00210 
00211 /***********************************************************************************************
00212 
00213 >   class ColRampItem
00214 
00215     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00216     Created:    2/2/97
00217     Purpose:    A instance of a single colour ramp entry
00218 
00219 ***********************************************************************************************/
00220 
00221 ColRampItem::ColRampItem()
00222 {
00223 }
00224 
00225 ColRampItem::ColRampItem(float pos, DocColour *pCol) : RampItem(pos)
00226 {
00227     Colour=(*pCol);
00228 }
00229 
00230 ColRampItem::ColRampItem(const ColRampItem& other) : RampItem(other)
00231 {
00232     Colour=other.GetColour();
00233 }
00234 
00235 
00236 /***********************************************************************************************
00237 
00238 >   void ColRampItem::SetColour(DocColour *pCol)
00239 
00240     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00241     Created:    2/2/97
00242     Inputs:     col = a document colour
00243     Purpose:    used to set the colour of this ramp entry
00244 
00245 ***********************************************************************************************/
00246 
00247 void ColRampItem::SetColour(DocColour *pCol)
00248 {
00249     Colour=(*pCol);
00250 }
00251 
00252 
00253 /***********************************************************************************************
00254 
00255 >   INT32 ColRampItem::operator==(const ColRampItem& other) const
00256 
00257     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00258     Created:    2/2/97
00259     Inputs:     other = the item to check this against
00260     Returns:    TRUE if this item is equivalent to other.
00261                 FALSE if not
00262     Purpose:    Check for ColRampItem equality. Do we get this as an internal function?
00263 
00264 ***********************************************************************************************/
00265 
00266 INT32 ColRampItem::operator==(const ColRampItem& other) const
00267 {
00268     return (    (Position == other.GetPosition()) && 
00269                 (Colour   == other.GetColour()) &&
00270                 (Selected == other.GetSelState())
00271            );
00272 }
00273 
00274 /***********************************************************************************************
00275 
00276 >   TranspRampItem::TranspRampItem()
00277     TranspRampItem::TranspRampItem(float pos, UINT32 transp) : RampItem(pos)
00278     TranspRampItem::TranspRampItem(const TranspRampItem& other) : RampItem(other)
00279 
00280     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00281     Created:    2/2/97
00282     Purpose:    Various constructors for the transparency ramp item class
00283 
00284 ***********************************************************************************************/
00285 
00286 TranspRampItem::TranspRampItem()
00287 {
00288 }
00289 
00290 TranspRampItem::TranspRampItem(float pos, UINT32 transp) : RampItem(pos)
00291 {
00292     Transparency=transp;
00293 }
00294 
00295 TranspRampItem::TranspRampItem(const TranspRampItem& other) : RampItem(other)
00296 {
00297     Transparency=other.GetTransparency();
00298 }
00299 
00300 
00301 /***********************************************************************************************
00302 
00303 >   void TranspRampItem::SetTransparency(UINT32 transp)
00304 
00305     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00306     Created:    2/2/97
00307     Inputs:     col = a document colour
00308     Purpose:    used to set the colour of this ramp entry
00309 
00310 ***********************************************************************************************/
00311 
00312 void TranspRampItem::SetTransparency(UINT32 transp)
00313 {
00314     Transparency=transp;
00315 }
00316 
00317 
00318 /***********************************************************************************************
00319 
00320 >   INT32 TranspRampItem::operator==(const TranspRampItem& other) const
00321 
00322     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00323     Created:    2/2/97
00324     Inputs:     other = the item to check this against
00325     Returns:    TRUE if this item is equivalent to other.
00326                 FALSE if not
00327     Purpose:    Check for ColRampItem equality. Do we get this as an internal function?
00328 
00329 ***********************************************************************************************/
00330 
00331 INT32 TranspRampItem::operator==(const TranspRampItem& other) const
00332 {
00333     return (    (Position     == other.GetPosition()) && 
00334                 (Transparency == other.GetTransparency()) &&
00335                 (Selected     == other.GetSelState())
00336            );
00337 }
00338 
00339 
00341 //
00342 //  FillRamp
00343 //
00344 //  Author:     Mike
00345 //  Created:    2/2/97
00346 //  Purpose:    The base class for our fill ramps. We keep an item of interest which follows
00347 //              the last selected or clicked item
00348 //
00350 
00351 
00352 /***********************************************************************************************
00353 
00354 >   RampItem* FillRamp::FindInsertPosition(float pos, INT32* pInsert, UINT32* pIndex)
00355 
00356     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00357     Created:    2/2/97
00358     Inputs:     pos = position of the current entry
00359     Outputs:    pInsert = 0, then insert the entry before ColRampItem*
00360                         = 1, then insert the entry after ColRampItem*
00361                 index   = then index of the returned item.
00362     Returns:    RampItem* , a pointer to an item to place pos before or after, 
00363                             NULL if the list is empty.
00364     Purpose:    Finds an insert context given a position. The idea is, if you have a new 
00365                 record to add, it needs to be added to the list after all items with a position
00366                 less than pos. This func finds the insert position and returns a value indicating
00367                 before or after. The index of your new item will depend on the pInsert value. If
00368                 0, then the new index will be (*pIndex) otherwise its (*pIndex)+1;
00369 
00370 ***********************************************************************************************/
00371 
00372 RampItem* FillRamp::FindInsertPosition(float pos, INT32* pInsert, UINT32* pIndex) const
00373 {
00374     ERROR3IF(pInsert==NULL, "NULL insert pointer passed to FillRamp::FindInsertPosition()");
00375 
00376     // need to search for
00377     RampItem *pLastItem=NULL, *pItem = (RampItem*)GetHead();
00378     (*pInsert) = 1;
00379     (*pIndex) = FILLRAMP_INDEXBASE-1;
00380 
00381     while (pItem)
00382     {
00383         (*pIndex)++;
00384         if (pItem->GetPosition() > pos)
00385         {
00386             (*pInsert) = 0;
00387             return pItem;
00388         }
00389         pLastItem = pItem;
00390         pItem = (RampItem*)GetNext(pItem);  
00391     }
00392     return pLastItem;
00393 }
00394 
00395 
00396 /***********************************************************************************************
00397 
00398 >   UINT32 FillRamp::InsertNewItem(RampItem* pNewItem)
00399 
00400     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00401     Created:    2/2/97
00402     Inputs:     pNewItem = a new item to insert in the list.
00403     Outputs:    -
00404     Returns:    the index of the inserted item
00405     Purpose:    Adds pNewItem to the growing list
00406 
00407 ***********************************************************************************************/
00408 
00409 UINT32 FillRamp::InsertNewItem(RampItem* pNewItem)
00410 {
00411     ERROR3IF(pNewItem==NULL, "NULL pointer passed to FillRamp::InsertNewItem");
00412 
00413     // keep an ordered list on pos please!
00414     INT32 insert;
00415     UINT32 index;
00416     RampItem *pContext = FindInsertPosition(pNewItem->GetPosition(),&insert,&index);
00417     if (pContext==NULL)
00418     {
00419         AddTail(pNewItem);
00420         return FILLRAMP_INDEXBASE;
00421     }
00422     if (insert==0)
00423     {
00424         InsertBefore(pContext, pNewItem);
00425         return index;
00426     }
00427     InsertAfter(pContext, pNewItem);
00428     return (index+1);
00429 }
00430 
00431 
00432 /***********************************************************************************************
00433 
00434 >   void FillRamp::DeselectAll() const
00435 
00436     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00437     Created:    2/2/97
00438     Inputs:     -
00439     Purpose:    Deselect all selection states in this fill ramp
00440 
00441 ***********************************************************************************************/
00442 
00443 void FillRamp::DeselectAll() const
00444 {
00445     RampItem *pItem = (RampItem*)GetHead();
00446     while (pItem)
00447     {
00448         pItem->SetSelState(FALSE);
00449         pItem = (RampItem*)GetNext(pItem);  
00450     }
00451 }
00452 
00453 /***********************************************************************************************
00454 
00455 >   void FillRamp::SortRamp()
00456 
00457     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00458     Created:    24/10/99
00459     Inputs:     
00460     Outputs:    
00461     Purpose:    Ensures all positions of all items in the list are in numerical order
00462 
00463 ***********************************************************************************************/
00464 void FillRamp::SortRamp()
00465 {
00466     // bubble sort algorithm - not fast but should be fast enough for our purposes
00467     RampItem * pPrevItem = (RampItem *)GetHead();
00468     RampItem * pThisItem = (RampItem *)GetNext(pPrevItem);
00469 
00470     while (pThisItem)
00471     {
00472         if (pPrevItem->GetPosition() > pThisItem->GetPosition())
00473         {
00474             // swap the values around, and then restart the list
00475             // first, remove this item
00476             RampItem * pRemovedItem = (RampItem *)RemoveItem(pThisItem);
00477             
00478             if (InsertBefore(pPrevItem, pRemovedItem) == NULL)
00479             {
00480                 ERROR3("Insert before failed");
00481                 return;
00482             }
00483 
00484             pPrevItem = (RampItem *)GetHead();
00485             pThisItem = (RampItem *)GetNext(pPrevItem);
00486         }
00487         // now, check for multiple points
00488         else if (pPrevItem->GetPosition() == pThisItem->GetPosition())
00489         {
00490             pThisItem->SetPosition(pPrevItem->GetPosition() + 0.01f);
00491             pThisItem = (RampItem *)GetNext(pThisItem);
00492             pPrevItem = (RampItem *)GetNext(pPrevItem);
00493         }
00494         else
00495         {
00496             pThisItem = (RampItem *)GetNext(pThisItem);
00497             pPrevItem = (RampItem *)GetNext(pPrevItem);
00498         }
00499     }
00500 }
00501 
00502 
00503 
00504 /***********************************************************************************************
00505 
00506 >   void FillRamp::Blend (BlendAttrParam* pBlendParam, FillRamp* OtherRamp)
00507 
00508     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00509     Created:    17/4/2000
00510     Inputs:     
00511     Outputs:    
00512     Purpose:    Blends mutistage fill ramps.  Well actually its support functions do, but
00513                 this one works out which blending case we are doing.
00514 
00515                 CGS:  I've added the ability to avoid inverting ratios (by passing notInvert as TRUE).
00516                 (only DoManyToNoneBlend () makes use of this at the moment)
00517 
00518 ***********************************************************************************************/
00519 
00520 void FillRamp::Blend (FillGeometryAttribute* pNewAttr, BlendAttrParam* pBlendParam, FillGeometryAttribute* pOtherFill, BOOL notInvert)
00521 {
00522     //ERRORIF (!pOtherFill, "Dodgy entry params!", NULL);
00523 
00524     FillRamp* OtherRamp = pOtherFill->GetColourRamp ();
00525     
00526     // if neither contains a fill ramp - then return
00527     if ((this == NULL) && (OtherRamp == NULL))
00528     {
00529         return;
00530     }
00531 
00532     // ok we've got at least one fillramp - so proceed ....
00533     // now decide the type of blending that we need to do ....
00534     
00535     enum MappingType { MT_ONETOONE,         // equal numbers of fill blobs
00536                        MT_NONETOMANY,       // no fill blobs to many
00537                        MT_MANYTONONE,       // many fill blobs to none
00538                        MT_MANYTOMANY,       // many fills blobs to many fills blobs
00539                                             // (but different numbers of fill blobs)
00540                      //MT_MANYTOMANYLESS,   // less fill blobs to more fill blobs
00541                      //MT_MANYTOMANYMORE,   // more fill blobs to less fill blobs
00542                        MT_NONE };           // sensible default
00543     
00544     MappingType FunctionMapper = MT_NONE;
00545 
00546     if (this == NULL)
00547     {
00548         if (OtherRamp != NULL)
00549         {
00550             FunctionMapper = MT_NONETOMANY;
00551         }
00552         // else - nothing (this is impossible)
00553     }
00554     else if (OtherRamp == NULL)
00555     {
00556         if (this != NULL)
00557         {
00558             FunctionMapper = MT_MANYTONONE;
00559         }
00560         // else - nothing (this is impossible)
00561     }
00562     else
00563     {
00564         if (GetCount () == OtherRamp->GetCount ())
00565         {
00566             FunctionMapper = MT_ONETOONE;
00567         }
00568         else
00569         {
00570             // were in the dreaded many-to-many case ....
00571 
00572             FunctionMapper = MT_MANYTOMANY;
00573         }
00574     }
00575 
00576     // invoke the appropriate support function ....
00577 
00578     switch (FunctionMapper)
00579     {
00580         case MT_ONETOONE:
00581         {
00582             DoOneToOneBlend (pNewAttr, pBlendParam, OtherRamp, notInvert);
00583         }
00584         break;
00585         case MT_NONETOMANY:
00586         {
00587             DoNoneToManyBlend (pNewAttr, pBlendParam, OtherRamp, notInvert);
00588         }
00589         break;
00590         case MT_MANYTONONE:
00591         {
00592             DoManyToNoneBlend (pNewAttr, pBlendParam, pOtherFill, notInvert);
00593         }
00594         break;
00595         case MT_MANYTOMANY:
00596         {
00597             DoManyToManyBlend (pNewAttr, pBlendParam, OtherRamp, notInvert);
00598         }
00599         break;
00600         default:
00601             return;     // um .....
00602         break;
00603     }
00604 }
00605 
00606 
00607 
00608 /***********************************************************************************************
00609 
00610 >   void FillRamp::DoOneToOneBlend (FillGeometryAttribute* pNewAttr, BlendAttrParam* pBlendParam, FillRamp* OtherRamp)
00611 
00612     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00613     Created:    17/4/2000
00614     Inputs:     
00615     Outputs:    
00616     Purpose:    Blends mutistage fill ramps.  This function blends equal numbers of blobs.
00617 
00618 ***********************************************************************************************/
00619 
00620 void FillRamp::DoOneToOneBlend (FillGeometryAttribute* pNewAttr, BlendAttrParam* pBlendParam, FillRamp* OtherRamp, BOOL notInvert)
00621 {
00622     // find what point along the blend we are at
00623     double Ratio = pBlendParam->GetBlendRatio ();
00624 
00625     RampItem* pItem = (RampItem*) GetHead ();
00626     RampItem* pOtherItem = (RampItem*) OtherRamp->GetHead ();
00627 
00628     // simply interpolate between the respective colour ramp blobs ....
00629 
00630     DocColour BlendedColour;
00631 
00632     ColourContext *cc = ColourManager::GetColourContext (COLOURMODEL_RGBT);
00633     
00634     while (pItem && pOtherItem)
00635     {
00636         DocColour StartColour = ((ColRampItem*) pItem->GetItem ())->GetColour ();
00637         DocColour EndColour = ((ColRampItem*) pOtherItem->GetItem ())->GetColour (); 
00638         BlendedColour.Mix (
00639                             &StartColour,       // start blend colour
00640                             &EndColour,         // end blend colour
00641                             Ratio,              // the blend ratio
00642                             cc                  // RGB space please
00643                           );
00644 
00645         ((ColRampItem*) pItem->GetItem ())->SetColour (&BlendedColour);
00646         
00647         pItem = (RampItem*) GetNext (pItem);
00648         pOtherItem = (RampItem*) OtherRamp->GetNext (pOtherItem);
00649     }
00650 }
00651 
00652 
00653 
00654 /***********************************************************************************************
00655 
00656 >   void FillRamp::DoNoneToManyBlend (FillGeometryAttribute* pNewAttr, BlendAttrParam* pBlendParam, FillRamp* OtherRamp)
00657 
00658     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00659     Created:    17/4/2000
00660     Inputs:     
00661     Outputs:    
00662     Purpose:    Blends mutistage fill ramps.  This function blends none to many blobs.
00663 
00664 ***********************************************************************************************/
00665 
00666 void FillRamp::DoNoneToManyBlend (FillGeometryAttribute* pNewAttr, BlendAttrParam* pBlendParam, FillRamp* OtherRamp, BOOL notInvert)
00667 {
00668     // find what point along the blend we are at
00669     double Ratio = pBlendParam->GetBlendRatio ();
00670 
00671     DocColour* StartCol = pNewAttr->GetStartColour ();
00672     DocColour* EndCol = pNewAttr->GetEndColour ();
00673 
00674     // first see if weve got something that we can safely blend with
00675     // if either colour is NULL, then forget it; just set the colour ramp to NULL ....
00676 
00677     if (!((StartCol == NULL) && (EndCol == NULL)))
00678     {
00679         ColourRamp* NewColourRamp = new ColourRamp ();
00680 
00681         DocColour BlendedColour;
00682         DocColour BlendedColour2;
00683 
00684         ColourContext *cc = ColourManager::GetColourContext (COLOURMODEL_RGBT);
00685 
00686         if (NewColourRamp)
00687         {
00688             ColRampItem* pOtherItem = (ColRampItem*) OtherRamp->GetHead ();
00689 
00690             while (pOtherItem)
00691             {
00692                 ColRampItem* pNewItem = new ColRampItem (*pOtherItem);
00693                 
00694                 // first mix the two endpoints based upon the other fillramp blob positions ....
00695                 
00696                 BlendedColour.Mix (
00697                                     StartCol,       // start blend colour
00698                                     EndCol,         // end blend colour
00699                                     ((ColRampItem*) pOtherItem->GetItem ())->GetPosition (),    // the blend ratio
00700                                     cc                                                          // RGB space please
00701                                   );
00702 
00703                 // then mix this new colour with the other fillramp blob colours ....
00704 
00705                 DocColour EndColour = ((ColRampItem*) pOtherItem->GetItem ())->GetColour ();
00706                 BlendedColour2.Mix (
00707                                     &BlendedColour,
00708                                     &EndColour,
00709                                     Ratio,                                                  // the blend ratio
00710                                     cc                                                      // RGB space please
00711                                    );
00712 
00713                 pNewItem->SetColour (&BlendedColour2);
00714 
00715                 NewColourRamp->InsertNewItem (pNewItem);
00716                 
00717                 pOtherItem = (ColRampItem*) OtherRamp->GetNext (pOtherItem);
00718             }
00719             pNewAttr->SetColourRamp (NewColourRamp);
00720         }
00721 
00722         delete (NewColourRamp);
00723     }
00724     else
00725     {
00726         pNewAttr->SetColourRamp (NULL);
00727     }
00728 }
00729 
00730 
00731 
00732 /***********************************************************************************************
00733 
00734 >   void FillRamp::DoManyToNoneBlend (FillGeometryAttribute* pNewAttr, BlendAttrParam* pBlendParam, FillRamp* OtherRamp)
00735 
00736     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00737     Created:    17/4/2000
00738     Inputs:     
00739     Outputs:    
00740     Purpose:    Blends mutistage fill ramps.  This function blends many to no none fill blobs.
00741 
00742 ***********************************************************************************************/
00743 
00744 void FillRamp::DoManyToNoneBlend (FillGeometryAttribute* pNewAttr, BlendAttrParam* pBlendParam, FillGeometryAttribute* pOtherFill, BOOL notInvert)
00745 {
00746     // find what point along the blend we are at
00747     double Ratio = 1;
00748         
00749     if (!notInvert)
00750     {
00751         Ratio = 1 - pBlendParam->GetBlendRatio ();
00752     }
00753     else
00754     {
00755         Ratio = pBlendParam->GetBlendRatio ();
00756     }
00757 
00758     DocColour* StartCol = pOtherFill->GetStartColour ();//pNewAttr->GetStartColour ();
00759     DocColour* EndCol = pOtherFill->GetEndColour ();//pNewAttr->GetEndColour ();
00760 
00761     if (!EndCol)
00762     {
00763         EndCol = StartCol;
00764     }
00765 
00766     if ((EndCol == NULL) && (StartCol == NULL))
00767     {
00768         // do nothing
00769         return;
00770     }
00771 
00772     ColourRamp* NewColourRamp = new ColourRamp ();
00773 
00774     DocColour BlendedColour;
00775     DocColour BlendedColour2;
00776 
00777     ColourContext *cc = ColourManager::GetColourContext (COLOURMODEL_RGBT);
00778 
00779     if (NewColourRamp)
00780     {
00781         ColRampItem* pItem = (ColRampItem*) GetHead ();
00782 
00783         while (pItem)
00784         {
00785             ColRampItem* pNewItem = new ColRampItem (*pItem);
00786             
00787             // first mix the two endpoints based upon the other fillramp blob positions ....
00788             
00789             BlendedColour.Mix (
00790                                 StartCol,       // start blend colour
00791                                 EndCol,         // end blend colour
00792                                 ((ColRampItem*) pItem->GetItem ())->GetPosition (), // the blend ratio
00793                                 cc                                                          // RGB space please
00794                               );
00795 
00796             // then mix this new colour with the other fillramp blob colours ....
00797             DocColour EndColour = ((ColRampItem*) pItem->GetItem ())->GetColour ();
00798             BlendedColour2.Mix (
00799                                 &BlendedColour,
00800                                 &EndColour,
00801                                 Ratio,                                                  // the blend ratio
00802                                 cc                                                      // RGB space please
00803                                );
00804 
00805             pNewItem->SetColour (&BlendedColour2);
00806 
00807             NewColourRamp->InsertNewItem (pNewItem);
00808             
00809             pItem = (ColRampItem*) GetNext (pItem);
00810         }
00811         pNewAttr->SetColourRamp (NewColourRamp);
00812     }
00813     
00814     delete (NewColourRamp);
00815 }
00816 
00817 // the following two functions do the following to achieve blending ....
00818 
00819 /*
00820     Fill (less blobs):          x           x           x                   x       
00821     Mapping:            |           |           |                   |               |
00822     Fill (more blobs):  x           x           x                   x               x
00823 */
00824 
00825 /*  'superimposes' the ramp positions of that with with the greatest onto that with the lesser.
00826      colour values are then ccalculated for for these new blobs with respect to the ranges of the
00827      old ....
00828 */
00829 
00830 /***********************************************************************************************
00831 
00832 >   void FillRamp::DoManyToManyBlend (FillGeometryAttribute* pNewAttr, BlendAttrParam* pBlendParam, FillRamp* OtherRamp)
00833 
00834     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00835     Created:    18/4/2000
00836     Inputs:     
00837     Outputs:    
00838     Purpose:    Blends mutistage fill ramps.  This function handles the many to many case.
00839 
00840 ***********************************************************************************************/
00841 
00842 void FillRamp::DoManyToManyBlend (FillGeometryAttribute* pNewAttr, BlendAttrParam* pBlendParam, FillRamp* OtherRamp, BOOL notInvert)
00843 {
00844     // find what point along the blend we are at
00845     double Ratio = pBlendParam->GetBlendRatio ();
00846 
00847     DocColour BlendedColour;
00848     ColourContext *cc = ColourManager::GetColourContext (COLOURMODEL_RGBT);
00849 
00850     RampItem* pItem = (RampItem*) GetHead ();
00851     RampItem* pOtherItem = (RampItem*) OtherRamp->GetHead ();
00852 
00853     ColourRamp* NewColourRamp1 = new ColourRamp ();
00854     *NewColourRamp1 = *((ColourRamp*) this);
00855     ColourRamp* NewColourRamp2 = new ColourRamp ();
00856     *NewColourRamp2 = *((ColourRamp*) OtherRamp);
00857     ColourRamp* NewColourRamp3 = new ColourRamp ();
00858     
00859     ColRampItem* pFirstItem = (ColRampItem*) GetHead ();
00860     ColRampItem* pSecondItem = (ColRampItem*) OtherRamp->GetHead ();
00861 
00862     DocColour* StartCol = NULL;//pNewAttr->GetStartColour ();
00863     DocColour* EndCol = NULL;//&pFirstItem->GetColour ();
00864 
00865     DocColour tempStartCol;
00866     DocColour tempEndCol; // these avoid taking the address of a temporary
00867 
00868     // now insert the first blobs into the second ....
00869 
00870     float PrevPos = -1, NextPos = -1;
00871 
00872     while (pSecondItem)
00873     {
00874         ColRampItem* pNewItem = new ColRampItem (*pSecondItem);
00875 
00876         NewColourRamp1->InsertNewItem (pNewItem);
00877 
00878         ColRampItem* pPrevItem = (ColRampItem*) NewColourRamp1->GetPrev (pNewItem);
00879         ColRampItem* pNextItem = (ColRampItem*) NewColourRamp1->GetNext (pNewItem);
00880 
00881         if (!pPrevItem)
00882         {
00883             StartCol = pNewAttr->GetStartColour ();
00884             PrevPos = 0.0;
00885         }
00886         else
00887         {
00888             tempStartCol = pPrevItem->GetColour ();
00889             StartCol = &tempStartCol;
00890             PrevPos = pPrevItem->GetPosition ();
00891         }
00892 
00893         if (!pNextItem)
00894         {
00895             EndCol = pNewAttr->GetEndColour ();
00896             NextPos = 1.0;
00897         }
00898         else
00899         {
00900             tempEndCol = pNextItem->GetColour ();
00901             EndCol = &tempEndCol;
00902             NextPos = pNextItem->GetPosition ();
00903         }
00904 
00905         BlendedColour.Mix (
00906                                 StartCol,                       // start blend colour
00907                                 EndCol,                         // end blend colour
00908                                 NextPos - PrevPos,              // the blend ratio
00909                                 cc                              // RGB space please
00910                               );
00911 
00912         pNewItem->SetColour (&BlendedColour);
00913         
00914         pSecondItem = (ColRampItem*) GetNext (pSecondItem);
00915     }
00916 
00917     pFirstItem = (ColRampItem*) GetHead ();
00918     pSecondItem = (ColRampItem*) OtherRamp->GetHead ();
00919 
00920     // now insert the first blobs into the second ....
00921 
00922     PrevPos = -1, NextPos = -1;
00923 
00924     while (pFirstItem)
00925     {
00926         ColRampItem* pNewItem = new ColRampItem (*pFirstItem);
00927 
00928         NewColourRamp2->InsertNewItem (pNewItem);
00929 
00930         ColRampItem* pPrevItem = (ColRampItem*) NewColourRamp2->GetPrev (pNewItem);
00931         ColRampItem* pNextItem = (ColRampItem*) NewColourRamp2->GetNext (pNewItem);
00932 
00933         if (!pPrevItem)
00934         {
00935             StartCol = pNewAttr->GetStartColour ();
00936             PrevPos = 0.0;
00937         }
00938         else
00939         {
00940             tempStartCol = pPrevItem->GetColour ();
00941             StartCol = &tempStartCol;
00942             PrevPos = pPrevItem->GetPosition ();
00943         }
00944 
00945         if (!pNextItem)
00946         {
00947             EndCol = pNewAttr->GetEndColour ();
00948             NextPos = 1.0;
00949         }
00950         else
00951         {
00952             tempEndCol = pNextItem->GetColour ();
00953             EndCol = &tempEndCol;
00954             NextPos = pNextItem->GetPosition ();
00955         }
00956 
00957         BlendedColour.Mix (
00958                                 StartCol,                       // start blend colour
00959                                 EndCol,                         // end blend colour
00960                                 NextPos - PrevPos,              // the blend ratio
00961                                 cc                              // RGB space please
00962                               );
00963 
00964         pNewItem->SetColour (&BlendedColour);
00965         
00966         pFirstItem = (ColRampItem*) GetNext (pFirstItem);
00967     }
00968     
00969     // simply interpolate between the respective colour ramp blobs ....
00970 
00971     pItem = (RampItem*) NewColourRamp1->GetHead ();
00972     pOtherItem = (RampItem*) NewColourRamp2->GetHead ();
00973     
00974     while (pItem && pOtherItem)
00975     {
00976         ColRampItem* pNewItem = new ColRampItem (*((ColRampItem*) pItem));
00977         
00978         NewColourRamp3->InsertNewItem (pNewItem);
00979         
00980         tempStartCol = ((ColRampItem*) pItem->GetItem ())->GetColour ();
00981         tempEndCol = ((ColRampItem*) pOtherItem->GetItem ())->GetColour ();
00982         BlendedColour.Mix (
00983                             &tempStartCol,      // start blend colour
00984                             &tempEndCol,        // end blend colour
00985                             Ratio,              // the blend ratio
00986                             cc                  // RGB space please
00987                           );
00988 
00989         pNewItem->SetColour (&BlendedColour);
00990         
00991         pItem = (RampItem*) NewColourRamp1->GetNext (pItem);
00992         pOtherItem = (RampItem*) NewColourRamp2->GetNext (pOtherItem);
00993     }
00994     pNewAttr->SetColourRamp (NewColourRamp3);
00995 
00996     delete (NewColourRamp1);
00997     delete (NewColourRamp2);
00998     delete (NewColourRamp3);
00999 }
01000 
01001 
01002 
01003 /***********************************************************************************************
01004 
01005 >   BOOL FillRamp::RotateSelRight(BOOL RollIn) const
01006 
01007     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01008     Created:    2/2/97
01009     Inputs:     RollIn = a boolean value rolled in from the previous item on the left
01010     Outputs:    A bool, the state of the last item rolled out of the right
01011     Purpose:    Roll the selection state of the items in the list to the right. That equates to
01012                 rolling the selection down the list by one element.
01013 
01014 ***********************************************************************************************/
01015 
01016 FillControl FillRamp::RotateSelRight(BOOL StartPointSelected, BOOL EndPointSelected, FillControl& OldSelectedBlob) const
01017 {
01018     if (StartPointSelected)
01019     {
01020         // select first blob in list ....
01021         RampItem *pItem = (RampItem*) GetHead();
01022         pItem->SetSelState (TRUE);
01023 
01024         FillControl Ret = GetSelectedIndex ();
01025         pItem->SetSelState (FALSE);
01026 
01027         OldSelectedBlob = FILLCONTROL_NULL;
01028         
01029         return (Ret);
01030     }
01031 
01032     if (EndPointSelected)
01033     {
01034         OldSelectedBlob = FILLCONTROL_ENDPOINT;
01035         return (FILLCONTROL_STARTPOINT);
01036     }
01037 
01038     // if we haven't returned yet, then the selection will within our ramp ....
01039 
01040     RampItem* pItem = (RampItem*) GetHead();
01041     RampItem* pSelectedBlob = NULL;
01042     while (pItem)
01043     {
01044         if (pItem->IsSelected ())
01045         {
01046             pSelectedBlob = pItem;
01047             break;
01048         }
01049         pItem = (RampItem*)GetNext(pItem);
01050     }
01051 
01052     RampItem* pSelNext = (RampItem*) GetNext (pSelectedBlob);
01053 
01054     if (pSelNext != NULL)
01055     {
01056         OldSelectedBlob = GetSelectedIndex ();
01057         pSelectedBlob->SetSelState (FALSE);
01058         pSelNext->SetSelState (TRUE);
01059 
01060         FillControl Ret = GetSelectedIndex ();
01061         pSelNext->SetSelState (FALSE);
01062         
01063         return (Ret);
01064     }
01065     else
01066     {
01067         OldSelectedBlob = GetSelectedIndex ();
01068         pSelectedBlob->SetSelState (FALSE);
01069         return (FILLCONTROL_ENDPOINT);
01070     }
01071 }
01072 
01073 /***********************************************************************************************
01074 
01075 >   BOOL FillRamp::RotateSelLeft(BOOL RollIn) const
01076 
01077     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01078     Created:    2/2/97
01079     Inputs:     RollIn = a boolean value rolled in from the previous item on the right
01080     Outputs:    A bool, the state of the last item rolled out of the left
01081     Purpose:    Roll the selection state of the items in the list to the left. That equates to
01082                 rolling the selection up the list by one element.
01083 
01084 ***********************************************************************************************/
01085 
01086 BOOL FillRamp::RotateSelLeft(BOOL StartPointSelected, BOOL EndPointSelected, FillControl& OldSelectedBlob) const
01087 {
01088     if (StartPointSelected)
01089     {
01090         OldSelectedBlob = FILLCONTROL_STARTPOINT;
01091         return (FILLCONTROL_ENDPOINT);
01092     }
01093 
01094     if (EndPointSelected)
01095     {
01096         // select first blob in list ....
01097         RampItem *pItem = (RampItem*) GetTail();
01098         pItem->SetSelState (TRUE);
01099 
01100         FillControl Ret = GetSelectedIndex ();
01101         pItem->SetSelState (FALSE);
01102 
01103         OldSelectedBlob = FILLCONTROL_NULL;
01104         
01105         return (Ret);
01106     }
01107 
01108     // if we haven't returned yet, then the selection will within our ramp ....
01109 
01110     RampItem* pItem = (RampItem*) GetTail();
01111     RampItem* pSelectedBlob = NULL;
01112     while (pItem)
01113     {
01114         if (pItem->IsSelected ())
01115         {
01116             pSelectedBlob = pItem;
01117             break;
01118         }
01119         pItem = (RampItem*)GetPrev(pItem);
01120     }
01121 
01122     RampItem* pSelNext = (RampItem*) GetPrev (pSelectedBlob);
01123 
01124     if (pSelNext != NULL)
01125     {
01126         OldSelectedBlob = GetSelectedIndex ();
01127         pSelectedBlob->SetSelState (FALSE);
01128         pSelNext->SetSelState (TRUE);
01129 
01130         FillControl Ret = GetSelectedIndex ();
01131         pSelNext->SetSelState (FALSE);
01132         
01133         return (Ret);
01134     }
01135     else
01136     {
01137         OldSelectedBlob = GetSelectedIndex ();
01138         pSelectedBlob->SetSelState (FALSE);
01139         return (FILLCONTROL_STARTPOINT);
01140     }
01141 
01142     /* perform a ROL on the selection in this fill ramp
01143     BOOL Temp;
01144     RampItem *pItem = (RampItem*)GetTail();
01145     while (pItem)
01146     {
01147         Temp = pItem->GetSelState();
01148         pItem->SetSelState(RollIn);
01149         RollIn = Temp;
01150         pItem = (RampItem*)GetPrev(pItem);  
01151     }
01152     return RollIn;*/
01153 }
01154     
01155 
01156 /***********************************************************************************************
01157 
01158 >   UINT32 FillRamp::CountSelBlobs() const
01159 
01160     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01161     Created:    2/2/97
01162     Inputs:     -
01163     Returns:    The number of selected items in this list
01164     Purpose:    Simply count all the selected items in this list.
01165 
01166 ***********************************************************************************************/
01167 
01168 UINT32 FillRamp::CountSelBlobs() const
01169 {
01170     // perform a ROL on the selection in this fill ramp
01171     UINT32 count=0;
01172     RampItem *pItem = (RampItem*)GetHead();
01173     while (pItem)
01174     {
01175         count += ((pItem->GetSelState()==TRUE) ? 1 : 0);
01176         pItem = (RampItem*)GetNext(pItem);  
01177     }
01178     return count;
01179 }
01180 
01181 
01182 /***********************************************************************************************
01183 
01184 >   INT32 FillRamp::GetSelectedIndex() const
01185 
01186     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01187     Created:    2/2/97
01188     Inputs:     -
01189     Returns:    The index of the first selected item in the ramp list [0..n-1]
01190                 the index is adjusted by FILLRAMP_INDEXBASE
01191                 -1 if there are no selected items in this ramp
01192     Purpose:    Return the index of the first selected item in this list. The index is
01193                 adjusted by FILLRAMP_INDEXBASE i.e. this constant value is always added to
01194                 an index to give the range [FILLRAMP_INDEXBASE...FILLRAMP_INDEXBASE+n-1].
01195                 This is done so one can distinguish between indexes for fill geometry end
01196                 points (usually 0..7 or thereabouts) and the fill ramp blobs.
01197 
01198 ***********************************************************************************************/
01199 
01200 INT32 FillRamp::GetSelectedIndex() const
01201 {
01202     UINT32 index=FILLRAMP_INDEXBASE;
01203     RampItem *pItem = (RampItem*)GetHead();
01204     while (pItem)
01205     {
01206         if (pItem->GetSelState())
01207             return index;
01208         index++;
01209         pItem = (RampItem*)GetNext(pItem);  
01210     }
01211     return -1;
01212 }
01213 
01214 
01215 /***********************************************************************************************
01216 
01217 >   BOOL FillRamp::GetIndexRange(UINT32 *pFirst, UINT32 *pLast) const
01218 
01219     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01220     Created:    2/2/97
01221     Inputs:     -
01222     Outputs:    pFirst = assigned the index of the first ramp item
01223                 pLast  = assigned the index of the last ramp item
01224     Returns:    FALSE if the list is actually empty
01225                 TRUE if there are entries in this list
01226     Purpose:    Return the index of the first and last entries in this list. As the list
01227                 indexes are biased by an unknown value, at least unknown to everyone but the
01228                 author, one needs to use this class function to find out the values of the
01229                 first and last indexes. All I'll tell you is that they behaviour linearly
01230                 between the two extreems. 
01231 
01232 ***********************************************************************************************/
01233 
01234 BOOL FillRamp::GetIndexRange(UINT32 *pFirst, UINT32 *pLast) const
01235 {
01236     INT32 c=GetCount();
01237     if (pFirst!=NULL)
01238         *pFirst = FILLRAMP_INDEXBASE;
01239     if (pLast!=NULL)
01240         *pLast  = FILLRAMP_INDEXBASE+c-1;
01241     return (c>0);
01242 }
01243     
01244 
01245 
01246 
01247 /***********************************************************************************************
01248 
01249 >   BOOL FillRamp::HitBlob(GeomType geom, DocCoord p0, DocCoord p1, DocCoord ClickPos) const
01250 
01251     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01252     Created:    5/2/97
01253     Inputs:     geom = the geometry, we currently support linear and circular
01254                 p0,p1 depend on geom
01255                 geom = GEOM_LINEAR
01256                     p0 = a coord describing the start of a line
01257                     p1 = a coord describing the start of a line or a point on the cir
01258                 geom = GEOM_CIRCULAR
01259                     p0 = a coord describing the centre of a circle
01260                     p1 = a coord describing the start of a line or a point on the cir
01261     
01262     Returns:    TRUE if a blob was hit
01263                 FALSE if no blob was hit
01264     Effects:    LastItemOfInterest is set to NULL if no blob was hit, or points to the item hit
01265     Purpose:    Check to see if a ramp item was hit by this click. If so return yes. We also
01266                 set and internal pointer on the result of this check, which can be used to
01267                 make edits.
01268 
01269 ***********************************************************************************************/
01270 
01271 UINT32 FillRamp::HitBlob(FillGeometryAttribute *pAttrValue, DocCoord& ClickPos) const
01272 {
01273     DocRect BlobRect;
01274     DocCoord point;
01275     float pos;
01276     
01277     if (pAttrValue!=NULL)
01278     {   
01279         // search from the last first
01280         RampItem *pItem = (RampItem*)GetHead();
01281         UINT32 i = FILLRAMP_INDEXBASE;
01282         // find a suitable blob rect around this point          
01283         (GetApplication()->GetBlobManager())->GetBlobRect(ClickPos, &BlobRect, TRUE);
01284         while (pItem)
01285         {
01286             pos = pItem->GetPosition();
01287             point = pAttrValue->GetGeometryCoord(pos);
01288             // See if the Click Position is within the rectangle
01289             if ( BlobRect.ContainsCoord(point) )
01290                 return i;
01291             // otherwise continue onwards
01292             i++;
01293             pItem = (RampItem*)GetNext(pItem);  
01294         }
01295     }
01296     // nothing was under this click position
01297     return FILLRAMP_ILLEGALINDEX;
01298 }
01299 
01300 
01301 /***********************************************************************************************
01302 
01303 >   void FillRamp::GetSelectionState(BOOL* SelState) const
01304 
01305     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01306     Created:    10/3/97
01307     Inputs:     SelState = a pointer to an array of BOOLs
01308     Purpose:    Record the selection state of all the ramp blobs in this array.
01309 
01310 ***********************************************************************************************/
01311 
01312 void FillRamp::GetSelectionState(BOOL* SelState) const
01313 {
01314     RampItem *pItem = (RampItem*)GetHead();
01315     while (pItem)
01316     {
01317         *SelState++ = (pItem->GetSelState());
01318         pItem = (RampItem*)GetNext(pItem);
01319     }
01320 }
01321 
01322 
01323 /***********************************************************************************************
01324 
01325 >   BOOL FillRamp::IsSelected(UINT32 index) const
01326 
01327     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01328     Created:    10/3/97
01329     Inputs:     index = the ramp index
01330     Purpose:    Find out whether this ramp index is selected or not.
01331 
01332 ***********************************************************************************************/
01333 
01334 BOOL FillRamp::IsSelected(UINT32 index) const
01335 {
01336     RampItem* pItem = GetValidIndexedItem(index);
01337     if (pItem)
01338         return pItem->IsSelected();
01339 
01340     return FALSE;
01341 }
01342     
01343 
01344 /***********************************************************************************************
01345 
01346 >   RampItem* FillRamp::GetIndexedItem(INT32 index) const
01347 
01348     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01349     Created:    10/3/97
01350     Inputs:     index = the ramp index
01351     Returns:    A pointer to the item at this index position in the ramp, or NULL if none
01352     Purpose:    Find the i'th item in this fill ramp
01353 
01354 ***********************************************************************************************/
01355 
01356 RampItem* FillRamp::GetIndexedItem(INT32 index) const
01357 {
01358     if (index>=0)
01359     {
01360         RampItem *pItem = (RampItem*)GetHead();
01361         while (pItem)
01362         {
01363             if (index==0)
01364                 return pItem;
01365             index--;
01366             pItem = (RampItem*)GetNext(pItem);
01367         }
01368     }
01369     return NULL;
01370 }
01371 
01372 /***********************************************************************************************
01373 
01374 >   RampItem* FillRamp::GetValidIndexedItem(UINT32 index) const
01375 
01376     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01377     Created:    10/3/97
01378     Inputs:     index = the ramp index
01379     Returns:    A pointer to the item at this index position in the ramp, or NULL if none
01380     Purpose:    Find the i'th item in this fill ramp. The index is the normal biased index
01381                 passed into us from the external world. We convert the index and perform
01382                 some error checking on it before we attempt to find the relevant item.
01383 
01384 ***********************************************************************************************/
01385 
01386 RampItem* FillRamp::GetValidIndexedItem(UINT32 index) const
01387 {
01388     INT32 i = ((INT32)(index)) - FILLRAMP_INDEXBASE;
01389     if (i<0)
01390     {
01391         ERROR3("Illegal index passed to FillRamp::GetValidIndexedItem()");
01392         return NULL;
01393     }
01394 
01395     RampItem *pItem = GetIndexedItem(i);
01396     if (pItem==NULL)
01397     {
01398         ERROR3("Index out of range in FillRamp::GetValidIndexedItem()");
01399         return NULL;
01400     }
01401 
01402     return pItem;
01403 }
01404 
01405 
01406 /********************************************************************************************
01407 
01408 >   void FillRamp::SetSelState(UINT32 HitControl, INT32 state)
01409 
01410     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01411     Created:    10/3/97
01412     Inputs:     HitControl, the FillControl that is to be selected.
01413                 state = 0 = deselect blob
01414                         1 = select blob
01415                         2 = toggle blob selection
01416     Purpose:    Sets the state of a fill ramp blob
01417 
01418 ********************************************************************************************/
01419 
01420 void FillRamp::SetSelState(UINT32 index, INT32 NewState)
01421 {
01422     INT32 i = ((INT32)(index)) - FILLRAMP_INDEXBASE;
01423     ERROR3IF(i<0, "Illegal index passed to FillRamp::ChangeBlobState()");
01424     if (i>=0)
01425     {
01426         RampItem* pItem = GetIndexedItem(i);
01427         if (pItem)
01428         {
01429             BOOL CurrState = pItem->GetSelState();
01430             switch (NewState)
01431             {
01432                 case 0: CurrState=FALSE;
01433                 break;
01434                 case 1: CurrState=TRUE;
01435                 break;
01436                 case 2: CurrState=!CurrState;
01437             }
01438             pItem->SetSelState(CurrState);
01439         }   
01440     }
01441 }
01442 
01443 
01444 /********************************************************************************************
01445 
01446 >   DocCoord FillRamp::GetGeometryCoord(FillGeometryAttribute *pGeom, UINT32 index) const
01447 
01448     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01449     Created:    10/3/97
01450     Inputs:     geom  = the geometry, we currently support linear and circular
01451                 index = the index of an item in our list.
01452     Returns:    The absolute doc coord on the geometry pGeom of Blob[index]
01453     Purpose:    Find the absolute coordinate of Blob[index]. The start coordinate
01454                 will be returned if index is out of range
01455 
01456 ********************************************************************************************/
01457 
01458 DocCoord FillRamp::GetGeometryCoord(FillGeometryAttribute *pGeom, UINT32 index) const
01459 {
01460     if (pGeom==NULL)
01461     {
01462         ERROR3("NULL geometry passed to FillRamp::GetGeometryCoord");
01463         return DocCoord(0,0);   
01464     }
01465 
01466     RampItem* pItem = GetValidIndexedItem(index);
01467     if (pItem==NULL)
01468         return DocCoord(0,0);
01469 
01470     return pGeom->GetGeometryCoord(pItem->GetPosition());
01471 }
01472 
01473 
01474 /********************************************************************************************
01475 
01476 >   void FillRamp::RenderRampBlobs(FillGeometryAttribute *pGeom, RenderRegion *pRender, BOOL *pSelState=NULL) const
01477 
01478     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01479     Created:    10/3/97
01480     Inputs:     geom      = the geometry, we currently support linear and circular
01481                 pRender   = the render region to plot the blobs into
01482                 pSelState = a selection state array which describes an alternate selection
01483                             state (other than that in this ramp) to use to render the blobs
01484     Returns:    -
01485     Purpose:    Render the fill blobs in their positions as they appear on the geometry this
01486                 fill ramp is associated with. We simply ask the geometry where they are and
01487                 render appropriately.
01488 
01489 ********************************************************************************************/
01490 
01491 void FillRamp::RenderRampBlobs(FillGeometryAttribute *pGeom, RenderRegion *pRender, BOOL* pSelState) const
01492 {
01493     BOOL Selected;
01494     DocCoord coord;
01495     RampItem* pItem = (RampItem*)GetHead();
01496     INT32 i=0;
01497     while (pItem!=NULL)
01498     {
01499         if (pSelState!=NULL)
01500             Selected=pSelState[i];
01501         else
01502             Selected=pItem->GetSelState();
01503         
01504         coord = pGeom->GetGeometryCoord(pItem->GetPosition());
01505 
01506         // Draw a blob at the end point
01507         if (Selected)
01508         {
01509             // Draw Selected Blob
01510             pRender->SetLineColour (COLOUR_SELECTEDBLOB);
01511             pRender->SetFillColour (COLOUR_SELECTEDBLOB);
01512             pRender->DrawBlob (coord, BT_MSTAGEFILLSELECTED);
01513         }
01514         else
01515         {
01516             // Draw Unselected Blob
01517             pRender->SetLineColour (COLOUR_NONE);
01518             pRender->SetFillColour (COLOUR_BLUE);
01519             pRender->DrawBlob (coord, BT_MSTAGEFILLUNSELECTED);
01520         }
01521     
01522         i++;
01523         pItem = (RampItem*)GetNext(pItem);
01524     }
01525 }
01526 
01527 void FillRamp::RenderSelectedBlob (FillGeometryAttribute *pGeom, RenderRegion *pRender)
01528 {
01529     DocCoord coord;
01530     
01531     RampItem* pItem = (RampItem*) GetHead();
01532 
01533     while (pItem)
01534     {
01535         if (pItem->IsSelected ())
01536         {
01537             coord = pGeom->GetGeometryCoord(pItem->GetPosition());
01538 
01539             pRender->SetLineColour (COLOUR_SELECTEDBLOB);
01540             pRender->SetFillColour (COLOUR_SELECTEDBLOB);
01541             pRender->DrawBlob (coord, BT_MSTAGEFILLSELECTED);
01542             
01543             return;
01544         }
01545         pItem = (RampItem*)GetNext(pItem);
01546     }
01547 }
01548 
01549 
01550 
01551 
01552 /********************************************************************************************
01553 
01554 >   UINT32 FillRamp::SetPosition(UINT32 index, float pos)
01555 
01556     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01557     Created:    10/3/97
01558     Inputs:     index = the index of the item whose position we're setting
01559                 pos   = the new parametric position
01560     Returns:    a new index.
01561     Purpose:    Sets the position of an existing ramp item identified by index. As we keep
01562                 our list of items ordered on position, the fact that it is being changed
01563                 will likely result in a shuffling of the item in the list. Hence we return
01564                 a new index (which obviously may or may not be the same as index). Those
01565                 who are keeping up amoung you might even be able to spot when an item
01566                 shuffles by looking at the input and ouput index values.
01567 
01568 ********************************************************************************************/
01569 
01570 UINT32 FillRamp::SetPosition(UINT32 index, float pos)
01571 {
01572     RampItem *pItem = GetValidIndexedItem(index);
01573     if (pItem==NULL)
01574         return FILLRAMP_ILLEGALINDEX;
01575 
01576     pItem->SetPosition(pos);
01577     //SortRamp (TRUE);
01578     index = ShuffleItem(pItem,index);
01579     return index;
01580 }
01581 
01582 
01583 /********************************************************************************************
01584 
01585 >   UINT32 FillRamp::ShuffleItem(RampItem *pItem, UINT32 index)
01586 
01587     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01588     Created:    10/3/97
01589     Inputs:     pItem = a pointer to a ramp item
01590                 index = the ramp items list index
01591     Returns:    a new index. (The same if no shuffle occured, otherwise err, not the same)
01592     Purpose:    ShuffleItem checks the validity of pItem. If the item's position in the list
01593                 is invalid, it will be shuffled into a valid position. This needs to be done
01594                 when the position parameter is changed, as we keep an ascending order of
01595                 item positions.
01596 
01597 ********************************************************************************************/
01598 
01599 UINT32 FillRamp::ShuffleItem(RampItem *pItem, UINT32 index)
01600 {
01601     float curpos = pItem->GetPosition();
01602     RampItem *pPrevContext = (RampItem*)GetPrev(pItem);
01603     RampItem *pNextContext = (RampItem*)GetNext(pItem);
01604     RampItem *pContext = NULL;
01605 
01606     if (pPrevContext == pNextContext)       // I don't know why this occurs, BUT it does sometimes!
01607     {
01608         pContext = pPrevContext;
01609     }
01610     else
01611     {
01612         if ((pPrevContext != NULL) && (pNextContext == NULL))
01613         {
01614             pContext = pPrevContext;
01615         }
01616         else if ((pNextContext != NULL) && (pPrevContext == NULL))
01617         {
01618             pContext = NULL;
01619         }
01620         else
01621         {
01622             float prevCurpos = pPrevContext->GetPosition ();
01623             float nextCurpos = pNextContext->GetPosition ();
01624 
01625             float diffPrev = curpos - prevCurpos;
01626             if (diffPrev < 0) diffPrev = -diffPrev;
01627             float diffNext = curpos - nextCurpos;
01628             if (diffNext < 0) diffNext = -diffNext;
01629 
01630             if (diffPrev < diffNext)
01631             {
01632                 pContext = pPrevContext;
01633             }
01634             else
01635             {
01636                 pContext = NULL;
01637             }
01638         }
01639     }
01640 
01641     if (pContext)
01642     {
01643         if (!(pContext->IsSelected ()))
01644         {
01645             float contextPos = pContext->GetPosition();
01646             BOOL shuffle = (curpos < contextPos);
01647 
01648             // do we need to shuffle this item to keep order?
01649             if (shuffle)
01650             {
01651                 RampItem *pRemoved = (RampItem*)RemoveItem(pItem);
01652                 pRemoved->ClearPointers ();
01653                 return InsertNewItem(pRemoved);
01654 
01655             }
01656         }
01657     }
01658     else
01659     {
01660         pContext = (RampItem*)GetNext(pItem);
01661         
01662         if (pContext)
01663         {
01664             if (!(pContext->IsSelected ()))
01665             {
01666                 float contextPos = pContext->GetPosition();
01667                 BOOL shuffle = (curpos > contextPos);
01668 
01669                 // do we need to shuffle this item to keep order?
01670                 if (shuffle)
01671                 {
01672                     RampItem *pRemoved = (RampItem*)RemoveItem(pItem);
01673                     pRemoved->ClearPointers ();
01674                     return InsertNewItem(pRemoved);
01675                 }
01676             }
01677         }
01678     }
01679 
01680     return index;
01681 }
01682 
01683 
01684 
01685 /***********************************************************************************************
01686 
01687 >   class ColourRamp
01688 
01689     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01690     Created:    2/2/97
01691     Purpose:    This class holds a list of colour records, each of which describe a colour
01692                 position in a colour ramp. The list contains the usual add/delete entry members
01693                 and other suitable interfaces to allow colour ramps to be edited.
01694                 The list is used inside GradFillAttribute to describe multicoloured fills.
01695 
01696 ***********************************************************************************************/
01697 
01698 ColourRamp::~ColourRamp()
01699 {
01700     DeleteAll();
01701 }
01702 
01703 
01704 /***********************************************************************************************
01705 
01706 >   void ColourRamp::DeleteAll()
01707 
01708     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01709     Created:    2/2/97
01710     Inputs:     -
01711     Purpose:    Deletes all members of the colour ramp list. This is an internal private
01712                 function which is used by other operations in this class
01713 
01714 ***********************************************************************************************/
01715 
01716 void ColourRamp::DeleteAll()
01717 {
01718     ColRampItem* pItem;
01719     while ((pItem=((ColRampItem*)RemoveTail()))!=NULL)
01720         delete pItem;
01721 }
01722 
01723 
01724 /***********************************************************************************************
01725 
01726 >   ColRampItem* ColourRamp::AddEntry(float pos, DocColour *pCol)
01727 
01728     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01729     Created:    2/2/97
01730     Inputs:     pos  = the position this doc colour occupies in the colour ramp 0..1
01731                 pCol = the doc colour to add
01732     Outputs:    -
01733     Returns:    ColRampItem* , a pointer to the list entry created or NULL if out of memory
01734     Purpose:    Add a new colour ramp entry. Its selected state is FALSE
01735 
01736 ***********************************************************************************************/
01737 
01738 ColRampItem* ColourRamp::AddEntry(float pos, DocColour *pCol)
01739 {
01740     ERROR2IF(((pos<0.0)||(pos>1.0)), NULL, "position out of range!");
01741     ERROR2IF(pCol==NULL, NULL, "no colour passed to ColourRamp::AddEntry()");
01742 
01743     // create ourselves a new colour ramp item
01744     ColRampItem *pNewItem = new ColRampItem(pos,pCol);
01745     if (pNewItem)
01746         // insert it in the list
01747         InsertNewItem(pNewItem);
01748 
01749     // return the item pointer
01750     return pNewItem;
01751 }
01752 
01753 /***********************************************************************************************
01754 
01755 >   void ColourRamp::Dump()
01756 
01757     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
01758     Created:    22/10/99
01759     Inputs:     
01760     Outputs:    -
01761     Returns:    
01762     Purpose:    Dumps the data held in the fill ramp to the debug output
01763 
01764 ***********************************************************************************************/
01765 #ifdef _DEBUG
01766 void ColourRamp::Dump()
01767 {
01768     ColRampItem *pItem = (ColRampItem *)GetHead();
01769 
01770     TRACE( _T("Colour ramp Dump\n"));
01771 
01772     while (pItem)
01773     {
01774         DocColour dc = pItem->GetColour();
01775 
01776         INT32 R = 0;
01777         INT32 G = 0;
01778         INT32 B = 0;
01779 
01780         dc.GetRGBValue(&R, &G, &B);
01781                 
01782         TRACE( _T("Pos %f : Colour %d %d %d\n"), pItem->GetPosition(),
01783             R, G, B);
01784 
01785         pItem = (ColRampItem *)GetNext(pItem);
01786     }
01787 }
01788 #endif
01789 
01790 /***********************************************************************************************
01791 
01792 >   INT32 ColourRamp::operator==(const ColourRamp& other) const
01793 
01794     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01795     Created:    2/2/97
01796     Inputs:     other = a colour ramp reference
01797     Outputs:    -
01798     Returns:    TRUE if other is equivalent to this
01799     Purpose:    Try to match this colour ramp with another colour ramp. We simply check the
01800                 numbers in the list, and if the same call the colour ramp entry eqivalence
01801                 operator agains each list entry.
01802 
01803 ***********************************************************************************************/
01804 
01805 INT32 ColourRamp::operator==(const ColourRamp& other) const
01806 {
01807     if (GetCount() != other.GetCount())
01808         return FALSE;
01809 
01810     ColRampItem *pThisItem = GetFirstCol();
01811     ColRampItem *pThatItem = other.GetFirstCol();
01812 
01813     BOOL ok=TRUE;
01814     while (pThisItem && ok)
01815     {
01816         ok = ((*pThisItem)==(*pThatItem));
01817         pThisItem = GetNextCol(pThisItem);
01818         pThatItem = other.GetNextCol(pThatItem);
01819     }
01820 
01821     return ok;
01822 }
01823 
01824 
01825 /***********************************************************************************************
01826 
01827 >   BOOL ColourRamp::IsDifferentTo(ColourRamp *pRamp)
01828 
01829     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01830     Created:    2/2/97
01831     Inputs:     pRamp = the ramp to check against
01832     Outputs:    -
01833     Returns:    TRUE if other is different to this
01834     Purpose:    Another matching function. See if this colour ramp is different to that pointed
01835                 to by pRamp
01836     See Also:   ColourRamp::operator==
01837 
01838 ***********************************************************************************************/
01839 
01840 BOOL ColourRamp::IsDifferentTo(ColourRamp *pRamp)
01841 {
01842     ERROR3IF(this==NULL, "NULL 'this' object in ColourRamp::IsDifferentTo()");
01843     if (pRamp==NULL)
01844         return TRUE;
01845     return (!((*this)==(*pRamp)));
01846 }
01847 
01848 
01849 /***********************************************************************************************
01850 
01851 >   ColourRamp& ColourRamp::operator=(const ColourRamp& other)
01852 
01853     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01854     Created:    2/2/97
01855     Inputs:     other = a colour ramp reference
01856     Outputs:    -
01857     Returns:    A reference to this colour ramp
01858     Purpose:    Assign this colour ramp the same values as those refered to in other.
01859 
01860 ***********************************************************************************************/
01861 
01862 ColourRamp& ColourRamp::operator=(const ColourRamp& other)
01863 {
01864     // the main problem we need to deal with here is 'what happens
01865     // when we fail to copy the entire list? Well, it makes no sense
01866     // to keep the old list as we've not then assigned anything
01867     // i.e. C=A=B not assigning A and C anything is a bit weird.
01868     // so we go ahead and toast whatever was in list A and copy B to
01869     // it (as much as we can at least). If afterwards A!=B then we
01870     // know we're out of memory
01871 
01872     // toast all colours in our list
01873     DeleteAll();
01874     BOOL ok = TRUE;
01875 
01876     ColRampItem *pThisItem, *pOtherItem = other.GetFirstCol();
01877     while (pOtherItem && ok)
01878     {
01879         pThisItem = new ColRampItem(*pOtherItem);
01880         ok = (pThisItem != NULL);
01881         if (ok)
01882         {
01883             // Add the new colour to our list
01884             AddTail(pThisItem);
01885             pOtherItem = other.GetNextCol(pOtherItem);
01886         }
01887     }
01888 
01889     // run a debug check.
01890     ERROR3IF(!ok, "ColourRamp::operator= failed to copy the complete ColourRamp");
01891 
01892     return (*this);
01893 }
01894 
01895 
01896 /***********************************************************************************************
01897 
01898 >   BOOL ColourRamp::SetItemColour(UINT32 index, DocColour *pCol)
01899 
01900     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01901     Created:    9/3/97
01902     Inputs:     index = the index of the ramp entry
01903                 pCol = the doc colour to set
01904     Returns:    TRUE if the colour has been set
01905     Purpose:    Set the colour of an existing colour ramp entry to a new value.
01906 
01907 ***********************************************************************************************/
01908 
01909 BOOL ColourRamp::SetItemColour(UINT32 index, DocColour *pCol)
01910 {
01911     RampItem *pItem = GetValidIndexedItem(index);
01912     if (pItem!=NULL)
01913         ((ColRampItem*)pItem)->SetColour(pCol);
01914     return (pItem!=NULL);
01915 }
01916 
01917 /***********************************************************************************************
01918 
01919 >   INT32 ColourRamp::SetSelectedColours(DocColour *pCol)
01920 
01921     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
01922     Created:    9/3/97
01923     Inputs:     col = the doc colour to set
01924     Returns:    the number of colours set.
01925     Purpose:    Set all selected items in the colour ramp to the colour specified
01926 
01927 ***********************************************************************************************/
01928 
01929 INT32 ColourRamp::SetSelectedColours(DocColour *pCol)
01930 {
01931     INT32 c=0;
01932     ColRampItem *pItem = GetFirstCol();
01933     while (pItem!=NULL)
01934     {
01935         if (pItem->IsSelected())
01936         {
01937             pItem->SetColour(pCol);
01938             c++;
01939         }
01940         pItem = GetNextCol(pItem);
01941     }
01942     return c;
01943 }
01944 
01945 
01946 
01947 /********************************************************************************************
01948 
01949 >   BOOL ColourRamp::CopyComponentData(BaseDocument* SrcDoc, BaseDocument* NodesDoc)
01950 
01951     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01952     Created:    1/9/2000
01953     Inputs:     SrcDoc:   The document from where this node was copied
01954                 NodesDoc: The document where this node lives 
01955     Outputs:    -
01956     Returns:    FALSE if unable to copy data
01957     Purpose:    If the attribute contains any DocColours which are indexed then a copy
01958                 of the indexed colour is made and added to the NodesDoc
01959                 ColourListComponent.
01960     Errors:     -
01961     SeeAlso:    AttrFillGeometry::CopyComponentData
01962 
01963     NOTE:       This is the companion function to the one in AttrFillGeometry.
01964 
01965 ********************************************************************************************/
01966 
01967 BOOL ColourRamp::CopyComponentData(BaseDocument* SrcDoc, BaseDocument* NodesDoc)
01968 {
01969     // Get the colour list component
01970     ColourListComponent *pComponent = 
01971         (ColourListComponent *) NodesDoc->GetDocComponent(CC_RUNTIME_CLASS(ColourListComponent));
01972 
01973     ENSURE (pComponent != NULL, "Could not find ColourListComponent");
01974     
01975     ColRampItem *pItem = GetFirstCol();
01976     
01977     // Copy across all DocColours
01978 
01979     while (pItem!=NULL)
01980     {
01981         DocColour* pDocCol = pItem->GetColourAddr ();
01982 
01983         if (pDocCol) if (pComponent->CopyColourAcross(pDocCol) == CCCOPY_FAILED) { return (FALSE); }
01984         
01985         pItem = GetNextCol(pItem);
01986     }
01987     
01988     return (TRUE);
01989 }
01990 
01991 
01992 /********************************************************************************************
01993 
01994   > virtual BOOL ColourRamp::WriteColourDefinitions (BaseCamelotFilter* pFilter)
01995 
01996     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01997     Created:    14/9/2000
01998     Inputs:     pFilter = ptr to the filter
01999     Returns:    TRUE if record is written, FALSE if not
02000     Purpose:    Writes out colour definitions for this fill.
02001     SeeAlso:    BaseCamelotFilter::WriteRemainingAtomicTagDefinitions ()
02002                 Layer::WriteAtomicNodesColourRefs ()
02003 
02004 ********************************************************************************************/
02005 
02006 BOOL ColourRamp::WriteColourDefinitions (BaseCamelotFilter* pFilter)
02007 {
02008     BOOL ok = TRUE;
02009 
02010     ColRampItem *pItem = GetFirstCol();
02011 
02012     while (pItem!=NULL)
02013     {
02014         DocColour* pDocCol = pItem->GetColourAddr ();
02015         INT32 ColRef = pFilter->WriteRecord(pDocCol);
02016 
02017         ok = (ColRef != 0);
02018 
02019         if (ok)
02020         {
02021             pItem = GetNextCol(pItem);
02022         }
02023         else
02024         {
02025             pItem = NULL;
02026         }
02027     }
02028 
02029     return (ok);
02030 }
02031 
02032 /***********************************************************************************************
02033 
02034 >   DocColour* ColourRamp::GetFirstSelectedColour()
02035 
02036     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02037     Created:    10/3/97
02038     Inputs:     col = the doc colour to set
02039     Returns:    the number of colours set.
02040     Purpose:    Set all selected items in the colour ramp to the colour specified
02041 
02042 ***********************************************************************************************/
02043 
02044 DocColour* ColourRamp::GetFirstSelectedColour()
02045 {
02046     ColRampItem *pItem = GetFirstCol();
02047     while (pItem!=NULL)
02048     {
02049         if (pItem->IsSelected())
02050             return pItem->GetColourAddr();
02051         pItem = GetNextCol(pItem);
02052     }
02053     return NULL;
02054 }
02055 
02056 /***********************************************************************************************
02057 
02058 >   DocColour* ColourRamp::EnumerateColourFields(UINT32 real_index)
02059 
02060     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02061     Created:    10/3/97
02062     Inputs:     real_index = an unbiased index [0..n-1]
02063     Returns:    A pointer to the colour record held in this indexed item or NULL
02064     Purpose:    Enumerates all colour fields in the colour ramp. This linear searching is not
02065                 so quick. We might need to keep a static context pointer here.
02066 
02067 ***********************************************************************************************/
02068 
02069 DocColour* ColourRamp::EnumerateColourFields(UINT32 real_index)
02070 {
02071     RampItem *pItem = GetIndexedItem(real_index);
02072     if (pItem)
02073         return ((ColRampItem*)pItem)->GetColourAddr();
02074     return NULL;
02075 }
02076 
02077 
02078 /***********************************************************************************************
02079 
02080 >   TransparencyRamp::~TransparencyRamp()
02081 
02082     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02083     Created:    2/2/97
02084     Inputs:     -
02085     Purpose:    Deletes all members of the list. This is an internal private
02086                 function which is used by other operations in this class
02087 
02088 ***********************************************************************************************/
02089 
02090 TransparencyRamp::~TransparencyRamp()
02091 {
02092     DeleteAll();
02093 }
02094 
02095 
02096 /***********************************************************************************************
02097 
02098 >   void TransparencyRamp::DeleteAll()
02099 
02100     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02101     Created:    2/2/97
02102     Inputs:     -
02103     Purpose:    Deletes all members of the list. This is an internal private
02104                 function which is used by other operations in this class
02105 
02106 ***********************************************************************************************/
02107 
02108 void TransparencyRamp::DeleteAll()
02109 {
02110     TranspRampItem* pItem;
02111     while ((pItem=((TranspRampItem*)RemoveTail()))!=NULL)
02112         delete pItem;
02113 }
02114 
02115 
02116 /***********************************************************************************************
02117 
02118 >   TranspRampItem* TransparencyRamp::AddEntry(float pos, UINT32 transp)
02119 
02120     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02121     Created:    2/2/97
02122     Inputs:     pos = the position this doc colour occupies in the colour ramp 0..1
02123                 transp = the transparency to add
02124     Outputs:    -
02125     Returns:    TranspRampItem* , a pointer to the list entry created or NULL if out of memory
02126     Purpose:    Add a new transparency ramp entry. Its selected state is FALSE
02127 
02128 ***********************************************************************************************/
02129 
02130 TranspRampItem* TransparencyRamp::AddEntry(float pos, UINT32 transp)
02131 {
02132     ERROR2IF(((pos<0.0)||(pos>1.0)), FALSE, "position out of range!");
02133 
02134     // create ourselves a new colour ramp item
02135     TranspRampItem *pNewItem = new TranspRampItem(pos,transp);
02136 
02137     if (pNewItem)
02138         // insert it into the list
02139         InsertNewItem(pNewItem);
02140 
02141     // return the item pointer
02142     return pNewItem;
02143 }
02144 
02145 
02146 
02147 /***********************************************************************************************
02148 
02149 >   INT32 TransparencyRamp::operator==(const TransparencyRamp& other) const
02150 
02151     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02152     Created:    2/2/97
02153     Inputs:     other = a transparency ramp reference
02154     Outputs:    -
02155     Returns:    TRUE if other is equivalent to this
02156     Purpose:    Try to match this ramp with another ramp. We simply check the
02157                 numbers in the list, and if the same call the transparency ramp entry eqivalence
02158                 operator against each list entry.
02159 
02160 ***********************************************************************************************/
02161 
02162 INT32 TransparencyRamp::operator==(const TransparencyRamp& other) const
02163 {
02164     if (GetCount() != other.GetCount())
02165         return FALSE;
02166 
02167     TranspRampItem *pThisItem = GetFirstTransp();
02168     TranspRampItem *pThatItem = other.GetFirstTransp();
02169 
02170     BOOL ok=TRUE;
02171     while (pThisItem && ok)
02172     {
02173         ok = ((*pThisItem)==(*pThatItem));
02174         pThisItem = GetNextTransp(pThisItem);
02175         pThatItem = other.GetNextTransp(pThatItem);
02176     }
02177 
02178     return TRUE;
02179 }
02180 
02181 /***********************************************************************************************
02182 
02183 >   BOOL TransparencyRamp::IsDifferentTo(TransparencyRamp *pRamp)
02184 
02185     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02186     Created:    2/2/97
02187     Inputs:     pRamp = the ramp to check against
02188     Outputs:    -
02189     Returns:    TRUE if pRamp is different to this
02190     Purpose:    Another matching function. See if this transparency ramp is different to that pointed
02191                 to by pRamp
02192     See Also:   TransparencyRamp::operator==
02193 
02194 ***********************************************************************************************/
02195 
02196 BOOL TransparencyRamp::IsDifferentTo(TransparencyRamp *pRamp)
02197 {
02198     ERROR3IF(this==NULL, "NULL 'this' object in TransparencyRamp::IsDifferentTo()");
02199     if (pRamp==NULL)
02200         return TRUE;
02201     return (!((*this)==(*pRamp)));
02202 }
02203 
02204 
02205 /***********************************************************************************************
02206 
02207 >   TransparencyRamp& TransparencyRamp::operator=(const TransparencyRamp& other)
02208 
02209     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02210     Created:    2/2/97
02211     Inputs:     other = a colour ramp reference
02212     Outputs:    -
02213     Returns:    A reference to this colour ramp
02214     Purpose:    Assign this transparency ramp the same values as those refered to in other.
02215 
02216 ***********************************************************************************************/
02217 
02218 TransparencyRamp& TransparencyRamp::operator=(const TransparencyRamp& other)
02219 {
02220     // toast all entries in our list
02221     DeleteAll();
02222     BOOL ok = TRUE;
02223 
02224     TranspRampItem *pThisItem, *pOtherItem = other.GetFirstTransp();
02225     while (pOtherItem && ok)
02226     {
02227         pThisItem = new TranspRampItem(*pOtherItem);
02228         ok = (pThisItem != NULL);
02229         if (ok)
02230         {
02231             // Add the new colour to our list
02232             AddTail(pThisItem);
02233             pOtherItem = other.GetNextTransp(pOtherItem);
02234         }
02235     }
02236 
02237     // run a debug check.
02238     ERROR3IF(!ok, "TransparencyRamp::operator= failed to copy the complete TransparencyRamp");
02239 
02240     return (*this);
02241 }
02242 
02243 
02244 
02245 /***********************************************************************************************
02246 
02247 >   INT32 TransparencyRamp::SetSelectedTransp(UINT32 transp)
02248 
02249     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02250     Created:    9/3/97
02251     Inputs:     transp = the level of transparency
02252     Returns:    the number of transparencies set
02253     Purpose:    Sets all selected items in this ramp to the given transparency.
02254 
02255 ***********************************************************************************************/
02256 
02257 INT32 TransparencyRamp::SetSelectedTransp(UINT32 transp)
02258 {
02259     INT32 c=0;
02260     TranspRampItem *pItem = GetFirstTransp();
02261     while (pItem!=NULL)
02262     {
02263         if (pItem->IsSelected())
02264         {
02265             pItem->SetTransparency(transp);
02266             c++;
02267         }
02268         pItem = GetNextTransp(pItem);
02269     }
02270     return c;
02271 }
02272 
02273 /***********************************************************************************************
02274 
02275 >   BOOL TransparencyRamp::SetItemTransp(UINT32 index, UINT32 t)
02276 
02277     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02278     Created:    9/3/97
02279     Inputs:     index = the index of the ramp entry
02280                 t     = the transparency to set
02281     Returns:    TRUE if the transparency has been set
02282     Purpose:    Set the transparency of an existing ramp entry to a new value.
02283 
02284 ***********************************************************************************************/
02285 
02286 BOOL TransparencyRamp::SetItemTransp(UINT32 index, UINT32 t)
02287 {
02288     RampItem *pItem = GetValidIndexedItem(index);
02289     if (pItem!=NULL)
02290         ((TranspRampItem*)pItem)->SetTransparency(t);
02291     return (pItem!=NULL);
02292 }
02293 
02294 /***********************************************************************************************
02295 
02296 >   UINT32* TransparencyRamp::GetFirstSelectedTransp()
02297 
02298     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
02299     Created:    10/3/97
02300     Inputs:     -
02301     Returns:    A pointer to the first selected transparency
02302     Purpose:    Get a pointer to the first selected item's transparency field. NULL will
02303                 be returned if there are no selected items
02304 
02305 ***********************************************************************************************/
02306 
02307 UINT32* TransparencyRamp::GetFirstSelectedTransp()
02308 {
02309     TranspRampItem *pItem = GetFirstTransp();
02310     while (pItem!=NULL)
02311     {
02312         if (pItem->IsSelected())
02313             return pItem->GetTranspAddr();
02314         pItem = GetNextTransp(pItem);
02315     }
02316     return NULL;
02317 }

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