blndhelp.cpp

Go to the documentation of this file.
00001 // $Id: blndhelp.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 // ppbevel - Definition of bevel BevelPathProcessor class
00099 
00100 #include "camtypes.h"
00101 //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00102 //#include "paths.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00103 #include "lineattr.h"
00104 #include "blendatt.h"
00105 #include "blndhelp.h"
00106 #include "attrmap.h"
00107 #include "nodebldr.h"
00108 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 //#include "mario.h"
00110 #include "ndbldpth.h"
00111 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 #include "gblend.h"
00113 //#include "nodecomp.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 #include "fthrattr.h"
00115 
00116 CC_IMPLEMENT_DYNAMIC(BlendHelpers, CCObject);
00117 CC_IMPLEMENT_DYNAMIC(SumAllPathsPathProcessor, PathProcessor);
00118 CC_IMPLEMENT_DYNCREATE(SumAllPathsElem, ListItem);
00119 
00120 BlendHelpers::BlendHelpers()
00121 {
00122     m_TempArraySize = 0;
00123     m_pTempCoords = NULL;
00124     m_pTempVerbs = NULL;
00125     m_pTempFlags = NULL;
00126     m_GBlendBuffSize = 0;
00127     m_pGBlendBuff = NULL;
00128     m_ArrayLength = 0;
00129 }
00130 
00131 BlendHelpers::~BlendHelpers()
00132 {
00133     DeallocTempBuffers();
00134 }
00135 
00136 /********************************************************************************************
00137 
00138 >   BOOL BlendHelpers::BlendAttributes(BlendNodeParam * pParam, CCAttrMap* pBlendedAttrMap)
00139 
00140     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com> based on blender code
00141     Created:    21/2/2000
00142     Inputs:     pParam  -   the blend node param
00143     Outputs:    -
00144     Returns:    TRUE if successful, FALSE otherwise
00145     Purpose:    Blends the attributes of the two BlendPath objects by the amount specified in BlendRatio
00146     SeeAlso:    -
00147 
00148 ********************************************************************************************/
00149 BOOL BlendHelpers::BlendAttributes(BlendNodeParam * pParam, CCAttrMap* pBlendedAttrMap)
00150 {
00151     // Check entry params
00152     double BlendRatio = pParam->GetAttrBlendRatio();
00153 
00154     BOOL ok = (pParam != NULL && pBlendedAttrMap != NULL);
00155     ERROR3IF(!ok,"One or more NULL entry params");
00156     if (!ok) return FALSE;
00157 
00158     // Find the attributes that are applied to the blend paths
00159 
00160     BlendPath * pBlendPathStart = pParam->GetStartBlendPath();
00161     BlendPath * pBlendPathEnd   = pParam->GetEndBlendPath();
00162     ok = (pBlendPathStart != NULL && pBlendPathEnd != NULL);
00163     ERROR3IF(!ok, "Blend paths are NULL");
00164     if (!ok) return FALSE;
00165 
00166     ok = (pBlendPathStart->GetCreatedByNode() != NULL && 
00167         pBlendPathEnd->GetCreatedByNode() != NULL);
00168     ERROR3IF(!ok, "Blend path created by nodes are NULL");
00169     if (!ok) return FALSE;
00170 
00171     BOOL startExludeGLAs = TRUE, endExcludeGLAs = TRUE;
00172 
00173     NodeAttribute           * pAttr             = NULL;
00174     if(pBlendPathStart->GetCreatedByNode()->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFeather),&pAttr))
00175     {
00176         startExludeGLAs = FALSE;
00177     }
00178     if(pBlendPathEnd->GetCreatedByNode()->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFeather),&pAttr))
00179     {
00180         endExcludeGLAs = FALSE;
00181     }
00182 
00183     CCAttrMap* pAttrMapStart = CCAttrMap::MakeAppliedAttrMap(pBlendPathStart->GetCreatedByNode(), startExludeGLAs);
00184     CCAttrMap* pAttrMapEnd   = CCAttrMap::MakeAppliedAttrMap(pBlendPathEnd->GetCreatedByNode(), endExcludeGLAs);
00185 
00186     if (!pAttrMapStart || !pAttrMapEnd)
00187         return FALSE;
00188 
00189     // find the attributes on the nodes
00190     
00191     if (pParam->GetNodeBlendPath() != NULL)
00192     {
00193         Trans2DMatrix* pRotateStart = GetRotateMatrix(pParam->GetNodeStart(),
00194             360.0 - pParam->GetAngleStart());
00195         Trans2DMatrix* pRotateEnd   = GetRotateMatrix(pParam->GetNodeEnd(),
00196             360.0 - pParam->GetAngleEnd());
00197         if (pRotateStart)   pAttrMapStart->Transform(*pRotateStart);
00198         if (pRotateEnd)     pAttrMapEnd  ->Transform(*pRotateEnd);
00199 
00200         if (pRotateStart)
00201             delete pRotateStart;
00202 
00203         if (pRotateEnd)
00204             delete pRotateEnd;
00205     }
00206 
00207     // These vars are used as params to the CCAttrMap funcs
00208     CCRuntimeClass     *pTypeStart; 
00209     void               *pValStart;
00210     void               *pValEnd;
00211     double              OldBlendRatio = pParam->GetBlendRatio();
00212     // Process each attribute in turn
00213     CCAttrMap::iterator PosStart = pAttrMapStart->GetStartPosition();
00214     CCAttrMap::iterator EndStart = pAttrMapStart->GetEndPosition();
00215     for (;PosStart != EndStart;)
00216     {
00217         // Get a ptr to the attr at position PosStart in the start node's attr map
00218         pAttrMapStart->GetNextAssoc(PosStart,pTypeStart,pValStart);
00219         NodeAttribute* pNodeAttrStart = (NodeAttribute *)pValStart;
00220     
00221         BlendRatio = OldBlendRatio; 
00222         // Diccon 10/99 When using non-linear profiles for the objects those attributes
00223         // that make use of control points were not being profiled, making the objects look strange.
00224         // to avoid this those attributes now share the same profiles as the objects.
00225         if (pNodeAttrStart->IsAGradFill())
00226         {
00227         
00228             if (!((AttrFillGeometry*)pNodeAttrStart)->IsAColourFill())
00229             {
00230                 
00231                 BlendRatio = pParam->GetObjectRatio();
00232             
00233             }
00234             else
00235             {
00236                 BlendRatio = pParam->GetInvertedAttributeRatio();
00237             
00238             }
00239 
00240         }
00241         if (pNodeAttrStart->IsAFlatFill() || (pNodeAttrStart->GetRuntimeClass() == CC_RUNTIME_CLASS(AttrLineWidth)))
00242         {
00243             BlendRatio = pParam->GetInvertedAttributeRatio();
00244         }
00245             
00246         // Get a blended attribute
00247         NodeAttribute* pBlendedNodeAttr = NULL;
00248 
00249         // Find an attr of the same type in the end object's attr list,
00250         // and blend the two attrs together
00251         pValEnd = NULL;
00252 
00253         if (pAttrMapEnd->Lookup(pTypeStart,pValEnd))
00254         {
00255             // We've found a matching end attr, so try to blend it with the start attr
00256 
00257             // Set up the param object to pass to the start attr's blend method
00258             BlendAttrParam BlendParam;
00259 
00260             NodeAttribute * pEndAttr = (NodeAttribute *)pValEnd;
00261 
00262             // Initialise the BlendParam with the end attr and blend ratio
00263             if (BlendParam.Init(pParam->GetRenderRegion(),
00264                                 pEndAttr,BlendRatio,
00265                                 pParam->GetColourBlendType(),
00266                                 pAttrMapStart, pAttrMapEnd))
00267             {
00268                 // Successfully initialised, so now try blending the attributes
00269                 if (pNodeAttrStart->Blend(&BlendParam))
00270                 {
00271                     // Attrs successfully blended, now get a ptr to the new attr.
00272                     // Once we get the blended attr ptr, it belongs to us, so we have
00273                     // to delete it when it is not needed
00274                     pBlendedNodeAttr = BlendParam.GetBlendedAttr();
00275                 }
00276             }
00277         }
00278 
00279         // If we have a blended attr, pBlendedNodeAttr != NULL
00280         if (pBlendedNodeAttr != NULL)
00281         {
00282             // Get the type of the blended attr
00283             CCRuntimeClass *pTypeBlend = pBlendedNodeAttr->GetAttributeType();
00284             void* pValBlend;
00285 
00286             // If we already have an attr in the blended attr map of the same type,
00287             // remove it and delete it, before inserting a new attr of this type
00288             if (pBlendedAttrMap->Lookup(pTypeBlend,pValBlend))
00289             {
00290                 if (pValBlend != NULL)
00291                 {
00292                     pBlendedAttrMap->RemoveKey(pTypeBlend);
00293                     delete (NodeAttribute*)pValBlend;
00294                 }
00295             }
00296             // add it to the blend map
00297             pBlendedAttrMap->SetAt(pTypeBlend,pBlendedNodeAttr);
00298         }
00299     }
00300 
00301     if (pParam->GetNodeBlendPath() != NULL)
00302     {
00303         Trans2DMatrix* pRotateStart = GetRotateMatrix(pParam->GetNodeStart(),
00304             pParam->GetAngleStart());
00305         Trans2DMatrix* pRotateEnd   = GetRotateMatrix(pParam->GetNodeEnd(),
00306             pParam->GetAngleEnd()  );
00307         if (pRotateStart)   pAttrMapStart->Transform(*pRotateStart);
00308         if (pRotateEnd)     pAttrMapEnd  ->Transform(*pRotateEnd);
00309 
00310         if (pRotateStart)
00311             delete pRotateStart;
00312         
00313         if (pRotateEnd)
00314             delete pRotateEnd;
00315     }
00316 
00317     delete pAttrMapStart;
00318     delete pAttrMapEnd;
00319 
00320     return TRUE;    
00321 }
00322 
00323 /********************************************************************************************
00324 
00325 > BOOL BlendHelpers::ReallocTempBuffers(UINT32 Size)
00326 
00327     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00328     Created:    7/11/94
00329     Inputs:     Size = Size the temp arrays should be
00330     Outputs:    -
00331     Returns:    -
00332     Purpose:    Allocates memory for the temp path arrays, and sets the size var to 0
00333                 You can use calls to GetCoordArray(), GetVerbArray() and GetFlagArray() to get the alloced arrays.
00334     SeeAlso:    -
00335 
00336 ********************************************************************************************/
00337 
00338 BOOL BlendHelpers::ReallocTempBuffers(UINT32 Size)
00339 {
00340     DeallocTempBuffers();
00341 
00342     // Allocate the arrays
00343     m_TempArraySize = Size;
00344     m_pTempCoords   = (DocCoord*)  CCMalloc(Size*sizeof(DocCoord));
00345     m_pTempVerbs    = (PathVerb*)  CCMalloc(Size*sizeof(PathVerb));
00346     m_pTempFlags    = (PathFlags*) CCMalloc(Size*sizeof(PathFlags));
00347 
00348     // If any of the arrays are not allocated, dealloc the alloced ones, and return FALSE
00349     if (m_pTempCoords == NULL || m_pTempVerbs == NULL || m_pTempFlags == NULL)
00350     {
00351         DeallocTempBuffers();
00352         return FALSE;
00353     }
00354 
00355     // It's all OK, so return TRUE
00356     return TRUE;
00357 }
00358 
00359 /********************************************************************************************
00360 
00361 >   void BlendHelpers::DeallocTempBuffers()
00362 
00363     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00364     Created:    7/11/94
00365     Inputs:     -
00366     Outputs:    -
00367     Returns:    -
00368     Purpose:    Releases memory allocated for the temp path arrays, and sets the size var to 0
00369     SeeAlso:    -
00370 
00371 ********************************************************************************************/
00372 
00373 void BlendHelpers::DeallocTempBuffers()
00374 {
00375     if (m_pTempCoords != NULL) { CCFree(m_pTempCoords); m_pTempCoords = NULL; }
00376     if (m_pTempVerbs  != NULL) { CCFree(m_pTempVerbs);  m_pTempVerbs  = NULL; }
00377     if (m_pTempFlags  != NULL) { CCFree(m_pTempFlags);  m_pTempFlags  = NULL; }
00378     m_TempArraySize = 0;
00379 
00380     if (m_pGBlendBuff != NULL) { CCFree(m_pGBlendBuff); m_pGBlendBuff = NULL; }
00381     m_GBlendBuffSize = 0;
00382 }
00383 
00384 /********************************************************************************************
00385 
00386 >   DocCoord*  BlendHelpers::GetCoordArray(UINT32 MinSize);
00387 
00388     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00389     Created:    7/11/94
00390     Inputs:     MinSize = min size the array should be
00391     Outputs:    -
00392     Returns:    Ptr to the array, or NULL if can't get memory
00393     Purpose:    Used to get an array you can write to.
00394     SeeAlso:    -
00395 
00396 ********************************************************************************************/
00397 
00398 DocCoord* BlendHelpers::GetCoordArray(UINT32 MinSize)
00399 {
00400     MinSize++;
00401     if (m_TempArraySize >= MinSize) return m_pTempCoords;
00402 
00403     if (ReallocTempBuffers(MinSize))
00404         return m_pTempCoords;
00405     else
00406         return NULL;
00407 }
00408 
00409 /********************************************************************************************
00410 
00411 >   PathVerb*  BlendHelpers::GetVerbArray(UINT32 MinSize);
00412 
00413     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00414     Created:    7/11/94
00415     Inputs:     MinSize = min size the array should be
00416     Outputs:    -
00417     Returns:    Ptr to the array, or NULL if can't get memory
00418     Purpose:    Used to get an array you can write to.
00419     SeeAlso:    -
00420 
00421 ********************************************************************************************/
00422 
00423 PathVerb* BlendHelpers::GetVerbArray(UINT32 MinSize)
00424 {
00425     MinSize++;
00426     if (m_TempArraySize >= MinSize) return m_pTempVerbs;
00427 
00428     if (ReallocTempBuffers(MinSize))
00429         return m_pTempVerbs;
00430     else
00431         return NULL;
00432 }
00433 
00434 /********************************************************************************************
00435 
00436 >   PathFlags*  BlendHelpers::GetFlagArray(UINT32 MinSize);
00437 
00438     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00439     Created:    7/11/94
00440     Inputs:     MinSize = min size the array should be
00441     Outputs:    -
00442     Returns:    Ptr to the array, or NULL if can't get memory
00443     Purpose:    Used to get an array you can write to.
00444     SeeAlso:    -
00445 
00446 ********************************************************************************************/
00447 
00448 PathFlags* BlendHelpers::GetFlagArray(UINT32 MinSize)
00449 {
00450     MinSize++;
00451     if (m_TempArraySize >= MinSize) return m_pTempFlags;
00452 
00453     if (ReallocTempBuffers(MinSize))
00454         return m_pTempFlags;
00455     else
00456         return NULL;
00457 }
00458 
00459 /********************************************************************************************
00460 
00461 >   UINT32*  BlendHelpers::GetGBlendBuff(UINT32 MinSize);
00462 
00463     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00464     Created:    7/11/94
00465     Inputs:     MinSize = min size the buffer should be
00466     Outputs:    -
00467     Returns:    Ptr to the buffer, or NULL if can't get memory
00468     Purpose:    Used to get a buffer you can write to.
00469     SeeAlso:    -
00470 
00471 ********************************************************************************************/
00472 
00473 UINT32* BlendHelpers::GetGBlendBuff(UINT32 MinSize)
00474 {
00475     MinSize++;
00476     if (m_GBlendBuffSize >= MinSize) return m_pGBlendBuff;
00477 
00478     if (m_pGBlendBuff != NULL) CCFree(m_pGBlendBuff);
00479 
00480     m_pGBlendBuff = (UINT32*) CCMalloc(MinSize*sizeof(UINT32));
00481 
00482     if (m_pGBlendBuff != NULL)
00483         m_GBlendBuffSize = MinSize;
00484     else
00485         m_GBlendBuffSize = 0;
00486 
00487     return m_pGBlendBuff;
00488 }
00489 
00490 
00491 /********************************************************************************************
00492 
00493 > Trans2DMatrix* BlendHelpers::GetRotateMatrix(NodeRenderableBounded* pNode,double Angle)
00494 
00495     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> - altered by DMc
00496     Created:    25/5/99
00497     Inputs:     pNode = the node who's bounds define the centre of rotation
00498                 Angle = Angle to rotate by, in degrees
00499     Outputs:    -
00500     Returns:    ptr to the matrix that will perform the rotation
00501                 or NULL if no rotation is necessary (i.e. Angle % 360.0 == 0.0)
00502     Purpose:    Function that returns a matrix that will rotate around the centre of the bounds of
00503                 the given node
00504     SeeAlso:    -
00505 
00506 ********************************************************************************************/
00507 
00508 Trans2DMatrix* BlendHelpers::GetRotateMatrix(NodeRenderableBounded* pNode,double Angle)
00509 {
00510     Trans2DMatrix* pMatrix = NULL;
00511 
00512     if (pNode != NULL && fmod(Angle,360.0) != 0.0)
00513     {
00514         DocRect BoundsStart = pNode->GetBoundingRect();
00515         DocCoord Centre = BoundsStart.Centre();
00516         pMatrix = new Trans2DMatrix(Centre,Angle);
00517     }
00518 
00519     return pMatrix;
00520 }
00521 
00522 
00523 /********************************************************************************************
00524 
00525 >   BOOL BlendHelpers::BlendPaths(BlendNodeParam * pParam, Path * pPath)
00526 
00527     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00528     Created:    21/2/2000
00529     Inputs:     The blend node parameter
00530     Outputs:    The blended path is stored in three arrays: the coords, the verbs, and the flags.
00531                 The arrays are:
00532     
00533                     pTempCoords
00534                     pTempVerbs
00535                     pTempFlags
00536 
00537                     ArrayLength = the length of all three arrays
00538 
00539                 This allows the caller to decide what to do with the blended path in a very flexible way.
00540 
00541     Returns:    TRUE if successful, FALSE otherwise
00542     Purpose:    Blends two BlendPath objects by the amount specified in BlendRatio
00543     SeeAlso:    -
00544 ********************************************************************************************/
00545 BOOL BlendHelpers::BlendPaths(BlendNodeParam * pParam, Path * pPath)
00546 {
00547     // Check entry params
00548     BlendPath * pBlendPathStart = pParam->GetStartBlendPath();
00549     BlendPath * pBlendPathEnd   = pParam->GetEndBlendPath();
00550 
00551     ERROR2IF(!pBlendPathStart->GetBlendNode()->IsNodePath(), FALSE,
00552         "Start blend path's node isn't a node path");
00553 
00554     ERROR2IF(!pBlendPathEnd->GetBlendNode()->IsNodePath(), FALSE,
00555         "End blend path's node isn't a node path");
00556 
00557     BOOL    ok = (pBlendPathStart != NULL && pBlendPathEnd != NULL);
00558     if (ok) ok = (pBlendPathStart->GetBlendNode() != NULL && pBlendPathEnd->GetBlendNode() != NULL);
00559     ERROR3IF(!ok,"One or more NULL entry params");
00560     if (!ok) return FALSE;
00561 
00562     // Get the types of the two paths
00563     PathTypeEnum PathTypeStart = pBlendPathStart->GetPathType();
00564     PathTypeEnum PathTypeEnd   = pBlendPathEnd  ->GetPathType();
00565     
00566     // The blended path will be closed if either of the paths is a shape
00567     BOOL Closed = (PathTypeStart == PATHTYPE_SHAPE) || (PathTypeEnd == PATHTYPE_SHAPE);
00568 
00569     Path * pPathStart = NULL;
00570 
00571     // Find the paths associated with the start and end blend paths
00572     if (pBlendPathStart->GetBlendNode()->IsNodePath())
00573     {
00574         pPathStart = &(((NodePath *)pBlendPathStart->GetBlendNode())->InkPath);
00575     }
00576 
00577     Path * pPathEnd = NULL;
00578 
00579     if (pBlendPathEnd->GetBlendNode()->IsNodePath())
00580     {
00581         pPathEnd   = &(((NodePath *)pBlendPathEnd->GetBlendNode())->InkPath);
00582     }
00583 
00584     // Calculate how large the arrays have to be to store the blended path definition
00585     INT32 DestPathSize = ((pPathStart->GetNumCoords()+pPathEnd->GetNumCoords())*3)+500;
00586 
00587     // Get some arrays used to hold the blended path data, and error if any are NULL
00588     DocCoord*   pDestCoords = GetCoordArray(DestPathSize);
00589     PathVerb*   pDestVerbs  = GetVerbArray(DestPathSize);
00590     PathFlags*  pDestFlags  = GetFlagArray(DestPathSize);
00591     UINT32*         pBuff       = GetGBlendBuff(DestPathSize);
00592     if (pDestCoords == NULL || pDestVerbs == NULL || pDestFlags == NULL || pBuff == NULL)
00593         return FALSE;
00594 
00595     // This section copes with the case when blending a line with a shape.
00596     // In this case we need to get a temp path the is actually a shape version of the line.
00597     // The line is simply reversed back onto itself to form a shape that would look identical to the 
00598     // line if rendered.  This allows the line to appear to open up to the shape when blended.
00599     Path Shape;
00600     if (PathTypeStart != PathTypeEnd)
00601     {
00602         BOOL ok = FALSE;
00603         if (!Shape.Initialise()) return FALSE;
00604 
00605         // if going from a line to a shape, convert the start path to a shape
00606         if (PathTypeStart == PATHTYPE_LINE && PathTypeEnd == PATHTYPE_SHAPE)
00607         {
00608             ok = NodeBlender::ConvertLineToShape(pPathStart,&Shape);
00609             pPathStart = &Shape;
00610         }
00611 
00612         // if going from a shape to a line, convert the end path to a shape
00613         if (PathTypeStart == PATHTYPE_SHAPE && PathTypeEnd == PATHTYPE_LINE)
00614         {
00615             ok = NodeBlender::ConvertLineToShape(pPathEnd,&Shape);
00616             pPathEnd = &Shape;
00617         }
00618 
00619         if (!ok) return FALSE;
00620     }
00621 
00622     // The blend should do a one-to-one mapping when the OneToOne flag is set AND both paths
00623     // have the same number of elements
00624     BOOL OneToOne = FALSE;
00625     if (pParam->GetOneToOne())
00626         OneToOne = (pBlendPathStart->GetNumElements() == pBlendPathEnd->GetNumElements());
00627 
00628     // Now actually blend the two paths
00629 
00630     GBlend GBlendObj;
00631 
00632     // Define the blend
00633     GBlendObj.Define(   (PPOINT)pPathStart->GetCoordArray(),    // Specify the start path
00634                         pPathStart->GetVerbArray(),
00635                         pPathStart->GetNumCoords(),
00636 
00637                         (PPOINT)pPathEnd  ->GetCoordArray(),    // Specify the end path
00638                         pPathEnd  ->GetVerbArray(),
00639                         pPathEnd  ->GetNumCoords(),
00640 
00641                         OneToOne,                               // The one-to-one flag
00642                         1024,                               // Flatness
00643 
00644                         pBuff,                                  // Buffer for GBlend to use
00645                         DestPathSize*sizeof(UINT32));           // The buffer size
00646 
00647     // Blend the paths
00648     m_ArrayLength = GBlendObj.Blend(pParam->GetBlendRatio(),    // The blend ratio, 0.0 < BlendRatio < 1.0
00649                                     (PPOINT)pDestCoords,        // Array to store blended coords
00650                                     pDestVerbs,                 // Array to store blended verbs
00651                                     DestPathSize);              // The num elements in the two arrays
00652 
00653 
00654     // If we're blending a line to another line, we need to make sure that the blended line
00655     // is going in a direction that corresponds to the source lines.  This ensures attributes
00656     // that depend on this direction (e.g. start and end arrows) look correct.
00657     //
00658     // When creating blend paths of lines, we can detect if the blend path has been reversed,
00659     // in relation to the original path, by the original mapping value.
00660     // If it's 0 it has NOT been reversed, otherwise it's been reversed.
00661     //
00662     // If the blend ratio is <=0.5, the blended path is closest to the start blend path,
00663     // so we look at the start blend path's original mapping.
00664     //
00665     // If blend ration > 0.5, look at the end blend path's original mapping.
00666     //
00667     // The (BlendRation <= 0.5) cut-off point is the same as the cut-off point used in the blending
00668     // of attributes.
00669     if (pBlendPathStart->IsLine() && pBlendPathEnd->IsLine())
00670     {
00671         BlendPath* pBlendPath;
00672         if (pParam->GetBlendRatio() <= 0.5) 
00673             pBlendPath = pBlendPathStart;
00674         else
00675             pBlendPath = pBlendPathEnd;
00676 
00677         if (pBlendPath->GetOrigMapping() != 0)
00678             NodeBlender::ReversePath(pDestCoords,pDestVerbs,m_ArrayLength);
00679     }
00680 
00681     // We need to do some work on the blended path
00682     if (!NodeBlender::ProcessBlendedPath(pDestCoords,pDestVerbs,pDestFlags,m_ArrayLength,Closed))
00683         return FALSE;
00684 
00685     Path RetnPath;
00686     RetnPath.Initialise(m_ArrayLength);
00687 
00688     BOOL Filled  = pPathStart->IsFilled  || pPathEnd->IsFilled;
00689     BOOL Stroked = pPathStart->IsStroked || pPathEnd->IsStroked;
00690 
00691     RetnPath.MergeTwoPaths(pDestCoords,pDestVerbs,pDestFlags,m_ArrayLength,Filled);
00692 
00693     pPath->ClearPath();
00694     pPath->CloneFrom(RetnPath);
00695     pPath->IsFilled = Filled;
00696     pPath->IsStroked = Stroked;
00697     
00698     return TRUE;
00699 }
00700 
00702 // The become a for compound nodes in blends
00703 /********************************************************************************************
00704 
00705 >   CompoundNodeBlendBecomeA::CompoundNodeBlendBecomeA(BecomeAReason ThisReason, 
00706             CCRuntimeClass* pClass, 
00707             UndoableOperation* pOp, 
00708             BOOL sel = TRUE, 
00709             BOOL First = FALSE,
00710             NodeCompound * pNode
00711             ) : BecomeA(ThisReason, pClass, pOp, sel, First)
00712 
00713     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00714     Created:    21/2/2000
00715     Inputs:     See base class, plus the compound node we're using
00716     Outputs:    
00717     Returns:    
00718     Purpose:    Constructor
00719     SeeAlso:    -
00720 ********************************************************************************************/
00721 BOOL CompoundNodeBlendBecomeA::PassBack(NodeRenderableInk* pNewNode,
00722         NodeRenderableInk* pCreatedByNode,
00723         CCAttrMap* pAttrMap)
00724 
00725 {
00726     ERROR2IF(pCreatedByNode == NULL, FALSE, "CompoundNodeBlendBecomeA - no created by node");
00727 
00728     NodeRenderableInk * pNewCompound = NULL;
00729 
00730     if (pAttrMap == NULL)
00731     {
00732         CCAttrMap * pAppliedAttrMap = CCAttrMap::MakeAppliedAttrMap(pCreatedByNode);
00733 //      pAppliedAttrMap->RemoveIndirectlyAppliedLayeredAttributes(pCreatedByNode,FALSE);
00734         pAttrMap = pAppliedAttrMap->Copy();
00735         delete pAppliedAttrMap;
00736     }
00737 
00738     pNewCompound = m_pCompound->CreateTreeFromNodeToBlend(pNewNode, pAttrMap);
00739     
00740     if (pNewCompound && pNewCompound->IsCompound())
00741     {
00742         ((NodeCompound *)pNewCompound)->SetBlendCreatedByNode(m_pCompound);
00743 
00744         TRACEUSER( "DavidM", _T("Count %d Num path nodes %d\n"),
00745             m_Count, m_NumPathNodes);
00746 
00747         if (m_Count == 0)
00748         {
00749             ((NodeCompound*)pNewCompound)->SetStartBlendGroupNode();
00750         }
00751         
00752         if (m_Count == m_NumPathNodes-1)
00753         {
00754             ((NodeCompound*)pNewCompound)->SetEndBlendGroupNode();
00755         }
00756     }
00757 
00758     m_Count++;
00759 
00760     return m_pBecomeA->PassBack(pNewCompound, pCreatedByNode, pAttrMap);
00761 }
00762 
00764 // SumAllPathsPathProcessor implementation
00765 
00766 /********************************************************************************************
00767 
00768 >   SumAllPathsPathProcessor::SumAllPathsPathProcessor(BOOL bDrawOriginalPaths)
00769 
00770     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00771     Created:    21/2/2000
00772     Inputs:     Whether to draw the paths passed in or not
00773     Outputs:    
00774     Returns:    
00775     Purpose:    Constructor
00776     SeeAlso:    -
00777 ********************************************************************************************/
00778 SumAllPathsPathProcessor::SumAllPathsPathProcessor(BOOL bDrawOriginalPaths)
00779 {
00780     m_bDrawPaths = bDrawOriginalPaths;
00781     m_bEnabled = TRUE;
00782 }
00783 
00784 /********************************************************************************************
00785 
00786 >   SumAllPathsPathProcessor::~SumAllPathsPathProcessor()
00787 
00788     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00789     Created:    21/2/2000
00790     Inputs:     
00791     Outputs:    
00792     Returns:    
00793     Purpose:    Destructor
00794     SeeAlso:    -
00795 ********************************************************************************************/
00796 SumAllPathsPathProcessor::~SumAllPathsPathProcessor()
00797 {
00798     PathList.DeleteAll();
00799 }
00800 
00801 /********************************************************************************************
00802 
00803 >   void SumAllPathsPathProcessor::ProcessPath(Path *pPath,
00804                              RenderRegion *pRender,
00805                              PathShape ShapePath = PATHSHAPE_PATH);
00806 
00807     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00808     Created:    21/2/2000
00809     Inputs:     The path to draw, the render region and the shape path 
00810     Outputs:    
00811     Returns:    
00812     Purpose:    Constructor
00813     SeeAlso:    -
00814 ********************************************************************************************/
00815 void SumAllPathsPathProcessor::ProcessPath(Path *pPath,
00816                              RenderRegion *pRender,
00817                              PathShape ShapePath)
00818 {
00819     if (!m_bEnabled)
00820     {
00821         pRender->DrawPath(pPath, this);
00822         return;
00823     }
00824     
00825     if (m_bDrawPaths)
00826     {
00827         pRender->DrawPath(pPath, this);
00828     }
00829 
00830     // create a new element and add it to the list
00831     CCAttrMap *pAttrMap = CCAttrMap::MakeAttrMapFromRenderRegion(pRender);
00832 
00833     SumAllPathsElem * pElem = new SumAllPathsElem(pPath, pAttrMap);
00834 
00835     PathList.AddTail(pElem);
00836 }
00837 
00838 
00839 
00840 /********************************************************************************************
00841 
00842 >   void SumAllPathsPathProcessor::InsertSumAllPathsElem (SumAllPathsElem* newElem)
00843 
00844     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00845     Created:    8/6/2000
00846     Inputs:     Element to be inserted
00847     Outputs:    
00848     Returns:    
00849     Purpose:    Allows us to insert paths directly into our list when performing convert to
00850                 editable shapes on blended shadows, bevels, etc.
00851     SeeAlso:    -
00852 ********************************************************************************************/
00853 
00854 void SumAllPathsPathProcessor::InsertSumAllPathsElem (SumAllPathsElem* newElem)
00855 {
00856     PathList.AddTail(newElem);
00857 }
00858 
00860 // SumAllPathsElem implementation
00861 
00862 SumAllPathsElem::SumAllPathsElem(Path * pPath, CCAttrMap * pAttrMap)
00863 {
00864     m_Path.Initialise(pPath->GetNumCoords());
00865     m_Path.CopyPathDataFrom(pPath);
00866 
00867     m_pAttrMap = pAttrMap;
00868 }
00869 
00870 SumAllPathsElem::~SumAllPathsElem()
00871 {
00872     // don't need to destroy the path, just the attribute map
00873     m_pAttrMap->DeleteAttributes();
00874     delete m_pAttrMap;
00875 }
00876 
00877 
00878 
00879 
00880 
00881 
00882 
00883 

Generated on Sat Nov 10 03:44:24 2007 for Camelot by  doxygen 1.4.4