nodebev.cpp

Go to the documentation of this file.
00001 // $Id: nodebev.cpp 1358 2006-06-25 12:51:36Z 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 #include "camtypes.h"
00100 
00101 #include <math.h>
00102 //#include "pathedit.h"
00103 #include "nodebev.h"
00104 #include "nbevcont.h"
00105 #include "noderect.h"
00106 #include "ppbevel.h"
00107 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 // Code headers
00109 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 #include "gclips.h"
00113 //#include "paths.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 #include "pathtrap.h"
00115 //#include "rndrgn.h"
00116 #include "grndrgn.h"
00117 #include "grndbmp.h"
00118 #include "nodebmp.h"
00119 //#include "becomea.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00120 #include "bmpcomp.h"
00121 #include "attrbev.h"
00122 //#include "xadrwold.h"
00123 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00124 #include "blobs.h"
00125 //#include "bevres.h"
00126 #include "lineattr.h"
00127 #include "bevtool.h"
00128 #include "csrstack.h"
00129 #include "prntview.h"
00130 #include "moldtool.h"
00131 #include "opcntr.h"
00132 #include "nodecntr.h"   // for the 'becomeA' stuff
00133 #include "ndbldpth.h"
00134 #include "ncntrcnt.h"   // ContourNodePathProcessor
00135 #include "nodetxts.h"
00136 //#include "mario.h"        // _R(IDE_NOMORE_MEMORY)
00137 #include "extender.h"   // for Extender code
00138 #include "swfrndr.h"    // For the FlashRenderRegion custom export code.
00139 #include "cmxrendr.h"   // For the CMXRenderRegion custom export code.
00140 #include "ai_epsrr.h"   // For the AIEPSRenderRegion custom export code.
00141 #include "rsmooth.h"
00142 #include "contmenu.h"
00143 #include "blndhelp.h"
00144 #include "offscrn.h"
00145 #include "scanrr.h"
00146 #include "opgrad.h"
00147 //#include "princomp.h"
00148 #include "strkattr.h"
00149 #include "ngcore.h"     // NameGallery, for stretching functionality
00150 #include "slicehelper.h"
00151 #include "brshattr.h"
00152 #include "fthrattr.h"   // for AttrFeather
00153 //#include "filtirr.h"
00154 #include "pmaskrgn.h"
00155 #include "ophist.h"
00156 #include "objchge.h"
00157 #include "attrmap.h"
00158 
00159 CC_IMPLEMENT_DYNCREATE(NodeBevel, NodeRenderableInk)
00160 CC_IMPLEMENT_DYNCREATE(BevelRecordHandler, CamelotRecordHandler)
00161 CC_IMPLEMENT_DYNCREATE(NodeBevelBegin, NodeRenderableBounded)
00162 
00163 // Declare smart memory handling in Debug builds
00164 #define new CAM_DEBUG_NEW
00165 
00166 
00167 #ifdef GENERATETIMINGS
00168 INT32 Timing1 = 0;
00169 #endif
00170 
00171 /**********************************************************************************************/
00172 
00173 const UINT32 BevelClipPathToPath_Tolerance   =  30 ;
00174 const UINT32 BevelClipPathToPath_Flatness    = 200 ;
00175 const UINT32 BevelStrokePathToPath_Flatness  = 200 ;
00176 
00177 const double BevelMaxBitmapWidth            = 1600.0;
00178 const double BevelMaxBitmapHeight           = 1200.0;
00179 
00180 
00181 /***********************************************************************************************
00182 
00183 >   NodeBevel::NodeBevel(Node*  ContextNode,
00184                         AttachNodeDirection Direction,
00185                         const DocRect&      BoundingRect,
00186                         BOOL                Locked = FALSE,
00187                         BOOL                Mangled = FALSE,
00188                         BOOL                Marked = FALSE,
00189                         BOOL                Selected = FALSE,
00190                         BOOL                Renderable = FALSE
00191                         )
00192 
00193     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00194     Created:    16/11/94
00195     Inputs:     ContextNode: Pointer to a node which this node is to be attached to.
00196                 MonoOn Direction: MonoOff
00197                 Specifies the direction in which the node is to be attached to the
00198                 ContextNode. The values this variable can take are as follows:
00199                                   
00200                 PREV      : Attach node as a previous sibling of the context node
00201                 NEXT      : Attach node as a next sibling of the context node
00202                 FIRSTCHILD: Attach node as the first child of the context node
00203                 LASTCHILD : Attach node as a last child of the context node
00204 
00205                 BoundingRect: Bounding rectangle
00206 
00207                 The remaining inputs specify the status of the node:
00208             
00209                 Locked:     Is node locked ?
00210                 Mangled:    Is node mangled ?
00211                 Marked:     Is node marked ?
00212                 Selected:   Is node selected ?
00213 
00214     Purpose:    This constructor initialises the nodes flags and links it to ContextNode in the
00215                 direction specified by Direction. All neccesary tree links are updated.
00216     Note:       SetUpShape() must be called before the NodeRegularShape is in a state in which
00217                 it can be used.
00218     SeeAlso:    NodeRegularShape::SetUpShape
00219     Errors:     An ENSURE will occur if ContextNode is NULL
00220 
00221 ***********************************************************************************************/
00222 NodeBevel::NodeBevel(Node* ContextNode,  
00223                     AttachNodeDirection Direction,  
00224                     BOOL Locked, 
00225                     BOOL Mangled,  
00226                     BOOL Marked, 
00227                     BOOL Selected    
00228               ) : NodeRenderableInk(ContextNode, Direction, Locked, Mangled, Marked, Selected )
00229 {                         
00230     m_Indent = 0;
00231     m_pBevelBitmap = NULL;
00232     m_Contrast = 100;
00233     m_bLock = FALSE;
00234     m_bRenderBitmaps = TRUE;
00235     m_bZeroLineWidth = TRUE;
00236     m_LastPixelSize = 0;
00237     m_bOuter = FALSE;
00238     m_BitmapWidth = 0;
00239     m_BitmapHeight = 0;
00240     InkPath.Initialise(0,12);
00241     m_ShrunkPath.Initialise();
00242     m_bStopRender = FALSE;
00243     m_pBMPFill = NULL;
00244     m_BevelType = 0;
00245     m_LightAngle = 0;
00246     m_ViewScale = 0;
00247     m_OuterBevelPath.Initialise();
00248     m_Path.Initialise();
00249     m_pBeveler = NULL;
00250     m_Tilt = 32.0;
00251     m_bPathIsClosed = FALSE;
00252     m_bCached = FALSE;
00253     m_DoingRotation = FALSE;
00254     m_SubPixelOffset.x = 0;
00255     m_SubPixelOffset.y = 0;
00256     m_IsFlatFilledOnly = TRUE;
00257     m_HasTransparencyApplied = FALSE;
00258     m_pTranspFill = NULL;
00259     m_pCombiBitmap = NULL;
00260     m_LastZoomFactor = 1.0;
00261     m_LastCachedPrintBMPDPI = 0.0;
00262     m_IsABlendStepBevel = FALSE;
00263     m_DoRender = TRUE;
00264     m_IsAnAlphaBMP = FALSE;
00265     m_AmConvertingToShapes = FALSE;
00266     m_LastExportedDPI = 96.0;
00267 }
00268 
00269 /*********************************************************************************************
00270 
00271 >   NodeBevel::NodeBevel() 
00272 
00273     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00274     Created:    6/10/98
00275     Purpose:    Default constructor
00276     Note:       
00277     SeeAlso:    
00278 
00279 **********************************************************************************************/
00280 NodeBevel::NodeBevel()
00281 {
00282     m_bStopRender = FALSE;
00283     m_Indent = 0;
00284     m_LightAngle = 300;
00285     m_bLock = FALSE;
00286     m_BevelType = 0;
00287     m_bZeroLineWidth = TRUE;
00288     m_pBevelBitmap = NULL;
00289     m_bOuter = FALSE;
00290     m_Contrast = 100;
00291     m_ShrunkPath.Initialise();
00292     m_ViewScale = 0;
00293     m_pBMPFill = NULL;
00294     m_bRenderBitmaps = TRUE;
00295     m_OuterBevelPath.Initialise();
00296     m_Path.Initialise();
00297     m_BevelType = 0;
00298     m_LightAngle = 0;
00299     m_JointType = MitreJoin;
00300     InkPath.Initialise(0,12);
00301     m_pBeveler = NULL;
00302     m_Tilt = 32.0;
00303     m_bPathIsClosed = FALSE;
00304     m_bCached = FALSE;
00305     m_DoingRotation = FALSE;
00306     m_SubPixelOffset.x = 0;
00307     m_SubPixelOffset.y = 0;
00308     m_IsFlatFilledOnly = TRUE;
00309     m_HasTransparencyApplied = FALSE;
00310     m_pTranspFill = NULL;
00311     m_pCombiBitmap = NULL;
00312     m_LastZoomFactor = 1.0;
00313     m_LastCachedPrintBMPDPI = 0.0;
00314     m_LastPixelSize = 0;
00315     m_IsABlendStepBevel = FALSE;
00316     m_DoRender = TRUE;
00317     m_IsAnAlphaBMP = FALSE;
00318     m_AmConvertingToShapes = FALSE;
00319     m_LastExportedDPI = 96.0;
00320 }
00321 
00322 /*********************************************************************************************
00323 
00324 >   NodeBevel::~NodeBevel() 
00325 
00326     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00327     Created:    6/10/98
00328     Purpose:    Default destructor
00329     Note:       
00330     SeeAlso:    
00331 
00332 **********************************************************************************************/
00333 
00334 NodeBevel::~NodeBevel()
00335 {
00336     if (m_pBMPFill)
00337     {
00338         delete m_pBMPFill;
00339         m_pBMPFill = NULL;
00340     }
00341 
00342     if (m_pTranspFill)
00343     {
00344         delete m_pTranspFill;
00345         m_pTranspFill = NULL;
00346     }
00347 
00348     if (m_pBevelBitmap)
00349     {
00350         delete m_pBevelBitmap;
00351         m_pBevelBitmap = NULL;
00352     }
00353 
00354     if(m_pCombiBitmap)
00355     {
00356         delete m_pCombiBitmap;
00357         m_pCombiBitmap = NULL;
00358     }
00359 
00360     DeleteCache();
00361 }
00362 
00363 /*********************************************************************************************
00364 
00365 >   String NodeBevel::Describe(BOOL Plural, BOOL Verbose) 
00366 
00367     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00368     Created:    6/10/98
00369     Purpose:    Default constructor
00370     Note:       
00371     SeeAlso:    
00372 
00373 **********************************************************************************************/
00374 
00375 String NodeBevel::Describe(BOOL Plural, BOOL Verbose) 
00376 {     
00377     String Name;
00378     Name.Load(_R(IDS_BEVEL_NODE_NAME));
00379     
00380     return Name; // Just to keep the compiler happy
00381 }; 
00382 
00383 /*********************************************************************************************
00384 
00385 >   BOOL NodeBeveler::GenerateBevel();
00386 
00387     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00388     Created:    6/10/98
00389     Purpose:    Creates the beveller class, and the beveller bitmap
00390     Note:       
00391     SeeAlso:    ContourBecomeA
00392 
00393 **********************************************************************************************/
00394 BOOL NodeBevel::GenerateBevel()
00395 {
00396     NodeBevelController* pControl = (NodeBevelController *)FindParent();
00397     if ( !pControl )
00398         return FALSE ;
00399 
00400     // are we safe to render ?
00401     if ( pControl->GetInsideBoundingRect().IsEmpty() )
00402         return FALSE;
00403     
00404     BOOL ok = TRUE;
00405     
00406     // Check the current bitmap pointers and delete them if still valid
00407     if (m_pBMPFill)
00408     {
00409         delete m_pBMPFill;
00410         m_pBMPFill = NULL;
00411     }
00412 
00413     if (m_pTranspFill)
00414     {
00415         delete m_pTranspFill;
00416         m_pTranspFill = NULL;
00417     }
00418 
00419     if (m_pCombiBitmap)
00420     {
00421         delete m_pCombiBitmap;
00422         m_pCombiBitmap = NULL;
00423     }
00424 
00425     // Create a new pointer for the bitmap and Transp Bitmap fill Attributes
00426     m_pBMPFill = new BitmapFillAttribute;
00427     ERROR2IF(m_pBMPFill == NULL,FALSE,"Failed to create a new BMP Fill Attrib!");
00428 
00429     m_pTranspFill = new BitmapTranspFillAttribute;
00430     ERROR2IF(m_pTranspFill == NULL,FALSE,"Failed to create a new TranspBMP Fill Attrib!");
00431 
00432     UINT32 startTrans   = 0x00;
00433     UINT32 endTrans = 0xff;
00434     m_pTranspFill->SetTranspType(TT_BEVEL);
00435     m_pTranspFill->SetStartTransp(&startTrans);
00436     m_pTranspFill->SetEndTransp(&endTrans);
00437     m_pTranspFill->SetTesselation(RT_RepeatInverted);
00438 
00439     m_pBMPFill->SetTesselation(RT_RepeatInverted);
00440 
00441     // set up the variables on myself & my parent by finding the appropriate attributes
00442     // create all the paths for the bevel
00443     // no need to do this if we're printing - they should already be set up
00444     if (!SetupVariables() || !CreateBevelPaths())
00445         ok = FALSE;
00446 
00447     return ok;
00448 }
00449 
00450 /*********************************************************************************************
00451 
00452 >   BOOL NodeBevel::GenerateBevelForBlendStep(List * pList, CCAttrMap * pMap)
00453 
00454     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00455     Created:    29/2/2000
00456     Purpose:    Creates the bevel data from the given list of SumAllPathsElem
00457                 
00458     Note:       Takes the variables from FindAppliedAttribute therefore the attributes
00459                 should be applied to this node before calling this function
00460     SeeAlso:    ContourBecomeA
00461 
00462 **********************************************************************************************/
00463 BOOL NodeBevel::GenerateBevelForBlendStep(SumAllPathsElem* pElem, CCAttrMap * pAttrMap)
00464 {
00465     // set up the variables on myself
00466     if (!SetupVariables(pAttrMap))
00467         return FALSE;   
00468 
00469     m_ViewScale = 0;
00470 
00471     BOOL bOuter = m_bOuter;
00472     INT32 Width = m_Indent;
00473 
00474     m_OuterBevelPath.ClearPath();
00475     m_Path.ClearPath();
00476 
00477     CProfileBiasGain Profile;
00478 
00479     // CGS - we need to generate the bevel with respect to the JoinType applied to the path
00480     // that we are generating it with; BUT if the original bevel had a jointype; then we need
00481     // to generate it with respect to this!
00482     
00483     JointType generateJoinType=MitreJoin;
00484 
00485     AttrJoinType * pJoinType = NULL;
00486     AttrJoinType * pBevelJoinType = NULL;
00487 
00488     pElem->GetAttrMap ()->Lookup( CC_RUNTIME_CLASS(AttrJoinType), (void *&)pJoinType);
00489     pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrJoinType), (void *&)pBevelJoinType);
00490 
00491     if (pJoinType && pBevelJoinType)
00492     {
00493         if (*pJoinType == *pBevelJoinType)
00494             generateJoinType = pJoinType->Value.JoinType;
00495         else
00496             generateJoinType = pBevelJoinType->Value.JoinType;
00497     }
00498 
00499     // use the contour becomeA to generate all the paths
00500     ContourBecomeA MyBecomeA(BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath),
00501         NULL, FALSE, &m_OuterBevelPath, &m_Path, Width, 1, bOuter, Profile,generateJoinType,
00502         BevelClipPathToPath_Flatness,TRUE);
00503 
00504     Path BlankPath;
00505     BlankPath.Initialise();
00506 
00507     NodePath* pPathNode = new NodePath;
00508     ERRORIF(pPathNode == NULL, _R(IDE_NOMORE_MEMORY), FALSE);
00509 
00510     pPathNode->InkPath.Initialise();
00511 
00512     pElem->GetPath()->ClipPathToPath(BlankPath, &(pPathNode->InkPath), 6);
00513 
00514     NodePath* pStrokedPathNode = pPathNode->MakeNodePathFromAttributes(30, pElem->GetAttrMap());
00515     
00516     if (pStrokedPathNode)
00517     {   
00518         pStrokedPathNode->DoBecomeA(&MyBecomeA);
00519         delete pStrokedPathNode;
00520     }
00521 
00522     delete pPathNode;
00523     pPathNode = NULL;
00524 
00525     if(m_Path.GetUsedSlots() <= 0)
00526         return TRUE;
00527     m_IsABlendStepBevel = TRUE;
00528 
00529     // set all the filled flags on the path list
00530     m_OuterBevelPath.IsFilled = TRUE;
00531     m_OuterBevelPath.IsStroked = FALSE;
00532 
00533     // reverse the original path so it will create a hole in the bevel path
00534     Path ReversedPath;
00535     ReversedPath.Initialise();
00536     ReversedPath.CloneFrom(m_Path);
00537 
00538     // Check to see what the zoom factor is so we can take it into account for the flatness values!
00539     DocView* pDocView = Document::GetCurrent()->GetFirstDocView();
00540     double CurrentZoom = 1.0;
00541 
00542     if(pDocView)
00543         CurrentZoom = pDocView->GetZoomFactor();
00544 
00545     ReverseAndShrinkBevelPathIntoInkPath(&ReversedPath, CurrentZoom, bOuter);
00546 
00547     // now the path has been created, create the bevel bitmap
00548     if (!CreateBevelBitmap())
00549         return FALSE;
00550 
00551     m_bCached = TRUE;
00552 
00553     return TRUE;
00554 }
00555 
00556 
00557 
00558 /*********************************************************************************************
00559 
00560 >   BOOL NodeBevel::CreateBevelBitmap()
00561 
00562     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00563     Created:    18/10/99
00564     Purpose:    Creates the bitmap used in generating the highlights for bevels
00565     Note:       
00566     SeeAlso:    
00567 
00568 **********************************************************************************************/
00569 BOOL NodeBevel::CreateBevelBitmap()
00570 {
00571     // Find the parent node and make sure it`s not null and it`s a bevel controller node
00572     Node* pNode = FindParent();
00573     if (!pNode && !pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelController)))
00574     {
00575         ERROR3("Bevel node has a parent which isn't a bevel controller node !");
00576         return FALSE;
00577     }
00578 
00579     TRACEUSER( "MarkH", _T("Creating a new Bevel Bitmap!\n"));
00580 
00581     // Clear the current shrunken path
00582     m_ShrunkPath.ClearPath();
00583     
00584     // delete the existing pointers
00585     if (m_pBevelBitmap)
00586     {
00587         delete m_pBevelBitmap;
00588         m_pBevelBitmap = NULL;
00589     }
00590 
00591     if (m_pBeveler)
00592     {
00593         delete m_pBeveler;
00594         m_pBeveler = NULL;
00595     }
00596 
00597     if(m_pCombiBitmap)
00598     {
00599         delete m_pCombiBitmap;
00600         m_pCombiBitmap = NULL;
00601     }
00602 
00603     // get the path to use from the processor
00604     if (m_Path.GetNumCoords() == 0)
00605         return FALSE;
00606 
00607     // Now create a new CBeveler Pointer
00608     m_pBeveler = new CBeveler(&m_Path);
00609     ERROR2IF(!m_pBeveler,FALSE,"Failed to create a CBeveler pointer!");
00610 
00611     // the flatness needs to be linked to the height of this
00612     MILLIPOINT Flatness = BEVEL_FLATNESS;
00613 
00614     // alter the flatness for printing
00615     NodeBevelController* pBevelController = (NodeBevelController *) pNode;
00616     if (pBevelController && pBevelController->IsPrinting())
00617         Flatness = (MILLIPOINT)(((double)BEVEL_FLATNESS) * (96.0 / pBevelController->GetDPI()));
00618 
00619     // set up the bevel type
00620     m_pBeveler->SetBevelType(m_BevelType);
00621     m_pBeveler->SetBevelAngle(m_LightAngle);
00622     m_pBeveler->SetBevelTilt(m_Tilt);
00623 
00624     // Find the current Join type
00625     AttrJoinType * pJoinType = NULL;
00626     FindAppliedAttribute(CC_RUNTIME_CLASS(AttrJoinType), (NodeAttribute **)(&pJoinType));
00627     JointType JT = RoundJoin;
00628     if (pJoinType)
00629         JT = pJoinType->Value.JoinType;
00630 
00631     // Calculate the angle using the lightangle variable
00632     double angle = 3.1415926536*m_LightAngle/180 ;
00633     NormCoord nc( cos(angle),sin(angle) );
00634 
00635     // Set up the beveler with all the new variables!
00636     BOOL ok = m_pBeveler->SetUpBeveler(m_Indent, JT, &nc, m_bOuter, pBevelController->m_Contrast, NULL, BevelClipPathToPath_Flatness);
00637 
00638     // Check to see if the setup went ok
00639     if(!ok)
00640         return FALSE;
00641 
00642     // Do another recalculation to setup the fill handles!
00643     CalculateBitmapSize(&m_BitmapWidth, &m_BitmapHeight);
00644 
00645     // Check to see if the size is valid
00646     if (m_BitmapWidth <= 0 || m_BitmapHeight <= 0)
00647         return TRUE;
00648 
00649     // Now tell the beveler how large to make the bevels.
00650     m_pBeveler->SetBevelerSize(m_BitmapWidth,m_BitmapHeight);
00651     
00652     // make the bounding box the same as the selection bounds 
00653     BoundingRectangle = m_PixelAllignedRect;
00654     IsBoundingRectValid = TRUE;
00655 
00656     m_BMPCentre.x = m_PixelAllignedRect.lo.x;
00657     m_BMPCentre.y = m_PixelAllignedRect.lo.y;
00658     m_BMPPoint1.x = m_PixelAllignedRect.hi.x;
00659     m_BMPPoint1.y = m_PixelAllignedRect.lo.y;
00660     m_BMPPoint2.x = m_PixelAllignedRect.lo.x;
00661     m_BMPPoint2.y = m_PixelAllignedRect.hi.y;
00662 
00663     NodeAttribute* pFillAttrib = NULL;
00664     DocColour FillColour = COLOUR_BLACK;
00665 
00666     // Test to see if theres a FillGeom Attribute applied to the bevel
00667     if(FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry),&pFillAttrib))
00668     {
00669         // If the pointer is valid and It`s a flat fill then get the colour and set the IsFlatFill Flag
00670         if(pFillAttrib != NULL && pFillAttrib->IsAFlatFill())
00671         {
00672             FillColour = *((AttrFlatColourFill*)pFillAttrib)->GetStartColour();
00673             m_IsFlatFilledOnly = TRUE;
00674         }
00675         else
00676         {
00677             // it`s not a plain flat fill so set the flag to false
00678             m_IsFlatFilledOnly = FALSE;
00679 
00680             // Make sure we know if it`s an Alpha Channel Bitmap as this needs special treatment!
00681             if(pFillAttrib->IsABitmapFill())
00682             {
00683                 BitmapFillAttribute* pFill = (BitmapFillAttribute*)pFillAttrib->GetAttributeValue();
00684                 m_IsAnAlphaBMP = (pFill->GetBitmap()->GetBitmapInfoHeader()->biBitCount == 32);
00685             }
00686             else
00687                 m_IsAnAlphaBMP = FALSE;
00688         }
00689     }
00690 
00691     // make sure the palette is setup ready for the BMP
00692     SetUpBitmapPalette((RenderRegion *)NULL,FillColour);
00693 
00694     // Everythings cool, return TRUE
00695     return TRUE;
00696 }
00697 
00698 
00699 
00700 
00701 /*********************************************************************************************
00702 
00703 >   BOOL NodeBevel::SetupVariables(CCAttrMap * pMap)
00704 
00705     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00706     Created:    17/10/99
00707     Purpose:    Sets up all the attributes on myself and my parent by finding the
00708                 appropriate attributes
00709     Inputs:     The attribute map to use, NULL to find applied attributes
00710     Note:       
00711     SeeAlso:    
00712 
00713 **********************************************************************************************/
00714 BOOL NodeBevel::SetupVariables(CCAttrMap * pMap)
00715 {
00716     // set the attributes up (on our parent !)
00717     AttrBevelIndent * pIndent = NULL;
00718     AttrBevelLightAngle * pLightAngle = NULL;
00719     AttrBevelContrast * pContrast = NULL;
00720     AttrBevelType * pType = NULL;
00721     AttrBevelLightTilt * pTilt = NULL;
00722 
00723     if(pMap == NULL)
00724     {
00725         this->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBevelIndent), (NodeAttribute **)(&pIndent));
00726         this->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBevelLightAngle), (NodeAttribute **)(&pLightAngle));
00727         this->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBevelContrast), (NodeAttribute **)(&pContrast));
00728         this->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBevelType), (NodeAttribute **)(&pType));
00729         this->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBevelLightTilt), (NodeAttribute **)(&pTilt));
00730     }
00731     else
00732     {
00733         pMap->Lookup( CC_RUNTIME_CLASS(AttrBevelIndent), (void *&)pIndent);
00734         pMap->Lookup( CC_RUNTIME_CLASS(AttrBevelLightAngle), (void *&)pLightAngle);
00735         pMap->Lookup( CC_RUNTIME_CLASS(AttrBevelContrast), (void *&)pContrast);
00736         pMap->Lookup( CC_RUNTIME_CLASS(AttrBevelType), (void *&)pType);
00737         pMap->Lookup( CC_RUNTIME_CLASS(AttrBevelLightTilt), (void *&)pTilt);
00738     }
00739 
00740     NodeBevelController * pBevelController = (NodeBevelController *)FindParent();
00741     if ( !pBevelController )
00742         return FALSE ;
00743 
00744     // Now make sure we`ve got valid pointers to all the varibale
00745     if (pIndent && pLightAngle && pContrast && pType && pTilt)
00746     {
00747         if (pIndent->Value.m_Indent < 0)
00748         {
00749             pBevelController->m_Indent = -pIndent->Value.m_Indent;
00750             pBevelController->m_bOuter = TRUE;
00751         }
00752         else
00753         {
00754             pBevelController->m_Indent = pIndent->Value.m_Indent;
00755             pBevelController->m_bOuter = FALSE;
00756         }
00757 
00758         m_Indent = pBevelController->m_Indent;
00759         m_bOuter = pBevelController->m_bOuter;
00760 
00761         m_LightAngle = pBevelController->m_LightAngle = pLightAngle->Value.m_LightAngle;
00762         m_Contrast = pBevelController->m_Contrast = pContrast->Value.m_Contrast;
00763         m_BevelType = pBevelController->m_BevelType = pType->Value.m_Type;
00764         m_Tilt = pBevelController->m_Tilt = pTilt->Value.m_LightTilt;
00765 
00766         return TRUE;
00767     }
00768 
00769     return FALSE;
00770 }
00771 
00772 /*********************************************************************************************
00773 
00774 >   BOOL NodeBevel::CreateBevelPaths()
00775 
00776     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
00777     Created:    17/10/99
00778     Purpose:    Sets up all the attributes on myself and my parent by finding the
00779                 appropriate attributes
00780     Note:       
00781     SeeAlso:    ContourBecomeA (in kernel/nodecntr.h), NodeContour::GenerateContour
00782 
00783 **********************************************************************************************/
00784 BOOL NodeBevel::CreateBevelPaths()
00785 {
00786     // Delete the current Cache
00787     DeleteCache();
00788 
00789     // build up the source path
00790     Node * pNode = FindParent();
00791     NodeBevelController * pControl = (NodeBevelController *)FindParent();
00792 
00793     if (!pNode)
00794         return FALSE;
00795 
00796     pNode = pNode->FindFirstChild();
00797 
00798     if (!pNode || pNode == this)
00799         return FALSE;
00800 
00801     double CurrentFlatness = 200.0;
00802 
00803     // Mark Howitt 31/10/00
00804     // This function call now replaces the passed in value when the BecomeA function is created.
00805     // This has been done to elliminate zoom dependancies which change the flatness values
00806     // depending on the current zoom value. See the function header for more details
00807     Node* pNodeToBevel = pNode->FindNextInk();
00808 
00809     while(pNodeToBevel == this && pNodeToBevel)
00810         pNodeToBevel = pNodeToBevel->FindNextInk();
00811 
00812     if(pNodeToBevel)
00813     {
00814         DocRect DR = ((NodeRenderableInk*)pNodeToBevel)->GetBoundingRect();
00815 
00816         // Get the smallest dimesion, Width or Height.
00817         double Smallest = DR.Height() < DR.Width() ? (double)DR.Height() : (double)DR.Width();
00818 
00819         // now make the flatness value equal to the smallest dimesion divided by 375
00820         CurrentFlatness = Smallest / 375.0;
00821 
00822         // Check to see if we`re within the specified limits
00823         if(1.0 > CurrentFlatness) CurrentFlatness = 1.0;
00824         if(375.0 < CurrentFlatness) CurrentFlatness = 375.0;
00825     }
00826 
00827     // Check to see what the zoom factor is so we can take it into account for the flatness values!
00828     DocView* pDocView = Document::GetCurrent()->GetFirstDocView();
00829     double CurrentZoom = 1.0;
00830 
00831     if(pDocView)
00832         CurrentZoom = pDocView->GetZoomFactor();
00833 
00834     m_LastZoomFactor = CurrentZoom;
00835 
00836     m_Path.ClearPath();
00837     InkPath.ClearPath();
00838     m_OuterBevelPath.ClearPath();
00839 
00840     INT32 Width  = pControl->m_Indent;
00841     BOOL bOuter = pControl->m_bOuter;
00842 
00843     // bog standard profile
00844     CProfileBiasGain Profile;
00845     AttrJoinType * pJoinType = NULL;
00846     FindAppliedAttribute(CC_RUNTIME_CLASS(AttrJoinType), (NodeAttribute **)(&pJoinType));
00847 
00848     JointType JT = RoundJoin;
00849     if (pJoinType)
00850         JT = pJoinType->Value.JoinType;
00851 
00852     // use the BecomeA passback mechanism to contour everything
00853 /*#ifdef NEWBEVEL
00854     ContourBecomeA MyBecomeA(BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath),
00855         NULL, FALSE, &m_OuterBevelPath, &m_Path, 0, 1, bOuter, Profile, JT,
00856         CurrentFlatness,TRUE);
00857 #else*/
00858     ContourBecomeA MyBecomeA(BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath),
00859         NULL, FALSE, &m_OuterBevelPath, &m_Path, Width, 1, bOuter, Profile, JT,
00860         CurrentFlatness,TRUE);
00861 //#endif
00862 
00863     m_bPathIsClosed = TRUE;
00864 
00865     Path CopyPath; CopyPath.Initialise();
00866     Path TempPath; TempPath.Initialise();
00867 //  UINT32 NumObjects = 0;
00868 //  AttrVariableWidth* pStroked = NULL;
00869 
00870 //  TextStory* pTextStory = NULL;
00871 
00872     // run through all nodes, contouring them
00873     while (pNode)
00874     {
00875         if(pNode != this)
00876         {
00877             // When we conditionally call CanBecomeA below, we want to find the number of paths
00878             // pNode will produce. So we must clear the counter now before the condition starts
00879             MyBecomeA.ResetCount();
00880 
00881             // is the node a blend path ?
00882             if (!pNode->IS_KIND_OF(NodeBlendPath))
00883             {   
00884                 // is the node a path ?
00885                 if (pNode->IsNodePath())
00886                 {
00887                     // turn the path into a closed shape
00888                     if (((NodePath *)pNode)->InkPath.IsClosed())
00889                         m_bPathIsClosed = FALSE;
00890 /*
00891                     FindAppliedAttribute(CC_RUNTIME_CLASS(AttrVariableWidth),(NodeAttribute**)(&pStroked));
00892                     if(pStroked && ((VariableWidthAttrValue*)pStroked->GetAttributeValue())->GetWidthFunction() != NULL)
00893                     {
00894                         ((NodePath *)pNode)->DoBecomeA(&MyBecomeA);
00895                     }
00896                     else
00897                     {
00898 */                      NodePath* pPathNode = ((NodePath *)pNode)->MakeNodePathFromAttributes(CurrentFlatness);
00899 
00900                         if (pPathNode)
00901                         {
00902                             pPathNode->DoBecomeA(&MyBecomeA);
00903                             delete pPathNode;
00904                         }
00905 //                  }
00906                 }
00907                 else if (pNode->CanBecomeA(&MyBecomeA))
00908                 {
00909                     // If the NumObjects > 0 then we`ve got a compound node of some sort!
00910                     if (MyBecomeA.GetCount() > 0)
00911                     {
00912                         // is this a text node ?
00913                         if (pNode->IS_KIND_OF(TextStory))
00914                         {
00915                             // reformat it first
00916                             ((TextStory *)pNode)->FormatAndChildren();
00917                         }
00918                         else
00919                         {
00920                             // See if we`ve got any text in our compound, and if so format them!
00921                             Node* pLid = pNode;
00922                             Node* pNext = pNode;
00923 
00924                             while(pNext)
00925                             {
00926                                 pNext = SliceHelper::FindNextOfClass(pNext,pLid,CC_RUNTIME_CLASS(TextStory));
00927                                 
00928                                 if(pNext)
00929                                     ((TextStory*)pNext)->FormatAndChildren();
00930                             }
00931                         }
00932 
00933                         if (!pNode->DoBecomeA(&MyBecomeA))
00934                             break;
00935                     }
00936 
00937                     if (MyBecomeA.GetCount() > 1)
00938                     {
00939                         TRACEUSER( "MarkH", _T("Clipping group to tidy things up!\n"));
00940 
00941                         // Need to clip!
00942                         CopyPath.ClearPath();
00943                         CopyPath.CloneFrom(m_Path);
00944                         m_Path.ClearPath();
00945 
00946                         if(TempPath.ClipPathToPath(CopyPath,&m_Path,7|CLIPPING_SOURCE_WINDING,BevelClipPathToPath_Tolerance,CurrentFlatness,CurrentFlatness) < 0)
00947                         {
00948                             TRACEUSER( "MarkH", _T("ClipFailed!!! NodeBev.cpp\n"));
00949                         }
00950                     }
00951                 }
00952             }
00953         }
00954 
00955         pNode = pNode->FindNext();
00956     }
00957 
00958     // set all the filled flags on the path list
00959     m_OuterBevelPath.IsFilled = TRUE;
00960     m_OuterBevelPath.IsStroked = FALSE;
00961 
00962     // reverse the original path so it will create a hole in the bevel path
00963     Path ReversedPath;
00964     ReversedPath.Initialise();
00965     ReversedPath.CloneFrom(m_Path);
00966 
00967     return ReverseAndShrinkBevelPathIntoInkPath(&ReversedPath, CurrentZoom, bOuter);
00968 }
00969 
00970 BOOL NodeBevel::ReverseAndShrinkBevelPathIntoInkPath(Path* pBevelPath, double ZoomValue, BOOL IsAnOuter)
00971 {
00972     // Reverses the bevel path and adds it to the original to create the new bevel path
00973     // Also shrinks/Expands the inner/outer path edge by a pixel to get rid of antialiasing
00974     // effects when overlapping the object
00975 
00976     if(pBevelPath == NULL)
00977         return FALSE;
00978 
00979     double CurrentFlatness = 200.0 * ZoomValue;
00980 
00981     Path CopyPath;
00982     CopyPath.Initialise();
00983     CopyPath.CloneFrom(*pBevelPath);
00984     pBevelPath->ClearPath();
00985     
00986     UINT32 Modifier = 750;
00987     
00988     if(!m_bOuter)
00989         Modifier = 0;
00990 
00991     if(ZoomValue < 1.0)
00992         Modifier = UINT32( double(Modifier) * ZoomValue );
00993 
00994     CurrentFlatness = CopyPath.CalculateFlatnessValueFromPath(375.0);
00995     CopyPath.InitializeContourValues(Modifier,JOIN_ROUND,!IsAnOuter,CurrentFlatness);
00996     
00997     if(CopyPath.GetContourForStep(pBevelPath) < 0)
00998         pBevelPath->CloneFrom(CopyPath);
00999 
01000     if(pBevelPath->GetUsedSlots() > 2)
01001         pBevelPath->Reverse();
01002 
01003     if (IsAnOuter)
01004     {   
01005         // copy the outer path into the inking path for the bevel, and add the
01006         // original path to create a hole in it
01007         InkPath.CloneFrom(m_OuterBevelPath);
01008         InkPath.MergeTwoPaths(*pBevelPath);
01009     }
01010     else 
01011     {
01012         // create the path list for inner contours
01013         // copy the outer path into the inking path for the bevel, and add the
01014         // original path to create a hole in it
01015         if(m_OuterBevelPath.ClipPathToPath(
01016             *pBevelPath, &InkPath, 1 | CLIPPING_CLIP_WINDING,
01017             BevelClipPathToPath_Tolerance,
01018             CurrentFlatness,CurrentFlatness) < 0)
01019         {
01020             TRACEUSER( "MarkH", _T("ClipFailed so copying path! PATHS\n"));
01021         }
01022     }
01023 
01024     InkPath.IsFilled = TRUE;
01025     InkPath.IsStroked = FALSE;
01026 
01027     return TRUE;
01028 }
01029 
01030 /***********************************************************************************************
01031 
01032 >   void NodeBevel::Render(RenderRegion* pRender)
01033 
01034     Author:     Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com>
01035     Created:    13/07/00
01036     Inputs:     Pointer to a render region
01037     Purpose:    Will build a path for the shape and draw it to the given render region.
01038 
01039 ***********************************************************************************************/
01040 void NodeBevel::Render(RenderRegion* pRender)
01041 {
01042 //  TRACEUSER( "Gerry", _T("NodeBevel::Render region 0x%08x\n"),pRender);
01043 
01044     // set up variables from parent
01045     NodeBevelController * pBevelController = (NodeBevelController *)GetParentController();
01046     DocView* pDocView = Document::GetCurrent()->GetFirstDocView();
01047     
01048     // Check to see if we`ve got valid pointer!
01049     if(pBevelController == NULL || pRender == NULL || !m_DoRender || !pDocView)
01050         return;
01051 
01052     // Get the bevel variables from the Bevel Controller node
01053     m_Indent = pBevelController->m_Indent;
01054     m_Contrast = pBevelController->m_Contrast;
01055     m_LightAngle    = pBevelController->m_LightAngle;
01056     m_BevelType = pBevelController->m_BevelType;
01057     m_bOuter = pBevelController->m_bOuter;
01058 
01059     // if we have a zero indent, then there`s no bevel! just return
01060     if (m_Indent==0)
01061         return;
01062 
01063     // if we`re printing then we need to check that our bounding render intersects with
01064     // the current render regions clipping rect
01065     if (pBevelController->IsPrinting())
01066     {
01067         // make sure we're intersected with the render regions clipping rectangle
01068         if (!(pRender->GetClipRect().IsIntersectedWith(BoundingRectangle)))
01069         {
01070             DeleteCachedBitmap();
01071             return ;
01072         }
01073     }
01074 
01075     // first, check for re-entry of code
01076     if (m_bLock)
01077         return;
01078 
01079     m_bStopRender = FALSE;
01080 
01081     // check if we have anything to draw
01082     // do this after we've removed all the path processors
01083     if (pBevelController->GetInsideBoundingRect().IsEmpty() || InkPath.GetNumCoords() == 0)
01084     {
01085         m_bStopRender = TRUE;
01086         return;
01087     }
01088 
01089     BOOL DoReRender = FALSE;
01090 
01091     double CurrentZoom = pDocView->GetZoomFactor();
01092 
01093     if(m_LastZoomFactor != CurrentZoom)
01094     {
01095         if(m_pCombiBitmap != NULL)
01096         {
01097             delete m_pCombiBitmap;
01098             m_pCombiBitmap = NULL;
01099         }
01100 
01101         Path ReversedPath;
01102         ReversedPath.Initialise();
01103         ReversedPath.CloneFrom(m_Path);
01104 
01105         if(!ReverseAndShrinkBevelPathIntoInkPath(&ReversedPath, CurrentZoom, m_bOuter))
01106         {
01107             m_bStopRender = TRUE;
01108             return;
01109         }
01110 
01111         m_LastZoomFactor = CurrentZoom;
01112     }
01113 
01114     pRender->SaveContext();
01115 
01116     NodeAttribute* pFillAttrib = NULL;
01117     DocColour FillColour = COLOUR_BLACK;
01118 
01119     // Store the last state of the IsFlatFilledOnly flag
01120     BOOL LastFillWasFlat = m_IsFlatFilledOnly;
01121 
01122     // Test to see if theres a FillGeom Attribute applied to the bevel
01123     if(FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry),&pFillAttrib))
01124     {
01125         // If the pointer is valid and It`s a flat fill then get the colour and set the IsFlatFill Flag
01126         if(pFillAttrib != NULL && pFillAttrib->IsAFlatFill())
01127         {
01128             FillColour = *((AttrFlatColourFill*)pFillAttrib)->GetStartColour();
01129             m_IsFlatFilledOnly = (FillColour != COLOUR_NONE);
01130         }
01131         else
01132         {
01133             // it`s not a plain flat fill so set the flag to false
01134             m_IsFlatFilledOnly = FALSE;
01135             if(pFillAttrib && m_pBMPFill)
01136                 m_pBMPFill->SetTesselation(((ColourFillAttribute*)pFillAttrib->GetAttributeValue())->GetTesselation());
01137         }
01138     }
01139 
01140     // Test to see if there`s a transparency applied to the bevel
01141     if(FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillGeometry),&pFillAttrib))
01142     {
01143         if(pFillAttrib != NULL && pFillAttrib->IsATranspFill())
01144         {
01145             // Check the Transparency Type. If it`s a flat fill check to see if the start value
01146             // is zero. if it`s not zero then it`s got transparency!
01147             if(pFillAttrib->IsAFlatFill())
01148             {
01149                 // Only set as Transparent if it`s not NONE!
01150                 m_HasTransparencyApplied = *((AttrFlatTranspFill*)pFillAttrib)->GetStartTransp() > 0;
01151             }
01152             else
01153                 m_HasTransparencyApplied = TRUE;
01154 
01155             if (m_HasTransparencyApplied && pFillAttrib!=NULL && m_pTranspFill!=NULL)
01156                 m_pTranspFill->SetTesselation(((ColourFillAttribute*)pFillAttrib->GetAttributeValue())->GetTesselation());
01157         }
01158         else
01159         {
01160             // Set the flag to false if it doesn`t 
01161             m_HasTransparencyApplied = FALSE;
01162         }
01163     }
01164 
01165     // Only re-render the bitmap if we`re not rotating the light angle, as this has already been
01166     // done for us, or if we`re doing hit testing!
01167     if((!m_DoingRotation && !pRender->IsHitDetect() && pRender->RRQuality.GetQuality() > 10 && !pRender->IsKindOf(CC_RUNTIME_CLASS(ScanningRenderRegion)))
01168         || !m_pBevelBitmap)
01169     {
01170         // check to see if we have changed from a gradfill to a flat fill with transparency as the bitmap will need to be
01171         // updated!
01172         DoReRender |= (m_IsFlatFilledOnly && !LastFillWasFlat && m_HasTransparencyApplied);
01173 
01174         if(pRender->IsPrinting())
01175         {
01176 //          TRACEUSER( "Gerry", _T("Printing Render\n"));
01177             if(!pRender->IsKindOf(CC_RUNTIME_CLASS(ScanningRenderRegion)) && pRender->RRQuality.GetQuality() > 100)
01178             {
01179                 if(m_LastCachedPrintBMPDPI == 0.0)
01180                 {
01181 //                  TRACEUSER( "Gerry", _T("Printing Render Updating\n"));
01182                     m_LastCachedPrintBMPDPI = pBevelController->GetDPI();
01183                     DoReRender = TRUE;
01184                 }
01185             }
01186         }
01187         else
01188             m_LastCachedPrintBMPDPI = 0.0;
01189 
01190         if(m_pBevelBitmap == NULL)
01191             DoReRender = TRUE;
01192 
01193         // re-render the bitmap
01194         if(((MILLIPOINT)m_LastPixelSize != pRender->GetScaledPixelWidth() && !pBevelController->IsPrinting()) || DoReRender)
01195         {
01196             if(pRender->GetScaledPixelWidth() > 2)
01197             {
01198                 m_LastPixelSize = pRender->GetScaledPixelWidth();
01199                 if (!RenderBitmapForDisplay(pRender))
01200                 {
01201                     m_bStopRender = TRUE;
01202                     pRender->RestoreContext();
01203                     return;
01204                 }
01205             }
01206             else if(pRender->IsKindOf(CC_RUNTIME_CLASS(FlashRenderRegion)))
01207             {
01208                 INT32 NewDPI = 96;
01209                 Camelot.GetPrefValue(TEXT("Displays"),TEXT("CompCToEDPI"),&NewDPI);
01210                 pBevelController->SetDPI(NewDPI);
01211 
01212                 BOOL OldFlag = m_AmConvertingToShapes;
01213                 m_AmConvertingToShapes = TRUE;
01214                 CreateBevelBitmap();
01215                 RenderBitmapForDisplay(pRender);
01216                 m_AmConvertingToShapes = OldFlag;
01217             }
01218         }
01219 
01220         // Now set up the palette (depending on contrast)
01221         SetUpBitmapPalette((RenderRegion *)NULL,FillColour);
01222     }
01223 
01224     // (ChrisG - 14/2/2001) Bitmaps should only be drawn if they have height or width 
01225     //  (otherwise GDraw has a fit and crashes).
01226     if (m_BitmapWidth > 0 && m_BitmapHeight > 0)
01227     {
01228         // now, render the bitmap to the display
01229         if(!pRender->IsHitDetect() && pRender->RRQuality.GetQuality() > 30)
01230         {
01231             RenderBitmap(pRender);
01232         }
01233         else
01234         {
01235             // DY 23/10/2000 if we have a brush attribute applied to this bevel then setting line width to 50
01236             // will cause it to scale to a really small value and lock up the program.  Therefore we 
01237             // ask the render region to disable all brush path processors on the stack
01238             
01239             pRender->EnableAllBrushPathProcessors(FALSE);
01240 
01241             pRender->SetLineColour(COLOUR_BLACK);
01242             pRender->SetFillColour(FillColour);
01243             pRender->SetLineWidth(50);
01244 
01245             InkPath.IsStroked = TRUE;
01246             pRender->DrawPath(&InkPath);
01247             InkPath.IsStroked = FALSE;
01248 
01249             // re-enable the path processors
01250             pRender->EnableAllBrushPathProcessors(TRUE);
01251         }
01252     }
01253 
01254     m_bStopRender = TRUE;
01255 
01256     // Reset the Lock Flag
01257     m_bLock = FALSE;
01258 
01259     pRender->RestoreContext();
01260 
01261 //  TRACEUSER( "Gerry", _T("Finished rendering into region 0x%08x\n"),pRender);
01262 }  
01263 
01264 
01265 /********************************************************************************************
01266 >   BOOL NodeBevel::RenderBitmapForDisplay(RenderRegion * pRegion)
01267 
01268     Author:     Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com>
01269     Created:    13/07/00
01270     Inputs:     The render region to be rendered into!
01271     Returns:    TRUE for success, FALSE for Failure!
01272     Purpose:    Creates the Brigtness bitmap for the bevel.
01273 
01274 ********************************************************************************************/
01275 BOOL NodeBevel::RenderBitmapForDisplay(RenderRegion * pRegion)
01276 {
01277     TRACEUSER( "Gerry", _T("NodeBevel::RenderBitmapForDisplay\n"));
01278 
01279     // Get the Bevel Controler
01280     NodeBevelController * pControl = (NodeBevelController *)GetParentController();
01281     
01282     // Make sure we`ve got some valid pointers!
01283     if (pControl == NULL)
01284         return FALSE;
01285 
01286     // (ChrisG - 14/2/2001) If we've got a zero sized (or less) bitmap, get rid of
01287     //  the old beveller and let it try to recreate the bitmap (hopefully at a 
01288     //  friendlier zoom factor).
01289     if (m_pBeveler != NULL)
01290     {
01291         if (m_BitmapHeight < 1 || m_BitmapWidth < 1)
01292         {
01293             delete m_pBeveler;
01294             m_pBeveler = NULL;
01295         }
01296     }
01297 
01298     if (m_pBeveler == NULL)
01299     {
01300         if (!CreateBevelBitmap())
01301             return(FALSE);
01302     }
01303 
01304     if (m_pBevelBitmap)
01305     {
01306         delete m_pBevelBitmap;
01307         m_pBevelBitmap = NULL;
01308     }
01309 
01310     // Save the current Pixel scale
01311     if(pRegion)
01312         m_LastPixelSize = pRegion->GetScaledPixelWidth();
01313 
01314     if (pRegion && pRegion->IS_KIND_OF(PrintingMaskedRenderRegion))
01315         CalculateBitmapSize(&m_BitmapWidth, &m_BitmapHeight, pRegion);
01316     else
01317         CalculateBitmapSize(&m_BitmapWidth, &m_BitmapHeight, NULL);
01318 
01319     // Get the pixel size of the current clipping rect! SHOULD be pixel alligned.
01320     INT32 Width = m_BitmapWidth;
01321     INT32 Height = m_BitmapHeight;
01322 
01323     if (Width == 0 || Height == 0)
01324         return FALSE;
01325 
01326 //  TRACEUSER( "Gerry", _T("Creating bevel bitmap (%d, %d)\n"), Width, Height);
01327 
01328     // Create a new bitmap of the current width and height!
01329     m_pBevelBitmap = new KernelBitmap(Width, Height, 8, 96, TRUE);
01330     ERROR2IF(m_pBevelBitmap == NULL,FALSE,"Failed to create a new bevel bitmap!");
01331 
01332     // Now render the bevel into the new Bevel Bitmap!
01333     m_pBeveler->RenderToBitmap(m_pBevelBitmap, TRUE, &m_SubPixelOffset);
01334 
01335     // If we're going to change the transp fill then the combi
01336     // bitmap will become out of date so uncache it here.
01337     if (m_pCombiBitmap)
01338     {
01339         delete m_pCombiBitmap;
01340         m_pCombiBitmap = NULL;
01341     }
01342 
01343     // Now set the Bitmap Ref to the Bevel Bitmap!
01344     m_pBMPFill->BitmapRef.SetBitmap(m_pBevelBitmap);
01345     m_pTranspFill->BitmapRef.SetBitmap(m_pBevelBitmap);
01346     // Everythings cool, return TRUE!
01347     return TRUE;
01348 }
01349 
01350 /********************************************************************************************
01351 
01352 >   void NodeBevel::RenderBitmap(RenderRegion* pRender)
01353 
01354     Author:     Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com>
01355     Created:    20/07/00
01356     Inputs:     pRender - The render region to use for rendering
01357     Purpose:    Renders the bevel using the bitmap bevelling system
01358 
01359     Function Outline :-
01360     
01361     1. Pass in render region.
01362     2. Check pointers for Region and Bitmap - return if failed.
01363     3. Save Region Context.
01364     4. Get a pointer to the current stroke colour attrib.
01365     5. Get the pointer for the parent bevel controller node.
01366     6. Check pointers for attrib and node - restore contrext and return if failed.
01367     7. Get the DocColour from the stroke attrib.
01368     8. Get the current pixel width from the render region.
01369     9. Get the pointer to the current view.
01370     10. If valid do 11, else goto 26. !!!
01371         11. Test that the current Pixel width is not equal to m_ViewScale,
01372             Test that m_ShrunkPath is not empty,
01373             Test the printing flag in the render region.
01374         12. If any one is true, do 13. else goto 26. !!!
01375             13. Check to see if the bevel is outer or inner.
01376             14. If bevel is inner then do 15, else do 17.
01377                 15. Clear the m_ShrunkPath.
01378                 16. Contour the InkPath out by 1/2 pixel into m_ShrunkPath.
01379             17. Else
01380                 18. Clone m_OuterBevelPath into m_ShrunkPath.
01381                 19. Contour m_Path in by 1/2 pixel into InnerMergePath.
01382                 20. Reverse InnerMergePath and Merge with m_ShrunkPath.
01383                 21. Clone m_ShrunkPath into InkPath.
01384             22. Close m_ShrunkPath.
01385             23. Set Filled and !Stroked
01386             24. If m_bZeroLineWidth is true set the line width to 50.
01387             25. m_VeiwScale = Pixel Width.
01388     26. if m_bZeroLineWidth do 27 else do 28.
01389         27. Set LineColour to NONE.
01390         
01391         28. Set FillColour to BLACK.
01392     29. Render m_ShrunkPath.
01393     30. If Bevel is an inner do 31 else do 35.
01394         31. Create a new winding rule attribute.
01395         32. if pointer is NULL do 33. else do 34.
01396             33. Restore Context and return.
01397         34. Render the new Winding Attrib.
01398     35. create a new AttrFillMappingLinear and set to repeat inverted.
01399     36. Render the new attrib.
01400     37. if m_bZeroLineWidth do 38. else do 40.
01401         38. Set the LineColour to COLOUR_NONE.
01402         39. Set the LineWidth to 50;
01403     40. Check the BMPFill pointer and do 41 if valid else do 44.
01404         41. Set up the fill handles.
01405         42. Set the repeat type to norepeattype.
01406         43. Render the fill into the region.
01407     44. Create a new TransparencyFillAttrib
01408     45. Check the pointer, if valid do 46 else do 50.
01409         46. Set the start transparency to 0.
01410         47. Set the end transparency to 0xff.
01411         48. Set the transparency type to 25 (Brightness)
01412         49. Render the TransparencyFillAttrib into the region.
01413         
01414         50. Restore the Context and return.
01415     51. Render the InkPath.
01416     52. Restore the context and tidy up the pointers
01417     53. return.
01418 
01419 ********************************************************************************************/
01420 void NodeBevel::RenderBitmap(RenderRegion* pRender)
01421 {
01422 //  TRACEUSER( "Gerry", _T("NodeBevel::RenderBitmap\n"));
01423 
01424     // check for valid pointers
01425     if(!pRender)
01426         return;
01427 
01428     // We should always do this so that 0% flat trans bevelled objects get treated
01429     // as transparent by the printing system
01430     // Otherwise we end up trying to generate a 72000 dpi bevel bitmap thanks
01431     // to the ScaledPixelWidth value of PrintPSRenderRegions
01432     if(pRender->IsKindOf(CC_RUNTIME_CLASS(ScanningRenderRegion)))
01433     {
01434         // with blends, we don't have a bitmap because this is generated on the fly
01435         // but a bitmap is NOT generated for a scanning render region ....
01436         ScanningRenderRegion* pScanner = (ScanningRenderRegion*)pRender;
01437         // we MUST force this node to be included
01438         pScanner->ComplexShapeFoundWrapper();
01439         return;
01440     }
01441 
01442     // Check to see if we`ve got a bitmap for rendering!
01443     if(!m_pBevelBitmap)
01444         return;
01445 
01446     // Save the render regions context so we can mess about and restore all at the end
01447     pRender->SaveContext();
01448 
01449     // Get the current Stroke colour and also a pointer to the bevel controller
01450     NodeBevelController* pControl = (NodeBevelController *)GetParentController();
01451 //  NodeAttribute* pFillAttrib = NULL;
01452     FillMappingAttribute FillMapAttrib;
01453     TranspFillMappingAttribute TranspFillMapAttrib;
01454 
01455     // Check for valid pointers
01456     if (pControl == NULL)
01457     {
01458         pRender->RestoreContext();
01459         return;
01460     }
01461 
01462     // first, render the inking path with the current settings no lines needed!
01463     // reduce/extend the ink path slightly to account for antialiasing glitches
01464     // only do this if the view scale has changed or we've re-rendered the bevel
01465     double PixelWidth  = pRender->GetScaledPixelWidth();
01466 
01467     // Get the current View pointer
01468     View* pView = View::GetCurrent();
01469 
01470     // if the view is valid then proceed
01471     if (pView)
01472     {
01473         // If the view scale is diffrent to the Pixel Width OR
01474         // the Shrunk Path is empty OR we are currently printing, then do the following
01475         if (m_ViewScale != PixelWidth || m_ShrunkPath.GetNumCoords() == 0 || pControl->IsPrinting())
01476         {
01477             // If this flag is set then set the line width to 50
01478             if (m_bZeroLineWidth)
01479                 pRender->SetLineWidth(50);
01480             
01481             // Make the viewscale variable equal to the PixelWidth
01482             m_ViewScale = (UINT32)PixelWidth;
01483         }
01484     }
01485 
01486     // if we`re doing an inner bevel then we need to render a Winding Rule Attrib
01487     if (!m_bOuter)
01488     {
01489         // Create a new Winding Rule Attrib
01490 //      pRender->SetWindingRule(PositiveWinding);
01491     }
01492 
01493     // if set, make sure we set the render region to have a line colour of NONE
01494     // and a line width of 50.
01495     if (m_bZeroLineWidth)
01496     {
01497         pRender->SetLineColour(COLOUR_NONE);
01498         pRender->SetLineWidth(50);
01499     }
01500 
01501     if(m_IsFlatFilledOnly) // Flat filled
01502     {
01503 //      TRACEUSER( "Gerry", _T("Flat filled bevel\n"));
01504         // If we`ve got a valid pointer to the bitmap then setup the handles and render into
01505         // the render region
01506         FillMapAttrib.Repeat = 0;
01507         FillMapAttrib.Render(pRender);
01508 
01509         if (m_pBMPFill)
01510         {
01511 //          TRACEUSER( "Gerry", _T("Rendering Bitmap Fill!\n"));
01512             m_pBMPFill->SetStartPoint(&m_BMPCentre);
01513             m_pBMPFill->SetEndPoint  (&m_BMPPoint1);
01514             m_pBMPFill->SetEndPoint2 (&m_BMPPoint2);
01515             m_pBMPFill->Render(pRender);
01516         }
01517         else
01518         {
01519             pRender->RestoreContext();
01520             ERROR1RAW(_R(IDE_NOMORE_MEMORY));
01521         }
01522     }
01523     else if(!m_IsFlatFilledOnly && !m_HasTransparencyApplied) // Bitmap or Gradient Filled
01524     {
01525 //      TRACEUSER( "Gerry", _T("Non-flat non-transp bevel\n"));
01526         // The pointer is valid then do the following
01527         if (m_pTranspFill)
01528         {
01529             TranspFillMapAttrib.Repeat = 0;
01530             TranspFillMapAttrib.Render(pRender);
01531 
01532 //          TRACEUSER( "Gerry", _T("Rendering Transparent Fill\n"));
01533             m_pTranspFill->SetStartPoint(&m_BMPCentre);
01534             m_pTranspFill->SetEndPoint  (&m_BMPPoint1);
01535             m_pTranspFill->SetEndPoint2 (&m_BMPPoint2);
01536             m_pTranspFill->Render(pRender);
01537         }
01538         else
01539         {
01540             pRender->RestoreContext();
01541             ERROR1RAW(_R(IDE_NOMORE_MEMORY));
01542         }
01543     }
01544     else if(!m_IsFlatFilledOnly && m_HasTransparencyApplied)
01545     {
01546 //      TRACEUSER( "Gerry", _T("Non-flat transp bevel\n"));
01547         // Check for the special case of the bevel having a bitmapfill AND a transparency applied
01548         // This is special as we need to use the transparency attribute for the brightness bitmap, therefore
01549         // we need to render the current fill and transparency into a 32Bit bitmap and use this as the bitmap fill
01550         // leaving the transparency attribute free for our brightness bitmap!!!
01551 
01552         // Make sure we have valid pointers before doing anything to it!
01553         if(m_pBMPFill)
01554         {
01555             if(!pRender->IsKindOf(CC_RUNTIME_CLASS(ScanningRenderRegion)))
01556             {
01557                 if(!m_pCombiBitmap)
01558                 {
01559                     // This involves the new technique of creating a new render region whilst still
01560                     // in the rendering loop! Therefore we need to make sure we save the current GDraw Context.
01561 //                  TRACEUSER( "Gerry", _T("Creating a new OffScreen Bitmap!\n"));
01562                     
01563                     // Call the new OffSreen Bitmap Function to get the new 32Bit BMP Fill!
01564                     // Check to see if it actually worked or failed!
01565                     m_pCombiBitmap = CreateCombinedBMPAndTranspFill(pRender);
01566                 }
01567 
01568                 if(m_pCombiBitmap == NULL)
01569                 {
01570                     ERROR3("Failed to create a new BitmapTransparency Bitmap!");
01571                     pRender->RestoreContext();
01572                     return;
01573                 }
01574 
01575                 // Now setup the new Bitmap Fill Attribute and render it into the render region!
01576                 m_pBMPFill->BitmapRef.SetBitmap(m_pCombiBitmap);
01577 
01578                 m_pBMPFill->SetStartPoint(&m_BMPCentre);
01579                 m_pBMPFill->SetEndPoint  (&m_BMPPoint1);
01580                 m_pBMPFill->SetEndPoint2 (&m_BMPPoint2);
01581                 m_pBMPFill->Render(pRender);
01582             }
01583             else
01584             {
01585 //              TRACEUSER( "Gerry", _T("Scanning RR\n"));
01586             }
01587 
01588             FillMapAttrib.Repeat = 0;
01589             FillMapAttrib.Render(pRender);
01590         }
01591         else
01592         {
01593 //          TRACEUSER( "Gerry", _T("No m_pBMPFill\n"));
01594             pRender->RestoreContext();
01595             ERROR1RAW(_R(IDE_NOMORE_MEMORY));
01596         }
01597     }
01598 
01599     // We need to get a bitmap for the fill
01600     if(InkPath.GetNumCoords() > 2)
01601         pRender->DrawPath(&InkPath);
01602 
01603     pRender->RestoreContext();
01604 //  TRACEUSER( "Gerry", _T("End of NodeBevel::RenderBitmap\n"));
01605 }
01606 
01607 /********************************************************************************************
01608 
01609 >   KernelBitmap* CreateCombinedBMPAndTranspFill(RenderRegion* pRegion = NULL)
01610 
01611     Author:     Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com>
01612     Created:    20/07/00
01613     Inputs:     pRegion - The render region to use for rendering
01614     return:     An OIL Bitmap pointer of the new Bitmap!
01615     Purpose:    Creates a new 32Bit Bitmap to hold the combined Transp & Bitmap Fill Attributes.
01616 
01617 ***********************************************************************************************/
01618 KernelBitmap* NodeBevel::CreateCombinedBMPAndTranspFill(RenderRegion* pRegion)
01619 {
01620     // Get the current view pointer
01621     View* pView = View::GetCurrent();
01622 
01623     // check the passed in pointer and view pointer
01624     if(pRegion == NULL || pView == NULL)
01625         return NULL;
01626 
01627     // Create a local OILBitmap pointer ready to hold the new BMP
01628     // Now we want a 32Bit BMP so lets setup a render region!
01629     KernelBitmap* pNewBMP = NULL;
01630 
01631     // Get the current pixel width as a scale value.
01632     double GScale = 1.0;
01633     double SPW = pRegion->GetScaledPixelWidth();
01634 //  TRACEUSER( "Gerry", _T("ScaledPixelWidth = %g\n"), SPW);
01635 
01636     // Do a quick check to make sure we don`t get any funny values!
01637     // 0 will obviously crash the dive later on!
01638     // Anything above 3750 will result in a scale factor of less than 0.2 and as this only happens
01639     // at zoom factors of 50% or less, we might as well leave the quality at a higher value as the 
01640     // bitmaps will be very small anyway!
01641     if(SPW <= 0.0 || SPW > 3750.0)
01642         SPW = 3750.0;
01643 
01644 //  TRACEUSER( "Gerry", _T("Using ScaledPixelWidth = %g\n"), SPW);
01645 
01646     DocRect RRect(m_BMPPoint2.x,m_BMPPoint1.y,m_BMPPoint1.x,m_BMPPoint2.y);// = m_PixelAllignedRect;
01647 
01648     // Get the Pixel Width and Height using the scaled pixel width.
01649     double ScaledWidth = (double)RRect.Width() / SPW;
01650     double ScaledHeight = (double)RRect.Height() / SPW;
01651 
01652 //  TRACEUSER( "Gerry", _T("scaled size (%g, %g)\n"), ScaledWidth, ScaledHeight);
01653 
01654     // Check to see if we`ve gone over the bounds!
01655     if((ScaledWidth > BevelMaxBitmapWidth) || (ScaledHeight > BevelMaxBitmapHeight))
01656     {
01657         // See which is the greater error
01658         if((BevelMaxBitmapWidth / ScaledWidth) >= (BevelMaxBitmapHeight / ScaledHeight))
01659         {
01660             // WIDTH
01661             SPW = 750.0 / (BevelMaxBitmapWidth / ScaledWidth);
01662             GScale = BevelMaxBitmapWidth / ScaledWidth;
01663         }
01664         else
01665         {
01666             // HEIGHT
01667             SPW = 750.0 / (BevelMaxBitmapHeight / ScaledHeight);
01668             GScale = BevelMaxBitmapHeight / ScaledHeight;
01669         }
01670 
01671 //      TRACEUSER( "Gerry", _T("Using changed ScaledPixelWidth = %g\n"), SPW);
01672     }
01673 
01674 // This GScale stuff causes problems and this routine should always create
01675 // a bitmap of the same size as the source bitmaps so it will always use 1.0
01676 // Gerry 22/06/2004
01677 #if FALSE
01678     // Get a pointer to the controller node!
01679     NodeBevelController * pControl = (NodeBevelController *)FindParent();
01680     if(pControl && pRegion->IsPrinting())
01681     {
01682         GScale = 96;
01683 
01684         Document* pDoc = pView->GetDoc();
01685 
01686         PrintComponent *pPrintComponent = (PrintComponent *)pDoc->GetDocComponent(CC_RUNTIME_CLASS(PrintComponent));
01687         if(pPrintComponent)
01688         {
01689             PrintControl *pPrintControl = pPrintComponent->GetPrintControl();
01690             if(pPrintControl)
01691                 GScale = 1.0 * pPrintControl->GetDotsPerInch() / 96.0;
01692         }
01693     }
01694     else
01695     {
01696         GScale = 750.0 / SPW;
01697 
01698         if(GScale > 1.0)
01699             GScale = 1.0;
01700     }
01701 #endif
01702 
01703 //  TRACEUSER( "Gerry", _T("GScale = %g\n"), GScale);
01704 
01705     // Now Expand the Path by 1 Pixel!
01706     Path InflatePath;
01707     InflatePath.Initialise();
01708     InflatePath.CreatePathFromDocRect(&RRect);
01709 
01710     // Get the Current Applied Fill from the bevel.
01711     NodeAttribute * pFillAttr = NULL;
01712     FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry),&pFillAttr);
01713 
01714     // Get the Current Applied MappingFill from the bevel.
01715     NodeAttribute * pFillMapAttr = NULL;
01716     FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillMapping),&pFillMapAttr);
01717 
01718     BOOL bOldForce = pView->SetForceDefaultColourContexts();
01719 
01720     // We need to save the current GDraw Context before we try to setup a new region!
01721     ConcurrentRenderer* pGOffScreen = new ConcurrentRenderer;
01722     if (pGOffScreen == NULL)
01723     {
01724         pView->SetForceDefaultColourContexts(bOldForce);
01725         ERROR2(NULL, "Failed to create a new Borrower Class!");
01726     }
01727 
01728     // (ChrisG 8/5/2001) Try to initialise the context. If this fails, then we won't 
01729     //  have a bitmap to render things into, so we can't do a lot else.
01730     if (pGOffScreen->Initialise((GRenderRegion*)pRegion, GScale, RRect, 32, TRUE))
01731     {       
01732         GRenderRegion* pGBMP = pGOffScreen->GetRenderRegion();
01733 
01734         // Now make sure the pointer is valid!
01735         if(pGBMP)
01736         {
01737             pGBMP->GetDrawContext()->SetAntialiasFlag(0);
01738 
01739             // If found, render the current Fill Attribute
01740             if(pFillAttr)
01741                 pFillAttr->Render(pGBMP);
01742 
01743             if(pFillMapAttr)
01744                 pFillMapAttr->Render(pGBMP);
01745 
01746             pGBMP->SetLineColour(COLOUR_NONE);
01747             pGBMP->SetLineWidth(50);
01748 
01749             if (m_pTranspFill)
01750             {
01751                 TRACEUSER( "MarkH", _T("Rendering Transparent Fill!\n"));
01752                 m_pTranspFill->SetStartPoint(&m_BMPCentre);
01753                 m_pTranspFill->SetEndPoint  (&m_BMPPoint1);
01754                 m_pTranspFill->SetEndPoint2 (&m_BMPPoint2);
01755                 m_pTranspFill->Render(pGBMP);
01756             }
01757 
01758             // We need to render the bevel object with the current attributes into the new region!
01759             pGBMP->DrawPath(&InflatePath);
01760 
01761             // NewBMP Now needs to be setup with the newly created bitmap
01762             pNewBMP = pGOffScreen->GetKernelBitmap();
01763 
01764 //          TRACEUSER( "Gerry", _T("Created combined bitmap (%d, %d)\n"), pNewBMP->GetWidth(), pNewBMP->GetHeight());
01765         }
01766         else
01767         {
01768             ERROR3("Failed to create a new GRenderBitmap!");
01769         }
01770 
01771         // Now restore the original render region!
01772         pGOffScreen->RestorePreviousRendererState();
01773     }
01774     else
01775     {
01776         // Initialise failed and we don't have a bitmap to give back, so clean up and give 
01777         //  nothing back.
01778         delete pGOffScreen;
01779         pNewBMP = NULL;
01780     }
01781 
01782     pView->SetForceDefaultColourContexts(bOldForce);
01783 
01784     // Return the new Pointer
01785     return pNewBMP;
01786 }
01787 
01788 /***********************************************************************************************
01789 
01790 >   void NodeBevel::CalculateBitmapSize(INT32 * retnWid,  INT32 * retnHei, RenderRegion * pRegion)
01791 
01792     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
01793     Created:    7/10/98
01794     Inputs:     Return pointers for witdth & height
01795     Purpose:    Calculates the width and the height for the bitmap depending on what's in m_Path
01796 
01797 ***********************************************************************************************/
01798 void NodeBevel::CalculateBitmapSize(INT32 * retnWid,  INT32 * retnHei, RenderRegion * pRegion)
01799 {
01800     // Get a pointer to the controller node!
01801     NodeBevelController * pControl = (NodeBevelController *)FindParent();
01802 
01803     // Check that all the pointers are valid!
01804     if(!retnWid || !retnHei || !pControl)
01805         return;
01806 
01807     // Get the bounding rect of the bevel!
01808     DocRect dr(0,0,0,0);
01809 
01810     // If it`s an outer then get the bounds that gavin creates when he generates his trap list!
01811     if(m_bOuter)
01812     {
01813         if(m_pBeveler)
01814             dr = m_pBeveler->GetSelectionRect();
01815         else
01816         {
01817             InkPath.GetTrueBoundingRect(&dr);
01818             dr.Inflate(m_Indent);
01819         }
01820     }
01821     else
01822     {
01823         // If it`s an inner then just get the bounds of the object and not the bevel path
01824         m_Path.GetTrueBoundingRect(&dr);
01825     }
01826 
01827     // Make sure we check to see if the returned rect is not empty!
01828     if (dr.IsEmpty())
01829     {
01830         *retnWid = 0;
01831         *retnHei = 0;
01832         return;
01833     }
01834 
01835     MILLIPOINT PixSize = 750;
01836     
01837     if(pRegion)
01838         PixSize = pRegion->GetScaledPixelWidth();
01839 
01840     if(Document::GetCurrent() && Document::GetCurrent()->GetFirstDocView()
01841              && !(pRegion && pRegion->IS_KIND_OF(PrintingMaskedRenderRegion))
01842         )
01843         PixSize = (MILLIPOINT)((double)PixSize / (Document::GetCurrent()->GetFirstDocView())->GetViewScale().MakeDouble());
01844     
01845     if(PixSize == 0)
01846         PixSize = 1;
01847 
01848     m_PixelAllignedRect = dr;
01849     double lWidth  = dr.Width() / PixSize;
01850     double lHeight = dr.Height() / PixSize;
01851     
01852     // Check to see if we`re not printing and then Scale up the values!
01853     if ((!pControl->IsPrinting() && !m_AmConvertingToShapes) ||
01854         (pRegion && pRegion->IS_KIND_OF(PrintingMaskedRenderRegion)))
01855     {
01856         // If the current render regions scale value is greater than 0 do the following
01857         if (pRegion && PixSize > 0 )
01858         {
01859             lWidth = (lWidth * 750) / PixSize;
01860             lHeight = (lHeight * 750) / PixSize;
01861         }
01862         
01863         // Make sure the values are under the maximum values!
01864         while ( lWidth  > BevelMaxBitmapWidth || lHeight > BevelMaxBitmapHeight )
01865         {
01866             // Divide them by a half!
01867             lWidth *= 0.5;
01868             lHeight *= 0.5;
01869         }
01870     }
01871     else
01872     {
01873         double DPI = pControl->GetDPI();
01874         lWidth  = dr.Width () * DPI / 72000 ;
01875         lHeight = dr.Height() * DPI / 72000 ;
01876     }
01877 
01878     // Now place the new values into the passed in variables
01879     *retnWid = (INT32)ceil(lWidth);
01880     *retnHei = (INT32)ceil(lHeight);
01881 }
01882 
01883 /***********************************************************************************************
01884 
01885 >   void NodeBevel::SetUpBitmapPalette(RenderRegion * pRegion)
01886 
01887     Author:     Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com> - Rewrite of David Mc code
01888     Created:    19/07/00
01889     Inputs:     Currently a pointer to a render region, But is not used.
01890     Purpose:    Sets up the bitmap palette depending on contrast setting
01891 
01892 ***********************************************************************************************/
01893 void NodeBevel::SetUpBitmapPalette(RenderRegion * pRegion, DocColour FlatColour)
01894 {
01895     // Check the Bevel Bitmap Pointer
01896     if (!m_pBevelBitmap)
01897         return;
01898     
01899     // Check that the Bitmap is an 8Bit BMP
01900     if (m_pBevelBitmap->GetBPP() != 8)
01901         return;
01902 
01903     // Setup a few local variables
01904     LPRGBQUAD pPalette = m_pBevelBitmap->GetPaletteForBitmap();
01905     INT32 Red = 0;
01906     INT32 Green = 0;
01907     INT32 Blue = 0;
01908 
01909     // Get the pointer to the parent controller and check it
01910     NodeBevelController* pControl = (NodeBevelController *)FindParent();
01911     ERROR3IF(pControl == NULL, "No parent");
01912 
01913     // Get the contrst value from the controller
01914     double Contrast = pControl->m_Contrast;
01915 
01916     // The following if statment never gets called as the pointer is always NULL
01917     if ( pRegion )
01918     {
01919         // find out the contrast first
01920         BevelAttributeValueContrast *pVal = (BevelAttributeValueContrast *)pRegion->GetCurrentAttribute(ATTR_BEVELCONTRAST);
01921         if (!pVal)
01922             return;
01923         Contrast = pVal->m_Contrast;
01924     }
01925 
01926     GDrawContext* pGD = GRenderRegion::GetStaticDrawContext();
01927     pGD->SetBevelLightness(UINT32(         Contrast*2.5599900)) ;
01928     pGD->SetBevelDarkness (UINT32(Contrast*Contrast*0.0255999)) ;
01929 
01930     // Get the component parts of the FillColour
01931     FlatColour.GetRGBValue(&Red,&Green,&Blue);
01932 
01933     // Now setup the palette of 255 grey scales OR if the bevel is flat filled and NOT transparent
01934     // then the palette is translated using the flat fill colour
01935     for ( INT32 i=0 ; i<256 ; i++ )
01936     {
01937         if(!m_IsFlatFilledOnly)
01938         {
01939             // Normal Brightness grey scales
01940             pPalette[i].rgbRed   =
01941             pPalette[i].rgbBlue  =
01942             pPalette[i].rgbGreen = i ;
01943         }
01944         else
01945         {
01946             // Translated colour table values used ONLY for Non Transparent Flat filled Bevels
01947             pPalette[i].rgbRed   = pGD->TranslateBevelValue(i,Red  ) ;
01948             pPalette[i].rgbGreen = pGD->TranslateBevelValue(i,Green) ;
01949             pPalette[i].rgbBlue  = pGD->TranslateBevelValue(i,Blue ) ;
01950         }
01951         pPalette[i].rgbReserved = 0 ;
01952     }
01953 }
01954 
01955 /********************************************************************************************
01956 
01957 >   KernelBitmap* CreateBitmapCopy(double DPI = -1.0, BOOL CheckFillFlags = TRUE);
01958 
01959     Author:     Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com>
01960     Created:    07/12/00
01961     Inputs:     DPI to render with, if this is -1.0 the code will find the options value.
01962                 CheckFillFlags when TRUE will use the member variable flags to decide what
01963                 to render. FALSE render it anyway.
01964     Purpose:    Creates a BitmapCopy of the Bevel Bitmap including the current fills and
01965                 transparency settings generated at the given DPI!
01966 
01967 ********************************************************************************************/
01968 KernelBitmap* NodeBevel::CreateBitmapCopy(double DPI, BOOL CheckFillFlags)
01969 {
01970     m_AmConvertingToShapes = TRUE;
01971 
01972     NodeBevelController* pControl = (NodeBevelController *)FindParent();
01973     
01974     INT32 NewDPI = 96;
01975     if(pControl && DPI == -1.0)
01976     {
01977         View* pView = View::GetCurrent();
01978         if (pView)
01979             NewDPI = (INT32)pView->GetConvertToEditableShapesDPI();
01980     }
01981     else
01982         NewDPI = (INT32)DPI;
01983 
01984     if(pControl)
01985         pControl->SetDPI(NewDPI);
01986 
01987     // The bitmap has not been rendered at this stage so we need to call the
01988     // appropriate render function!
01989     ERROR2IF(!RenderBitmapForDisplay(NULL),FALSE,"Failed to create the bevel bitmap!");
01990 
01991     NodeAttribute* pFillAttrib = NULL;
01992     NodeAttribute* pFillMapAttr = NULL;
01993     NodeAttribute* pFillTranspMapAttr = NULL;
01994     NodeAttribute* pFillEffectAttr = NULL;
01995     DocColour FillColour = COLOUR_BLACK;
01996 
01997     // Get the Current Applied MappingFill from the bevel.
01998     FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillMapping),&pFillMapAttr);
01999     FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillMapping),&pFillTranspMapAttr);
02000     FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillEffect),&pFillEffectAttr);
02001 
02002     // Test to see if theres a FillGeom Attribute applied to the bevel
02003     if(FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry),&pFillAttrib))
02004     {
02005         // If the pointer is valid and It`s a flat fill then get the colour and set the IsFlatFill Flag
02006         if(pFillAttrib != NULL && pFillAttrib->IsAFlatFill())
02007             FillColour = *((AttrFlatColourFill*)pFillAttrib)->GetStartColour();
02008     }
02009 
02010     // make sure the palette is setup ready for the BMP
02011     SetUpBitmapPalette((RenderRegion *)NULL,FillColour);
02012 
02013     KernelBitmap* pConvertedBMP = NULL;
02014     
02015     // We now need to check to see if we`re a Fourth state bevel, in which case we need to
02016     // Create a new fill bitmap using the current Bevel Bitmap!
02017     if(!m_IsFlatFilledOnly && (m_HasTransparencyApplied || !CheckFillFlags))
02018     {
02019         // Ok, Lets setup a few variables need to create the new BMP
02020         View*   pView = View::GetCurrent();
02021         Matrix  Mat(1,0,0,1,0,0);
02022         FIXED16 Scale = 1;
02023         DocRect RenderRect(m_BMPPoint2.x,m_BMPPoint1.y,m_BMPPoint1.x,m_BMPPoint2.y);
02024         Path InflatePath;
02025         InflatePath.Initialise();
02026         InflatePath.CreatePathFromDocRect(&RenderRect);
02027         
02028         // Check to see if we`ve got an empty rect if so then return NULL!
02029         ERROR2IF(RenderRect.IsEmpty(),NULL,"We`ve got an empty DocRect in the selection! (CBMPBits)");
02030 
02031         // Create a new GRenderBitmap region
02032         GRenderBitmap* pGBMP = new GRenderBitmap(RenderRect, Mat, Scale, 32, NewDPI, FALSE, 0, NULL, TRUE);
02033 
02034         if(pGBMP)
02035         {
02036             pGBMP->m_DoCompression = TRUE;
02037             
02038             if(!pGBMP->AttachDevice(pView, NULL, NULL))
02039             {
02040                 delete pGBMP;
02041                 pGBMP = NULL;
02042             }
02043             else
02044             {
02045                 // Get the Current Applied Fill from the bevel.
02046                 NodeAttribute * pFillAttr = NULL;
02047                 FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry),&pFillAttr);
02048 
02049                 pGBMP->InitDevice();
02050                 pGBMP->InitAttributes();
02051                 pGBMP->RRQuality.SetQuality(QUALITY_MAX);
02052                 pGBMP->SetQualityLevel();
02053                 pGBMP->SetLineAttributes();
02054                 pGBMP->SetFillAttributes();
02055 
02056                 pGBMP->StartRender();
02057 
02058                 pGBMP->GetDrawContext()->SetAntialiasFlag(0);
02059 
02060                 // If found, render the current Fill Attribute
02061                 if(pFillAttr)
02062                     pFillAttr->Render(pGBMP);
02063 
02064                 if(pFillMapAttr)
02065                     pFillMapAttr->Render(pGBMP);
02066 
02067                 if(pFillEffectAttr)
02068                     pFillEffectAttr->Render(pGBMP);
02069 
02070                 pGBMP->SetLineColour(COLOUR_NONE);
02071                 pGBMP->SetLineWidth(50);
02072 
02073                 if (m_pTranspFill)
02074                 {
02075                     TRACEUSER( "MarkH", _T("Rendering Transparent Fill!\n"));
02076                     m_pTranspFill->SetStartPoint(&m_BMPCentre);
02077                     m_pTranspFill->SetEndPoint  (&m_BMPPoint1);
02078                     m_pTranspFill->SetEndPoint2 (&m_BMPPoint2);
02079                     m_pTranspFill->Render(pGBMP);
02080                 }
02081 
02082                 // We need to render the bevel object with the current attributes into the new region!
02083                 pGBMP->DrawPath(&InflatePath);
02084             
02085                 pGBMP->StopRender();
02086 
02087                 pConvertedBMP = new KernelBitmap(pGBMP->ExtractBitmapCopy());
02088                 delete pGBMP;
02089                 pGBMP = NULL;
02090             }
02091         }
02092     }
02093     else
02094     {
02095         // Now make a copy of the bevel bitmap!
02096         pConvertedBMP = new KernelBitmap(m_pBevelBitmap->ActualBitmap->MakeCopy());
02097     }
02098 
02099     return pConvertedBMP;
02100 }
02101 
02102 /********************************************************************************************
02103 
02104 >   BOOL NodeBevel::DoBecomeA(BecomeA* pBecomeA);
02105 
02106     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02107     Created:    26/2/99
02108     Inputs:     BecomeA struct
02109     Purpose:    Converts me to a path
02110     SeeAlso:    
02111 
02112 ********************************************************************************************/
02113 BOOL NodeBevel::DoBecomeA(BecomeA* pBecomeA)
02114 {
02115     // Check for a NULL entry param                            
02116     ERROR2IF_PF(pBecomeA == NULL,FALSE,("pBecomeA is NULL"));
02117 
02118     if (!pBecomeA->BAPath())
02119         return FALSE;
02120 
02121     // This lump checks that the Reason is one that we understand
02122     // It also makes sure that we don't have a NULL UndoOp ptr
02123     BOOL ValidReason = (pBecomeA->GetReason() == BECOMEA_REPLACE || pBecomeA->GetReason() == BECOMEA_PASSBACK);
02124     ERROR2IF_PF(!ValidReason,FALSE,("Unkown BecomeA reason %d",pBecomeA->GetReason()));
02125 
02126     NodePath                * pNewNodePath      = NULL;
02127     Node                    * pBevelStartNode   = NULL;
02128     NodeRenderableInk       * pParent           = NULL;
02129     NodeHidden              * pHiddenNode       = NULL;
02130     NodeAttribute           * pAttr             = NULL;
02131 //  NodeAttribute           * pAttrT            = NULL;
02132 //  AttrStrokeTransp        * pStrokeColour1    = NULL;
02133 //  BitmapFillAttribute     * pBitmapFill       = NULL;
02134 //  AttrFillMappingLinear   * pFillMapping      = NULL;
02135     AttrStrokeColour        * pStrokeColour     = NULL;
02136     AttrLineWidth           * pLineWidth        = NULL;
02137     
02138     NodeAttribute* pFillMapAttr = NULL;
02139     NodeAttribute* pFillTranspMapAttr = NULL;
02140     NodeAttribute* pFillEffectAttr = NULL;
02141     
02142 //  UINT32 startTrans = 0x00;
02143 //  UINT32 endTrans = 0xff;
02144 
02145     DocColour dcNone(COLOUR_NONE);
02146 
02147     switch (pBecomeA->GetReason())
02148     {
02149     case BECOMEA_REPLACE:
02150         {
02151             // Mark Howitt 15/08/00 - Rewrite of david code!!!!
02152             // What we need to do here is be quite warry of the current set up of our bevels!! There are four types we can
02153             // have which are as follows...
02154             //
02155             // 1. Flat filled bevel NO transparency. This type is as with all the others is made up of just one
02156             // shape that just has a bitmap fill of the bevel.
02157             // 2. Flat filled WITH transparency. As type 1 but with the transparency applied as normal.
02158             // 3. NON Flat fill NO transparency. This type has the bevel bitmap as a transparency bitmap fill with applied
02159             // NON flat fill as normal.
02160             // 4. NON Flat filled WITH Transparency. NOTE! These are a special case as both the transparent and normal fill
02161             // attributes are already taken! In this case there is an off screen Bitmap render of the normal fill and the bevel bitmap
02162             // as a tranparency ( Not the applied transparency ) which replaces the normal fill. This means the bevel bitmap
02163             // is merged into the original fill to make a new one( 32Bit Alpha Channeled!!!) The Original transparency is rendered
02164             // as normal!
02165             // 
02166             // As you can see we`ve got 4 cases that are different and will need to be converted in different ways!
02167             // The main variables which decide the the current state are...
02168             // m_IsFlatFilledOnly - which tells you wether you`ve got just a flat fill attribute.
02169             // m_HasTransparencyApplied - which indicates wether there is any transparency applied.
02170             // therefore the states match up as follows...
02171             //
02172             // 1. m_IsFlatFilledOnly && !m_HasTransparencyApplied
02173             // 2. m_IsFlatFilledOnly && m_HasTransparencyApplied
02174             // 3. !m_IsFlatFilledOnly && !m_HasTransparencyApplied
02175             // 4. !m_IsFlatFilledOnly && m_HasTransparencyApplied
02176 
02177             // CGS:  actually this is more complex - because we can have ilans wonderful feathers knocking
02178             // around in here !!!!  I have decided that the best way to account for this is to check for
02179             // the feather attribute directly within each of marks four cases ....
02180 
02181             // First things first, lets make a new NodePath to hold all the bevel info!
02182             // Get a pointer to the undo op and create a new path undoably!
02183             UndoableOperation* pOp = pBecomeA->GetUndoOp();
02184             ALLOC_WITH_FAIL(pNewNodePath, new NodePath, pOp); 
02185 /*
02186             NodeAttribute* pFillAttrib = NULL;
02187             DocColour FillColour = COLOUR_BLACK;
02188 
02189             // Get the Current Applied MappingFill from the bevel.
02190             FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillMapping),&pFillMapAttr);
02191             FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillMapping),&pFillTranspMapAttr);
02192             FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillEffect),&pFillEffectAttr);
02193 
02194             // Test to see if theres a FillGeom Attribute applied to the bevel
02195             if(FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry),&pFillAttrib))
02196             {
02197                 // If the pointer is valid and It`s a flat fill then get the colour and set the IsFlatFill Flag
02198                 if(pFillAttrib != NULL && pFillAttrib->IsAFlatFill())
02199                     FillColour = *((AttrFlatColourFill*)pFillAttrib)->GetStartColour();
02200             }
02201 
02202             // make sure the palette is setup ready for the BMP
02203             SetUpBitmapPalette((RenderRegion *)NULL,FillColour);
02204 
02205             KernelBitmap* pConvertedBMP = NULL;
02206             
02207             // We now need to check to see if we`re a Fourth state bevel, in which case we need to
02208             // Create a new fill bitmap using the current Bevel Bitmap!
02209             if(!m_IsFlatFilledOnly && m_HasTransparencyApplied)
02210             {
02211                 // Ok, Lets setup a few variables need to create the new BMP
02212                 View*   pView = View::GetCurrent();
02213                 Matrix  Mat(1,0,0,1,0,0);
02214                 FIXED16 Scale = 1;
02215                 DocRect RenderRect(m_BMPPoint2.x,m_BMPPoint1.y,m_BMPPoint1.x,m_BMPPoint2.y);
02216                 Path InflatePath;
02217                 InflatePath.Initialise();
02218                 InflatePath.CreatePathFromDocRect(&RenderRect);
02219                 
02220                 // Check to see if we`ve got an empty rect if so then return NULL!
02221                 ERROR2IF(RenderRect.IsEmpty(),NULL,"We`ve got an empty DocRect in the selection! (CBMPBits)");
02222 
02223                 // Create a new GRenderBitmap region
02224                 GRenderBitmap* pGBMP = new GRenderBitmap(RenderRect, Mat, Scale, 32, DPI, FALSE, 0, NULL, TRUE);
02225 
02226                 if(pGBMP)
02227                 {
02228                     pGBMP->m_DoCompression = TRUE;
02229                     
02230                     if(!pGBMP->AttachDevice(pView, NULL, NULL))
02231                     {
02232                         delete pGBMP;
02233                         pGBMP = NULL;
02234                     }
02235                     else
02236                     {
02237                         // Get the Current Applied Fill from the bevel.
02238                         NodeAttribute * pFillAttr = NULL;
02239                         FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry),&pFillAttr);
02240 
02241                         pGBMP->InitDevice();
02242                         pGBMP->InitAttributes();
02243                         pGBMP->RRQuality.SetQuality(QUALITY_MAX);
02244                         pGBMP->SetQualityLevel();
02245                         pGBMP->SetLineAttributes();
02246                         pGBMP->SetFillAttributes();
02247 
02248                         pGBMP->StartRender();
02249 
02250                         pGBMP->GetDrawContext()->SetAntialiasFlag(0);
02251 
02252                         // If found, render the current Fill Attribute
02253                         if(pFillAttr)
02254                             pFillAttr->Render(pGBMP);
02255 
02256                         if(pFillMapAttr)
02257                             pFillMapAttr->Render(pGBMP);
02258 
02259                         if(pFillEffectAttr)
02260                             pFillEffectAttr->Render(pGBMP);
02261 
02262                         pGBMP->SetLineColour(COLOUR_NONE);
02263                         pGBMP->SetLineWidth(50);
02264 
02265                         if (m_pTranspFill)
02266                         {
02267                             TRACEUSER( "MarkH", _T("Rendering Transparent Fill!\n"));
02268                             m_pTranspFill->SetStartPoint(&m_BMPCentre);
02269                             m_pTranspFill->SetEndPoint  (&m_BMPPoint1);
02270                             m_pTranspFill->SetEndPoint2 (&m_BMPPoint2);
02271                             m_pTranspFill->Render(pGBMP);
02272                         }
02273 
02274                         // We need to render the bevel object with the current attributes into the new region!
02275                         pGBMP->DrawPath(&InflatePath);
02276                     
02277                         pGBMP->StopRender();
02278 
02279                         pConvertedBMP = new KernelBitmap(pGBMP->ExtractBitmapCopy());
02280                         delete pGBMP;
02281                         pGBMP = NULL;
02282                     }
02283                 }
02284             }
02285             else
02286             {
02287                 // Now make a copy of the bevel bitmap!
02288                 pConvertedBMP = new KernelBitmap(m_pBevelBitmap->ActualBitmap->MakeCopy());
02289             }
02290 */
02291             // If the path to be bevelled has no points then don't insert anything to replace this node
02292             BOOL bCreateNew = (m_Path.GetNumCoords() != 0);
02293 
02294             KernelBitmap* pConvertedBMP = NULL;
02295 
02296             if (bCreateNew)
02297             {
02298                 pConvertedBMP = CreateBitmapCopy();
02299                 
02300                 if(!pConvertedBMP)
02301                 {
02302                     ERROR3("Failed To Create Bevel Bitmap Copy!");
02303                     return FALSE;
02304                 }
02305                 else
02306                 {
02307                     NodeCompound* pControl = GetParentController();
02308                     if (pControl != NULL)
02309                     {
02310                         LPBITMAPINFOHEADER pBevelHeader = pConvertedBMP->GetBitmapInfoHeader();
02311                         const double PixPerMetre = pControl->GetDPI() * INCHES_PER_METRE;
02312                         pBevelHeader->biXPelsPerMeter = pBevelHeader->biYPelsPerMeter = (INT32)(PixPerMetre + 0.5);
02313                     }
02314 
02315                     pConvertedBMP->Attach(Document::GetCurrent()->GetBitmapList());
02316                 }
02317 
02318                 // Now delete the bevel bitmap as when undoing it will automatically be recreated!
02319                 if(m_pBevelBitmap)
02320                 {
02321                     delete m_pBevelBitmap;
02322                     m_pBevelBitmap = NULL;
02323                 }
02324 
02325                 // Make sure that our fill attributes reference the new bitmap!
02326                 m_pBMPFill->BitmapRef.SetBitmap(pConvertedBMP);
02327                 m_pTranspFill->BitmapRef.SetBitmap(pConvertedBMP);
02328 
02329                 if (m_pCombiBitmap)
02330                 {
02331                     delete m_pCombiBitmap;
02332                     m_pCombiBitmap = NULL;
02333                 }
02334 
02335                 m_pBMPFill->SetStartPoint(&m_BMPCentre);
02336                 m_pBMPFill->SetEndPoint(&m_BMPPoint1);
02337                 m_pBMPFill->SetEndPoint2(&m_BMPPoint2);
02338 
02339                 m_pTranspFill->SetStartPoint(&m_BMPCentre);
02340                 m_pTranspFill->SetEndPoint(&m_BMPPoint1);
02341                 m_pTranspFill->SetEndPoint2(&m_BMPPoint2);
02342 
02343                 // Copy the current bevel path into the new path with flattening
02344                 pNewNodePath->InkPath.Initialise();
02345                 pNewNodePath->InkPath.CloneFrom(InkPath);
02346                 pNewNodePath->InkPath.IsFilled = TRUE;
02347                 pNewNodePath->InkPath.TryToClose();
02348                 pNewNodePath->InkPath.InitialiseFlags();
02349 
02350                 // Make sure that we copy across the Feather attribute if there`s one there!
02351                 if(FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFeather),&pAttr))
02352                     pAttr->CopyNode(pNewNodePath, FIRSTCHILD);
02353 
02354                 // First state check
02355                 if(m_IsFlatFilledOnly && !m_HasTransparencyApplied)
02356                 {
02357                     // STATE 1
02358                     if(m_pBMPFill)
02359                     {
02360                         // Make sure the Fill attributes point to the new bitmap!
02361                         pAttr = m_pBMPFill->MakeNode();
02362                         pAttr->AttachNode(pNewNodePath,FIRSTCHILD);
02363                     }
02364                 }
02365                 else if((m_IsFlatFilledOnly && m_HasTransparencyApplied) || (!m_IsFlatFilledOnly && m_HasTransparencyApplied))
02366                 {   
02367                     // STATE 2 OR STATE 4
02368                     if(FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillGeometry),&pAttr))
02369                         pAttr->CopyNode(pNewNodePath, FIRSTCHILD);
02370 
02371                     if(m_pBMPFill)
02372                     {
02373                         // Make sure the Fill attributes point to the new bitmap!
02374                         pAttr = m_pBMPFill->MakeNode();
02375                         pAttr->AttachNode(pNewNodePath,FIRSTCHILD);
02376                     }
02377                 }
02378                 else
02379                 {
02380                     // STATE 3
02381                     if(FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry),&pAttr))
02382                         pAttr->CopyNode(pNewNodePath, FIRSTCHILD);
02383 
02384                     if(m_pTranspFill)
02385                     {
02386                         // Make sure the Fill attributes point to the new bitmap!
02387                         pAttr = m_pTranspFill->MakeNode();
02388                         pAttr->AttachNode(pNewNodePath,FIRSTCHILD);
02389                     }
02390                 }
02391 
02392                 // Make sure the line width is none as they shouldn`t have outlines!
02393                 ALLOC_WITH_FAIL(pLineWidth, new AttrLineWidth, pOp);
02394                 pLineWidth->Value.LineWidth = 50;
02395                 pLineWidth->AttachNode(pNewNodePath, FIRSTCHILD);
02396 
02397                 // Also make the line colour NONE
02398                 ALLOC_WITH_FAIL(pStrokeColour, new AttrStrokeColour, pOp);
02399                 pStrokeColour->SetStartColour(&dcNone);
02400                 pStrokeColour->AttachNode(pNewNodePath, FIRSTCHILD);
02401 
02402                 if(pFillMapAttr)
02403                     pFillMapAttr->CopyNode(pNewNodePath,FIRSTCHILD);
02404 
02405                 if(pFillTranspMapAttr)
02406                     pFillTranspMapAttr->CopyNode(pNewNodePath,FIRSTCHILD);
02407 
02408                 if(pFillEffectAttr)
02409                     pFillEffectAttr->CopyNode(pNewNodePath,FIRSTCHILD);
02410 
02411             }
02412 
02413             m_AmConvertingToShapes = FALSE;
02414 
02415             // hide the bevel start node & me and
02416             // insert the ink path node
02417             pParent = (NodeRenderableInk *)FindParent();
02418             
02419             if (pParent)
02420             {
02421                 // first, remove all existing line widths
02422                 // and also all bevel attributes
02423 
02424 // TODOG: This must all work with a NULL pOp pointer!!!
02425                 
02426                 pBevelStartNode = pParent->FindFirstChild(CC_RUNTIME_CLASS(NodeBevelBegin));
02427 
02428                 if (pOp)
02429                 {
02430                     pOp->DoRemoveAttrTypeFromSubtree(pParent, CC_RUNTIME_CLASS(AttrBevelLightAngle));
02431                     pOp->DoRemoveAttrTypeFromSubtree(pParent, CC_RUNTIME_CLASS(AttrBevelType));
02432                     pOp->DoRemoveAttrTypeFromSubtree(pParent, CC_RUNTIME_CLASS(AttrBevelContrast));
02433                     pOp->DoRemoveAttrTypeFromSubtree(pParent, CC_RUNTIME_CLASS(AttrBevelIndent));
02434 
02435                     if (bCreateNew)
02436                     {
02437                         // insert all the nodes
02438                         if(!m_bOuter)
02439                             pOp->DoInsertNewNode(pNewNodePath, pParent, LASTCHILD, TRUE, FALSE, FALSE, TRUE);
02440                         else
02441                             pOp->DoInsertNewNode(pNewNodePath, pBevelStartNode, NEXT, TRUE, FALSE, FALSE, TRUE);
02442                     }
02443 
02444                     if (pBevelStartNode)
02445                         pOp->DoHideNode(pBevelStartNode, TRUE, &pHiddenNode, FALSE);
02446                 }
02447                 else
02448                 {
02449                     pParent->RemoveAttrTypeFromSubtree(CC_RUNTIME_CLASS(AttrBevelLightAngle));
02450                     pParent->RemoveAttrTypeFromSubtree(CC_RUNTIME_CLASS(AttrBevelType));
02451                     pParent->RemoveAttrTypeFromSubtree(CC_RUNTIME_CLASS(AttrBevelContrast));
02452                     pParent->RemoveAttrTypeFromSubtree(CC_RUNTIME_CLASS(AttrBevelIndent));
02453 
02454                     if (bCreateNew)
02455                     {
02456                         // insert all the nodes
02457                         if(!m_bOuter)
02458                             pNewNodePath->AttachNode(pParent, LASTCHILD, FALSE, FALSE);
02459                         else
02460                             pNewNodePath->AttachNode(pBevelStartNode, NEXT, FALSE, FALSE);
02461                     }
02462 
02463                     if (pBevelStartNode)
02464                     {
02465                         pBevelStartNode->CascadeDelete();
02466                         delete pBevelStartNode;
02467                     }
02468                 }
02469             }
02470                         
02471             if (bCreateNew)
02472             {
02473                 CCAttrMap ThisMap;
02474                 if (!pNewNodePath->FindAppliedAttributes(&ThisMap))
02475                     return FALSE;
02476 
02477                 CCAttrMap* pThisMap = ThisMap.Copy();
02478                 if (pThisMap)
02479                 {
02480                     if (pThisMap->Lookup(CC_RUNTIME_CLASS(AttrStrokeColour), (void *&)(pStrokeColour)))
02481                     {
02482                         if (pStrokeColour && pStrokeColour->GetStartColour())
02483                             pStrokeColour->SetStartColour(&dcNone);
02484                     }
02485                 }
02486                 pBecomeA->PassBack(pNewNodePath, this, pThisMap);
02487             }
02488 
02489             // now hide me too
02490             if (pOp)
02491                 pOp->DoHideNode(this, TRUE, &pHiddenNode, FALSE);
02492             else
02493             {
02494                 CascadeDelete();
02495                 delete this;
02496             }
02497         }
02498         break;
02499     case BECOMEA_PASSBACK:
02500         {
02501             // we need to pass back 2 node paths, with appropriate attributes maps
02502             pNewNodePath = new NodePath;
02503             ERRORIF(pNewNodePath == NULL, _R(IDE_NOMORE_MEMORY), FALSE);
02504             
02505             // clone the ink path from me !
02506             pNewNodePath->InkPath.Initialise();
02507             pNewNodePath->InkPath.CloneFrom(InkPath);
02508             pNewNodePath->InkPath.IsFilled = TRUE;
02509             pNewNodePath->InkPath.TryToClose();
02510             pNewNodePath->InkPath.InitialiseFlags();
02511             
02512             // if we're passing back, just do the first path
02513             CCAttrMap ThisMap;
02514             if (!FindAppliedAttributes(&ThisMap))
02515                 return FALSE;
02516 
02517             // make a copy of this attribute map
02518             CCAttrMap * pNewAttrMap = ThisMap.Copy();
02519             // get the stroke colour attribute out of this map and set it to COLOUR_NONE
02520             if( pNewAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStrokeColour), (void *&)(pStrokeColour)))
02521             {
02522                 if (pStrokeColour && pStrokeColour->GetStartColour())
02523                     pStrokeColour->SetStartColour(&dcNone);
02524             }
02525             // ok, now lets set up the attribute maps
02526             pBecomeA->PassBack(pNewNodePath, this, pNewAttrMap);
02527         }
02528         break;
02529         default:
02530             break;
02531     }
02532     return TRUE;
02533 }
02534 
02535 /********************************************************************************************
02536 
02537 >   BOOL NodeBevel::CanBecomeA(BecomeA* pBecomeA);
02538 
02539     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02540     Created:    26/2/99
02541     Inputs:     Ink class to test
02542     Purpose:    Can become a path !
02543     SeeAlso:    
02544 
02545 ********************************************************************************************/
02546 
02547 BOOL NodeBevel::CanBecomeA(BecomeA* pBecomeA)
02548 {
02549     if (pBecomeA->BAPath())
02550     {
02551         pBecomeA->AddCount(2);
02552 
02553         return TRUE;
02554     }
02555 
02556     return FALSE;
02557 }
02558 
02559 /********************************************************************************************
02560 >   void NodeBevel::RenderTinyBlobs(RenderRegion* pRender)
02561 
02562     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02563     Created:    7/10/98
02564     Inputs:     -
02565     Returns:    See base class
02566     Purpose:    
02567 ********************************************************************************************/
02568 void NodeBevel::RenderTinyBlobs(RenderRegion* pRender)
02569 {
02570     pRender->SaveContext();
02571     pRender->SetLineColour(COLOUR_NONE);
02572     pRender->SetFillColour(COLOUR_UNSELECTEDBLOB);
02573 
02574     // Render the blobs on the path
02575     BlobManager* BlobMgr = GetApplication()->GetBlobManager();
02576 
02577     DocRect dr(0,0,0,0);
02578     InkPath.GetTrueBoundingRect(&dr);
02579 
02580     DocCoord Coord(dr.lo.x + (BlobMgr->GetBlobSize() / 2), 
02581         dr.hi.y - (BlobMgr->GetBlobSize() / 2));
02582     pRender->DrawBlob(Coord, BT_UNSELECTED);
02583     pRender->RestoreContext();
02584 }
02585 
02586 /********************************************************************************************
02587 
02588 >   BitmapFillAttribute* NodeBevel::GetBitmapFillAttribute ( void )
02589 
02590     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
02591     Created:    16/12/99
02592     Inputs:     -
02593     Returns:    A constant pointer to m_pBMPFill.
02594     Purpose:    Returns a pointer to the bitmap fill contained within NoveBevel.
02595 
02596 ********************************************************************************************/
02597 BitmapFillAttribute* NodeBevel::GetBitmapFillAttribute ( void )
02598 {
02599     return m_pBMPFill;
02600 }
02601 
02602 /********************************************************************************************
02603 >   DocRect NodeBevel::GetBoundingRect(BOOL DontUseAttrs = FALSE, BOOL HitTest = FALSE)
02604 
02605     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02606     Created:    7/10/98
02607     Inputs:     -
02608     Returns:    The bounding rect for the bevel
02609     Purpose:    
02610 ********************************************************************************************/
02611 
02612 DocRect NodeBevel::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest)
02613 {
02614     if ( IsBoundingRectValid && !DontUseAttrs )
02615         return BoundingRectangle;
02616     
02617     DocRect dr(0,0,0,0);
02618 
02619     // run through all previous nodes calculating their bounding rects
02620     if (InkPath.GetNumCoords() == 0)
02621     {
02622         Node* pNode = NULL;
02623 
02624         if(m_bOuter)
02625             pNode = FindNext(CC_RUNTIME_CLASS(NodeRenderableBounded));
02626         else
02627             pNode = FindPrevious(CC_RUNTIME_CLASS(NodeRenderableBounded));
02628 
02629         if (!pNode)         
02630             return DocRect(0,0,0,0);
02631         
02632         while (pNode)
02633         {
02634             if (pNode->IsRenderable() && !pNode->IsAnAttribute() &&
02635                 !pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelBegin)) &&
02636                 !pNode->IsNodeHidden())
02637             {
02638                 if (pNode->IsNodePath())
02639                 {
02640                     // rough guess of how big the path bounding rect is
02641                     NodePath * pNodePath = ((NodePath *)pNode)->MakeNodePathFromAttributes(BevelClipPathToPath_Flatness);
02642 
02643                     DocRect dr2(0,0,0,0);
02644                     pNodePath->InkPath.GetTrueBoundingRect(&dr2);
02645                     dr = dr.Union(dr2);
02646                     
02647                     delete pNodePath;
02648                 }
02649                 else
02650                     dr = dr.Union(((NodeRenderableBounded *) pNode)->GetBoundingRect(DontUseAttrs, HitTest));
02651             }
02652             
02653             if(m_bOuter)
02654                 pNode = pNode->FindNext(CC_RUNTIME_CLASS(NodeRenderableBounded));
02655             else
02656                 pNode = pNode->FindPrevious(CC_RUNTIME_CLASS(NodeRenderableBounded));
02657         }
02658         
02659         BoundingRectangle = dr;
02660         
02661         if (m_bOuter)
02662             BoundingRectangle.Inflate(m_Indent * 2);
02663     }
02664     else
02665         InkPath.GetTrueBoundingRect(&BoundingRectangle);
02666     
02667     IsBoundingRectValid = TRUE;
02668 
02669     return BoundingRectangle;
02670 }
02671 
02672 
02673 DocRect NodeBevel::GetBlobBoundingRect()
02674 {
02675     // now, find out if the blob manager's interest is in artistic blobs or not
02676     BlobManager* BlobMgr = GetApplication()->GetBlobManager();
02677     BlobStyle BS = BlobMgr->GetCurrentInterest(TRUE);
02678 
02679     INT32 BlobSize = BlobMgr->GetBlobSize();
02680     DocRect br = GetBoundingRect();
02681     br.lo.x -= BlobSize;
02682     br.lo.y -= BlobSize;
02683     br.hi.x += BlobSize;
02684     br.hi.y += BlobSize;
02685 
02686     IncludeChildrensBoundingRects(&br);
02687     
02688     // is the bevel tool active ?
02689     if (Tool::GetCurrentID() != TOOLID_BEVELTOOL || !BevelTool::AmActive())
02690         return br;
02691 
02692     DocRect BlobRect;
02693 
02694     // calculate the position of the light angle blob
02695     DocCoord blob( (br.hi.x+br.lo.x)>>1, 
02696                    (br.hi.y+br.lo.y)>>1 );
02697 
02698     View * pView = View::GetCurrent();
02699     if (!pView)
02700         return br;
02701 
02702     INT32 iLen = (INT32)(pView->GetScaledPixelWidth().MakeDouble()*40) ;
02703 
02704     // get from the blob manager the size of blobs
02705     if (pView)
02706     {
02707         iLen += (INT32)(pView->GetScaledPixelWidth().MakeDouble()*15);
02708         iLen += GetApplication()->GetBlobManager()->GetBlobSize();
02709     }
02710 
02711     DocRect dr;
02712     // calculate the rect for the blob
02713     dr.lo.x = blob.x - iLen;
02714     dr.lo.y = blob.y - iLen;
02715     dr.hi.x = blob.x + iLen;
02716     dr.hi.y = blob.y + iLen;
02717 
02718     BlobRect = br;
02719     // finally, union this with the standard group's bounding rect to give
02720     // the true blob bounding rect
02721     BlobRect = BlobRect.Union(dr);
02722 
02723     return BlobRect;
02724 }
02725 
02726 /********************************************************************************************
02727 
02728 >   virtual void NodeBevel::Transform( TransformBase& Trans )
02729 
02730     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02731     Created:    21/11/94
02732     Inputs:     Trans - The transform Object
02733     Purpose:    Transforms the shape.
02734     SeeAlso:    NodePath::Transform()
02735 
02736 ********************************************************************************************/
02737 void NodeBevel::Transform( TransformBase& tb )
02738 {
02739     if(!m_MustRegenOnChildChange)
02740         return;
02741 
02742     // get the scale factor for the transformation
02743     FIXED16 ScaleFactor = tb.GetScalar();
02744 
02745     TransformChildren(tb);
02746     Trans2DMatrix * pMat2D = NULL;
02747     if (tb.IsInvertable())
02748         pMat2D = (Trans2DMatrix*)(&tb);
02749 
02750     // And scale the line width
02751     m_Indent= labs( INT32(ScaleFactor.MakeDouble() * ((double)m_Indent) ));
02752 
02753     NodeBevelController * pControl = (NodeBevelController *)FindParent();
02754     if (pControl)
02755         pControl->m_Indent = m_Indent;
02756 
02757     AttrBevelIndent * pApplied = NULL;
02758     AttrBevelIndent * pIndent = NULL;
02759 
02760     if ( pMat2D &&
02761          !pMat2D->GetMatrix().IsTranslation() &&
02762          FindAppliedAttribute(CC_RUNTIME_CLASS(AttrBevelIndent),(NodeAttribute **)&pApplied) &&
02763          pApplied->IsADefaultAttr() )
02764     {
02765         // we need to insert an attribute onto me
02766         pIndent = new AttrBevelIndent(FindParent(), FIRSTCHILD);
02767         if (pIndent)
02768         {
02769             pIndent->Value.m_Indent = m_Indent;
02770             if (m_bOuter)
02771                 pIndent->Value.m_Indent = -m_Indent;
02772             ((NodeRenderableInk *)FindParent())->NormaliseAttributes();
02773         }
02774     }
02775             
02776     // transform the paths
02777     if (m_Path.GetNumCoords() > 0)
02778         tb.Transform(m_Path.GetCoordArray(), m_Path.GetNumCoords());
02779 
02780     if (m_OuterBevelPath.GetNumCoords() > 0)
02781         tb.Transform(m_OuterBevelPath.GetCoordArray(), m_OuterBevelPath.GetNumCoords());
02782 
02783     if (InkPath.GetNumCoords() > 0)
02784         tb.Transform(InkPath.GetCoordArray(), InkPath.GetNumCoords());
02785 
02786     if (m_ShrunkPath.GetNumCoords() > 0)
02787         tb.Transform(m_ShrunkPath.GetCoordArray(), m_ShrunkPath.GetNumCoords());
02788 
02789     // and regenerate the bitmap (if necessary)
02790     if (pMat2D)
02791     {
02792         if (!pMat2D->GetMatrix().IsTranslation())
02793         {
02794             GenerateBevel();
02795         }
02796         else
02797         {
02798             DocCoord TransCoords(0,0);
02799             pMat2D->GetMatrix().GetTranslation(TransCoords);
02800 
02801 //          if(TransCoords.x % 750 != 0 || TransCoords.y % 750 != 0)
02802 //              GenerateBevel();
02803 //          else
02804             {
02805                 // transform the source points of the bitmap fill
02806                 tb.Transform(&m_BMPCentre, 1);
02807                 tb.Transform(&m_BMPPoint1, 1);
02808                 tb.Transform(&m_BMPPoint2, 1);
02809                 tb.Transform(&BoundingRectangle.lo, 1);
02810                 tb.Transform(&BoundingRectangle.hi, 1);
02811             }
02812         }
02813     }
02814 
02815     InvalidateBoundingRect();
02816     GetBoundingRect(TRUE, FALSE);
02817 }
02818 
02819 /********************************************************************************************
02820 >   BOOL NodeBevel::NeedsTransparency()
02821 
02822     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02823     Created:    4/12/98
02824     Inputs:     -
02825     Returns:    TRUE
02826     Purpose:    We sure do need transparency !
02827 ********************************************************************************************/
02828 BOOL NodeBevel::NeedsTransparency() const
02829 {
02830     return TRUE;
02831 }
02832 
02833 
02834 /********************************************************************************************
02835 
02836 >   virtual BOOL Bevel::RequiresAttrib(CCRuntimeClass* pAttribClass,
02837                                             BOOL Search = FALSE)
02838 
02839     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02840     Created:    23/08/2000
02841     Inputs:     pAttribClass    the attr type to test.
02842                 Search          not a clue - look at base class implementation for info.
02843 
02844     Returns:    FALSE if pAttribClass is a brush attr,
02845                 calls base implementation otherwise.
02846 
02847     Purpose:    NodeBevel does not require brush attrs.
02848 
02849     Errors:     returns FALSE if pAttribClass is NULL.
02850 
02851 ********************************************************************************************/
02852 BOOL NodeBevel::RequiresAttrib(CCRuntimeClass* pAttribClass, BOOL Search)
02853 {
02854     if (pAttribClass == NULL || pAttribClass == CC_RUNTIME_CLASS(AttrBrushType))
02855         return FALSE;
02856     else
02857         return NodeRenderableInk::RequiresAttrib(pAttribClass, Search);
02858 }
02859 
02860 
02861 
02862 /********************************************************************************************
02863 
02864 >   virtual BOOL NodeBevel::RequiresAttrib(NodeAttribute* pAttr,
02865                                             BOOL Search = FALSE)
02866 
02867     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02868     Created:    23/08/2000
02869     Inputs:     pAttr       the attr to test.
02870                 Search      not a clue - look at base class implementation for info.
02871 
02872     Returns:    FALSE if pAttr is a brush attr,
02873                 calls base implementation otherwise.
02874 
02875     Purpose:    NodeBevel does not require brush attrs.
02876 
02877     Errors:     returns FALSE if pAttr is NULL.
02878 
02879 ********************************************************************************************/
02880 BOOL NodeBevel::RequiresAttrib(NodeAttribute* pAttr, BOOL Search)
02881 {
02882     if (pAttr == NULL || pAttr->IS_KIND_OF(AttrBrushType))
02883         return FALSE;
02884     else
02885         return NodeRenderableInk::RequiresAttrib(pAttr, Search);
02886 }
02887 
02888 
02889 
02890 /********************************************************************************************
02891 
02892 >   virtual BOOL NodeBevel::CanAttrBeAppliedToMe(CCRuntimeClass* pAttribClass)
02893 
02894     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02895     Created:    22/08/2000
02896     Inputs:     pAttribClass    the attr type to test.
02897     Returns:    FALSE if pAttribClass is a brush attr,
02898                 TRUE otherwise.
02899 
02900     Purpose:    Determine whether the given attr type can be applied directly to me.
02901                 We don't like brushed bevels, so we don't accept brush attrs.
02902 
02903     Errors:     returns FALSE if pAttribClass is NULL.
02904 
02905 ********************************************************************************************/
02906 BOOL NodeBevel::CanAttrBeAppliedToMe(CCRuntimeClass* pAttribClass)
02907 {
02908     if (pAttribClass == NULL || pAttribClass == CC_RUNTIME_CLASS(AttrBrushType))
02909         return FALSE;
02910     else
02911         return TRUE;
02912 }
02913 
02914 
02915 
02916 
02917 /********************************************************************************************
02918 >   virtual NodeCompound* NodeBevel::GetParentController() const
02919 
02920     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
02921     Created:    4/12/96
02922     Inputs:     -
02923     Returns:    Pointer to parent Bevel controller (NULL if not found!)
02924     Purpose:    Returns a type correct pointer to the parent Bevel controller
02925 ********************************************************************************************/
02926 NodeCompound* NodeBevel::GetParentController() const
02927 {
02928     NodeBevelController* pBob = (NodeBevelController*)FindParent();
02929     if (pBob != NULL && !IS_A(pBob, NodeBevelController))
02930     {
02931         ERROR3("Parent of Bevel was not a NodeBevelController");
02932         pBob = NULL;
02933     }
02934 
02935     return pBob;
02936 }
02937 
02938 /********************************************************************************************
02939 >   void NodeBevel::DeleteCachedBitmap()
02940 
02941     Author:     Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com>
02942     Created:    9/10/98
02943     Inputs:     -
02944     Returns:    
02945     Purpose:    Deletes the current Bevel Bitmap. Mainly used when printing to reduce
02946                 memory usage.
02947 ********************************************************************************************/
02948 void NodeBevel::DeleteCachedBitmap()
02949 {
02950     if(m_pBevelBitmap)
02951     {
02952         m_pBevelBitmap->Detach();
02953         m_pBevelBitmap->DestroyGreyscaleVersion();
02954         delete m_pBevelBitmap;
02955         m_pBevelBitmap = NULL;
02956     }
02957 
02958     if(m_pCombiBitmap)
02959     {
02960         delete m_pCombiBitmap;
02961         m_pCombiBitmap = NULL;
02962     }
02963 }
02964 
02965 /********************************************************************************************
02966 >   void NodeBevel::DeleteCache()
02967 
02968     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
02969     Created:    9/10/98
02970     Inputs:     -
02971     Returns:    
02972     Purpose:    Deletes all data held in this class
02973 ********************************************************************************************/
02974 void NodeBevel::DeleteCache()
02975 {
02976     m_bCached = FALSE;
02977     
02978     if (m_pBevelBitmap)
02979     {
02980         m_pBevelBitmap->Detach();
02981         delete m_pBevelBitmap;
02982         m_pBevelBitmap = NULL;
02983     }
02984 
02985     if (m_pBeveler)
02986     {
02987         delete m_pBeveler;
02988         m_pBeveler = NULL;
02989     }
02990 
02991     InkPath.ClearPath();
02992     m_OuterBevelPath.ClearPath();
02993     m_ShrunkPath.ClearPath();
02994     m_Path.ClearPath();
02995     InvalidateMe();
02996 }
02997 
02998 /********************************************************************************************
02999 >   BOOL NodeBevel::ReRenderBevelBitmap(BOOL bAntialias)
03000 
03001     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03002     Created:    9/10/98
03003     Inputs:     -
03004     Returns:    
03005     Purpose:    Re-renders the bevel bitmap using the beveler as it's already set up
03006                 with the currently applied attributes
03007 ********************************************************************************************/
03008 BOOL NodeBevel::ReRenderBevelBitmap(BOOL bAntialias)
03009 {
03010     BOOL ok = TRUE;
03011     
03012     if (m_pBeveler && m_pBevelBitmap)
03013     {
03014         // if the beveler is present, and we have a bitmap then re-render the bitmap
03015         m_pBeveler->SetBevelAngle(m_LightAngle);
03016         m_pBeveler->SetBevelType(m_BevelType);
03017         m_pBeveler->SetBevelTilt(m_Tilt);
03018 
03019         if(m_pCombiBitmap)
03020         {
03021             delete m_pCombiBitmap;
03022             m_pCombiBitmap = NULL;
03023         }
03024 
03025         // if we're antialiasing, then do the wait cursor
03026         if (bAntialias)
03027             m_DoingRotation = FALSE;
03028         else
03029             m_DoingRotation = TRUE;
03030 
03031         m_pBevelBitmap->DestroyGreyscaleVersion();
03032         ok = m_pBeveler->RenderToBitmap(m_pBevelBitmap, bAntialias, &m_SubPixelOffset);
03033     }
03034 
03035     return ok;
03036 }
03037 
03038 
03039 /********************************************************************************************
03040 >   BOOL NodeBevel::IsNodePath() const
03041 
03042     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03043     Created:    9/10/98
03044     Inputs:     -
03045     Returns:    FALSE always since I'm not a path - just am pretending to be one
03046     Purpose:    
03047 ********************************************************************************************/
03048 BOOL NodeBevel::IsNodePath() const
03049 {
03050     return FALSE;
03051 }
03052 
03053 /********************************************************************************************
03054 >   BOOL NodeBevel::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
03055 
03056     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03057     Created:    27/10/98
03058     Inputs:     -
03059     Returns:    FALSE for failure
03060     Purpose:    Writes out a dummy record, for my attribute to be attached to
03061 ********************************************************************************************/
03062 BOOL NodeBevel::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
03063 {
03064     UINT32 Tag = TAG_BEVELINK;
03065 
03066     CamelotFileRecord Rec(pFilter,Tag,0);
03067 
03068     pFilter->Write(&Rec);
03069 
03070     return TRUE;
03071 }
03072 
03073 BOOL NodeBevel::WritePreChildrenNative(BaseCamelotFilter* pFilter)
03074 {
03075     return WritePreChildrenWeb(pFilter);    
03076 }
03077 
03078 
03079 
03080 /********************************************************************************************
03081 >   Node* NodeBevel::SimpleCopy()
03082 
03083     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03084     Created:    27/10/98
03085     Inputs:     -
03086     Returns:    
03087     Purpose:    Returns a copy of me
03088 ********************************************************************************************/
03089 Node* NodeBevel::SimpleCopy()
03090 {
03091     NodeBevel * pNewNode = new NodeBevel;
03092 
03093     ERRORIF(pNewNode == NULL, _R(IDE_NOMORE_MEMORY), NULL);
03094 
03095     CopyNodeContents(pNewNode);
03096 
03097     return pNewNode;
03098 }
03099 
03100 
03101 
03102 
03103 /********************************************************************************************
03104 >   void NodeBevel::CopyNodeContents(NodeBevel* pNewNode)
03105 
03106     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
03107     Created:    05/01/2004
03108     Inputs:     -
03109     Returns:    
03110     Purpose:    Sort of backwards copy constructor
03111 
03112 ********************************************************************************************/
03113 void NodeBevel::CopyNodeContents(NodeBevel* pNewNode)
03114 {
03115     pNewNode->m_Indent     = m_Indent;
03116     pNewNode->m_LightAngle = m_LightAngle;
03117     pNewNode->m_Contrast   = m_Contrast;
03118     pNewNode->m_BevelType  = m_BevelType;
03119     pNewNode->m_bOuter     = m_bOuter;
03120 
03121     pNewNode->InkPath.Initialise(InkPath.GetNumCoords());
03122     pNewNode->InkPath.CopyPathDataFrom(&InkPath);
03123 
03124     pNewNode->m_MustRegenOnChildChange = m_MustRegenOnChildChange;
03125 
03126     pNewNode->m_Tilt = m_Tilt;
03127 
03128     pNewNode->m_IsABlendStepBevel = m_IsABlendStepBevel;
03129 
03130     // points determining the fill control points
03131     pNewNode->m_BMPCentre = m_BMPCentre;
03132     pNewNode->m_BMPPoint1 = m_BMPPoint1;
03133     pNewNode->m_BMPPoint2 = m_BMPPoint2;
03134 
03135     // the rect of the (original) selection
03136     pNewNode->m_SelectedRect = m_SelectedRect;
03137     pNewNode->m_JointType = m_JointType;
03138 
03139     pNewNode->m_Path.Initialise(m_Path.GetNumCoords());
03140     pNewNode->m_Path.CopyPathDataFrom(&m_Path);
03141 
03142     pNewNode->m_DoRender = TRUE;
03143 
03144     pNewNode->DeleteCachedBitmap();
03145 
03146     if (m_pBevelBitmap==NULL && m_pBMPFill!=NULL)
03147         m_pBMPFill->BitmapRef.SetBitmap(m_pBevelBitmap);
03148     if (m_pBevelBitmap==NULL && m_pTranspFill!=NULL)
03149         m_pTranspFill->BitmapRef.SetBitmap(m_pBevelBitmap);
03150 
03151     if (pNewNode->m_pBMPFill)
03152         delete pNewNode->m_pBMPFill;
03153     pNewNode->m_pBMPFill = NULL;
03154     if (m_pBMPFill)
03155     {
03156         pNewNode->m_pBMPFill = new BitmapFillAttribute;
03157         pNewNode->m_pBMPFill->SimpleCopy(m_pBMPFill);
03158     }
03159 
03160     if (pNewNode->m_pTranspFill)
03161         delete pNewNode->m_pTranspFill;
03162     pNewNode->m_pTranspFill = NULL;
03163     if (m_pTranspFill)
03164     {
03165         pNewNode->m_pTranspFill = new BitmapTranspFillAttribute;
03166         pNewNode->m_pTranspFill->SimpleCopy(m_pTranspFill);
03167     }
03168 
03169     pNewNode->m_BitmapWidth = m_BitmapWidth;
03170     pNewNode->m_BitmapHeight = m_BitmapHeight;
03171 
03172     pNewNode->m_SubPixelOffset = m_SubPixelOffset;
03173     pNewNode->m_PixelAllignedRect = m_PixelAllignedRect;
03174     pNewNode->m_IsFlatFilledOnly = m_IsFlatFilledOnly;
03175     pNewNode->m_IsAnAlphaBMP = m_IsAnAlphaBMP;
03176     pNewNode->m_HasTransparencyApplied = m_HasTransparencyApplied;
03177     pNewNode->m_AmConvertingToShapes = m_AmConvertingToShapes;
03178 
03179     pNewNode->m_LastCachedPrintBMPDPI = m_LastCachedPrintBMPDPI;
03180     pNewNode->m_LastExportedDPI = m_LastExportedDPI;
03181 
03182     // lock on rendering
03183     pNewNode->m_bStopRender = m_bStopRender;
03184     pNewNode->m_DoingRotation = m_DoingRotation;
03185 
03186     // this is the bevel path generated by the path processor for outer bevels (without
03187     // the hole in it)
03188     pNewNode->m_OuterBevelPath.Initialise(m_OuterBevelPath.GetNumCoords());
03189     pNewNode->m_OuterBevelPath.CopyPathDataFrom(&m_OuterBevelPath);
03190 
03191     // the pixel sizes used to create the bevel bitmap
03192     pNewNode->m_ViewScale = m_ViewScale;
03193 
03194     // the shrunk path used in rendering
03195     pNewNode->m_ShrunkPath.Initialise(m_ShrunkPath.GetNumCoords());
03196     pNewNode->m_ShrunkPath.CopyPathDataFrom(&m_ShrunkPath);
03197 
03198     pNewNode->m_bLock = m_bLock;
03199     pNewNode->m_bRenderBitmaps = m_bRenderBitmaps;
03200 
03201     // indicates we should zero the line width of the path, or not (as the case might be)
03202     pNewNode->m_bZeroLineWidth = m_bZeroLineWidth;
03203 
03204     // Make sure the new node doesn't have an old CBeveler lying around.
03205     if (pNewNode->m_pBeveler)
03206     {
03207         delete pNewNode->m_pBeveler;
03208         pNewNode->m_pBeveler = NULL;
03209     }
03210 
03211     // whether the original path is closed or not
03212     // if not, don't do any path shrinking
03213     pNewNode->m_bPathIsClosed = m_bPathIsClosed;
03214 
03215     // flag to indicate that when this node is inside of a blend there's
03216     // no need to regenerate it - it's already been cached
03217     pNewNode->m_bCached = m_bCached;
03218 
03219     // Reverses the bevel path and adds it to the original to create the new bevel path
03220     // Also shrinks/Expands the inner/outer path edge by a pixel to get rid of antialiasing
03221     // effects when overlapping the object
03222     pNewNode->m_LastZoomFactor = m_LastZoomFactor;
03223 
03224     // the last pixel size for the bitmap
03225     pNewNode->m_LastPixelSize = m_LastPixelSize;
03226 
03227     NodeRenderableInk::CopyNodeContents(pNewNode);
03228 }
03229 
03230 
03231 
03232 
03233 /***********************************************************************************************
03234 >   void NodeBevel::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
03235 
03236     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
03237     Created:    18/12/2003
03238     Outputs:    -
03239     Purpose:    Polymorphically copies the contents of this node to another
03240     Errors:     An assertion failure will occur if NodeCopy is NULL
03241     Scope:      protected
03242                                      
03243 ***********************************************************************************************/
03244 
03245 void NodeBevel::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
03246 {
03247     ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node");
03248     ENSURE(IS_A(pNodeCopy, NodeBevel), "PolyCopyNodeContents given wrong dest node type");
03249 
03250     if (IS_A(pNodeCopy, NodeBevel))
03251         CopyNodeContents((NodeBevel*)pNodeCopy);
03252 }
03253 
03254 
03255 
03256 /********************************************************************************************
03257 >   BOOL NodeBevel::PostDuplicate(UndoableOperation* pOp)
03258 
03259     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03260     Created:    1/6/99
03261     Inputs:     -
03262     Returns:    -
03263     Purpose:    Regens the node after a duplication
03264 ********************************************************************************************/
03265 BOOL NodeBevel::PostDuplicate(UndoableOperation* pOp)
03266 {
03267     // set my variables from the parent
03268     return TRUE;
03269 }
03270 
03271 
03273 // class to handle loading in of bevel records
03274 
03275 
03276 /********************************************************************************************
03277 >   BevelRecordHandler::BevelRecordHandler()
03278 
03279     Author:     Luke_Hart (Xara Group Ltd) <camelotdev@xara.com>
03280     Created:    19/07/05
03281     Inputs:     -
03282     Returns:    
03283     Purpose:    Constructor
03284 ********************************************************************************************/
03285 BevelRecordHandler::BevelRecordHandler()
03286 {
03287 }
03288 
03289 /********************************************************************************************
03290 >   BevelRecordHandler::~BevelRecordHandler()
03291 
03292     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03293     Created:    27/10/98
03294     Inputs:     -
03295     Returns:    
03296     Purpose:    Destructor
03297 ********************************************************************************************/
03298 BevelRecordHandler::~BevelRecordHandler()
03299 {
03300 }
03301 
03302 /********************************************************************************************
03303 >   UINT32* BevelRecordHandler::GetTagList()
03304 
03305     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03306     Created:    27/10/98
03307     Inputs:     -
03308     Returns:    
03309     Purpose:    Gets the tag list for this handler to handle 
03310 ********************************************************************************************/
03311 UINT32* BevelRecordHandler::GetTagList()
03312 {
03313     static const UINT32 TagList[] = {TAG_BEVEL,
03314                                     TAG_BEVATTR_INDENT,
03315                                     TAG_BEVATTR_LIGHTANGLE,
03316                                     TAG_BEVATTR_CONTRAST,
03317                                     TAG_BEVATTR_TYPE,
03318                                     TAG_BEVELINK, 
03319                                     CXFRH_TAG_LIST_END};
03320     return (UINT32*)&TagList;
03321 }
03322 
03323 /********************************************************************************************
03324 >   BOOL BevelRecordHandler::HandleRecord(CXaraFileRecord* pCXaraFileRecord)
03325 
03326     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03327     Created:    27/10/98
03328     Inputs:     -
03329     Returns:    
03330     Purpose:    Handles the bevel record - basically creates a BevelController node &
03331                 creates all the attributes
03332 ********************************************************************************************/
03333 BOOL BevelRecordHandler::HandleRecord(CXaraFileRecord* pCXaraFileRecord)
03334 {
03335     // load in the bevel information and the source path for the node
03336     // create the bevel node and include in the tree
03337 
03338 //  AttrBevelIndent *     pBevIndent = NULL;
03339 //  AttrBevelLightAngle * pBevLightAngle = NULL;
03340 //  AttrBevelContrast *   pBevContrast = NULL;
03341 //  AttrBevelType *       pBevType = NULL;
03342 
03343     INT32 value = 0;
03344 
03345     if (pCXaraFileRecord->GetTag() == TAG_BEVEL)
03346     {
03347         m_pBevelController = new NodeBevelController();
03348 
03349         if (!m_pBevelController)
03350         {
03351             ERROR(_R(IDE_NOMORE_MEMORY), FALSE);
03352         }
03353 
03354         BOOL ok = m_pBevelController->LoadBevelFromRecord(pCXaraFileRecord);
03355         if (!ok)
03356         {
03357             delete m_pBevelController ;
03358             m_pBevelController = NULL;
03359             return FALSE;
03360         }
03361     
03362         // insert it into the tree
03363         InsertNode(m_pBevelController);
03364     }
03365     else if (pCXaraFileRecord->GetTag() == TAG_BEVELINK)
03366     {
03367         // create the bevel node an insert it
03368         m_pBevelInk = new NodeBevel;
03369 
03370         if (!m_pBevelInk)
03371         {
03372             ERROR(_R(IDE_NOMORE_MEMORY), FALSE);            
03373         }
03374 
03375         InsertNode(m_pBevelInk);
03376         m_pBevelInk->InvalidateMe();
03377     }
03378     else if (pCXaraFileRecord->GetTag() == TAG_BEVATTR_INDENT)
03379     {
03380         // read the record
03381         if (!pCXaraFileRecord->ReadINT32(&value))
03382             return FALSE;
03383     }
03384     else if (pCXaraFileRecord->GetTag() == TAG_BEVATTR_LIGHTANGLE)
03385     {
03386         // read the record
03387         if (!pCXaraFileRecord->ReadINT32(&value))
03388             return FALSE;
03389     }
03390     else if (pCXaraFileRecord->GetTag() == TAG_BEVATTR_CONTRAST)
03391     {
03392         // read the record
03393         if (!pCXaraFileRecord->ReadINT32(&value))
03394             return FALSE;
03395     }
03396     else if (pCXaraFileRecord->GetTag() == TAG_BEVATTR_TYPE)
03397     {
03398         // read the record
03399         if (!pCXaraFileRecord->ReadINT32(&value))
03400             return FALSE;
03401     }
03402     
03403     return TRUE;
03404 }
03405 
03406 /********************************************************************************************
03407 
03408 >   virtual BOOL NodeBevel::NeedsParent(Node* pNode) const
03409 
03410 
03411     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03412     Created:    7/5/99
03413     Inputs:     A node to do the class checking on
03414     Returns:    
03415     Purpose:    Do we need a parent of the same class as the given node ???
03416     See also:   NodeCompound::OnChildChange
03417 
03418 ********************************************************************************************/
03419 BOOL NodeBevel::NeedsParent(Node* pNode) const
03420 {
03421     if (!pNode)
03422         return TRUE;
03423     
03424     if (pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelController)))
03425         return TRUE;
03426 
03427     return FALSE;
03428 }
03429 
03430 /********************************************************************************************
03431 
03432 >   DocRect NodeBevel::GetInsideBoundingRect()
03433 
03434 
03435     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03436     Created:    27/7/99
03437     Inputs:     
03438     Returns:    A bounding rect
03439     Purpose:    Gets the bounding rect of the original (non-bevelled) objects
03440     See also:   NodeCompound::OnChildChange
03441 
03442 ********************************************************************************************/
03443 DocRect NodeBevel::GetInsideBoundingRect()
03444 {
03445     Node * pNode = FindPrevious();
03446 
03447     DocRect dr(0,0,0,0);
03448 
03449     while (pNode)
03450     {
03451         if (pNode->IsAnObject() && !pNode->IsNodeHidden() && pNode->IsBounded() &&
03452             !pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelBegin)))
03453         {
03454             dr = dr.Union(((NodeRenderableBounded *)pNode)->GetBoundingRect());
03455         }
03456         pNode = pNode->FindPrevious();
03457     }
03458 
03459     return dr;
03460 }
03461 
03462 /********************************************************************************************
03463 
03464 >   void NodeBevel::DrawNodesForPrinting(RenderRegion * pRender)
03465 
03466 
03467     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03468     Created:    28/7/99
03469     Inputs:     
03470     Returns:    
03471     Purpose:    Renders all original nodes again
03472     Notes:      Used because in printing, problems occur with the ShrinkPath stuff, causing
03473                 holes to appear in the printed image. Thus, we take a different tack of rendering
03474                 the bevelled path without the original being taken away from it, and then rendering
03475                 the original nodes again so no holes occur
03476     See also:   NodeBevel::RenderBitmap
03477 
03478 ********************************************************************************************/
03479 void NodeBevel::RenderNodesForPrinting(RenderRegion * pRender)
03480 {
03481     // first, save the context
03482     pRender->SaveContext();
03483 
03484     // next get the first child node of the controller
03485     Node* pController = (Node*)GetParentController();
03486 
03487     Node* pNode = pController->FindFirstChild();
03488 
03489     while (pNode)
03490     {
03491         if (!pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelBegin)) &&
03492             !pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevel)) &&
03493             !pNode->IsNodeHidden() &&
03494             pNode->IsNodeRenderableClass())
03495         {
03496             RenderNodeRecursively(pNode, pRender);
03497         }
03498         pNode = pNode->FindNext();
03499     }
03500 
03501     pRender->RestoreContext();
03502 }
03503 
03504 /********************************************************************************************
03505 
03506 >   void NodeBevel::RenderNodeRecursively(Node * pNode, RenderRegion * pRender)
03507 
03508 
03509     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03510     Created:    28/7/99
03511     Inputs:     
03512     Returns:    
03513     Purpose:    Renders all children of this node first, then renders the node itself
03514     Notes:      
03515     See also:   NodeBevel::DrawNodesForPrinting
03516 
03517 ********************************************************************************************/
03518 void NodeBevel::RenderNodeRecursively(Node * pNode, RenderRegion * pRender)
03519 {
03520     BOOL bHasChildren = FALSE;
03521 
03522     // get the first child node
03523     Node * pChildNode = pNode->FindFirstChild();
03524 
03525     if (pChildNode)
03526     {
03527         // save the context if this node has children
03528         pRender->SaveContext();
03529         bHasChildren = TRUE;
03530     }   
03531 
03532     while (pChildNode)
03533     {
03534         if (!pChildNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelBegin)) &&
03535             !pChildNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevel)) &&
03536             !pChildNode->IsNodeHidden() &&
03537             pChildNode->IsNodeRenderableClass())
03538         {
03539             RenderNodeRecursively(pChildNode, pRender);
03540         }
03541         pChildNode = pChildNode->FindNext();
03542     }
03543 
03544     // now, render the node itself
03545     pRender->SaveContext();
03546     pRender->SetLineColour(COLOUR_NONE);
03547     pNode->Render(pRender);
03548     pRender->RestoreContext();
03549     
03550     // restore the context
03551     if (bHasChildren)
03552         pRender->RestoreContext();
03553 }
03554 
03555 
03556 
03557 /********************************************************************************************
03558 
03559 >   virtual BOOL NodeBevel::AllowOp(ObjChangeParam *pParam, BOOL SetOpPermissionState,
03560                                                             BOOL DoPreTriggerEdit = TRUE)
03561 
03562     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>; Karim 20/01/2000
03563     Created:    20/11/96
03564     Inputs:     pParam                  describes the way an op wants to change the node
03565                 SetOpPermissionState    if TRUE the OpPermission of nodes should be set
03566                 DoPreTriggerEdit        if TRUE then NameGallery::PreTriggerEdit is called.
03567                                         *Must* be TRUE if the calling Op may make any nodes
03568                                         change their bounds, eg move, line width, cut.
03569                                         Use TRUE if unsure.
03570     Purpose:    
03571     SeeAlso:    
03572 
03573 ********************************************************************************************/
03574 BOOL NodeBevel::AllowOp(ObjChangeParam *pParam, BOOL SetOpPermissionState,
03575                                                 BOOL DoPreTriggerEdit)
03576 {
03577     ERROR2IF(pParam==NULL, FALSE, "NodeBevel::AllowOp; NULL pParam");
03578 
03579     // Set up a flag to see if any of the child objects get changed
03580     BOOL allowed = TRUE;
03581 
03582     UndoableOperation* pOp = pParam->GetOpPointer();
03583 
03584     // clean out the calling-child ptr, so it doesn't get passed around unintentionally.
03585     pParam->SetCallingChild(NULL);
03586 
03587     // before going further, see whether our parents allow the Op.
03588     if (allowed && Parent != NULL && pParam->GetDirection()!= OBJCHANGE_CALLEDBYPARENT)
03589     {
03590         ObjChangeDirection OldDirection = pParam->GetDirection();
03591         pParam->SetCallingChild(this);
03592         pParam->SetDirection(OBJCHANGE_CALLEDBYCHILD);
03593         allowed = Parent->AllowOp(pParam, SetOpPermissionState, DoPreTriggerEdit);
03594         pParam->SetDirection(OldDirection);
03595     }
03596 
03597     // if the parent allows this, then test the op for ourself.
03598     if (allowed && pOp)
03599     {
03600         // disallow mould and contour Ops.
03601         if ( pOp->IsKindOf(CC_RUNTIME_CLASS(OpCreateNewMould)) ||
03602              pOp->IsKindOf(CC_RUNTIME_CLASS(OpPasteEnvelope)) ||
03603              pOp->IsKindOf(CC_RUNTIME_CLASS(OpPastePerspective)) ||
03604              pOp->IsKindOf(CC_RUNTIME_CLASS(OpCreateContour))
03605             )
03606             allowed = FALSE;
03607 
03608         if( (pOp->IsKindOf(CC_RUNTIME_CLASS(OpEditFill)) ||
03609              pOp->IsKindOf(CC_RUNTIME_CLASS(OpApplyAttribToSelected))) &&
03610              !m_IsFlatFilledOnly && m_HasTransparencyApplied && m_pCombiBitmap )
03611         {
03612             // Make sure the attributes aren't pointing at the bitmap we are about to delete
03613             if (m_pBMPFill->GetBitmap() == m_pCombiBitmap)
03614                 m_pBMPFill->BitmapRef.SetBitmap(NULL);
03615             if (m_pTranspFill->GetBitmap() == m_pCombiBitmap)
03616                 m_pTranspFill->BitmapRef.SetBitmap(NULL);
03617             
03618             delete m_pCombiBitmap;
03619             m_pCombiBitmap = NULL;
03620         }
03621     }
03622 
03623     // if necessary, set permissions for OnChildChange.
03624     if (SetOpPermissionState)
03625         SetOpPermission(allowed ? PERMISSION_ALLOWED : PERMISSION_DENIED, TRUE);
03626 
03627     if (allowed)
03628     {
03629         UndoableOperation* pChangeOp = pParam->GetOpPointer();
03630 
03631         // check for geometry linked attributes
03632         BOOL InformGeomLinkedAttrs = SetOpPermissionState && pChangeOp && pChangeOp->MayChangeNodeBounds();
03633         if (InformGeomLinkedAttrs)
03634         {
03635             NodeAttribute* pNA = FindFirstGeometryLinkedAttr();
03636             while(pNA)
03637             {
03638                 pNA->LinkedNodeGeometryHasChanged(pChangeOp);
03639                 pNA = pNA->FindNextGeometryLinkedAttr();
03640             }
03641         }       
03642 
03643         // if we're ok so far and were asked to do a PreTriggerEdit, then
03644         // determine whether the Op may change the bounds of some nodes.
03645         // If it may, then call NameGallery::PreTriggerEdit.
03646         if (DoPreTriggerEdit && pChangeOp && pChangeOp->MayChangeNodeBounds() && NameGallery::Instance())
03647             allowed = NameGallery::Instance()->PreTriggerEdit(pChangeOp, pParam, this);
03648     }
03649 
03650     // return result (directly, or indirectly via a child AllowOp()) to op
03651     return allowed;
03652 }
03653 
03654 
03655 
03656 /********************************************************************************************
03657 
03658 >   void NodeBevel::RenderEorDrag(RenderRegion * pRegion)
03659 
03660     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03661     Created:    20/11/96
03662     Inputs:     
03663     Purpose:    
03664     SeeAlso:    
03665 
03666 ********************************************************************************************/
03667 void NodeBevel::RenderEorDrag(RenderRegion * pRegion)
03668 {
03669     pRegion->DrawPath(&InkPath);
03670 }
03671 
03672 /********************************************************************************************
03673 
03674 >   virtual DocRect NodeBevel::ValidateExtend(const ExtendParams& ExtParams)
03675 
03676     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
03677     Created:    06/12/1999
03678     Inputs:     ExtParams       description parameters for the extension.
03679     Outputs:    
03680     Returns:    TRUE if extending this Nodewill be a reversible operation,
03681                 FALSE otherwise.
03682     Purpose:    Tests the reversibility of an Extend operation applied to this node.
03683 
03684                 A NodeBevel cannot itself extend, so instead it asks its parent controller
03685                 to extend for it. Infinite recursion does not occur, as the controller node
03686                 ignores its child node, this NodeBevel.
03687     Errors:     In debug builds, ERROR3 if this Node has no NodeBevelController,
03688                 in release, we return TRUE.
03689     See also:   IsTypeExtendible(), Extend().
03690 
03691 ********************************************************************************************/
03692 DocRect NodeBevel::ValidateExtend(const ExtendParams& ExtParams)
03693 {
03694     Node* pBob = GetParentController();
03695     if (pBob == NULL)
03696     {
03697         ERROR3("NodeBevel::ValidateExtend- no controller Node found!");
03698         return DocRect(INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX);
03699     }
03700     else
03701     {
03702         return pBob->ValidateExtend(ExtParams);
03703     }
03704 }
03705 
03706 
03707 
03708 /********************************************************************************************
03709 
03710 >   virtual void NodeBevel::Extend(const ExtendParams& ExtParams)
03711 
03712     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
03713     Created:    06/12/1999
03714     Inputs:     ExtParams       description parameters for the extension.
03715     Outputs:    Some of the child nodes of this BevelNode's NodeBevelController may have
03716                 their dimensions altered.
03717     Returns:    
03718     Purpose:    Perform an Extend operation on this Node, and its children if appropriate.
03719 
03720                 A NodeBevel cannot itself extend, so instead it asks its parent controller
03721                 to extend for it. Infinite recursion does not occur, as the controller node
03722                 ignores its child node, this NodeBevel.
03723     Errors:     In debug builds, ERROR3 if this Node has no NodeBevelController,
03724                 in release, we do nothing.
03725     See also:   
03726 
03727 ********************************************************************************************/
03728 void NodeBevel::Extend(const ExtendParams& ExtParams)
03729 {
03730     Node* pBob = GetParentController();
03731     if (pBob == NULL)
03732     {
03733         ERROR3("NodeBevel::ValidateExtend- no controller Node found!");
03734     }
03735     else
03736         pBob->Extend(ExtParams);
03737 
03738     return;
03739 }
03740 
03741 
03742 
03743 /********************************************************************************************
03744 
03745 >   virtual INT32 NodeBevel::EstimateNodeComplexity (OpParam* details)
03746 
03747     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
03748     Created:    6/09/2000
03749 
03750     Inputs:     details     any data that should be used for the calculation
03751 
03752     Outputs:    -
03753 
03754     Returns:    an estimate of the nodes complexity
03755 
03756     Purpose:    This function estimates a complexity value for the node.  The complexity
03757                 value is based upon the total length of all paths in the node.
03758 
03759     See Also:   OpBlendNodes::DeterminBlendObjectsProcessorHit ()
03760 
03761 ********************************************************************************************/
03762 
03763 INT32 NodeBevel::EstimateNodeComplexity (OpParam* details)
03764 {
03765     return (InkPath.GetUsedSlots ());
03766 }
03767 
03768 void NodeBevel::PreExportRender ( RenderRegion *pRegion )
03769 {
03770     if( pRegion 
03771 PORTNOTE("other","Removed ImagemapRenderRegion usage")
03772 #ifndef EXCLUDE_FROM_XARALX
03773         && !pRegion->IsKindOf( CC_RUNTIME_CLASS(ImagemapRenderRegion) )
03774 #endif
03775      )
03776     {
03777         NodeBevelController* pControl = (NodeBevelController *)FindParent();
03778         if(pControl)
03779         {
03780             INT32 NewDPI = 96;
03781             Camelot.GetPrefValue(TEXT("Displays"),TEXT("CompCToEDPI"),&NewDPI);
03782             pControl->SetDPI(NewDPI);
03783             DeleteCachedBitmap();
03784             m_AmConvertingToShapes = TRUE;
03785 /*
03786             double ThisDPI = 96.0;
03787             
03788             if(pRegion->GetScaledPixelWidth() > 75)
03789                 ThisDPI = (750.0 / pRegion->GetScaledPixelWidth()) * 96.0;
03790 
03791             if(m_LastExportedDPI != ThisDPI)
03792             {
03793                 m_LastExportedDPI = ThisDPI;
03794                 pControl->SetDPI(ThisDPI);
03795                 DeleteCachedBitmap();
03796                 m_AmConvertingToShapes = TRUE;
03797             }
03798             else
03799                 m_AmConvertingToShapes = FALSE;
03800 */
03801         }
03802     }
03803     else
03804         m_AmConvertingToShapes = FALSE;
03805 }
03806 
03807 /********************************************************************************************
03808 
03809 >   virtual BOOL NodeBevel::ExportRender ( RenderRegion *pRegion )
03810 
03811     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
03812     Created:    14/12/99
03813     Inputs:     pRegion - A pointer to a RenderRegion.
03814     Outputs:    -
03815     Returns:    TRUE if custom export code is invoked, otherwise FALSE.
03816     Purpose:    If pRenderRegion points to a FlashRenderRegion, the bevel will be
03817                 processed as a bitmap filled shape, and stored as a pair of records
03818                 (shape and bitmap) within the resulting Flash file.
03819 
03820                 If pRenderRegion points to a CMXRenderRegion, a similar conversion function
03821                 will be invoked.
03822 
03823 ********************************************************************************************/
03824 BOOL NodeBevel::ExportRender( RenderRegion *pRegion )
03825 {
03826     BOOL bResult = FALSE;
03827 
03828 //  NodeBevelController * pController = (NodeBevelController *)FindParent();
03829 
03830     // Step 1:  If the RenderRegion is a FlashRenderRegion, use custom Flash export code.
03831     if ( pRegion->IsKindOf ( CC_RUNTIME_CLASS ( FlashRenderRegion ) ) )
03832     {
03833         // Step 1a: Cast the pRegion pointer to be a FlashRenderRegion pointer, so that
03834         //          it can access the custom Flash export methods.
03835         FlashRenderRegion   *pFlash = ( FlashRenderRegion* ) pRegion;
03836 
03837         // Step 1b: Pass the character into the appropriate method to export the character.
03838         //          This is where all the hard work is done.
03839         bResult = pFlash->ExportBevel ( this );
03840     }
03841 PORTNOTE("cmx", "Removed CMX Support")
03842 #ifndef EXCLUDE_FROM_XARALX
03843     // Step 2:  Otherwise check whether it's a CMXRenderRegion.
03844     else if ( pRegion->IsKindOf ( CC_RUNTIME_CLASS ( CMXRenderRegion ) ) )
03845     {
03846         // Step 2a: Cast the pRegion pointer to be a CMXRenderRegion pointer.
03847         CMXRenderRegion     *pCMX   = ( CMXRenderRegion* ) pRegion;
03848 
03849         // Step 2b: Pass the character into the appropriate method to export the character.
03850         //          This is where all the hard work is done.
03851         bResult = pCMX->ExportBevel ( this );
03852     }
03853 #endif
03854     // Step 3:  Otherwise check whether it's an AIEPSRenderRegion.
03855     else if ( pRegion->IsKindOf ( CC_RUNTIME_CLASS ( AIEPSRenderRegion ) ) )
03856     {
03857         // Step 3a: Cast the pRegion pointer to be a CMXRenderRegion pointer.
03858         AIEPSRenderRegion   *pAIEPS = ( AIEPSRenderRegion* ) pRegion;
03859 
03860         // Step 3b: Pass the character into the appropriate method to export the character.
03861         //          This is where all the hard work is done.
03862         bResult = pAIEPS->ExportBevel ( this );
03863     }
03864 
03865     // Step 4:  The export has been done successfully. Return TRUE to prevent Camelot
03866     //          from rendering the character out as paths as well as text. (If there's
03867     //          been an error, bResult will have been set to FALSE.)
03868     return bResult;
03869 }
03870 
03871 /********************************************************************************************
03872 
03873 >   virtual BOOL NodeBevel::OnNodePopUp(Spread* pSpread, DocCoord PointerPos, ContextMenu* pMenu)
03874 
03875     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03876     Created:    7/2/2000
03877     Inputs:     pSpread     The spread in which things are happening
03878                 PointerPos  The Location of the mouse pointer at the time of the click
03879                 pMenu       The menu to which items should be added
03880     Returns:    BOOL - TRUE if the node claims the click as its own and FALSE if it is
03881                 not interested in the click
03882     Purpose:    Allows the shadow to respond to the click
03883 
03884 ********************************************************************************************/
03885 BOOL NodeBevel::OnNodePopUp(Spread* pSpread, DocCoord PointerPos, ContextMenu* pMenu)
03886 {
03887     BOOL ok = TRUE;
03888 
03889     PORTNOTETRACE("other","NodeBevel::ExportRender - do nothing");
03890 #ifndef NO_ADVANCED_TOOLS   
03891     ok = ok && pMenu->BuildCommand(TOOL_OPTOKEN_BEVEL, TRUE);
03892 #endif
03893     return ok;
03894 }
03895 
03896 
03897 /****************************************************************************
03898 
03899 >   void NodeBevel::GetDebugDetails( StringBase* Str )
03900 
03901     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
03902     Created:    07/07/2005
03903 
03904     Inputs:     Str         - pointer to a StringBase
03905     Purpose:    Builds debug info for camelot tree dialog
03906 
03907 ****************************************************************************/
03908 
03909 void NodeBevel::GetDebugDetails( StringBase* Str )
03910 {
03911 #if DEBUG_TREE
03912     // Call base class
03913     NodeRenderableInk::GetDebugDetails( Str );
03914     
03915     String_256 TempStr;
03916     String_256 TempStr2;
03917         
03918     (*Str) += TEXT( "\r\nNodeBevel Data Dump\r\n" );
03919 
03920     DocRect BlobRect = GetBlobBoundingRect();
03921     TempStr._MakeMsg( TEXT("Blob Bounding Rect :\r\n\t#1%ld,\t#2%ld\r\n\t#3%ld,\t#4%ld\r\n"),
03922                       BlobRect.lo.x, BlobRect.lo.y, BlobRect.hi.x, BlobRect.hi.y );
03923     (*Str) += TempStr;
03924 
03925     TempStr._MakeMsg( TEXT("Type :\t#1%d\r\n"), m_BevelType);
03926     (*Str) += TempStr;
03927 
03928 #endif
03929 }
03930 
03931 
03932 
03934 // The NodeBevelBegin class - used to set up the path processor to
03935 // build the bevel path before rendering the 
03936 
03937 /********************************************************************************************
03938 >   NodeBevelBegin::NodeBevelBegin()
03939 
03940     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03941     Created:    27/10/98
03942     Inputs:     -
03943     Returns:    
03944     Purpose:    Constructor for the NodeBevelBegin class.
03945     Notes:      This class is purely used to set up the bevel path processor which builds
03946                 the bevel path
03947 ********************************************************************************************/
03948 NodeBevelBegin::NodeBevelBegin()
03949 {
03950 }
03951 
03952 /********************************************************************************************
03953 >   NodeBevelBegin::NodeBevelBegin(Node* ContextNode,  
03954          AttachNodeDirection Direction, 
03955          BOOL Locked, 
03956          BOOL Mangled,  
03957          BOOL Marked, 
03958          BOOL Selected) 
03959             : NodePath(ContextNode, Direction, Locked, Mangled, Marked, Selected)
03960 
03961 
03962     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03963     Created:    27/10/98
03964     Inputs:     -
03965     Returns:    
03966     Purpose:    Constructor for the NodeBevelBegin class.
03967     Notes:      This class is purely used to set up the bevel path processor which builds
03968                 the bevel path
03969 ********************************************************************************************/
03970 NodeBevelBegin::NodeBevelBegin(Node* ContextNode,  
03971          AttachNodeDirection Direction, 
03972          BOOL Locked, 
03973          BOOL Mangled,  
03974          BOOL Marked, 
03975          BOOL Selected) 
03976             : NodeRenderableBounded(ContextNode, Direction, Locked, Mangled, Marked, Selected)
03977 {
03978     
03979 }
03980 
03981 
03982 /********************************************************************************************
03983 >   void NodeBevelBegin::Render(RenderRegion * rr)
03984 
03985     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
03986     Created:    27/10/98
03987     Inputs:     -
03988     Returns:    
03989     Purpose:    Pushes the bevel path processor onto the path processor stack of the given
03990                 render region
03991     Notes:      
03992 ********************************************************************************************/
03993 void NodeBevelBegin::Render(RenderRegion * rr)
03994 {
03995     return;
03996     // is the ink path valid in the ink node ?
03997 /*  Node * pNode = FindNext(CC_RUNTIME_CLASS(NodeBevel));
03998 
03999     NodeBevelController * pControl = (NodeBevelController *)FindParent();
04000 
04001     if (!pControl)
04002         return;
04003 
04004     // no inside bounding rect ? no render !
04005     if (pControl->GetInsideBoundingRect().IsEmpty())
04006         return;
04007 
04008     if (pControl->IsPrinting())
04009     {
04010         // make sure we're intersected with the render regions clipping rectangle
04011         if (!(rr->GetClipRect().IsIntersectedWith(BoundingRectangle)))
04012             return ;
04013     }
04014 
04015     // push the contour path processor to do the extension of the node
04016     // only if we're an outer bevel
04017     BevelAttributeValueIndent * pBevelIndent = (BevelAttributeValueIndent *)
04018         rr->GetCurrentAttribute(ATTR_BEVELINDENT); */
04019 }
04020 
04021 /********************************************************************************************
04022 >   DocRect NodeBevelBegin::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest)
04023 
04024     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
04025     Created:    27/10/98
04026     Inputs:     -
04027     Returns:    
04028     Purpose:    Returns the bounding rect of the bevel controller node
04029     Notes:      
04030 ********************************************************************************************/
04031 DocRect NodeBevelBegin::GetBoundingRect(BOOL DontUseAttrs, BOOL HitTest)
04032 {
04033     // same as first sibling
04034     NodeBevelController* pBevelController = (NodeBevelController*)FindParent();
04035 
04036     if (pBevelController->GetInsideBoundingRect().IsEmpty())
04037         return DocRect(0,0,0,0);
04038 
04039     if (pBevelController)
04040     {
04041         NodeBevel* pBevel = pBevelController->GetBevelNode();
04042 
04043         if (pBevel)
04044         {
04045             BoundingRectangle = pBevel->GetBoundingRect(DontUseAttrs, HitTest);
04046             return BoundingRectangle;
04047         }
04048     }
04049     
04050     Node * pNode = this->FindNext(CC_RUNTIME_CLASS(NodeRenderableBounded));
04051     if (!pNode || pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevel)))
04052     {
04053         // ERROR3("NodeBevelBegin - Can't find renderable node !\n");
04054         return BoundingRectangle;
04055     }
04056 
04057     BoundingRectangle = ((NodeRenderableBounded *)pNode)->GetBoundingRect(DontUseAttrs, HitTest);
04058     return BoundingRectangle;
04059 }
04060 
04061 
04062 DocRect NodeBevelBegin::GetBlobBoundingRect()
04063 {
04064     return GetBoundingRect(TRUE, FALSE);
04065 }
04066 
04067 
04068 /********************************************************************************************
04069 >   Node* NodeBevelBegin::SimpleCopy()
04070 
04071     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
04072     Created:    27/10/98
04073     Inputs:     -
04074     Returns:    
04075     Purpose:    Returns a copy of me
04076 ********************************************************************************************/
04077 Node* NodeBevelBegin::SimpleCopy()
04078 {
04079     NodeBevelBegin * pNewNode = new NodeBevelBegin;
04080 
04081     ERRORIF(pNewNode == NULL, _R(IDE_NOMORE_MEMORY), NULL);
04082 
04083     return pNewNode;
04084 }
04085 
04086 /********************************************************************************************
04087 
04088 >   virtual BOOL NodeBevelBegin::NeedsParent(Node* pNode)
04089 
04090 
04091     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
04092     Created:    7/5/99
04093     Inputs:     A node to do the class checking on
04094     Returns:    
04095     Purpose:    Do we need a parent of the same class as the given node ???
04096     See also:   NodeCompound::OnChildChange
04097 
04098 ********************************************************************************************/
04099 BOOL NodeBevelBegin::NeedsParent(Node* pNode) const
04100 {
04101     if (!pNode || pNode->IsKindOf(CC_RUNTIME_CLASS(NodeBevelController)))
04102         return TRUE;
04103 
04104     return FALSE;
04105 }
04106 
04107 // a NodeBevelBegin can never be selected ....
04108 
04109 void NodeBevelBegin::SetSelected(BOOL Status)
04110 {
04111     Node::SetSelected(FALSE);
04112 }
04113 
04114 
04115 /********************************************************************************************
04116 
04117 >   BOOL NodeBevelBegin::NeedsToRender(RenderRegion * pRender)
04118 
04119     Author:     David_McClarnon (Xara Group Ltd) <camelotdev@xara.com>
04120     Created:    7/5/99
04121     Inputs:     A Render region
04122     Returns:    
04123     Purpose:    Is the top path processor a bevel path processor ? if so, I don't need to
04124                 render myself
04125     See also:   NodeBevelBegin::Render
04126 
04127 ********************************************************************************************/
04128 
04129 SubtreeRenderState NodeBevelBegin::RenderSubtree(RenderRegion* pRender, Node** ppNextNode, BOOL bClip)
04130 {
04131     return SUBTREE_ROOTANDCHILDREN;
04132 }
04133 
04134 
04135 /********************************************************************************************
04136 
04137 >   virtual BOOL NodeBevelBegin::ExportRender ( RenderRegion *pRegion )
04138 
04139     Author:     Graeme_Sutherland (Xara Group Ltd) <camelotdev@xara.com>
04140     Created:    15/12/99
04141     Inputs:     pRegion - A pointer to a RenderRegion.
04142     Outputs:    -
04143     Returns:    TRUE if the RenderRegion is a FlashRenderRegion, otherwise FALSE.
04144     Purpose:    If pRenderRegion points to a FlashRenderRegion, the bevel will be
04145                 processed as a bitmap filled shape, and stored as a pair of records
04146                 (shape and bitmap) within the resulting Flash file.
04147 
04148 ********************************************************************************************/
04149 
04150 BOOL NodeBevelBegin::ExportRender ( RenderRegion *pRegion )
04151 {
04152     BOOL bResult = FALSE;
04153 
04154 //  NodeBevelController * pController = (NodeBevelController *)FindParent();
04155 
04156     // Step 1:  Test whether the render region is a Flash one. If so, invoke it's custom
04157     //          export code.
04158     if ( pRegion->IsKindOf ( CC_RUNTIME_CLASS ( FlashRenderRegion ) ) )
04159     {
04160         // Step 1a: Cast the pRegion pointer to be a FlashRenderRegion pointer, so that
04161         //          it can access the custom Flash export methods.
04162         FlashRenderRegion *pFlash = ( FlashRenderRegion* ) pRegion;
04163 
04164         // Step 1b: Pass the character into the appropriate method to export the character.
04165         //          This is where all the hard work is done.
04166         bResult = pFlash->ExportBevelBegin ( this );
04167     }
04168     // Step 2:  Test whether the render region is a CMX one. If so, invoke it's custom
04169     //          export code.
04170 PORTNOTE("cmx", "Removed CMX Support")
04171 #ifndef EXCLUDE_FROM_XARALX
04172     else if ( pRegion->IsKindOf ( CC_RUNTIME_CLASS ( CMXRenderRegion ) ) )
04173     {
04174         // Step 2a: Cast the pRegion pointer to be a CMXRenderRegion pointer, so that
04175         //          it can access the custom CMX export methods.
04176         CMXRenderRegion *pCMX = ( CMXRenderRegion* ) pRegion;
04177 
04178         // Step 2b: Invoke the stub function within the CMX render region.
04179         bResult = pCMX->ExportBevelBegin ( this );
04180     }
04181 #endif
04182     // render bitmap stuff
04183     else
04184     {
04185         // ok, im intersecting so render
04186         Render(pRegion);
04187 
04188         return TRUE;
04189     }
04190 
04191     // Step 3:  The export has been done successfully. Return TRUE to prevent Camelot
04192     //          from rendering the character out as paths as well as text. (If there's
04193     //          been an error, bResult will have been set to FALSE.)
04194     return bResult;
04195 }
04196 
04197 //#endif

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