fthrattr.cpp

Go to the documentation of this file.
00001 // $Id: fthrattr.cpp 1738 2006-09-04 15:23:34Z luke $
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 #include "fthrattr.h"
00101 
00102 // Algorithms and node classes used for creating feather transp mask
00103 #include "nodecntr.h"       // NodeContour::GenerateContourPathForNode
00104 //#include "doccolor.h"     // DocColour and COLOUR_BLACK
00105 #include "lineattr.h"       // AttrLineWidth
00106 //#include "fillval.h"      // BitmapFillAttribute, TransparencyFillAttribute - in camtypes.h [AUTOMATICALLY REMOVED]
00107 #include "offscrn.h"        // GRenderRegionWrapper
00108 
00109 // Tags, messages and other UI stuff
00110 //#include "attrmgr.h"      // enum AttrIndex - in camtypes.h [AUTOMATICALLY REMOVED]
00111 //#include "feather.h"      // _R(IDS_FEATHER_ATTR_ID)
00112 //#include "mario.h"            // _R(IDE_NOMORE_MEMORY)
00113 
00114 // RenderRegions
00115 #include "grndrgn.h"        // GRenderRegion
00116 
00117 // Fiddling with bitmaps - offscreen and feather transp bmps
00118 //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00119 #include "oilbitmap.h"
00120 
00121 // Caching contour path and updating on pseudo AllowOps
00122 #include "opfeathr.h"       // RegenerateFeatherContourAction
00123 #include "objchge.h"        // ObjChange and AllowOp stuff
00124 #include "transop.h"        // TransOperation - optimise which operations trigger recontour
00125 
00126 // Blending (creating dynamic attributes)
00127 #include "blendatt.h"       // BlendAttrParam
00128 #include "nodeblnd.h"       // NodeBlend
00129 #include "attrmap.h"        // CCAttrMap
00130 #include "nodepath.h"
00131 
00132 // Special cases
00133 #include "nodedoc.h"        // NodeDocument
00134 //#include "grndclik.h"     // GRenderClick
00135 //#include "grndbrsh.h"     // GRenderBrush
00136 
00137 // Saving and loading
00138 #include "cxftags.h"
00139 //#include "cxfdefs.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00140 //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00141 
00142 // Printing
00143 //#include "saveeps.h"
00144 
00145 // Quality settings
00146 #include "qualattr.h"
00147 
00148 #include "nodemold.h"
00149 //#include "bitmapcache.h"
00150 #include "pathndge.h"
00151 
00152 //DECLARE_SOURCE("$Revision: 1738 $")
00153 
00154 CC_IMPLEMENT_DYNCREATE( FeatherAttrValue, OffscreenAttrValue )
00155 CC_IMPLEMENT_DYNAMIC( AttrFeather, NodeAttribute )
00156 CC_IMPLEMENT_DYNAMIC( FeatherRecordHandler,CamelotRecordHandler )
00157 
00158 // Declare smart memory handling in Debug builds
00159 #define new CAM_DEBUG_NEW   
00160 
00161 // Uncomment any of the following to attach the associated bitmap into the bitmap gallery
00162 //#define DEBUG_ATTACH_PRECONV_OFFSCREEN_BMP
00163 //#define DEBUG_ATTACH_OFFSCREEN_BMP
00164 //#define DEBUG_ATTACH_SILHOUETTE_BMP
00165 //#define DEBUG_ATTACH_FEATHER_BMP
00166 //#define DEBUG_RENDER_OFFSCREEN_BMP_WITHOUT_MASK
00167 
00168 // The maximum feather size which we allow the user to play with.
00169 // If you're thinking of changing this, PLEASE BE AWARE that other/older versions
00170 // of the app will cap feathers loaded/pasted into them at THEIR maximum value.
00171 // As of 30/01/2001, GDraw's maximum blur size is a 200 pixel diameter.
00172 // I'm choosing a user limit of 50 pixels diameter at 96dpi (100% zoom on most systems)
00173 // which gives 50 * (72000 / 96) = 37500 millipoints.
00174 //
00175 const MILLIPOINT FeatherAttrValue::MaxUserFeatherSize = 37500;
00176 
00177 
00179 //
00180 //                              Helper functions
00181 //
00183 // TRUE if map contains all necessary line attrs for NodePath::MakeNodePathFromAttributes to succeed
00184 // FALSE otherwise
00185 BOOL CheckLineAttrs(CCAttrMap* pAttrMap)
00186 {
00187     void* ptr = NULL;
00188     return (
00189         pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrLineWidth),(void *&)ptr) &&
00190         pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStartArrow),(void *&)ptr) &&
00191         pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrEndArrow),(void *&)ptr) &&
00192         pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrJoinType),(void *&)ptr) &&
00193         pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStartCap),(void *&)ptr) &&
00194         pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrDashPattern),(void *&)ptr)
00195         );
00196 }
00197 
00198 BOOL MakeLineAttributeCompleteForContouring(Node* Context, Node* NodeToModify, CCAttrMap* pAttrMap)
00199 {
00200     AttrLineWidth * pAttrLineWidth = NULL;
00201     AttrStartArrow * pAttrStartArrow = NULL;
00202     AttrEndArrow * pAttrEndArrow = NULL;
00203     AttrJoinType * pAttrJoinType = NULL;
00204     AttrStartCap * pAttrStartCap = NULL;
00205     AttrDashPattern * pAttrDashPattern = NULL;
00206     AttrStrokeColour* pAttrStrokeColour = NULL;
00207 
00208     // get all the attributes out of the attribute map
00209     pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrLineWidth),(void *&)pAttrLineWidth);
00210     if(pAttrLineWidth)
00211         pAttrLineWidth->AttachNode(Context,FIRSTCHILD,FALSE,FALSE);
00212         
00213     pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStartArrow),(void *&)pAttrStartArrow);
00214     if (pAttrStartArrow)
00215         pAttrStartArrow->AttachNode(Context,FIRSTCHILD,FALSE,FALSE);
00216 
00217     pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrEndArrow),(void *&)pAttrEndArrow);
00218     if (pAttrEndArrow)
00219         pAttrEndArrow->AttachNode(Context,FIRSTCHILD,FALSE,FALSE);
00220 
00221     pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrJoinType),(void *&)pAttrJoinType);
00222     if(pAttrJoinType)
00223         pAttrJoinType->AttachNode(Context,FIRSTCHILD,FALSE,FALSE);
00224         
00225     pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStartCap),(void *&)pAttrStartCap);
00226     if(pAttrStartCap)
00227         pAttrStartCap->AttachNode(Context,FIRSTCHILD,FALSE,FALSE);
00228         
00229     pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrDashPattern),(void *&)pAttrDashPattern);
00230     if(pAttrDashPattern)
00231         pAttrDashPattern->AttachNode(Context,FIRSTCHILD,FALSE,FALSE);
00232 
00233     pAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStrokeColour),(void *&)pAttrStrokeColour);
00234     if(pAttrStrokeColour)
00235         pAttrStrokeColour->AttachNode(Context,FIRSTCHILD,FALSE,FALSE);
00236 
00237     if( pAttrLineWidth && pAttrStartArrow && pAttrEndArrow && pAttrJoinType && 
00238         pAttrStartCap && pAttrDashPattern && pAttrStrokeColour)
00239     {
00240         Node* pLastChild = Context->FindLastChild();
00241         NodeToModify->AttachNode(pLastChild,NEXT,FALSE,FALSE);  // dynamic attrs are copies, so we are free to modify them
00242         return TRUE;
00243     }
00244     else
00245     {
00246         return FALSE;
00247     }
00248 }
00249 
00250 
00252 //
00253 //                              AttributeValue classes
00254 //
00256 
00257 /********************************************************************************************
00258 >   FeatherAttrValue::
00259     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
00260     Created:    24/01/2000
00261     Purpose:    This constructor is called in three different scenarios:-
00262                 1 - to initialise attrvalue tables
00263                 2 - to create a new feather to apply to a selected node by an OpFeather operation
00264                 3 - in the process of creating a simple copy of an exisiting Feather attr
00265                     ie. either a default attr from the attr table (to attach to a new node)
00266                     or  a clone of an AttrFeather __node__ (ie as part of OpClone)
00267                 The initialisation process will always create 0 width default feather attributes
00268                 and hence will always attach 0 width feathers as the documents base feather attr.
00269 
00270     SeeAlso:    
00271  ********************************************************************************************/
00272 FeatherAttrValue::FeatherAttrValue()
00273 {
00274 //  m_Profile = CProfileBiasGain()              // Defaults to this
00275     m_GapSize = DEFAULT_GAP_TOLERANCE_MP;
00276     m_FeatherSize = 0;                          // Document base Feather has 0 feather size.
00277                                                 // The doc base feather is created when camelot
00278                                                 // initialises a new document.
00279                                                 // The default feather applied to each new object
00280                                                 // is also setup by this constructor.
00281     m_pOuterContour = NULL;
00282     m_bCached = FALSE;
00283 }
00284 
00285 /********************************************************************************************
00286 >   FeatherAttrValue::
00287     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
00288     Created:    24/01/2000
00289     Purpose:    Free outer contour path if we have one
00290     SeeAlso:    
00291  ********************************************************************************************/
00292 FeatherAttrValue::~FeatherAttrValue()
00293 {
00294     // only m_pOuterContour may be left because it is cached
00295     if (m_pOuterContour != NULL)
00296     {
00297         delete m_pOuterContour;
00298         m_pOuterContour = NULL;
00299     }
00300 }
00301 
00302 /********************************************************************************************
00303 >   FeatherAttrValue::
00304     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
00305     Created:    24/01/2000
00306     Purpose:    
00307     SeeAlso:    
00308  ********************************************************************************************/
00309 BOOL FeatherAttrValue::Init()
00310 {
00311     // Default to no feathering
00312     FeatherAttrValue *pAttr = new FeatherAttrValue;
00313     if (pAttr==NULL)
00314         // error message has already been set by new
00315         return FALSE;
00316 
00317     pAttr->SetDefault();
00318 
00319     UINT32 AttrID = AttributeManager::RegisterDefaultAttribute(CC_RUNTIME_CLASS(NodeRenderableInk),
00320                                                          pAttr);
00321 
00322     ERROR2IF(AttrID == ATTR_BAD_ID, FALSE, "Bad ID when Initialising FeatherAttrValue");
00323     ERROR2IF(AttrID != ATTR_FEATHER, FALSE, "Incorrect ID for FeatherAttrValue");
00324 
00325     return TRUE;
00326 }
00327 
00328 /********************************************************************************************
00329 >   FeatherAttrValue::
00330     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
00331     Created:    24/01/2000
00332     Purpose:    
00333     SeeAlso:    
00334     TODO:       Determine whether to copy bitmap or just pointer to it
00335  ********************************************************************************************/
00336 void FeatherAttrValue::SimpleCopy(AttributeValue *pVal)
00337 {
00338     ERROR3IF(!pVal->IS_KIND_OF(FeatherAttrValue), "Incorrect runtime class passed to FeatherAttrValue::SimpleCopy");
00339     FeatherAttrValue* pFthr = (FeatherAttrValue*) pVal;
00340 
00341     m_Profile = pFthr->m_Profile;
00342     SetFeatherSize(pFthr->GetFeatherSize());
00343     m_GapSize = pFthr->m_GapSize;
00344 
00345 // NOTE! Don't copy m_outerContour because callers assume that this will
00346 // not be copied and rely on it being regenerated on demand. Urgh!
00347     // Remember to copy or blank cached path data without leaking memory...
00348     if (m_pOuterContour)
00349         delete m_pOuterContour;
00350     m_pOuterContour = NULL;
00351 /*
00352     Path* pSrcPath = pFthr->GetOuterContour();
00353     if (pSrcPath)
00354     {
00355         m_pOuterContour = new Path();
00356         m_pOuterContour->Initialise(pSrcPath->GetNumCoords());
00357         m_pOuterContour->CopyPathDataFrom(pSrcPath);
00358     }
00359 */
00360     // preserves default flag to avoid confusion when copying CCAttrMaps
00361     GeometryLinkedAttrValue::SimpleCopy(pVal);
00362 }
00363     
00364 /********************************************************************************************
00365 >   FeatherAttrValue::
00366     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
00367     Created:    24/01/2000
00368     Purpose:    
00369     SeeAlso:    
00370  ********************************************************************************************/
00371 NodeAttribute* FeatherAttrValue::MakeNode()
00372 {
00373     AttrFeather* pNode = new AttrFeather();
00374     pNode->Value.SimpleCopy(this);
00375     return pNode;
00376 }
00377 
00378 /********************************************************************************************
00379 >   FeatherAttrValue::
00380     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
00381     Created:    24/01/2000
00382     Purpose:    
00383     SeeAlso:    
00384  ********************************************************************************************/
00385 BOOL FeatherAttrValue::Blend(BlendAttrParam* pBlendParam)
00386 {
00387     // First get the fill that we are blending to
00388     FeatherAttrValue* OtherFthr = (FeatherAttrValue*)pBlendParam->GetOtherAttrVal();
00389 
00390     if(IsDefaultFlagSet() && OtherFthr->IsDefaultFlagSet())
00391     {
00392         // no blending required
00393 //      pBlendParam->SetBlendedAttrVal(NULL);
00394         return FALSE;
00395     }
00396 
00397 
00398     FeatherAttrValue* pNewAttr = new FeatherAttrValue;
00399 
00400     if (pNewAttr == NULL)
00401     {
00402         // Fail if we couldn't create the new fill
00403         pBlendParam->SetBlendedAttrVal(NULL);
00404         return FALSE;
00405     }
00406 
00407     // and what point along the blend we are at
00408     double Ratio = pBlendParam->GetBlendRatio();
00409 
00410     // blend m_pFeatherWidth
00411     MILLIPOINT Start = GetFeatherSize();
00412     MILLIPOINT End = OtherFthr->GetFeatherSize();
00413     pNewAttr->SetFeatherSize( (MILLIPOINT) ( Start + Ratio*(End - Start) ) );
00414 
00415     // blend m_Profile
00416     CProfileBiasGain BiasGain = m_Profile;                      // the first fills profile
00417     CProfileBiasGain OtherBiasGain = OtherFthr->m_Profile;      // the other fills profile
00418     if (!(BiasGain == OtherBiasGain))
00419     {
00420 /*      From other blend Profiles code
00421         double InvRatio = 1 - Ratio;
00422         double BlendedBias = (BiasGain.GetBias () * InvRatio) + (OtherBiasGain.GetBias () * Ratio);
00423         double BlendedGain = (BiasGain.GetGain () * InvRatio) + (OtherBiasGain.GetGain () * Ratio);
00424 */
00425         double StartBias = m_Profile.GetBias(); double EndBias = OtherBiasGain.GetBias();
00426         double StartGain = m_Profile.GetGain(); double EndGain = OtherBiasGain.GetGain();
00427         double BlendedBias = StartBias + ((EndBias - StartBias) * Ratio);
00428         double BlendedGain = StartGain + ((EndGain - StartGain) * Ratio);
00429 
00430         pNewAttr->m_Profile.SetBias (BlendedBias);
00431         pNewAttr->m_Profile.SetGain (BlendedGain);
00432     }
00433 
00434     // Set the new fill as the blended attribute
00435     pBlendParam->SetBlendedAttrVal(pNewAttr);
00436 
00437     return TRUE;
00438 }
00439 
00440 /********************************************************************************************
00441 >   FeatherAttrValue::
00442     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
00443     Created:    24/01/2000
00444     Purpose:    Put the GRenderRegion offscreen rendering system into play (provided we're
00445                 dealing with a real feather attribute and not just the base doc attr).
00446     SeeAlso:    GRenderRegion::SetFeathering, FeatherAttrValue::OffscreenRenderingCompleted()
00447  ********************************************************************************************/
00448 void FeatherAttrValue::Render(RenderRegion *pRender, BOOL Temp)
00449 {
00450 //  TRACEUSER( "Gerry", _T("Rendering feather attribute of %d (0x%08x)\n"), GetFeatherSize(), this);
00451     
00452     // Karim 20/07/2000
00453     // currently, we only generate an offscreen bitmap for GRenderRegions, although we are
00454     // 'rendered' into all RR's. therefore we must quit quietly if pRender is not a GRR.
00455     // Gerry 12/01/2005
00456     // This is no longer true.  We need to render this into all types of render region
00457     // so the code has been removed
00458     
00459 //  if (!pRender->IS_KIND_OF(GRenderRegion))
00460 //      return;
00461 
00462     // if the feather size is zero, then quit now - no feathering is necessary.
00463     MILLIPOINT mpFeather = GetFeatherSize();
00464     if (mpFeather == 0)
00465         return;
00466 
00467     // ... and shout out if the feather size is negative - something is WRONG!
00468     else if (mpFeather < 0)
00469     {
00470         ERROR3("Negative feather size! What's going on?");
00471         return;
00472     }
00473 
00474     // you would place code here if you need to affect currentAttrs table
00475     // also alloc any mem you need for the duration of the rendering cycle
00476     OffscreenAttrValue::Render(pRender, Temp);
00477 }
00478 
00479 /********************************************************************************************
00480 >   FeatherAttrValue::
00481     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
00482     Created:    24/01/2000
00483     Purpose:    
00484     SeeAlso:    GRenderRegion::RestoreGDrawBitmap
00485  ********************************************************************************************/
00486 void FeatherAttrValue::Restore(RenderRegion *pRegion, BOOL Temp)
00487 {
00488 //TRACEUSER( "Phil", _T("Restoring feather attribute of %d (0x%08x)\n"), GetFeatherSize(), this);
00489     // NB this function doesn't need to be implemented - the base class handles everything
00490     // Just showing you where to put extra code
00491 
00492     OffscreenAttrValue::Restore(pRegion, Temp);
00493 }
00494 
00495 /********************************************************************************************
00496 >   FeatherAttrValue::
00497     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
00498     Created:    24/01/2000
00499     Purpose:    The random nature of generation of redraw cliprect coordinates means that we
00500                 may sometimes be asked to redraw a really thin sliver of the feathered object.
00501                 This is a problem for the convolution code if the sliver is thinner (in height
00502                 or width) than 2 pixels.
00503     SeeAlso:    GRenderRegion::RestoreGDrawBitmap
00504  ********************************************************************************************/
00505 void FeatherAttrValue::GetMinimumOffscreenBmpDimensions(UINT32* RequiredWidth, UINT32* RequiredHeight)
00506 {
00507     *RequiredWidth = 2;
00508     *RequiredHeight = 2;
00509 }
00510 
00511 /********************************************************************************************
00512 >   FeatherAttrValue::
00513     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
00514     Created:    24/01/2000
00515     Purpose:    To allow the offscreen attribute to perform whatever processing it requires on
00516                 the bitmap copy of the subtree rooted at m_pLinkedNode and then draw into the partially
00517                 rendered bitmap of the predecessors of m_pLinkedNode
00518 
00519     Notes:      1)  This function gets called when the RR exits the context under which the
00520                 attribute was Render()ed (ie after completeing a DrawPath("this->m_pLinkedNode->Path").
00521                 2)  The offscreen rendering system (implemented in GRenderRegion) has already
00522                 restored the clip rect and GDraw bitmap and matrix state of the previous offscreen
00523                 attribute.
00524                     This function is actually being called by the RenderRegion in the process of
00525                 Restore()ing this previous offscreen attribute (ie the process of taking the attribute
00526                 which is sitting on top of the attribute context stack, and restoring it to the
00527                 CurrentAttrs table).
00528                     So at this point the GRenderRegion and GDraw context are back the way they
00529                 were before "this" offscreen attribute was Render()ed.
00530                 3)  m_pOffscreenBmpBits points to the buffer holding the fully rendered bitmap
00531                 of the subtree rooted at m_pLinkedNode
00532                 4)  Any transparency attribute existing at the same level as this offscreen attr
00533                 (ie attached to "this->m_pLinkedNode") will already have affected the bitmap in
00534                 "this->m_pOffscreenBmpBits".
00535                 5)  You don't need to delete the bitmap pointers UNLESS you installed "this" attribute
00536                 as a non-temporary attribute in the Render() function (ie SetFeathering(this, FALSE..)).
00537                 If it is a temporary attribute (which is the default) then the deconstructor will handle
00538                 the deallocation of the memory pointed to by m_pOffscreenBmpBits & m_pOffscreenBmpInfo
00539     SeeAlso:    GRenderRegion::RestoreFeathering(); ~FeatherAttrValue(); RenderRegion::RestoreAttribute()
00540                 FeatherAttrValue::Render(), GRenderRegion::SetFeathering()
00541  ********************************************************************************************/
00542 void FeatherAttrValue::OffscreenRenderingCompleted(RenderRegion *pRender, LPBITMAPINFO lpBitmapInfo, LPBYTE lpBits, DocRect BitmapRect)
00543 {
00544 //  TRACEUSER( "Gerry", _T("Feather attribute OffscreenRenderingCompleted (0x%08x)\n"), this);
00545 //  TRACEUSER( "Phil", _T("Feather attribute OffscreenRenderingCompleted (0x%08x)\n"), this);
00546 
00547 // TEMP BODGE
00548     m_OffBB = BitmapRect;
00549 
00550     // Karim 20/07/2000
00551     // currently, we only generate an offscreen bitmap for GRenderRegions, although we are
00552     // 'rendered' into all RR's. therefore we must quit quietly if pRender is not a GRR.
00553     if (!pRender->IS_KIND_OF(GRenderRegion))
00554         return;
00555 
00556     GRenderRegion* pGRR = (GRenderRegion*)pRender;
00557     RRCaps Caps;
00558     pGRR->GetRenderRegionCaps(&Caps);
00559     if (!Caps.DoesRegionDoAll())
00560         return;
00561 
00562     // Karim 19/10/2000
00563     // The offscreen rendering may possibly fail,
00564     // in which case all we can do now is quit.
00565     if (lpBitmapInfo == NULL || lpBits == NULL)
00566     {
00567 //      ERROR3("FeatherAttrValue::OffscreenRenderingCompleted; don't have any bitmap info!");
00568         return;
00569     }
00570 
00571     double fScaledPixelWidth = pGRR->GetScaledPixelWidthDouble();
00572 //  TRACEUSER( "Gerry", _T("ScaledPixelWidth = %f\n"), fScaledPixelWidth);
00573     double pixBlurDiameter = GetFeatherPixelSize(fScaledPixelWidth);
00574 //  TRACEUSER( "Gerry", _T("BlurDiameter = %f\n"), pixBlurDiameter);
00575 
00576     // Setup path to draw
00577     Path* pPathToDraw = GetVisibleBoundingPath();
00578     if (pPathToDraw == NULL)
00579     {
00580         ERROR3("FeatherAttrValue::OffscreenRenderingCompleted; Couldn't create path!");
00581         return;
00582     }
00583 
00585     //  Create the bitmap fill containing the offscreen rendition of the objects to feather.
00587 
00588     CWxBitmap          *wBitmap = NULL;
00589     KernelBitmap       *OffscreenBitmap = NULL;
00590 
00591 //  TRACEUSER( "Gerry", _T("Offscreen size = (%d, %d)\n"), pOffBmpHdr->biWidth, pOffBmpHdr->biHeight);
00592 
00593     // Create a Kernel bitmap from the bmp data.
00594     wBitmap         = new CWxBitmap(lpBitmapInfo, lpBits);
00595     OffscreenBitmap = new KernelBitmap(wBitmap,TRUE);
00596 
00597     // Setup the bitmap fill.
00598     // Since the offscreen bitmap has been plotted using the full rendering matrix
00599     // which may include a rotation during printing, we must now force GDraw to
00600     // render it using the same rotation (see GRenderRegion::AllocateOffScreenState)
00601     BitmapFillAttribute BmpFill;
00602     ANGLE rot;
00603     Matrix m = pGRR->GetMatrix();
00604     m.Decompose(NULL, NULL, &rot, NULL, NULL);
00605     if (rot==0)
00606 //      CreateBitmapFill(OffscreenBitmap, &m_OffBB, &BmpFill);
00607         CreateBitmapFill(OffscreenBitmap, &BitmapRect, &BmpFill);
00608     else
00609 //      CreateBitmapFillRot90(OffscreenBitmap, &m_OffBB, &BmpFill);
00610         CreateBitmapFillRot90(OffscreenBitmap, &BitmapRect, &BmpFill);
00611     // No other rotations are currently possible...
00612 
00613 // DEBUG: add offscreen bmp to bitmap gallery
00614 #ifdef DEBUG_ATTACH_OFFSCREEN_BMP
00615     OffscreenBitmap->AttachDebugCopyToCurrentDocument("Offscreen Bitmap");
00616 #endif
00617 
00618 
00620     //  Create the feather bitmap transparency mask.
00622 
00623     KernelBitmap* FeatherBitmap = CreateFeatherBitmap(pGRR, pixBlurDiameter);
00624 
00625     BitmapTranspFillAttribute BmpTranspFill;
00626     if (FeatherBitmap != NULL)
00627     {
00628         CreateBitmapTranspFill(FeatherBitmap, &m_drFeatherBB, &BmpTranspFill);
00629     }
00630 
00631 
00633     //  Render the bitmaps together for the final feathered result.
00634     //
00635     //  If we had any problems creating the feather bitmap transparency, or if our debug
00636     //  rendering is enabled, then we try to fail gracefully by rendering just the
00637     //  offscreen bitmap. Note that this bitmap will only have an alpha channel if some of
00638     //  the feathered objects require it, and will have a white background otherwise.
00640     pGRR->SaveContext();
00641 
00642 // DEBUG: see note above.
00643 #ifndef DEBUG_RENDER_OFFSCREEN_BMP_WITHOUT_MASK
00644     if (FeatherBitmap != NULL)
00645         pGRR->RenderBitmapWithTransparency(pPathToDraw, &BmpFill, &BmpTranspFill);
00646 #else
00647     pGRR->RenderBitmapWithTransparency(pPathToDraw, &BmpFill, NULL);
00648 #endif
00649 
00650     pGRR->RestoreContext();
00651 
00653     //  Clean up all our data structures.
00655     if (FeatherBitmap != NULL)
00656     {
00657         delete FeatherBitmap;
00658         FeatherBitmap = NULL;
00659     }
00660 
00661     if (pPathToDraw != NULL)
00662     {
00663         delete pPathToDraw;
00664         pPathToDraw = NULL;
00665     }
00666 
00667     FreeDIB(lpBitmapInfo, lpBits, NULL, FALSE);
00668 
00669     // makes ~CWxBitmap() think that bmp HasBeenDeleted().
00670     wBitmap->BMBytes = ( (CWxBitmap *)OILBitmap::Default )->BMBytes;
00671     delete OffscreenBitmap;
00672 }
00673 
00674 
00675 
00676 
00677 /********************************************************************************************
00678 
00679 >   virtual BOOL FeatherAttrValue::CreateFeatherTransp( GRenderRegion* pGRR,
00680                                                         Path* pPath,
00681                                                         double dPixelWidth,
00682                                                         BitmapTranspFillAttribute** ppFeatherTransp,
00683                                                         KernelBitmap** ppFeatherBitmap
00684                                                         )
00685 
00686     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00687     Created:    05/08/2005
00688     Inputs:     pPath           - Pointer to path to be feathered
00689                 dPixelWidth     - Pixel width in millipoints
00690     Outputs:    pFeatherTransp  - Pointer to transparency attribute for feathering
00691                 pFeatherBitmap  - POinter to feather bitmap used in transparency attribute
00692     Returns:    TRUE if it worked
00693                 FALSE otherwise
00694     Purpose:    Create the feather transparency attribute using the supplied path /without/
00695                 reference to any surrounding nodes in the tree
00696                 Used by NodeBitmap::GetDirectBitmap
00697 
00698 ********************************************************************************************/
00699 BOOL FeatherAttrValue::CreateFeatherTransp( GRenderRegion* pGRR,
00700                                             Path* pPath,
00701                                             double dPixelWidth,
00702                                             BitmapTranspFillAttribute** ppFeatherTransp,
00703                                             KernelBitmap** ppFeatherBitmap
00704                                             )
00705 {
00706     double dpixBlurDiameter = GetFeatherPixelSize(dPixelWidth);
00707     LPBYTE          pFeatherBits    = NULL;
00708     LPBITMAPINFO    pFeatherInfo    = NULL;
00709     KernelBitmap*   kbmpFeather     = NULL;
00710     DocRect         rectBounds      = pPath->GetBoundingRect();
00711 //  UINT32          pixWidth        = UINT32(floor( rectBounds.Width() / dPixelWidth + 0.5 ));
00712 //  UINT32          pixHeight       = UINT32(floor( rectBounds.Height() / dPixelWidth + 0.5 ));
00713 
00714     // -------------------------------------------------------------------
00715     // First make the silhouette bitmap
00716     // create the silhouette bitmap.
00717     m_OffBB = rectBounds;
00718     m_GapSize = 0;
00719     LPBYTE          pSilhouetteBits;
00720     LPBITMAPINFO    pSilhouetteInfo = CreateSilhouetteBitmap(pGRR, &pSilhouetteBits, pPath);
00721 
00722     if (pSilhouetteInfo==NULL || pSilhouetteBits==NULL)
00723         return FALSE;
00724 
00725     // -------------------------------------------------------------------
00726     // Next blur the silhouette bitmap to obtain the feather bitmap.
00727     pFeatherInfo = CBitmapShadow::Feather8BppBitmap(
00728                                                     dpixBlurDiameter,
00729                                                     pSilhouetteInfo,
00730                                                     pSilhouetteBits,
00731                                                     &pFeatherBits
00732                                                 );
00733 
00734     // If Feather8BPP returned the same bitmap, clear silhouette pointers so we don't
00735     // deallocate the bitmap at the end of this function...
00736     if (pFeatherInfo == pSilhouetteInfo)
00737     {
00738         pSilhouetteInfo = NULL;
00739         pSilhouetteBits = NULL;
00740     }
00741 
00742     if (pFeatherInfo != NULL && pFeatherBits != NULL)
00743     {
00744         CWxBitmap*      wbmpFeather = new CWxBitmap(pFeatherInfo, pFeatherBits);
00745                         kbmpFeather = new KernelBitmap(wbmpFeather, TRUE);
00746 
00747         SetupFeatherBitmapPalette(kbmpFeather);
00748 
00749         *ppFeatherBitmap = kbmpFeather;
00750     }
00751 
00752     // We don't need the silhouette bitmap any more
00753     if (pSilhouetteInfo != NULL && pSilhouetteBits != NULL)
00754         FreeDIB(pSilhouetteInfo, pSilhouetteBits);
00755 
00756     // If we failed to create the blurred bitmap then exit now
00757     if (*ppFeatherBitmap==NULL)
00758         return FALSE;
00759 
00760     // ----------------------------------------------------------------------
00761     // Now make the transparency attribute to carry the feather bitmap
00762     *ppFeatherTransp  = new BitmapTranspFillAttribute;
00763     if (*ppFeatherTransp==NULL)
00764     {
00765         delete *ppFeatherBitmap;
00766         *ppFeatherBitmap = NULL;
00767         return FALSE;
00768     }
00769 
00770     CreateBitmapTranspFill(*ppFeatherBitmap, &rectBounds, *ppFeatherTransp);
00771 
00772     return TRUE;
00773 }
00774 
00775 
00776 
00777 
00778 /********************************************************************************************
00779 
00780 >   virtual BOOL FeatherAttrValue::DoesOffscreenBmpRequireTransp(GRenderRegion* pGRR)
00781 
00782     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
00783     Created:    19/11/2000
00784 
00785     Inputs:     pGRR    the RR which the feather will be rendered into.
00786 
00787     Purpose:    Override of OffscreenAttrValue virtual function.
00788                 Feathers always require a transparent bitmap if their feather size is less
00789                 than a certain value, otherwise they use the default implementation.
00790 
00791                 This prevents white artifacts on small feather sizes.
00792 
00793     See also:   CreateSilhouetteBitmap, OffscreenAttrValue::DoesOffscreenBmpRequireTransp.
00794 
00795 ********************************************************************************************/
00796 BOOL FeatherAttrValue::DoesOffscreenBmpRequireTransp(GRenderRegion* pGRR)
00797 {
00798 // In conjunction with DoesOffscreenBMPCaptureBackground this function should
00799 // now return FALSE always so that the offscreen bitmap does not attempt to
00800 // capture transparency info but rather captures the RESULTS of transparency...
00801     if (DoesOffscreenBMPCaptureBackground())
00802         return FALSE;
00803 
00804     if (pGRR == NULL)
00805     {
00806         ERROR3("FeatherAttrValue::DoesOffscreenBmpRequireTransp; Invalid params!");
00807         return FALSE;
00808     }
00809 
00810     const double ScaledPixelWidth = pGRR->GetScaledPixelWidthDouble();
00811     const double FeatherPixelSize = GetFeatherPixelSize(ScaledPixelWidth);
00812 
00813     return (FeatherPixelSize < 2*MIN_BLUR_DIAMETER) ? TRUE :
00814             OffscreenAttrValue::DoesOffscreenBmpRequireTransp(pGRR) ;
00815 }
00816 
00817 
00818 
00819 /********************************************************************************************
00820 
00821 >   KernelBitmap* FeatherAttrValue::CreateFeatherBitmap(GRenderRegion* pGRR,
00822                                                         double pixBlurDiameter)
00823     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
00824     Created:    19 September 2000
00825     Inputs:     pGRR                the GRenderRegion to base the silhouette bitmap on.
00826                 pixBlurDiameter     feather blur width, in pixels (can be non-integer).
00827 
00828     Returns:    A ptr to a KernelBitmap containing the transparency mask part of the feather.
00829 
00830     Purpose:    Create the feather bitmap-transparency mask.
00831 
00832     See Also:   CreateSilhouetteBitmap().
00833 
00834 ********************************************************************************************/
00835 KernelBitmap* FeatherAttrValue::CreateFeatherBitmap(GRenderRegion* pGRR,
00836                                                     double pixBlurDiameter)
00837 {
00838     // will contain the feather bitmap transparency mask.
00839     LPBYTE          pFeatherBits    = NULL;
00840     LPBITMAPINFO    pFeatherInfo    = NULL;
00841     KernelBitmap*   kbmpFeather     = NULL;
00842 
00843     // create the silhouette bitmap.
00844     LPBYTE          pSilhouetteBits;
00845     LPBITMAPINFO    pSilhouetteInfo = CreateSilhouetteBitmap(pGRR, &pSilhouetteBits);
00846 
00847     if (pSilhouetteInfo != NULL && pSilhouetteBits != NULL)
00848     {
00849 //      TRACEUSER( "Gerry", _T("Silhouette size = (%d, %d)\n"), pSilhouetteInfo->bmiHeader.biWidth, pSilhouetteInfo->bmiHeader.biHeight);
00850 
00851         // blur the silhouette bitmap to obtain the feather bitmap.
00852         pFeatherInfo = CBitmapShadow::Feather8BppBitmap(
00853                                                         pixBlurDiameter,
00854                                                         pSilhouetteInfo,
00855                                                         pSilhouetteBits,
00856                                                         &pFeatherBits
00857                                                     );
00858 
00859         // If Feather8BPP returned the same bitmap, clear silhouette pointers so we don't
00860         // deallocate the bitmap at the end of this function...
00861         if (pFeatherInfo == pSilhouetteInfo)
00862         {
00863             pSilhouetteInfo = NULL;
00864             pSilhouetteBits = NULL;
00865         }
00866 
00867         if (pFeatherInfo != NULL && pFeatherBits != NULL)
00868         {
00869 //          TRACEUSER( "Gerry", _T("Feather size = (%d, %d)\n"), pFeatherInfo->bmiHeader.biWidth, pFeatherInfo->bmiHeader.biHeight);
00870             CWxBitmap*      wbmpFeather = new CWxBitmap(pFeatherInfo, pFeatherBits);
00871                             kbmpFeather = new KernelBitmap(wbmpFeather, TRUE);
00872 
00873             SetupFeatherBitmapPalette(kbmpFeather);
00874         }
00875     }
00876 
00878 //
00879 // DEBUG: add copies of the silhouette and feather bitmaps to the bitmap gallery.
00880 //
00881 #ifdef DEBUG_ATTACH_SILHOUETTE_BMP
00882     if (pSilhouetteInfo != NULL && pSilhouetteBits != NULL)
00883     {
00884         CWxBitmap*      wbmpSilhouette = new CWxBitmap(pSilhouetteInfo, pSilhouetteBits);
00885         KernelBitmap*   kbmpSilhouette = new KernelBitmap(wbmpSilhouette, TRUE);
00886 
00887         SetupFeatherBitmapPalette(kbmpSilhouette);
00888         kbmpSilhouette->AttachDebugCopyToCurrentDocument("Silhouette Bitmap");
00889 
00890         wbmpSilhouette->BMBytes = ((CWxBitmap*)OILBitmap::Default)->BMBytes;
00891         delete kbmpSilhouette;
00892     }
00893 #endif
00894 
00895 #ifdef DEBUG_ATTACH_FEATHER_BMP
00896     if (kbmpFeather != NULL)
00897     {
00898         kbmpFeather->AttachDebugCopyToCurrentDocument("Feather Mask Bitmap");
00899     }
00900 #endif
00901 //
00903 
00904     // Silhouette bitmap does not use limited mem manager, so free its DIB ourself.
00905     if (pSilhouetteInfo != NULL && pSilhouetteBits != NULL)
00906         FreeDIB(pSilhouetteInfo, pSilhouetteBits, NULL, FALSE);
00907 
00908     return kbmpFeather;
00909 }
00910 
00911 
00912 
00913 /********************************************************************************************
00914 >   FeatherAttrValue::
00915     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
00916     Created:    03/04/2000
00917     Inputs:     ppBmpBits = pointer to a LPBYTE pointer which we should allocate memory for
00918     Outputs:    ppBmpBits = monochrome bitmap of the outline of the feathered object(s)
00919     Returns:    BitmapInfo structure describing the mono bitmap @ **ppBmpBits
00920     Purpose:    Create a monochrome image of the accumulated path, using a white outline so the
00921                 resulting image matches the inner contour of the path. The thickness of the line
00922                 is determined by the feather width.
00923                 NB line width is centred about the path outline. Hence if we require the inner
00924                 contour to be featherwidth pixels inside the outline, then need to use a line
00925                 width of 2*FeatherSize
00926                 NB2 Feathersize is moderated to max 40 pix
00927     SeeAlso:    FeatherAttrValue::GetFeatherSize,OffscreenRenderingCompleted,Render
00928                 PathAccumulatorPathProcessor
00929                 OffscreenRenderer
00930     TechnicalNotes: leverages the offscreen rendering system to get the active renderegion to
00931                     render the path into a new bitmap and then restore the renderregion to the
00932                     way it was.
00933                     
00934                     I order to avoid DWORD aligning overhead in the convolution code we always
00935                     render into bitmaps which are DWORD aligned. This means we need to be careful
00936                     when creating a transparency attribute to hold the mask as we must use
00937                     the aligned co-ords, not m_OffBB otherwise we will introduce scaling.
00938                     NB we do this by drawing more pixels on the right hand border to account
00939                     for the alignment.
00940     NB NB NB
00941     Non-technical notes: these notes are out of date so ignore! will fix later.
00942  **********************************************************************************************/
00943 LPBITMAPINFO FeatherAttrValue::CreateSilhouetteBitmap(GRenderRegion* GRR,
00944                                                       LPBYTE* ppBmpBits,
00945                                                       Path* pOutline)
00946 {
00947 //  ERROR3IF(m_pOffscreenBmpInfo == NULL,
00948 //          "FeatherAttrValue::CreateSilhouetteBitmap; No offscreen bitmap info.");
00949 
00950     // generate a contour of m_GapSize around the path of our linked node, to
00951     // eradicate any small gaps which would otherwise be feathered.
00952     if (pOutline==NULL)
00953     {
00954         if (m_pOuterContour == NULL)
00955             GenerateOuterContour();
00956 
00957         pOutline = m_pOuterContour;
00958     }
00959 
00960     // if we couldn't generate our outer contour, or it had no points in it,
00961     // don't try to produce a feather bitmap.
00962     if (pOutline == NULL || pOutline->GetNumCoords() == 0)
00963     {
00964         *ppBmpBits = NULL;
00965         return NULL;
00966     }
00967 
00969     //  -   Work out the appropriate size silhouette bitmap by inflating the invalid
00970     //      offscreen rectangle by the blur *radius* (half the feather size).
00971     //  -   If the blur radius is above the maximum we can do, then we work out *how*
00972     //      much bigger it is and render the silhouette bitmap appropriately scaled down.
00973     //  -   The final feather bitmap will then scale up to fill the offscreen rect,
00974     //      making it look like we actually used the requested blur radius.
00975     const   double  ScaledPixelWidth    = GRR->GetScaledPixelWidthDouble();
00976     const   double  FeatherMPSize       = GetFeatherSize();
00977     const   double  FeatherPixelSize    = GetFeatherPixelSize(ScaledPixelWidth);
00978             double  FeatherScaleFactor  = 1;
00979 
00980     DocRect drSilhouetteBounds = m_OffBB;
00981     m_drFeatherBB = drSilhouetteBounds;
00982     if (FeatherPixelSize >= MIN_BLUR_DIAMETER)
00983     {
00984         // requested blur diameter  = BlurPixDiam pixels.
00985         // actual blur we can do    = FeatherPixelSize pixels.
00986         double BlurPixDiam = (ScaledPixelWidth > 0) ? (FeatherMPSize / ScaledPixelWidth) : 0;
00987         if (BlurPixDiam > FeatherPixelSize)
00988         {
00989             FeatherScaleFactor = BlurPixDiam / FeatherPixelSize;
00990 
00991             // Scale the silhouette around its centre by the feather scale factor.
00992             // This is so that the rendered silhouette bitmap is has a width of
00993             // at least (2 * FeatherRadius + 1) pixels.
00994             double BoundsSF = (FeatherScaleFactor - 1.0) / 2.0;
00995             UINT32  nWidth  = (UINT32)(0.5 + (double)drSilhouetteBounds.Width() * BoundsSF);
00996             UINT32  nHeight = (UINT32)(0.5 + (double)drSilhouetteBounds.Height() * BoundsSF);
00997             drSilhouetteBounds.Inflate(nWidth, nHeight);
00998             m_drFeatherBB = drSilhouetteBounds;
00999         }
01000 
01001         // Inflate the silhouette bounds by FeatherRadius pixels around each edge.
01002         // This will shrink down to the correct bounds when blurred.
01003         const UINT32 nBlur = (UINT32)(BlurPixDiam +  0.5);
01004 
01005         UINT32 nHiInflate = (nBlur - 1) / 2;
01006         UINT32 nLoInflate = (nBlur - 1) - nHiInflate;
01007 
01008         nHiInflate = (UINT32)(ScaledPixelWidth * (double)nHiInflate);
01009         nLoInflate = (UINT32)(ScaledPixelWidth * (double)nLoInflate);
01010 
01011         drSilhouetteBounds.hi.x += nHiInflate;
01012         drSilhouetteBounds.hi.y += nHiInflate;
01013         drSilhouetteBounds.lo.x -= nLoInflate;
01014         drSilhouetteBounds.lo.y -= nLoInflate;
01015 
01016         // Don't allow further code to try to make a zero pixel silhouette bitmap
01017         if (drSilhouetteBounds.Width()<ScaledPixelWidth || drSilhouetteBounds.Height()<ScaledPixelWidth)
01018         {
01019             *ppBmpBits = NULL;
01020             return NULL;
01021         }
01022     }
01024 
01025     // create our offscreen render-region.
01026     ConcurrentRenderer* pRendWrap = NULL;
01027     pRendWrap = GRenderRegionWrapper::GetConcurrentRenderer(GRR, 1.0 / FeatherScaleFactor,
01028                                                             drSilhouetteBounds, 8, FALSE);
01029     if (pRendWrap == NULL)
01030     {
01031         *ppBmpBits = NULL;
01032         return NULL;
01033     }
01034 
01035     GRenderRegion* pLocalGRR = NULL;
01036     pLocalGRR = pRendWrap->GetRenderRegion();
01037 
01038     pLocalGRR->GetDrawContext()->SetHintingFlag(FALSE);
01039 
01040     // ask the bitmap shadower if it the final feather bitmap will be offset diagonally
01041     // by half a pixel. if this is the case then we must compensate, by rendering
01042     // the silhouette bitmap at a half-pixel offset in the other direction.
01043     if (CBitmapShadow::BlurringWillOffsetBitmap(FeatherPixelSize))
01044         pLocalGRR->OffsetByHalfPixel();
01045 
01047     // Draw into new RenderRegion which GRenderRegionWrapper has created
01049     pLocalGRR->SaveContext();
01050 
01051     // Initialise our new render-region:
01052     //  1.  Render in solid black with solid white line-widths.
01053     //  1a. Line colour now graduates from black -> off-white over 0->2*MIN_BLUR_DIAMETER.
01054     //  2.  Line width is half feather size + contour gap size, on either side.
01055     //  3.  No arrowheads/dashed lines/fancy join types.
01056     //  4.  High quality rendering, so we get anti-aliased lines.
01057 
01058     pLocalGRR->SetFillColour(COLOUR_BLACK);
01059     if (FeatherPixelSize < (2*MIN_BLUR_DIAMETER))
01060     {
01061         double RampValue = FeatherPixelSize / (2*MIN_BLUR_DIAMETER);
01062         ColourValue GreyVal(0.8 * RampValue);
01063         DocColour FeatherGrey(GreyVal, GreyVal, GreyVal);
01064         pLocalGRR->SetLineColour(FeatherGrey);
01065     }
01066     else
01067         pLocalGRR->SetLineColour(COLOUR_WHITE);
01068 
01069     pLocalGRR->SetJoinType(RoundJoin);
01070     pLocalGRR->SetStartArrow(SA_NULLARROW);
01071     pLocalGRR->SetEndArrow(SA_NULLARROW);
01072     pLocalGRR->SetDashPattern(SD_SOLID);
01073 
01074     MILLIPOINT RequiredLineWidth = (MILLIPOINT)(FeatherMPSize + 2*m_GapSize);
01075     pLocalGRR->SetLineWidth(RequiredLineWidth);
01076 
01077     FlatTranspFillAttribute NoFillTransp(TT_NoTranspType);
01078     pLocalGRR->SetTranspFillGeometry(&NoFillTransp, FALSE);
01079 
01080     StrokeTranspAttribute NoLineTransp(TT_NoTranspType);
01081     pLocalGRR->SetLineTransp(&NoLineTransp, FALSE);
01082 
01083     Quality AntiAliasQuality;
01084     AntiAliasQuality.SetQuality(Quality::QualityMax);
01085     QualityAttribute AntiAliasQualityAttr(AntiAliasQuality);
01086     pLocalGRR->SetQuality(&AntiAliasQualityAttr, FALSE);
01087 
01088     // render our contoured silhouette path into the new RR.
01089     pOutline->IsFilled  = TRUE;
01090     pOutline->IsStroked = TRUE;
01091     pLocalGRR->DrawPath(pOutline);
01092     pLocalGRR->RestoreContext();
01093 
01095     // Extract bitmap from GRenderRegionWrapper and restore GDraw state
01097     LPBITMAPINFO tmpBI;
01098     pRendWrap->GetBitmapPointers(&tmpBI, ppBmpBits);
01099     pRendWrap->RestorePreviousRendererState();
01100 
01101     return tmpBI;
01102 }
01103 
01104 
01105 
01106 /********************************************************************************************
01107 >   FeatherAttrValue::
01108     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01109     Created:    24/01/2000
01110     Purpose:    Setup the feather bitmap's palette using the bias/gain profile
01111     SeeAlso:    
01112  **********************************************************************************************/
01113 void FeatherAttrValue::SetupFeatherBitmapPalette(KernelBitmap* pFeatherBMP)
01114 {
01115     LPRGBQUAD pPalette = pFeatherBMP->GetPaletteForBitmap();
01116 
01117     // Using linear palette
01118     // For some reason we have to initialise the palette even though the rendering
01119     // code sets up the palette using the profile which is attached to the bitmap
01120     // transparency attribute which contains the feather bitmap mask.
01121     for (INT32 i = 0; i < 256; i ++)
01122     {
01123         pPalette[i].rgbRed = pPalette[i].rgbBlue = pPalette[i].rgbGreen = (BYTE)i;
01124         pPalette[i].rgbReserved = 0x00;
01125     }
01126 
01127     // Mark this bitmap as being greyscale to avoid re-conversion by GetGreyscaleVersion
01128     pFeatherBMP->SetAsGreyscale();
01129 }
01130 
01131 /********************************************************************************************
01132 >   FeatherAttrValue::
01133     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01134     Created:    24/01/2000
01135     Purpose:    
01136     SeeAlso:    
01137  ********************************************************************************************/
01138 void FeatherAttrValue::CreateBitmapFill(KernelBitmap* pBitmap, DocRect* dr, BitmapFillAttribute* BmpFill)
01139 {
01140     // Bitmap fill is the size of the current offscreen bitmap
01141     DocCoord StartPoint(dr->lo);
01142     DocCoord EndPoint(dr->hi.x,dr->lo.y);
01143     DocCoord EndPoint2(dr->lo.x,dr->hi.y);
01144     DocCoord EndPoint3(dr->hi);
01145 
01146     BmpFill->SetStartPoint(&StartPoint);
01147     BmpFill->SetEndPoint(&EndPoint);
01148     BmpFill->SetEndPoint2(&EndPoint2);
01149     BmpFill->SetEndPoint3(&EndPoint3);
01150     BmpFill->GetBitmapRef()->SetBitmap(pBitmap);
01151 }
01152 
01153 /********************************************************************************************
01154 >   FeatherAttrValue::
01155     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01156     Created:    24/01/2000
01157     Purpose:    
01158     SeeAlso:    
01159  ********************************************************************************************/
01160 void FeatherAttrValue::CreateBitmapFillRot90(KernelBitmap* pBitmap, DocRect* dr, BitmapFillAttribute* BmpFill)
01161 {
01162     // Bitmap fill is the size of the current offscreen bitmap
01163     DocCoord StartPoint(dr->hi.x, dr->lo.y);
01164     DocCoord EndPoint(dr->hi);
01165     DocCoord EndPoint2(dr->lo);
01166     DocCoord EndPoint3(dr->lo.x,dr->hi.y);
01167 
01168     BmpFill->SetStartPoint(&StartPoint);
01169     BmpFill->SetEndPoint(&EndPoint);
01170     BmpFill->SetEndPoint2(&EndPoint2);
01171     BmpFill->SetEndPoint3(&EndPoint3);
01172     BmpFill->GetBitmapRef()->SetBitmap(pBitmap);
01173 }
01174 
01175 void FeatherAttrValue::CreateBitmapTranspFill(KernelBitmap* pFeather, DocRect* dr, BitmapTranspFillAttribute* BmpTranspFill)
01176 {
01177     // Transp fill is same size as viewable part of the bitmap 
01178     DocCoord StartPoint(dr->lo);
01179     DocCoord EndPoint(dr->hi.x,dr->lo.y);
01180     DocCoord EndPoint2(dr->lo.x,dr->hi.y);
01181     DocCoord EndPoint3(dr->hi);
01182 
01183     BmpTranspFill->SetStartPoint(&StartPoint);
01184     BmpTranspFill->SetEndPoint(&EndPoint);
01185     BmpTranspFill->SetEndPoint2(&EndPoint2);
01186     BmpTranspFill->SetEndPoint3(&EndPoint3);
01187     BmpTranspFill->GetBitmapRef()->SetBitmap(pFeather);
01188     BmpTranspFill->Transp = 0;
01189     BmpTranspFill->EndTransp = 255;
01190     m_Profile.SetIsAFeatherProfile (TRUE);      // enable extra processing on the profile
01191     BmpTranspFill->SetProfile(m_Profile);
01192 }
01193 
01194 Path* FeatherAttrValue::GetVisibleBoundingPath()
01195 {
01196     DocRect dr = GetOffscreenBoundingRect();
01197     Path* p = new Path();
01198     if (p != NULL)
01199     {
01200         p->Initialise(5);
01201         p->CreatePathFromDocRect(&dr);
01202     }
01203     return p;
01204 }
01205 
01206 /********************************************************************************************
01207 >   FeatherAttrValue::
01208     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01209     Created:    24/01/2000
01210     Inputs:     pNode   - node to feather (possibly compound node)
01211                 size    - of feather region (NB millipoint = INT32, pixels = INT32)
01212                         - "INT32" rather than "MILLIPOINT" Width used to emphasize that
01213                            millipoints are expected but not only measure excepted
01214 
01215                 type    - which measurment used for size
01216     Purpose:    Setup feather member variables so that it is created properly on rendering
01217     SeeAlso:    OpFeather::Do
01218  ********************************************************************************************/
01219 BOOL FeatherAttrValue::SetupFeather(Node* pNode, INT32 Width, UnitType type)
01220 {
01221     // Get required feather size in Millipoints, taking current zoom into account
01222     // if width specified in Pixels
01223     MILLIPOINT BlurSize = ConvertMeasurementToMillipointsAtCurrentViewScale(Width,type);
01224     if (BlurSize == -1)
01225         BlurSize = DEFAULT_FEATHERSIZE_MP;
01226     SetFeatherSize(BlurSize);
01227 
01228     // Save pointer to node so we can get at it in the rendering code.
01229     SetLinkedNode((NodeRenderableBounded*) pNode);
01230 
01231 #ifdef _DEBUG_OFFSCREEN_PIXEL_WIDTH
01232     RenderDebuggingBitmaps(NULL, pNode, 1.0, 32, FALSE);
01233 #endif
01234 
01235     return TRUE;
01236 }
01237 
01238 /********************************************************************************************
01239 >   FeatherAttrValue::
01240     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01241     Created:    24/01/2000
01242     Purpose:    
01243     SeeAlso:    
01244  ********************************************************************************************/
01245 BOOL FeatherAttrValue::ChangeFeatherProfile(CProfileBiasGain &biasgain)
01246 {
01247     AFp BiasValue = biasgain.GetBias();
01248     AFp GainValue = biasgain.GetGain();
01249 
01250     m_Profile.SetBias(BiasValue);
01251     m_Profile.SetGain(GainValue);
01252 
01253     return TRUE;
01254 }
01255 
01256 /********************************************************************************************
01257 >   FeatherAttrValue::
01258     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01259     Created:    24/01/2000
01260     Purpose:    
01261     SeeAlso:    
01262  ********************************************************************************************/
01263 BOOL FeatherAttrValue::ChangeFeatherSize(INT32 Width, UnitType type)
01264 {
01265     BOOL res=SetupFeather(GetLinkedNode(), Width, type);
01266 
01267     return res;
01268 }
01269 
01270 
01271 
01272 /********************************************************************************************
01273 
01274 >   MILLIPOINT FeatherAttrValue::GetFeatherSize()
01275 
01276     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
01277     Created:    31/01/2001
01278 
01279     Returns:    Our feather size, in millipoints.
01280 
01281     Purpose:    Accessor method for our feather size.
01282 
01283     Notes:      This value is always capped off to MaxUserFeatherSize millipoints,
01284                 to prevent anybody ever using a feather size which we cannot handle.
01285 
01286 ********************************************************************************************/
01287 MILLIPOINT FeatherAttrValue::GetFeatherSize()
01288 {
01289     return (m_FeatherSize > MaxUserFeatherSize) ? MaxUserFeatherSize : m_FeatherSize;
01290 }
01291 
01292 
01293 
01294 /********************************************************************************************
01295 
01296 >   MILLIPOINT FeatherAttrValue::SetFeatherSize(MILLIPOINT mpWidth)
01297 
01298     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
01299     Created:    31/01/2001
01300 
01301     Inputs:     Our new feather size, in millipoints.
01302 
01303     Returns:    The feather size we actually set, taking cap values into account.
01304 
01305     Purpose:    Mutator method for our feather size.
01306 
01307     Notes:      This method will not set a value <0 mp or >MaxUserFeatherSize mp,
01308                 to prevent us dealing in feather sizes that we cannot handle.
01309 
01310 ********************************************************************************************/
01311 MILLIPOINT FeatherAttrValue::SetFeatherSize(MILLIPOINT mpWidth)
01312 {
01313     m_FeatherSize = mpWidth < 0                     ? 0 :
01314                     mpWidth > MaxUserFeatherSize    ? MaxUserFeatherSize :
01315                     mpWidth;
01316 
01317     return m_FeatherSize;
01318 }
01319 
01320 
01321 
01322 /********************************************************************************************
01323 
01324 >   inline double FeatherAttrValue::GetFeatherPixelSize(double fPixelWidth)
01325 
01326     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
01327     Created:    17/08/2000
01328     Inputs:     fPixelWidth     width of a pixel in millipoints - accepts non-integer values.
01329 
01330     Returns:    The feather size, in pixels which are fPixelWidth millipoints wide,
01331                 capped off to a maximum of (2 * MAX_SHADOW_BLUR) pixels.
01332 
01333     Purpose:    Return the size of this feather, in pixels of the specified width.
01334                 Different from GetFeatherSize(PIXELS) mainly because:
01335                     1. we return a double, so eg you can get back a value of 2.5 pix.
01336                     2. we're inline.
01337 
01338     Notes:      inline, as it's small and fast.
01339 
01340 ********************************************************************************************/
01341 inline double FeatherAttrValue::GetFeatherPixelSize(double fPixelWidth)
01342 {
01343     const double MaxFeatherBlurDiameter = 2.0 * MAX_SHADOW_BLUR;
01344     double fFeatherSize = (fPixelWidth <= 0) ? 0 : (double)m_FeatherSize / fPixelWidth;
01345     return (fFeatherSize > MaxFeatherBlurDiameter) ? MaxFeatherBlurDiameter : fFeatherSize;
01346 }
01347 
01348 
01349 
01350 /********************************************************************************************
01351 >   FeatherAttrValue::
01352     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01353     Created:    24/01/2000
01354     Purpose:    
01355     SeeAlso:    
01356  ********************************************************************************************/
01357 void FeatherAttrValue::SetFeatherProfile(CProfileBiasGain &biasgain)
01358 {
01359     AFp BiasValue = biasgain.GetBias();
01360     AFp GainValue = biasgain.GetGain();
01361 
01362     m_Profile.SetBias(BiasValue);
01363     m_Profile.SetGain(GainValue);
01364 }
01365 
01366 
01367 
01368 /********************************************************************************************
01369 
01370 >   virtual void FeatherAttrValue::SetLinkedNode(NodeRenderableBounded* pNode)
01371 
01372     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
01373     Created:    11/10/2000
01374     Purpose:    Our outer contour gap size depends on what our linked node is, so we must
01375                 recalculate our gap size whenever our linked node is set.
01376 
01377 ********************************************************************************************/
01378 void FeatherAttrValue::SetLinkedNode(NodeRenderableBounded* pNode)
01379 {
01380     m_pLinkedNode = pNode;
01381 
01382     if (pNode != NULL)
01383     {
01384         if (IS_A(GetLinkedNode(), NodeGroup) ||
01385             IS_A(GetLinkedNode(), NodeMould) ||
01386             IS_A(GetLinkedNode(), NodeBlend) ||
01387             GetLinkedNode()->IsANodeClipViewController())
01388         {
01389             m_GapSize = DEFAULT_GAP_TOLERANCE_MP;
01390         }
01391         else
01392         {
01393             m_GapSize = 1;
01394         }
01395     }
01396 }
01397 
01398 
01399 
01400 /********************************************************************************************
01401 >   FeatherAttrValue::
01402     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01403     Created:    24/01/2000
01404     Purpose:    
01405     SeeAlso:    
01406  ********************************************************************************************/
01407 BOOL FeatherAttrValue::GenerateOuterContour()
01408 {
01409     // fail now if we have no linked node.
01410     if (GetLinkedNode() == NULL)
01411     {
01412         ERROR3("FeatherAttrValue::GenerateOuterContour; Aarrgh!! Where's our linked node?!!");
01413         return FALSE;
01414     }
01415 
01416     // We know we are about to overwrite this value so if it's still set up
01417     // we shuold delete it now to prevent memory leaks
01418     if (m_pOuterContour)
01419     {
01420         delete m_pOuterContour;
01421         m_pOuterContour = NULL;
01422     }
01423 
01424     // Get outer contour
01425     // NB m_pOuterContour is a contour which is m_GapSize outside m_pPath's outline
01426     // Outer contour with m_GapSize is used so that small gaps are forced out. This is
01427     // especially desireable when there are a large number of tiny gaps within the object
01428     // we are trying feather (eg the gaps between the 'front windscreen' shape and the 
01429     // 'windscreen frame')
01430 
01431     m_pOuterContour = new Path;
01432     BOOL fSuccess =
01433         NodeContour::GenerateContourPathForNode(m_pOuterContour, GetLinkedNode(), NULL,
01434                                                 m_GapSize, TRUE, RoundJoin, -1, TRUE, TRUE);
01435 
01436     if (!fSuccess)
01437     {
01438         delete m_pOuterContour;
01439         m_pOuterContour = NULL;
01440     }
01441 
01442     return fSuccess;
01443 }
01444 
01445 /********************************************************************************************
01446 >   FeatherAttrValue::
01447     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01448     Created:    3/5/2000
01449  ********************************************************************************************/
01450 BOOL FeatherAttrValue::CanBeRenderedDirectly()
01451 {
01452     if(!GetLinkedNode())
01453         return FALSE;
01454     if(GetLinkedNode()->IS_KIND_OF(NodeDocument))
01455         return FALSE;
01456     if(GetFeatherSize()==0)
01457         return FALSE;
01458 
01459     return TRUE;
01460 }
01461 
01462 
01463 
01464 /********************************************************************************************
01465 
01466 >   BOOL FeatherAttrValue::RegenerateOuterContourOnNextRedraw(UndoableOperation* pOp = NULL)
01467 
01468     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>;        Karim MacDonald
01469     Created:    24/01/2000; 01/03/2001
01470     Inputs:     pOp     optional ptr to an UndoOp, letting us store undo information.
01471 
01472     Returns:    TRUE if we were successful,
01473                 FALSE otherwise.
01474 
01475     Purpose:    Clear the cache of our outer-contour path.
01476 
01477     See also:   AttrFeather::Transform(), AttrFeather::LinkedNodeGeometryHasChanged().
01478 
01479 ********************************************************************************************/
01480 BOOL FeatherAttrValue::RegenerateOuterContourOnNextRedraw(UndoableOperation* pOp)
01481 {
01482     if (m_pOuterContour != NULL)
01483     {
01484         if (pOp != NULL)
01485         {
01486             // make this undoable
01487             RegenerateFeatherContourAction* pAct = NULL;
01488             if (RegenerateFeatherContourAction::Init(pOp, pOp->GetUndoActionList(), this, m_pOuterContour, &pAct) == AC_FAIL)
01489             {
01490                 TRACEALL( _T("FeatherAttrValue::RegenerateOuterContourOnNextRedraw; Could not record undo information.\n"));
01491                 return FALSE;
01492             }
01493         }
01494         // don't actually delete the old outer contour
01495         // if it's been saved via the undoable operation.
01496         if (pOp == NULL)
01497             delete m_pOuterContour;
01498 
01499         m_pOuterContour = NULL;
01500     }
01501 
01502     return TRUE;
01503 }
01504 
01505 
01506 
01508 //
01509 //                              NodeAttribute classes
01510 //
01512 
01513 /********************************************************************************************
01514 
01515 >   void AttrFeather::Render( RenderRegion* pRender )
01516 
01517     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>     , Karim MacDonald
01518     Created:    24/01/2000  , 21/07/2000
01519 
01520     Inputs:     pRender     the render-region to render into.
01521 
01522     Purpose:    Render this feather attribute.
01523                 We do one or two checks for validity of this attr, and then render its
01524                 attribute-value into the RR.
01525 
01526     Notes:      If you want to customise for different RRs, then override
01527                 RenderRegion::SetOffscreen and FeatherAttrValue::OffscreenRenderingCompleted.
01528 
01529     Errors:     ERROR3 if we have no linked node at the mo'.
01530 
01531     See also:   FeatherAttrValue::Render().
01532 
01533 ********************************************************************************************/
01534 void AttrFeather::Render( RenderRegion* pRender )
01535 {
01536     // no feathering for hit-testing, please.
01537     if (pRender->IsHitDetect())
01538         return;
01539 
01540     // Karim 21/07/2000
01541     // Feathers can render into most render regions.
01542     // If a render region can't deal with feathering, then the attribute will only be
01543     // 'rendered' in the RenderRegion sense - ie plonked on the context stack - and
01544     // no attempt will be made to generate offscreen bitmaps and what-not.
01545 
01546     // only bother rendering us if our feather size is non-zero.
01547     if (Value.GetFeatherSize() != 0)
01548     {
01549         // ensure internal pointer is setup for rendering.
01550         if (Value.GetLinkedNode() == NULL)
01551         {
01552             Node* pParent = FindParent();
01553             if (pParent != NULL && pParent->IsAnObject())
01554                 Value.SetLinkedNode((NodeRenderableBounded*) FindParent());
01555 
01556             else
01557             {
01558 //              ERROR3("AttrFeather::Render; No linked node and parent is not an ink-node!");
01559                 return;
01560             }
01561         }
01562         Value.Render(pRender);
01563     }
01564 }
01565 
01566 
01567 
01568 /********************************************************************************************
01569 >   void* AttrFeather::GetDebugDetails(StringBase* Str) 
01570     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01571     Created:    
01572     Outputs:    Str: String giving debug info about the node
01573     Purpose:    For obtaining debug information about the Node
01574  ********************************************************************************************/
01575 #ifdef _DEBUG
01576 void AttrFeather::GetDebugDetails(StringBase* Str) 
01577 {
01578     // Output base class debug info.
01579     NodeRenderable::GetDebugDetails(Str);
01580 
01581     // Output our feather size, in millipoints.
01582     MILLIPOINT mp = Value.GetFeatherSize();
01583 
01584     String_256 TempStr; 
01585     TempStr._MakeMsg(TEXT("\r\nFeather size (millipoints)    #1%ld"), mp);
01586     (*Str) += TempStr;
01587 }
01588 #endif
01589 
01590 /********************************************************************************************
01591 >   AttrFeather::
01592     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01593     Created:    24/01/2000
01594     Purpose:    
01595     SeeAlso:    Node::CopyChildren(OpClone); attrmgr::applycurrentattribstonode (opnewregshape)
01596     TODO:       Code which uses this to localise attributes must be changed. Inconsistencies
01597                 arise if bitmap preserved and subsequently generated from ex-member node only,
01598                 and time delays occur if feather bmp regenerated for each member node on
01599                 localisation.
01600  ********************************************************************************************/
01601 Node* AttrFeather::SimpleCopy()
01602 {
01603     AttrFeather* pAttr =  new AttrFeather();
01604     ERRORIF(pAttr==NULL, _R(IDE_NOMORE_MEMORY),NULL);
01605 
01606     CopyNodeContents(pAttr);
01607     return pAttr;
01608 }
01609 
01610 /********************************************************************************************
01611 >   AttrFeather::
01612     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01613     Created:    24/01/2000
01614     Purpose:    
01615  ********************************************************************************************/
01616 void AttrFeather::CopyNodeContents(NodeAttribute *pCopy)
01617 {
01618     NodeAttribute::CopyNodeContents(pCopy);
01619     ((AttrFeather*)pCopy)->Value.SimpleCopy( &Value  );
01620 }
01621 
01622 /***********************************************************************************************
01623 >   void AttrFeather::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
01624 
01625     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
01626     Created:    18/12/2003
01627     Outputs:    -
01628     Purpose:    Polymorphically copies the contents of this node to another
01629     Errors:     An assertion failure will occur if NodeCopy is NULL
01630     Scope:      protected
01631                                      
01632 ***********************************************************************************************/
01633 
01634 void AttrFeather::PolyCopyNodeContents(NodeRenderable* pNodeCopy)
01635 {
01636     ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node");
01637     ENSURE(IS_A(pNodeCopy, AttrFeather), "PolyCopyNodeContents given wrong dest node type");
01638 
01639     if (IS_A(pNodeCopy, AttrFeather))
01640         CopyNodeContents((AttrFeather*)pNodeCopy);
01641 }
01642 
01643 
01644 
01645 /********************************************************************************************
01646 >   AttrFeather::
01647     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01648     Created:    24/01/2000
01649     Purpose:    Closely tied in with the attr optimisation code. The ShouldBeOptimized()
01650                 function will only allow a AttrFeather (ie a NodeAttribute) to be factored
01651                 out if the contained value's feather size is 0. This will happen when new
01652                 nodes are created using a current feather attribute with 0 feather size.
01653                 When this occurs we want to let the optimisation code (NormaliseAttributes())
01654                 remove the AttrFeather from the node on insertion into the tree.
01655                 NB the check in the optim code is
01656                     "if (AttrAleadyAppliedHigherUpTheTree == attrToOptimize)"
01657                 so we want to return TRUE if attrToOptimize->Value.feathersize is 0 so that it
01658                 gets deleted.
01659                 NB As long as the optimisation method is always used to insert nodes into the tree,
01660                 and also the order of comparison (ie a==b but not b==a) is preserved, we can always
01661                 expect  0 width feathers to be optimised out.
01662     TODOCHECK:  Assuming here that == is not required anywhere other than in the attribute
01663                 optimisation code. May not be correct behaviour if comparison required in other
01664                 circumstance.
01665  ********************************************************************************************/
01666 INT32 AttrFeather::operator==(const NodeAttribute& NodeAttrib)
01667 {
01668     ERROR3IF(!NodeAttrib.IsAFeatherAttr(), "AttrFeather::operator==; Compared with a non-feather attr.");
01669     AttrFeather *PotentialAttrToOptimize = (AttrFeather*) &NodeAttrib;
01670 
01671     return (Value.GetFeatherSize() == PotentialAttrToOptimize->Value.GetFeatherSize());
01672 }
01673 
01674 /********************************************************************************************
01675 >   AttrFeather::
01676     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01677     Created:    24/01/2000
01678     Purpose:    
01679     SeeAlso:    
01680  ********************************************************************************************/
01681 UINT32 AttrFeather::GetAttrNameID()
01682 {
01683     return (_R(IDS_FEATHER_ATTR_ID)); 
01684 }                          
01685 
01686 /********************************************************************************************
01687 >   AttrFeather::
01688     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01689     Created:    24/01/2000
01690     Purpose:    
01691     SeeAlso:    
01692  ********************************************************************************************/
01693 UINT32 AttrFeather::GetNodeSize()
01694 {
01695     return sizeof(AttrFeather);
01696 }
01697 
01698 /********************************************************************************************
01699 >   AttrFeather::
01700     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01701     Created:    24/01/2000
01702     Purpose:    
01703     SeeAlso:    
01704  ********************************************************************************************/
01705 BOOL AttrFeather::IsAFeatherAttr() const
01706 {
01707     return TRUE;
01708 }
01709 
01710 /********************************************************************************************
01711 >   BOOL AttrFeather::DoFeather(Node* pNode, INT32 size = DEFAULT_FEATHERSIZE_MP, UnitType type = MILLIPOINTS)
01712     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01713     Created:    24/01/2000
01714     Purpose:    Setup new FeatherAttrValue to apply feathering or change existing feather size
01715     SeeAlso:    OpFeather::Do(),OpChangeFeather::DoWithParam(...)
01716  ********************************************************************************************/
01717 BOOL AttrFeather::DoFeather(Node* pNode, INT32 size, UnitType type)
01718 {
01719     return Value.SetupFeather(pNode, size, type);
01720 }
01721 
01722 /********************************************************************************************
01723 >   AttrFeather::
01724     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01725     Created:    24/01/2000
01726     Purpose:    
01727     SeeAlso:    
01728  ********************************************************************************************/
01729 BOOL AttrFeather::DoSetProfile(CProfileBiasGain bg)
01730 {
01731     return Value.ChangeFeatherProfile(bg);
01732 }
01733 
01734 /********************************************************************************************
01735 
01736                         Layering and redundant feather removal
01737 
01738     Purpose:    Feathers are layered attributes. Feathering individual members in a 
01739                 group will look visibly different to feathering the entire group (if
01740                 any of the children overlap)
01741                 Hence once a feather attribute has been inserted in to the tree it must
01742                 not be moved around by the optimisation code.
01743                 However, we don't want zero size feather attributes to be stuck into the
01744                 tree ever. This function determines when an attribute can be optimised
01745                 so determined whether we can get rid of rdundant attributes.
01746                 Hence we allow optimisation to occur in the case where we have a zero width
01747                 feather.
01748 
01749  ********************************************************************************************/
01750     
01751 /********************************************************************************************
01752 >   AttrFeather::
01753     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01754     Created:    24/01/2000
01755     Purpose:    Ensure that this node is not optimised (ie factored out when groups created
01756                 or new / cloned nodes inserted into the tree).
01757 
01758                 Called when :-
01759                 1) a new node is inserted into the tree
01760                 2) a clone is inserted into the tree
01761                 3) a node with feathering applied is being grouped with other nodes
01762                 4) when a group with feathering applied is being ungrouped
01763                 
01764                 Feathers should never be optimised. This means that they will always be
01765                 inserted into the tree with each new node created, and not factored out.
01766                 The default feather after camelot initialises itself (ie on startup) has zero
01767                 feather width. To prevent the tree becomming filled with lots of superfluous
01768                 0 width feather attrs we have an extra check in AttributeManager::ApplyCurrentAttribsToNode.
01769 
01770     SeeAlso:    AttributeManager::ApplyCurrentAttribsToNode
01771  ********************************************************************************************/
01772 BOOL AttrFeather::ShouldBeOptimized()
01773 {
01774     // don't want zero width feathers in the tree
01775     if (Value.GetFeatherSize() == 0)
01776         return TRUE;
01777 
01778     return FALSE;
01779 }
01780 
01781 /********************************************************************************************
01782 
01783                             Feather prevention ;)
01784 
01785     Purpose:    Feathering is not supported in certain circumstances listed below
01786                 Rather than hacking other code to prevent these situations arising
01787                 I am using this method to prevent feathers causing damage to other
01788                 nodes.
01789 
01790                 This way feathering can be added simply once the individual
01791                 incompatibilities have been resolved
01792 
01793     Notes:      Attributes aren't always rendered by the standard render loop
01794                 (eg DocView::RenderView). Hence this function doesn't catch all cases
01795                 where feathers will get rendered, and this test needs to be repeated
01796                 in the corresdponding AttrValue::Render()
01797                 See RenderRegion::InitDevice() and CCAttrMap::Render() for egs of 
01798                 where these functions will be skipped.
01799 
01800     More Notes: Karim 21/07/2000
01801                 I have now annihilated all of the render-region checks - rather than
01802                 do checks on the type of render-region, we'll just let the RR's
01803                 feather-rendering methods do the job for us.
01804                 This makes it a *lot* easier to customise for different RR's ;o)
01805 
01806  ********************************************************************************************/
01807 SubtreeRenderState AttrFeather::RenderSubtree(RenderRegion *pRender, Node** ppNextNode, BOOL bClip)
01808 {
01809     // Can't feather unless attribute is attached to an object (ie something
01810     // with an inkpath)
01811     if (Value.GetLinkedNode() == NULL && FindParent() == NULL)
01812         return SUBTREE_NORENDER;
01813 
01814     // don't bother rendering if feather size is zero or we're the default attr.
01815     if (Value.GetFeatherSize() == 0 || Value.IsDefaultFlagSet())
01816         return SUBTREE_NORENDER;
01817 
01818     return SUBTREE_ROOTONLY;
01819 }
01820 
01821 
01822 /********************************************************************************************
01823 
01824                             Dynamic Attribute creation
01825 
01826     Purpose:    Support dynamic creation of feather attibutes by other complex nodes
01827                 (just Blends and Contours so far)
01828                 
01829                 Dynamic attrs are created by CCAttrMap::MakeAppliedAttrMap
01830                 which calls NodeRenderableInk::FindAppliedAttributes
01831                 
01832                 However the problem is that some attributes require additional info
01833                 inorder to apply themselves to a given path or node. These attributes
01834                 are specific to the node that they are attached to, so need an additonal
01835                 step to set themselves up after being dynamically created.
01836                 
01837                 Feather attributes need their internal node pointer to be setup. This
01838                 pointer is required in order to work out the dimensions of the offscreen
01839                 bitmap, to place this bitmap onscreen once it has been created, and to
01840                 get the inkpath so that the convolved transparency mask can be created
01841 
01842  ********************************************************************************************/
01843 BOOL AttrFeather::PostDynCreateInit(CCAttrMap* pBlendMap, Path* pInkPath, CCRuntimeClass* CreatorClass)
01844 {
01845     // all defaults will be out by this stage
01846     // blending default to default will return false - so no feather should be in blend attr map
01847     // blending from default to non-def will dyn create a new feather and blend it's state members
01848     //      its m_bDefault will be FALSE as it's set in the constructor
01849     ENSURE(!Value.IsDefaultFlagSet(),"How did this attribute get copied from the default attr?"); 
01850 
01851     if (Value.GetFeatherSize() == 0)
01852         return FALSE;           // Won't render and doesn't alloc mem
01853 
01854     // Karim 17/08/2000
01855     // Feather attrs usually decide for themselves whether to use a transparency-capable
01856     // bitmap when rendering. However, within contours and blends, we must force them to,
01857     // as they are now detached from the tree, and therefore cannot examine the surroundings
01858     // to make a transparency decision.
01859     Value.SetAlwaysUseTransparency();
01860 
01861     // fix internal node pointer so that we can setup offscreen bitmap
01862     // and create outer contour for generating feather mask
01863 
01864     // if we fail (eg out of mem) then put this feather attr into a state so that it won't NeedsToRender()
01865 
01866     NodePath* pNodePath = new NodePath();
01867     if(!pNodePath)
01868     {
01869         return FALSE;   // nb don't report errors. simply render without feathering if this fails
01870     }
01871 
01872     pNodePath->SetUpPath(pInkPath->GetNumCoords(),12);
01873     pNodePath->InkPath.CopyPathDataFrom(pInkPath);
01874 
01875     if(!MakeLineAttributeCompleteForContouring(pNodePath, this, pBlendMap))
01876     {
01877         // Feather is unrenderable
01878         // Need to de-alloc mem because we will be returning FALSE and
01879         // hence won't be added to the attrmap - therefore no PostDynCreateDeinit
01880         // Set Child pointer to null in case we had partial sucess
01881         // *** Change here if copy attrs from blendmap inside MakeLineAttributeCompleteForContouring
01882         pNodePath->SetChildDangerous(NULL);
01883         delete pNodePath;
01884         return FALSE;
01885     }
01886 
01887     Value.SetLinkedNode(pNodePath);
01888     return TRUE;
01889 }
01890 
01891 
01892 
01893 /********************************************************************************************
01894 
01895 >   void AttrFeather::PostDynCreateDeInit()
01896 
01897     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01898     Created:    Mid-2000
01899 
01900     Purpose:    Free memory allocated by PostDynCreateInit(..) functions
01901     Errors:     No memory needs to be allocated, so cannot fail.
01902 
01903 ********************************************************************************************/
01904 void AttrFeather::PostDynCreateDeInit()
01905 {
01906     if (Value.GetFeatherSize() == 0)
01907     {
01908         ERROR3("Failure to PostDynCreateInit should have removed this attr from the attrmap");
01909         return;     // nothing to de-alloc
01910     }
01911 
01912 
01913     // Karim 17/08/2000
01914     // This call is for completeness - probably isn't 100% necessary, but
01915     // better safe than sorry. See PostDynCreateInit() above for more info.
01916     Value.UnsetAlwaysUseTransparency();
01917 
01918     // NB this must only be called if you have called PostDynCreateInit(..)
01919 
01920     // dealloc the memory that we allocated in order to perform dynamic feathering
01921     // check parent node
01922     Node* pParent = FindParent();
01923     ENSURE(pParent->FindParent()==NULL && pParent->FindPrevious()==NULL && pParent->FindNext()==NULL,"Parent not created dynamically");
01924 
01925     // delete line attrs which we added
01926     // *** Change here if copy attrs from blendmap inside MakeLineAttributeCompleteForContouring
01927 /*  Node* pPrev = FindPrevious();
01928     if(pPrev)
01929     {
01930         ENSURE(pPrev->FindParent()==pParent,"Deleting dynamic child attrs which we didn't alloc.");
01931         pPrev->SetNextDangerous(NULL);
01932         pParent->CascadeDelete();
01933     }
01934 */  
01935     pParent->SetChildDangerous(NULL);
01936     delete pParent;
01937     return;
01938 }
01939 
01940 
01941 
01942 /********************************************************************************************
01943 
01944 >   BOOL AttrFeather::IsLinkedToThisNode(Node* pNode)
01945 
01946     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
01947     Created:    Mid-2000
01948     Inputs:     pNode   ptr to the node to check for linkage.
01949 
01950     Returns:    TRUE if we're linked to pNode,
01951                 FALSE otherwise.
01952 
01953     See Also:   LinkToGeometry().
01954 
01955 ********************************************************************************************/
01956 BOOL AttrFeather::IsLinkedToThisNode(Node* pNode)
01957 {
01958     return (Value.GetLinkedNode() == pNode);
01959 }
01960 
01961 
01962 
01963 /********************************************************************************************
01964 
01965 >   virtual void AttrFeather::Transform(TransformBase& Trans)
01966 
01967     Author:     Karim_MacDonald (Xara Group Ltd) <camelotdev@xara.com>
01968     Created:    16/10/2000
01969     Inputs:     Trans   the applied transformation.
01970     Outputs:    The feather size of our FeatherAttrValue will scale.
01971     Purpose:    Scales the size of the feather as the feathered object is transformed.
01972 
01973 ********************************************************************************************/
01974 void AttrFeather::Transform(TransformBase& Trans)
01975 {
01976     static const FIXED16 One(1.0);
01977 
01978     FIXED16 ScaleFactor = Trans.GetScalar();
01979     if (ScaleFactor != One)
01980     {
01981         // Only transform feather width of the transform allows widths to be affected
01982 // NEW FEATURE?
01983 //      if (Trans.TransLines)
01984 //      {
01985             MILLIPOINT FeatherSize = Value.GetFeatherSize();
01986             MILLIPOINT NewSize = INT32(0.5 + fabs(ScaleFactor.MakeDouble() * (double)FeatherSize) );
01987             FeatherSize = (NewSize == 0) ? 1 : NewSize;
01988 
01989             Value.SetFeatherSize(FeatherSize);
01990 //      }
01991     }
01992 
01993     // Always transform the outer path so that the shape appears correctly during solid drags
01994     Path* pOuterContour = Value.GetOuterContour();
01995     if (pOuterContour != NULL)
01996     {
01997         Trans.Transform(pOuterContour->GetCoordArray(), pOuterContour->GetNumCoords());
01998     }
01999 }
02000 
02001 
02002 
02003 /********************************************************************************************
02004 
02005 >   BOOL AttrFeather::Blend(BlendAttrParam* pBlendParam)
02006 
02007     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
02008     Created:    Mid-2000
02009 
02010     Inputs:     pBlendParam     contains the blending info.
02011     Returns:    TRUE if success,
02012                 FALSE otherwise.
02013 
02014     Purpose:    Blend us.
02015     
02016     Notes:      Always returns FALSE if blending from default to default.
02017                 NB  in this case will never add an attr of this type to the blended attr map
02018                     hence PostDynCreateInit will not be called ('cause it doesn't get dyn created!)
02019 
02020     Errors:     ERROR3 if NULL input param; ENSURE if pBlendParam has no blend-attr.
02021 
02022 ********************************************************************************************/
02023 BOOL AttrFeather::Blend(BlendAttrParam* pBlendParam)
02024 {
02025     // Check entry param isn't NULL
02026     ERROR3IF(pBlendParam == NULL, "NULL entry param");
02027     if (pBlendParam == NULL)
02028         return FALSE;
02029 
02030     BOOL Success = FALSE;
02031 
02032     // We have a valid feather to blend, so do it (in the convoluted style copied from other attrs...)
02033     // Get the Value member to blend to the Value member of the other NodeAttribute.
02034     // If it succeeds, ask the blended Value to make a NodeAttribute out of itself.
02035     if (Value.Blend(pBlendParam))
02036     {
02037         // Get the blended attr val. After this call, the ptr is our reponsibility
02038         // so we have to delete it if it's no longer needed
02039         AttributeValue* pBlendedAttrVal = pBlendParam->GetBlendedAttrVal();
02040 
02041         if (pBlendedAttrVal != NULL)
02042         {
02043             // We have a blended attr val, so ask it to make a NodeAttribute out of itself
02044             // and set the pBlendParam's blended NodeAttribute ptr to it
02045             NodeAttribute* pBlendedAttr = pBlendedAttrVal->MakeNode();
02046             pBlendParam->SetBlendedAttr(pBlendedAttr);
02047 
02048             if (pBlendedAttr != NULL)
02049             {
02050                 // We were able to make a blended NodeAttribute
02051                 // so delete the blended attr val, and return TRUE
02052                 delete pBlendedAttrVal;
02053                 Success = TRUE;
02054             }
02055             else
02056             {
02057                 // Couldn't make a blended NodeAttribute, so give the blended attr val back
02058                 // and return FALSE
02059                 pBlendParam->SetBlendedAttrVal(pBlendedAttrVal);
02060                 Success = FALSE;
02061             }
02062         }
02063         else
02064         {
02065             ENSURE(FALSE,"Couldn't get blended attr val from BlendAttrParam.");
02066             Success = FALSE;
02067         }
02068     }
02069     
02070     return Success;
02071 }
02072 
02073 
02074 
02075 /********************************************************************************************
02076 >   virtual BOOL AttrFeather::PostDynCreateInit(    CCAttrMap* pMap,
02077                                                Node* pNode,
02078                                                CCRuntimeClass* pCreatorClass)
02079     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
02080     Created:    24/01/2000
02081     Purpose:    
02082     SeeAlso:    
02083  ********************************************************************************************/
02084 BOOL AttrFeather::PostDynCreateInit(CCAttrMap* pMap,
02085                                        Node* pNode,
02086                                        CCRuntimeClass* pCreatorClass)
02087 {
02088     return TRUE;
02089 }
02090 
02091 
02092 
02093 /********************************************************************************************
02094 
02095 >   BOOL AttrFeather::LinkedNodeGeometryHasChanged(UndoableOperation* pOp)
02096 
02097     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>;        Karim MacDonald
02098     Created:    27/4/00;    01/03/2001
02099 
02100     Inputs:     pOp     the operation causing our linked node's geometry to change.
02101     Outputs:    Our cache of our outer-contour path may be cleared.
02102     Returns:    TRUE if successful,
02103                 FALSE otherwise.
02104 
02105     Purpose:    Inform this attribute that the geometry of its linked node may be changing.
02106 
02107     Errors:     ERROR2 if pOp is NULL - should *never* happen.
02108 
02109     See also:   Node::AllowOp() + overrides - main place from which this fn is called.
02110 
02111 ********************************************************************************************/
02112 BOOL AttrFeather::LinkedNodeGeometryHasChanged(UndoableOperation* pOp)
02113 {
02114 // DEBUG:
02115 //  static UINT32 ctr = 0;
02116 //  TRACEUSER( "Karim", _T("%d. LinkedNodeGeometryHasChanged() for 0x%x.\n"), ++ctr, &Value);
02117 
02118     ERROR2IF(pOp == NULL, FALSE,
02119             "AttrFeather::LinkedNodeGeometryHasChanged; Should never call with NULL pOp!");
02120 
02121     // Karim 28/02/2000
02122     // If we're undergoing translation, rotation or reflection, then our transform
02123     // method will automatically update our outer-contour.
02124     // In all other cases, we should clear out our outer-contour,
02125     // so it is refreshed at the next render.
02126     //
02127     // The only way to detect whether we're being transformed as above, is to test on the Op.
02128 
02129     if (pOp->IS_KIND_OF(TransOperation) 
02130         && !pOp->IsKindOf( CC_RUNTIME_CLASS(OpPathNudge) )
02131         )
02132     {
02133         // arbitrarily chosen error threshold.
02134         static const double epsilon = 0.000016;
02135         Matrix Mat = ((TransOperation*)pOp)->GetCurrentMatrix();
02136         if (Mat.IsTranslation() ||
02137             Mat.IsReflection() ||
02138             Mat.IsRotation(epsilon))
02139         {
02140             // can only know for sure that we were transformed,
02141             // if our linked node, or one of its parents, is the op's target.
02142             Node* pLinkedNode   = Value.GetLinkedNode();
02143 //          Node* pTransNode    = ((TransOperation*)pOp)->GetNode();
02144 //          if( pLinkedNode == pTransNode ||
02145 //              (pTransNode != NULL && pTransNode->IsNodeInSubtree(pLinkedNode)) )
02146 //              return TRUE;
02147             Range* pRange = ((TransOperation*)pOp)->GetTransformRange();
02148             if (pRange && pRange->Contains(pLinkedNode, TRUE))
02149                 return TRUE;
02150         }
02151     }
02152 
02153     return Value.RegenerateOuterContourOnNextRedraw(pOp);
02154 }
02155 
02156 /********************************************************************************************
02157 >   virtual void AttrFeather::NewlyCreatedDefaultAttr(NodeDocument* pNode)
02158     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
02159     Created:    27/4/00
02160     Inputs:     
02161     Outputs:    
02162     Returns:    
02163     Purpose:    Attributes which are linked to the geometry of the objects which they affect,
02164                 may not be able to perform a useful function if attached directly to the 
02165                 NodeDocument node (ie a default attribute). This function allows a default
02166                 attribute of this type to perform an extra initialisation step so that the
02167                 Render() function can handle 
02168     Errors:     
02169     SeeAlso:    -
02170  ********************************************************************************************/
02171 void AttrFeather::NewlyCreatedDefaultAttr(NodeDocument* pNode)
02172 {
02173     Value.SetLinkedNode((NodeRenderableBounded*)pNode);
02174     Value.SetDefault();
02175 }
02176 
02177 /********************************************************************************************
02178 >   AttrFeather::
02179     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
02180     Created:    9/5/2000
02181     Purpose:    connect attribute values internal node pointer
02182     SeeAlso:    
02183  ********************************************************************************************/
02184 BOOL AttrFeather::LinkToGeometry(Node* pContext)
02185 {
02186     Value.SetLinkedNode((NodeRenderableBounded*) pContext);
02187     return TRUE;
02188 }
02189 
02190 /********************************************************************************************
02191 >   virtual BOOL AttrFeather::ContainsAttributeValue(AttributeValue* pVal)
02192     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
02193     Created:    7/6/00
02194     Inputs:     
02195     Outputs:    
02196     Returns:    
02197     Purpose:    To check if this NodeAttribute contains a the AttributeValue
02198                 NB needs to be implemented in a manner specific to the way in which
02199                 the derived NodeAttribute class stores the AttributeValue
02200     Errors:     
02201     SeeAlso:    OffscreenAttrValue::DoesOffscreenBmpRequireTransp
02202                 AttrFeather::ContainsAttributeValue
02203  ********************************************************************************************/
02204 BOOL AttrFeather::ContainsAttributeValue(AttributeValue* pVal)
02205 {
02206     if(!pVal->IS_KIND_OF(FeatherAttrValue))
02207     {
02208         ENSURE(FALSE,"Strange attr value comparison test requested");
02209         return FALSE;
02210     }
02211 
02212     return (pVal == &Value);
02213 }
02214 
02215 /********************************************************************************************
02216 >   AttrFeather::
02217     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
02218     Created:    24/01/2000
02219     Purpose:    
02220     SeeAlso:    
02221  ********************************************************************************************/
02222 
02224 //
02225 //                              Saving and loading
02226 //
02228 BOOL AttrFeather::WritePreChildrenWeb(BaseCamelotFilter* pFilter)
02229 {
02230     ERROR2IF(pFilter == NULL,FALSE,"NULL filter param");
02231     CXaraFileRecord Rec(TAG_FEATHER,TAG_FEATHER_SIZE);
02232     BOOL ok = TRUE;
02233     
02234     MILLIPOINT sz = Value.GetFeatherSize();
02235     CProfileBiasGain pProfile(Value.GetProfile());
02236 
02237     ok = Rec.Init();
02238     if (ok) ok = Rec.WriteINT32(sz);
02239     if (ok) ok = Rec.WriteDOUBLE ((double) pProfile.GetBias());
02240     if (ok) ok = Rec.WriteDOUBLE ((double) pProfile.GetGain());
02241     if (ok) ok = pFilter->Write(&Rec);
02242 
02243     return ok;
02244 }
02245 
02246 BOOL AttrFeather::WritePreChildrenNative(BaseCamelotFilter* pFilter)
02247 {
02248     return WritePreChildrenWeb(pFilter);
02249 }
02250 
02251 UINT32* FeatherRecordHandler::GetTagList()
02252 {
02253     static UINT32 TagList[] = {TAG_FEATHER,CXFRH_TAG_LIST_END};
02254     return (UINT32*)&TagList;
02255 }
02256 
02257 BOOL FeatherRecordHandler::HandleRecord(CXaraFileRecord* pCXaraFileRecord)
02258 {
02259     ERROR2IF(pCXaraFileRecord == NULL,FALSE,"pCXaraFileRecord is NULL");
02260     BOOL ok = TRUE;
02261 
02262     switch (pCXaraFileRecord->GetTag())
02263     {
02264         case TAG_FEATHER:
02265             ok = HandleFeatherRecord(pCXaraFileRecord);
02266             break;
02267 
02268         default:
02269             ok = FALSE;
02270             ERROR3_PF(("Incorrect tag supplied to HandleRecord. Tag = (%d)\n",pCXaraFileRecord->GetTag()));
02271             break;
02272     }
02273 
02274     return ok;
02275 }
02276 
02277 BOOL FeatherRecordHandler::HandleFeatherRecord(CXaraFileRecord* pCXaraFileRecord)
02278 {
02279     BOOL ok = TRUE;
02280 
02281     MILLIPOINT FeatherSz;
02282     double Bias = 0, Gain = 0;
02283     double* ptrBias = &Bias, *ptrGain = &Gain;
02284 
02285     // Read in the feather data
02286     if (ok) ok = pCXaraFileRecord->ReadINT32(&FeatherSz);
02287     if (ok) ok = pCXaraFileRecord->ReadDOUBLEnoError (ptrBias);
02288     if (ok) ok = pCXaraFileRecord->ReadDOUBLEnoError (ptrGain);
02289 
02290     CProfileBiasGain Profile;
02291 
02292     if ((ptrBias != NULL) && (ptrGain != NULL))
02293     {
02294         Profile.SetBias((AFp) Bias);
02295         Profile.SetGain((AFp) Gain);
02296     }
02297 
02298     if (ok)
02299     {
02300         AttrFeather* pAttr = new AttrFeather;
02301         if (pAttr != NULL)
02302         {
02303             // Get a ptr to the attr value object
02304             FeatherAttrValue* pValue = (FeatherAttrValue*)&pAttr->Value;
02305 
02306             if (pValue != NULL)
02307             {
02308                 // Set the feather size
02309                 pValue->SetFeatherSize(FeatherSz);
02310 
02311                 // Set the profile
02312                 pValue->SetFeatherProfile(Profile);
02313                 
02314                 if (ok) ok = InsertNode(pAttr);
02315 
02316                 // Set the m_Node pointer (TODO remove)
02317                 if (ok && pBaseCamelotFilter->GetInsertMode()==INSERTMODE_ATTACHTOTREE)
02318                     pValue->SetLinkedNode((NodeRenderableBounded*)pAttr->FindParent());
02319             }
02320             else
02321                 ok = FALSE;
02322         }
02323         else
02324             ok = FALSE;
02325     }
02326 
02327     return ok;
02328 }

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