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 }